2013-05-21 11:50:10 +04:00
|
|
|
package writer
|
|
|
|
|
|
|
|
import (
|
|
|
|
"goposm/cache"
|
2013-06-11 16:12:45 +04:00
|
|
|
"goposm/database"
|
2013-05-21 11:50:10 +04:00
|
|
|
"goposm/element"
|
|
|
|
"goposm/geom"
|
|
|
|
"goposm/geom/geos"
|
|
|
|
"goposm/mapping"
|
|
|
|
"goposm/proj"
|
|
|
|
"goposm/stats"
|
|
|
|
"log"
|
|
|
|
"sync"
|
|
|
|
)
|
|
|
|
|
|
|
|
type WayWriter struct {
|
2013-05-28 14:54:19 +04:00
|
|
|
OsmElemWriter
|
2013-06-21 13:05:29 +04:00
|
|
|
ways chan *element.Way
|
2013-05-21 11:50:10 +04:00
|
|
|
lineStringTagMatcher *mapping.TagMatcher
|
|
|
|
polygonTagMatcher *mapping.TagMatcher
|
|
|
|
}
|
|
|
|
|
2013-06-21 13:05:29 +04:00
|
|
|
func NewWayWriter(osmCache *cache.OSMCache, diffCache *cache.DiffCache, ways chan *element.Way,
|
2013-06-11 16:12:45 +04:00
|
|
|
insertBuffer database.RowInserter, lineStringTagMatcher *mapping.TagMatcher,
|
2013-06-19 11:19:21 +04:00
|
|
|
polygonTagMatcher *mapping.TagMatcher, progress *stats.Statistics, srid int) *OsmElemWriter {
|
2013-05-21 11:50:10 +04:00
|
|
|
ww := WayWriter{
|
2013-05-28 14:54:19 +04:00
|
|
|
OsmElemWriter: OsmElemWriter{
|
|
|
|
osmCache: osmCache,
|
2013-05-30 14:00:11 +04:00
|
|
|
diffCache: diffCache,
|
2013-05-28 14:54:19 +04:00
|
|
|
progress: progress,
|
|
|
|
wg: &sync.WaitGroup{},
|
|
|
|
insertBuffer: insertBuffer,
|
2013-06-19 11:19:21 +04:00
|
|
|
srid: srid,
|
2013-05-28 14:54:19 +04:00
|
|
|
},
|
2013-05-21 11:50:10 +04:00
|
|
|
ways: ways,
|
|
|
|
lineStringTagMatcher: lineStringTagMatcher,
|
|
|
|
polygonTagMatcher: polygonTagMatcher,
|
|
|
|
}
|
2013-05-28 14:54:19 +04:00
|
|
|
ww.OsmElemWriter.writer = &ww
|
|
|
|
return &ww.OsmElemWriter
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (ww *WayWriter) loop() {
|
2013-05-24 12:08:38 +04:00
|
|
|
geos := geos.NewGeos()
|
2013-06-19 11:19:21 +04:00
|
|
|
geos.SetHandleSrid(ww.srid)
|
2013-05-21 11:50:10 +04:00
|
|
|
defer geos.Finish()
|
2013-06-21 13:05:29 +04:00
|
|
|
for w := range ww.ways {
|
2013-07-15 13:41:03 +04:00
|
|
|
if len(w.Tags) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
2013-05-21 11:50:10 +04:00
|
|
|
ww.progress.AddWays(1)
|
|
|
|
inserted, err := ww.osmCache.InsertedWays.IsInserted(w.Id)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if inserted {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
err = ww.osmCache.Coords.FillWay(w)
|
|
|
|
if err != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
proj.NodesToMerc(w.Nodes)
|
2013-07-12 16:57:06 +04:00
|
|
|
|
2013-07-15 13:14:03 +04:00
|
|
|
inserted = false
|
2013-05-23 15:09:47 +04:00
|
|
|
if matches := ww.lineStringTagMatcher.Match(&w.Tags); len(matches) > 0 {
|
2013-06-19 11:19:21 +04:00
|
|
|
ww.buildAndInsert(geos, w, matches, geom.LineString)
|
2013-07-15 13:14:03 +04:00
|
|
|
inserted = true
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
if w.IsClosed() {
|
2013-05-23 15:09:47 +04:00
|
|
|
if matches := ww.polygonTagMatcher.Match(&w.Tags); len(matches) > 0 {
|
2013-06-19 11:19:21 +04:00
|
|
|
ww.buildAndInsert(geos, w, matches, geom.Polygon)
|
2013-07-15 13:14:03 +04:00
|
|
|
inserted = true
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-15 13:14:03 +04:00
|
|
|
if inserted && ww.expireTiles != nil {
|
|
|
|
ww.expireTiles.ExpireFromNodes(w.Nodes)
|
|
|
|
}
|
2013-05-30 14:00:11 +04:00
|
|
|
if ww.diffCache != nil {
|
|
|
|
ww.diffCache.Coords.AddFromWay(w)
|
|
|
|
}
|
2013-05-21 11:50:10 +04:00
|
|
|
}
|
|
|
|
ww.wg.Done()
|
|
|
|
}
|
2013-05-28 14:54:19 +04:00
|
|
|
|
2013-06-19 11:19:21 +04:00
|
|
|
type geomBuilder func(*geos.Geos, []element.Node) (*geos.Geom, error)
|
2013-05-28 14:54:19 +04:00
|
|
|
|
|
|
|
func (ww *WayWriter) buildAndInsert(geos *geos.Geos, w *element.Way, matches []mapping.Match, builder geomBuilder) {
|
|
|
|
var err error
|
|
|
|
// make copy to avoid interference with polygon/linestring matches
|
|
|
|
way := element.Way(*w)
|
2013-06-19 11:19:21 +04:00
|
|
|
geosgeom, err := builder(geos, way.Nodes)
|
2013-05-28 14:54:19 +04:00
|
|
|
if err != nil {
|
|
|
|
if err, ok := err.(ErrorLevel); ok {
|
|
|
|
if err.Level() <= 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Println(err)
|
|
|
|
return
|
|
|
|
}
|
2013-06-19 11:19:21 +04:00
|
|
|
|
|
|
|
way.Geom, err = geom.AsGeomElement(geos, geosgeom)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-05-28 14:54:19 +04:00
|
|
|
if ww.clipper != nil {
|
|
|
|
parts, err := ww.clipper.Clip(way.Geom.Geom)
|
|
|
|
if err != nil {
|
|
|
|
log.Println(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, g := range parts {
|
|
|
|
way := element.Way(*w)
|
2013-06-19 11:19:21 +04:00
|
|
|
way.Geom = &element.Geometry{g, geos.AsEwkbHex(g)}
|
2013-05-28 16:07:06 +04:00
|
|
|
ww.insertMatches(&way.OSMElem, matches)
|
2013-05-28 14:54:19 +04:00
|
|
|
}
|
|
|
|
} else {
|
2013-05-28 16:07:06 +04:00
|
|
|
ww.insertMatches(&way.OSMElem, matches)
|
2013-05-28 14:54:19 +04:00
|
|
|
}
|
|
|
|
}
|