예제 #1
0
void WayCleaner::cleanWay(WayPtr way, const ConstOsmMapPtr& map)
{
  const vector<long> nodeIds = way->getNodeIds();

  if (isZeroLengthWay(way, map))
  {
    throw HootException("Cannot clean zero length way.");
  }

  QList<long> modifiedNodeIds = QVector<long>::fromStdVector(nodeIds).toList();
  QList<long> nodeIdsTemp;
  QList<Coordinate> coords;
  for (size_t i = 0; i < nodeIds.size(); i++)
  {
    bool found = false;
    if (nodeIdsTemp.contains(nodeIds[i]))
    {
      //the only duplicated nodes allowed are the first and last for a closed way
      if (i == (nodeIds.size() - 1) && nodeIds[0] == nodeIds[i])
      {
      }
      else
      {
        found = true;
      }
    }
    else
    {
      nodeIdsTemp.append(nodeIds[i]);
    }

    const Coordinate coord = map->getNode(nodeIds[i])->toCoordinate();
    if (coords.contains(coord))
    {
      //the only duplicated coords allowed are the first and last for a closed way, if the node ID's
      //match
      if (i == (nodeIds.size() - 1) && nodeIds[0] == nodeIds[i])
      {
      }
      else
      {
        found = true;
      }
    }
    else
    {
      coords.append(coord);
    }

    if (found)
    {
      modifiedNodeIds.removeAt(i);
    }
  }

  way->setNodes(modifiedNodeIds.toVector().toStdVector());
}
예제 #2
0
vector<ElementPtr> PertyWaySplitVisitor::_split(ElementPtr element)
{
  //randomly select elements and split them into two parts
  boost::uniform_real<> randomSplitDistribution(0.0, 1.0);
  const double randomSplitNum = randomSplitDistribution(*_rng);
  if (randomSplitNum <= _waySplitProbability)
  {
    LOG_TRACE("element " << element->getElementId() << " *will* be split based on a split " <<
      "probability of: " <<  _waySplitProbability << " and a randomly generated number: " <<
      randomSplitNum << "\n");

    _splitRecursionLevel++;
    LOG_VART(_splitRecursionLevel);

    const int numNodesBeforeSplit = _map->getNodes().size();
    LOG_VART(numNodesBeforeSplit);
    const int numWaysBeforeSplit = _map->getWays().size();
    LOG_VART(numWaysBeforeSplit);

    WayLocation waySplitPoint;
    MultiLineStringLocation multiLineSplitPoint;
    QList<long> nodeIdsBeforeSplit;
    int segmentIndex = -1;
    ElementId wayId;
    //determine where to split the element
    if (element->getElementType() == ElementType::Way)
    {
      WayPtr way = boost::dynamic_pointer_cast<Way>(element);
      LOG_VART(way->getNodeCount());
      nodeIdsBeforeSplit = QVector<long>::fromStdVector(way->getNodeIds()).toList();
      LOG_VART(nodeIdsBeforeSplit);
      waySplitPoint = _calcSplitPoint(way);
    }
    else
    {
      multiLineSplitPoint = _calcSplitPoint(boost::dynamic_pointer_cast<Relation>(element), wayId);
      waySplitPoint = multiLineSplitPoint.getWayLocation();
    }

    const QString distanceMsgStrEnd =
      QString("a minimum node spacing of ")
        .append(QString::number(_minNodeSpacing))
        .append(" meters");
    if (!waySplitPoint.isValid())
    {
      _splitRecursionLevel--;
      LOG_VART(_splitRecursionLevel);

      LOG_TRACE("split point *will not* be used because *it violates* " << distanceMsgStrEnd);
      //if it violates the min node spacing, return an empty element collection, which will end the
      //recursive splitting on the current way
      return vector<ElementPtr>();
    }
    else
    {
      LOG_TRACE("split point *will* be used because it *does not* violate " << distanceMsgStrEnd);
      segmentIndex = waySplitPoint.getSegmentIndex();
      LOG_VART(segmentIndex);
    }

    //split the element
    vector<ElementPtr> newElementsAfterSplit;
    if (element->getElementType() == ElementType::Way)
    {
      vector<WayPtr> newWaysAfterSplit =
        WaySplitter::split(_map->shared_from_this(),
        boost::dynamic_pointer_cast<Way>(element), waySplitPoint);
      for (size_t i = 0; i < newWaysAfterSplit.size(); i++)
      {
        newElementsAfterSplit.push_back(newWaysAfterSplit.at(i));
      }
    }
    else
    {
      ElementPtr match;
      MultiLineStringSplitter().split(_map->shared_from_this(), multiLineSplitPoint, match);
      newElementsAfterSplit.push_back(match);
    }

    const int numNodesAfterSplit = _map->getNodes().size();
    LOG_VART(numNodesAfterSplit);
    const int numNewNodesCreatedBySplit = numNodesAfterSplit - numNodesBeforeSplit;
    LOG_VART(numNewNodesCreatedBySplit);
    LOG_VART(_map->getWays().size());

    if (numNewNodesCreatedBySplit > 0)
    {
      WayPtr way = boost::dynamic_pointer_cast<Way>(element);
      //Its possible that the splitting of a relation could generate a new node.  In that case,
      //_updateNewNodeProperties does not need to be called b/c the MultiLineStringSplitter has
      //already properly updated the new node's properties.  when a way is split, however, the
      //new node's properties must be updated by the call to _updateNewNodeProperties.
      if (way != 0)
      {
        assert(nodeIdsBeforeSplit.size() > 0);
        //update properties on any nodes added as a result of the way splitting (new ways created as a
        //result of the splitting will already have had their parent's tags added by WaySplitter)
        _updateNewNodeProperties(
          _getNodeAddedBySplit(nodeIdsBeforeSplit, newElementsAfterSplit),
          _map->getNode(way->getNodeId(segmentIndex)),
          _map->getNode(way->getNodeId(segmentIndex + 1)));
      }
    }

    //recursive call
    for (vector<ElementPtr>::const_iterator it = newElementsAfterSplit.begin();
         it != newElementsAfterSplit.end(); ++it)
    {
      _split(*it);
    }

    return newElementsAfterSplit;
  }
  else
  {
    LOG_TRACE("element " << element->getElementId() << " *will not* be split based on a split " <<
      "probability of: " << _waySplitProbability << " and a randomly generated number: " <<
      randomSplitNum << "\n");
  }

  //end the recursive splitting on the current way
  return vector<ElementPtr>();
}
  void _sanityCheckSplit(SplitLongLinearWaysVisitor& /*splitVisitor*/, const int startNode,
                         const int numNodes, const int numWays)
  {
    // Pull out ways
    WayMap ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );

    // Pull out nodes
    OsmMap::NodeMap nodes = _map->getNodeMap();
    CPPUNIT_ASSERT_EQUAL( numNodes, nodes.size() );

    // Make sure no relations
    RelationMap relations = _map->getRelationMap();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(0), relations.size() );

    unsigned int nodesLeftToFind = numNodes;
    unsigned int searchId = startNode;
    while ( nodesLeftToFind > 0 )
    {
      LOG_DEBUG("Looking for node ID " << searchId);
      bool madeProgress = false;
      bool hitError = false;
      for (WayMap::const_iterator it = ways.begin(); it != ways.end(); it++)
      {
        // Does this way have the node we're looking for?
        WayPtr currWay = it->second;

        if ( currWay->getFirstNodeId() == searchId )
        {
          nodesLeftToFind--;
          LOG_DEBUG("Found node ID " << searchId << " at start of way " <<
                     currWay->getId());
          madeProgress = true;
          // Make sure rest of nodes we want exist and are in correct order
          searchId++;
          std::vector<long> wayIds = currWay->getNodeIds();

          // Start at second node, since we already checked first one
          for ( std::vector<long>::const_iterator nodeIt = wayIds.begin() + 1;
            nodeIt != wayIds.end(); ++nodeIt )
          {
             if ( *nodeIt != searchId )
             {
               // Throw a hissy fit
               hitError = true;
               break;
             }

             nodesLeftToFind--;
             searchId++;
          }
          searchId--;
          // Search count is off by one
          if ( nodesLeftToFind > 0 )
          {
            nodesLeftToFind++;
          }

          LOG_DEBUG("Found remainder of IDs up to " << searchId << " inside way");
          LOG_DEBUG("Nodes left to find: " << nodesLeftToFind);

          // We found what we needed, bail out of looking for more ways
          break;
        }
        else
        {
          LOG_DEBUG("Way started with ID " << currWay->getFirstNodeId() << ", skipping");
        }
      }

      CPPUNIT_ASSERT( (madeProgress == true) && (hitError == false) );
    }
  }