vector< pair<WayLocation, WayLocation> > MaximalSubline::_discretizePointPairs( const ConstOsmMapPtr &map, const ConstWayPtr& w1, const ConstWayPtr& w2, vector<WaySublineMatch>& rawSublineMatches) { /// @todo this requires a more robust mechanism for generating point pairs. -JRS #2701 // figure out where to start on the lines double diff = rawSublineMatches[0].getSubline1().getStart().calculateDistanceOnWay() - rawSublineMatches[0].getSubline2().getStart().calculateDistanceOnWay(); Meters w1Offset = max(0.0, diff); Meters w2Offset = max(0.0, -diff); Meters w1Length = ElementConverter(map).convertToLineString(w1)->getLength(); Meters w2Length = ElementConverter(map).convertToLineString(w2)->getLength(); int count = min((w1Length - w1Offset) / _spacing, (w2Length - w2Offset) / _spacing) + 1; vector< pair<WayLocation, WayLocation> > result(count); WayLocation lastMatch(map, w2, 0, 0); for (int i = 0; i < count; i++) { double loc = (double)i * _spacing; WayLocation wl1(map, w1, loc + w1Offset); WayLocation wl2(LocationOfPoint(map, w2).locateAfter(wl1.getCoordinate(), lastMatch)); //WayLocation wl2(LocationOfPoint::locate(w2, wl1.getCoordinate())); result[i] = pair<WayLocation, WayLocation>(wl1, wl2); lastMatch = wl2; } return result; }
vector<long> OsmMapIndex::findWayNeighborsBruteForce(shared_ptr<const Way> way, Meters buffer) const { vector<long> result; // grab the geometry for the way that we're comparing all others against. shared_ptr<LineString> ls1 = ElementConverter(_map.shared_from_this()).convertToLineString(way); // go through all other ways for (WayMap::const_iterator it = _map.getWays().begin(); it != _map.getWays().end(); ++it) { long nId = it->first; shared_ptr<const Way> n = it->second; if (n != 0 && nId != way->getId()) { shared_ptr<LineString> ls2 = ElementConverter(_map.shared_from_this()).convertToLineString(n); Meters d = ls1->distance(ls2.get()); if (d < buffer) { result.push_back(nId); } } } return result; }
double ProbabilityOfMatch::lengthScore(const ConstOsmMapPtr &map, const shared_ptr<const Way>& w1, const shared_ptr<const Way> &w2) { Meters l1 = ElementConverter(map).convertToLineString(w1)->getLength(); Meters l2 = ElementConverter(map).convertToLineString(w2)->getLength(); // longer matches get a higher score. Meters mean = (l1 + l2) / 2.0; return 0.2 + ((mean / (mean + 20)) * 0.8); }
std::vector<long> OsmMapIndex::findWayNeighbors(Coordinate& from, Meters buffer) const { vector<long> result; // grab the geometry for the way that we're comparing all others against. Point* p = GeometryFactory::getDefaultInstance()->createPoint(from); // go through all other ways for (WayMap::const_iterator it = _map.getWays().begin(); it != _map.getWays().end(); ++it) { long nId = it->first; shared_ptr<const Way> n = it->second; if (n != 0 && n->getNodeCount() > 1) { shared_ptr<LineString> ls2 = ElementConverter(_map.shared_from_this()).convertToLineString(n); Meters d = p->distance(ls2.get()); if (d < buffer) { result.push_back(nId); } } } delete p; return result; }
long OsmMapIndex::findNearestWay(Coordinate c) const { long result = 0; double bestDistance = std::numeric_limits<double>::max(); // grab the geometry for the way that we're comparing all others against. Point* p = GeometryFactory::getDefaultInstance()->createPoint(c); // go through all other ways for (WayMap::const_iterator it = _map.getWays().begin(); it != _map.getWays().end(); ++it) { long nId = it->first; shared_ptr<const Way> n = it->second; if (n != 0 && n->getNodeCount() > 1) { shared_ptr<LineString> ls2 = ElementConverter(_map.shared_from_this()).convertToLineString(n); Meters d = p->distance(ls2.get()); if (d < bestDistance) { result = nId; bestDistance = d; } } } delete p; return result; }
void MaximalSubline::_snapToTerminal(WayLocation& wl, bool startOfLines, double thresh) { Meters d1 = wl.calculateDistanceOnWay(); // if we're not at the start of the line if (!startOfLines) { // calculate the distance from the end to this way location. d1 = ElementConverter(wl.getMap()).convertToLineString(wl.getWay())->getLength() - d1; } if (thresh == -1) { thresh = _minSplitSize; } // if we should snap the end points if (d1 <= thresh) { // if we're at the start of the line if (startOfLines) { // snap to the beginning wl = WayLocation(wl.getMap(), wl.getWay(), 0, 0.0); } // if we're at the end of the line else { // snap to the end wl = WayLocation(wl.getMap(), wl.getWay(), wl.getWay()->getNodeCount(), 0.0); } } }
void TranslatedTagCountVisitor::visit(ElementType type, long id) { shared_ptr<const Element> e = _map->getElement(type, id); if (e->getTags().getInformationCount() > 0) { shared_ptr<Geometry> g = ElementConverter(_map->shared_from_this()).convertToGeometry(e); Tags t = e->getTags(); t["error:circular"] = QString::number(e->getCircularError()); t["hoot:status"] = e->getStatusString(); // remove all the empty tags. for (Tags::const_iterator it = e->getTags().begin(); it != e->getTags().end(); ++it) { if (t[it.key()] == "") { t.remove(it.key()); } } QString layerName; vector<ScriptToOgrTranslator::TranslatedFeature> f = _translator->translateToOgr(t, e->getElementType(), g->getGeometryTypeId()); // only write the feature if it wasn't filtered by the translation script. for (size_t i = 0; i < f.size(); i++) { _countTags(f[i].feature); } } }
void DirectedGraph::deriveEdges(shared_ptr<const OsmMap> map) { const WayMap& ways = map->getWays(); for (WayMap::const_iterator it = ways.begin(); it != ways.end(); ++it) { const shared_ptr<Way>& way = it->second; double cost = determineCost(way); double length = ElementConverter(map).convertToLineString(way)->getLength(); long nStart = way->getNodeId(0); long nEnd = way->getNodeId(way->getNodeCount() - 1); if (cost >= 0) { if (isOneWay(way)) { addEdge(nStart, nEnd, cost * length); } else { addEdge(nStart, nEnd, cost * length); addEdge(nEnd, nStart, cost * length); } } } }
void GraphComparator::_paintWay(cv::Mat& mat, ConstOsmMapPtr map, shared_ptr<Way> way, double friction, double startCost, double endCost) { LocationOfPoint lop(map, way); double length = ElementConverter(map).convertToLineString(way)->getLength(); // v is the distance along the way in meters for (double v = 0.0; v <= length; v += _pixelSize / 2.0) { double cost = std::min(startCost + v * friction, endCost + (length - v) * friction); Coordinate c = lop.locate(v); int x = (c.x - _projectedBounds.MinX) / _pixelSize; int y = _height - (c.y - _projectedBounds.MinY) / _pixelSize; float* row = mat.ptr<float>(y); if (row[x] >= 0.0) { row[x] = std::min((float)cost, row[x]); } else { row[x] = cost; } } }
WayLocation LocationOfPoint::locate(const Coordinate& inputPt) const { double minDistance = std::numeric_limits<double>().max(); int minIndex = 0; double minFrac = -1.0; LineSegment seg; if (_length == -1) { _length = ElementConverter(_map).convertToLineString(_way)->getLength(); } if (_length <= 0.0) { return WayLocation(_map, _way, 0, 0); } for (size_t i = 0; i < _way->getNodeCount() - 1; i++) { seg.p0 = _map->getNode(_way->getNodeId(i))->toCoordinate(); seg.p1 = _map->getNode(_way->getNodeId(i + 1))->toCoordinate(); double segDistance = seg.distance(inputPt); double segFrac = segmentFraction(seg, inputPt); if (segDistance < minDistance) { minIndex = i; minFrac = segFrac; minDistance = segDistance; } } return WayLocation(_map, _way, minIndex, minFrac); }
double KnnWayIterator::_calculateDistance(const BoxInternalData&, int id) const { // if the id in the index isn't valid, then report the maximum possible distance. double result = numeric_limits<double>::max(); long otherWayId = _treeIdToWid[id]; if (otherWayId == _wayId) { result = 0.0; } // if this is a valid way id. else if (_map.containsWay(otherWayId)) { ConstWayPtr w = _map.getWay(otherWayId); // grab the geometry for the way that we're comparing against. boost::shared_ptr<LineString> ls = ElementConverter(_map.shared_from_this()).convertToLineString(w); Meters d = ls->distance(_lsFast); if (_addError) { Meters acc = w->getCircularError(); d = std::max(0.0, ls->distance(_lsFast) - (acc + _baseAccuracy)); } _distanceCount++; result = d * d; } return result; }
double WayMergeManipulation::_calculateExpertProbability(ConstOsmMapPtr map) const { OsmMapPtr theMap(new OsmMap()); CopyMapSubsetOp(map, ElementId(ElementType::Way, _left), ElementId(ElementType::Way, _right)).apply(theMap); WayPtr left = theMap->getWay(_left); WayPtr right = theMap->getWay(_right); // use the maximal nearest subline code to find the best subline WayPtr mnsLeft = MaximalNearestSubline::getMaximalNearestSubline(theMap, left, right, _minSplitSize, left->getCircularError() + right->getCircularError()); if (mnsLeft == 0) { return 0.0; } WayPtr mnsRight = MaximalNearestSubline::getMaximalNearestSubline(theMap, right, mnsLeft, _minSplitSize, left->getCircularError() + right->getCircularError()); if (mnsRight == 0) { return 0.0; } // what portion of the original lines is the MNS double pl = ElementConverter(theMap).convertToLineString(mnsLeft)->getLength() / ElementConverter(theMap).convertToLineString(left)->getLength(); double pr = ElementConverter(theMap).convertToLineString(mnsRight)->getLength() / ElementConverter(theMap).convertToLineString(right)->getLength(); // give it a score double ps = std::min(pl, pr) / 2.0 + 0.5; double p; // if either of the lines are zero in length. if (pl == 0 || pr == 0) { p = 0.0; } else { p = ps * ProbabilityOfMatch::getInstance().expertProbability(theMap, mnsLeft, mnsRight); } return p; }
bool WayBufferFilter::isFiltered(const Way& w) const { try { bool result = true; shared_ptr<LineString> ls2 = ElementConverter(_map). convertToLineString(_map->getWay(w.getId())); if (fabs((w.getCircularError() + _buffer) - _bufferAccuracy) > 0.1) { _bufferAccuracy = w.getCircularError() + _buffer; _baseBuffered.reset(_baseLs->buffer(_bufferAccuracy, 3, geos::operation::buffer::BufferOp::CAP_ROUND)); _boundsPlus = *_baseBuffered->getEnvelopeInternal(); } if (ls2->getEnvelopeInternal()->intersects(_boundsPlus)) { shared_ptr<Geometry> g(_baseBuffered->intersection(ls2.get())); double ls2Length = ls2->getLength(); double ls2IntersectLength = g->getLength(); if (ls2IntersectLength / ls2Length >= _matchPercent) { shared_ptr<Geometry> ls2Buffer(ls2->buffer(_bufferAccuracy, 3, geos::operation::buffer::BufferOp::CAP_ROUND)); g.reset(ls2Buffer->intersection(_baseLs.get())); double ls1IntersectLength = g->getLength(); if (ls1IntersectLength / _baseLength >= _matchPercent) { result = false; } } } return result; } catch (geos::util::TopologyException& e) { LOG_WARN(ElementConverter(_map).convertToLineString(_map->getWay(w.getId()))); throw e; } }
void OsmMapIndex::_buildWayTree() const { QTime t; t.start(); LOG_DEBUG("Building way R-Tree index"); // 10 children - 368 shared_ptr<MemoryPageStore> mps(new MemoryPageStore(728)); _wayTree.reset(new HilbertRTree(mps, 2)); vector<Box> boxes; vector<int> ids; const WayMap& ways = _map.getWays(); _treeIdToWid.resize(0); _treeIdToWid.reserve(ways.size()); boxes.reserve(ways.size()); ids.reserve(ways.size()); Box b(2); int count = 0; for (WayMap::const_iterator it = ways.begin(); it != ways.end(); ++it) { shared_ptr<const Way> w = it->second; shared_ptr<LineString> ls = ElementConverter(_map.shared_from_this()).convertToLineString(w); const Envelope* e = ls->getEnvelopeInternal(); Meters a = w->getCircularError(); b.setBounds(0, e->getMinX() - a, e->getMaxX() + a); b.setBounds(1, e->getMinY() - a, e->getMaxY() + a); boxes.push_back(b); ids.push_back(_createTreeWid(w->getId())); if (Log::getInstance().isDebugEnabled() && count % 1000 == 0) { cout << " building way R-Tree count: " << count << " / " << ways.size() << " \r"; cout.flush(); } count += 1; } if (Log::getInstance().isDebugEnabled()) { cout << endl; } _pendingWayInsert.clear(); _pendingWayRemoval.clear(); LOG_DEBUG(" Doing bulk insert."); _wayTree->bulkInsert(boxes, ids); LOG_DEBUG(" Done. Time elapsed: " << t.elapsed() << "ms"); }
Handle<Value> ElementConverterJs::calculateLength(const Arguments& args) { HandleScope scope; Context::Scope context_scope(Context::GetCurrent()); ConstOsmMapPtr m = toCpp<ConstOsmMapPtr>(args[0]); ConstElementPtr e = toCpp<ConstElementPtr>(args[1]); return scope.Close(toV8(ElementConverter(m).calculateLength(e))); }
WaySublineMatchString MaximalNearestSublineMatcher::findMatch(const ConstOsmMapPtr &map, const ConstWayPtr& way1, const ConstWayPtr &way2, double &score, Meters maxRelevantDistance) const { score = 0; Meters mrd = maxRelevantDistance == -1 ? way1->getCircularError() + way2->getCircularError() : maxRelevantDistance; vector<long> wayIds; wayIds.push_back(way1->getId()); wayIds.push_back(way2->getId()); OsmMapPtr mapCopy(map->copyWays(wayIds)); WayPtr way1NonConst = mapCopy->getWay(way1->getId()); WayPtr way2NonConst = mapCopy->getWay(way2->getId()); MaximalNearestSubline mns1( mapCopy, way1NonConst, way2NonConst, _minSplitSize, mrd, _maxRelevantAngle, _headingDelta); // use the maximal nearest subline code to find the best subline std::vector<WayLocation> interval1 = mns1.getInterval(); if (!interval1[0].isValid() || !interval1[1].isValid() || interval1[0] == interval1[1]) { // if the interval isn't valid then return an invalid result. return WaySublineMatchString(); } _snapToEnds(map, interval1); WayPtr subline1 = WaySubline(interval1[0], interval1[1]).toWay(mapCopy); MaximalNearestSubline mns2(mapCopy, way2NonConst, subline1, _minSplitSize, -1, -1, _headingDelta); std::vector<WayLocation> interval2 = mns2.getInterval(); if (!interval2[0].isValid() || !interval2[1].isValid() || interval2[0] == interval2[1]) { return WaySublineMatchString(); } _snapToEnds(map, interval2); WaySublineMatch match = WaySublineMatch(WaySubline(interval1[0], interval1[1]), WaySubline(interval2[0], interval2[1])); if (subline1->getNodeCount() > 1) { shared_ptr<LineString> ls = ElementConverter(mapCopy).convertToLineString(subline1); if (ls->isValid()) { score = ls->getLength(); } } vector<WaySublineMatch> v; // switch the subline match to reference a different map. v.push_back(WaySublineMatch(match, map)); return WaySublineMatchString(v); }
virtual void visit(const shared_ptr<const Element>& e) { if (e->getElementType() == ElementType::Way) { shared_ptr<const Way> w(dynamic_pointer_cast<const Way>(e)); Geometry* ls = ElementConverter(_map->shared_from_this()).convertToLineString(w)->clone(); _lines.push_back(ls); } }
WayBufferFilter::WayBufferFilter(ConstOsmMapPtr map, ConstWayPtr baseWay, Meters buffer, double matchPercent) : _map(map) { _matchPercent = matchPercent; _buffer = buffer + baseWay->getCircularError(); _baseLs = ElementConverter(map).convertToLineString(baseWay); _baseLength = _baseLs->getLength(); _bufferAccuracy = -1; }
void OgrWriter::_writePartial(ElementProviderPtr& provider, const ConstElementPtr& e) { if (_translator.get() == 0) { throw HootException("You must call open before attempting to write."); } if (e->getTags().getInformationCount() > 0) { // There is probably a cleaner way of doing this. // convertToGeometry calls getGeometryType which will throw an exception if it gets a relation // that it doesn't know about. E.g. "route", "superroute", " turnlanes:turns" etc shared_ptr<Geometry> g; try { g = ElementConverter(provider).convertToGeometry(e); } catch (IllegalArgumentException& err) { LOG_WARN("Error converting geometry: " << err.getWhat() << " (" << e->toString() << ")"); g.reset((GeometryFactory::getDefaultInstance()->createEmptyGeometry())); } /* LOG_DEBUG("After conversion to geometry, element is now a " << g->getGeometryType() ); */ Tags t = e->getTags(); t["error:circular"] = QString::number(e->getCircularError()); t["hoot:status"] = e->getStatusString(); for (Tags::const_iterator it = e->getTags().begin(); it != e->getTags().end(); ++it) { if (t[it.key()] == "") { t.remove(it.key()); } } vector<ScriptToOgrTranslator::TranslatedFeature> tf = _translator->translateToOgr(t, e->getElementType(), g->getGeometryTypeId()); // only write the feature if it wasn't filtered by the translation script. for (size_t i = 0; i < tf.size(); i++) { OGRLayer* layer = _getLayer(tf[i].tableName); if (layer != 0) { _addFeature(layer, tf[i].feature, g); } } } }
WayLocation::WayLocation(ConstOsmMapPtr map, ConstWayPtr way, double distance) : _map(map) { double d = 0.0; _segmentIndex = -1; _segmentFraction = -1; _way = way; double length = ElementConverter(map).convertToLineString(way)->getLength(); if (distance <= 0) { _segmentIndex = 0.0; _segmentFraction = 0; } else if (distance >= length) { _segmentIndex = _way->getNodeCount() - 1; _segmentFraction = 0.0; } else { Coordinate last = _map->getNode(way->getNodeId(0))->toCoordinate(); _segmentIndex = way->getNodeCount() - 1; _segmentFraction = 0; for (size_t i = 1; i < way->getNodeCount(); i++) { ConstNodePtr n = _map->getNode(_way->getNodeId(i)); Coordinate next = n->toCoordinate(); double delta = next.distance(last); last = next; if (d <= distance && d + delta > distance) { _segmentIndex = i - 1; _segmentFraction = (distance - d) / delta; // this can sometimes happen due to rounding errors. if (_segmentFraction >= 1.0) { _segmentFraction = 0.0; _segmentIndex++; } _way = way; break; } d += delta; } } assert(_segmentFraction < 1.0); assert((size_t)_segmentIndex <= _way->getNodeCount() - 1); }
double ProbabilityOfMatch::expertProbability(const ConstOsmMapPtr& map, const shared_ptr<const Way>& w1, const shared_ptr<const Way>& w2) { double ds = distanceScore(map, w1, w2); // weight this more heavily. double ps = parallelScore(map, w1, w2); double as = (attributeScore(map, w1, w2) * .7 + .3); double zs = zipperScore(map, w1, w2); double ls = lengthScore(map, w1, w2); if (debug) { LOG_INFO(" ds2 " << distanceScore(map, w2, w1)); LOG_INFO(" l1 " << ElementConverter(map).convertToLineString(w1)->getLength()); LOG_INFO(" l2 " << ElementConverter(map).convertToLineString(w2)->getLength()); LOG_INFO("" << "probability of match " << ds << " " << ps << " " << as << " " << zs); LOG_INFO("" << " " << ds * ps * as * zs); } return ds * ps * as * zs * ls; }
void UnionPolygonsVisitor::visit(const shared_ptr<const Element>& e) { if (e->getElementType() == ElementType::Node) { return; } if (OsmSchema::getInstance().isArea(e->getTags(), e->getElementType())) { shared_ptr<Geometry> g = ElementConverter(_map->shared_from_this()).convertToGeometry(e); _result.reset(g->Union(_result.get())); } }
void MultiLineStringVisitor::visit(const shared_ptr<const Way>& w) { if (w->getNodeCount() >= 2) { if (_ls == 0) { _ls = new vector<Geometry*>(); } Geometry* g = ElementConverter(_map->shared_from_this()).convertToLineString(w)->clone(); _ls->push_back(g); } }
void OsmMapIndex::_insertWay(long wid) { shared_ptr<const Way> w = _map.getWay(wid); Box b(2); shared_ptr<LineString> ls = ElementConverter(_map.shared_from_this()).convertToLineString(w); const Envelope* e = ls->getEnvelopeInternal(); b.setBounds(0, e->getMinX() - _indexSlush, e->getMaxX() + _indexSlush); b.setBounds(1, e->getMinY() - _indexSlush, e->getMaxY() + _indexSlush); _wayTree->insert(b, _createTreeWid(wid)); }
KnnWayIterator::KnnWayIterator(const OsmMap& map, ConstWayPtr way, const RStarTree* tree, const vector<long>& treeIdToWid, bool addError) : KnnIterator(tree, 0.0, 0.0, Box()), _map(map), _treeIdToWid(treeIdToWid) { _wayId = way->getId(); _ls = ElementConverter(map.shared_from_this()).convertToLineString(way); _lsFast = _ls.get(); _indexSlush = _map.getIndex().getIndexSlush(); _distanceCount = 0; _addError = addError; _baseAccuracy = way->getCircularError(); }
void AddGeometryTypeVisitor::visit(const shared_ptr<Element>& e) { if (e->getTags().getNonDebugCount() > 0) { if (e->getElementType() == ElementType::Node) { e->getTags()["geometry_type"] = "Point"; } else { QString type = QString::fromStdString( ElementConverter(_map->shared_from_this()).convertToGeometry(e)->getGeometryType()); e->getTags()["geometry_type"] = type; } } }
WaySubline WaySubline::reverse(const ConstWayPtr& reversedWay) const { WaySubline result; // sanity check to make sure they're actually reversed, this isn't conclusive but should help // if there is a major goof. assert(reversedWay->getNodeCount() == getWay()->getNodeCount()); assert(reversedWay->getNodeId(0) == getWay()->getLastNodeId()); double l = ElementConverter(getMap()).convertToLineString(getWay())->getLength(); result._start = WayLocation(getMap(), reversedWay, l - getEnd().calculateDistanceOnWay()); result._end = WayLocation(getMap(), reversedWay, l - getStart().calculateDistanceOnWay()); return result; }
void WaySplitter::split(const OsmMapPtr& map, const shared_ptr<Way>& w, double maxSize) { shared_ptr<LineString> ls = ElementConverter(map).convertToLineString(w); double l = ls->getLength(); if (l > maxSize) { WayLocation wl (map, w, l / 2.0); vector< shared_ptr<Way> > children = WaySplitter(map, w).split(wl); for (size_t i = 0; i < children.size(); i++) { split(map, children[i], maxSize); } } }
bool WayMergeManipulation::_directConnect(const OsmMapPtr& map, WayPtr w) const { boost::shared_ptr<LineString> ls = ElementConverter(map).convertToLineString(w); CoordinateSequence* cs = GeometryFactory::getDefaultInstance()->getCoordinateSequenceFactory()-> create(2, 2); cs->setAt(map->getNode(w->getNodeId(0))->toCoordinate(), 0); cs->setAt(map->getNode(w->getLastNodeId())->toCoordinate(), 1); // create a straight line and buffer it boost::shared_ptr<LineString> straight(GeometryFactory::getDefaultInstance()->createLineString(cs)); boost::shared_ptr<Geometry> g(straight->buffer(w->getCircularError())); // is the way in question completely contained in the buffer? return g->contains(ls.get()); }
Coordinate BaseComparator::_findNearestPointOnFeature(shared_ptr<OsmMap> map, Coordinate c) { Coordinate result; // find the nearest feature long wId = map->getIndex().findNearestWay(c); shared_ptr<Way> w = map->getWay(wId); // find the nearest point on that feature. shared_ptr<Point> p(GeometryFactory::getDefaultInstance()->createPoint(c)); shared_ptr<LineString> ls = ElementConverter(map).convertToLineString(w); CoordinateSequence* cs = DistanceOp::closestPoints(p.get(), ls.get()); cs->getAt(0, result); delete cs; return result; }