Skip to content

Commit

Permalink
Fix RelateNG IM for empty-nonempty cases
Browse files Browse the repository at this point in the history
  • Loading branch information
dr-jts committed Oct 11, 2024
1 parent 29a4c7e commit face089
Show file tree
Hide file tree
Showing 3 changed files with 1,177 additions and 14 deletions.
18 changes: 14 additions & 4 deletions src/operation/relateng/TopologyComputer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,16 @@ TopologyComputer::addPointOnPointExterior(bool isGeomA, const CoordinateXY* pt)

/* public */
void
TopologyComputer::addPointOnGeometry(bool isA, Location locTarget, int dimTarget, const CoordinateXY* pt)
TopologyComputer::addPointOnGeometry(bool isPointA, Location locTarget, int dimTarget, const CoordinateXY* pt)
{
(void)pt;
updateDim(isA, Location::INTERIOR, locTarget, Dimension::P);
//-- update entry for Point interior
updateDim(isPointA, Location::INTERIOR, locTarget, Dimension::P);

//-- an empty geometry has no points to infer entries from
if (getGeometry(! isPointA).isEmpty())
return;

switch (dimTarget) {
case Dimension::P:
return;
Expand All @@ -323,8 +329,8 @@ TopologyComputer::addPointOnGeometry(bool isA, Location locTarget, int dimTarget
* If a point intersects an area target, then the area interior and boundary
* must extend beyond the point and thus interact with its exterior.
*/
updateDim(isA, Location::EXTERIOR, Location::INTERIOR, Dimension::A);
updateDim(isA, Location::EXTERIOR, Location::BOUNDARY, Dimension::L);
updateDim(isPointA, Location::EXTERIOR, Location::INTERIOR, Dimension::A);
updateDim(isPointA, Location::EXTERIOR, Location::BOUNDARY, Dimension::L);
return;
}
throw IllegalStateException("Unknown target dimension: " + std::to_string(dimTarget));
Expand All @@ -339,6 +345,10 @@ TopologyComputer::addLineEndOnGeometry(bool isLineA, Location locLineEnd, Locati
//-- record topology at line end point
updateDim(isLineA, locLineEnd, locTarget, Dimension::P);

//-- an empty geometry has no points to infer entries from
if (getGeometry(! isLineA).isEmpty())
return;

//-- Line and Area targets may have additional topology
switch (dimTarget) {
case Dimension::P:
Expand Down
59 changes: 49 additions & 10 deletions tests/unit/operation/relateng/RelateNGTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,20 +839,21 @@ void object::test<60> ()

//================ Empty Geometries ==============

std::string empties[] = {
"POINT EMPTY",
"LINESTRING EMPTY",
"POLYGON EMPTY",
"MULTIPOINT EMPTY",
"MULTILINESTRING EMPTY",
"MULTIPOLYGON EMPTY",
"GEOMETRYCOLLECTION EMPTY"
};

//-- test equals against all combinations of empty geometries
template<>
template<>
void object::test<61> ()
{
std::string empties[] = {
"POINT EMPTY",
"LINESTRING EMPTY",
"POLYGON EMPTY",
"MULTIPOINT EMPTY",
"MULTILINESTRING EMPTY",
"MULTIPOLYGON EMPTY",
"GEOMETRYCOLLECTION EMPTY"
};
int nempty = 7;
for (int i = 0; i < nempty; i++) {
for (int j = 0; j < nempty; j++) {
Expand All @@ -862,13 +863,51 @@ void object::test<61> ()
checkEquals(a, b, true);
}
}
}

// testEmptyNonEmpty
template<>
template<>
void object::test<62> ()
{
std::string nonEmptyPoint = "POINT (1 1)";
std::string nonEmptyLine = "LINESTRING (1 1, 2 2)";
std::string nonEmptyPolygon = "POLYGON ((1 1, 1 2, 2 1, 1 1))";

for (int i = 0; i < 7; i++) {
std::string empty = empties[i];

checkRelate(empty, nonEmptyPoint, "FFFFFF0F2");
checkRelate(nonEmptyPoint, empty, "FF0FFFFF2");

checkRelate(empty, nonEmptyLine, "FFFFFF102");
checkRelate(nonEmptyLine, empty, "FF1FF0FF2");

checkRelate(empty, nonEmptyPolygon, "FFFFFF212");
checkRelate(nonEmptyPolygon, empty, "FF2FF1FF2");

checkEquals(empty, nonEmptyPoint, false);
checkEquals(empty, nonEmptyLine, false);
checkEquals(empty, nonEmptyPolygon, false);

checkIntersectsDisjoint(empty, nonEmptyPoint, false);
checkIntersectsDisjoint(empty, nonEmptyLine, false);
checkIntersectsDisjoint(empty, nonEmptyPolygon, false);

checkContainsWithin(empty, nonEmptyPoint, false);
checkContainsWithin(empty, nonEmptyLine, false);
checkContainsWithin(empty, nonEmptyPolygon, false);

checkContainsWithin(nonEmptyPoint, empty, false);
checkContainsWithin(nonEmptyLine, empty, false);
checkContainsWithin(nonEmptyPolygon, empty, false);
}
}

// Prepared test
template<>
template<>
void object::test<62> ()
void object::test<63> ()
{
std::string a = "POLYGON((0 0, 1 0, 1 1, 0 1, 0 0))";
std::string b = "POLYGON((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))";
Expand Down
Loading

0 comments on commit face089

Please sign in to comment.