-
Notifications
You must be signed in to change notification settings - Fork 129
/
snapper.go
98 lines (80 loc) · 3.09 KB
/
snapper.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Package snap Snaps the vertices and segments of a Geometry's vertices to another Geometry's vertices.
// Snap two geometries together with a given tolerance.
package snap
import "github.com/spatial-go/geoos/algorithm/matrix"
// Snap two geometries together with a given tolerance.
func Snap(g0, g1 matrix.Steric, snapTolerance float64) (snapGeom matrix.Collection) {
snapper0 := &Snapper{g0, g1, snapTolerance}
snapGeom = append(snapGeom, snapper0.SnapTo(g1, snapTolerance))
// Snap the second geometry to the snapped first geometry
// (this strategy minimizes the number of possible different points in the result)
snapper1 := &Snapper{g1, g0, snapTolerance}
snapGeom = append(snapGeom, snapper1.SnapTo(snapGeom[0], snapTolerance))
return snapGeom
}
// Snapper Snaps the vertices and segments of a Geometry
// to another Geometry's vertices.
type Snapper struct {
srcGeom, snapGeom matrix.Steric
snapTolerance float64
}
// SnapTo Snaps the vertices in the component LineStrings
// of the source geometry
// to the vertices of the given snap geometry.
func (s *Snapper) SnapTo(snapGeom matrix.Steric, snapTolerance float64) matrix.Steric {
return s.transform(snapGeom)
}
func (s *Snapper) transform(inputGeom matrix.Steric) matrix.Steric {
switch m := inputGeom.(type) {
case matrix.Matrix:
return s.transformPoint(m, nil)
case matrix.LineMatrix:
return s.transformLine(m, nil)
case matrix.PolygonMatrix:
return s.transformPolygon(m, nil)
case matrix.Collection:
return s.transformCollection(m, nil)
}
return nil
}
func (s *Snapper) transformMatrix(srcPt matrix.Matrix, parent matrix.Steric) matrix.Steric {
newPts := s.snapLine(matrix.LineMatrix{srcPt}, s.snapGeom)
return newPts
}
func (s *Snapper) transformMatrixes(srcPts matrix.LineMatrix, parent matrix.Steric) matrix.Steric {
newPts := s.snapLine(srcPts, s.snapGeom)
return newPts
}
func (s *Snapper) snapLine(srcPts matrix.LineMatrix, snapPts matrix.Steric) matrix.Steric {
snapper := &LineSnapper{srcPts, snapPts, s.snapTolerance}
return snapper.snapTo()
}
func (s *Snapper) transformPoint(pt matrix.Matrix, parent matrix.Steric) matrix.Steric {
return s.transformMatrix(pt, pt)
}
// transformLine Transforms a LinearRing.
// The transformation of a LinearRing may result in a coordinate sequence
// which does not form a structurally valid ring (i.e. a degenerate ring of 3 or fewer points).
// In this case a LineString is returned.
func (s *Snapper) transformLine(geom matrix.LineMatrix, parent matrix.Steric) matrix.Steric {
seq := s.transformMatrixes(geom, geom)
return seq
}
func (s *Snapper) transformPolygon(geom matrix.PolygonMatrix, parent matrix.Steric) matrix.Steric {
poly := matrix.PolygonMatrix{}
for _, v := range geom {
poly = append(poly, s.transformLine(v, geom).(matrix.LineMatrix))
}
return poly
}
func (s *Snapper) transformCollection(geom matrix.Collection, parent matrix.Steric) matrix.Collection {
transGeoms := matrix.Collection{}
for _, v := range geom {
transformGeom := s.transform(v)
if transformGeom == nil {
continue
}
transGeoms = append(transGeoms, transformGeom)
}
return transGeoms
}