Пример #1
0
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);
}
Пример #2
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);
        }
    }
}
Пример #3
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;
}
Пример #4
0
WaySubline::WaySubline(const WaySubline& from, const ConstOsmMapPtr& newMap)
{
  if (from.isValid())
  {
    ConstWayPtr oldWay = from.getStart().getWay();
    ConstWayPtr newWay = newMap->getWay(oldWay->getId());
    _start = WayLocation(newMap, newWay,
      from.getStart().getSegmentIndex(), from.getStart().getSegmentFraction());
    _end = WayLocation(newMap, newWay,
      from.getEnd().getSegmentIndex(), from.getEnd().getSegmentFraction());
  }
}
Пример #5
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;
}
Пример #6
0
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;
}
WayLocation PertyWaySplitVisitor::_calcSplitPoint(shared_ptr<const Way> 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_VARD(splitWayLength);
  if (splitWayLength > 0)
  {
    boost::uniform_real<> randomSplitPointDistribution(0.0, splitWayLength);
    const double splitPoint = randomSplitPointDistribution(*_rng);
    LOG_VARD(splitPoint);
    return splitWayStart.move(splitPoint);
  }
  //otherwise, return an empty location
  else
  {
    return WayLocation();
  }
}
void MaximalNearestSublineMatcher::_snapToEnds(const ConstOsmMapPtr &map,
  vector<WayLocation>& wl) const
{
  if (wl[0].calculateDistanceOnWay() <= _minSplitSize)
  {
    wl[0] = WayLocation(map, wl[0].getWay(), 0, 0);
  }
  if (wl[1].calculateDistanceFromEnd() <= _minSplitSize)
  {
    wl[1] = WayLocation::createAtEndOfWay(map, wl[1].getWay());
  }
}
Пример #9
0
WayLocation MaximalSubline::_calculateEndWayLocation(const ConstOsmMapPtr &map,
        const ConstWayPtr& a, const ConstWayPtr& b, int indexA, int indexB)
{
    Coordinate ca1 = map->getNode(a->getNodeId(indexA))->toCoordinate();
    Coordinate ca2 = map->getNode(a->getNodeId(indexA + 1))->toCoordinate();
    Coordinate cb2 = map->getNode(b->getNodeId(indexB + 1))->toCoordinate();

    LineSegment lsA(ca1, ca2);
    Coordinate start;
    lsA.closestPoint(cb2, start);

    return LocationOfPoint(map, a).locateAfter(start, WayLocation(map, a, indexA, 0));
}
Пример #10
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;
}
  /**
   * Create a couple of simple way strings and verify that the generated subline match is correct.
   */
  void runTest()
  {
    OsmMapPtr map(new OsmMap());

    NodePtr n1a = TestUtils::createNode(map, Status::Unknown1, 0, 0);
    NodePtr n1b = TestUtils::createNode(map, Status::Unknown1, 100, 0);
    NodePtr n1c = TestUtils::createNode(map, Status::Unknown1, 200, 0);
    WayPtr w1 = TestUtils::createWay(map, QList<NodePtr>() << n1a << n1b);
    WayPtr w2 = TestUtils::createWay(map, QList<NodePtr>() << n1b << n1c);

    NodePtr n2a = TestUtils::createNode(map, Status::Unknown1, 0, 10);
    NodePtr n2b = TestUtils::createNode(map, Status::Unknown1, 150, 10);
    NodePtr n2c = TestUtils::createNode(map, Status::Unknown1, 210, 10);
    WayPtr w3 = TestUtils::createWay(map, QList<NodePtr>() << n2a << n2b);
    WayPtr w4 = TestUtils::createWay(map, QList<NodePtr>() << n2c << n2b);

    WayStringPtr wstr1(new WayString());
    wstr1->append(WaySubline(WayLocation(map, w1, 0), WayLocation::createAtEndOfWay(map, w1)));
    wstr1->append(WaySubline(WayLocation(map, w2, 0), WayLocation::createAtEndOfWay(map, w2)));
    WayStringPtr wstr2(new WayString());
    wstr2->append(WaySubline(WayLocation(map, w3, 0), WayLocation::createAtEndOfWay(map, w3)));
    wstr2->append(WaySubline(WayLocation::createAtEndOfWay(map, w4), WayLocation(map, w4, 0)));

    WayMatchStringMappingPtr mapping(new NaiveWayMatchStringMapping(wstr1, wstr2));
    WaySublineMatchStringPtr wsms = WayMatchStringMappingConverter().
      toWaySublineMatchString(mapping);

    //LOG_VAR(TestUtils::toQuotedString(hoot::toString(wsms)));
    HOOT_STR_EQUALS("matches:\n"
      "subline 1: start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n"
      "subline 2: start: way(-3) index: 0 fraction: 0 end: way(-3) index: 0 fraction: 0.7\n"
      "subline 1: start: way(-2) index: 0 fraction: 0 end: way(-2) index: 0 fraction: 0.428571428571429\n"
      "subline 2: start: way(-3) index: 0 fraction: 0.7 end: way(-3) index: 1 fraction: 0\n"
      "reversed, subline 1: start: way(-2) index: 0 fraction: 0.428571428571429 end: way(-2) index: 1 fraction: 0\n"
      "subline 2: start: way(-4) index: 0 fraction: 0 end: way(-4) index: 1 fraction: 0",
      wsms);
  }
Пример #12
0
WayLocation WayLocation::createAtEndOfWay(const ConstOsmMapPtr& map, const ConstWayPtr way)
{
  return WayLocation(map, way, way->getNodeCount() - 1, 0.0);
}
Пример #13
0
/// @todo this is in desperate need of a rewrite by someone with more rest than myself. -JRS
vector<WaySublineMatch> MaximalSubline::_snapIntersections(const ConstOsmMapPtr& map,
        const ConstWayPtr& w1, const ConstWayPtr& w2, vector<WaySublineMatch>& rawSublineMatches)
{
    // this only works if the rawSublineMatches are in order. We order by subline1
    sort(rawSublineMatches.begin(), rawSublineMatches.end(), lessThan);

    // make sure that ordering by subline1 results in sorted subline2s. If this isn't the case then
    // there isn't much we can do.
    for (size_t i = 2; i < rawSublineMatches.size(); i++)
    {
        if (rawSublineMatches[i].getSubline2().getStart() >
                rawSublineMatches[i - 1].getSubline2().getStart())
        {
            LOG_WARN("Way matches sublines out of order. This is unusual and may give a sub-optimal "
                     "result.");
            return rawSublineMatches;
        }
    }

    for (size_t i = 0; i < rawSublineMatches.size(); i++)
    {
        // if any of the raw sublines are crazy small, then don't try to snap the intersections.
        if (rawSublineMatches[i].getSubline1().getLength() < _spacing * 2 ||
                rawSublineMatches[i].getSubline2().getLength() < _spacing * 2)
        {
            return rawSublineMatches;
        }
    }

    ////
    // calculate a series of point pair matches along the lines.
    ////

    // discretize the first line into a series of points.
    vector< pair<WayLocation, WayLocation> > pairs;
    pairs = _discretizePointPairs(map, w1, w2, rawSublineMatches);
    assert(pairs.size() > 0);
    //LOG_DEBUG_VAR(pairs);

    // extract features on the point pairs and populate a matrix.
    Meters acc = w1->getCircularError() + w2->getCircularError();

    cv::Mat m(pairs.size(), 2, CV_64F);

    size_t currentSubline = 0;

    vector<int> starts(rawSublineMatches.size(), numeric_limits<int>::max());
    vector<int> ends(rawSublineMatches.size(), 0);

    for (size_t i = 0; i < pairs.size(); i++)
    {
        WayLocation& wl1 = pairs[i].first;
        WayLocation& wl2 = pairs[i].second;
        // If the rawSublineMatches is smaller than _spacing, then it may not directly overlap with
        // one of the point pairs. To avoid this, we create a subline that surrounds the point pair
        // and will guarantee that each rawSublineMatches will touch at least one point pair.
        WaySubline ws1 = WaySubline(wl1.move(-_spacing / 2.0), wl1.move(_spacing / 2.0));
        WaySubline ws2 = WaySubline(wl2.move(-_spacing / 2.0), wl2.move(_spacing / 2.0));

        if (currentSubline < rawSublineMatches.size())
        {
            // figure out the first and last match for this subline.
            if (rawSublineMatches[currentSubline].getSubline1().touches(ws1) ||
                    rawSublineMatches[currentSubline].getSubline2().touches(ws2))
            {
                starts[currentSubline] = min<int>(starts[currentSubline], i);
                ends[currentSubline] = max<int>(ends[currentSubline], i);
            }
            else
            {
                // if this is past the current subline, advance to the right subline.
                while (currentSubline < rawSublineMatches.size() &&
                        rawSublineMatches[currentSubline].getSubline1().getEnd() < ws1.getStart() &&
                        rawSublineMatches[currentSubline].getSubline2().getEnd() < ws2.getStart())
                {
                    currentSubline++;
                }
            }
        }

        Meters distance = wl1.getCoordinate().distance(wl2.getCoordinate());
        Radians angle1 = WayHeading::calculateHeading(wl1);
        Radians angle2 = WayHeading::calculateHeading(wl2);
        Radians angleDiff = WayHeading::deltaMagnitude(angle1, angle2);

        m.at<double>(i, 0) = distance / acc;
        m.at<double>(i, 1) = angleDiff;
    }

    //LOG_DEBUG("starts: " << starts);
    //LOG_DEBUG("ends: " << ends);

    // create the matrix of constraints.
    vector<int> finalStarts;
    vector<int> finalEnds;

    if (starts[0] != 0)
    {
        finalStarts.push_back(0);
        finalEnds.push_back(starts[0] + (ends[0] - starts[0]) / 3);
    }

    // this maps finalStarts indexes to the rawSublineMatches indexes. E.g.
    // rawSublineMatches[i] maps to finalStarts[matchIndexes[i]]
    vector<int> matchIndexes(starts.size());

    for (size_t i = 0; i < starts.size(); i++)
    {
        if (starts[i] == numeric_limits<int>::max())
        {
            // Due to poor subline pair matching we cannot properly snap these intersections. Warn the
            // user and move on. It is likely they aren't a good match anyways.
            LOG_WARN("A solid set of point pair matches could not be found.");
            return rawSublineMatches;
        }
        matchIndexes[i] = finalStarts.size();
        finalStarts.push_back(starts[i]);
        finalEnds.push_back(ends[i]);

        if (i != starts.size() - 1)
        {
            finalStarts.push_back(ends[i] - (ends[i] - starts[i]) / 3);
            finalEnds.push_back(starts[i + 1] + (ends[i + 1] - starts[i + 1]) / 3);
        }
    }

    int last = ends.size() - 1;
    if ((size_t)ends[last] != pairs.size() - 1)
    {
        finalStarts.push_back(ends[last] - (ends[last] - starts[last]) / 3);
        finalEnds.push_back(pairs.size() - 1);
    }

    //LOG_DEBUG("finalStarts: " << finalStarts);
    //LOG_DEBUG("finalEnds: " << finalEnds);

    Mat ranges(finalStarts.size(), 2, CV_32S);
    for (size_t i = 0; i < finalStarts.size(); i++)
    {
        ranges.at<int>(i, 0) = finalStarts[i];
        ranges.at<int>(i, 1) = finalEnds[i];
    }

    // run ExpectationIntersection to determine new intersection points.
    ExpectationIntersection ei;
    vector<double> splits = ei.snapMatches(m, ranges);

    //LOG_DEBUG_VAR(splits);

    vector<WaySublineMatch> result = rawSublineMatches;

    for (size_t i = 0; i < matchIndexes.size(); i++)
    {
        size_t mi = matchIndexes[i];
        WayLocation w1Start;
        WayLocation w2Start;

        //LOG_DEBUG(rawSublineMatches[i]);

        // if this is the first subline, then it starts at the beginning of the subline.
        if (matchIndexes[i] == 0)
        {
            w1Start = WayLocation(rawSublineMatches[i].getSubline1().getStart());
            w2Start = WayLocation(rawSublineMatches[i].getSubline2().getStart());
        }
        else
        {
            int wi = (int)splits[mi - 1];
            //LOG_DEBUG("start split: " << wi);
            double r = splits[mi - 1] - wi;
            Meters offset1 = pairs[wi].first.calculateDistanceOnWay() * r +
                             pairs[wi + 1].first.calculateDistanceOnWay() * (1 - r);
            Meters offset2 = pairs[wi].second.calculateDistanceOnWay() * r +
                             pairs[wi + 1].second.calculateDistanceOnWay() * (1 - r);

            //LOG_DEBUG("offset1: " << offset1 << " r: " << r);
            //LOG_DEBUG("offset2: " << offset2 << " r: " << r);
            w1Start = WayLocation(map, w1, offset1);
            w2Start = WayLocation(map, w2, offset2);

        }

        //LOG_DEBUG_VAR(w1Start);
        //LOG_DEBUG_VAR(w2Start);

        // if we are passed the point where we have a node pairing, then snap it back to a legit pair.
        if (w1Start < pairs.front().first.move(-_spacing))
        {
            w1Start = pairs.front().first;
        }
        if (w2Start < pairs.front().second.move(-_spacing))
        {
            w2Start = pairs.front().second;
        }

        //LOG_DEBUG_VAR(w1Start);
        //LOG_DEBUG_VAR(w2Start);

        WayLocation w1End(rawSublineMatches[i].getSubline1().getEnd());
        WayLocation w2End(rawSublineMatches[i].getSubline2().getEnd());

        // convert the end split location into a WayLocation
        if (matchIndexes[i] < (int)splits.size())
        {
            int wi = (int)splits[mi];
            //LOG_DEBUG("end split: " << wi << " matchIndexes[" << i << "]: " << mi);
            double r = splits[mi] - wi;
            Meters offset1 = pairs[wi].first.calculateDistanceOnWay() * r +
                             pairs[wi + 1].first.calculateDistanceOnWay() * (1 - r);
            Meters offset2 = pairs[wi].second.calculateDistanceOnWay() * r +
                             pairs[wi + 1].second.calculateDistanceOnWay() * (1 - r);

            w1End = WayLocation(map, w1, offset1);
            w2End = WayLocation(map, w2, offset2);

            //LOG_DEBUG("offset1: " << offset1 << " r: " << r);
            //LOG_DEBUG("offset2: " << offset2 << " r: " << r);
        }

        // if we are passed the point where we have a node pairing, then snap it back to a legit pair.
        //LOG_DEBUG_VAR(w1End);
        //LOG_DEBUG_VAR(pairs.back().first.move(_spacing));
        if (w1End > pairs.back().first.move(_spacing))
        {
            w1End = pairs.back().first;
        }
        if (w2End > pairs.back().second.move(_spacing))
        {
            w2End = pairs.back().second;
        }
        //LOG_DEBUG("w1End: " << w1End.toString());
        //LOG_DEBUG("w2End: " << w2End.toString());

        WaySubline ws1Expanded = rawSublineMatches[i].getSubline1().expand(
                                     max(_minSplitSize, _spacing));
        WaySubline ws2Expanded = rawSublineMatches[i].getSubline2().expand(
                                     max(_minSplitSize, _spacing));
        if (ws1Expanded.contains(w1Start) == false ||
                ws2Expanded.contains(w2Start) == false ||
                ws1Expanded.contains(w1End) == false ||
                ws2Expanded.contains(w2End) == false ||
                w1Start > w1End ||
                w2Start > w2End)
        {
            LOG_DEBUG("Point pair matching failed, skipping intersection snapping.");
            return rawSublineMatches;
        }

        // snap to the start if we're within spacing distance.
        _snapToStart(w1Start, max(_minSplitSize, _spacing));
        _snapToStart(w2Start, max(_minSplitSize, _spacing));

        // snap to the end if we're within spacing distance.
        _snapToEnd(w1End, max(_minSplitSize, _spacing));
        _snapToEnd(w2End, max(_minSplitSize, _spacing));

        //LOG_DEBUG_VAR(w1End);
        //LOG_DEBUG_VAR(w2End);

        WaySubline ws1(w1Start, w1End);
        WaySubline ws2(w2Start, w2End);
        result[i] = WaySublineMatch(ws1, ws2);
    }

    // Put the updated intersection points into the result.
    return result;
}
Пример #14
0
double MaximalSubline::ThresholdMatchCriteria::match(int index1, int index2) const
{
    Coordinate c11 = _map->getNode(_w1->getNodeId(index1))->toCoordinate();
    Coordinate c12 = _map->getNode(_w1->getNodeId(index1 + 1))->toCoordinate();
    Coordinate c21 = _map->getNode(_w2->getNodeId(index2))->toCoordinate();
    Coordinate c22 = _map->getNode(_w2->getNodeId(index2 + 1))->toCoordinate();

    LineSegment ls1(c11, c12);
    LineSegment ls2(c21, c22);

    Radians heading1, heading2;

    // if the line segment is zero length
    if (ls1.p0 == ls1.p1)
    {
        // calculate heading based on location in way. See #4765 for the drama associated with this fix.
        // This should find way headings appropriately even if there are one or more duplicate nodes in
        // the way. This is done by calculating the way location before and after this node location.
        // There may be some edge conditions when this will fail, but that seems very unlikely.
        heading1 = WayHeading::calculateHeading(WayLocation(_map, _w1, index1, 0));
    }
    else
    {
        // little faster than above and better defined.
        heading1 = ls1.angle();
    }

    // if the line segment is zero length
    if (ls2.p0 == ls2.p1)
    {
        // calculate heading based on location in way
        heading2 = WayHeading::calculateHeading(WayLocation(_map, _w2, index2, 0));
    }
    else
    {
        // little faster than above and better defined.
        heading2 = ls2.angle();
    }

    Radians angleDiff = WayHeading::deltaMagnitude(heading1, heading2);

    if (angleDiff > _maxAngleDiff)
    {
        return 0.0;
    }

    double maxD;

    // Treat this as a variation of Frechet's Distance. This means that we're looking for the longest
    // subline that is within _maxDistance of the other linestring.

    // find the subline that is within _maxDistance. Ultimately we'll need a proper implementation of
    // Frechet's distance, but that'll have to wait till later. See #3213
    matchingSubline(ls1, ls2);

    // previously I found the maximalNearest subline, but that causes issues when there is a large
    // offset between the two datasets.
    //maximalNearestSubline(ls1, ls2);

    maxD = max(ls1.p0.distance(ls2.p0), ls1.p1.distance(ls2.p1));
    double mns = min(ls1.getLength(), ls2.getLength());
    const double epsilon = 1e-6;
    if (maxD > _maxDistance + epsilon)
    {
        return 0.0;
    }

    return 1.0 * mns;
}
Пример #15
0
  void runLocateAfterTest()
  {
    OsmMap::resetCounters();
    shared_ptr<OsmMap> map(new OsmMap());

    Coordinate c[] = { Coordinate(0.0, 0.0), Coordinate(100.0, 0.0),
                       Coordinate(100.0, 10.0), Coordinate(0.0, 10.0),
                       Coordinate::getNull() };
    WayPtr w = TestUtils::createWay(map, Unknown1, c, 1, "");

    WayLocation wl(w, 0, 0);
    HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(0,0), wl));
    HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.1",
      LocationOfPoint(w).locateAfter(Coordinate(0,0), WayLocation(w, 10.0)));
    HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.1",
      LocationOfPoint(w).locateAfter(Coordinate(10,0), WayLocation(w, 0.0)));
    HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.2",
      LocationOfPoint(w).locateAfter(Coordinate(20,0), WayLocation(w, 0.0)));
    HOOT_STR_EQUALS("way: -1 index: 0 fraction: 0.5",
      LocationOfPoint(w).locateAfter(Coordinate(50,0), WayLocation(w, 20.0)));
    HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5",
      LocationOfPoint(w).locateAfter(Coordinate(50,10), WayLocation(w, 0.0)));

    HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5",
      LocationOfPoint(w).locateAfter(Coordinate(50,0), WayLocation(w, 100.0)));
    HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(100,0), WayLocation(w, 0.0)));
    HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0.2",
      LocationOfPoint(w).locateAfter(Coordinate(100,0), WayLocation(w, 102.0)));
    HOOT_STR_EQUALS("way: -1 index: 1 fraction: 0.2",
      LocationOfPoint(w).locateAfter(Coordinate(100,2), WayLocation(w, 100.0)));
    HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(100,10), WayLocation(w, 110.0)));

    HOOT_STR_EQUALS("way: -1 index: 2 fraction: 0.5",
      LocationOfPoint(w).locateAfter(Coordinate(50,10), WayLocation(w, 110.0)));
    HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(0,10), WayLocation(w, 0.0)));
    HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(0,0), WayLocation(w, 3, 0)));
    HOOT_STR_EQUALS("way: -1 index: 3 fraction: 0",
      LocationOfPoint(w).locateAfter(Coordinate(0,10), WayLocation(w, 2, 0.3)));
  }
Пример #16
0
  void runTest()
  {
    OsmMapPtr map = createTestMap();
    WayPtr w1 = map->getWay(FindWaysVisitor::findWaysByTag(map, "note", "w1")[0]);
    WayPtr w2 = map->getWay(FindWaysVisitor::findWaysByTag(map, "note", "w2")[0]);


    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 0.0), WayLocation(map, w1, 30.0)));

      HOOT_STR_EQUALS("", uut.invert());
    }

    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 0.0), WayLocation(map, w1, 20.0)));

      HOOT_STR_EQUALS("start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0",
                      uut.invert());
    }

    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 20.0), WayLocation(map, w1, 30.0)));

      HOOT_STR_EQUALS("start: way(-1) index: 0 fraction: 0 end: way(-1) index: 2 fraction: 0",
                      uut.invert());
    }

    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 20.0)));

      HOOT_STR_EQUALS("start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n"
        "start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0",
        uut.invert());
    }

    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 20.0)));
      uut.addSubline(WaySubline(WayLocation(map, w2, 10.0), WayLocation(map, w2, 20.0)));

      HOOT_STR_EQUALS("start: way(-2) index: 0 fraction: 0 end: way(-2) index: 1 fraction: 0\n"
                      "start: way(-2) index: 2 fraction: 0 end: way(-2) index: 3 fraction: 0\n"
                      "start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0\n"
                      "start: way(-1) index: 2 fraction: 0 end: way(-1) index: 3 fraction: 0",
                      uut.invert());
    }

    {
      WaySublineCollection uut;
      uut.addSubline(WaySubline(WayLocation(map, w1, 10.0), WayLocation(map, w1, 30.0)));
      uut.addSubline(WaySubline(WayLocation(map, w2, 0.0), WayLocation(map, w2, 20.0)));

      HOOT_STR_EQUALS("start: way(-2) index: 2 fraction: 0 end: way(-2) index: 3 fraction: 0\n"
                      "start: way(-1) index: 0 fraction: 0 end: way(-1) index: 1 fraction: 0",
                      uut.invert());
    }
  }