Opened 9 years ago

Closed 3 years ago

#9768 closed Bugs (duplicate)

difference of multi-polygon and box returns multi-polygon with redundant points

Reported by: Volker Schöch <vschoech@…> Owned by: Barend Gehrels
Milestone: To Be Determined Component: geometry
Version: Boost 1.56.0 Severity: Problem
Keywords: difference, multi-polygon, polygon, box, unique Cc:

Description

boost::geometry::difference should not add redundant points to a polygon. In the following example I subtract an empty box from a polygon, and the result ends up representing the empty box even though obviously it should not. My polygon type is oriented counter-clockwise and not closed, my point type is based on int.

This is the data used as input to difference:

_TPolygon<int> const polygon =
	_TPolygon<int>( "MULTIPOLYGON(((249 509,5103 509,5103 3566,249 3566)))" )
	- _TRect<int>( "POLYGON((1220 1019,1220 1019,1220 1019,1220 1019,1220 1019))" );

This is the resulting multi-polygon, with the additional/redundant empty box:

MULTIPOLYGON(((249 509,5103 509,5103 3566,249 3566),(1220 1019,1220 1019,1220 1019)))

This is my code that wraps boost::geometry to implement the operator used above:

template<typename T>
template<typename Geometry>
_TPolygon< T > _TPolygon< T >::operator-(Geometry geometry) const
{
	_TPolygon< T > polygonOut;
	boost::geometry::difference(*this, geometry, polygonOut);
	
	// the following line fixes the problem but should not be necessary
	//boost::geometry::unique( polygonOut );

	return polygonOut;
}

These are the traits as defined to use _TRect<...> as a boost::geometry box:

namespace boost { namespace geometry { namespace traits {

	template<typename T>
	struct tag< _TRect<T> >
	{
		typedef box_tag type;
	};

	template<typename T>
	struct point_type< _TRect<T> >
	{
		typedef _TPoint<T> type;
	};

	template<typename T, std::size_t Dimension>
	struct indexed_access< _TRect<T>, min_corner, Dimension >
	{
		typedef typename geometry::coordinate_type< _TPoint<T> >::type coordinate_type;

		static inline coordinate_type get(_TRect<T> const& rect)
		{
			return geometry::get<Dimension>( rect.TopLeft() );
		}

		static inline void set(_TRect<T>& rect, coordinate_type const& value)
		{
			geometry::set<Dimension>( rect.TopLeft(), value );
		}
	};

	template<typename T, std::size_t Dimension>
	struct indexed_access< _TRect<T>, max_corner, Dimension >
	{
		typedef typename geometry::coordinate_type< _TPoint<T> >::type coordinate_type;

		static inline coordinate_type get(_TRect<T> const& rect)
		{
			return geometry::get<Dimension>( rect.BottomRight() );
		}

		static inline void set(_TRect<T>& rect, coordinate_type const& value)
		{
			geometry::set<Dimension>( rect.BottomRight(), value );
		}
	};

} } } // namespace boost::geometry::traits

Change History (2)

comment:1 by vschoech@…, 8 years ago

Version: Boost 1.55.0Boost 1.56.0

Originally filed for 1.55.0, still present in 1.56.0.

comment:2 by Barend Gehrels, 3 years ago

Resolution: duplicate
Status: newclosed
Note: See TracTickets for help on using tickets.