inline return_type operator()(P const& p, Segment const& s) const
    {
        assert_dimension_equal<P, Segment>();

        /* Algorithm
        POINT v(x2 - x1, y2 - y1);
        POINT w(px - x1, py - y1);
        c1 = w . v
        c2 = v . v
        b = c1 / c2
        RETURN POINT(x1 + b * vx, y1 + b * vy);
        */

        typedef typename boost::remove_const
        <
            typename point_type<Segment>::type
        >::type segment_point_type;

        segment_point_type v, w;

        // TODO
        // ASSUMPTION: segment
        // SOLVE THIS USING OTHER FUNCTIONS using get<,>
        copy_coordinates(s.second, v);
        copy_coordinates(p, w);
        subtract_point(v, s.first);
        subtract_point(w, s.first);

        Strategy strategy;

        coordinate_type c1 = dot_product(w, v);
        if (c1 <= 0)
        {
            return strategy(p, s.first);
        }
        coordinate_type c2 = dot_product(v, v);
        if (c2 <= c1)
        {
            return strategy(p, s.second);
        }

        // Even in case of char's, we have to turn to a point<double/float>
        // because of the division.
        coordinate_type b = c1 / c2;

        // Note that distances with integer coordinates do NOT work because
        // - the project point is integer
        // - if we solve that, the used distance_strategy cannot handle double points
        segment_point_type projected;
        copy_coordinates(s.first, projected);
        multiply_value(v, b);
        add_point(projected, v);

        return strategy(p, projected);

    }
    inline return_type apply(Point const& p,
                    PointOfSegment const& p1, PointOfSegment const& p2) const
    {
        assert_dimension_equal<Point, PointOfSegment>();

        /* Algorithm
        POINT v(x2 - x1, y2 - y1);
        POINT w(px - x1, py - y1);
        c1 = w . v
        c2 = v . v
        b = c1 / c2
        RETURN POINT(x1 + b * vx, y1 + b * vy);
        */


        // Take here the first point type. It should have a default constructor.
        // That is not required for the second point type.
        Point v, w;

        copy_coordinates(p2, v);
        copy_coordinates(p, w);
        subtract_point(v, p1);
        subtract_point(w, p1);

        Strategy strategy;

        coordinate_type zero = coordinate_type();
        coordinate_type c1 = dot_product(w, v);
        if (c1 <= zero)
        {
            return strategy.apply(p, p1);
        }
        coordinate_type c2 = dot_product(v, v);
        if (c2 <= c1)
        {
            return strategy.apply(p, p2);
        }

        // Even in case of char's, we have to turn to a point<double/float>
        // because of the division.
        typedef typename geometry::select_most_precise<coordinate_type, double>::type divisor_type;
        divisor_type b = c1 / c2;

        // Note that distances with integer coordinates do NOT work because
        // - the project point is integer
        // - if we solve that, the used distance_strategy cannot handle double points
        PointOfSegment projected;
        copy_coordinates(p1, projected);
        multiply_value(v, b);
        add_point(projected, v);

        return strategy.apply(p, projected);

    }
Beispiel #3
0
    static inline void apply(G& geometry, P const& point, int , int )
    {
        typename point_type<G>::type point_type;

        copy_coordinates(point, point_type);
        geometry.push_back(point_type);
    }
Beispiel #4
0
inline bool range_ok(Range const& range, Point& centroid)
{
    std::size_t const n = boost::size(range);
    if (n > 1)
    {
        return true;
    }
    else if (n <= 0)
    {
#if defined(CENTROID_WITH_CATCH)
        throw centroid_exception();
#endif
        return false;
    }
    else // if (n == 1)
    {
        // Take over the first point in a "coordinate neutral way"
        copy_coordinates(range.front(), centroid);
        return false;
    }
    return true;
}
OutputIterator clip_linestring_with_box(Box const& b, Linestring const& linestring,
            OutputIterator out, Strategy const& strategy)
{
    if (boost::begin(linestring) == boost::end(linestring))
    {
        return out;
    }

    typedef typename point_type<OutputLinestring>::type point_type;

    OutputLinestring line_out;

    typedef typename boost::range_const_iterator<Linestring>::type iterator_type;
    iterator_type vertex = boost::begin(linestring);
    for(iterator_type previous = vertex++;
            vertex != boost::end(linestring);
            previous = vertex++)
    {
        point_type p1, p2;
        copy_coordinates(*previous, p1);
        copy_coordinates(*vertex, p2);

        // Clip the segment. Five situations:
        // 1. Segment is invisible, finish line if any (shouldn't occur)
        // 2. Segment is completely visible. Add (p1)-p2 to line
        // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2...
        // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2
        // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2
        //
        // This results in:
        // a. if p1 is clipped, start new line
        // b. if segment is partly or completely visible, add the segment
        // c. if p2 is clipped, end the line

        bool c1 = false;
        bool c2 = false;
        segment<point_type> s(p1, p2);

        if (!strategy.clip_segment(b, s, c1, c2))
        {
            strategy.apply(line_out, out);
        }
        else
        {
            // a. If necessary, finish the line and add a start a new one
            if (c1)
            {
                strategy.apply(line_out, out);
            }

            // b. Add p1 only if it is the first point, then add p2
            if (boost::empty(line_out))
            {
                geometry::append(line_out, p1);
            }
            geometry::append(line_out, p2);

            // c. If c2 is clipped, finish the line
            if (c2)
            {
                strategy.apply(line_out, out);
            }
        }

    }

    // Add last part
    strategy.apply(line_out, out);
    return out;
}
Beispiel #6
0
 static inline void apply(Point const& point, PointCentroid& centroid,
         Strategy const&)
 {
     copy_coordinates(point, centroid);
 }