예제 #1
0
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();
  }
}
예제 #2
0
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;
}
예제 #3
0
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);
        }
    }
}
예제 #4
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;
}
예제 #5
0
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;
}
예제 #6
0
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;
}
예제 #7
0
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();
  }
}
예제 #8
0
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;
}
예제 #9
0
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;
}
예제 #10
0
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);
}
예제 #11
0
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>();
}
예제 #12
0
bool LocationOfPoint::isGreater(int i, double segFrac, const WayLocation& loc) const
{
  return WayLocation::compareLocationValues(i, segFrac,
      loc.getSegmentIndex(), loc.getSegmentFraction()) > 0;
}