Skip to content

Commit 70b1ce4

Browse files
committed
add more tests
1 parent 6f64432 commit 70b1ce4

File tree

5 files changed

+130
-37
lines changed

5 files changed

+130
-37
lines changed

src/basic_types.jl

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ Face index, connecting points to form a simplex
2929

3030
@fixed_vector SimplexFace AbstractSimplexFace
3131
const LineFace{T} = SimplexFace{2, T}
32+
const TetrahedronFace{T} = SimplexFace{4, T}
3233
Face(::Type{<: SimplexFace{N}}, ::Type{T}) where {N, T} = SimplexFace{N, T}
33-
Face(::Type{<: NSimplex{N}}, ::Type{T}) where {N, T} = SimplexFace{N, T}
3434

3535

3636

@@ -40,7 +40,6 @@ Face index, connecting points to form an Ngon
4040

4141
@fixed_vector NgonFace AbstractNgonFace
4242
const TriangleFace{T} = NgonFace{3, T}
43-
4443
const QuadFace{T} = NgonFace{4, T}
4544

4645
Base.show(io::IO, x::TriangleFace{T}) where T = print(io, "TriangleFace(", join(x, ", "), ")")
@@ -172,15 +171,14 @@ struct LineString{
172171
Dim, T <: Real,
173172
P <: AbstractPoint,
174173
V <: AbstractVector{<: LineP{Dim, T, P}}
175-
} <: AbstractVector{LineP{Dim, T}}
174+
} <: AbstractVector{LineP{Dim, T, P}}
176175
points::V
177176
end
178177
coordinates(x::LineString) = x.points
179178

180179
Base.size(x::LineString) = size(coordinates(x))
181180
Base.getindex(x::LineString, i) = getindex(coordinates(x), i)
182181

183-
184182
function LineString(points::AbstractVector{LineP{Dim, T, P}}) where {Dim, T, P}
185183
LineString{Dim, T, P, typeof(points)}(points)
186184
end
@@ -244,8 +242,8 @@ end
244242

245243
Base.:(==)(a::Polygon, b::Polygon) = (a.exterior == b.exterior) && (a.interiors == b.interiors)
246244

247-
function Polygon(exterior::AbstractVector{LineP{Dim, T, P}}, interiors::V) where {Dim, T, P, V <: AbstractVector{<: AbstractVector{LineP{Dim, T, P}}}}
248-
Polygon{Dim, T, typeof(exterior), V}(exterior, interiors)
245+
function Polygon(exterior::E, interiors::AbstractVector{E}) where E <: AbstractVector{LineP{Dim, T, P}} where {Dim, T, P}
246+
Polygon{Dim, T, P, typeof(exterior), typeof(interiors)}(exterior, interiors)
249247
end
250248

251249
Polygon(exterior::L) where L <: AbstractVector{<: LineP} = Polygon(exterior, L[])
@@ -268,18 +266,13 @@ struct MultiPolygon{
268266
Element <: AbstractPolygon{Dim, T},
269267
A <: AbstractVector{Element}
270268
} <: AbstractVector{Element}
271-
272269
polygons::A
273270
end
274271

275-
function MultiPolygon(polygons::AbstractVector{P}; meta...) where P <: AbstractPolygon{Dim, T} where {Dim, T}
276-
nt = values(meta)
277-
n = keys(nt)
278-
typs = Tuple{eltype.(values(nt))...}
279-
m = StructArray(nt)
280-
PType = MetaPolygon{Dim, T, P, n, typs}
281-
mpolys = StructArray{PType}((polygons, m))
282-
MultiPolygon{Dim, T, PType, typeof(mpolys)}(mpolys)
272+
273+
274+
function MultiPolygon(polygons::AbstractVector{P}; kw...) where P <: AbstractPolygon{Dim, T} where {Dim, T}
275+
MultiPolygon(meta(polygons; kw...))
283276
end
284277

285278
Base.getindex(mp::MultiPolygon, i) = mp.polygons[i]

src/metadata.jl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ macro meta_type(name, mainfield, supertype, params...)
6565
const $NoParams{Typ, Names, Types} = $MetaName{$(params...), Typ, Names, Types} where {$(params...)}
6666

6767
function Base.getproperty(x::$MetaName{$(params...), Typ, Names, Types}, field::Symbol) where {$(params...), Typ, Names, Types}
68-
field === $field && return getfield(x, $field)
68+
field === $field && return getfield(x, :main)
6969
field === :main && return getfield(x, :main)
7070
Base.sym_in(field, Names) && return getfield(getfield(x, :meta), field)
7171
error("Field $field not part of Element")
@@ -120,3 +120,8 @@ Base.getindex(x::PointMeta, idx::Int) = getindex(metafree(x), idx)
120120

121121
@meta_type(NgonFace, ngon, AbstractNgonFace, N, T)
122122
Base.getindex(x::NgonFaceMeta, idx::Int) = getindex(metafree(x), idx)
123+
124+
@meta_type(SimplexFace, simplex, AbstractSimplexFace, N, T)
125+
Base.getindex(x::SimplexFaceMeta, idx::Int) = getindex(metafree(x), idx)
126+
127+
@meta_type(Polygon, polygon, AbstractPolygon, N, T)

src/viewtypes.jl

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ end
7676
reinterpret(Face(P, T), TupleView{N, skip}(points))
7777
end
7878

79+
80+
@inline function connect(points::AbstractMatrix{T}, P::Type{<: AbstractPoint{N}}) where {T <: Real, N}
81+
if size(points, 1) === N
82+
return reinterpret(Point{N, T}, points)
83+
elseif size(points, 2) === N
84+
seglen = size(points, 1)
85+
columns = ntuple(N) do i
86+
view(points, ((i-1) * seglen + 1):(i * seglen))
87+
end
88+
return StructArray{Point{N, T}}((StructArray{NTuple{N, T}}(columns),))
89+
else
90+
error("Dim 1 or 2 must be equal to the point dimension!")
91+
end
92+
end
93+
7994
"""
8095
FaceView enables to link one array of points via a face array, to generate one
8196
abstract array of elements.

test/REQUIRE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Query

test/runtests.jl

Lines changed: 100 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,89 @@
11
using GeometryBasics
2-
using GeometryBasics: Polygon, MultiPolygon, Point, LineFace, Polytope, Line, Simplex, connect, Triangle, NSimplex, Tetrahedron, TupleView, TriangleFace, SimplexFace, LineString, Mesh
3-
using Test, Random
4-
5-
6-
@testset "polygon with metadata" begin
7-
polys = [Polygon(rand(Point{2, Float32}, 20)) for i in 1:10]
8-
pnames = [randstring(4) for i in 1:10]
9-
numbers = rand(10)
10-
bin = rand(Bool, 10)
11-
x = MultiPolygon(polys, name = pnames, value = numbers, category = bin)
12-
for (mp, p, n, num, b) in zip(x, polys, pnames, numbers, bin)
13-
@test mp.polygon == p
14-
@test mp.name == n
15-
@test mp.value == num
16-
@test mp.category == b
2+
using GeometryBasics: Polygon, MultiPolygon, Point, LineFace, Polytope, Line
3+
using GeometryBasics: Simplex, connect, Triangle, NSimplex, Tetrahedron
4+
using GeometryBasics: QuadFace, hascolumn, getcolumn, metafree, coordinates, TetrahedronFace
5+
using GeometryBasics: TupleView, TriangleFace, SimplexFace, LineString, Mesh, meta
6+
using Test, Random, Query, StructArrays, Tables
7+
using StaticArrays
8+
9+
10+
@testset "embedding metadata" begin
11+
@testset "Meshes" begin
12+
13+
@testset "per vertex attributes" begin
14+
points = rand(Point{3, Float64}, 8)
15+
tfaces = TetrahedronFace{Int}[(1, 2, 3, 4), (5, 6, 7, 8)]
16+
normals = rand(SVector{3, Float64}, 8)
17+
stress = LinRange(0, 1, 8)
18+
mesh = Mesh(meta(points, normals = normals, stress = stress), tfaces)
19+
20+
@test hascolumn(coordinates(mesh), :stress)
21+
@test hascolumn(coordinates(mesh), :normals)
22+
@test coordinates(mesh).stress === stress
23+
@test coordinates(mesh).normals === normals
24+
@test coordinates(mesh).normals === normals
25+
@test GeometryBasics.faces(mesh) === tfaces
26+
27+
end
28+
29+
@testset "per face attributes" begin
30+
31+
# Construct a cube out of Quads
32+
points = Point{3, Float64}[
33+
(0.0, 0.0, 0.0), (2.0, 0.0, 0.0),
34+
(2.0, 2.0, 0.0), (0.0, 2.0, 0.0),
35+
(0.0, 0.0, 12.0), (2.0, 0.0, 12.0),
36+
(2.0, 2.0, 12.0), (0.0, 2.0, 12.0)
37+
]
38+
39+
facets = QuadFace{Cint}[
40+
1:4,
41+
5:8,
42+
[1,5,6,2],
43+
[2,6,7,3],
44+
[3, 7, 8, 4],
45+
[4, 8, 5, 1]
46+
]
47+
48+
markers = Cint[-1, -2, 0, 0, 0, 0]
49+
# attach some additional information to our faces!
50+
mesh = Mesh(points, meta(facets, markers = markers))
51+
@test hascolumn(GeometryBasics.faces(mesh), :markers)
52+
# test with === to assert we're not doing any copies
53+
@test getcolumn(GeometryBasics.faces(mesh), :markers) === markers
54+
@test coordinates(mesh) === points
55+
@test metafree(GeometryBasics.faces(mesh)) === facets
56+
57+
end
58+
59+
end
60+
@testset "polygon with metadata" begin
61+
polys = [Polygon(rand(Point{2, Float32}, 20)) for i in 1:10]
62+
pnames = [randstring(4) for i in 1:10]
63+
numbers = LinRange(0.0, 1.0, 10)
64+
bin = rand(Bool, 10)
65+
# create just an array
66+
plain = meta(polys, name = pnames, value = numbers, category = bin)
67+
# create a MultiPolygon with the right type & meta information!
68+
multipoly = MultiPolygon(polys; name = pnames, value = numbers, category = bin)
69+
for x in (plain, multipoly)
70+
for (mp, p, n, num, b) in zip(x, polys, pnames, numbers, bin)
71+
@test mp.polygon == p
72+
@test mp.name == n
73+
@test mp.value == num
74+
@test mp.category == b
75+
end
76+
77+
filtered = @from i in x begin
78+
@where i.value < 0.7
79+
@select i
80+
@collect
81+
end
82+
@test length(filtered) == 7
83+
end
1784
end
1885
end
1986

20-
2187
@testset "view" begin
2288
@testset "TupleView" begin
2389
x = [1, 2, 3, 4, 5, 6]
@@ -48,8 +114,20 @@ end
48114

49115
triangles = connect(x, Triangle)
50116
@test triangles == [Triangle(Point(1, 2), Point(3, 4), Point(5, 6))]
51-
tetrahedra = connect(x, NSimplex{3})
52-
@test tetrahedra == [Tetrahedron(x[1], x[2], x[3])]
117+
x = connect([1, 2, 3, 4, 5, 6, 7, 8], Point{2})
118+
tetrahedra = connect(x, NSimplex{4})
119+
@test tetrahedra == [Tetrahedron(x[1], x[2], x[3], x[4])]
120+
121+
@testset "matrix non-copy point views" begin
122+
# point in row
123+
points = [1 2; 1 4; 66 77]
124+
comparison = [Point(1, 2), Point(1, 4), Point(66, 77)]
125+
@test connect(points, Point{2}) == comparison
126+
# point in column
127+
points = [1 1 66; 2 4 77]
128+
# huh, reinterpret array doesn't seem to like `==`
129+
@test all(((a,b),)-> a==b, zip(connect(points, Point{2}), comparison))
130+
end
53131
end
54132

55133
@testset "face views" begin
@@ -61,8 +139,8 @@ end
61139
x = Point{3}(1.0)
62140
triangles = connect([x], [TriangleFace(1, 1, 1)])
63141
@test triangles == [Triangle(x, x, x)]
64-
65-
faces = connect([1, 2, 3], SimplexFace{3})
142+
points = connect([1, 2, 3, 4, 5, 6, 7, 8], Point{2})
143+
faces = connect([1, 2, 3, 4], SimplexFace{4})
66144
triangles = connect(points, faces)
67145
@test triangles == [Tetrahedron(points...)]
68146
end
@@ -133,7 +211,8 @@ end
133211
mesh = Mesh([x], [TriangleFace(1, 1, 1)])
134212
@test mesh == [Triangle(x, x, x)]
135213

136-
faces = connect([1, 2, 3], SimplexFace{3})
214+
points = connect([1, 2, 3, 4, 5, 6, 7, 8], Point{2})
215+
faces = connect([1, 2, 3, 4], SimplexFace{4})
137216
mesh = Mesh(points, faces)
138217
@test mesh == [Tetrahedron(points...)]
139218

0 commit comments

Comments
 (0)