예제 #1
0
void Network::consolidateWays(bool discard_if_missing_reference) {
   std::map<unsigned long long int, WayPtr>::iterator wayIt = ways.begin();
   //loop through the ways
   while(wayIt != ways.end()) {
      WayPtr way = wayIt->second;
      try {
         way->consolidate(this);
         wayIt++;
      } catch(RefNotFoundException e) {
         //the way references a node that doesn't exist
         if(discard_if_missing_reference) {
            //discard relations referencing this way
            std::map<unsigned long long int,RelationPtr>::iterator relIt = relations.begin();
            while(relIt != relations.end()) {
               if(relIt->second->contains(way)) {
                  relations.erase(relIt++);
               } else {
                  relIt++;
               }
            }

            //discard the way
            std::map<unsigned long long int,WayPtr>::iterator way_to_delete = wayIt++;
            ways.erase(way_to_delete);
         } else {
            wayIt++;
         }
      }
   }
}
예제 #2
0
  void runEscapeTags()
  {
    OsmMapPtr map(new OsmMap());
    Coordinate coords[] = { Coordinate(0, 0), Coordinate(0, 1), Coordinate(1, 1), Coordinate(1, 0), Coordinate::getNull() };
    Tags tags;
    tags.set("note", "<2>");
    tags.set("aerialway", "t-bar");
    tags.set("first name", "first name goes here");
    tags.set("full_name", "\"Hacksaw\" Jim Duggan");
    WayPtr way = TestUtils::createWay(map, Status::Unknown1, coords);
    way->setTags(tags);

    QList<ElementPtr> nodes;
    NodePtr node1(new Node(Status::Unknown1, map->createNextNodeId(), Coordinate(0.0, 0.1), 15));
    node1->getTags().appendValue("name", "test1");
    nodes.append(node1);

    NodePtr node2(new Node(Status::Unknown1, map->createNextNodeId(), Coordinate(0.1, 0.0), 15));
    node2->getTags().appendValue("name", "test2");
    nodes.append(node2);

    RelationPtr relation = TestUtils::createRelation(map, nodes);
    relation->setType("review");
    relation->getTags().appendValue("name", "Test Review");
    std::vector<RelationData::Entry> members = relation->getMembers();
    members[0].role = "reviewee";
    members[1].role = "reviewee";
    relation->setMembers(members);

    QString output = OsmPgCsvWriter::toString(map);
    //  Compare the results
    HOOT_STR_EQUALS(expected_runEscapeTags, output);
  }
  void runReadByBoundsTest()
  {
    insertDataForBoundTest();

    OsmApiDb database;
    database.open(ServicesDbTestUtils::getOsmApiDbUrl());
    OsmApiDbReader reader;
    reader.open(ServicesDbTestUtils::getOsmApiDbUrl().toString());
    OsmMapPtr map(new OsmMap());

    reader.setBoundingBox("-88.1,28.91,-88.0,28.89");
    reader.read(map);

    //quick check to see if the element counts are off...consult the test output for more detail

    //All but two of the seven nodes should be returned.  There are five nodes outside of the
    //requested bounds, one of them is referenced by a way within the bounds and the other three by a
    //relation within the bounds.  The nodes not returned is outside of the requested bounds and not
    //reference by any other element.
    CPPUNIT_ASSERT_EQUAL(5, (int)map->getNodes().size());
    //Two of the five ways should be returned.  The ways not returned contain nodes
    //that are out of bounds.
    CPPUNIT_ASSERT_EQUAL(2, (int)map->getWays().size());
    //Two of the six relations should be returned.  The relations not returned contain all
    //members that are out of bounds.
    CPPUNIT_ASSERT_EQUAL(2, (int)map->getRelations().size());

    // Verify timestamps look OK
    WayPtr pWay = map->getWays().begin()->second;
    CPPUNIT_ASSERT(0 != pWay->getTimestamp());


    //Need to remove timestamps, otherwise they cause issues with the compare
    QList<ElementAttributeType> types;
    types.append(ElementAttributeType(ElementAttributeType::Timestamp));
    RemoveAttributesVisitor attrVis(types);
    map->visitRw(attrVis);

    TestUtils::mkpath("test-output/io/ServiceOsmApiDbReaderTest");
    MapProjector::projectToWgs84(map);
    OsmMapWriterFactory::write(map,
      "test-output/io/ServiceOsmApiDbReaderTest/runReadByBoundsTest.osm");
    HOOT_STR_EQUALS(
      TestUtils::readFile("test-files/io/ServiceOsmApiDbReaderTest/runReadByBoundsTest.osm"),
      TestUtils::readFile("test-output/io/ServiceOsmApiDbReaderTest/runReadByBoundsTest.osm"));

    //just want to make sure I can read against the same data twice in a row w/o crashing and also
    //make sure I don't get the same result again for a different bounds
    reader.setBoundingBox("-1,-1,1,1");
    map.reset(new OsmMap());
    reader.read(map);

    CPPUNIT_ASSERT_EQUAL(0, (int)map->getNodes().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getWays().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getRelations().size());

    reader.close();
  }
예제 #4
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());
}
예제 #5
0
bool WayMergeManipulation::_directConnect(const OsmMapPtr& map, WayPtr w) const
{
  boost::shared_ptr<LineString> ls = ElementConverter(map).convertToLineString(w);

  CoordinateSequence* cs = GeometryFactory::getDefaultInstance()->getCoordinateSequenceFactory()->
    create(2, 2);

  cs->setAt(map->getNode(w->getNodeId(0))->toCoordinate(), 0);
  cs->setAt(map->getNode(w->getLastNodeId())->toCoordinate(), 1);

  // create a straight line and buffer it
  boost::shared_ptr<LineString> straight(GeometryFactory::getDefaultInstance()->createLineString(cs));
  boost::shared_ptr<Geometry> g(straight->buffer(w->getCircularError()));

  // is the way in question completely contained in the buffer?
  return g->contains(ls.get());
}
예제 #6
0
WayPtr GeometryConverter::convertLineStringToWay(const LineString* ls,
  const OsmMapPtr& map, Status s, double circularError)
{
  WayPtr way;
  if (ls->getNumPoints() > 0)
  {
    Coordinate c = ls->getCoordinateN(0);
    way.reset(new Way(s, map->createNextWayId(), circularError));

    for (size_t i = 0; i < ls->getNumPoints(); i++)
    {
      c = ls->getCoordinateN(i);
      way->addNode(_createNode(map, c, s, circularError)->getId());
    }
    map->addWay(way);
  }

  return way;
}
예제 #7
0
boost::shared_ptr<Element> GeometryConverter::convertPolygonToElement(const Polygon* polygon,
  const OsmMapPtr& map, Status s, double circularError)
{
  // if the geometry is empty.
  if (polygon->isEmpty())
  {
    return boost::shared_ptr<Element>();
  }
  else if (polygon->getNumInteriorRing() == 0)
  {
    WayPtr result = convertLineStringToWay(polygon->getExteriorRing(), map, s, circularError);
    result->getTags()["area"] = "yes";
    return result;
  }
  else
  {
    return convertPolygonToRelation(polygon, map, s, circularError);
  }
}
  void runCaseSensitiveTest()
  {
    OsmMap::resetCounters();
    shared_ptr<OsmMap> map(new OsmMap());
    Coordinate coords[] = { Coordinate(0.0, 0.0), Coordinate(100.0, 0.0),
                            Coordinate(100.0, 10.0), Coordinate(0.0, 10.0),
                            Coordinate::getNull() };
    WayPtr way = TestUtils::createWay(map, Status::Unknown1, coords, 15);
    way->getTags().appendValue("name", "test");
    way->getTags().appendValue("name", "TEST");

    DuplicateNameRemover dupeNameRemover;
    dupeNameRemover.setCaseSensitive(true);
    dupeNameRemover.apply(map);

    CPPUNIT_ASSERT_EQUAL(1, (int)map->getWays().size());
    const Tags& tags = map->getWay(way->getElementId())->getTags();
    CPPUNIT_ASSERT_EQUAL(1, tags.size());
    CPPUNIT_ASSERT_EQUAL(QString("test;TEST"), tags.get("name"));
  }
예제 #9
0
MultiLineStringLocation PertyWaySplitVisitor::_calcSplitPoint(ConstRelationPtr relation,
                                                              ElementId& wayId) const
{
  const vector<RelationData::Entry>& members = relation->getMembers();
  LOG_VART(members.size());

  //find the way to split on
  boost::uniform_int<> randomWayIndexDistribution(0, members.size() - 1);
  int wayIndex = randomWayIndexDistribution(*_rng);
  wayId = members.at(wayIndex).getElementId();
  LOG_VART(wayIndex);
  LOG_VART(wayId);
  ElementPtr element = _map->getElement(wayId);
  if (element->getElementType() != ElementType::Way)
  {
    throw HootException(
      "PERTY feature splitting for multi-line string relations may only occur on relations which contain only ways.");
  }
  WayPtr way = boost::dynamic_pointer_cast<Way>(element);
  LOG_VART(way->getNodeCount());

  //calculate the split point
  WayLocation wayLocation = _calcSplitPoint(way);
  //return it, if its valid
  if (wayLocation.isValid())
  {
    return
      MultiLineStringLocation(
        _map->shared_from_this(),
        relation,
        wayIndex,
        wayLocation);
  }
  //otherwise, return an empty location
  else
  {
    return MultiLineStringLocation();
  }
}
예제 #10
0
void WayMergeManipulation::_removeSpans(OsmMapPtr map,
  set<ElementId>& impactedElements) const
{
  WayPtr left = map->getWay(_left);
  WayPtr right = map->getWay(_right);

  set<ElementId> impactedWaysTmp = impactedElements;
  for (set<ElementId>::iterator it = impactedWaysTmp.begin(); it != impactedWaysTmp.end(); ++it)
  {
    ElementId eid = *it;
    WayPtr w = map->getWay(eid.getId());
    long first = w->getNodeId(0);
    long last = w->getLastNodeId();
    if ((left->hasNode(first) && right->hasNode(last)) ||
        (left->hasNode(last) && right->hasNode(first)))
    {
      if (_directConnect(map, w))
      {
        RemoveWayOp::removeWay(map, eid.getId());
        impactedElements.erase(eid);
      }
    }
  }
}
예제 #11
0
double WayMergeManipulation::_calculateExpertProbability(ConstOsmMapPtr map) const
{
  OsmMapPtr theMap(new OsmMap());
  CopyMapSubsetOp(map,
               ElementId(ElementType::Way, _left),
               ElementId(ElementType::Way, _right)).apply(theMap);

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

  // use the maximal nearest subline code to find the best subline
  WayPtr mnsLeft = MaximalNearestSubline::getMaximalNearestSubline(theMap, left, right,
    _minSplitSize, left->getCircularError() + right->getCircularError());
  if (mnsLeft == 0)
  {
    return 0.0;
  }
  WayPtr mnsRight = MaximalNearestSubline::getMaximalNearestSubline(theMap, right, mnsLeft,
    _minSplitSize, left->getCircularError() + right->getCircularError());
  if (mnsRight == 0)
  {
    return 0.0;
  }

  // what portion of the original lines is the MNS
  double pl = ElementConverter(theMap).convertToLineString(mnsLeft)->getLength() /
      ElementConverter(theMap).convertToLineString(left)->getLength();
  double pr = ElementConverter(theMap).convertToLineString(mnsRight)->getLength() /
      ElementConverter(theMap).convertToLineString(right)->getLength();

  // give it a score
  double ps = std::min(pl, pr) / 2.0 + 0.5;

  double p;

  // if either of the lines are zero in length.
  if (pl == 0 || pr == 0)
  {
    p = 0.0;
  }
  else
  {
    p = ps * ProbabilityOfMatch::getInstance().expertProbability(theMap, mnsLeft, mnsRight);
  }

  return p;
}
  void verifyFullReadOutput(OsmMapPtr map)
  {
    //nodes
    CPPUNIT_ASSERT_EQUAL(2, (int)map->getNodes().size());
    HOOT_STR_EQUALS(true, map->containsNode(1));
    NodePtr node = map->getNode(1);
    CPPUNIT_ASSERT_EQUAL((long)1, node->getId());
    CPPUNIT_ASSERT_EQUAL(38.4, node->getY());
    CPPUNIT_ASSERT_EQUAL(-106.5, node->getX());
    CPPUNIT_ASSERT_EQUAL(15.0, node->getCircularError());
    CPPUNIT_ASSERT_EQUAL(2, node->getTags().size());

    NodePtr node1 = map->getNode(2);
    CPPUNIT_ASSERT_EQUAL((long)2, node1->getId());
    CPPUNIT_ASSERT_EQUAL(38.0, node1->getY());
    CPPUNIT_ASSERT_EQUAL(-104.0, node1->getX());

    //ways
    HOOT_STR_EQUALS(true, map->containsWay(1));
    WayPtr way = map->getWay(1);
    CPPUNIT_ASSERT_EQUAL((long)1, way->getId());
    CPPUNIT_ASSERT_EQUAL(2, (int)way->getNodeCount());
    CPPUNIT_ASSERT_EQUAL((long)1, way->getNodeId(0));
    CPPUNIT_ASSERT_EQUAL((long)2, way->getNodeId(1));
    CPPUNIT_ASSERT_EQUAL(15.0, way->getCircularError());
    CPPUNIT_ASSERT_EQUAL(1, way->getTags().size());

    //relations
    HOOT_STR_EQUALS(true, map->containsRelation(1));
    RelationPtr relation = map->getRelation(1);
    CPPUNIT_ASSERT_EQUAL((long)1, relation->getId());
    vector<RelationData::Entry> relationData = relation->getMembers();
    CPPUNIT_ASSERT_EQUAL(2, (int)relation->getMembers().size());
    HOOT_STR_EQUALS("wayrole", relationData[0].getRole());
    HOOT_STR_EQUALS("noderole",relationData[1].getRole());
    CPPUNIT_ASSERT_EQUAL(15.0, relation->getCircularError());
  }
예제 #13
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());
    }
  }
}
예제 #14
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;
}
예제 #15
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;
}
예제 #16
0
std::map<unsigned long long int,std::pair<RelationPtr,std::map<unsigned long long int, WayPtr> > > Network::getWalkableWaysByAdminBoundary(int admin_level) {
   std::map<unsigned long long int, std::pair<RelationPtr, std::map<unsigned long long int, WayPtr> > > ret;
   util::Log::GetInstance().info("extracting administrative boundaries");
   std::map<unsigned long long int, RelationPtr> adminBoundaries = getAdministrativeBoundaries(admin_level);
   util::Log::GetInstance().info("finished extracting administrative boundaries");
   std::map<unsigned long long int, WayPtr> walkableWays = getWalkableWays();

   util::Log::GetInstance().info("extracting ways by administrative boundaries");
   /*
   std::map<unsigned long long int,RelationPtr>::iterator boundaryIterator = adminBoundaries.begin();
   while(boundaryIterator != adminBoundaries.end()) {
      RelationPtr boundary = boundaryIterator->second;
      ret[boundaryIterator->first] = std::pair<RelationPtr,std::map<unsigned long long int,WayPtr> >(boundary, std::map<unsigned long long int,WayPtr>());
      boost::shared_ptr<const geos::geom::prep::PreparedGeometry> boundaryPrepGeom =
            boundary->toPreparedGeometry();
      std::map<unsigned long long int,WayPtr>::iterator wayIterator = walkableWays.begin();
      while(wayIterator != walkableWays.end()) {
         WayPtr way = wayIterator->second;
         boost::shared_ptr<const geos::geom::Geometry> wayGeom = way->toGeometry();
         if(boundaryPrepGeom->covers(wayGeom.get())) {
            //the way is inside this boundary, keep it
            ret[boundaryIterator->first].second[wayIterator->first]=way;

            //mark the nodes of this way for next step reference counting
            way->referenceWithNodes();

            //remove way from list to avoid further superfluous geometry computations
            walkableWays.erase(wayIterator++);

         } else if(boundaryPrepGeom->intersects(wayGeom.get())) {
            //the way isn't inside, but intersects, flag it as invalid
            walkableWays.erase(wayIterator++);
            //TODO: log the way
         } else {
            //no interaction with current boundary
            wayIterator++;
         }
      }
      boundaryIterator++;
   }
   */

   std::map<unsigned long long int, RelationPtr>::iterator boundaryIterator = adminBoundaries.begin();
   while(boundaryIterator != adminBoundaries.end()) {
      RelationPtr boundary = boundaryIterator->second;
      ret[boundaryIterator->first] = std::pair<RelationPtr, std::map<unsigned long long int, WayPtr> >(boundary, std::map<unsigned long long int, WayPtr>());
      boundaryIterator++;
   }

   std::map<unsigned long long int,WayPtr>::iterator wayIterator = walkableWays.begin();
   while(wayIterator != walkableWays.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())) {
            //the way is inside this 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 if(boundaryPrepGeom->intersects(wayGeom.get())) {
            //the way isn't inside, but intersects, continue
            break;
            //TODO: log the way
         } else {
            //no interaction with current boundary
            boundaryIterator++;
         }
      }
      ++wayIterator;
   }

   util::Log::GetInstance().info("finished extracting ways by administrative boundaries");
   return ret;
}
  void runPartialReadTest()
  {
    //The differences in tag counts here when compared to
    //ServiceHootApiDbReaderTest::runPartialReadTest are due to differences between the way
    //HootApiDbWriter and OsmApiDbBulkInserter handle metadata tags, which is by design.

    populatePartialMap();

    OsmApiDbReader reader;
    const int chunkSize = 3;
    reader.setMaxElementsPerMap(chunkSize);
    reader.open(ServicesDbTestUtils::getOsmApiDbUrl().toString());
    reader.initializePartial();

    int ctr = 0;
    OsmMapPtr map(new OsmMap());

    //3 nodes

    CPPUNIT_ASSERT(reader.hasMoreElements());
    reader.readPartial(map);
    CPPUNIT_ASSERT_EQUAL(3, (int)map->getNodes().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getWays().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getRelations().size());

    NodePtr node = map->getNode(1);
    CPPUNIT_ASSERT_EQUAL((long)1, node->getId());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getX());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getY());
    CPPUNIT_ASSERT_EQUAL(0, node->getTags().size());

    node = map->getNode(2);
    CPPUNIT_ASSERT_EQUAL((long)2, node->getId());
    CPPUNIT_ASSERT_EQUAL(0.1, node->getX());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getY());
    CPPUNIT_ASSERT_EQUAL(1, node->getTags().size());
    HOOT_STR_EQUALS("n2b", node->getTags().get("noteb"));

    node = map->getNode(3);
    CPPUNIT_ASSERT_EQUAL((long)3, node->getId());
    CPPUNIT_ASSERT_EQUAL(0.2, node->getX());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getY());
    CPPUNIT_ASSERT_EQUAL(1, node->getTags().size());
    HOOT_STR_EQUALS("n3", node->getTags().get("note"));

    ctr++;

    //2 nodes, 1 way

    map.reset(new OsmMap());
    CPPUNIT_ASSERT(reader.hasMoreElements());
    reader.readPartial(map);
    CPPUNIT_ASSERT_EQUAL(2, (int)map->getNodes().size());
    CPPUNIT_ASSERT_EQUAL(1, (int)map->getWays().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getRelations().size());

    node = map->getNode(4);
    CPPUNIT_ASSERT_EQUAL((long)4, node->getId());
    CPPUNIT_ASSERT_EQUAL(0.3, node->getX());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getY());
    CPPUNIT_ASSERT_EQUAL(1, node->getTags().size());
    HOOT_STR_EQUALS("n4", node->getTags().get("note"));

    node = map->getNode(5);
    CPPUNIT_ASSERT_EQUAL((long)5, node->getId());
    CPPUNIT_ASSERT_EQUAL(0.4, node->getX());
    CPPUNIT_ASSERT_EQUAL(0.0, node->getY());
    CPPUNIT_ASSERT_EQUAL(0, node->getTags().size());

    WayPtr way = map->getWay(1);
    CPPUNIT_ASSERT_EQUAL((long)1, way->getId());
    CPPUNIT_ASSERT(way->hasNode(1));
    CPPUNIT_ASSERT(way->hasNode(2));
    CPPUNIT_ASSERT_EQUAL(1, way->getTags().size());
    HOOT_STR_EQUALS("w1b", way->getTags().get("noteb"));

    ctr++;

    //2 ways, 1 relation

    map.reset(new OsmMap());
    CPPUNIT_ASSERT(reader.hasMoreElements());
    reader.readPartial(map);
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getNodes().size());
    CPPUNIT_ASSERT_EQUAL(2, (int)map->getWays().size());
    CPPUNIT_ASSERT_EQUAL(1, (int)map->getRelations().size());

    way = map->getWay(2);
    CPPUNIT_ASSERT_EQUAL((long)2, way->getId());
    CPPUNIT_ASSERT(way->hasNode(2));
    CPPUNIT_ASSERT(way->hasNode(3));
    CPPUNIT_ASSERT_EQUAL(1, way->getTags().size());
    HOOT_STR_EQUALS("w2", way->getTags().get("note"));

    way = map->getWay(3);
    CPPUNIT_ASSERT_EQUAL((long)3, way->getId());
    CPPUNIT_ASSERT(way->hasNode(2));
    CPPUNIT_ASSERT_EQUAL(0, way->getTags().size());

    RelationPtr relation = map->getRelation(1);
    CPPUNIT_ASSERT_EQUAL((long)1, relation->getId());
    CPPUNIT_ASSERT_EQUAL(size_t(2), relation->getMembers().size());
    CPPUNIT_ASSERT(relation->contains(ElementId::node(1)));
    CPPUNIT_ASSERT(relation->contains(ElementId::way(1)));
    RelationData::Entry member = relation->getMembers().at(0);
    HOOT_STR_EQUALS("n1", member.role);
    CPPUNIT_ASSERT_EQUAL((long)1, member.getElementId().getId());
    member = relation->getMembers().at(1);
    HOOT_STR_EQUALS("w1", member.role);
    CPPUNIT_ASSERT_EQUAL((long)1, member.getElementId().getId());
    CPPUNIT_ASSERT_EQUAL(1, relation->getTags().size());
    HOOT_STR_EQUALS("r1", relation->getTags().get("note"));

    ctr++;

    //1 relation

    map.reset(new OsmMap());
    CPPUNIT_ASSERT(reader.hasMoreElements());
    reader.readPartial(map);
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getNodes().size());
    CPPUNIT_ASSERT_EQUAL(0, (int)map->getWays().size());
    CPPUNIT_ASSERT_EQUAL(1, (int)map->getRelations().size());

    relation = map->getRelation(2);
    CPPUNIT_ASSERT_EQUAL((long)2, relation->getId());
    HOOT_STR_EQUALS("", relation->getType());
    CPPUNIT_ASSERT(relation->contains(ElementId::node(2)));
    CPPUNIT_ASSERT_EQUAL(size_t(1), relation->getMembers().size());
    member = relation->getMembers().at(0);
    HOOT_STR_EQUALS("n2", member.role);
    CPPUNIT_ASSERT_EQUAL((long)2, member.getElementId().getId());
    CPPUNIT_ASSERT_EQUAL(0, relation->getTags().size());

    ctr++;

    CPPUNIT_ASSERT(!reader.hasMoreElements());
    reader.finalizePartial();

    CPPUNIT_ASSERT_EQUAL(4, ctr);
  }
  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) );
    }
  }
예제 #19
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>();
}
예제 #20
0
      */
      geos::operation::linemerge::LineMerger lm;
      BOOST_FOREACH(WayPtr w, ways) {
         if(w->getNodes()->size() < 2)
            continue;
         lm.add(w->toGeometry().get());
      }
      std::vector< geos::geom::LineString * > *lss = lm.getMergedLineStrings();
      BOOST_FOREACH(geos::geom::LineString *ls, *lss) {
         if(ls->getNumPoints()>3 && ls->isClosed()) {
            geos::geom::Polygon *p = gf->createPolygon(gf->createLinearRing(ls->getCoordinates()),0);
            ret->push_back(p);
         }
      }
   } else if(ways.size() == 1){
      WayPtr w = ways.front();
      const std::list<std::pair<unsigned long long int,NodePtr> > *nodes = w->getNodes();
      if(nodes->size()>3 && nodes->front().first == nodes->back().first) {
         //we have a closed way, return it
         g = w->toGeometry().get()->clone();
         geos::geom::CoordinateSequence *cs = g->getCoordinates();
         geos::geom::LinearRing *lr = gf->createLinearRing(cs);
         //std::vector<geos::geom::Geometry*>* holes = new std::vector<geos::geom::Geometry*>();

         geos::geom::Polygon *p = gf->createPolygon(lr,NULL);
         ret->push_back(p);
         delete g;
      }
   }

   return ret;