Пример #1
0
void RubberSheet::applyTransform(shared_ptr<OsmMap>& map)
{
  _map = map;

  if (!_interpolator2to1)
  {
    LOG_WARN("No appropriate interpolator was specified, skipping rubber sheet transform.");
    return;
  }

  if (_projection.get() != 0)
  {
    MapReprojector::reproject(_map, _projection);
  }
  else
  {
    // if it is already planar then nothing will be done.
    MapReprojector::reprojectToPlanar(_map);
  }

  const OsmMap::NodeMap& nm = map->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nm.constBegin(); it != nm.constEnd(); ++it)
  {
    const shared_ptr<Node>& n = it.value();

    if (_ref == false || n->getStatus() == Status::Unknown2)
    {
      Coordinate c = n->toCoordinate();
      Coordinate newC = _translate(c, n->getStatus());

      n->setX(newC.x);
      n->setY(newC.y);
    }
  }
}
  void _buildIndex()
  {
    LOG_DEBUG(SystemInfo::getMemoryUsageString());
    LOG_DEBUG("Creating index. (node count: " << _map->getNodeMap().size() << ")");
    vector<TreeKey> keys;
    vector<long> nids;

    // reserve some space to reduce reallocs
    keys.reserve(_map->getNodeMap().size() * 2);
    nids.reserve(_map->getNodeMap().size() * 2);

    for (OsmMap::NodeMap::const_iterator it = _map->getNodeMap().begin();
         it != _map->getNodeMap().end(); ++it)
    {
      const shared_ptr<const Node>& n = it.value();
      set<QString> allNames = _getNamePermutations(n->getTags().getNames());
      for (set<QString>::iterator it = allNames.begin(); it != allNames.end(); ++it)
      {
        TreeKey tk(n->toCoordinate(), *it);
        keys.push_back(tk);
        nids.push_back(n->getId());
      }
    }

    LOG_DEBUG(SystemInfo::getMemoryUsageString());
    LOG_DEBUG("Calling build index.");
    _index.reset(new hybrid::RFqHybridTree<TreeKey, long, LevenshteinDistance>());
    _index->buildIndex(keys, nids);
    LOG_DEBUG("Built index with " << keys.size() << " keys and " << _map->getNodeMap().size() <<
             " nodes.");
    LOG_DEBUG(SystemInfo::getMemoryUsageString());
  }
Пример #3
0
void WayJoin1Mapper::_map(shared_ptr<OsmMap>& m, HadoopPipes::MapContext& context)
{
  LOG_INFO("Starting map");
  string keyStr;
  string valueStr;
  keyStr.resize(sizeof(int64_t));
  int64_t* key = (int64_t*)keyStr.data();

  // Remove all non-roads.
  m->removeWays(TagFilter(Filter::FilterMatches, "highway", ""));

  Debug::printTroubled(m);

  // emit the node's ID as the key and x/y as the value.
  valueStr.resize(sizeof(ValueNode));
  ValueNode* valueNode = (ValueNode*)valueStr.data();
  const OsmMap::NodeMap& nm = m->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nm.constBegin(); it != nm.constEnd(); ++it)
  {
    const shared_ptr<const Node>& n = it.value();

    *key = n->getId();
    valueNode->x = n->getX();
    valueNode->y = n->getY();
    context.emit(keyStr, valueStr);
  }

  // emit the way's nodes as the key and the way's id as the value.
  valueStr.resize(sizeof(ValueWay));
  ValueWay* valueWay = (ValueWay*)valueStr.data();
  const WayMap& wm = m->getWays();
  for (WayMap::const_iterator it = wm.begin(); it != wm.end(); ++it)
  {
    const shared_ptr<const Way>& w = it->second;

    valueWay->id = w->getId();

    const std::vector<long>& nids = w->getNodeIds();
    for (size_t i = 0; i < nids.size(); i++)
    {
      *key = nids[i];
      context.emit(keyStr, valueStr);
    }
  }
}
Пример #4
0
bool Debug::printTroubled(const shared_ptr<const OsmMap>& map)
{
  bool result = false;
  const OsmMap::NodeMap& nm = map->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nm.constBegin(); it != nm.constEnd(); ++it)
  {
    const shared_ptr<Node>& n = it.value();
    if (isTroubledNode(n->getId()))
    {
      LOG_WARN("Found troubled node: " << n->toString());
      result = true;
    }
  }

  const WayMap& wm = map->getWays();
  for (WayMap::const_iterator it = wm.begin(); it != wm.end(); ++it)
  {
    const shared_ptr<Way>& w = it->second;

    if (isTroubledWay(w->getId()))
    {
      LOG_WARN("Found troubled way: " << w->toString());
      result = true;
    }
    else
    {
      vector<long> troubled;
      const vector<long>& nids = w->getNodeIds();
      for (size_t i = 0; i < nids.size(); i++)
      {
        if (isTroubledNode(nids[i]))
        {
          troubled.push_back(nids[i]);
        }
      }
      if (troubled.size() > 0)
      {
        LOG_WARN("Found a way with troubled node(s): " << w->toString());
        LOG_WARN("  troubled nodes: " << troubled);
        result = true;
      }
    }
  }
  return result;
}
Пример #5
0
void PointsToTracksOp::apply(shared_ptr<OsmMap>& map)
{
  HashMap<QString, deque<long> > trackIdToNid;

  const OsmMap::NodeMap& nm = map->getNodeMap();

  for (OsmMap::NodeMap::const_iterator it = nm.begin(); it != nm.end(); ++it)
  {
    if (it.value()->getTags().contains("hoot:track:id") &&
        it.value()->getTags().contains("hoot:track:seq"))
    {
      QString trackId = it.value()->getTags()["hoot:track:id"];
      trackIdToNid[trackId].push_back(it.key());
    }
  }

  _sortTracks(map, trackIdToNid);
  _createWays(map, trackIdToNid);
}
Пример #6
0
void WayJoin2Mapper::mapOsmMap(shared_ptr<OsmMap> m)
{
  // The first byte on the value says if it is a PBF/WayJoin1Reducer::Value
  PbfWriter writer;

  // Remove all non-roads.
  m->removeWays(TagFilter(Filter::FilterMatches, "highway", ""));

  _key->elementType = NodesType;
  // Go through all the nodes
  const OsmMap::NodeMap& nm = m->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nm.constBegin(); it != nm.constEnd(); ++it)
  {
    // add this node onto a map. Since the nodes aren't very important at this stage we'll just
    // ship a bunch at a time in one big record.
    _emitNode(it.value());
  }

  _key->elementType = WayType;
  // Go through all the ways
  const WayMap& wm = m->getWays();
  for (WayMap::const_iterator it = wm.begin(); it != wm.end(); ++it)
  {
    const shared_ptr<const Way>& w = it->second;

    _key->id = w->getId();
    stringstream ss(stringstream::out);
    pp::DataOutputStream dos(ss);

    //LOG_INFO("Writing way: " << _key->id);

    dos.writeByte(PbfData);
    writer.writePb(w, &ss);

    // Emit the way
    _context->emit(_keyStr, ss.str());
  }
}
Пример #7
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));
  }
}
Пример #8
0
void MergeNearbyNodes::apply(shared_ptr<OsmMap>& map)
{
  LOG_INFO("MergeNearbyNodes start");

  QTime time;
  time.start();

  shared_ptr<OsmMap> wgs84;
  shared_ptr<OsmMap> planar;

  if (MapReprojector::isGeographic(map))
  {
    wgs84 = map;
    planar.reset(new OsmMap(map));
    MapReprojector::reprojectToPlanar(planar);
  }
  else
  {
    planar = map;
    // if we need to check for bounds containment
    if (_bounds.isNull() == false)
    {
      wgs84.reset(new OsmMap(map));
      MapReprojector::reprojectToWgs84(wgs84);
    }
  }

  ClosePointHash cph(_distance);

  const OsmMap::NodeMap& nodes = planar->getNodeMap();
  for (OsmMap::NodeMap::const_iterator it = nodes.begin(); it != nodes.end(); it++)
  {
    const shared_ptr<Node>& n = it.value();
    cph.addPoint(n->getX(), n->getY(), n->getId());
  }

  int mergeCount = 0;
  int count = 0;

  cph.resetIterator();
  while (cph.next())
  {
    const vector<long>& v = cph.getMatch();

    for (size_t i = 0; i < v.size(); i++)
    {
      for (size_t j = 0; j < v.size(); j++)
      {
        if (v[i] != v[j] && map->containsNode(v[i]) && map->containsNode(v[j]))
        {
          const shared_ptr<Node>& n1 = planar->getNode(v[i]);
          const shared_ptr<Node>& n2 = planar->getNode(v[j]);
          double d = calcDistance(n1, n2);
          if (d < _distance && n1->getStatus() == n2->getStatus())
          {
            bool replace = false;
            // if the geographic bounds are not specified.
            if (_bounds.isNull() == true)
            {
              replace = true;
            }
            // if the geographic bounds are specified, then make sure both points are inside.
            else
            {
              const shared_ptr<Node>& g1 = wgs84->getNode(v[i]);
              const shared_ptr<Node>& g2 = wgs84->getNode(v[j]);
              if (_bounds.contains(g1->getX(), g1->getY()) &&
                  _bounds.contains(g2->getX(), g2->getY()))
              {
                replace = true;
              }
            }

            if (replace)
            {
              map->replaceNode(v[j], v[i]);
              mergeCount++;
            }
          }
        }
      }
    }

    if (Log::getInstance().isInfoEnabled() && count % 1000 == 0)
    {
      cout << "MergeNearbyNodes " << count << " " << mergeCount << "    \r";
      cout.flush();
    }
    count++;
  }

  if (Log::getInstance().isInfoEnabled())
  {
    cout << "MergeNearbyNodes " << nodes.size() << " elapsed: " << time.elapsed() << "ms        \n";
  }
}
Пример #9
0
void ShapefileWriter::writePoints(shared_ptr<const OsmMap> map, const QString& path)
{
    OGRRegisterAll();

    _removeShapefile(path);

    const char *pszDriverName = "ESRI Shapefile";
    OGRSFDriver *poDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName(pszDriverName);
    if( poDriver == NULL )
    {
        throw HootException(QString("%1 driver not available.").arg(pszDriverName));
    }

    OGRDataSource* poDS = poDriver->CreateDataSource(path.toAscii(), NULL );
    if( poDS == NULL )
    {
        throw HootException(QString("Data source creation failed. %1").arg(path));
    }

    OGRLayer *poLayer;

    QString layerName;
    layerName = QFileInfo(path).baseName();
    poLayer = poDS->CreateLayer(layerName.toAscii(),
                                map->getProjection().get(), wkbPoint, NULL );
    if( poLayer == NULL )
    {
        throw HootException(QString("Layer creation failed. %1").arg(path));
    }

    QStringList shpColumns;
    QStringList columns = getColumns(map, ElementType::Node);

    for (int i = 0; i < columns.size(); i++)
    {
        OGRFieldDefn oField(columns[i].toAscii(), OFTString);

        oField.SetWidth(64);

        if( poLayer->CreateField( &oField ) != OGRERR_NONE )
        {
            throw HootException(QString("Error creating field (%1).").arg(columns[i]));
        }

        shpColumns.append(poLayer->GetLayerDefn()->GetFieldDefn(i)->GetNameRef());
    }

    if (_includeInfo)
    {
        OGRFieldDefn oField("error_circ", OFTReal);
        if( poLayer->CreateField( &oField ) != OGRERR_NONE )
        {
            throw HootException(QString("Error creating field (error:circular)."));
        }
        _circularErrorIndex = poLayer->GetLayerDefn()->GetFieldCount() - 1;
    }

    const OsmMap::NodeMap& nodes = map->getNodeMap();
    for (OsmMap::NodeMap::const_iterator it = nodes.begin(); it != nodes.end(); ++it)
    {
        const shared_ptr<Node>& node = it.value();

        if (node->getTags().getNonDebugCount() > 0)
        {
            OGRFeature* poFeature = OGRFeature::CreateFeature( poLayer->GetLayerDefn() );
            // set all the column values.
            for (int i = 0; i < columns.size(); i++)
            {
                if (node->getTags().contains(columns[i]))
                {
                    QByteArray c = shpColumns[i].toAscii();
                    QByteArray v = node->getTags()[columns[i]].toAscii();
                    poFeature->SetField(c.constData(), v.constData());
                }
            }

            if (_includeInfo)
            {
                poFeature->SetField(_circularErrorIndex, node->getCircularError());
            }

            // convert the geometry.
            OGRGeometry* geom = new OGRPoint(node->getX(), node->getY());

            if (poFeature->SetGeometryDirectly(geom) != OGRERR_NONE)
            {
                throw HootException(QString("Error setting geometry"));
            }

            if (poLayer->CreateFeature(poFeature) != OGRERR_NONE)
            {
                throw HootException(QString("Error creating feature"));
            }

            OGRFeature::DestroyFeature(poFeature);
        }
    }

    OGRDataSource::DestroyDataSource(poDS);
}
Пример #10
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);
}