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++; } } } }
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(); }
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()); }
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()); }
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; }
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")); }
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(); } }
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); } } } }
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()); }
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()); } } }
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; }
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; }
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) ); } }
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>(); }
*/ 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;