2013-04-21 18:37:05 +04:00
|
|
|
package geom
|
|
|
|
|
|
|
|
import (
|
2013-05-15 15:49:41 +04:00
|
|
|
"errors"
|
2013-04-21 18:37:05 +04:00
|
|
|
"goposm/element"
|
2013-05-06 21:24:49 +04:00
|
|
|
"goposm/geom/geos"
|
2013-04-21 18:37:05 +04:00
|
|
|
)
|
|
|
|
|
2013-05-10 12:57:06 +04:00
|
|
|
type GeomError struct {
|
|
|
|
message string
|
|
|
|
level int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *GeomError) Error() string {
|
|
|
|
return e.message
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *GeomError) Level() int {
|
|
|
|
return e.level
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewGeomError(message string, level int) *GeomError {
|
|
|
|
return &GeomError{message, level}
|
|
|
|
}
|
|
|
|
|
2013-05-10 12:08:31 +04:00
|
|
|
var (
|
2013-05-10 12:57:06 +04:00
|
|
|
ErrorOneNodeWay = NewGeomError("need at least two separate nodes for way", 0)
|
2013-05-17 15:05:59 +04:00
|
|
|
ErrorNoRing = NewGeomError("linestrings do not form ring", 0)
|
2013-05-10 12:08:31 +04:00
|
|
|
)
|
|
|
|
|
2013-05-24 12:08:38 +04:00
|
|
|
func PointWkb(g *geos.Geos, node element.Node) (*element.Geometry, error) {
|
2013-05-06 21:24:49 +04:00
|
|
|
coordSeq, err := g.CreateCoordSeq(1, 2)
|
2013-05-06 18:17:07 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// coordSeq inherited by LineString
|
2013-05-06 21:24:49 +04:00
|
|
|
coordSeq.SetXY(g, 0, node.Long, node.Lat)
|
|
|
|
geom, err := coordSeq.AsPoint(g)
|
2013-05-06 18:17:07 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-05-24 12:08:38 +04:00
|
|
|
wkb := g.AsWkb(geom)
|
2013-05-15 15:49:41 +04:00
|
|
|
if wkb == nil {
|
2013-05-15 11:49:38 +04:00
|
|
|
g.Destroy(geom)
|
2013-05-15 15:49:41 +04:00
|
|
|
return nil, errors.New("could not create wkb")
|
2013-05-15 11:49:38 +04:00
|
|
|
}
|
|
|
|
g.DestroyLater(geom)
|
|
|
|
return &element.Geometry{
|
|
|
|
Wkb: wkb,
|
|
|
|
Geom: geom,
|
|
|
|
}, nil
|
2013-05-06 18:17:07 +04:00
|
|
|
}
|
|
|
|
|
2013-05-24 12:08:38 +04:00
|
|
|
func LineStringWkb(g *geos.Geos, nodes []element.Node) (*element.Geometry, error) {
|
2013-05-10 12:08:31 +04:00
|
|
|
if len(nodes) < 2 {
|
|
|
|
return nil, ErrorOneNodeWay
|
|
|
|
}
|
|
|
|
|
2013-05-06 21:24:49 +04:00
|
|
|
coordSeq, err := g.CreateCoordSeq(uint32(len(nodes)), 2)
|
2013-04-24 00:02:27 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
// coordSeq inherited by LineString
|
2013-04-21 18:37:05 +04:00
|
|
|
for i, nd := range nodes {
|
2013-05-06 21:24:49 +04:00
|
|
|
coordSeq.SetXY(g, uint32(i), nd.Long, nd.Lat)
|
2013-04-21 18:37:05 +04:00
|
|
|
}
|
2013-05-06 21:24:49 +04:00
|
|
|
geom, err := coordSeq.AsLineString(g)
|
2013-05-28 13:10:19 +04:00
|
|
|
if err != nil {
|
|
|
|
// coordSeq gets Destroy by GEOS
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
g.DestroyLater(geom)
|
2013-05-24 12:08:38 +04:00
|
|
|
wkb := g.AsWkb(geom)
|
2013-05-15 15:49:41 +04:00
|
|
|
if wkb == nil {
|
|
|
|
return nil, errors.New("could not create wkb")
|
2013-04-24 00:02:27 +04:00
|
|
|
}
|
2013-05-15 11:49:38 +04:00
|
|
|
return &element.Geometry{
|
|
|
|
Wkb: wkb,
|
|
|
|
Geom: geom,
|
|
|
|
}, nil
|
2013-04-21 18:37:05 +04:00
|
|
|
}
|
2013-04-24 00:02:27 +04:00
|
|
|
|
2013-05-24 12:08:38 +04:00
|
|
|
func PolygonWkb(g *geos.Geos, nodes []element.Node) (*element.Geometry, error) {
|
2013-05-16 14:17:21 +04:00
|
|
|
geom, err := Polygon(g, nodes)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-05-24 12:08:38 +04:00
|
|
|
wkb := g.AsWkb(geom)
|
2013-05-16 14:17:21 +04:00
|
|
|
if wkb == nil {
|
|
|
|
return nil, errors.New("could not create wkb")
|
|
|
|
}
|
|
|
|
return &element.Geometry{
|
|
|
|
Wkb: wkb,
|
|
|
|
Geom: geom,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2013-05-24 12:08:38 +04:00
|
|
|
func Polygon(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) {
|
2013-05-06 21:24:49 +04:00
|
|
|
coordSeq, err := g.CreateCoordSeq(uint32(len(nodes)), 2)
|
2013-04-24 00:02:27 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-05-28 13:10:19 +04:00
|
|
|
|
|
|
|
// coordSeq inherited by LinearRing, no destroy
|
2013-04-24 00:02:27 +04:00
|
|
|
for i, nd := range nodes {
|
2013-05-06 21:24:49 +04:00
|
|
|
err := coordSeq.SetXY(g, uint32(i), nd.Long, nd.Lat)
|
2013-04-24 00:02:27 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
}
|
2013-05-28 11:33:59 +04:00
|
|
|
ring, err := coordSeq.AsLinearRing(g)
|
2013-04-24 00:02:27 +04:00
|
|
|
if err != nil {
|
2013-05-28 13:10:19 +04:00
|
|
|
// coordSeq gets Destroy by GEOS
|
2013-04-24 00:02:27 +04:00
|
|
|
return nil, err
|
|
|
|
}
|
2013-05-28 11:33:59 +04:00
|
|
|
// ring inherited by Polygon, no destroy
|
2013-05-16 14:17:21 +04:00
|
|
|
|
2013-05-28 11:33:59 +04:00
|
|
|
geom := g.CreatePolygon(ring, nil)
|
|
|
|
if geom == nil {
|
|
|
|
g.Destroy(ring)
|
|
|
|
return nil, errors.New("unable to create polygon")
|
2013-04-24 00:02:27 +04:00
|
|
|
}
|
2013-05-28 11:33:59 +04:00
|
|
|
g.DestroyLater(geom)
|
2013-05-16 14:17:21 +04:00
|
|
|
return geom, nil
|
2013-04-24 00:02:27 +04:00
|
|
|
}
|