void runConflateTest()
  {
    OsmReader reader;

    shared_ptr<OsmMap> map(new OsmMap());
    reader.setDefaultStatus(Status::Unknown1);
    reader.read("test-files/ToyBuildingsTestA.osm", map);
    reader.setDefaultStatus(Status::Unknown2);
    reader.read("test-files/ToyBuildingsTestB.osm", map);

    MapProjector::projectToPlanar(map);

    WayMap wm = map->getWays();
    for (WayMap::const_iterator it = wm.begin(); it != wm.end(); ++it)
    {
      const ConstWayPtr& w = it->second;
      const Tags& t = w->getTags();
      if (t["REF1"] != "Target" && t["REF2"] != "Target")
      {
        map->removeWay(it->first);
      }
    }

    Conflator uut;

    shared_ptr<Manipulator> m(new BuildingMergeManipulator());
    deque< shared_ptr<Manipulator> > manipulators;
    manipulators.push_back(m);
    uut.setManipulators(manipulators);

    uut.loadSource(map);
    uut.conflate();

    shared_ptr<OsmMap> out(new OsmMap(uut.getBestMap()));
    MapProjector::projectToWgs84(out);

    OsmWriter writer;
    writer.setIncludeIds(true);
    writer.write(out, "test-output/BuildingConflatorTest.osm");

    ConstWayPtr cheddars = getWay(out, "REF1", "Cheddar's");
    CPPUNIT_ASSERT_EQUAL(string("Cheddar's"), cheddars->getTags()["REF2"].toStdString());
    HOOT_STR_EQUALS(Status::Conflated, cheddars->getStatus());

    ConstWayPtr biondi = getWay(out, "REF1", "Biondi");
    CPPUNIT_ASSERT_EQUAL(string("Biondi"), biondi->getTags()["REF2"].toStdString());
    HOOT_STR_EQUALS(Status::Conflated, biondi->getStatus());

    ConstWayPtr freddys = getWay(out, "REF1", "Freddy's");
    CPPUNIT_ASSERT_EQUAL(false, freddys->getTags().contains("REF2"));
    HOOT_STR_EQUALS(Status::Unknown1, freddys->getStatus());

    ConstWayPtr target = getWay(out, "REF1", "Target");
    CPPUNIT_ASSERT_EQUAL(string("Target"), biondi->getTags()["REF2"].toStdString());
    HOOT_STR_EQUALS(Status::Unknown1, target->getStatus());

    CPPUNIT_ASSERT_EQUAL((size_t)9, out->getWays().size());
  }
예제 #2
0
void SuperfluousWayRemover::removeWays()
{
  LOG_INFO("Removing superfluous ways...");

  shared_ptr<ElementToRelationMap> e2r = _inputMap->getIndex().getElementToRelationMap();

  // make a copy of the ways to avoid issues when removing.
  const WayMap ways = _inputMap->getWays();
  for (WayMap::const_iterator it = ways.begin(); it != ways.end(); ++it)
  {
    const shared_ptr<const Way>& w = it->second;

    bool same = true;
    long firstId;
    const vector<long>& nodeIds = w->getNodeIds();
    if (nodeIds.size() > 0)
    {
      firstId = nodeIds[0];

      for (size_t i = 1; i < nodeIds.size(); i++)
      {
        if (nodeIds[i] != firstId)
        {
          same = false;
        }
      }
    }

    bool inRelation = e2r->getRelationByElement(w).size() > 0;

    // if all the nodes in a way are the same or there are zero nodes
    if ((same || w->getTags().size() == 0) && !inRelation)
    {
      _inputMap->removeWayFully(w->getId());
    }
  }
}
  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) );
    }
  }
  void _modifyTests(SplitLongLinearWaysVisitor& splitVisitor)
  {

    int wayID = 0;
    int startNode = 234;
    int numNodes;
    int numWays;

    // N + 1 nodes: 2 ways
    _map.reset(new OsmMap());
    numNodes = splitVisitor.getMaxNumberOfNodes() + 1;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    WayMap ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // N + 2 nodes: 2 ways
    _map.reset(new OsmMap());
    numNodes = splitVisitor.getMaxNumberOfNodes() + 2;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;

    // (2N) - 2 nodes: 2 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 2) - 2;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (2N) - 1 nodes: 2 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 2) - 1;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (2N) nodes: 2 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 2);
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (2N) + 1 nodes: 3 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 2) + 1;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (2N) + 2 nodes: 3 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 2) + 2;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    ways = _map->getWays();
    CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(numWays), ways.size() );
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;



    // Picking 541N as 541 is large enough to be a good stress test, plus it's a prime number
    //    and primes are good at exposing problems

    // (541N) - 2 nodes: 541 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 541) - 2;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (541N) - 1 nodes: 541 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 541) - 1;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (541N) nodes: 541 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 541);
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (541N) + 1 nodes: 542 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 541) + 1;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;


    // (541N) + 2 nodes: 542 ways
    _map.reset(new OsmMap());
    numNodes = (splitVisitor.getMaxNumberOfNodes() * 541) + 2;
    numWays = _calcNumWays(numNodes, splitVisitor);
    _createWay(++wayID, startNode, startNode + numNodes - 1);
    _map->visitRw(splitVisitor);

    // Sanity checks on split
    _sanityCheckSplit(splitVisitor, startNode, numNodes, numWays);
    startNode += numNodes;
  }
예제 #5
0
std::map<unsigned long long int, std::pair<RelationPtr, std::map<unsigned long long int, WayPtr> > > Network::getWaysByAdminBoundary(int admin_level)
{
	typedef std::map<unsigned long long int, WayPtr> WayMap;
	typedef std::pair<unsigned long long int, WayPtr> WayType;
	typedef std::map<unsigned long long int, RelationPtr> RelationMap;
	typedef std::pair<RelationPtr, WayMap> RelationWayPair;
	typedef std::map<unsigned long long int, RelationWayPair> GlobalMap;

	GlobalMap ret;

	util::Log::GetInstance().info("extracting administrative boundaries");
	RelationMap adminBoundaries = getAdministrativeBoundaries(admin_level);
	util::Log::GetInstance().info("finished extracting administrative boundaries");

	WayMap waysList;
	BOOST_FOREACH(WayType w, ways)
	{
		if(
			w.second->getNodes()->size() > 1 &&
			w.second->hasTag(Element::TAG_HIGHWAY) &&
			Way::highwayTypes.find(w.second->getTag(Element::TAG_HIGHWAY)) != Way::highwayTypes.end()
		)
		{
			waysList[w.second->getId()] = w.second;
		}
	}

	util::Log::GetInstance().info("extracting ways by administrative boundaries");

	RelationMap::iterator boundaryIterator = adminBoundaries.begin();
	while(boundaryIterator != adminBoundaries.end())
	{
		RelationPtr boundary = boundaryIterator->second;
		ret[boundaryIterator->first] = RelationWayPair(boundary, WayMap());
		boundaryIterator++;
	}

	WayMap::iterator wayIterator = waysList.begin();
	while(wayIterator != waysList.end())
	{
		WayPtr way = wayIterator->second;
		boost::shared_ptr<const geos::geom::Geometry> wayGeom = way->toGeometry();

		boundaryIterator = adminBoundaries.begin();
		while(boundaryIterator != adminBoundaries.end())
		{
			RelationPtr boundary = boundaryIterator->second;
			boost::shared_ptr<const geos::geom::prep::PreparedGeometry> boundaryPrepGeom = boundary->toPreparedGeometry();
			if(boundaryPrepGeom->covers(wayGeom.get()) || boundaryPrepGeom->intersects(wayGeom.get()))
			{
				//the way is inside or intersected by the boundary, keep it
				ret[boundaryIterator->first].second[wayIterator->first] = way;
				//mark the nodes of this way for next step reference counting
				way->referenceWithNodes();
				break;
			}
			else //no interaction with current boundary
				boundaryIterator++;
		}
		++wayIterator;
	}

   util::Log::GetInstance().info("finished extracting ways by administrative boundaries");

   return ret;
}
예제 #6
0
void MapCropper::apply(shared_ptr<OsmMap>& map)
{
  LOG_INFO("Cropping map.");
  shared_ptr<OsmMap> result = map;

  if (MapReprojector::isGeographic(map) == false && _nodeBounds.isNull() == false)
  {
    throw HootException("If the node bounds is set the projection must be geographic.");
  }

  // @todo visit the elements from the most senior (e.g. relation that has no parents) to the
  // most junior (nodes).

  // go through all the ways
  const WayMap ways = result->getWays();
  for (WayMap::const_iterator it = ways.begin(); it != ways.end(); it++)
  {
    const shared_ptr<Way>& w = it->second;
    shared_ptr<LineString> ls = ElementConverter(map).convertToLineString(w);
    const Envelope& e = *(ls->getEnvelopeInternal());

    // if the way is completely outside the region we're keeping
    if (_isWhollyOutside(e))
    {
      // remove the way
      result->removeWayFully(w->getId());
    }
    else if (_isWhollyInside(e))
    {
      // keep the way
    }
    else
    {
      // do an expensive operation to decide how much to keep, if any.
      _cropWay(result, w->getId());
    }
  }

  shared_ptr<NodeToWayMap> n2wp = result->getIndex().getNodeToWayMap();
  NodeToWayMap& n2w = *n2wp;

  LOG_INFO("  Removing nodes...");

  // go through all the nodes
  const OsmMap::NodeMap nodes = result->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nodes.constBegin(); it != nodes.constEnd(); it++)
  {
    const Coordinate& c = it.value()->toCoordinate();

    bool nodeInside = false;

    if (_envelope.isNull() == false)
    {
      if (_invert == false)
      {
        nodeInside = _envelope.covers(c);
      }
      else
      {
        nodeInside = !_envelope.covers(c);
      }
    }
    else
    {
      auto_ptr<Point> p(GeometryFactory::getDefaultInstance()->createPoint(c));

      if (_invert == false)
      {
        nodeInside = _envelopeG->intersects(p.get());
      }
      else
      {
        nodeInside = !_envelopeG->intersects(p.get());
      }
    }

    // if the node is outside
    if (!nodeInside)
    {
      // if the node is within the limiting bounds.
      if (_nodeBounds.isNull() == true || _nodeBounds.contains(c))
      {
        // if the node is not part of a way
        if (n2w.find(it.key()) == n2w.end())
        {
          // remove the node
          result->removeNodeNoCheck(it.value()->getId());
        }
      }
    }
  }

  RemoveEmptyRelationsVisitor v;
  map->visitRw(v);
}