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) ); } }
v8::Handle<v8::Value> PoiMergerJs::jsPoiMerge(const v8::Arguments& args) { HandleScope scope; try{ if (args.Length() != 2) { return v8::ThrowException(HootExceptionJs::create(IllegalArgumentException( "Expected exactly two arguments to 'poiMerge'."))); } // Argument 1: script -- note second param is directory to search under (~/hoot/rules) const QString scriptPath = ConfPath::search(toCpp<QString>(args[0]), "rules"); // Argument 2: Map with POIs OsmMapJs* mapJs = node::ObjectWrap::Unwrap<OsmMapJs>(args[1]->ToObject()); // Pull out internal POI map OsmMapPtr map( mapJs->getMap() ); // Instantiate script merger shared_ptr<PluginContext> script(new PluginContext()); v8::HandleScope handleScope; v8::Context::Scope context_scope(script->getContext()); script->loadScript(scriptPath, "plugin"); v8::Handle<v8::Object> global = script->getContext()->Global(); if (global->Has(String::New("plugin")) == false) { return v8::ThrowException(HootExceptionJs::create(IllegalArgumentException( "Expected the script to have exports."))); } v8::Handle<v8::Value> pluginValue = global->Get(String::New("plugin")); v8::Persistent<v8::Object> plugin = v8::Persistent<v8::Object>::New(v8::Handle<v8::Object>::Cast(pluginValue)); if (plugin.IsEmpty() || plugin->IsObject() == false) { return v8::ThrowException(HootExceptionJs::create(IllegalArgumentException( "Expected plugin to be a valid object."))); } // Got in Map with POIs A, B, C, D, E // // Make a set of pairs to indicate all are same object: // A->B, A->C, A->D, A->E // // ...then pass those pairs one at a time through the merger, since it only merges pairs OsmMap::NodeMap nodes = map->getNodeMap(); OsmMapPtr mergedMap(map); const ElementId firstId = ElementId::node((*(nodes.constBegin()))->getId()); //LOG_DEBUG("First ID: " << firstId.getId()); for (OsmMap::NodeMap::const_iterator it = nodes.constBegin() + 1; it != nodes.constEnd(); ++it) { const boost::shared_ptr<const Node>& n = it.value(); std::set< std::pair< ElementId, ElementId> > matches; matches.insert(std::pair<ElementId,ElementId>(firstId, ElementId::node(n->getId()))); // Now create scriptmerger, and invoke apply method which will apply apply merge transformation, reducing the POIs down to one ScriptMerger merger(script, plugin, matches); OsmMapPtr mergedMap(map); std::vector< std::pair< ElementId, ElementId > > replacedNodes; merger.apply(mergedMap, replacedNodes ); if ( replacedNodes.size() == 1 ) { /* LOG_DEBUG("POI merge: replacing node #" << replacedNodes[0].first.getId() << " with updated version of node #" << replacedNodes[0].second.getId() ); */ mergedMap->replaceNode(replacedNodes[0].first.getId(), replacedNodes[0].second.getId()); } } // Hand merged POIs back to caller in OsmMap v8::Handle<v8::Object> returnMap = OsmMapJs::create(mergedMap); return scope.Close(returnMap); } catch ( const HootException& e ) { return v8::ThrowException(HootExceptionJs::create(e)); } }
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); }