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);
}
Exemplo n.º 2
0
void WayMergeManipulation::applyManipulation(OsmMapPtr map,
  set<ElementId> &impactedElements, set<ElementId> &newElements) const
{
  OsmMapPtr result = map;

  // insert the impacted ways
  impactedElements = getImpactedElementIds(map);
  impactedElements.erase(ElementId::way(_left));
  impactedElements.erase(ElementId::way(_right));

  // remove any ways that spanned the left & right
  _removeSpans(result, impactedElements);

  WayPtr left = result->getWay(_left);
  WayPtr right = result->getWay(_right);

  Meters minSplitSize = _minSplitSize;
  minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(left)->getLength() * .7);
  minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(right)->getLength() * .7);

  // split left into its maximal nearest sublines
  MaximalNearestSubline mns1(map, left, right, minSplitSize,
    left->getCircularError() + right->getCircularError());
  int mnsLeftIndex;
  vector< WayPtr > splitsLeft = mns1.splitWay(result, mnsLeftIndex);
  assert(splitsLeft.size() != 0);
  WayPtr mnsLeft = splitsLeft[mnsLeftIndex];

  // split right into its maximal nearest sublines
  MaximalNearestSubline mns2(map, right, mnsLeft, minSplitSize,
    left->getCircularError() + right->getCircularError());
  int mnsRightIndex;
  vector< WayPtr > splitsRight = mns2.splitWay(result, mnsRightIndex);
  assert(splitsRight.size() != 0);
  WayPtr mnsRight = splitsRight[mnsRightIndex];

  for (size_t i = 0; i < splitsLeft.size(); i++)
  {
    if ((int)i != mnsLeftIndex)
    {
      newElements.insert(ElementId::way(splitsLeft[i]->getId()));
    }
    result->addWay(splitsLeft[i]);
  }

  for (size_t i = 0; i < splitsRight.size(); i++)
  {
    if ((int)i != mnsRightIndex)
    {
      newElements.insert(ElementId::way(splitsRight[i]->getId()));
    }
    result->addWay(splitsRight[i]);
  }

  // average the two MNSs
  WayPtr w = WayAverager::average(map, mnsRight, mnsLeft);
  w->setStatus(Status::Conflated);

  RemoveWayOp::removeWay(result, _left);
  RemoveWayOp::removeWay(result, _right);

  result->addWay(w);

  // insert the new merged way
  newElements.insert(ElementId::way(w->getId()));

  for (set<ElementId>::iterator it = impactedElements.begin(); it != impactedElements.end(); ++it)
  {
    if (result->containsElement(*it) == false)
    {
      LOG_ERROR("" << "Internal error: bad way " << it->toString());
    }
  }
}
Exemplo n.º 3
0
void WayMergeManipulation::_splitWays(OsmMapPtr map, WayPtr& left,
  WayPtr& right) const
{
  OsmMapPtr result = map;

  // insert the impacted ways
  set<ElementId> impactedElements = getImpactedElementIds(map);
  impactedElements.erase(ElementId::way(_left));
  impactedElements.erase(ElementId::way(_right));

  // remove any ways that spanned the left & right
  _removeSpans(result, impactedElements);

  left = result->getWay(_left);
  right = result->getWay(_right);

  Meters minSplitSize = _minSplitSize;
  minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(left)->getLength() * .7);
  minSplitSize = min(minSplitSize, ElementConverter(map).convertToLineString(right)->getLength() * .7);

  // split left into its maximal nearest sublines
  MaximalNearestSubline mns1(result, left, right, minSplitSize,
    left->getCircularError() + right->getCircularError());
  int mnsLeftIndex;
  vector< WayPtr > splitsLeft = mns1.splitWay(result, mnsLeftIndex);
  assert(splitsLeft.size() != 0);
  WayPtr mnsLeft = splitsLeft[mnsLeftIndex];

  // split right into its maximal nearest sublines
  MaximalNearestSubline mns2(result, right, mnsLeft, minSplitSize,
    left->getCircularError() + right->getCircularError());
  int mnsRightIndex;
  vector< WayPtr > splitsRight = mns2.splitWay(result, mnsRightIndex);
  assert(splitsRight.size() != 0);
  WayPtr mnsRight = splitsRight[mnsRightIndex];

  for (size_t i = 0; i < splitsLeft.size(); i++)
  {
    if (splitsLeft[i] != left)
    {
      result->addWay(splitsLeft[i]);
    }
  }

  for (size_t i = 0; i < splitsRight.size(); i++)
  {
    if (splitsRight[i] != right)
    {
      result->addWay(splitsRight[i]);
    }
  }

  RemoveWayOp::removeWay(result, _left);
  RemoveWayOp::removeWay(result, _right);

  for (set<ElementId>::iterator it = impactedElements.begin(); it != impactedElements.end(); ++it)
  {
    if (result->containsElement(*it) == false)
    {
      LOG_ERROR("" << "Internal error: bad way " << it->toString());
    }
  }
  left = mnsLeft;
  right = mnsRight;
}