Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

correct intersections for named area (explicitly check them against t… #41

Merged
merged 3 commits into from
Jan 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/osm2rdf/osm/GeometryHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,8 @@ typedef std::vector<osm2rdf::osm::Relation::id_t> RelationRelationList;
// Relation: envelope, osm id, geometry, node list, way list, relation list
#if BOOST_VERSION >= 107800
typedef std::tuple<osm2rdf::geometry::Box, osm2rdf::osm::Way::id_t,
osm2rdf::geometry::Relation, RelationNodeList, RelationWayList,
RelationRelationList>
osm2rdf::geometry::Relation, RelationNodeList,
RelationWayList, RelationRelationList>
SpatialRelationValue;
#endif // BOOST_VERSION >= 107800

Expand Down Expand Up @@ -344,7 +344,9 @@ class GeometryHandler {

std::string areaNS(AreaFromType type) const;

void writeTransitiveClosure(const std::vector<osm2rdf::osm::Area::id_t>& successors, const std::string& entryIRI, const std::string& rel);
void writeTransitiveClosure(
const std::vector<osm2rdf::osm::Area::id_t>& successors,
const std::string& entryIRI, const std::string& rel, bool symmetric);

void getBoxIds(
const osm2rdf::geometry::Area& area, const osm2rdf::geometry::Area& inner,
Expand Down
118 changes: 103 additions & 15 deletions src/osm/GeometryHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -722,13 +722,16 @@ void GeometryHandler<W>::dumpNamedAreaRelations() {
std::cerr << std::endl;
std::cerr << currentTimeFormatted() << " Dumping relations from DAG with "
<< _directedAreaGraph.getNumEdges() << " edges and "
<< _directedAreaGraph.getNumVertices() << " vertices ... "
<< _directedAreaGraph.getNumVertices()
<< " vertices and calculation intersect relationships... "
<< std::endl;

osm2rdf::util::ProgressBar progressBar{_directedAreaGraph.getNumVertices(),
true};
size_t entryCount = 0;
progressBar.update(entryCount);
GeomRelationStats intersectStats;

std::vector<DirectedGraph<Area::id_t>::entry_t> vertices =
_directedAreaGraph.getVertices();
#pragma omp parallel for shared( \
Expand All @@ -738,15 +741,21 @@ void GeometryHandler<W>::dumpNamedAreaRelations() {
osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA, \
osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_AREA, \
osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA, \
progressBar, entryCount) default(none) schedule(static)
progressBar, entryCount) \
reduction(+ : intersectStats) default(none) schedule(static)
for (size_t i = 0; i < vertices.size(); i++) {
const auto id = vertices[i];
const auto& entry = _spatialStorageArea[_spatialStorageAreaIndex[id]];
const auto& entryId = std::get<1>(entry);
const auto& entryObjId = std::get<3>(entry);
const auto& entryFromType = std::get<5>(entry);
std::string entryIRI =
_writer->generateIRI(areaNS(entryFromType), entryObjId);

// all areas we can skip via the DAG
SkipSet skip;

// contains relations, simply dump the DAG
for (const auto& dst : _directedAreaGraph.getEdges(id)) {
assert(_spatialStorageAreaIndex[dst] < _spatialStorageArea.size());
const auto& area = _spatialStorageArea[_spatialStorageAreaIndex[dst]];
Expand All @@ -758,21 +767,86 @@ void GeometryHandler<W>::dumpNamedAreaRelations() {

_writer->writeTriple(areaIRI, IRI__OSM2RDF_CONTAINS_AREA, entryIRI);
_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_AREA, entryIRI);
_writer->writeTriple(entryIRI, IRI__OSM2RDF_INTERSECTS_AREA, areaIRI);

// transitive closure
const auto& successors = _directedAreaGraph.findSuccessorsFast(areaId);

writeTransitiveClosure(successors, entryIRI,
IRI__OSM2RDF_INTERSECTS_AREA);
writeTransitiveClosure(successors, entryIRI, IRI__OSM2RDF_CONTAINS_AREA);
skip.insert(areaId);
skip.insert(successors.begin(), successors.end());

writeTransitiveClosure(successors, entryIRI, IRI__OSM2RDF_INTERSECTS_AREA,
true);
writeTransitiveClosure(successors, entryIRI, IRI__OSM2RDF_CONTAINS_AREA,
false);
}

// intersect relation, use R-Tree
const auto& queryResult = indexQryIntersect(entry);

for (const auto& areaRef : queryResult) {
const auto& area = _spatialStorageArea[areaRef.second];
const auto& areaId = std::get<1>(area);
const auto& areaObjId = std::get<3>(area);
const auto& areaFromType = std::get<5>(area);

intersectStats.checked();

// don't compare to itself
if (areaId == entryId) continue;

GeomRelationInfo geomRelInf;

const auto& areaIRI =
_writer->generateIRI(areaNS(areaFromType), areaObjId);

if (skip.find(areaId) != skip.end()) {
geomRelInf.intersects = YES;
intersectStats.skippedByDAG();
} else if (areaIntersectsArea(entry, area, &geomRelInf,
&intersectStats)) {
const auto& successors = _directedAreaGraph.findSuccessorsFast(areaId);
skip.insert(successors.begin(), successors.end());

// transitive closure
writeTransitiveClosure(successors, entryIRI,
IRI__OSM2RDF_INTERSECTS_AREA, true);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_AREA, entryIRI);
_writer->writeTriple(entryIRI, IRI__OSM2RDF_INTERSECTS_AREA, areaIRI);
}
}

#pragma omp critical(progress)
progressBar.update(entryCount++);
}

progressBar.done();

std::cerr << currentTimeFormatted() << " ... done" << std::endl;
std::cerr << currentTimeFormatted() << " ... done.\n"
<< osm2rdf::util::formattedTimeSpacer << " checked "
<< intersectStats.printTotalChecks()
<< " area/area pairs A, B for intersect\n"
<< osm2rdf::util::formattedTimeSpacer << " decided "
<< intersectStats.printSkippedByDAG() << " by DAG\n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printSkippedByBox()
<< " by non-intersecting bounding boxes \n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printSkippedByBoxIdIntersect()
<< " by box id intersect\n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printSkippedByBoxIdIntersectCutout()
<< " by check against box id cutout\n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printSkippedByInner()
<< " by inner simplified geom\n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printSkippedByOuter()
<< " by outer simplified geom\n"
<< osm2rdf::util::formattedTimeSpacer << " "
<< intersectStats.printFullChecks() << " by full geometric check"
<< std::endl;
}

// ____________________________________________________________________________
Expand Down Expand Up @@ -858,10 +932,12 @@ void GeometryHandler<W>::dumpUnnamedAreaRelations() {

// transitive closure
writeTransitiveClosure(successors, entryIRI,
IRI__OSM2RDF_INTERSECTS_NON_AREA);
IRI__OSM2RDF_INTERSECTS_NON_AREA, true);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
entryIRI);
_writer->writeTriple(entryIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
areaIRI);
}

if (geomRelInf.intersects == NO) {
Expand All @@ -879,7 +955,7 @@ void GeometryHandler<W>::dumpUnnamedAreaRelations() {

// transitive closure
writeTransitiveClosure(successors, entryIRI,
IRI__OSM2RDF_CONTAINS_NON_AREA);
IRI__OSM2RDF_CONTAINS_NON_AREA, false);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_CONTAINS_NON_AREA,
entryIRI);
Expand Down Expand Up @@ -1055,13 +1131,16 @@ GeometryHandler<W>::dumpNodeRelations() {

// transitive closure
writeTransitiveClosure(successors, nodeIRI,
IRI__OSM2RDF_INTERSECTS_NON_AREA);
IRI__OSM2RDF_INTERSECTS_NON_AREA, true);
writeTransitiveClosure(successors, nodeIRI,
IRI__OSM2RDF_CONTAINS_NON_AREA);
IRI__OSM2RDF_CONTAINS_NON_AREA, false);

_writer->writeTriple(
areaIRI, osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA,
nodeIRI);
_writer->writeTriple(
nodeIRI, osm2rdf::ttl::constants::IRI__OSM2RDF_INTERSECTS_NON_AREA,
areaIRI);
_writer->writeTriple(
areaIRI, osm2rdf::ttl::constants::IRI__OSM2RDF_CONTAINS_NON_AREA,
nodeIRI);
Expand Down Expand Up @@ -1218,10 +1297,12 @@ void GeometryHandler<W>::dumpWayRelations(

// transitive closure
writeTransitiveClosure(successors, wayIRI,
IRI__OSM2RDF_INTERSECTS_NON_AREA);
IRI__OSM2RDF_INTERSECTS_NON_AREA, true);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
wayIRI);
_writer->writeTriple(wayIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
areaIRI);
} else if (skipNodeContained.find(areaId) != skipNodeContained.end()) {
intersectStats.skippedByNodeContained();
geomRelInf.intersects = YES;
Expand All @@ -1235,10 +1316,12 @@ void GeometryHandler<W>::dumpWayRelations(

// transitive closure
writeTransitiveClosure(successors, wayIRI,
IRI__OSM2RDF_INTERSECTS_NON_AREA);
IRI__OSM2RDF_INTERSECTS_NON_AREA, true);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
wayIRI);
_writer->writeTriple(wayIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
areaIRI);
} else if (wayIntersectsArea(way, area, &geomRelInf, &intersectStats)) {
const auto& successors =
_directedAreaGraph.findSuccessorsFast(areaId);
Expand All @@ -1249,10 +1332,12 @@ void GeometryHandler<W>::dumpWayRelations(

// transitive closure
writeTransitiveClosure(successors, wayIRI,
IRI__OSM2RDF_INTERSECTS_NON_AREA);
IRI__OSM2RDF_INTERSECTS_NON_AREA, true);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
wayIRI);
_writer->writeTriple(wayIRI, IRI__OSM2RDF_INTERSECTS_NON_AREA,
areaIRI);
}

if (geomRelInf.intersects == NO) {
Expand Down Expand Up @@ -1291,7 +1376,7 @@ void GeometryHandler<W>::dumpWayRelations(

// transitive closure
writeTransitiveClosure(successors, wayIRI,
IRI__OSM2RDF_CONTAINS_NON_AREA);
IRI__OSM2RDF_CONTAINS_NON_AREA, false);

_writer->writeTriple(areaIRI, IRI__OSM2RDF_CONTAINS_NON_AREA, wayIRI);
}
Expand Down Expand Up @@ -2471,7 +2556,7 @@ uint8_t GeometryHandler<W>::borderContained(Way::id_t wayId,
template <typename W>
void GeometryHandler<W>::writeTransitiveClosure(
const std::vector<osm2rdf::osm::Area::id_t>& successors,
const std::string& entryIRI, const std::string& rel) {
const std::string& entryIRI, const std::string& rel, bool symmetric) {
// transitive closure
if (_config.writeGeomRelTransClosure) {
for (const auto& succ : successors) {
Expand All @@ -2482,6 +2567,9 @@ void GeometryHandler<W>::writeTransitiveClosure(
_writer->generateIRI(areaNS(succAreaFromType), succAreaId);

_writer->writeTriple(succAreaIRI, rel, entryIRI);
if (symmetric) {
_writer->writeTriple(entryIRI, rel, succAreaIRI);
}
}
}
}
Expand Down
42 changes: 42 additions & 0 deletions tests/osm/GeometryHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,8 @@ TEST(OSM_GeometryHandler, dumpNamedAreaRelationsSimple) {
osmium::memory::Buffer::auto_grow::yes};
osmium::memory::Buffer osmiumBuffer4{initial_buffer_size,
osmium::memory::Buffer::auto_grow::yes};
osmium::memory::Buffer osmiumBuffer5{initial_buffer_size,
osmium::memory::Buffer::auto_grow::yes};
osmium::builder::add_area(osmiumBuffer1, osmium::builder::attr::_id(22),
osmium::builder::attr::_tag("name", "22"),
osmium::builder::attr::_outer_ring({
Expand Down Expand Up @@ -786,21 +788,33 @@ TEST(OSM_GeometryHandler, dumpNamedAreaRelationsSimple) {
{4, {50.1, 0.51}},
{1, {20.0, 0.51}},
}));
osmium::builder::add_area(osmiumBuffer5, osmium::builder::attr::_id(30),
osmium::builder::attr::_tag("name", "30"),
osmium::builder::attr::_outer_ring({
{1, {48.0, 7.51}},
{2, {48.0, 7.71}},
{3, {48.05, 7.71}},
{4, {48.05, 7.51}},
{1, {48.0, 7.51}},
}));

// Create osm2rdf object from osmium object
auto area1 = osm2rdf::osm::Area(osmiumBuffer1.get<osmium::Area>(0));
auto area2 = osm2rdf::osm::Area(osmiumBuffer2.get<osmium::Area>(0));
auto area3 = osm2rdf::osm::Area(osmiumBuffer3.get<osmium::Area>(0));
auto area4 = osm2rdf::osm::Area(osmiumBuffer4.get<osmium::Area>(0));
auto area5 = osm2rdf::osm::Area(osmiumBuffer5.get<osmium::Area>(0));
area1.finalize();
area2.finalize();
area3.finalize();
area4.finalize();
area5.finalize();

gh.area(area1);
gh.area(area2);
gh.area(area3);
gh.area(area4);
gh.area(area5);

gh.flushExternalStorage();
gh.prepareRTree();
Expand Down Expand Up @@ -878,6 +892,24 @@ TEST(OSM_GeometryHandler, dumpNamedAreaRelationsSimple) {
"intersects_area") +
" " +
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, 11)));
ASSERT_THAT(
printedData,
Not(::testing::HasSubstr(
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, 14) +
" " +
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM2RDF,
"contains_area") +
" " +
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, 15))));
ASSERT_THAT(
printedData,
::testing::HasSubstr(
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, 14) +
" " +
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM2RDF,
"intersects_area") +
" " +
writer.generateIRI(osm2rdf::ttl::constants::NAMESPACE__OSM_WAY, 15)));

// Reset std::cerr and std::cout
std::cerr.rdbuf(cerrBufferOrig);
Expand Down Expand Up @@ -1353,7 +1385,9 @@ TEST(OSM_GeometryHandler, dumpUnnamedAreaRelationsSimpleIntersects) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:11 osm2rdf:intersects_nonarea osmrel:15 .\n"
"osmrel:15 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:13 osm2rdf:intersects_nonarea osmrel:15 .\n"
"osmrel:15 osm2rdf:intersects_nonarea osmway:13 .\n"
"osmway:12 osm2rdf:contains_nonarea osmrel:15 .\n",
printedData);

Expand Down Expand Up @@ -1479,6 +1513,7 @@ TEST(OSM_GeometryHandler, dumpUnnamedAreaRelationsSimpleContainsOnly) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:11 osm2rdf:intersects_nonarea osmrel:15 .\n"
"osmrel:15 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:11 osm2rdf:contains_nonarea osmrel:15 .\n",
printedData);

Expand Down Expand Up @@ -1768,6 +1803,7 @@ TEST(OSM_GeometryHandler, dumpNodeRelationsSimpleIntersects) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:13 osm2rdf:intersects_nonarea osmnode:42 .\n"
"osmnode:42 osm2rdf:intersects_nonarea osmway:13 .\n"
"osmway:13 osm2rdf:contains_nonarea osmnode:42 .\n",
printedData);

Expand Down Expand Up @@ -1888,6 +1924,7 @@ TEST(OSM_GeometryHandler, dumpNodeRelationsSimpleContains) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:11 osm2rdf:intersects_nonarea osmnode:42 .\n"
"osmnode:42 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:11 osm2rdf:contains_nonarea osmnode:42 .\n",
printedData);

Expand Down Expand Up @@ -2178,7 +2215,9 @@ TEST(OSM_GeometryHandler, dumpWayRelationsSimpleIntersects) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:11 osm2rdf:intersects_nonarea osmway:42 .\n"
"osmway:42 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:13 osm2rdf:intersects_nonarea osmway:42 .\n"
"osmway:42 osm2rdf:intersects_nonarea osmway:13 .\n"
"osmway:12 osm2rdf:contains_nonarea osmway:42 .\n",
printedData);

Expand Down Expand Up @@ -2300,6 +2339,7 @@ TEST(OSM_GeometryHandler, dumpWayRelationsSimpleContains) {
const std::string printedData = coutBuffer.str();
ASSERT_EQ(
"osmway:11 osm2rdf:intersects_nonarea osmway:42 .\n"
"osmway:42 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:11 osm2rdf:contains_nonarea osmway:42 .\n",
printedData);

Expand Down Expand Up @@ -2585,10 +2625,12 @@ TEST(OSM_GeometryHandler, dumpWayRelationsSimpleContainsWithNodeInfo) {
ASSERT_THAT(
printedData,
::testing::HasSubstr("osmway:11 osm2rdf:intersects_nonarea osmnode:2 .\n"
"osmnode:2 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:11 osm2rdf:contains_nonarea osmnode:2 .\n"));
ASSERT_THAT(
printedData,
::testing::HasSubstr("osmway:11 osm2rdf:intersects_nonarea osmway:42 .\n"
"osmway:42 osm2rdf:intersects_nonarea osmway:11 .\n"
"osmway:11 osm2rdf:contains_nonarea osmway:42 .\n"));

// Reset std::cerr and std::cout
Expand Down