
Hi Luke, I'm only now having some time to follow the GTL evolution...
The user must register their type as a polygon set type:
template <> geometry_traits<std::list<UserPolygonType> > { typedef polygon_set_concept geometry_concept; };
This is probably explained somewhere but, could you state what a geometry_traits<T>::geometry_concept is?
Then the user can use their type along with the library provided type to perform set operations through the intuitively overridden c++ logical operators & | ^ -.
template <typename geometry_type_1, typename geometry_type_2> polygon_set_view operator&(const geometry_type_1& geo1, const geometry_type_2& geo2) { ...tag dispatching and so forth... }
tag dispatching (used in this way) won't prevent ambiguity in the overload resolution, so I don't think you should have operators taking just any types.
I also provide some Boolean logic capabilities to move flow control into functional code.
template <typename geometry_type> polygon_set_view operator&(const geometry_type& geo, bool condition) { if(condition) return polygon_set_view(geo); }
else return polygon_set_view(); I presume?
to the user to write code that looks like the following:
std::list<UserPolygonType>* do_something_complex(bool condition1, bool condition2) { std::list<UserPolygonType>* resultPolygons = new std::list<UserPolygonType>; std::vector<rectangle_data> input1; initialize1(input1); std::vector<rectangle_data> input2; initialize2(input2);
//if both condition1 and condition2 are true return the merged //result of the subtraction of input2 from input1 //stored as UserPolygonType into resultPolygons //if condition1 is true and condition2 is false return input1 //merged and stored as UserPolygonType into resultPolygons //if condition1 is false return empty resultPolygons resultPolygons |= ((input1 & condition1) - (input2 & condition2)); //legacy application puts onus on caller to delete resultPolygons return resultPolygons; }
Apart from the fact that the operator declaration needs sme work to avoid ambiguity, this is nice.
Note that I'm using a polygon_set_view to provide lazy evaluation of the scanline algorithm when chaining operations. A polygon_set_view models the polygon_set_concept on the lazily produced result of the operation.
I would like better if the library used a general expression templates framework instead of a custom mechanism so it can be used in much more than just polygon set operations. But then of course, does boost has any of that already?
Because evaluation is lazy, the result of a Boolean operation should be stored to a polygon_set data structure before the arguments go out of scope or are deleted to ensure correct execution.
Checking and proper generation of exceptions for such cases should be provided by the view. Modification of an argument after creating a view from it and before evaluating the view would be an undetectable user error.
How is this ensured in your proposal? I'm inclined to think that the only reliable way to do this is to store the operands via shared_ptr.
This proposed API is the most concise and intuitive way I can think of to provide these algorithms to the library user.
Do you mean the operator syntax or the lazy evaluation? I don't care for the former, but I certainly do for the latter, and to a broader extent. Best Fernando Cacciola