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);
}
WaySublineMatchString MaximalSublineMatcher::findMatch(const ConstOsmMapPtr &map,
  const ConstWayPtr& way1, const ConstWayPtr& way2, double &score, Meters maxRelevantDistance) const
{
  Meters mrd = maxRelevantDistance == -1 ? way1->getCircularError() + way2->getCircularError() :
    maxRelevantDistance;
//  LOG_INFO("min split size: " << _minSplitSize << " _maxAngle " << _maxAngle << " mrd: " << mrd);
//  assert(_minSplitSize >= 0.0 && _maxAngle >= 0.0 && mrd >= 0.0);

  MaximalSubline::ThresholdMatchCriteria* threshold =
    new MaximalSubline::ThresholdMatchCriteria(mrd, _maxAngle);
  // This should use the _minSplitSize rather than mrd, but that causes some tests to fail. We
  // should look into the problem and solve it. See #6159
  MaximalSubline ms(threshold, mrd);

  vector<WaySublineMatch> matches = ms.findAllMatches(map, way1, way2, score);

  return WaySublineMatchString(matches);
}