static inline void apply(Collection& collection, Range const& range) { if (boost::size(range) < 2) { return; } typedef typename boost::range_iterator<Range const>::type iterator; bool first = true; iterator it = boost::begin(range); for (iterator prev = it++; it != boost::end(range); prev = it++) { typename boost::range_value<Collection>::type v; v.x = get<0>(*prev); v.y = get<1>(*prev); v.dx = get<0>(*it) - v.x; v.dy = get<1>(*it) - v.y; v.dx_0 = v.dx; v.dy_0 = v.dy; // Normalize the vector -> this results in points+direction // and is comparible between geometries calculation_type magnitude = sqrt( boost::numeric_cast<calculation_type>(v.dx * v.dx + v.dy * v.dy)); // Avoid non-duplicate points (AND division by zero) if (magnitude > 0) { v.dx /= magnitude; v.dy /= magnitude; // Avoid non-direction changing points if (first || ! v.same_direction(collection.back())) { collection.push_back(v); } first = false; } } // TODO: if first one has same direction as last one, remove first one... }
static inline void apply(Collection& collection, Range const& range) { if (boost::size(range) < 2) { return; } typedef typename boost::range_size<Collection>::type collection_size_t; collection_size_t c_old_size = boost::size(collection); typedef typename boost::range_iterator<Range const>::type iterator; bool first = true; iterator it = boost::begin(range); for (iterator prev = it++; it != boost::end(range); prev = it++) { typename boost::range_value<Collection>::type v; v.x = get<0>(*prev); v.y = get<1>(*prev); v.dx = get<0>(*it) - v.x; v.dy = get<1>(*it) - v.y; v.dx_0 = v.dx; v.dy_0 = v.dy; // Normalize the vector -> this results in points+direction // and is comparible between geometries calculation_type magnitude = math::sqrt( boost::numeric_cast<calculation_type>(v.dx * v.dx + v.dy * v.dy)); // Avoid non-duplicate points (AND division by zero) if (magnitude > 0) { v.dx /= magnitude; v.dy /= magnitude; // Avoid non-direction changing points if (first || ! v.same_direction(collection.back())) { collection.push_back(v); } first = false; } } // If first one has same direction as last one, remove first one collection_size_t collected_count = boost::size(collection) - c_old_size; if ( collected_count > 1 ) { typedef typename boost::range_iterator<Collection>::type c_iterator; c_iterator first = range::pos(collection, c_old_size); if ( first->same_direction(collection.back()) ) { //collection.erase(first); // O(1) instead of O(N) *first = collection.back(); collection.pop_back(); } } }