WayLocation PertyWaySplitVisitor::_calcSplitPoint(ConstWayPtr way) const { //create a way location that is the minimum node spacing distance from the beginning of the way WayLocation splitWayStart(_map->shared_from_this(), way, _minNodeSpacing); //create a way location that is the minimum node spacing from the end of the way WayLocation splitWayEnd = WayLocation::createAtEndOfWay(_map->shared_from_this(), way). move(-1 * _minNodeSpacing); //if the length between the way locations is greater than zero, then then a way location can be //selected that doesn't violate the min node spacing const double splitWayLength = splitWayEnd.calculateDistanceOnWay() - splitWayStart.calculateDistanceOnWay(); LOG_VART(splitWayLength); if (splitWayLength > 0) { boost::uniform_real<> randomSplitPointDistribution(0.0, splitWayLength); const double splitPoint = randomSplitPointDistribution(*_rng); LOG_VART(splitPoint); return splitWayStart.move(splitPoint); } //otherwise, return an empty location else { return WayLocation(); } }
vector<WayPtr> WaySplitter::createSplits(const vector<WayLocation>& wl) { vector<WayPtr> result; WayLocation last = WayLocation(_map, _a, 0, 0.0); result.resize(wl.size() + 1); for (size_t i = 0; i < wl.size(); i++) { assert(wl[i].getWay() == _a); WayLocation curr = wl[i]; if (last.compareTo(curr) != 0) { result[i] = WaySubline(last, curr).toWay(_map); if (result[i]->getNodeCount() == 0) { result[i].reset(); } } last = curr; } WayLocation end(_map, _a, _a->getNodeCount() - 1, 0.0); if (last.compareTo(end) != 0) { result[result.size() - 1] = WaySubline(last, end).toWay(_map, _nf.get()); } 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); } } }
Coordinate WayHeading::calculateVector(const WayLocation& loc, Meters delta) { Coordinate sc = loc.move(-delta).getCoordinate(); Coordinate ec = loc.move(delta).getCoordinate(); Coordinate result; result.x = ec.x - sc.x; result.y = ec.y - sc.y; double mag = result.distance(Coordinate(0, 0)); result.x /= mag; result.y /= mag; return result; }
cv::Mat GraphComparator::_calculateCostDistance(shared_ptr<OsmMap> map, Coordinate c) { // make a copy of the map so we can manipulate it. map.reset(new OsmMap(map)); // find the nearest feature long wId = map->getIndex().findNearestWay(c); shared_ptr<Way> w = map->getWay(wId); // split way at c WayLocation wl = LocationOfPoint::locate(map, w, c); vector< shared_ptr<Way> > v = WaySplitter::split(map, w, wl); wl = LocationOfPoint::locate(map, v[0], c); if (wl.isNode() == false) { // I haven't been able to recreate the case when this happens. LOG_WARN("Internal Error: Expected wl to be on a node, but it was this: " << wl); } assert(wl.isNode() == true); // populate graph shared_ptr<DirectedGraph> graph(new DirectedGraph()); graph->deriveEdges(map); ShortestPath sp(graph); // set cost at c to zero. long sourceId = v[0]->getNodeId(wl.getSegmentIndex()); sp.setNodeCost(sourceId, 0.0); // calculate cost sp.calculateCost(); // paint graph onto raster //_exportGraphImage(map, *graph, sp, "/home/jason.surratt/tmp/graph.png"); cv::Mat mat = _paintGraph(map, *graph, sp); // calculate cost distance raster _calculateRasterCost(mat); return mat; }
WaySublineCollection WaySublineCollection::invert() const { WaySublineCollection result; if (_sublines.size() == 0) { return result; } // We are going to sort all the way sublines so we can generate the inverted sublines starting // at the beginning and working on to the end. We'll maintain a simple variable for where the // next subline starts and then use a little simple logic to determine when we've found a legit // inverted subline and push it on to the result. // make a copy so we can sort. vector<WaySubline> sublines = _sublines; sort(sublines.begin(), sublines.end(), compareSublines); WayLocation sublineStart = WayLocation(_sublines[0].getMap(), sublines[0].getWay(), 0, 0); // go through all the sorted sublines for (size_t i = 0; i < sublines.size(); i++) { if (sublineStart.getWay() != sublines[i].getWay()) { // if this isn't an empty subline if (sublineStart.isLast() == false) { result.addSubline(WaySubline(sublineStart, WayLocation::createAtEndOfWay(_sublines[0].getMap(), sublineStart.getWay()))); } sublineStart = WayLocation(_sublines[0].getMap(), sublines[i].getWay(), 0, 0); } assert(sublineStart.getWay() == sublines[i].getWay()); if (sublineStart == sublines[i].getStart()) { // an empty subline at the beginning sublineStart = sublines[i].getEnd(); } else { // add another subline from the sublineStart to the beginning of the next subline. result.addSubline(WaySubline(sublineStart, sublines[i].getStart())); // the next negative subline starts at the end of this positive subline sublineStart = sublines[i].getEnd(); } } // if we haven't reached the end, then add one more subline for the end of the line. if (sublineStart.isLast() == false) { result.addSubline(WaySubline(sublineStart, WayLocation::createAtEndOfWay(_sublines[0].getMap(), sublineStart.getWay()))); } return result; }
MultiLineStringLocation PertyWaySplitVisitor::_calcSplitPoint(ConstRelationPtr relation, ElementId& wayId) const { const vector<RelationData::Entry>& members = relation->getMembers(); LOG_VART(members.size()); //find the way to split on boost::uniform_int<> randomWayIndexDistribution(0, members.size() - 1); int wayIndex = randomWayIndexDistribution(*_rng); wayId = members.at(wayIndex).getElementId(); LOG_VART(wayIndex); LOG_VART(wayId); ElementPtr element = _map->getElement(wayId); if (element->getElementType() != ElementType::Way) { throw HootException( "PERTY feature splitting for multi-line string relations may only occur on relations which contain only ways."); } WayPtr way = boost::dynamic_pointer_cast<Way>(element); LOG_VART(way->getNodeCount()); //calculate the split point WayLocation wayLocation = _calcSplitPoint(way); //return it, if its valid if (wayLocation.isValid()) { return MultiLineStringLocation( _map->shared_from_this(), relation, wayIndex, wayLocation); } //otherwise, return an empty location else { return MultiLineStringLocation(); } }
vector< shared_ptr<Way> > WaySplitter::split(WayLocation& splitPoint) { vector< shared_ptr<Way> > result; if (splitPoint.isFirst() || splitPoint.isLast()) { result.push_back(_a); } else { WayLocation first(_map, _a, 0, 0.0); WayLocation last(_map, _a, _a->getNodeCount() - 1, 0.0); result.push_back(WaySubline(first, splitPoint).toWay(_map, _nf.get())); result.push_back(WaySubline(splitPoint, last).toWay(_map, _nf.get())); _map->removeWay(_a); _map->addWay(result[0]); _map->addWay(result[1]); } return result; }
WayLocation LocationOfPoint::locateAfter(const Coordinate& inputPt, const WayLocation& minLocation) const { if (minLocation.isValid() == false) { return locate(inputPt); } assert(minLocation.getWay() == _way); double minDistance = std::numeric_limits<double>().max(); WayLocation nextClosestLocation = minLocation; LineSegment seg; size_t startIndex = 0; startIndex = (size_t)minLocation.getSegmentIndex(); for (size_t i = startIndex; i < _way->getNodeCount() - 1; i++) { seg.p0 = _map->getNode(_way->getNodeId(i))->toCoordinate(); seg.p1 = _map->getNode(_way->getNodeId(i + 1))->toCoordinate(); if (i == startIndex) { seg.p0 = minLocation.getCoordinate(); } double segDistance = seg.distance(inputPt); double segFrac = segmentFraction(seg, inputPt); if (segDistance < minDistance) { // if this is the first case (a partial line segment) if (i == startIndex) { // recalculate the segFrac in terms of the whole line segment. segFrac = minLocation.getSegmentFraction() + (1 - minLocation.getSegmentFraction()) * segFrac; } nextClosestLocation = WayLocation(_map, _way, i, segFrac); minDistance = segDistance; } } // Return the minDistanceLocation found. // This will not be null, since it was initialized to minLocation Assert::isFalse(nextClosestLocation >= minLocation, "computed location is before specified minimum location"); return nextClosestLocation; }
void GraphComparator::drawCostDistance(shared_ptr<OsmMap> map, vector<Coordinate>& c, QString output) { _updateBounds(); // make a copy of the map so we can manipulate it. map.reset(new OsmMap(map)); for (size_t i = 0; i < c.size(); i++) { cout << c[i].x << " " << c[i].y << endl; c[i] = _findNearestPointOnFeature(map, c[i]); cout << c[i].x << " " << c[i].y << endl; // find the nearest feature long wId = map->getIndex().findNearestWay(c[i]); shared_ptr<Way> w = map->getWay(wId); // split way at c WayLocation wl = LocationOfPoint::locate(map, w, c[i]); vector< shared_ptr<Way> > v = WaySplitter::split(map, w, wl); wl = LocationOfPoint::locate(map, v[0], c[i]); assert(wl.isNode() == true); } // populate graph shared_ptr<DirectedGraph> graph(new DirectedGraph()); graph->deriveEdges(map); LOG_WARN("Running cost"); ShortestPath sp(graph); for (size_t i = 0; i < c.size(); i++) { long wId = map->getIndex().findNearestWay(c[i]); shared_ptr<Way> w = map->getWay(wId); WayLocation wl = LocationOfPoint::locate(map, w, c[i]); // set cost at c to zero. long sourceId = w->getNodeId(wl.getSegmentIndex()); sp.setNodeCost(sourceId, 0.0); } // calculate cost sp.calculateCost(); LOG_WARN("Cost done"); cv::Mat mat = _paintGraph(map, *graph, sp); _saveImage(mat, output, -1.0, false); _saveImage(mat, output.replace(".png", "2.png"), -1.0, true); shared_ptr<OGRSpatialReference> srs(new OGRSpatialReference()); srs->importFromEPSG(900913); Coordinate c1 = MapProjector::project(Coordinate(_projectedBounds.MinX, _projectedBounds.MinY), map->getProjection(), srs); cout << "coord " << c1.x << ", " << c1.y << endl; Coordinate c2 = MapProjector::project(Coordinate(_projectedBounds.MaxX, _projectedBounds.MaxY), map->getProjection(), srs); cout << "coord2 " << c2.x << ", " << c2.y << endl; printf("POSITION_Y=%f\n", (c1.y + c2.y) / 2.0); //cout << "POSITION_Y=" << (c1.y + c2.y) / 2.0 << endl; printf("POSITION_X=%f\n", (c1.x + c2.x) / 2.0); //cout << "POSITION_X=" << (c1.x + c2.x) / 2.0 << endl; cout << "M12=0.0" << endl; cout << "M11=1.0" << endl; cout << "M10=0.0" << endl; cout << "M02=0.0" << endl; cout << "INITIAL_SCALE=" << (c2.x - c1.x) / (double)_width * 100.0 << endl; cout << "M01=0.0" << endl; cout << "M00=1.0" << endl; // paint graph onto raster //_exportGraphImage(map, *graph, sp, output); }
vector<ElementPtr> PertyWaySplitVisitor::_split(ElementPtr element) { //randomly select elements and split them into two parts boost::uniform_real<> randomSplitDistribution(0.0, 1.0); const double randomSplitNum = randomSplitDistribution(*_rng); if (randomSplitNum <= _waySplitProbability) { LOG_TRACE("element " << element->getElementId() << " *will* be split based on a split " << "probability of: " << _waySplitProbability << " and a randomly generated number: " << randomSplitNum << "\n"); _splitRecursionLevel++; LOG_VART(_splitRecursionLevel); const int numNodesBeforeSplit = _map->getNodes().size(); LOG_VART(numNodesBeforeSplit); const int numWaysBeforeSplit = _map->getWays().size(); LOG_VART(numWaysBeforeSplit); WayLocation waySplitPoint; MultiLineStringLocation multiLineSplitPoint; QList<long> nodeIdsBeforeSplit; int segmentIndex = -1; ElementId wayId; //determine where to split the element if (element->getElementType() == ElementType::Way) { WayPtr way = boost::dynamic_pointer_cast<Way>(element); LOG_VART(way->getNodeCount()); nodeIdsBeforeSplit = QVector<long>::fromStdVector(way->getNodeIds()).toList(); LOG_VART(nodeIdsBeforeSplit); waySplitPoint = _calcSplitPoint(way); } else { multiLineSplitPoint = _calcSplitPoint(boost::dynamic_pointer_cast<Relation>(element), wayId); waySplitPoint = multiLineSplitPoint.getWayLocation(); } const QString distanceMsgStrEnd = QString("a minimum node spacing of ") .append(QString::number(_minNodeSpacing)) .append(" meters"); if (!waySplitPoint.isValid()) { _splitRecursionLevel--; LOG_VART(_splitRecursionLevel); LOG_TRACE("split point *will not* be used because *it violates* " << distanceMsgStrEnd); //if it violates the min node spacing, return an empty element collection, which will end the //recursive splitting on the current way return vector<ElementPtr>(); } else { LOG_TRACE("split point *will* be used because it *does not* violate " << distanceMsgStrEnd); segmentIndex = waySplitPoint.getSegmentIndex(); LOG_VART(segmentIndex); } //split the element vector<ElementPtr> newElementsAfterSplit; if (element->getElementType() == ElementType::Way) { vector<WayPtr> newWaysAfterSplit = WaySplitter::split(_map->shared_from_this(), boost::dynamic_pointer_cast<Way>(element), waySplitPoint); for (size_t i = 0; i < newWaysAfterSplit.size(); i++) { newElementsAfterSplit.push_back(newWaysAfterSplit.at(i)); } } else { ElementPtr match; MultiLineStringSplitter().split(_map->shared_from_this(), multiLineSplitPoint, match); newElementsAfterSplit.push_back(match); } const int numNodesAfterSplit = _map->getNodes().size(); LOG_VART(numNodesAfterSplit); const int numNewNodesCreatedBySplit = numNodesAfterSplit - numNodesBeforeSplit; LOG_VART(numNewNodesCreatedBySplit); LOG_VART(_map->getWays().size()); if (numNewNodesCreatedBySplit > 0) { WayPtr way = boost::dynamic_pointer_cast<Way>(element); //Its possible that the splitting of a relation could generate a new node. In that case, //_updateNewNodeProperties does not need to be called b/c the MultiLineStringSplitter has //already properly updated the new node's properties. when a way is split, however, the //new node's properties must be updated by the call to _updateNewNodeProperties. if (way != 0) { assert(nodeIdsBeforeSplit.size() > 0); //update properties on any nodes added as a result of the way splitting (new ways created as a //result of the splitting will already have had their parent's tags added by WaySplitter) _updateNewNodeProperties( _getNodeAddedBySplit(nodeIdsBeforeSplit, newElementsAfterSplit), _map->getNode(way->getNodeId(segmentIndex)), _map->getNode(way->getNodeId(segmentIndex + 1))); } } //recursive call for (vector<ElementPtr>::const_iterator it = newElementsAfterSplit.begin(); it != newElementsAfterSplit.end(); ++it) { _split(*it); } return newElementsAfterSplit; } else { LOG_TRACE("element " << element->getElementId() << " *will not* be split based on a split " << "probability of: " << _waySplitProbability << " and a randomly generated number: " << randomSplitNum << "\n"); } //end the recursive splitting on the current way return vector<ElementPtr>(); }
bool LocationOfPoint::isGreater(int i, double segFrac, const WayLocation& loc) const { return WayLocation::compareLocationValues(i, segFrac, loc.getSegmentIndex(), loc.getSegmentFraction()) > 0; }