Skip to content

Commit 62371e8

Browse files
authored
Merge pull request #41 from visr/gb
README provide quickstart
2 parents 10d2bb1 + 1347597 commit 62371e8

File tree

2 files changed

+79
-224
lines changed

2 files changed

+79
-224
lines changed

README.md

Lines changed: 78 additions & 223 deletions
Original file line numberDiff line numberDiff line change
@@ -12,231 +12,86 @@ Basic Geometry Types.
1212
This package aimes to offer a standard set of Geometry types, which easily work with metadata, query frameworks on geometries and different memory layouts.
1313
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.
1414

15+
This package is a replacement for the discontinued [GeometryTypes](https://github.com/JuliaGeometry/GeometryTypes.jl/).
1516

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
1918

2019
```julia
2120
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])
24297
```

src/interfaces.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ texturecoordinates(tesselation::Tesselation) = texturecoordinates(tesselation.pr
7575

7676

7777
## Decompose methods
78-
# Dispatch type to make `decompose(UV{Vec2f0}, priomitive)` work
78+
# Dispatch type to make `decompose(UV{Vec2f0}, primitive)` work
7979
# and to pass through tesselation information
8080

8181
# Types that can be converted to a mesh via the functions below

0 commit comments

Comments
 (0)