filter by relation tags before finishing the multipolygon
parent
f65b23a1c7
commit
198f2d925f
|
@ -0,0 +1,26 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"goposm/geom/clipper"
|
||||||
|
"goposm/geom/geos"
|
||||||
|
"log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
clipper, err := clipper.NewFromOgrSource(flag.Arg(0))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
g := geos.NewGeos()
|
||||||
|
defer g.Finish()
|
||||||
|
|
||||||
|
line := g.FromWkt("LINESTRING(1106543 7082055, 1107105.2 7087540.0)")
|
||||||
|
|
||||||
|
result, err := clipper.Clip(line)
|
||||||
|
fmt.Println(result, err)
|
||||||
|
}
|
|
@ -12,6 +12,9 @@ func BuildRelation(rel *element.Relation, srid int) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)
|
||||||
|
|
||||||
_, err = BuildRelGeometry(rel, rings, srid)
|
_, err = BuildRelGeometry(rel, rings, srid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -19,6 +22,32 @@ func BuildRelation(rel *element.Relation, srid int) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type preparedRelation struct {
|
||||||
|
rings []*Ring
|
||||||
|
rel *element.Relation
|
||||||
|
srid int
|
||||||
|
}
|
||||||
|
|
||||||
|
func PrepareRelation(rel *element.Relation, srid int) (*preparedRelation, error) {
|
||||||
|
rings, err := BuildRings(rel)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rel.Tags = relationTags(rel.Tags, rings[0].ways[0].Tags)
|
||||||
|
|
||||||
|
return &preparedRelation{rings, rel, srid}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (prep *preparedRelation) Build() (*element.Relation, error) {
|
||||||
|
_, err := BuildRelGeometry(prep.rel, prep.rings, prep.srid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return prep.rel, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func destroyRings(g *geos.Geos, rings []*Ring) {
|
func destroyRings(g *geos.Geos, rings []*Ring) {
|
||||||
for _, r := range rings {
|
for _, r := range rings {
|
||||||
if r.geom != nil {
|
if r.geom != nil {
|
||||||
|
@ -83,6 +112,13 @@ func BuildRings(rel *element.Relation) ([]*Ring, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
completeRings = append(completeRings, mergedRings...)
|
completeRings = append(completeRings, mergedRings...)
|
||||||
|
|
||||||
|
// sort by area (large to small)
|
||||||
|
for _, r := range completeRings {
|
||||||
|
r.area = r.geom.Area()
|
||||||
|
}
|
||||||
|
sort.Sort(SortableRingsDesc(completeRings))
|
||||||
|
|
||||||
return completeRings, nil
|
return completeRings, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,17 +128,13 @@ func (r SortableRingsDesc) Len() int { return len(r) }
|
||||||
func (r SortableRingsDesc) Less(i, j int) bool { return r[i].area > r[j].area }
|
func (r SortableRingsDesc) Less(i, j int) bool { return r[i].area > r[j].area }
|
||||||
func (r SortableRingsDesc) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
func (r SortableRingsDesc) Swap(i, j int) { r[i], r[j] = r[j], r[i] }
|
||||||
|
|
||||||
|
// BuildRelGeometry builds the geometry of rel by creating a multipolygon of all rings.
|
||||||
|
// rings need to be sorted by area (large to small).
|
||||||
func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geom, error) {
|
func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geom, error) {
|
||||||
g := geos.NewGeos()
|
g := geos.NewGeos()
|
||||||
g.SetHandleSrid(srid)
|
g.SetHandleSrid(srid)
|
||||||
defer g.Finish()
|
defer g.Finish()
|
||||||
|
|
||||||
// sort by area (large to small)
|
|
||||||
for _, r := range rings {
|
|
||||||
r.area = r.geom.Area()
|
|
||||||
}
|
|
||||||
sort.Sort(SortableRingsDesc(rings))
|
|
||||||
|
|
||||||
totalRings := len(rings)
|
totalRings := len(rings)
|
||||||
shells := map[*Ring]bool{rings[0]: true}
|
shells := map[*Ring]bool{rings[0]: true}
|
||||||
for i := 0; i < totalRings; i++ {
|
for i := 0; i < totalRings; i++ {
|
||||||
|
@ -135,13 +167,11 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geo
|
||||||
g.PreparedDestroy(testGeom)
|
g.PreparedDestroy(testGeom)
|
||||||
}
|
}
|
||||||
|
|
||||||
relTags := relationTags(rel.Tags, rings[0].ways[0].Tags)
|
|
||||||
|
|
||||||
var polygons []*geos.Geom
|
var polygons []*geos.Geom
|
||||||
for shell, _ := range shells {
|
for shell, _ := range shells {
|
||||||
var interiors []*geos.Geom
|
var interiors []*geos.Geom
|
||||||
for hole, _ := range shell.holes {
|
for hole, _ := range shell.holes {
|
||||||
hole.MarkInserted(relTags)
|
hole.MarkInserted(rel.Tags)
|
||||||
ring := g.Clone(g.ExteriorRing(hole.geom))
|
ring := g.Clone(g.ExteriorRing(hole.geom))
|
||||||
g.Destroy(hole.geom)
|
g.Destroy(hole.geom)
|
||||||
if ring == nil {
|
if ring == nil {
|
||||||
|
@ -149,7 +179,7 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geo
|
||||||
}
|
}
|
||||||
interiors = append(interiors, ring)
|
interiors = append(interiors, ring)
|
||||||
}
|
}
|
||||||
shell.MarkInserted(relTags)
|
shell.MarkInserted(rel.Tags)
|
||||||
exterior := g.Clone(g.ExteriorRing(shell.geom))
|
exterior := g.Clone(g.ExteriorRing(shell.geom))
|
||||||
g.Destroy(shell.geom)
|
g.Destroy(shell.geom)
|
||||||
if exterior == nil {
|
if exterior == nil {
|
||||||
|
@ -202,7 +232,6 @@ func BuildRelGeometry(rel *element.Relation, rings []*Ring, srid int) (*geos.Geo
|
||||||
return nil, errors.New("unable to create WKB for relation")
|
return nil, errors.New("unable to create WKB for relation")
|
||||||
}
|
}
|
||||||
rel.Geom = &element.Geometry{Geom: result, Wkb: wkb}
|
rel.Geom = &element.Geometry{Geom: result, Wkb: wkb}
|
||||||
rel.Tags = relTags
|
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,27 @@ NextRel:
|
||||||
// for the diffCache
|
// for the diffCache
|
||||||
allMembers := r.Members
|
allMembers := r.Members
|
||||||
|
|
||||||
err = geom.BuildRelation(r, rw.srid)
|
// prepare relation first (build rings and compute actual
|
||||||
|
// relation tags)
|
||||||
|
prepedRel, err := geom.PrepareRelation(r, rw.srid)
|
||||||
|
if err != nil {
|
||||||
|
if err, ok := err.(ErrorLevel); ok {
|
||||||
|
if err.Level() <= 0 {
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Println(err)
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for matches befor building the geometry
|
||||||
|
matches := rw.tagMatcher.Match(&r.Tags)
|
||||||
|
if len(matches) == 0 {
|
||||||
|
continue NextRel
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the multipolygon
|
||||||
|
r, err = prepedRel.Build()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if r.Geom != nil && r.Geom.Geom != nil {
|
if r.Geom != nil && r.Geom.Geom != nil {
|
||||||
geos.Destroy(r.Geom.Geom)
|
geos.Destroy(r.Geom.Geom)
|
||||||
|
@ -87,38 +107,36 @@ NextRel:
|
||||||
continue NextRel
|
continue NextRel
|
||||||
}
|
}
|
||||||
|
|
||||||
if matches := rw.tagMatcher.Match(&r.Tags); len(matches) > 0 {
|
if rw.clipper != nil {
|
||||||
if rw.clipper != nil {
|
parts, err := rw.clipper.Clip(r.Geom.Geom)
|
||||||
parts, err := rw.clipper.Clip(r.Geom.Geom)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
continue NextRel
|
|
||||||
}
|
|
||||||
for _, g := range parts {
|
|
||||||
rel := element.Relation(*r)
|
|
||||||
rel.Geom = &element.Geometry{g, geos.AsEwkbHex(g)}
|
|
||||||
rw.insertMatches(&rel.OSMElem, matches)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rw.insertMatches(&r.OSMElem, matches)
|
|
||||||
}
|
|
||||||
err := rw.osmCache.InsertedWays.PutMembers(r.Members)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
log.Println(err)
|
||||||
|
continue NextRel
|
||||||
}
|
}
|
||||||
if rw.diffCache != nil {
|
for _, g := range parts {
|
||||||
rw.diffCache.Ways.AddFromMembers(r.Id, allMembers)
|
rel := element.Relation(*r)
|
||||||
for _, member := range allMembers {
|
rel.Geom = &element.Geometry{g, geos.AsEwkbHex(g)}
|
||||||
if member.Way != nil {
|
rw.insertMatches(&rel.OSMElem, matches)
|
||||||
rw.diffCache.Coords.AddFromWay(member.Way)
|
}
|
||||||
}
|
} else {
|
||||||
|
rw.insertMatches(&r.OSMElem, matches)
|
||||||
|
}
|
||||||
|
err = rw.osmCache.InsertedWays.PutMembers(r.Members)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if rw.diffCache != nil {
|
||||||
|
rw.diffCache.Ways.AddFromMembers(r.Id, allMembers)
|
||||||
|
for _, member := range allMembers {
|
||||||
|
if member.Way != nil {
|
||||||
|
rw.diffCache.Coords.AddFromWay(member.Way)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rw.expireTiles != nil {
|
}
|
||||||
for _, m := range allMembers {
|
if rw.expireTiles != nil {
|
||||||
if m.Way != nil {
|
for _, m := range allMembers {
|
||||||
rw.expireTiles.ExpireFromNodes(m.Way.Nodes)
|
if m.Way != nil {
|
||||||
}
|
rw.expireTiles.ExpireFromNodes(m.Way.Nodes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue