Example #1
0
    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();
            }
        }
    }