Example #1
0
/*!

*/
double
Segment2D::dist( const Vector2D & p ) const
{
    double len = this->length();

    if ( len == 0.0 )
    {
        return origin().dist( p );
    }

    const Vector2D vec = terminal() - origin();
    const double prod = vec.innerProduct( p - origin() );

    //
    // A: p1 - p0
    // A: p - p0
    //
    // check if 0 <= |B|cos(theta) <= |A|
    //       -> 0 <= |A||b|cos(theta) <= |A|^2
    //       -> 0 <= A.B <= |A|^2  // A.B = |A||B|cos(theta)
    //
    if ( 0.0 <= prod && prod <= len * len )
    {
        // return perpendicular distance
        //return std::fabs( Triangle2D( *this, p ).doubleSignedArea() / len );
        return std::fabs( Triangle2D::double_signed_area( origin(), terminal(), p ) / len );
    }

    return std::sqrt( std::min( origin().dist2( p ),
                                terminal().dist2( p ) ) );
}
Example #2
0
/*!

*/
Vector2D
Segment2D::projection( const Vector2D & p ) const
{
    Vector2D dir = terminal() - origin();
    double len = dir.r();

    if ( len < EPSILON )
    {
        return origin();
    }

    dir /= len; // normalize

    double d = dir.innerProduct( p - origin() );
    if ( -EPSILON < d && d < len + EPSILON )
    {
        dir *= d;
        return Vector2D( origin() ) += dir;
    }

    return Vector2D::INVALIDATED;

#if 0
    Line2D my_line = this->line();
    Vector2D sol = my_line.projection( p );

    if ( ! sol.isValid()
         || ! this->contains( sol ) )
    {
        return Vector2D::INVALIDATED;
    }

    return sol;
#endif
}
Example #3
0
/*!

*/
Vector2D
Segment2D::nearestPoint( const Vector2D & p ) const
{
    const Vector2D vec = terminal() - origin();

    const double len_square = vec.r2();

    if ( len_square == 0.0 )
    {
        return origin();
    }


    double inner_product = vec.innerProduct( (p - origin()) );

    //
    // A: p1 - p0
    // B: p - p0
    //
    // check if 0 <= |B|cos(theta) <= |A|
    //       -> 0 <= |A||B|cos(theta) <= |A|^2
    //       -> 0 <= A.B <= |A|^2  // A.B = |A||B|cos(theta)
    //
    if ( inner_product <= 0.0 )
    {
        return origin();
    }
    else if ( inner_product >= len_square )
    {
        return terminal();
    }

    return origin() + vec * inner_product / len_square;
}