geometry icon indicating copy to clipboard operation
geometry copied to clipboard

Will overlay operations handle spikes?

Open gigimava opened this issue 5 years ago • 6 comments

In a past private email exchange, @barendgehrels mentioned it was planned that all overlay operations would be able to handle spikes (including, in particular, intersection against a degenerated box).

I see that's not the case yet, in boost 1.72.0 Is this feature still on its way, or has it been scrapped?

gigimava avatar Mar 12 '20 12:03 gigimava

I don't remember the context, and I can't see from your nickname who you are, so I can't look up our conversation.

In general spikes are handled, already for several versions, but there are some exceptions.

If you have a case where it is not handled correctly, you're welcome to create an issue including the WKT of the inputs.

barendgehrels avatar Apr 15 '20 11:04 barendgehrels

I'm sorry, my previous message was too vague. I contacted you after reading this (now ancient) exchange with my collegue https://lists.boost.org/geometry/2014/11/3249.php

We were having issues when subtracting a degenerated box from a (OGC valid) polygon. From boost's documentation, I could get the following

  • boost::geometry::difference (1.59.0) requires its two operands to be OGC-valid : http://www.boost.org/doc/libs/1_59_0/libs/geometry/doc/html/geometry/reference/concepts/concept_polygon.html
  • a degenerated box is (in terms of OGC) a polygon consisting of a single spike. Meaning it’s not a legitimate input to difference.
  • difference is able to handle empty geometries, but the concept of emptiness is defined in terms of the set of points. So, a degenerated box is not empty (in fact, boost::geometry::is_empty will always return false for boxes) http://www.boost.org/doc/libs/1_59_0/libs/geometry/doc/html/geometry/reference/algorithms/is_empty.html

So, at that point, it was clearly our responsibility to make sure we were not passing degenerated boxes to boost::geometry::difference.

In response, you mentioned that you were planning to make all overlay operations handle spikes, which should include degenerated rectangles.

Fast forward to now, with boost 1.73.0, I get the following

int main()
{
	using point = boost::geometry::model::point<int, 2, boost::geometry::cs::cartesian>;
	using polygon = boost::geometry::model::polygon<point>;
	using box = boost::geometry::model::box<point>;
	using multipolygon = boost::geometry::model::multi_polygon<polygon>;

	polygon poly;
	boost::geometry::read_wkt("POLYGON((0 0,0 4,4 4,4 0,0 0))", poly);

	{
		box b;
		boost::geometry::read_wkt("BOX(0 1,4 2)", b);

		multipolygon mpolyResult;
		boost::geometry::difference(poly, b, mpolyResult);
		// MULTIPOLYGON(((0 2,0 4,4 4,4 2,0 2)),((0 1,4 1,4 0,0 0,0 1)))
		std::cout << boost::geometry::wkt(mpolyResult) << std::endl;
	}

	{
		box b;
		boost::geometry::read_wkt("BOX(0 2,4 2)", b);

		multipolygon mpolyResult;
		boost::geometry::difference(poly, b, mpolyResult);
		// Actual:   MULTIPOLYGON()
		// Expected: MULTIPOLYGON((0 0,0 4,4 4,4 0,0 0))
		std::cout << boost::geometry::wkt(mpolyResult) << std::endl;
	}

	{
		polygon polySubtract;
		boost::geometry::read_wkt("POLYGON((0 2,4 2,0 2))", polySubtract);

		multipolygon mpolyResult;
		boost::geometry::difference(poly, polySubtract, mpolyResult);
		// Actual:   MULTIPOLYGON()
		// Expected: MULTIPOLYGON((0 0,0 4,4 4,4 0,0 0))
		std::cout << boost::geometry::wkt(mpolyResult) << std::endl;
	}

	{
		polygon polySubtract;
		boost::geometry::read_wkt("POLYGON((0 2,4 2,0 2))", polySubtract);
		boost::geometry::remove_spikes(polySubtract);

		multipolygon mpolyResult;
		boost::geometry::difference(poly, polySubtract, mpolyResult);
		// MULTIPOLYGON((0 0,0 4,4 4,4 0,0 0))
		std::cout << boost::geometry::wkt(mpolyResult) << std::endl;
	}

	return 0;
}

This leads me back to the question: can I expect that, at some point, difference will handle degenerated boxes? Or have I misunderstood the meaning of "handle", and you deem the current behavior to be appropriate?

gigimava avatar May 27 '20 11:05 gigimava

The problem is still not fixed in boost 1.73.0.

vschoech avatar Jun 17 '20 11:06 vschoech

Apparently, we must still pre-process degenerated boxes so that we do not pass them to boost::geometry::difference(...), in boost 1.79.0.

vschoech avatar Jul 08 '22 14:07 vschoech

⚠️ Still the same behavior in boost 1.83.0.

vschoech avatar Aug 28 '23 13:08 vschoech