func SplitPolygonAtGrid(g *geos.Geos, geom *geos.Geom, gridWidth, currentGridWidth float64) ([]*geos.Geom, error) { var result []*geos.Geom geomBounds := geom.Bounds() if geomBounds == geos.NilBounds { return nil, errors.New("couldn't create bounds for geom") } for _, bounds := range tileBounds(geom.Bounds(), currentGridWidth) { clipGeom := g.BoundsPolygon(bounds) if clipGeom == nil { return nil, errors.New("couldn't create bounds polygon") } part := g.Intersection(geom, clipGeom) g.Destroy(clipGeom) if part == nil { return nil, errors.New("couldn't create intersection") } if !g.IsEmpty(part) && strings.HasSuffix(g.Type(part), "Polygon") { if gridWidth >= currentGridWidth { result = append(result, part) } else { moreParts, err := SplitPolygonAtGrid(g, part, gridWidth, currentGridWidth/2.0) g.Destroy(part) if err != nil { return nil, err } result = append(result, moreParts...) } } } return result, nil }
func Polygon(g *geos.Geos, nodes []element.Node) (*geos.Geom, error) { nodes = unduplicateNodes(nodes) if len(nodes) < 4 { return nil, ErrorNoRing } coordSeq, err := g.CreateCoordSeq(uint32(len(nodes)), 2) if err != nil { return nil, err } // coordSeq inherited by LinearRing, no destroy for i, nd := range nodes { err := coordSeq.SetXY(g, uint32(i), nd.Long, nd.Lat) if err != nil { return nil, err } } ring, err := coordSeq.AsLinearRing(g) if err != nil { // coordSeq gets Destroy by GEOS return nil, err } // ring inherited by Polygon, no destroy geom := g.Polygon(ring, nil) if geom == nil { g.Destroy(ring) return nil, errors.New("unable to create polygon") } g.DestroyLater(geom) return geom, nil }
func geosPolygon(g *geos.Geos, polygon polygon) (*geos.Geom, error) { if len(polygon) == 0 { return nil, errors.New("empty polygon") } shell, err := geosRing(g, polygon[0]) if err != nil { return nil, err } holes := make([]*geos.Geom, len(polygon)-1) for i, ls := range polygon[1:] { hole, err := geosRing(g, ls) if err != nil { return nil, err } holes[i] = hole } geom := g.Polygon(shell, holes) if geom == nil { g.Destroy(shell) for _, hole := range holes { g.Destroy(hole) } return nil, errors.New("unable to create polygon") } return geom, nil }
func destroyRings(g *geos.Geos, rings []*Ring) { for _, r := range rings { if r.geom != nil { g.Destroy(r.geom) r.geom = nil } } }
func filterInvalidLineStrings(g *geos.Geos, geoms []*geos.Geom) []*geos.Geom { var result []*geos.Geom for _, geom := range geoms { if geom.Length() > 1e-9 { result = append(result, geom) } else { g.Destroy(geom) } } return result }
func flattenLineStrings(g *geos.Geos, geoms []*geos.Geom) []*geos.Geom { var result []*geos.Geom for _, geom := range geoms { if g.Type(geom) == "MultiLineString" { for _, part := range g.Geoms(geom) { result = append(result, g.Clone(part)) } g.Destroy(geom) } else if g.Type(geom) == "LineString" { result = append(result, geom) } else { log.Printf("unexpected geometry type in flattenPolygons") g.Destroy(geom) } } return result }
func (c *Limiter) IntersectsBuffer(g *geos.Geos, x, y float64) bool { if c.bufferedPrep == nil { return true } if x < c.bufferedBbox.MinX || y < c.bufferedBbox.MinY || x > c.bufferedBbox.MaxX || y > c.bufferedBbox.MaxY { return false } p := g.Point(x, y) if p == nil { return false } defer g.Destroy(p) c.bufferedPrepMu.Lock() defer c.bufferedPrepMu.Unlock() return g.PreparedIntersects(c.bufferedPrep, p) }
func filterGeometryByType(g *geos.Geos, geom *geos.Geom, targetType string) []*geos.Geom { // Filter (multi)geometry for compatible `geom_type`, // because we can't insert points into linestring tables for example geomType := g.Type(geom) if geomType == targetType { // same type is fine return []*geos.Geom{geom} } if geomType == "Polygon" && targetType == "MultiPolygon" { // multipolygon mappings also support polygons return []*geos.Geom{geom} } if geomType == "MultiPolygon" && targetType == "Polygon" { // polygon mappings should also support multipolygons return []*geos.Geom{geom} } if g.NumGeoms(geom) >= 1 { // GeometryCollection or MultiLineString? return list of geometries var geoms []*geos.Geom for _, part := range g.Geoms(geom) { // only parts with same type if g.Type(part) == targetType { geoms = append(geoms, g.Clone(part)) } } g.Destroy(geom) if len(geoms) != 0 { return geoms } return []*geos.Geom{} } g.Destroy(geom) return []*geos.Geom{} }