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
14 changes: 0 additions & 14 deletions encoding/error.go
Original file line number Diff line number Diff line change
@@ -1,15 +1 @@
package encoding

import (
"fmt"

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

type ErrUnknownGeometry struct {
Geom geom.Geometry
}

func (e ErrUnknownGeometry) Error() string {
return fmt.Sprintf("unknown geometry: %T", e.Geom)
}
3 changes: 1 addition & 2 deletions encoding/geojson/geojson.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"encoding/json"

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

type GeoJSONType string
Expand Down Expand Up @@ -95,7 +94,7 @@ func (geo Geometry) MarshalJSON() ([]byte, error) {
})

default:
return nil, encoding.ErrUnknownGeometry{g}
return nil, geom.ErrUnknownGeometry{g}
}
}

Expand Down
3 changes: 1 addition & 2 deletions encoding/geojson/geojson_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"testing"

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

Expand Down Expand Up @@ -109,7 +108,7 @@ func TestFeatureMarshalJSON(t *testing.T) {
geom: nil,
expectedErr: json.MarshalerError{
Type: reflect.TypeOf(geojson.Geometry{}),
Err: encoding.ErrUnknownGeometry{nil},
Err: geom.ErrUnknownGeometry{nil},
},
},
}
Expand Down
10 changes: 1 addition & 9 deletions encoding/wkb/wkb.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,6 @@ import (
"github.com/go-spatial/geom/encoding/wkb/internal/encode"
)

type ErrUnknownGeometry struct {
Geom geom.Geometry
}

func (e ErrUnknownGeometry) Error() string {
return fmt.Sprintf("Unknown Geometry! %v", e.Geom)
}

type ErrUnknownGeometryType struct {
Typ uint32
}
Expand Down Expand Up @@ -108,7 +100,7 @@ func _encode(en *encode.Encoder, g geom.Geometry) error {
}
}
default:
return ErrUnknownGeometry{g}
return geom.ErrUnknownGeometry{g}
}
return en.Err()
}
Expand Down
10 changes: 1 addition & 9 deletions encoding/wkt/wkt.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,6 @@ use to take a tagola.Geometry and convert it to a wkt string. It will, also,
contain functions to parse a wkt string into a wkb.Geometry.
*/

type ErrUnknownGeometry struct {
Geom geom.Geometry
}

func (e ErrUnknownGeometry) Error() string {
return fmt.Sprintf("Unknown Geometry! %v", e.Geom)
}

func _encode(geo geom.Geometry) string {

switch g := geo.(type) {
Expand Down Expand Up @@ -173,7 +165,7 @@ func _encode(geo geom.Geometry) string {
func Encode(geo geom.Geometry) (string, error) {
switch g := geo.(type) {
default:
return "", ErrUnknownGeometry{geo}
return "", geom.ErrUnknownGeometry{geo}
case geom.Pointer:
// POINT( 10 10)
if isNil(g) {
Expand Down
2 changes: 1 addition & 1 deletion encoding/wkt/wkt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func TestEncode(t *testing.T) {
tests := map[string]map[string]tcase{
"Point": {
"empty nil": {
Err: ErrUnknownGeometry{nil},
Err: geom.ErrUnknownGeometry{nil},
},
"empty": {
Geom: (*geom.Point)(nil),
Expand Down
12 changes: 12 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package geom

import "fmt"

// ErrUnknownGeometry represents an objects that is not a known geom geometry.
type ErrUnknownGeometry struct {
Geom Geometry
}

func (e ErrUnknownGeometry) Error() string {
return fmt.Sprintf("unknown geometry: %T", e.Geom)
}
7 changes: 1 addition & 6 deletions geom.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
// Package geom describes geometry interfaces.
package geom

import "errors"

// ErrUnknownGeometry is returned when the geometry type is unknown or unsupported.
var ErrUnknownGeometry = errors.New("unknown geometry")

// Geometry is an object with a spatial reference.
// if a method accepts a Geometry type it's only expected to support the geom types in this package
type Geometry interface{}
Expand Down Expand Up @@ -62,7 +57,7 @@ func getCoordinates(g Geometry, pts *[]Point) error {

default:

return ErrUnknownGeometry
return ErrUnknownGeometry{g}

case Pointer:

Expand Down
40 changes: 40 additions & 0 deletions planar/planar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package planar

import (
"math"
)

const Rad = math.Pi / 180

type PointLineDistanceFunc func(line [2][2]float64, point [2]float64) float64

// PerpendicularDistance provides the distance between a line and a point in Euclidean space.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Line defined by two points" section

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// ref: https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line#Line_defined_by_two_points
func PerpendicularDistance(line [2][2]float64, point [2]float64) float64 {

deltaX := line[1][0] - line[0][0]
deltaY := line[1][1] - line[0][1]
deltaXSq := deltaX * deltaX
deltaYSq := deltaY * deltaY

num := math.Abs((deltaY * point[0]) - (deltaX * point[1]) + (line[1][0] * line[0][1]) - (line[1][1] * line[0][0]))
denom := math.Sqrt(deltaYSq + deltaXSq)
if denom == 0 {
return 0
}
return num / denom
}

// Slope — finds the Slope of a line
func Slope(line [2][2]float64) (m, b float64, defined bool) {
dx := line[1][0] - line[0][0]
dy := line[1][1] - line[0][1]
if dx == 0 || dy == 0 {
// if dx == 0 then m == 0; and the intercept is y.
// However if the lines are verticle then the slope is not defined.
return 0, line[0][1], dx != 0
}
m = dy / dx
b = line[0][1] - (m * line[0][0])
return m, b, true
}
50 changes: 50 additions & 0 deletions planar/planar_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package planar

import (
"strconv"
"testing"
)

func TestSlope(t *testing.T) {
type tcase struct {
line [2][2]float64
m, b float64
defined bool
}

fn := func(t *testing.T, tc tcase) {
t.Parallel()
gm, gb, gd := Slope(tc.line)
if tc.defined != gd {
t.Errorf("sloped defined, expected %v got %v", tc.defined, gd)
return
}
// if the slope is not defined, line is verticle and m,b don't have good values.
if !tc.defined {
return
}
if tc.m != gm {
t.Errorf("sloped, expected %v got %v", tc.m, gm)

}
if tc.b != gb {
t.Errorf("sloped intercept, expected %v got %v", tc.b, gb)
}
}
tests := []tcase{
{
line: [2][2]float64{{0, 0}, {10, 10}},
m: 1,
b: 0,
defined: true,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With all the test framework in place, you'll want to add some more tests. For instance, this won't catch a case where x/y get swapped.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I don't have very good tests in there right now. I was still in the process of converting over the code, and did not have time to add all the test cases. This was just to get the framework for the test in place, to make it easy to add more.

},
{
line: [2][2]float64{{1, 7}, {1, 17}},
defined: false,
},
}
for i := range tests {
tc := tests[i]
t.Run(strconv.FormatInt(int64(i), 10), func(t *testing.T) { fn(t, tc) })
}
}
87 changes: 87 additions & 0 deletions planar/simplify.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package planar

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

// Simplifer is an interface for Simplifying geometries.
type Simplifer interface {
Simplify(linestring [][2]float64, isClosed bool) ([][2]float64, error)
}

func simplifyPolygon(simplifer Simplifer, plg [][][2]float64, isClosed bool) (ret [][][2]float64, err error) {
ret = make([][][2]float64, len(plg))
for i := range plg {
ls, err := simplifer.Simplify(plg[i], isClosed)
if err != nil {
return nil, err
}
ret[i] = ls
}
return ret, nil

}

// Simplify will simplify the provided geometry using the provided simplifer.
// If the simplifer is nil, no simplification will be attempted.
func Simplify(simplifer Simplifer, geometry geom.Geometry) (geom.Geometry, error) {

if simplifer == nil {
return geometry, nil
}

switch gg := geometry.(type) {

case geom.Collectioner:

geos := gg.Geometries()
coll := make([]geom.Geometry, len(geos))
for i := range geos {
geo, err := Simplify(simplifer, geos[i])
if err != nil {
return nil, err
}
coll[i] = geo
}
return geom.Collection(coll), nil

case geom.MultiPolygoner:

plys := gg.Polygons()
mply := make([][][][2]float64, len(plys))
for i := range plys {
ply, err := simplifyPolygon(simplifer, plys[i], true)
if err != nil {
return nil, err
}
mply[i] = ply
}
return geom.MultiPolygon(mply), nil

case geom.Polygoner:

ply, err := simplifyPolygon(simplifer, gg.LinearRings(), true)
if err != nil {
return nil, err
}
return geom.Polygon(ply), nil

case geom.MultiLineStringer:

mls, err := simplifyPolygon(simplifer, gg.LineStrings(), false)
if err != nil {
return nil, err
}
return geom.MultiLineString(mls), nil

case geom.LineStringer:

ls, err := simplifer.Simplify(gg.Verticies(), false)
if err != nil {
return nil, err
}
return geom.LineString(ls), nil

default: // Points, MutliPoints or anything else.
return geometry, nil

}
}
1 change: 0 additions & 1 deletion slippy/tile.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func Lat2Tile(zoom uint, lat float64) (y uint) {
}

func Lon2Tile(zoom uint, lon float64) (x uint) {

return uint(math.Exp2(float64(zoom)) * (lon + 180.0) / 360.0)
}

Expand Down