@@ -12,231 +12,86 @@ Basic Geometry Types.
12
12
This package aimes to offer a standard set of Geometry types, which easily work with metadata, query frameworks on geometries and different memory layouts.
13
13
The aim is to create a solid basis for Graphics/Plotting, finite elements analysis, Geo applications, and general geometry manipulations - while offering a julian API, that still allows performant C-interop.
14
14
15
+ This package is a replacement for the discontinued [ GeometryTypes] ( https://github.com/JuliaGeometry/GeometryTypes.jl/ ) .
15
16
16
- It is planned to merge this package with [ GeometryTypes] ( https://github.com/JuliaGeometry/GeometryTypes.jl/ ) once it's fully mature, or simply replace it!
17
-
18
- To get an idea, look at the runtests:
17
+ ## Quick start
19
18
20
19
``` julia
21
20
using GeometryBasics
22
- using GeometryBasics: Polygon, MultiPolygon, Point, LineFace, Polytope, Line
23
- using GeometryBasics: Simplex, connect, Triangle, NSimplex, Tetrahedron
24
- using GeometryBasics: QuadFace, hascolumn, getcolumn, metafree, coordinates, TetrahedronFace
25
- using GeometryBasics: TupleView, TriangleFace, SimplexFace, LineString, Mesh, meta
26
- using Test, Random, Query, StructArrays, Tables
27
- using StaticArrays
28
-
29
-
30
- @testset " embedding metadata" begin
31
- @testset " Meshes" begin
32
-
33
- @testset " per vertex attributes" begin
34
- points = rand (Point{3 , Float64}, 8 )
35
- tfaces = TetrahedronFace{Int}[(1 , 2 , 3 , 4 ), (5 , 6 , 7 , 8 )]
36
- normals = rand (SVector{3 , Float64}, 8 )
37
- stress = LinRange (0 , 1 , 8 )
38
- mesh = Mesh (meta (points, normals = normals, stress = stress), tfaces)
39
-
40
- @test hascolumn (coordinates (mesh), :stress )
41
- @test hascolumn (coordinates (mesh), :normals )
42
- @test coordinates (mesh). stress === stress
43
- @test coordinates (mesh). normals === normals
44
- @test coordinates (mesh). normals === normals
45
- @test GeometryBasics. faces (mesh) === tfaces
46
-
47
- end
48
-
49
- @testset " per face attributes" begin
50
-
51
- # Construct a cube out of Quads
52
- points = Point{3 , Float64}[
53
- (0.0 , 0.0 , 0.0 ), (2.0 , 0.0 , 0.0 ),
54
- (2.0 , 2.0 , 0.0 ), (0.0 , 2.0 , 0.0 ),
55
- (0.0 , 0.0 , 12.0 ), (2.0 , 0.0 , 12.0 ),
56
- (2.0 , 2.0 , 12.0 ), (0.0 , 2.0 , 12.0 )
57
- ]
58
-
59
- facets = QuadFace{Cint}[
60
- 1 : 4 ,
61
- 5 : 8 ,
62
- [1 , 5 , 6 , 2 ],
63
- [2 , 6 , 7 , 3 ],
64
- [3 , 7 , 8 , 4 ],
65
- [4 , 8 , 5 , 1 ]
66
- ]
67
-
68
- markers = Cint[- 1 , - 2 , 0 , 0 , 0 , 0 ]
69
- # attach some additional information to our faces!
70
- mesh = Mesh (points, meta (facets, markers = markers))
71
- @test hascolumn (GeometryBasics. faces (mesh), :markers )
72
- # test with === to assert we're not doing any copies
73
- @test getcolumn (GeometryBasics. faces (mesh), :markers ) === markers
74
- @test coordinates (mesh) === points
75
- @test metafree (GeometryBasics. faces (mesh)) === facets
76
-
77
- end
78
-
79
- end
80
- @testset " polygon with metadata" begin
81
- polys = [Polygon (rand (Point{2 , Float32}, 20 )) for i in 1 : 10 ]
82
- pnames = [randstring (4 ) for i in 1 : 10 ]
83
- numbers = LinRange (0.0 , 1.0 , 10 )
84
- bin = rand (Bool, 10 )
85
- # create just an array
86
- plain = meta (polys, name = pnames, value = numbers, category = bin)
87
- # create a MultiPolygon with the right type & meta information!
88
- multipoly = MultiPolygon (polys; name = pnames, value = numbers, category = bin)
89
- for x in (plain, multipoly)
90
- for (mp, p, n, num, b) in zip (x, polys, pnames, numbers, bin)
91
- @test mp. polygon == p
92
- @test mp. name == n
93
- @test mp. value == num
94
- @test mp. category == b
95
- end
96
-
97
- filtered = @from i in x begin
98
- @where i. value < 0.7
99
- @select i
100
- @collect
101
- end
102
- @test length (filtered) == 7
103
- end
104
- end
105
- end
106
-
107
- @testset " view" begin
108
- @testset " TupleView" begin
109
- x = [1 , 2 , 3 , 4 , 5 , 6 ]
110
- y = TupleView {2, 1} (x)
111
- @test y == [(1 , 2 ), (2 , 3 ), (3 , 4 ), (4 , 5 ), (5 , 6 )]
112
-
113
- y = TupleView {2} (x)
114
- @test y == [(1 , 2 ), (3 , 4 ), (5 , 6 )]
115
-
116
- y = TupleView {2, 3} (x)
117
- @test y == [(1 , 2 ), (4 , 5 )]
118
-
119
- y = TupleView {3, 1} (x)
120
- @test y == [(1 , 2 , 3 ), (2 , 3 , 4 ), (3 , 4 , 5 ), (4 , 5 , 6 )]
121
-
122
- y = TupleView {2, 1} (x, connect = true )
123
- @test y == [(1 , 2 ), (2 , 3 ), (3 , 4 ), (4 , 5 ), (5 , 6 ), (6 , 1 )]
124
-
125
- end
126
- @testset " connected views" begin
127
- numbers = [1 , 2 , 3 , 4 , 5 , 6 ]
128
- x = connect (numbers, Point{2 })
129
-
130
- @test x == Point[(1 , 2 ), (3 , 4 ), (5 , 6 )]
131
-
132
- line = connect (x, Line, 1 )
133
- @test line == [Line (Point (1 , 2 ), Point (3 , 4 )), Line (Point (3 , 4 ), Point (5 , 6 ))]
134
-
135
- triangles = connect (x, Triangle)
136
- @test triangles == [Triangle (Point (1 , 2 ), Point (3 , 4 ), Point (5 , 6 ))]
137
- x = connect ([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ], Point{2 })
138
- tetrahedra = connect (x, NSimplex{4 })
139
- @test tetrahedra == [Tetrahedron (x[1 ], x[2 ], x[3 ], x[4 ])]
140
-
141
- @testset " matrix non-copy point views" begin
142
- # point in row
143
- points = [1 2 ; 1 4 ; 66 77 ]
144
- comparison = [Point (1 , 2 ), Point (1 , 4 ), Point (66 , 77 )]
145
- @test connect (points, Point{2 }) == comparison
146
- # point in column
147
- points = [1 1 66 ; 2 4 77 ]
148
- # huh, reinterpret array doesn't seem to like `==`
149
- @test all (((a,b),)-> a== b, zip (connect (points, Point{2 }), comparison))
150
- end
151
- end
152
-
153
- @testset " face views" begin
154
- numbers = [1 , 2 , 3 , 4 , 5 , 6 ]
155
- points = connect (numbers, Point{2 })
156
- faces = connect ([1 , 2 , 3 ], TriangleFace)
157
- triangles = connect (points, faces)
158
- @test triangles == [Triangle (Point (1 , 2 ), Point (3 , 4 ), Point (5 , 6 ))]
159
- x = Point {3} (1.0 )
160
- triangles = connect ([x], [TriangleFace (1 , 1 , 1 )])
161
- @test triangles == [Triangle (x, x, x)]
162
- points = connect ([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ], Point{2 })
163
- faces = connect ([1 , 2 , 3 , 4 ], SimplexFace{4 })
164
- triangles = connect (points, faces)
165
- @test triangles == [Tetrahedron (points... )]
166
- end
167
-
168
- end
169
-
170
-
171
- @testset " constructors" begin
172
- @testset " LineFace" begin
173
-
174
- points = connect ([1 , 2 , 3 , 4 , 5 , 6 ], Point{2 })
175
- linestring = LineString (points)
176
- @test linestring == [Line (points[1 ], points[2 ]), Line (points[2 ], points[3 ])]
177
-
178
- points = rand (Point{2 , Float64}, 4 )
179
- linestring = LineString (points, 2 )
180
- @test linestring == [Line (points[1 ], points[2 ]), Line (points[3 ], points[4 ])]
181
-
182
- linestring = LineString ([points[1 ] => points[2 ], points[2 ] => points[3 ]])
183
- @test linestring == [Line (points[1 ], points[2 ]), Line (points[2 ], points[3 ])]
184
-
185
- faces = [1 , 2 , 3 ]
186
- linestring = LineString (points, faces)
187
- @test linestring == LineString ([points[1 ] => points[2 ], points[2 ] => points[3 ]])
188
- a, b, c, d = Point (1 , 2 ), Point (3 , 4 ), Point (5 , 6 ), Point (7 , 8 )
189
- points = [a, b, c, d]; faces = [1 , 2 , 3 , 4 ]
190
- linestring = LineString (points, faces, 2 )
191
- @test linestring == LineString ([a => b, c => d])
192
-
193
- faces = [LineFace (1 , 2 ), LineFace (3 , 4 )]
194
- linestring = LineString (points, faces)
195
- @test linestring == LineString ([a => b, c => d])
196
- end
197
-
198
- @testset " Polygon" begin
199
-
200
- points = connect ([1 , 2 , 3 , 4 , 5 , 6 ], Point{2 })
201
- polygon = Polygon (points)
202
- @test polygon == Polygon (LineString (points))
203
-
204
- points = rand (Point{2 , Float64}, 4 )
205
- linestring = LineString (points, 2 )
206
- @test Polygon (points, 2 ) == Polygon (linestring)
207
-
208
- faces = [1 , 2 , 3 ]
209
- polygon = Polygon (points, faces)
210
- @test polygon == Polygon (LineString (points, faces))
211
-
212
- a, b, c, d = Point (1 , 2 ), Point (3 , 4 ), Point (5 , 6 ), Point (7 , 8 )
213
- points = [a, b, c, d]; faces = [1 , 2 , 3 , 4 ]
214
- polygon = Polygon (points, faces, 2 )
215
- @test polygon == Polygon (LineString (points, faces, 2 ))
216
-
217
- faces = [LineFace (1 , 2 ), LineFace (3 , 4 )]
218
- polygon = Polygon (points, faces)
219
- @test polygon == Polygon (LineString (points, faces))
220
- end
221
-
222
- @testset " Mesh" begin
223
-
224
- numbers = [1 , 2 , 3 , 4 , 5 , 6 ]
225
- points = connect (numbers, Point{2 })
226
-
227
- mesh = Mesh (points, [1 ,2 ,3 ])
228
- @test mesh == [Triangle (points... )]
229
-
230
- x = Point {3} (1.0 )
231
- mesh = Mesh ([x], [TriangleFace (1 , 1 , 1 )])
232
- @test mesh == [Triangle (x, x, x)]
233
-
234
- points = connect ([1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 ], Point{2 })
235
- faces = connect ([1 , 2 , 3 , 4 ], SimplexFace{4 })
236
- mesh = Mesh (points, faces)
237
- @test mesh == [Tetrahedron (points... )]
238
-
239
- end
240
-
241
- end
21
+
22
+ # create some points
23
+ julia> p1 = Point (3 , 1 )
24
+ 2 - element Point{2 ,Int64} with indices SOneTo (2 ):
25
+ 3
26
+ 1
27
+
28
+ julia> p2 = Point (1 , 3 );
29
+
30
+ julia> p3 = Point (4 , 4 );
31
+
32
+ # geometries can carry metadata
33
+ julia> poi = meta (p1, city= " Abuja" , rainfall= 1221.2 )
34
+ 2 - element PointMeta{2 ,Int64,Point{2 ,Int64},(:city , :rainfall ),Tuple{String,Float64}} with indices SOneTo (2 ):
35
+ 3
36
+ 1
37
+
38
+ # metadata is stored in a NamedTuple and can be retrieved as such
39
+ julia> meta (poi)
40
+ (city = " Abuja" , rainfall = 1221.2 )
41
+
42
+ # specific metadata attributes can be directly retrieved
43
+ julia> poi. rainfall
44
+ 1221.2
45
+
46
+ # to remove the metadata and keep only the geometry, use metafree
47
+ julia> metafree (poi)
48
+ 2 - element Point{2 ,Int64} with indices SOneTo (2 ):
49
+ 3
50
+ 1
51
+
52
+ # connect the points with lines
53
+ julia> l1 = Line (p1, p2)
54
+ Line ([3 , 1 ] => [1 , 3 ])
55
+
56
+ julia> l2 = Line (p2, p3);
57
+
58
+ # connect the lines in a linestring
59
+ julia> LineString ([l1, l2])
60
+ 2 - element LineString{2 ,Int64,Point{2 ,Int64},Array{GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}},1 }}:
61
+ Line ([3 , 1 ] => [1 , 3 ])
62
+ Line ([1 , 3 ] => [4 , 4 ])
63
+
64
+ # linestrings can also be constructed directly from points
65
+ julia> LineString ([p1, p2, p3])
66
+ 2 - element LineString{2 ,Int64,Point{2 ,Int64},Base. ReinterpretArray{GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}},1 ,Tuple{Point{2 ,Int64},Point{2 ,Int64}},TupleView{Tuple{Point{2 ,Int64},Point{2 ,Int64}}, 1 }}}:
67
+ Line ([3 , 1 ] => [1 , 3 ])
68
+ Line ([1 , 3 ] => [4 , 4 ])
69
+
70
+ # the same goes for polygons
71
+ julia> Polygon (Point{2 , Int}[(3 , 1 ), (4 , 4 ), (2 , 4 ), (1 , 2 ), (3 , 1 )])
72
+ Polygon{2 ,Int64,Point{2 ,Int64},LineString{2 ,Int64,Point{2 ,Int64},Base. ReinterpretArray{GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}},1 ,Tuple{Point{2 ,Int64},Point{2 ,Int64}},TupleView{Tuple{Point{2 ,Int64},Point{2 ,Int64}}, 1 }}},Array{LineString{2 ,Int64,Point{2 ,Int64},Base. ReinterpretArray{GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}},1 ,Tuple{Point{2 ,Int64},Point{2 ,Int64}},TupleView{Tuple{Point{2 ,Int64},Point{2 ,Int64}}, 1 }}},1 }}(GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}}[Line ([3 , 1 ] => [4 , 4 ]), Line ([4 , 4 ] => [2 , 4 ]), Line ([2 , 4 ] => [1 , 2 ]), Line ([1 , 2 ] => [3 , 1 ])], LineString{2 ,Int64,Point{2 ,Int64},Base. ReinterpretArray{GeometryBasics. Ngon{2 ,Int64,2 ,Point{2 ,Int64}},1 ,Tuple{Point{2 ,Int64},Point{2 ,Int64}},TupleView{Tuple{Point{2 ,Int64},Point{2 ,Int64}}, 1 }}}[])
73
+
74
+ # create a rectangle placed at the origin with unit widths
75
+ julia> rect = Rect (Vec (0.0 , 0.0 ), Vec (1.0 , 1.0 ))
76
+ GeometryBasics. HyperRectangle {2,Float64} ([0.0 , 0.0 ], [1.0 , 1.0 ])
77
+
78
+ # decompose the rectangle into two triangular faces
79
+ julia> rect_faces = decompose (TriangleFace{Int}, rect)
80
+ 2 - element Array{NgonFace{3 ,Int64},1 }:
81
+ TriangleFace (1 , 2 , 4 )
82
+ TriangleFace (1 , 4 , 3 )
83
+
84
+ # decompose the rectangle into four vertices
85
+ julia> rect_vertices = decompose (Point{2 , Float64}, rect)
86
+ 4 - element Array{Point{2 ,Float64},1 }:
87
+ [0.0 , 0.0 ]
88
+ [1.0 , 0.0 ]
89
+ [0.0 , 1.0 ]
90
+ [1.0 , 1.0 ]
91
+
92
+ # combine the vertices and faces into a triangle mesh
93
+ julia> mesh = Mesh (rect_vertices, rect_faces)
94
+ Mesh{2 , Float64, Triangle}:
95
+ Triangle ([0.0 , 0.0 ], [1.0 , 0.0 ], [1.0 , 1.0 ])
96
+ Triangle ([0.0 , 0.0 ], [1.0 , 1.0 ], [0.0 , 1.0 ])
242
97
```
0 commit comments