Exemplo n.º 1
0
/*!
 * \brief GetPointForTurn returns ingoingPoint or outgoingPoint for turns.
 * These points belongs to the route but they often are not neighbor of junctionPoint.
 * To calculate the resulting point the function implements the following steps:
 * - going from junctionPoint along feature ft according to the direction which is set in GetPointIndex().
 * - until one of following conditions is fulfilled:
 *   - the end of ft is reached; (returns the last feature point)
 *   - more than kMaxPointsCount points are passed; (returns the kMaxPointsCount-th point)
 *   - the length of passed parts of segment exceeds kMinDistMeters; (returns the next point after the event)
 * \param segment is a ingoing or outgoing feature segment.
 * \param ft is a ingoing or outgoing feature.
 * \param junctionPoint is a junction point.
 * \param maxPointsCount returned poit could't be more than maxPointsCount poins away from junctionPoint
 * \param minDistMeters returned point should be minDistMeters away from junctionPoint if ft is long and consists of short segments
 * \param GetPointIndex is a function for getting points by index.
 * It defines a direction of following along a feature. So it differs for ingoing and outgoing cases.
 * It has following parameters:
 * - start is an index of the start point of a feature segment. For example, FtSeg::m_pointStart.
 * - end is an index of the end point of a feature segment. For example, FtSeg::m_pointEnd.
 * - shift is a number of points which shall be added to end or start index. After that
 *   the sum reflects an index of a feature segment point which will be used for a turn calculation.
 * The sum shall belongs to a range [min(start, end), max(start, end)].
 * shift belongs to a  range [0, abs(end - start)].
 * \return an ingoing or outgoing point for a turn calculation.
 */
m2::PointD GetPointForTurn(OsrmMappingTypes::FtSeg const & segment, FeatureType const & ft,
                           m2::PointD const & junctionPoint,
                           size_t const maxPointsCount,
                           double const minDistMeters,
                           size_t (*GetPointIndex)(const size_t start, const size_t end, const size_t shift))
{
  double curDistanceMeters = 0.;
  m2::PointD point = junctionPoint;
  m2::PointD nextPoint;

  size_t const numSegPoints = abs(segment.m_pointEnd - segment.m_pointStart);
  ASSERT_GREATER(numSegPoints, 0, ());
  ASSERT_LESS(numSegPoints, ft.GetPointsCount(), ());
  size_t const usedFtPntNum = min(maxPointsCount, numSegPoints);

  for (size_t i = 1; i <= usedFtPntNum; ++i)
  {
    nextPoint = ft.GetPoint(GetPointIndex(segment.m_pointStart, segment.m_pointEnd, i));
    curDistanceMeters += MercatorBounds::DistanceOnEarth(point, nextPoint);
    if (curDistanceMeters > minDistMeters)
      return nextPoint;
    point = nextPoint;
  }

  return nextPoint;
}
Exemplo n.º 2
0
/*!
 * \brief GetPointForTurn returns ingoingPoint or outgoingPoint for turns.
 * These points belongs to the route but they often are not neighbor of junctionPoint.
 * To calculate the resulting point the function implements the following steps:
 * - going from junctionPoint along feature ft according to the direction which is set in GetPointIndex().
 * - until one of following conditions is fulfilled:
 *   - the end of ft is reached; (returns the last feature point)
 *   - more than kMaxPointsCount points are passed; (returns the kMaxPointsCount-th point)
 *   - the length of passed parts of segment exceeds kMinDistMeters; (returns the next point after the event)
 * \param segment is a ingoing or outgoing feature segment.
 * \param ft is a ingoing or outgoing feature.
 * \param junctionPoint is a junction point.
 * \param GetPointIndex is a function for getting points by index.
 * It defines a direction of following along a feature. So it differs for ingoing and outgoing cases.
 * It has following parameters:
 * - start is an index of the start point of a feature segment. For example, FtSeg::m_pointStart.
 * - end is an index of the end point of a feature segment. For example, FtSeg::m_pointEnd.
 * - shift is a number of points which shall be added to end or start index. After that
 * the sum reflects an index of a point of a feature segment which will be used for turn calculation.
 * The sum shall belongs to a range [min(start, end), max(start, end)].
 * shift belongs to a  range [0, abs(end - start)].
 * \return an ingoing or outgoing point for turn calculation.
 */
m2::PointD GetPointForTurn(OsrmMappingTypes::FtSeg const & segment, FeatureType const & ft,
                           m2::PointD const & junctionPoint,
                           size_t (*GetPointIndex)(const size_t start, const size_t end, const size_t shift))
{
  // An ingoing and outgoing point could be farther then kMaxPointsCount points from the junctionPoint
  size_t const kMaxPointsCount = 7;
  // If ft feature is long enough and consist of short segments
  // the point for turn generation is taken as the next point the route after kMinDistMeters.
  double const kMinDistMeters = 300.;
  double curDistanceMeters = 0.;
  m2::PointD point = junctionPoint;
  m2::PointD nextPoint;

  size_t const numSegPoints = abs(segment.m_pointEnd - segment.m_pointStart);
  ASSERT_GREATER(numSegPoints, 0, ());
  ASSERT_LESS(numSegPoints, ft.GetPointsCount(), ());
  size_t const usedFtPntNum = min(kMaxPointsCount, numSegPoints);

  for (size_t i = 1; i <= usedFtPntNum; ++i)
  {
    nextPoint = ft.GetPoint(GetPointIndex(segment.m_pointStart, segment.m_pointEnd, i));
    curDistanceMeters += MercatorBounds::DistanceOnEarth(point, nextPoint);
    if (curDistanceMeters > kMinDistMeters)
      return nextPoint;
    point = nextPoint;
  }
  return nextPoint;
}
Exemplo n.º 3
0
void Point2PhantomNode::CalculateWeight(OsrmMappingTypes::FtSeg const & seg,
                                        m2::PointD const & segPt, NodeID const & nodeId,
                                        bool calcFromRight, int & weight, int & offset) const
{
  // nodeId can be INVALID_NODE_ID when reverse node is absent. This node has no weight.
  if (nodeId == INVALID_NODE_ID)
  {
    offset = 0;
    weight = 0;
    return;
  }

  Index::FeaturesLoaderGuard loader(m_index, m_routingMapping.GetMwmId());

  // Offset is measured in milliseconds. We don't know about speed restrictions on the road.
  // So we find it by a whole edge weight.
  // Distance from the node border to the projection point is in meters.
  double distanceM = 0.;
  // Whole node distance in meters.
  double fullDistanceM = 0.;
  // Minimal OSRM edge weight in milliseconds.
  EdgeWeight minWeight = 0;

  auto const range = m_routingMapping.m_segMapping.GetSegmentsRange(nodeId);
  OsrmMappingTypes::FtSeg segment;

  size_t const startIndex = calcFromRight ? range.second - 1 : range.first;
  size_t const endIndex = calcFromRight ? range.first - 1 : range.second;
  int const indexIncrement = calcFromRight ? -1 : 1;

  bool foundSeg = false;
  m2::PointD lastPoint;
  for (size_t segmentIndex = startIndex; segmentIndex != endIndex; segmentIndex += indexIncrement)
  {
    m_routingMapping.m_segMapping.GetSegmentByIndex(segmentIndex, segment);
    if (!segment.IsValid())
      continue;

    FeatureType ft;
    loader.GetFeatureByIndex(segment.m_fid, ft);
    ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

    // Find whole edge weight by node outgoing point.
    if (segmentIndex == range.second - 1)
      minWeight = GetMinNodeWeight(nodeId, ft.GetPoint(segment.m_pointEnd));

    // Calculate distances.
    double distance = CalculateDistance(ft, segment.m_pointStart, segment.m_pointEnd);
    fullDistanceM += distance;
    if (foundSeg)
      continue;

    if (segment.m_fid == seg.m_fid && OsrmMappingTypes::IsInside(segment, seg))
    {
      auto const splittedSegment = OsrmMappingTypes::SplitSegment(segment, seg, !calcFromRight);
      distanceM += CalculateDistance(ft, splittedSegment.m_pointStart, splittedSegment.m_pointEnd);
      // node.m_seg always forward ordered (m_pointStart < m_pointEnd)
      distanceM -= MercatorBounds::DistanceOnEarth(
          ft.GetPoint(calcFromRight ? seg.m_pointStart : seg.m_pointEnd), segPt);

      foundSeg = true;
    }
    else
    {
      distanceM += distance;
    }
  }

  ASSERT_GREATER(fullDistanceM, 0, ("No valid segments on the edge."));
  double const ratio = (fullDistanceM == 0) ? 0 : distanceM / fullDistanceM;
  ASSERT_LESS_OR_EQUAL(ratio, 1., ());

  // OSRM calculates edge weight form start to user point how offset + weight.
  // But it doesn't place info about start and end edge result weight into result structure.
  // So we store whole edge weight into offset and calculates this weights at a postprocessing step.
  offset = minWeight;
  weight = max(static_cast<int>(minWeight * ratio), 0) - minWeight;
}
Exemplo n.º 4
0
void Point2PhantomNode::MakeResult(vector<FeatureGraphNode> & res, size_t maxCount)
{
  vector<OsrmMappingTypes::FtSeg> segments;

  sort(m_candidates.begin(), m_candidates.end(), [](Candidate const & r1, Candidate const & r2)
       {
         return (r1.m_dist < r2.m_dist);
       });

  size_t const n = min(m_candidates.size(), maxCount);
  segments.resize(n);

  for (size_t j = 0; j < n; ++j)
  {
    OsrmMappingTypes::FtSeg & seg = segments[j];
    Candidate const & c = m_candidates[j];

    seg.m_fid = c.m_fid;
    seg.m_pointStart = c.m_segIdx;
    seg.m_pointEnd = c.m_segIdx + 1;
  }

  OsrmFtSegMapping::OsrmNodesT nodes;
  m_routingMapping.m_segMapping.GetOsrmNodes(segments, nodes);

  res.clear();
  res.resize(maxCount);

  for (size_t j = 0; j < maxCount; ++j)
  {
    if (!segments[j].IsValid())
      continue;

    auto it = nodes.find(segments[j].Store());
    if (it == nodes.cend())
      continue;

    FeatureGraphNode & node = res[j];

    if (!m_direction.IsAlmostZero())
    {
      // Filter income nodes by direction mode
      OsrmMappingTypes::FtSeg const & node_seg = segments[j];
      FeatureType feature;
      Index::FeaturesLoaderGuard loader(m_index, m_routingMapping.GetMwmId());
      loader.GetFeatureByIndex(node_seg.m_fid, feature);
      feature.ParseGeometry(FeatureType::BEST_GEOMETRY);
      m2::PointD const featureDirection = feature.GetPoint(node_seg.m_pointEnd) - feature.GetPoint(node_seg.m_pointStart);
      bool const sameDirection = (m2::DotProduct(featureDirection, m_direction) > 0);
      if (sameDirection)
      {
        node.node.forward_node_id = it->second.first;
        node.node.reverse_node_id = INVALID_NODE_ID;
      }
      else
      {
        node.node.forward_node_id = INVALID_NODE_ID;
        node.node.reverse_node_id = it->second.second;
      }
    }
    else
    {
      node.node.forward_node_id = it->second.first;
      node.node.reverse_node_id = it->second.second;
    }

    node.segment = segments[j];
    node.segmentPoint = m_candidates[j].m_point;
    node.mwmId = m_routingMapping.GetMwmId();

    CalculateWeights(node);
  }
  res.erase(remove_if(res.begin(), res.end(),
                      [](FeatureGraphNode const & f)
                      {
                        return !f.mwmId.IsAlive();
                      }),
            res.end());
}
Exemplo n.º 5
0
int main(int argc, char * argv[])
{
  google::SetUsageMessage("SRTM coverage checker.");
  google::ParseCommandLineFlags(&argc, &argv, true);

  Platform & platform = GetPlatform();
  if (!FLAGS_mwm_path.empty())
    platform.SetWritableDirForTests(FLAGS_mwm_path);

  if (FLAGS_srtm_path.empty())
  {
    LOG(LERROR, ("SRTM files directory is not specified."));
    return -1;
  }

  LOG(LINFO, ("writable dir =", platform.WritableDir()));
  LOG(LINFO, ("srtm dir =", FLAGS_srtm_path));

  vector<platform::LocalCountryFile> localFiles;
  platform::FindAllLocalMapsAndCleanup(numeric_limits<int64_t>::max() /* latestVersion */,
                                       localFiles);

  auto fetcher = integration::CreateFeaturesFetcher(localFiles);
  generator::SrtmTileManager manager(FLAGS_srtm_path);

  for (auto & file : localFiles)
  {
    file.SyncWithDisk();
    if (file.GetFiles() != MapOptions::MapWithCarRouting)
    {
      LOG(LINFO, ("Warning! Routing file not found for:", file.GetCountryName()));
      continue;
    }

    FilesMappingContainer container(file.GetPath(MapOptions::CarRouting));
    if (!container.IsExist(ROUTING_FTSEG_FILE_TAG))
    {
      LOG(LINFO, ("Warning! Mwm file has not routing ftseg section:", file.GetCountryName()));
      continue;
    }

    routing::TDataFacade dataFacade;
    dataFacade.Load(container);

    OsrmFtSegMapping segMapping;
    segMapping.Load(container, file);
    segMapping.Map(container);

    size_t all = 0;
    size_t good = 0;

    for (size_t i = 0; i < dataFacade.GetNumberOfNodes(); ++i)
    {
      buffer_vector<OsrmMappingTypes::FtSeg, 8> buffer;
      segMapping.ForEachFtSeg(i, MakeBackInsertFunctor(buffer));

      vector<m2::PointD> path;
      for (size_t k = 0; k < buffer.size(); ++k)
      {
        auto const & segment = buffer[k];
        if (!segment.IsValid())
          continue;
        // Load data from drive.
        FeatureType ft;
        Index::FeaturesLoaderGuard loader(
            fetcher->GetIndex(), fetcher->GetIndex().GetMwmIdByCountryFile(file.GetCountryFile()));
        loader.GetFeatureByIndex(segment.m_fid, ft);
        ft.ParseGeometry(FeatureType::BEST_GEOMETRY);

        // Get points in proper direction.
        auto const startIdx = segment.m_pointStart;
        auto const endIdx = segment.m_pointEnd;
        for (auto idx = min(startIdx, endIdx); idx <= max(startIdx, endIdx); ++idx)
          path.push_back(ft.GetPoint(idx));

        all += path.size();
        for (auto const & point : path)
        {
          auto const height = manager.GetHeight(MercatorBounds::ToLatLon(point));
          if (height != generator::SrtmTile::kInvalidHeight)
            good++;
        }
      }
    }

    auto const bad = all - good;
    auto const percent = all == 0 ? 0.0 : bad * 100.0 / all;
    if (percent > 10.0)
    {
      LOG(LINFO, ("Huge error rate in:", file.GetCountryName(), "good:", good, "bad:", bad, "all:",
                  all, "%:", percent));
    }
  }

  return 0;
}