예제 #1
0
bool CustomPoiMatch::_isExactMatch(const ConstNodePtr& n1, const ConstNodePtr& n2) const
{
  // distance that is considered an exact match. Defaults to 1mm.
  Meters epsilon = conf().getDouble(epsilonDistanceKey(), 1e-3);

  bool result = true;

  if (n1->getElementId() == n2->getElementId())
  {
    // pass, return = true
  }
  else if (n1->toCoordinate().distance(n2->toCoordinate()) > epsilon)
  {
    result = false;
  }
  else
  {
    // if at least one name pair is an exact match then it is an exact string match.
    double stringDistance = NameExtractor(new ExactStringDistance()).extract(n1, n2);

    if (stringDistance != 1.0)
    {
      result = false;
    }
  }

  return result;
}
예제 #2
0
void DualWaySplitter::_reconnectEnd(long centerNodeId, shared_ptr<Way> edge)
{
  Coordinate centerNodeC = _result->getNode(centerNodeId)->toCoordinate();
  // determine which end of edge we're operating on
  Coordinate edgeEnd;
  long edgeEndId;

  ConstNodePtr first = _result->getNode(edge->getNodeId(0));
  ConstNodePtr last = _result->getNode(edge->getLastNodeId());
  if (first->toCoordinate().distance(centerNodeC) <
      last->toCoordinate().distance(centerNodeC))
  {
    edgeEnd = first->toCoordinate();
    edgeEndId = first->getId();
  }
  else
  {
    edgeEnd = last->toCoordinate();
    edgeEndId = last->getId();
  }

  // find all the nodes that are about the right distance from centerNodeId
  shared_ptr<DistanceNodeFilter> filterOuter(new DistanceNodeFilter(Filter::KeepMatches,
    centerNodeC, _splitSize * 1.01));
  shared_ptr<DistanceNodeFilter> filterInner(new DistanceNodeFilter(Filter::FilterMatches,
    centerNodeC, _splitSize * .99));
  ChainNodeFilter chain(filterOuter, filterInner);

  vector<long> nids = _result->filterNodes(chain, centerNodeC, _splitSize * 1.02);

  Radians bestAngle = std::numeric_limits<Radians>::max();
  long bestNid = numeric_limits<long>::max();

  Radians edgeAngle = WayHeading::calculateHeading(centerNodeC, edgeEnd);

  // find the smallest angle from edgeEnd to any of the candidate nodes
  for (size_t i = 0; i < nids.size(); i++)
  {
    if (edgeEndId != nids[i])
    {
      Coordinate c = _result->getNode(nids[i])->toCoordinate();
      Radians thisAngle = WayHeading::calculateHeading(centerNodeC, c);

      Radians deltaMagnitude = WayHeading::deltaMagnitude(edgeAngle, thisAngle);
      if (deltaMagnitude < bestAngle)
      {
        bestAngle = deltaMagnitude;
        bestNid = nids[i];
      }
    }
  }

  // if the smallest angle is less than 45 deg, then connect them.
  if (toDegrees(bestAngle) < 45)
  {
    edge->replaceNode(edgeEndId, bestNid);
  }
}
예제 #3
0
bool CustomPoiMatch::_isDistanceMatch(const ConstNodePtr &n1, const ConstNodePtr &n2) const
{
  double d = n1->toCoordinate().distance(n2->toCoordinate());

  double s1 = n1->getCircularError() / 2.0;
  double s2 = n2->getCircularError() / 2.0;
  // calculated the expected sigma for the distance value.
  double sigma = sqrt(s1 * s1 + s2 * s2);

  // if the distance is within 2 sigma of the expected distance, then call it a match.
  return d < sigma * 2.0;
}
예제 #4
0
WayLocation::WayLocation(ConstOsmMapPtr map, ConstWayPtr way, double distance) :
  _map(map)
{
  double d = 0.0;

  _segmentIndex = -1;
  _segmentFraction = -1;

  _way = way;
  double length = ElementConverter(map).convertToLineString(way)->getLength();

  if (distance <= 0)
  {
    _segmentIndex = 0.0;
    _segmentFraction = 0;
  }
  else if (distance >= length)
  {
    _segmentIndex = _way->getNodeCount() - 1;
    _segmentFraction = 0.0;
  }
  else
  {
    Coordinate last = _map->getNode(way->getNodeId(0))->toCoordinate();

    _segmentIndex = way->getNodeCount() - 1;
    _segmentFraction = 0;

    for (size_t i = 1; i < way->getNodeCount(); i++)
    {
      ConstNodePtr n = _map->getNode(_way->getNodeId(i));
      Coordinate next = n->toCoordinate();
      double delta = next.distance(last);
      last = next;

      if (d <= distance && d + delta > distance)
      {
        _segmentIndex = i - 1;
        _segmentFraction = (distance - d) / delta;
        // this can sometimes happen due to rounding errors.
        if (_segmentFraction >= 1.0)
        {
          _segmentFraction = 0.0;
          _segmentIndex++;
        }
        _way = way;
        break;
      }
      d += delta;
    }
  }
  assert(_segmentFraction < 1.0);
  assert((size_t)_segmentIndex <= _way->getNodeCount() - 1);
}
예제 #5
0
Meters WayLocation::calculateDistanceOnWay() const
{
  //LOG_TRACE("Calculating distance on way...");

  Meters result = 0.0;
  Coordinate last = _map->getNode(_way->getNodeId(0))->toCoordinate();
  for (int i = 1; i < (int)_way->getNodeCount() && i <= _segmentIndex; i++)
  {
    ConstNodePtr n = _map->getNode(_way->getNodeId(i));
    Coordinate next = n->toCoordinate();
    result += next.distance(last);
    last = next;
  }

  if (_segmentIndex < (int)_way->getNodeCount() - 1)
  {
    ConstNodePtr n = _map->getNode(_way->getNodeId(_segmentIndex + 1));
    Coordinate next = n->toCoordinate();
    Meters d = next.distance(last);
    result += d * _segmentFraction;
  }

  return result;
}
  set<long> _findNeighbors(const ConstNodePtr& n)
  {
    set<long> result;

    set<QString> allNames = _getNamePermutations(n->getTags().getNames());

    double minSimilarity = conf().getDouble(PlacesPoiMatch::minimumEditSimilarityKey(),
                                            PlacesPoiMatch::minimumEditSimilarityDefault());

    for (set<QString>::const_iterator it = allNames.begin(); it != allNames.end(); ++it)
    {
      const QString& s = *it;
      // if the string we're comparing against is longer then D may be bigger than
      // (1 - minSimilarity) * string length. Account for that below.
      int D = (int)round((double)s.size() / minSimilarity) - s.size();
      set<long> r = _index->find(n->toCoordinate(), n->getCircularError(), s, D);
      result.insert(r.begin(), r.end());
    }

    return result;
  }
예제 #7
0
WayLocation WayLocation::move(Meters distance) const
{
  WayLocation result(*this);
  Coordinate last = result.getCoordinate();

  // This odd statement avoid us adding irrelevantly small distances.
  while (1 + distance > 1)
  {
    // if we're at the end of the way
    if (result.isLast())
    {
      return result;
    }

    ConstNodePtr n = _map->getNode(_way->getNodeId(result.getSegmentIndex() + 1));
    Coordinate next = n->toCoordinate();

    double delta = last.distance(next);

    // if the next node is too far
    if (distance - delta < 0)
    {
      // figure out what distance we need to move along the segment.
      Coordinate lastSegment = _map->getNode(_way->getNodeId(result.getSegmentIndex()))->
          toCoordinate();
      double segmentLength = lastSegment.distance(next);
      result._segmentFraction += (distance / segmentLength);

      // this can happen due to floating point errors when the new location is very close to a
      // node.
      if (result._segmentFraction >= 1.0)
      {
        result._segmentFraction = 0.0;
        result._segmentIndex = result._segmentIndex + 1;
      }

      distance = 0;
    }
    // if we need to go past the next node
    else
    {
      distance -= delta;
      last = next;
      result._segmentIndex = result.getSegmentIndex() + 1;
      result._segmentFraction = 0.0;
    }
  }

  // This odd statement avoid us subtracting irrelevantly small distances.
  while (1 + distance < 1)
  {
    // if we're at the end of the way
    if (result.isFirst())
    {
      return result;
    }

    if (result._segmentFraction > 0)
    {
      Coordinate next = _map->getNode(_way->getNodeId(result.getSegmentIndex()))->toCoordinate();

      Meters delta = last.distance(next);
      if (distance + delta > 0)
      {
        // figure out what distance we need to move along the segment.
        Coordinate last = _map->getNode(_way->getNodeId(result._segmentIndex + 1))->toCoordinate();
        double segmentLength = last.distance(next);
        result._segmentFraction += (distance / segmentLength);

        // this can happen due to floating point errors when the new location is very close to a
        // node.
        if (result._segmentFraction >= 1.0)
        {
          result._segmentFraction = 0.0;
          result._segmentIndex = result._segmentIndex + 1;
        }

        distance = 0;
      }
      else
      {
        result._segmentFraction = 0;
        distance += delta;
        last = next;
      }
    }
    else
    {
      Coordinate next = _map->getNode(_way->getNodeId(result.getSegmentIndex() - 1))->
          toCoordinate();

      Meters delta = last.distance(next);
      if (distance + delta > 0)
      {
        // figure out what distance we need to move along the segment.
        Coordinate last = _map->getNode(_way->getNodeId(result.getSegmentIndex()))->toCoordinate();
        double segmentLength = last.distance(next);
        result._segmentFraction = 1.0 + (distance / segmentLength);
        // if we're suffering from a floating point issue.
        if (result._segmentFraction >= 1.0)
        {
          // make sure the floating point issue is within the expected bounds.
          assert(result._segmentFraction < 1.0 + 1e-14);
          result._segmentFraction = 0;
        }
        else
        {
          result._segmentIndex = result.getSegmentIndex() - 1;
        }
        distance = 0;
      }
      else
      {
        result._segmentIndex--;
        distance += delta;
        last = next;
      }
    }
  }

  assert(result._segmentFraction < 1.0 && result._segmentFraction >= 0);
  assert(result._segmentIndex >= 0 && result._segmentIndex < (int)result.getWay()->getNodeCount());

  return result;
}