bool LinearCriterion::isSatisfied(const ConstElementPtr& e) const
{
  bool result = false;

  if (e->getElementType() == ElementType::Node)
  {
    return false;
  }

  const Tags& t = e->getTags();

  if (e->getElementType() == ElementType::Relation)
  {
    ConstRelationPtr r = boost::dynamic_pointer_cast<const Relation>(e);
    result |= r->getType() == MetadataTags::RelationMultilineString();
    result |= r->getType() == MetadataTags::RelationRoute();
    result |= r->getType() == MetadataTags::RelationBoundary();
  }

  for (Tags::const_iterator it = t.constBegin(); it != t.constEnd(); ++it)
  {
    const SchemaVertex& tv = OsmSchema::getInstance().getTagVertex(it.key() + "=" + it.value());
    uint16_t g = tv.geometries;
    if (g & (OsmGeometries::LineString | OsmGeometries::ClosedWay) && !(g & OsmGeometries::Area))
    {
      result = true;
      break;
    }
  }

  return result;
}
void MaximalSublineStringMatcher::_validateElement(const ConstOsmMapPtr& map, ElementId eid) const
{
  ConstElementPtr e = map->getElement(eid);

  if (e->getElementType() == ElementType::Relation)
  {
    ConstRelationPtr r = dynamic_pointer_cast<const Relation>(e);

    if (OsmSchema::getInstance().isMultiLineString(*r) == false)
    {
      throw NeedsReviewException("Internal Error: When matching sublines expected a multilinestring "
        "relation not a " + r->getType() + ".  A non-multilinestring should never be found here.  "
        "Please report this to [email protected]");
    }

    const vector<RelationData::Entry>& entries = r->getMembers();
    for (size_t i = 0; i < entries.size(); i++)
    {
      if (entries[i].getElementId().getType() != ElementType::Way)
      {
        throw NeedsReviewException("MultiLineString relations can only contain ways when matching "
                                   "sublines.");
      }
    }
  }
  if (e->getElementType() == ElementType::Way)
  {
    ConstWayPtr w = dynamic_pointer_cast<const Way>(e);

    if (w->getNodeCount() <= 1)
    {
      throw NeedsReviewException("Internal Error: Attempting to match against a zero length way.");
    }
  }
}
Exemple #3
0
void OsmApiDbSqlChangesetFileWriter::_createNewElement(ConstElementPtr element)
{
  const QString elementTypeStr = element->getElementType().toString().toLower();
  ElementPtr changeElement = _getChangeElement(element);

  //we only grab and assign a new id if we have a new element with a negative id, since we'll be
  //writing this directly to the database and negative ids aren't allowed
  LOG_TRACE("ID before: " << changeElement->getElementId());
  long id;
  if (changeElement->getId() < 0)
  {
    id = _db.getNextId(element->getElementType().getEnum());
  }
  else
  {
    id = changeElement->getId();
  }
  LOG_TRACE("ID after: " << ElementId(changeElement->getElementType(), id));

  changeElement->setId(id);
  changeElement->setVersion(1);
  changeElement->setVisible(true);
  changeElement->setChangeset(_changesetId);
  LOG_TRACE("Creating: " << changeElement->getElementId());

  QString note = "";
  LOG_VART(changeElement->getId());
  LOG_VART(note);
  LOG_VART(changeElement->getVersion());
  QString commentStr = "/* create " + elementTypeStr + " " + QString::number(changeElement->getId());
  commentStr += "*/\n";
  _outputSql.write((commentStr).toUtf8());

  const QString values = _getInsertValuesStr(changeElement);
  _outputSql.write(
    ("INSERT INTO " + elementTypeStr + "s (" + elementTypeStr + "_id, " + values).toUtf8());
  _outputSql.write(("INSERT INTO current_" + elementTypeStr + "s (id, " + values).toUtf8());

  _createTags(changeElement);

  switch (changeElement->getElementType().getEnum())
  {
    case ElementType::Way:
      _createWayNodes(boost::dynamic_pointer_cast<const Way>(changeElement));
      break;
    case ElementType::Relation:
      _createRelationMembers(boost::dynamic_pointer_cast<const Relation>(changeElement));
      break;
    default:
      //node
      break;
  }
}
 static bool isRelated(ConstElementPtr e1, ConstElementPtr e2)
 {
   if (e1->getStatus() != e2->getStatus() &&
       e1->isUnknown() && e2->isUnknown() &&
       OsmSchema::getInstance().isBuilding(e1->getTags(), e1->getElementType()) &&
       OsmSchema::getInstance().isBuilding(e2->getTags(), e2->getElementType()))
   {
     return true;
   }
   else
   {
     return false;
   }
 }
void TranslatedTagCountVisitor::visit(const ConstElementPtr& e)
{
  if (e->getTags().getInformationCount() > 0)
  {
    shared_ptr<Geometry> g = ElementConverter(_map->shared_from_this()).convertToGeometry(e);

    Tags t = e->getTags();
    t["error:circular"] = QString::number(e->getCircularError());
    t["hoot:status"] = e->getStatusString();

    // remove all the empty tags.
    for (Tags::const_iterator it = e->getTags().begin(); it != e->getTags().end(); ++it)
    {
      if (t[it.key()] == "")
      {
        t.remove(it.key());
      }
    }

    QString layerName;
    vector<ScriptToOgrTranslator::TranslatedFeature> f = _translator->translateToOgr(t,
      e->getElementType(), g->getGeometryTypeId());

    // only write the feature if it wasn't filtered by the translation script.
    for (size_t i = 0; i < f.size(); i++)
    {
      _countTags(f[i].feature);
    }
  }
}
bool PoiPolygonMatch::isPoiIsh(ConstElementPtr e)
{
  return e->getElementType() == ElementType::Node &&
    (OsmSchema::getInstance().getCategories(e->getTags()).intersects(
        OsmSchemaCategory::building() | OsmSchemaCategory::poi()) ||
     e->getTags().getNames().size() > 0);
}
Exemple #7
0
Handle<Object> ElementJs::New(ConstElementPtr e)
{
  HandleScope scope;

  Handle<Object> result;

  switch (e->getElementType().getEnum())
  {
  case ElementType::Node:
    {
      ConstNodePtr n = dynamic_pointer_cast<const Node>(e);
      result = NodeJs::New(n);
      break;
    }
  case ElementType::Way:
    {
      ConstWayPtr w = dynamic_pointer_cast<const Way>(e);
      result = WayJs::New(w);
      break;
    }
  case ElementType::Relation:
    {
      ConstRelationPtr r = dynamic_pointer_cast<const Relation>(e);
      result = RelationJs::New(r);
      break;
    }
  default:
    throw IllegalArgumentException("Unexpected element type.");
  }

  return scope.Close(result);
}
void MaximalSublineStringMatcher::_validateElement(const ConstOsmMapPtr& map, ElementId eid) const
{
  ConstElementPtr e = map->getElement(eid);

  if (e->getElementType() == ElementType::Relation)
  {
    ConstRelationPtr r = dynamic_pointer_cast<const Relation>(e);

    if (OsmSchema::getInstance().isMultiLineString(*r) == false)
    {
      throw NeedsReviewException("When matching sublines expected a multilinestring relation not"
                                 " a " + r->getType());
    }

    const vector<RelationData::Entry>& entries = r->getMembers();
    for (size_t i = 0; i < entries.size(); i++)
    {
      if (entries[i].getElementId().getType() != ElementType::Way)
      {
        throw NeedsReviewException("MultiLineString relations can only contain ways when matching "
                                   "sublines.");
      }
    }
  }
}
void PertyRemoveRandomElementVisitor::visit(const ConstElementPtr& e)
{
  boost::uniform_real<> uni(0.0, 1.0);
  if (uni(*_rng) <= _p)
  {
    RecursiveElementRemover(ElementId(e->getElementType(), e->getId())).apply(_map->shared_from_this());
  }
}
 virtual void visit(const ConstElementPtr& e)
 {
   if (e->getElementType() == ElementType::Way)
   {
     WayDiscretizer wd(_map->shared_from_this(), dynamic_pointer_cast<const Way>(e));
     wd.discretize(_spacing, _result);
   }
 }
bool ContainsNodeCriterion::isSatisfied(const ConstElementPtr& e) const
{
  if (e->getElementType() == ElementType::Way)
  {
    ConstWayPtr w = boost::dynamic_pointer_cast<const Way>(e);
    return w->hasNode(_nodeId);
  }
  else if (e->getElementType() == ElementType::Relation)
  {
    ConstRelationPtr r = boost::dynamic_pointer_cast<const Relation>(e);
    return r->contains(ElementId(ElementType::Node, _nodeId));
  }
  else if (e->getElementType() == ElementType::Node)
  {
    ConstNodePtr n = boost::dynamic_pointer_cast<const Node>(e);
    return (n->getId() == _nodeId);
  }
  return false;
}
Exemple #12
0
void OgrWriter::_writePartial(ElementProviderPtr& provider, const ConstElementPtr& e)
{
  if (_translator.get() == 0)
  {
    throw HootException("You must call open before attempting to write.");
  }

  if (e->getTags().getInformationCount() > 0)
  {
    // There is probably a cleaner way of doing this.
    // convertToGeometry calls  getGeometryType which will throw an exception if it gets a relation
    // that it doesn't know about. E.g. "route", "superroute", " turnlanes:turns" etc

    shared_ptr<Geometry> g;

    try
    {
      g = ElementConverter(provider).convertToGeometry(e);
    }
    catch (IllegalArgumentException& err)
    {
      LOG_WARN("Error converting geometry: " << err.getWhat() << " (" << e->toString() << ")");
      g.reset((GeometryFactory::getDefaultInstance()->createEmptyGeometry()));
    }

    /*
    LOG_DEBUG("After conversion to geometry, element is now a " <<
             g->getGeometryType() );
    */

    Tags t = e->getTags();
    t["error:circular"] = QString::number(e->getCircularError());
    t["hoot:status"] = e->getStatusString();
    for (Tags::const_iterator it = e->getTags().begin(); it != e->getTags().end(); ++it)
    {
      if (t[it.key()] == "")
      {
        t.remove(it.key());
      }
    }

    vector<ScriptToOgrTranslator::TranslatedFeature> tf = _translator->translateToOgr(t,
      e->getElementType(), g->getGeometryTypeId());

    // only write the feature if it wasn't filtered by the translation script.
    for (size_t i = 0; i < tf.size(); i++)
    {
      OGRLayer* layer = _getLayer(tf[i].tableName);
      if (layer != 0)
      {
        _addFeature(layer, tf[i].feature, g);
      }
    }
  }
}
void DecomposeBuildingRelationsVisitor::visit(const ConstElementPtr& e)
{
  if (e->getElementType() == ElementType::Relation)
  {
    const shared_ptr<Relation>& r = _map->getRelation(e->getId());
    if (r->getType() == "building")
    {
      _decomposeBuilding(r);
    }
  }
}
bool HgisPoiCriterion::isSatisfied(const ConstElementPtr& e) const
{
  bool result = false;
  // See ticket #6853 for a definition of a "HGIS POI"
  if (e->getElementType() == ElementType::Node)
  {
    result =
      OsmSchema::getInstance().hasCategory(e->getTags(), OsmSchemaCategory::hgisPoi().toString());
  }
  return result;
}
Exemple #15
0
void OsmApiDbSqlChangesetFileWriter::_updateExistingElement(ConstElementPtr element)
{
  const QString elementTypeStr = element->getElementType().toString().toLower();
  ElementPtr changeElement = _getChangeElement(element);

  //if another parsed change previously modified the element with this id, we want to get the
  //modified version
  const long currentVersion = changeElement->getVersion();
  const long newVersion = currentVersion + 1;

  changeElement->setVersion(newVersion);
  changeElement->setChangeset(_changesetId);
  changeElement->setVisible(true);
  LOG_TRACE("Updating: " << changeElement->getElementId());

  QString note = "";
  LOG_VART(changeElement->getId());
  LOG_VART(note);
  LOG_VART(changeElement->getVersion());
  QString commentStr = "/* modify " + elementTypeStr + " " + QString::number(changeElement->getId());
  commentStr += "*/\n";
  _outputSql.write((commentStr).toUtf8());

  //<element-name> table contains all version of all elements of that type in a history, so insert
  //into that table.
  _outputSql.write(
    ("INSERT INTO " + elementTypeStr + "s (" + elementTypeStr + "_id, " +
     _getInsertValuesStr(changeElement)).toUtf8());
  //current_<element-name> contains the single latest version of the element, so update that record
  _outputSql.write(
    ("UPDATE current_" + elementTypeStr + "s SET " + _getUpdateValuesStr(changeElement)).toUtf8());

  _deleteCurrentTags(changeElement->getElementId());
  _createTags(changeElement);

  switch (changeElement->getElementType().getEnum())
  {
    case ElementType::Way:
      _deleteAll(ApiDb::getCurrentWayNodesTableName(), "way_id", changeElement->getId());
      _deleteAll(ApiDb::getWayNodesTableName(), "way_id", changeElement->getId());
      _createWayNodes(boost::dynamic_pointer_cast<const Way>(changeElement));
      break;
    case ElementType::Relation:
      _deleteAll(ApiDb::getCurrentRelationMembersTableName(), "relation_id", changeElement->getId());
      _deleteAll(ApiDb::getRelationMembersTableName(), "relation_id", changeElement->getId());
      _createRelationMembers(boost::dynamic_pointer_cast<const Relation>(changeElement));
      break;
    default:
      //node
      break;
  }
}
Exemple #16
0
QString OsmApiDbSqlChangesetFileWriter::_getInsertValuesStr(ConstElementPtr element) const
{
  switch (element->getElementType().getEnum())
  {
    case ElementType::Node:
      return _getInsertValuesNodeStr(boost::dynamic_pointer_cast<const Node>(element));
    case ElementType::Way:
      return _getInsertValuesWayOrRelationStr(element);
    case ElementType::Relation:
      return _getInsertValuesWayOrRelationStr(element);
    default:
      throw HootException("Unknown element type");
  }
}
Exemple #17
0
void KeepBuildingsVisitor::visit(const ConstElementPtr& e)
{
  ElementType type = e->getElementType();
  long id = e->getId();

  if (type != ElementType::Node)
  {
    boost::shared_ptr<Element> ee = _map->getElement(type, id);

    if (BuildingCriterion().isSatisfied(ee->getTags(), type) == false)
    {
      RemoveElementOp::removeElementNoCheck(_map->shared_from_this(), e->getElementId());
    }
  }
}
void KeepBuildingsVisitor::visit(const ConstElementPtr& e)
{
  ElementType type = e->getElementType();
  long id = e->getId();

  if (type != ElementType::Node)
  {
    shared_ptr<Element> ee = _map->getElement(type, id);

    if (OsmSchema::getInstance().isBuilding(ee->getTags(), type) == false)
    {
      // @todo This could do bad things if the element is in use.
      _map->removeElementNoCheck(type, id);
    }
  }
}
Exemple #19
0
void OsmApiDbSqlChangesetFileWriter::_createTags(ConstElementPtr element)
{
  LOG_TRACE("Creating tags for: " << element->getElementId());

  QStringList tableNames = _tagTableNamesForElement(element->getElementId());

  Tags tags = element->getTags();
  if (_includeDebugTags)
  {
    tags.set(MetadataTags::HootStatus(), QString::number(element->getStatus().getEnum()));
  }
  LOG_VART(tags);
  if (element->getElementType().getEnum() == ElementType::Relation && !tags.contains("type"))
  {
    ConstRelationPtr tmp = boost::dynamic_pointer_cast<const Relation>(element);
    tags.appendValue("type", tmp->getType());
  }

  for (Tags::const_iterator it = tags.begin(); it != tags.end(); ++it)
  {
    QString k = it.key();
    QString v = it.value();

    if (k != MetadataTags::HootHash())
    {
      const QString currentTagValues =
      QString("(%1_id, k, v) VALUES (%2, '%3', '%4');\n")
        .arg(element->getElementId().getType().toString().toLower())
        .arg(element->getElementId().getId())
        .arg(k.replace('\'', "''"))
        .arg(v.replace('\'', "''"));

      const QString tagValues =
        QString("(%1_id, k, v, version) VALUES (%2, '%3', '%4', %5);\n")
          .arg(element->getElementId().getType().toString().toLower())
          .arg(element->getElementId().getId())
          .arg(k.replace('\'', "''"))
          .arg(v.replace('\'', "''"))
          .arg(element->getVersion());

      _outputSql.write(
        (QString("INSERT INTO %1 ").arg(tableNames.at(0)) + currentTagValues).toUtf8());
      _outputSql.write((QString("INSERT INTO %1 ").arg(tableNames.at(1)) + tagValues).toUtf8());
    }
  }
}
Exemple #20
0
ElementPtr OsmApiDbSqlChangesetFileWriter::_getChangeElement(ConstElementPtr element)
{
  ElementPtr changeElement;
  switch (element->getElementType().getEnum())
  {
    case ElementType::Node:
      changeElement.reset(new Node(*boost::dynamic_pointer_cast<const Node>(element)));
      break;
    case ElementType::Way:
      changeElement.reset(new Way(*boost::dynamic_pointer_cast<const Way>(element)));
      break;
   case ElementType::Relation:
      changeElement.reset(new Relation(*boost::dynamic_pointer_cast<const Relation>(element)));
      break;
    default:
      throw HootException("Unknown element type");
  }
  return changeElement;
}
void RemoveElementsVisitor::visit(const ConstElementPtr& e)
{
  assert(_filter);
  ElementType type = e->getElementType();
  long id = e->getId();
  const shared_ptr<Element>& ee = _map->getElement(type, id);

  if (_filter->isSatisfied(ee))
  {
    if (_recursive)
    {
      RecursiveElementRemover(ee->getElementId()).apply(_map->shared_from_this());
    }
    else
    {
      _map->removeElement(ElementId(type, id));
    }
  }
}
  bool isMatchCandidate(ConstElementPtr element)
  {
    if (element->getElementType() == ElementType::Node)
    {
      const shared_ptr<const Node>& n(dynamic_pointer_cast<const Node>(element));

      bool inBounds = true;
      // if the bounds is specified, make sure this node is inside the bounds.
      if (_bounds.isNull() == false)
      {
        Coordinate uc = _projectToWgs84(n->toCoordinate());
        inBounds = _bounds.contains(uc);
      }

      if (inBounds && OsmSchema::getInstance().isPoi(*n))
      {
        return true;
      }
    }
    return false;
  }
void RemoveRef2Visitor::visit(const ConstElementPtr& e)
{
  if (!_criterion)
  {
    throw IllegalArgumentException("You must specify a criterion before calling "
                                   "RemoveRef2Visitor.");
  }
  ElementType type = e->getElementType();
  long id = e->getId();
  ElementPtr ee = _map->getElement(ElementId(type, id));

  // if e has a REF2 and meets the criterion
  if (_hasRef2Tag(ee) && _criterion->isSatisfied(ee))
  {
    // go through each REF2 and evaluate for deletion
    for (int i = 0; i < _ref2Keys.size(); i++)
    {
      _checkAndDeleteRef2(ee, _ref2Keys[i]);
    }
  }
}
Meters ElementConverter::calculateLength(const ConstElementPtr &e) const
{
  // Doing length/distance calcs only make sense if we've projected down onto a flat surface
  assert(MapReprojector::isPlanar(_constProvider));

  // if the element is not a point and is not an area.
  // NOTE: Originally I was using isLinear. This was a bit too strict in that it wants evidence of
  // being linear before the length is calculated. Conversely, this wants evidence that is is not
  // linear before it will assume it doesn't have a length.
  if (e->getElementType() != ElementType::Node &&
      OsmSchema::getInstance().isArea(e) == false)
  {
    /// @optimize
    // we don't really need to convert first, we can just loop through the nodes and sum up the
    // distance.
    return convertToGeometry(e)->getLength();
  }
  else
  {
    return 0;
  }
}
  virtual void visit(const ConstElementPtr& e)
  {
    if (e->getElementType() == ElementType::Way)
    {
      const ConstWayPtr& w = boost::dynamic_pointer_cast<const Way>(e);

      vector<long> nodes = w->getNodeIds();
      if (nodes[0] != nodes[nodes.size() - 1])
      {
        nodes.push_back(nodes[0]);
      }

      Coordinate last = _map.getNode(nodes[0])->toCoordinate();
      for (size_t i = 1; i < nodes.size(); i++)
      {
        Coordinate c = _map.getNode(nodes[i])->toCoordinate();
        double distance = c.distance(last);
        double theta = atan2(c.y - last.y, c.x - last.x);
        _h.addAngle(theta, distance);
        last = c;
      }
    }
  }
bool NodeCriterion::isSatisfied(const ConstElementPtr& e) const
{
  return e->getElementType() == ElementType::Node;
}
void ElementCacheLRU::addElement(ConstElementPtr &newElement)
{
  ConstNodePtr newNode;
  ConstWayPtr newWay;
  ConstRelationPtr newRelation;

  switch ( newElement->getElementType().getEnum() )
  {
  case ElementType::Node:
    newNode = dynamic_pointer_cast<const Node>(newElement);
    if ( newNode != ConstNodePtr() )
    {
      // Do we have to replace an entry?
      if ( _nodes.size() == _maxCountPerType )
      {
        _removeOldest(ElementType::Node);
      }

      _nodes.insert(std::make_pair(newNode->getId(),
       std::make_pair(newNode, boost::posix_time::microsec_clock::universal_time())));
        //LOG_DEBUG("Added new node with ID " << newNode->getId() );
    }
    break;
  case ElementType::Way:
    newWay = dynamic_pointer_cast<const Way>(newElement);
    if ( newWay != ConstWayPtr() )
    {
      // Do we have to replace an entry?
      if ( _ways.size() == _maxCountPerType )
      {
        _removeOldest(ElementType::Way);
      }
      _ways.insert(std::make_pair(newWay->getId(),
        std::make_pair(newWay, boost::posix_time::microsec_clock::universal_time())));
    }

    break;
  case ElementType::Relation:
    newRelation = dynamic_pointer_cast<const Relation>(newElement);
    if ( newRelation != ConstRelationPtr() )
    {
      // Do we have to replace an entry?
      if ( _relations.size() == _maxCountPerType )
      {
        _removeOldest(ElementType::Relation);
      }

      _relations.insert(std::make_pair(newRelation->getId(),
        std::make_pair(newRelation, boost::posix_time::microsec_clock::universal_time())));
    }
    break;
  default:
    throw HootException(QString("Unexpected element type: %1").arg(
                          newElement->getElementType().toString()));

    break;
  }

  // Reset all iterators to maintain interface contract
  resetElementIterators();
}
Exemple #28
0
void OsmApiDbSqlChangesetFileWriter::_deleteExistingElement(ConstElementPtr element)
{
  const QString elementIdStr = QString::number(element->getId());
  const QString elementTypeStr = element->getElementType().toString().toLower();
  ElementPtr changeElement = _getChangeElement(element);

  const long currentVersion = changeElement->getVersion();
  const long newVersion = currentVersion + 1;

  changeElement->setVersion(newVersion);
  changeElement->setVisible(false);
  changeElement->setChangeset(_changesetId);
  LOG_TRACE("Deleting: " << changeElement->getElementId());

  QString note = "";
  LOG_VART(changeElement->getId());
  LOG_VART(note);
  LOG_VART(changeElement->getVersion());
  QString commentStr = "/* delete " + elementTypeStr + " " + QString::number(changeElement->getId());
  commentStr += "*/\n";
  _outputSql.write((commentStr).toUtf8());

  //OSM API DB keeps history for all elements, so the existing element in the master table is not
  //modified and a new record is added with the updated version and visible set to false
  _outputSql.write(("INSERT INTO " + elementTypeStr + "s (" + elementTypeStr + "_id, " +
                    _getInsertValuesStr(changeElement)).toUtf8());

  _deleteCurrentTags(changeElement->getElementId());

  switch (changeElement->getElementType().getEnum())
  {
    case ElementType::Node:

      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentWayNodesTableName() +
         " WHERE node_id=" + elementIdStr + ";\n").toUtf8());
      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentRelationMembersTableName() +
         " WHERE member_type = 'Node' AND member_id = " +
         elementIdStr + ";\n").toUtf8());

      break;

    case ElementType::Way:

      //all of its entries in current way nodes are removed
      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentWayNodesTableName() +
         " WHERE way_id=" + elementIdStr + ";\n").toUtf8());
      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentRelationMembersTableName() +
         " WHERE member_type = 'Way' AND member_id = " +
         elementIdStr + ";\n").toUtf8());

      break;

    case ElementType::Relation:

      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentRelationMembersTableName() +
         " WHERE relation_id=" + elementIdStr + ";\n").toUtf8());
      _outputSql.write(
        ("DELETE FROM " + ApiDb::getCurrentRelationMembersTableName() +
         " WHERE member_type = 'Relation' AND member_id = " +
         elementIdStr + ";\n").toUtf8());

      break;

    default:
      throw HootException("Unknown element type");
  }

  //in the current table, the element isn't deleted but set to be invisible
  const QString values =
    QString("changeset_id=%1, visible=%2, version=%3 WHERE id=%4;\n")
      .arg(changeElement->getChangeset())
      .arg(_getVisibleStr(changeElement->getVisible()))
      .arg(changeElement->getVersion())
      .arg(changeElement->getId());
  _outputSql.write(("UPDATE current_" + elementTypeStr + "s SET " + values).toUtf8());
}
 static bool isMatchCandidate(ConstElementPtr element)
 {
   return OsmSchema::getInstance().isBuilding(element->getTags(), element->getElementType());
 }
bool PoiPolygonMatch::isBuildingIsh(ConstElementPtr e)
{
  return OsmSchema::getInstance().isArea(e->getTags(), e->getElementType()) &&
    OsmSchema::getInstance().getCategories(e->getTags()).intersects(
        OsmSchemaCategory::building() | OsmSchemaCategory::poi());
}