Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

encoding/wkt: various code improvements #95

Merged
merged 4 commits into from
Apr 6, 2022
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
17 changes: 9 additions & 8 deletions encoding/wkt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@ This package provides encoding and decoding of [WKT](https://en.wikipedia.org/wi
data. The interface is defined as:

```go
func MarshalString(g orb.Geometry) string
func MarshalString(orb.Geometry) string

func UnmarshalCollection(s string) (p orb.Collection, err error)
func UnmarshalLineString(s string) (p orb.LineString, err error)
func UnmarshalMultiLineString(s string) (p orb.MultiLineString, err error)
func UnmarshalMultiPoint(s string) (p orb.MultiPoint, err error)
func UnmarshalMultiPolygon(s string) (p orb.MultiPolygon, err error)
func UnmarshalPoint(s string) (p orb.Point, err error)
func UnmarshalPolygon(s string) (p orb.Polygon, err error)
func Unmarshal(string) (orb.Geometry, error)
func UnmarshalPoint(string) (orb.Point, err error)
func UnmarshalMultiPoint(string) (orb.MultiPoint, err error)
func UnmarshalLineString(string) (orb.LineString, err error)
func UnmarshalMultiLineString(string) (orb.MultiLineString, err error)
func UnmarshalPolygon(string) (orb.Polygon, err error)
func UnmarshalMultiPolygon(string) (orb.MultiPolygon, err error)
func UnmarshalCollection(string) (orb.Collection, err error)
```
177 changes: 70 additions & 107 deletions encoding/wkt/unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,127 +9,112 @@ import (
)

var (
errEmptyGeometry = errors.New("empty geometry")
errUnMarshalPoint = errors.New("unmarshal point error")
errUnMarshalMultiPoint = errors.New("unmarshal multipoint error")
errUnMarshaLineString = errors.New("unmarshal linestring error")
errUnMarshaMultiLineString = errors.New("unmarshal multilinestring error")
errUnMarshaPolygon = errors.New("unmarshal polygon error")
errUnMarshaMultiPolygon = errors.New("unmarshal multipolygon error")
errUnMarshaGeometryCollection = errors.New("unmarshal collection error")
// ErrNotWKT is returned when unmarshalling WKT and the data is not valid.
ErrNotWKT = errors.New("wkt: invalid data")

errConvertToPoint = errors.New("convert to point error")
errConvertToMultiPoint = errors.New("convert to multi point error")
errConvertToLineString = errors.New("convert to line string error")
errConvertToMultiLineString = errors.New("convert to multi line string error")
errConvertToPolygon = errors.New("convert to polygon error")
errConvertToMultiPolygon = errors.New("convert to multi polygon error")
errConvertToGeometryCollection = errors.New("convert to geometry collection error")
)

// errWrap errWarp
func errWrap(err error, es ...error) error {
s := make([]string, 0)
if err != nil {
s = append(s, err.Error())
}

for _, e := range es {
if e != nil {
s = append(s, e.Error())
}
}
// ErrIncorrectGeometry is returned when unmarshalling WKT data into the wrong type.
// For example, unmarshaling linestring data into a point.
ErrIncorrectGeometry = errors.New("wkt: incorrect geometry")

return errors.New(strings.Join(s, "\n"))
}
// ErrUnsupportedGeometry is returned when geometry type is not supported by this lib.
ErrUnsupportedGeometry = errors.New("wkt: unsupported geometry")
)

// UnmarshalPoint return point by parse wkt point string
// UnmarshalPoint returns the point represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a point.
func UnmarshalPoint(s string) (p orb.Point, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.Point{}, errWrap(err, errEmptyGeometry)
return orb.Point{}, err
}
g, ok := geom.(orb.Point)
if !ok {
return orb.Point{}, errWrap(err, errConvertToPoint)
return orb.Point{}, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalMultiPoint return multipoint by parse wkt multipoint string
// UnmarshalMultiPoint returns the multi-point represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a multi-point.
func UnmarshalMultiPoint(s string) (p orb.MultiPoint, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.MultiPoint{}, errWrap(err, errEmptyGeometry)
return nil, err
}

g, ok := geom.(orb.MultiPoint)
if !ok {
return orb.MultiPoint{}, errWrap(err, errConvertToMultiPoint)
return nil, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalLineString return linestring by parse wkt linestring string
// UnmarshalLineString returns the linestring represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a linestring.
func UnmarshalLineString(s string) (p orb.LineString, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.LineString{}, errWrap(err, errEmptyGeometry)
return nil, err
}
g, ok := geom.(orb.LineString)
if !ok {
return orb.LineString{}, errWrap(err, errConvertToLineString)
return nil, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalMultiLineString return linestring by parse wkt multilinestring string
// UnmarshalMultiLineString returns the multi-linestring represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a multi-linestring.
func UnmarshalMultiLineString(s string) (p orb.MultiLineString, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.MultiLineString{}, errWrap(err, errEmptyGeometry)
return nil, err
}
g, ok := geom.(orb.MultiLineString)
if !ok {
return orb.MultiLineString{}, errWrap(err, errConvertToMultiLineString)
return nil, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalPolygon return linestring by parse wkt polygon string
// UnmarshalPolygon returns the polygon represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a polygon.
func UnmarshalPolygon(s string) (p orb.Polygon, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.Polygon{}, errWrap(err, errEmptyGeometry)
return nil, err
}
g, ok := geom.(orb.Polygon)
if !ok {
return orb.Polygon{}, errWrap(err, errConvertToPolygon)
return nil, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalMultiPolygon return linestring by parse wkt multipolygon string
// UnmarshalMultiPolygon returns the multi-polygon represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a multi-polygon.
func UnmarshalMultiPolygon(s string) (p orb.MultiPolygon, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.MultiPolygon{}, errWrap(err, errEmptyGeometry)
return nil, err
}
g, ok := geom.(orb.MultiPolygon)
if !ok {
return orb.MultiPolygon{}, errWrap(err, errConvertToMultiPolygon)
return nil, ErrIncorrectGeometry
}
return g, nil
}

// UnmarshalCollection return linestring by parse wkt collection string
// UnmarshalCollection returns the geometry collection represented by the wkt string.
// Will return ErrIncorrectGeometry if the wkt is not a geometry collection.
func UnmarshalCollection(s string) (p orb.Collection, err error) {
geom, err := unmarshal(s)
geom, err := Unmarshal(s)
if err != nil {
return orb.Collection{}, errWrap(err, errEmptyGeometry)
return orb.Collection{}, err
}
g, ok := geom.(orb.Collection)
if !ok {
return orb.Collection{}, errWrap(err, errConvertToGeometryCollection)
return nil, ErrIncorrectGeometry
}
return g, nil
}
Expand All @@ -143,26 +128,28 @@ func trimSpaceBrackets(s string) string {
if s[len(s)-1] == ')' {
s = s[:len(s)-1]
}
s = strings.Trim(s, " ")
return s

return strings.Trim(s, " ")
}

// parsePoint pase point by (x y)
func parsePoint(s string) (p orb.Point, err error) {
ps := strings.Split(s, " ")
if len(ps) != 2 {
return orb.Point{}, errors.New("can't get x,y")
return orb.Point{}, ErrNotWKT
}

x, err := strconv.ParseFloat(ps[0], 64)
if err != nil {
return orb.Point{}, err
}

y, err := strconv.ParseFloat(ps[1], 64)
if err != nil {
return orb.Point{}, err
}
p = orb.Point{x, y}
return p, nil

return orb.Point{x, y}, nil
}

// splitGeometryCollection split GEOMETRYCOLLECTION to more geometry
Expand Down Expand Up @@ -191,37 +178,27 @@ func splitGeometryCollection(s string) (r []string) {
return
}

/*
unmarshal return a geometry by parse wkt string
order:
GEOMETRYCOLLECTION
MULTIPOINT
POINT
MULTILINESTRING
LINESTRING
MULTIPOLYGON
POLYGON
*/
func unmarshal(s string) (geom orb.Geometry, err error) {
// Unmarshal return a geometry by parsing the WKT string.
func Unmarshal(s string) (geom orb.Geometry, err error) {
s = strings.ToUpper(strings.Trim(s, " "))
switch {
case strings.Contains(s, "GEOMETRYCOLLECTION"):
if s == "GEOMETRYCOLLECTION " {
if s == "GEOMETRYCOLLECTION EMPTY" {
return orb.Collection{}, nil
}
s = strings.Replace(s, "GEOMETRYCOLLECTION", "", -1)
c := orb.Collection{}
ms := splitGeometryCollection(s)
if len(ms) == 0 {
return nil, errUnMarshaGeometryCollection
return nil, err
}
for _, v := range ms {
if len(v) == 0 {
continue
}
g, err := unmarshal(v)
g, err := Unmarshal(v)
if err != nil {
return nil, errWrap(errUnMarshaGeometryCollection, err)
return nil, err
}
c = append(c, g)
}
Expand All @@ -238,7 +215,7 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
for _, p := range ps {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshalPoint, err)
return nil, err
}
mp = append(mp, tp)
}
Expand All @@ -248,7 +225,7 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
s = strings.Replace(s, "POINT", "", -1)
tp, err := parsePoint(trimSpaceBrackets(s))
if err != nil {
return nil, errWrap(errUnMarshalPoint, err)
return nil, err
}
geom = tp

Expand All @@ -263,7 +240,7 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
for _, p := range strings.Split(trimSpaceBrackets(l), ",") {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshaMultiLineString, err)
return nil, err
}
tl = append(tl, tp)
}
Expand All @@ -282,7 +259,7 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
for _, p := range ps {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshaLineString, err)
return nil, err
}
ls = append(ls, tp)
}
Expand All @@ -301,7 +278,7 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
for _, p := range strings.Split(ls, ",") {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshaMultiPolygon, err)
return nil, err
}
ring = append(ring, tp)
}
Expand All @@ -317,38 +294,24 @@ func unmarshal(s string) (geom orb.Geometry, err error) {
}
s = strings.Replace(s, "POLYGON", "", -1)
s = trimSpaceBrackets(s)

rs := strings.Split(s, "),(")
if len(rs) == 1 {
// ring
ps := strings.Split(trimSpaceBrackets(s), ",")
pol := make(orb.Polygon, 0, len(rs))
for _, r := range rs {
ps := strings.Split(trimSpaceBrackets(r), ",")
ring := orb.Ring{}
for _, p := range ps {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshaLineString, err)
return nil, err
}
ring = append(ring, tp)
}
geom = orb.Polygon{ring}
} else {
// more ring
pol := orb.Polygon{}
for _, r := range rs {
ps := strings.Split(trimSpaceBrackets(r), ",")
ring := orb.Ring{}
for _, p := range ps {
tp, err := parsePoint(trimSpaceBrackets(p))
if err != nil {
return nil, errWrap(errUnMarshaLineString, err)
}
ring = append(ring, tp)
}
pol = append(pol, ring)
}
geom = pol
pol = append(pol, ring)
}
geom = pol
default:
return nil, errors.New("wkt: unsupported geometry")
return nil, ErrUnsupportedGeometry
}

return
Expand Down
Loading