From 3baf2b482ffc6cced04ab5178a742f9f28a76f5e Mon Sep 17 00:00:00 2001 From: Oliver Tonnhofer Date: Wed, 6 Jan 2016 08:46:44 +0100 Subject: [PATCH] refactor relation writing --- writer/relations.go | 304 ++++++++++++++++++++++++-------------------- 1 file changed, 165 insertions(+), 139 deletions(-) diff --git a/writer/relations.go b/writer/relations.go index 8351456..9c8b92d 100644 --- a/writer/relations.go +++ b/writer/relations.go @@ -80,7 +80,7 @@ NextRel: if err != cache.NotFound { log.Warn(err) } - continue NextRel + continue } for i, m := range r.Members { if m.Way == nil { @@ -97,132 +97,84 @@ NextRel: r.Members[i].Elem = &m.Way.OSMElem } - relMemberMatches := rw.relationMemberMatcher.MatchRelation(r) - if len(relMemberMatches) > 0 { - for i, m := range r.Members { - if m.Type == element.RELATION { - mrel, err := rw.osmCache.Relations.GetRelation(m.Id) - if err != nil { - if err == cache.NotFound { - log.Warn(err) - continue NextRel - } - } - r.Members[i].Elem = &mrel.OSMElem - } else if m.Type == element.NODE { - nd, err := rw.osmCache.Nodes.GetNode(m.Id) - if err != nil { - if err == cache.NotFound { - nd, err = rw.osmCache.Coords.GetCoord(m.Id) - if err != nil { - if err != cache.NotFound { - log.Warn(err) - } - continue NextRel - } - } else { - log.Warn(err) - continue NextRel - } - } - rw.NodeToSrid(nd) - r.Members[i].Node = nd - r.Members[i].Elem = &nd.OSMElem - } - } - - for _, m := range r.Members { - var g *geosp.Geom - var err error - if m.Node != nil { - g, err = geomp.Point(geos, *m.Node) - } else if m.Way != nil { - g, err = geomp.LineString(geos, m.Way.Nodes) - } - - if err != nil { - log.Warn(err) - continue - } - - var gelem geomp.Geometry - if g == nil { - g = geos.FromWkt("POLYGON EMPTY") - gelem = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)} - } else { - gelem, err = geomp.AsGeomElement(geos, g) - if err != nil { - log.Warn(err) - continue - } - } - - rw.inserter.InsertRelationMember(*r, m, gelem, relMemberMatches) - } - } - - relMatches := rw.relationMatcher.MatchRelation(r) - if len(relMatches) > 0 { - rw.inserter.InsertPolygon(r.OSMElem, geomp.Geometry{}, relMatches) - } - - // BuildRelation updates r.Members but we need all of them + // handleRelation updates r.Members but we need all of them // for the diffCache allMembers := r.Members - // prepare relation first (build rings and compute actual - // relation tags) - prepedRel, err := geomp.PrepareRelation(r, rw.srid, rw.maxGap) - if err != nil { - if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { - log.Warn(err) - } - continue NextRel + inserted := false + + if handleRelationMembers(rw, r, geos) { + inserted = true + } + if handleRelation(rw, r, geos) { + inserted = true + } + if handleMultiPolygon(rw, r, geos) { + inserted = true } - // check for matches befor building the geometry - matches := rw.polygonMatcher.MatchRelation(r) - if len(matches) == 0 { - continue NextRel - } - - // build the multipolygon - geom, err := prepedRel.Build() - if err != nil { - if geom.Geom != nil { - geos.Destroy(geom.Geom) - } - if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { - log.Warn(err) - } - continue NextRel - } - - if rw.limiter != nil { - start := time.Now() - parts, err := rw.limiter.Clip(geom.Geom) - if err != nil { - log.Warn(err) - continue NextRel - } - if duration := time.Now().Sub(start); duration > time.Minute { - log.Warnf("clipping relation %d to -limitto took %s", r.Id, duration) - } - for _, g := range parts { - rel := element.Relation(*r) - rel.Id = rw.relId(r.Id) - geom = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)} - err := rw.inserter.InsertPolygon(rel.OSMElem, geom, matches) - if err != nil { - if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { - log.Warn(err) - } - continue + if inserted && rw.diffCache != nil { + rw.diffCache.Ways.AddFromMembers(r.Id, allMembers) + for _, member := range allMembers { + if member.Way != nil { + rw.diffCache.Coords.AddFromWay(member.Way) } } - } else { + } + if inserted && rw.expireor != nil { + for _, m := range allMembers { + if m.Way != nil { + expire.ExpireNodes(rw.expireor, m.Way.Nodes) + } + } + } + } + rw.wg.Done() +} + +func handleMultiPolygon(rw *RelationWriter, r *element.Relation, geos *geosp.Geos) bool { + // prepare relation first (build rings and compute actual + // relation tags) + prepedRel, err := geomp.PrepareRelation(r, rw.srid, rw.maxGap) + if err != nil { + if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { + log.Warn(err) + } + return false + } + + // check for matches befor building the geometry + matches := rw.polygonMatcher.MatchRelation(r) + if matches == nil { + return false + } + + // build the multipolygon + geom, err := prepedRel.Build() + if geom.Geom != nil { + defer geos.Destroy(geom.Geom) + } + if err != nil { + if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { + log.Warn(err) + } + return false + } + + if rw.limiter != nil { + start := time.Now() + parts, err := rw.limiter.Clip(geom.Geom) + if err != nil { + log.Warn(err) + return false + } + if duration := time.Now().Sub(start); duration > time.Minute { + log.Warnf("clipping relation %d to -limitto took %s", r.Id, duration) + } + for _, g := range parts { rel := element.Relation(*r) rel.Id = rw.relId(r.Id) + geom = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)} err := rw.inserter.InsertPolygon(rel.OSMElem, geom, matches) if err != nil { if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { @@ -231,29 +183,103 @@ NextRel: continue } } - - for _, m := range mapping.SelectRelationPolygons(rw.polygonMatcher, r) { - err = rw.osmCache.InsertedWays.PutWay(m.Way) - if err != nil { + } else { + rel := element.Relation(*r) + rel.Id = rw.relId(r.Id) + err := rw.inserter.InsertPolygon(rel.OSMElem, geom, matches) + if err != nil { + if errl, ok := err.(ErrorLevel); !ok || errl.Level() > 0 { log.Warn(err) } + return false } - 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.expireor != nil { - for _, m := range allMembers { - if m.Way != nil { - expire.ExpireNodes(rw.expireor, m.Way.Nodes) - } - } - } - geos.Destroy(geom.Geom) } - rw.wg.Done() + + for _, m := range mapping.SelectRelationPolygons(rw.polygonMatcher, r) { + err = rw.osmCache.InsertedWays.PutWay(m.Way) + if err != nil { + log.Warn(err) + } + } + return true +} + +func handleRelation(rw *RelationWriter, r *element.Relation, geos *geosp.Geos) bool { + relMatches := rw.relationMatcher.MatchRelation(r) + if relMatches == nil { + return false + } + rel := element.Relation(*r) + rel.Id = rw.relId(r.Id) + rw.inserter.InsertPolygon(rel.OSMElem, geomp.Geometry{}, relMatches) + return true +} + +func handleRelationMembers(rw *RelationWriter, r *element.Relation, geos *geosp.Geos) bool { + relMemberMatches := rw.relationMemberMatcher.MatchRelation(r) + if relMemberMatches == nil { + return false + } + for i, m := range r.Members { + if m.Type == element.RELATION { + mrel, err := rw.osmCache.Relations.GetRelation(m.Id) + if err != nil { + if err == cache.NotFound { + log.Warn(err) + return false + } + } + r.Members[i].Elem = &mrel.OSMElem + } else if m.Type == element.NODE { + nd, err := rw.osmCache.Nodes.GetNode(m.Id) + if err != nil { + if err == cache.NotFound { + nd, err = rw.osmCache.Coords.GetCoord(m.Id) + if err != nil { + if err != cache.NotFound { + log.Warn(err) + } + return false + } + } else { + log.Warn(err) + return false + } + } + rw.NodeToSrid(nd) + r.Members[i].Node = nd + r.Members[i].Elem = &nd.OSMElem + } + } + + for _, m := range r.Members { + var g *geosp.Geom + var err error + if m.Node != nil { + g, err = geomp.Point(geos, *m.Node) + } else if m.Way != nil { + g, err = geomp.LineString(geos, m.Way.Nodes) + } + + if err != nil { + log.Warn(err) + return false + } + + var gelem geomp.Geometry + if g == nil { + g = geos.FromWkt("POLYGON EMPTY") + gelem = geomp.Geometry{Geom: g, Wkb: geos.AsEwkbHex(g)} + } else { + gelem, err = geomp.AsGeomElement(geos, g) + if err != nil { + log.Warn(err) + return false + } + } + rel := element.Relation(*r) + rel.Id = rw.relId(r.Id) + rw.inserter.InsertRelationMember(rel, m, gelem, relMemberMatches) + } + return true }