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) );
    }
  }
Ejemplo n.º 2
0
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));
  }
}
Ejemplo n.º 3
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);
}