2013-05-21 11:50:10 +04:00
|
|
|
package writer
|
|
|
|
|
|
|
|
import (
|
2013-08-29 17:44:15 +04:00
|
|
|
"imposm3/cache"
|
|
|
|
"imposm3/database"
|
|
|
|
"imposm3/element"
|
|
|
|
"imposm3/geom"
|
|
|
|
"imposm3/geom/geos"
|
|
|
|
"imposm3/proj"
|
|
|
|
"imposm3/stats"
|
2013-05-21 11:50:10 +04:00
|
|
|
"sync"
|
2013-11-07 18:49:40 +04:00
|
|
|
"time"
|
2013-05-21 11:50:10 +04:00
|
|
|
)
|
|
|
|
|
|
|
|
type RelationWriter struct {
|
2013-05-28 14:54:19 +04:00
|
|
|
OsmElemWriter
|
2013-10-28 14:37:58 +04:00
|
|
|
rel chan *element.Relation
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
|
2013-05-30 18:04:14 +04:00
|
|
|
func NewRelationWriter(osmCache *cache.OSMCache, diffCache *cache.DiffCache, rel chan *element.Relation,
|
2013-10-28 14:37:58 +04:00
|
|
|
inserter database.Inserter, progress *stats.Statistics,
|
2013-06-19 11:19:21 +04:00
|
|
|
srid int) *OsmElemWriter {
|
2013-05-21 11:50:10 +04:00
|
|
|
rw := RelationWriter{
|
2013-05-28 14:54:19 +04:00
|
|
|
OsmElemWriter: OsmElemWriter{
|
2013-10-28 11:26:51 +04:00
|
|
|
osmCache: osmCache,
|
|
|
|
diffCache: diffCache,
|
|
|
|
progress: progress,
|
|
|
|
wg: &sync.WaitGroup{},
|
|
|
|
inserter: inserter,
|
|
|
|
srid: srid,
|
2013-05-28 14:54:19 +04:00
|
|
|
},
|
2013-10-28 14:37:58 +04:00
|
|
|
rel: rel,
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
2013-05-28 14:54:19 +04:00
|
|
|
rw.OsmElemWriter.writer = &rw
|
|
|
|
return &rw.OsmElemWriter
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (rw *RelationWriter) loop() {
|
2013-05-28 10:59:59 +04:00
|
|
|
geos := geos.NewGeos()
|
2013-06-19 11:19:21 +04:00
|
|
|
geos.SetHandleSrid(rw.srid)
|
2013-05-28 10:59:59 +04:00
|
|
|
defer geos.Finish()
|
|
|
|
|
2013-06-07 10:25:45 +04:00
|
|
|
NextRel:
|
2013-05-21 11:50:10 +04:00
|
|
|
for r := range rw.rel {
|
|
|
|
rw.progress.AddRelations(1)
|
|
|
|
err := rw.osmCache.Ways.FillMembers(r.Members)
|
2013-06-07 10:25:45 +04:00
|
|
|
if err != nil {
|
|
|
|
if err != cache.NotFound {
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-06-07 10:25:45 +04:00
|
|
|
}
|
|
|
|
continue NextRel
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
for _, m := range r.Members {
|
|
|
|
if m.Way == nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
err := rw.osmCache.Coords.FillWay(m.Way)
|
2013-06-07 10:25:45 +04:00
|
|
|
if err != nil {
|
|
|
|
if err != cache.NotFound {
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-06-07 10:25:45 +04:00
|
|
|
}
|
|
|
|
continue NextRel
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
proj.NodesToMerc(m.Way.Nodes)
|
|
|
|
}
|
|
|
|
|
2013-05-30 18:04:14 +04:00
|
|
|
// BuildRelation updates r.Members but we need all of them
|
|
|
|
// for the diffCache
|
|
|
|
allMembers := r.Members
|
|
|
|
|
2013-07-15 13:39:43 +04:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
}
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-07-15 13:39:43 +04:00
|
|
|
continue NextRel
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for matches befor building the geometry
|
2013-10-28 14:28:56 +04:00
|
|
|
ok, matches := rw.inserter.ProbePolygon(r.OSMElem)
|
|
|
|
if !ok {
|
2013-07-15 13:39:43 +04:00
|
|
|
continue NextRel
|
|
|
|
}
|
|
|
|
|
|
|
|
// build the multipolygon
|
|
|
|
r, err = prepedRel.Build()
|
2013-05-21 11:50:10 +04:00
|
|
|
if err != nil {
|
2013-06-07 10:25:45 +04:00
|
|
|
if r.Geom != nil && r.Geom.Geom != nil {
|
|
|
|
geos.Destroy(r.Geom.Geom)
|
|
|
|
}
|
2013-05-21 11:50:10 +04:00
|
|
|
if err, ok := err.(ErrorLevel); ok {
|
|
|
|
if err.Level() <= 0 {
|
2013-06-07 10:25:45 +04:00
|
|
|
continue NextRel
|
|
|
|
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
}
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-06-07 10:25:45 +04:00
|
|
|
continue NextRel
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
2013-06-07 10:25:45 +04:00
|
|
|
|
2013-07-30 10:17:47 +04:00
|
|
|
if rw.limiter != nil {
|
2013-11-07 18:49:40 +04:00
|
|
|
start := time.Now()
|
2013-07-30 10:17:47 +04:00
|
|
|
parts, err := rw.limiter.Clip(r.Geom.Geom)
|
2013-05-21 11:50:10 +04:00
|
|
|
if err != nil {
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-07-15 13:39:43 +04:00
|
|
|
continue NextRel
|
|
|
|
}
|
2013-11-07 18:49:40 +04:00
|
|
|
if duration := time.Now().Sub(start); duration > time.Minute {
|
|
|
|
log.Warnf("clipping relation %d to -limitto took %s", r.Id, duration)
|
|
|
|
}
|
2013-07-15 13:39:43 +04:00
|
|
|
for _, g := range parts {
|
|
|
|
rel := element.Relation(*r)
|
2013-11-07 19:09:08 +04:00
|
|
|
rel.Id = -r.Id
|
2013-07-15 13:39:43 +04:00
|
|
|
rel.Geom = &element.Geometry{g, geos.AsEwkbHex(g)}
|
2013-10-28 14:28:56 +04:00
|
|
|
rw.inserter.InsertPolygon(rel.OSMElem, matches)
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
2013-07-15 13:39:43 +04:00
|
|
|
} else {
|
2013-11-07 19:09:08 +04:00
|
|
|
rel := element.Relation(*r)
|
|
|
|
rel.Id = -r.Id
|
|
|
|
rw.inserter.InsertPolygon(rel.OSMElem, matches)
|
2013-07-15 13:39:43 +04:00
|
|
|
}
|
|
|
|
err = rw.osmCache.InsertedWays.PutMembers(r.Members)
|
|
|
|
if err != nil {
|
2013-11-07 18:48:55 +04:00
|
|
|
log.Warn(err)
|
2013-07-15 13:39:43 +04:00
|
|
|
}
|
|
|
|
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)
|
2013-05-30 18:04:14 +04:00
|
|
|
}
|
|
|
|
}
|
2013-07-15 13:39:43 +04:00
|
|
|
}
|
|
|
|
if rw.expireTiles != nil {
|
|
|
|
for _, m := range allMembers {
|
|
|
|
if m.Way != nil {
|
|
|
|
rw.expireTiles.ExpireFromNodes(m.Way.Nodes)
|
2013-07-15 13:14:03 +04:00
|
|
|
}
|
|
|
|
}
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
2013-06-07 10:25:45 +04:00
|
|
|
geos.Destroy(r.Geom.Geom)
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
rw.wg.Done()
|
|
|
|
}
|