Skip to content

Commit 93bdce4

Browse files
authored
Merge pull request #56 from JuliaGeometry/sd/meta2
add meshmeta & multilinestringmeta
2 parents 0cc4a97 + 6e157ca commit 93bdce4

File tree

4 files changed

+60
-25
lines changed

4 files changed

+60
-25
lines changed

src/GeometryBasics.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ module GeometryBasics
2929
export OffsetInteger, ZeroIndex, OneIndex, GLIndex
3030
export FaceView, SimpleFaceView
3131
export AbstractPoint, PointMeta, PointWithUV
32-
export PolygonMeta, MultiPointMeta
32+
export PolygonMeta, MultiPointMeta, MultiLineStringMeta, MeshMeta
3333
export decompose, coordinates, faces, normals, decompose_uv, decompose_normals, texturecoordinates
3434
export Tesselation, pointmeta, Normal, UV, UVW
3535
export GLTriangleFace, GLNormalMesh3D, GLPlainTriangleMesh, GLUVMesh3D, GLUVNormalMesh3D

src/basic_types.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ An abstract mesh is a collection of Polytope elements (Simplices / Ngons).
336336
The connections are defined via faces(mesh), the coordinates of the elements are returned by
337337
coordinates(mesh). Arbitrary meta information can be attached per point or per face
338338
"""
339-
const AbstractMesh{Element} = AbstractVector{Element}
339+
abstract type AbstractMesh{Element<:Polytope} <: AbstractVector{Element} end
340340

341341
"""
342342
Mesh <: AbstractVector{Element}

src/metadata.jl

Lines changed: 38 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,46 +63,52 @@ macro meta_type(name, mainfield, supertype, params...)
6363
MetaName = Symbol("$(name)Meta")
6464
field = QuoteNode(mainfield)
6565
NoParams = Symbol("$(MetaName)NoParams")
66+
67+
params_sym = map(params) do param
68+
param isa Symbol && return param
69+
param isa Expr && param.head == :(<:) && return param.args[1]
70+
error("Unsupported type parameter: $(param)")
71+
end
72+
6673
expr = quote
67-
struct $MetaName{$(params...), Typ <: $supertype{$(params...)}, Names, Types} <: $supertype{$(params...)}
74+
struct $MetaName{$(params...), Typ <: $supertype{$(params_sym...)}, Names, Types} <: $supertype{$(params_sym...)}
6875
main::Typ
6976
meta::NamedTuple{Names, Types}
7077
end
7178

72-
const $NoParams{Typ, Names, Types} = $MetaName{$(params...), Typ, Names, Types} where {$(params...)}
79+
const $NoParams{Typ, Names, Types} = $MetaName{$(params_sym...), Typ, Names, Types} where {$(params_sym...)}
7380

74-
function Base.getproperty(x::$MetaName{$(params...), Typ, Names, Types}, field::Symbol) where {$(params...), Typ, Names, Types}
81+
function Base.getproperty(x::$MetaName{$(params_sym...), Typ, Names, Types},
82+
field::Symbol) where {$(params...), Typ, Names, Types}
7583
field === $field && return getfield(x, :main)
7684
field === :main && return getfield(x, :main)
7785
Base.sym_in(field, Names) && return getfield(getfield(x, :meta), field)
7886
error("Field $field not part of Element")
7987
end
8088

81-
GeometryBasics.MetaType(T::Type{<: $supertype}) = $MetaName{T}
89+
function GeometryBasics.MetaType(XX::Type{<: $supertype{$(params_sym...)} where {$(params...)}})
90+
return $MetaName
91+
end
92+
8293
function GeometryBasics.MetaType(
83-
ST::Type{<: $supertype{$(params...)}},
94+
ST::Type{<: $supertype{$(params_sym...)}},
8495
::Type{NamedTuple{Names, Types}}) where {$(params...), Names, Types}
85-
return $MetaName{$(params...), ST, Names, Types}
96+
return $MetaName{$(params_sym...), ST, Names, Types}
8697
end
8798

88-
8999
GeometryBasics.MetaFree(::Type{<: $MetaName{Typ}}) where Typ = Typ
90100
GeometryBasics.MetaFree(::Type{<: $MetaName}) = $name
91101
GeometryBasics.metafree(x::$MetaName) = getfield(x, :main)
92-
GeometryBasics.metafree(x::AbstractVector{<: $MetaName}) = getcolumns(x, $field)[1]
102+
GeometryBasics.metafree(x::AbstractVector{<: $MetaName}) = getproperty(x, $field)
93103
GeometryBasics.meta(x::$MetaName) = getfield(x, :meta)
94-
GeometryBasics.meta(x::AbstractVector{<: $MetaName}) = getcolumns(x, :meta)[1]
104+
GeometryBasics.meta(x::AbstractVector{<: $MetaName}) = getproperty(x, :meta)
95105

96-
function GeometryBasics.meta(main::$supertype; meta...)
106+
function GeometryBasics.meta(main::$supertype{$(params_sym...)}; meta...) where {$(params...)}
97107
isempty(meta) && return elements # no meta to add!
98108
return $MetaName(main; meta...)
99109
end
100110

101-
function GeometryBasics.attributes(hasmeta::$MetaName)
102-
return Dict{Symbol, Any}((name => getproperty(hasmeta, name) for name in propertynames(hasmeta)))
103-
end
104-
105-
function GeometryBasics.meta(elements::AbstractVector{T}; meta...) where T <: $supertype
111+
function GeometryBasics.meta(elements::AbstractVector{XX}; meta...) where XX <: $supertype{$(params_sym...)} where {$(params...)}
106112
isempty(meta) && return elements # no meta to add!
107113
n = length(elements)
108114
for (k, v) in meta
@@ -118,7 +124,11 @@ macro meta_type(name, mainfield, supertype, params...)
118124
# get the first element to get the per element named tuple type
119125
ElementNT = typeof(map(first, nt))
120126

121-
return StructArray{MetaType(T, ElementNT)}(($(mainfield) = elements, nt...))
127+
return StructArray{MetaType(XX, ElementNT)}(($(mainfield) = elements, nt...))
128+
end
129+
130+
function GeometryBasics.attributes(hasmeta::$MetaName)
131+
return Dict{Symbol, Any}((name => getproperty(hasmeta, name) for name in propertynames(hasmeta)))
122132
end
123133

124134
function (MT::Type{<: $MetaName})(args...; meta...)
@@ -132,22 +142,20 @@ macro meta_type(name, mainfield, supertype, params...)
132142
return MT(main, nt)
133143
end
134144

135-
function Base.propertynames(::$MetaName{$(params...), Typ, Names, Types}) where {$(params...), Typ, Names, Types}
145+
function Base.propertynames(::$MetaName{$(params_sym...), Typ, Names, Types}) where {$(params...), Typ, Names, Types}
136146
return ($field, Names...)
137147
end
138148

139-
function StructArrays.staticschema(::Type{$MetaName{$(params...), Typ, Names, Types}}) where {$(params...), Typ, Names, Types}
149+
function StructArrays.staticschema(::Type{$MetaName{$(params_sym...), Typ, Names, Types}}) where {$(params...), Typ, Names, Types}
140150
NamedTuple{($field, Names...), Base.tuple_type_cons(Typ, Types)}
141151
end
142152

143153
function StructArrays.createinstance(
144-
::Type{$MetaName{$(params...), Typ, Names, Types}},
154+
::Type{$MetaName{$(params_sym...), Typ, Names, Types}},
145155
metafree, args...
146156
) where {$(params...), Typ, Names, Types}
147157
$MetaName(metafree, NamedTuple{Names, Types}(args))
148158
end
149-
150-
151159
end
152160
return esc(expr)
153161
end
@@ -163,6 +171,14 @@ Base.getindex(x::SimplexFaceMeta, idx::Int) = getindex(metafree(x), idx)
163171

164172
@meta_type(Polygon, polygon, AbstractPolygon, N, T)
165173

166-
@meta_type(MultiPoint, points, AbstractVector, P)
174+
@meta_type(MultiPoint, points, AbstractVector, P <: AbstractPoint)
167175
Base.getindex(x::MultiPointMeta, idx::Int) = getindex(metafree(x), idx)
168176
Base.size(x::MultiPointMeta) = size(metafree(x))
177+
178+
@meta_type(MultiLineString, linestrings, AbstractVector, P <: LineString)
179+
Base.getindex(x::MultiLineStringMeta, idx::Int) = getindex(metafree(x), idx)
180+
Base.size(x::MultiLineStringMeta) = size(metafree(x))
181+
182+
@meta_type(Mesh, mesh, AbstractMesh, Element <: Polytope)
183+
Base.getindex(x::MeshMeta, idx::Int) = getindex(metafree(x), idx)
184+
Base.size(x::MeshMeta) = size(metafree(x))

test/runtests.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ using GeometryBasics: attributes
7777
@test length(filtered) == 7
7878
end
7979
@test GeometryBasics.getcolumn(plain, :name) == pnames
80-
@test GeometryBasics.MetaType(Polygon) == PolygonMeta{Polygon,T,Typ,Names,Types} where Types where Names where Typ<:GeometryBasics.AbstractPolygon{Polygon,T} where T
80+
@test GeometryBasics.MetaType(Polygon) == PolygonMeta
8181
@test_throws ErrorException GeometryBasics.meta(plain)
8282
@test GeometryBasics.MetaFree(PolygonMeta) == Polygon
8383

@@ -99,6 +99,25 @@ using GeometryBasics: attributes
9999
@test metafree(pm) === p
100100
@test propertynames(pm) == (:position, :a, :b)
101101
end
102+
103+
@testset "MultiLineString with metadata" begin
104+
linestring1 = LineString(Point{2, Int}[(10, 10), (20, 20), (10, 40)])
105+
linestring2 = LineString(Point{2, Int}[(40, 40), (30, 30), (40, 20), (30, 10)])
106+
multilinestring = MultiLineString([linestring1, linestring2])
107+
multilinestringmeta = MultiLineStringMeta([linestring1, linestring2]; boundingbox = Rect(1.0, 1.0, 2.0, 2.0))
108+
@test multilinestringmeta isa AbstractVector
109+
@test meta(multilinestringmeta) === (boundingbox = Rect(1.0, 1.0, 2.0, 2.0),)
110+
@test metafree(multilinestringmeta) == multilinestring
111+
@test propertynames(multilinestringmeta) == (:linestrings, :boundingbox)
112+
end
113+
114+
@testset "Mesh with metadata" begin
115+
m = triangle_mesh(Sphere(Point3f0(0), 1))
116+
m_meta = MeshMeta(m; boundingbox=Rect(1.0, 1.0, 2.0, 2.0))
117+
@test meta(m_meta) === (boundingbox = Rect(1.0, 1.0, 2.0, 2.0),)
118+
@test metafree(m_meta) === m
119+
@test propertynames(m_meta) == (:mesh, :boundingbox)
120+
end
102121
end
103122

104123
@testset "view" begin

0 commit comments

Comments
 (0)