static inline bool projection_on_segment(Point const& subject, Point const& p, Point const& q)
    {
        typedef Point vector_type;
        typedef typename geometry::coordinate_type<Point>::type coordinate_type;

        vector_type v = q;
        vector_type w = subject;
        subtract_point(v, p);
        subtract_point(w, p);

        coordinate_type const zero = coordinate_type();
        coordinate_type const c1 = dot_product(w, v);

        if (c1 < zero)
        {
            return false;
        }
        coordinate_type const c2 = dot_product(v, v);
        if (c2 < c1)
        {
            return false;
        }

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

        /* 
            Algorithm [p1: (x1,y1), p2: (x2,y2), p: (px,py)]
            VECTOR v(x2 - x1, y2 - y1)
            VECTOR w(px - x1, py - y1)
            c1 = w . v
            c2 = v . v
            b = c1 / c2
            RETURN POINT(x1 + b * vx, y1 + b * vy)
        */

        // v is multiplied below with a (possibly) FP-value, so should be in FP
        // For consistency we define w also in FP
        fp_vector_type v, w;

        geometry::convert(p2, v);
        geometry::convert(p, w);
        subtract_point(v, p1);
        subtract_point(w, p1);

        Strategy strategy;
        boost::ignore_unused_variable_warning(strategy);

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

        // See above, c1 > 0 AND c2 > c1 so: c2 != 0
        fp_type const b = c1 / c2;

        fp_strategy_type fp_strategy
            = strategy::distance::services::get_similar
                <
                    Strategy, Point, fp_point_type
                >::apply(strategy);

        fp_point_type projected;
        geometry::convert(p1, projected);
        multiply_value(v, b);
        add_point(projected, v);

        //std::cout << "distance " << dsv(p) << " .. " << dsv(projected) << std::endl;

        return fp_strategy.apply(p, projected);
    }
    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);

    }
static inline Vector create_vector(Point1 const& p1, Point2 const& p2)
{
    Vector v;
    convert(p1, v);
    subtract_point(v, p2);
    return v;
}
                inline bool operator()(const segment<const PS>& s, state_type& state) const
                {
                    /* Algorithm:
                    For each segment:
                    begin
                        dx = x2 - x1;
                        dy = y2 - y1;
                        sx = x2 + x1;
                        sy = y2 + y1;
                        mx = dx * sy;
                        my = sx * dy;

                        sum_mx += mx;
                        sum_my += my;
                        sum_msx += mx * sx;
                        sum_msy += my * sy;
                    end;
                    return POINT(0.5 * sum_msx / sum_mx, 0.5 * sum_msy / sum_my);
                    */

                    PS diff = s.second, sum = s.second;
                    subtract_point(diff, s.first);
                    add_point(sum, s.first);

                    // We might create an arithmatic operation for this.
                    PS m;
                    get<0>(m) = get<0>(diff) * get<1>(sum);
                    get<1>(m) = get<0>(sum) * get<1>(diff);

                    add_point(state.sum_m, m);
                    multiply_point(m, sum);
                    add_point(state.sum_ms, m);

                    return true;
                }
Exemple #7
0
inline void experimental_elliptic_plane(Point3d const& p1, Point3d const& p2,
                                        Point3d & v1, Point3d & v2,
                                        Point3d & origin, Point3d & normal,
                                        Spheroid const& spheroid)
{
    typedef typename coordinate_type<Point3d>::type coord_t;

    Point3d xy1 = projected_to_xy(p1, spheroid);
    Point3d xy2 = projected_to_xy(p2, spheroid);

    // origin = (xy1 + xy2) / 2
    origin = xy1;
    add_point(origin, xy2);
    multiply_value(origin, coord_t(0.5));

    // v1 = p1 - origin
    v1 = p1;
    subtract_point(v1, origin);
    // v2 = p2 - origin
    v2 = p2;
    subtract_point(v2, origin);

    normal = cross_product(v1, v2);
}
Exemple #8
0
static inline int elliptic_side_value(Point3d1 const& origin, Point3d1 const& norm, Point3d2 const& pt)
{
    typedef typename coordinate_type<Point3d1>::type calc_t;
    calc_t c0 = 0;

    // vector oposite to pt - origin
    // only for the purpose of assigning origin
    Point3d1 vec = origin;
    subtract_point(vec, pt);

    calc_t d = dot_product(norm, vec);

    // since the vector is opposite the signs are opposite
    return math::equals(d, c0) ? 0
        : d < c0 ? 1
        : -1; // d > 0
}