Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions encoding/mvt/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"log"

"github.com/go-spatial/geom"
"github.com/go-spatial/geom/encoding/wkt"
vectorTile "github.com/go-spatial/geom/encoding/mvt/vector_tile"
"github.com/go-spatial/geom/encoding/wkt"
)

var (
Expand Down Expand Up @@ -36,7 +36,6 @@ func (f Feature) String() string {
return fmt.Sprintf("encoding error for geom geom, %v", err)
}


if f.ID != nil {
return fmt.Sprintf("{Feature: %v, GEO: %v, Tags: %+v}", *f.ID, g, f.Tags)
}
Expand Down Expand Up @@ -255,6 +254,23 @@ func encodeGeometry(ctx context.Context, geometry geom.Geometry) (g []uint32, vt
}
return g, vectorTile.Tile_POLYGON, nil

case *geom.MultiPolygon:
if t == nil {
return g, vectorTile.Tile_POLYGON, nil
}

polygons := t.Polygons()
for _, p := range polygons {
lines := geom.Polygon(p).LinearRings()
for _, l := range lines {
points := geom.LineString(l).Verticies()
g = append(g, c.MoveTo(points[0])...)
g = append(g, c.LineTo(points[1:]...)...)
g = append(g, c.ClosePath())
}
}
return g, vectorTile.Tile_POLYGON, nil

default:
return nil, vectorTile.Tile_UNKNOWN, ErrUnknownGeometryType
}
Expand Down
2 changes: 1 addition & 1 deletion planar/makevalid/walker/walker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ func TestPolygonForTriangle(t *testing.T) {
},
idx: []int{0},
polygons: [][][][2]float64{
{{{0, 0}, {10, 0}, {10, 10}, {0, 10}, {0, 7}}, {{0, 7}, {7, 7}, {7, 2}}},
{{{0, 0}, {10, 0}, {10, 10}, {0, 10}}, {{0, 7}, {7, 7}, {7, 2}}},
{{{0, 0}, {10, 0}, {10, 10}, {0, 10}}},
},
seenTriangles: [][]int{
Expand Down
20 changes: 17 additions & 3 deletions planar/planar.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ func IsPointOnLine(pt [2]float64, l1, l2 [2]float64) bool {
switch {
case !defined:
// line is vertical, so if we the y values are the same it's on the line.
return cmp.Float(pt[1], l1[1])
case m == 0:
// line is horizontal, so if the x values are the same it's on the line.
return cmp.Float(pt[0], l1[0])
case m == 0:
// line is horizontal, so if the y values are the same it's on the line.
return cmp.Float(pt[1], l1[1])
default:
y := (m * pt[0]) + b
return cmp.Float(pt[1], y)
Expand Down Expand Up @@ -89,6 +89,20 @@ func IsPointOnLineSegment(pt geom.Point, seg geom.Line) bool {

}

// PointOnLineAt will return a point on the given line at the distance from the
// origin of the line
func PointOnLineAt(ln geom.Line, distance float64) geom.Point {

lineDist := math.Sqrt(ln.LenghtSquared())
ratio := distance / lineDist
var x, y float64

x = ln[0][0] + (ratio * (ln[1][0] - ln[0][0]))
y = ln[0][1] + (ratio * (ln[1][1] - ln[0][1]))
return geom.Point{x, y}
}

// IsCCW will check if the given points are in counter-clockwise order.
func IsCCW(a, b, c geom.Point) bool {
return geom.Triangle{[2]float64(a), [2]float64(b), [2]float64(c)}.Area() > 0
}
189 changes: 188 additions & 1 deletion planar/planar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"strconv"
"testing"

"github.com/go-spatial/geom/cmp"

"github.com/go-spatial/geom"
)

Expand Down Expand Up @@ -51,6 +53,71 @@ func TestSlope(t *testing.T) {
t.Run(strconv.FormatInt(int64(i), 10), func(t *testing.T) { fn(t, tc) })
}
}
func TestIsPointOnLine(t *testing.T) {
type tcase struct {
desc string
point geom.Point
segment geom.Line
expected bool
}
fn := func(tc tcase) (string, func(*testing.T)) {
return fmt.Sprintf("%v on %v", tc.point, tc.segment),
func(t *testing.T) {
if tc.expected != IsPointOnLine(tc.point, tc.segment[0], tc.segment[1]) {
t.Errorf("expected %v, got %v", tc.expected, !tc.expected)
}
}
}
tests := [...]tcase{
{
// Diagonal line
point: geom.Point{1, 1},
segment: geom.Line{{0, 0}, {1, 10}},
},
{
// Vertical line
point: geom.Point{1, 1},
segment: geom.Line{{0, 0}, {0, 10}},
},
{
// Vertical line
point: geom.Point{1, 1},
segment: geom.Line{{0, 10}, {10, 10}},
},
{
// horizontal line
point: geom.Point{1, 1},
segment: geom.Line{{1, 0}, {1, 10}},
expected: true,
},
{
// horizontal line
point: geom.Point{1, 100},
segment: geom.Line{{1, 0}, {1, 10}},
expected: true,
},
{
// horizontal line
point: geom.Point{1, -100},
segment: geom.Line{{1, 0}, {1, 10}},
expected: true,
},
{
// horizontal line on close to the end point
point: geom.Point{-0.5, 0},
segment: geom.Line{{1, 0}, {1, 10}},
},
{
// horizontal line on the end point
point: geom.Point{1, 0},
segment: geom.Line{{1, 0}, {1, 10}},
expected: true,
},
}
for _, tc := range tests {
t.Run(fn(tc))
}
}

func TestIsPointOnLineSegment(t *testing.T) {
type tcase struct {
Expand All @@ -63,7 +130,7 @@ func TestIsPointOnLineSegment(t *testing.T) {
return fmt.Sprintf("%v on %v", tc.point, tc.segment),
func(t *testing.T) {
if tc.expected != IsPointOnLineSegment(tc.point, tc.segment) {
t.Errorf("got %v, expected %v", !tc.expected, tc.expected)
t.Errorf("expected %v, got %v", tc.expected, !tc.expected)
}
}
}
Expand Down Expand Up @@ -105,3 +172,123 @@ func TestIsPointOnLineSegment(t *testing.T) {
t.Run(fn(tc))
}
}

func TestIsCCW(t *testing.T) {
type tcase struct {
desc string
p1, p2, p3 geom.Point
is bool
}
fn := func(tc tcase) func(*testing.T) {
return func(t *testing.T) {
got := IsCCW(tc.p1, tc.p2, tc.p3)
if got != tc.is {
t.Errorf(
"%v:%v:%v, expected %v got %v",
tc.p1, tc.p2, tc.p3,
tc.is, got,
)
return
}
}
}

tests := []tcase{
{
p1: geom.Point{0, 0},
p2: geom.Point{1, 0},
p3: geom.Point{1, 1},
is: true,
},
{
p1: geom.Point{204, 694},
p2: geom.Point{-2511, -3640},
p3: geom.Point{3462, -3640},
is: true,
},
{
p2: geom.Point{204, 694},
p3: geom.Point{-2511, -3640},
p1: geom.Point{3462, -3640},
is: true,
},
{
p3: geom.Point{204, 694},
p1: geom.Point{-2511, -3640},
p2: geom.Point{3462, -3640},
is: true,
},
{
p1: geom.Point{-2511, -3640},
p2: geom.Point{204, 694},
p3: geom.Point{3462, -3640},
is: false,
},
{
p1: geom.Point{-2511, 3640},
p2: geom.Point{204, 694},
p3: geom.Point{3462, -3640},
is: false,
},
}

for _, tc := range tests {
t.Run(tc.desc, fn(tc))
}
}
func TestPointOnLineAt(t *testing.T) {

type tcase struct {
desc string
line geom.Line
distance float64
point geom.Point
}

fn := func(tc tcase) func(*testing.T) {
return func(t *testing.T) {
got := PointOnLineAt(tc.line, tc.distance)
if !cmp.GeomPointEqual(tc.point, got) {
t.Errorf("point, expected %v, got %v", tc.point, got)
}
}
}

tests := []tcase{
{
desc: "simple test case",
line: geom.Line{{0, 0}, {10, 0}},
distance: 5.0,
point: geom.Point{5, 0},
},
{
line: geom.Line{{204, 694}, {-2511, -3640}},
distance: 100,
point: geom.Point{150.9122535714552, 609.2551406919657},
},
{
line: geom.Line{{204, 694}, {475.500, 8853}},
distance: 100,
point: geom.Point{207.3257728713106, 793.9446808730132},
},
{
line: geom.Line{{204, 694}, {369, 793}},
distance: 100,
point: geom.Point{289.7492925712544, 745.4495755427527},
},
{
line: geom.Line{{204, 694}, {426, 539}},
distance: 100,
point: geom.Point{285.9925374282251, 636.7529581019149},
},
{
line: geom.Line{{204, 694}, {273, 525}},
distance: 100,
point: geom.Point{241.79928289224065, 601.4191476987149},
},
}

for _, tc := range tests {
t.Run(tc.desc, fn(tc))
}
}
6 changes: 4 additions & 2 deletions planar/triangulate/gdey/quadedge/subdivision/subdivision.go
Original file line number Diff line number Diff line change
Expand Up @@ -253,11 +253,13 @@ func (sd *Subdivision) InsertSite(x geom.Point) bool {
}
}

// appendNonrepeate will append points to an array if that point
// is not the same as the point immediately prior
func appendNonrepeat(pts []geom.Point, v geom.Point) []geom.Point {
if len(pts) == 0 || cmp.GeomPointEqual(v, pts[len(pts)-1]) {
return append(pts, v)
return pts
}
return pts
return append(pts, v)
}

func selectCorrectEdges(from, to *quadedge.Edge) (cfrom, cto *quadedge.Edge) {
Expand Down