Skip to content

Commit 75e489d

Browse files
committed
common: fix Inferno.ConvexHull3D() with quickhull
migrate from github.com/golang/geo/s2 to github.com/markus-wa/quickhull-go github.com/golang/geo/s2 only works in spherical geometry (S2), since we're in R3 we need to use a different algorithm.
1 parent 9a7720e commit 75e489d

File tree

5 files changed

+66
-43
lines changed

5 files changed

+66
-43
lines changed

common/inferno.go

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ package common
33
import (
44
"math/rand"
55

6+
quickhull "github.com/markus-wa/quickhull-go"
7+
68
r3 "github.com/golang/geo/r3"
7-
s2 "github.com/golang/geo/s2"
89
)
910

1011
// Inferno is a list of Fires with helper functions.
@@ -50,33 +51,31 @@ func (inf Inferno) Active() Inferno {
5051
return res
5152
}
5253

53-
// ConvexHull2D returns the 2D convex hull of all the fires in the inferno.
54+
// ConvexHull2D returns the vertices making up the 2D convex hull of all the fires in the inferno.
5455
// Useful for drawing on 2D maps.
55-
func (inf Inferno) ConvexHull2D() *s2.Loop {
56-
q := s2.NewConvexHullQuery()
56+
func (inf Inferno) ConvexHull2D() []r3.Vector {
57+
pointCloud := make([]r3.Vector, 0, len(inf.Fires))
5758

5859
for _, f := range inf.Fires {
59-
q.AddPoint(s2.Point{
60-
Vector: r3.Vector{
61-
X: f.Vector.X,
62-
Y: f.Vector.Y,
63-
Z: 1,
64-
},
60+
pointCloud = append(pointCloud, r3.Vector{
61+
X: f.Vector.X,
62+
Y: f.Vector.Y,
63+
Z: 0,
6564
})
6665
}
6766

68-
return q.ConvexHull()
67+
return quickhull.ConvexHull(pointCloud)
6968
}
7069

71-
// ConvexHull3D returns the 3D convex hull of all the fires in the inferno.
72-
func (inf Inferno) ConvexHull3D() *s2.Loop {
73-
q := s2.NewConvexHullQuery()
70+
// ConvexHull3D returns the vertices making up the 3D convex hull of all the fires in the inferno.
71+
func (inf Inferno) ConvexHull3D() []r3.Vector {
72+
pointCloud := make([]r3.Vector, len(inf.Fires))
7473

75-
for _, f := range inf.Fires {
76-
q.AddPoint(s2.Point{Vector: f.Vector})
74+
for i, f := range inf.Fires {
75+
pointCloud[i] = f.Vector
7776
}
7877

79-
return q.ConvexHull()
78+
return quickhull.ConvexHull(pointCloud)
8079
}
8180

8281
// NewInferno creates a inferno and sets the Unique-ID.

common/inferno_test.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"testing"
55

66
r3 "github.com/golang/geo/r3"
7-
s2 "github.com/golang/geo/s2"
87
assert "github.com/stretchr/testify/assert"
98
)
109

@@ -40,7 +39,7 @@ func TestInfernoActive(t *testing.T) {
4039
}
4140

4241
func TestInfernoConvexHull2D(t *testing.T) {
43-
// Construct a Inferno that looks roughly like this.
42+
// Construct a Inferno that looks roughly like this.
4443
// D should be inside the 2D Convex Hull but a corner of the 3D Convex Hull
4544
//
4645
// C
@@ -66,15 +65,43 @@ func TestInfernoConvexHull2D(t *testing.T) {
6665
},
6766
}
6867

69-
expectedHull := s2.LoopFromPoints([]s2.Point{
70-
{Vector: r3.Vector{X: 4, Y: 7, Z: 1}},
71-
{Vector: r3.Vector{X: 1, Y: 2, Z: 1}},
72-
{Vector: r3.Vector{X: 7, Y: 2, Z: 1}},
73-
})
68+
expectedHull := []r3.Vector{
69+
{X: 1, Y: 2, Z: 0},
70+
{X: 4, Y: 7, Z: 0},
71+
{X: 7, Y: 2, Z: 0},
72+
}
7473

75-
assert.ElementsMatch(t, expectedHull.Vertices(), inf.ConvexHull2D().Vertices(), "ConvexHull2D should be as expected")
76-
assert.True(t, inf.ConvexHull2D().BoundaryEqual(expectedHull), "Boundary of expected and actual should be equal")
74+
assert.ElementsMatch(t, expectedHull, inf.ConvexHull2D(), "ConvexHull2D should be as expected")
7775

7876
// 3D-hull should be different
79-
assert.NotEqual(t, expectedHull.NumVertices(), inf.ConvexHull3D().NumVertices(), "3D hull should contain the vertex 'D'")
77+
assert.NotEqual(t, len(expectedHull), len(inf.ConvexHull3D()), "3D hull should contain the vertex 'D'")
78+
}
79+
80+
// Just check that all fires are passed to quickhull.ConvexHull()
81+
func TestInfernoConvexHull3D(t *testing.T) {
82+
inf := Inferno{
83+
Fires: []*Fire{
84+
{
85+
Vector: r3.Vector{X: 1, Y: 2, Z: 3},
86+
},
87+
{
88+
Vector: r3.Vector{X: 4, Y: 7, Z: 6},
89+
},
90+
{
91+
Vector: r3.Vector{X: 7, Y: 2, Z: 9},
92+
},
93+
{
94+
Vector: r3.Vector{X: 4, Y: 4, Z: 12},
95+
},
96+
},
97+
}
98+
99+
expectedHull := []r3.Vector{
100+
{X: 1, Y: 2, Z: 3},
101+
{X: 4, Y: 7, Z: 6},
102+
{X: 7, Y: 2, Z: 9},
103+
{X: 4, Y: 4, Z: 12},
104+
}
105+
106+
assert.ElementsMatch(t, expectedHull, inf.ConvexHull3D(), "ConvexHull3D should contain all fire locations")
80107
}

examples/nade-trajectories/nade_trajectories.go

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import (
99
_ "image/jpeg"
1010
"os"
1111

12-
r3 "github.com/golang/geo/r3"
13-
s2 "github.com/golang/geo/s2"
14-
draw2dimg "github.com/llgcode/draw2d/draw2dimg"
12+
"github.com/golang/geo/r3"
13+
"github.com/llgcode/draw2d/draw2dimg"
1514

1615
dem "github.com/markus-wa/demoinfocs-golang"
17-
common "github.com/markus-wa/demoinfocs-golang/common"
18-
events "github.com/markus-wa/demoinfocs-golang/events"
16+
"github.com/markus-wa/demoinfocs-golang/common"
17+
"github.com/markus-wa/demoinfocs-golang/events"
1918
ex "github.com/markus-wa/demoinfocs-golang/examples"
20-
metadata "github.com/markus-wa/demoinfocs-golang/metadata"
19+
"github.com/markus-wa/demoinfocs-golang/metadata"
2120
)
2221

2322
type nadePath struct {
@@ -136,7 +135,7 @@ func drawInfernos(gc *draw2dimg.GraphicContext, infernos []*common.Inferno) {
136135
gc.SetFillColor(colorInferno)
137136

138137
// Calculate hulls
139-
hulls := make([]*s2.Loop, len(infernos))
138+
hulls := make([][]r3.Vector, len(infernos))
140139
for i := range infernos {
141140
hulls[i] = infernos[i].ConvexHull2D()
142141
}
@@ -156,8 +155,7 @@ func drawInfernos(gc *draw2dimg.GraphicContext, infernos []*common.Inferno) {
156155
}
157156
}
158157

159-
func buildInfernoPath(gc *draw2dimg.GraphicContext, hull *s2.Loop) {
160-
vertices := hull.Vertices()
158+
func buildInfernoPath(gc *draw2dimg.GraphicContext, vertices []r3.Vector) {
161159
x, y := curMap.TranslateScale(vertices[0].X, vertices[0].Y)
162160
gc.MoveTo(x, y)
163161

go.mod

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
module github.com/markus-wa/demoinfocs-golang
22

33
require (
4-
github.com/davecgh/go-spew v1.1.1 // indirect
54
github.com/dustin/go-heatmap v0.0.0-20180603032536-b89dbd73785a
65
github.com/gogo/protobuf v1.1.1
76
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
8-
github.com/golang/geo v0.0.0-20180801001241-0bf2f2ac7257
7+
github.com/golang/geo v0.0.0-20180826223333-635502111454
98
github.com/llgcode/draw2d v0.0.0-20180124133339-274031cf2abe
109
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb // indirect
1110
github.com/markus-wa/gobitread v0.2.2
1211
github.com/markus-wa/godispatch v1.1.0
13-
github.com/pmezard/go-difflib v1.0.0 // indirect
12+
github.com/markus-wa/quickhull-go v1.0.1
1413
github.com/stretchr/objx v0.1.1 // indirect
1514
github.com/stretchr/testify v1.2.2
1615
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,18 @@ github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
66
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
77
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
88
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
9-
github.com/golang/geo v0.0.0-20180801001241-0bf2f2ac7257 h1:LJXHhZDgQO3st4q/lNphb98GAQMMe0N+t3W8H6H/5bw=
10-
github.com/golang/geo v0.0.0-20180801001241-0bf2f2ac7257/go.mod h1:vgWZ7cu0fq0KY3PpEHsocXOWJpRtkcbKemU4IUw0M60=
9+
github.com/golang/geo v0.0.0-20180826223333-635502111454 h1:UiKw4ZsXdOM6qRj2nP54DJY6Mp3Vd+aSu1OhPvPR+94=
10+
github.com/golang/geo v0.0.0-20180826223333-635502111454/go.mod h1:vgWZ7cu0fq0KY3PpEHsocXOWJpRtkcbKemU4IUw0M60=
1111
github.com/llgcode/draw2d v0.0.0-20180124133339-274031cf2abe h1:1o9roQNCPeUd4ILU0nZ2isdGk2cwKyij3HyGSXjaTS4=
1212
github.com/llgcode/draw2d v0.0.0-20180124133339-274031cf2abe/go.mod h1:th5ThsEAha37D8D9FbfhLvGuf04dR1aM0mgdYs+XHto=
1313
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb h1:61ndUreYSlWFeCY44JxDDkngVoI7/1MVhEl98Nm0KOk=
1414
github.com/llgcode/ps v0.0.0-20150911083025-f1443b32eedb/go.mod h1:1l8ky+Ew27CMX29uG+a2hNOKpeNYEQjjtiALiBlFQbY=
15-
github.com/markus-wa/gobitread v0.2.1 h1:tINORxAv9XyBR5Nm2XWh+e5YLe7IWoR7xHjVrBn4I0g=
16-
github.com/markus-wa/gobitread v0.2.1/go.mod h1:PcWXMH4gx7o2CKslbkFkLyJB/aHW7JVRG3MRZe3PINg=
1715
github.com/markus-wa/gobitread v0.2.2 h1:4Z4oJ8Bf1XnOy6JZ2/9AdFKVAoxdq7awRjrb+j2BeSQ=
1816
github.com/markus-wa/gobitread v0.2.2/go.mod h1:PcWXMH4gx7o2CKslbkFkLyJB/aHW7JVRG3MRZe3PINg=
1917
github.com/markus-wa/godispatch v1.1.0 h1:J8O+hRkOCexDUQevaSKWDtKeZ3+HcmbEUKY1uYraAjY=
2018
github.com/markus-wa/godispatch v1.1.0/go.mod h1:6o18u24oo58yseMXYD0zQFI6LbSkjJSSBQ4YyDqFX5c=
19+
github.com/markus-wa/quickhull-go v1.0.1 h1:msrwpA4mlVI2Rww6ZzQuCxv+axXVknMaMJYO1om37Mk=
20+
github.com/markus-wa/quickhull-go v1.0.1/go.mod h1:gMPnFb0DpuzRpbHesp64Nq4oFXE5SglAD86nlKrkETs=
2121
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
2222
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
2323
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=

0 commit comments

Comments
 (0)