/*****************************************************************************
 *
 * MODULE:       Vector library
 *
 * AUTHOR(S):    Original author CERL, probably Dave Gerdes.
 *               Update to GRASS 5.7 Radim Blazek.
 *
 * PURPOSE:      Lower level functions for reading/writing/manipulating vectors.
 *
 * COPYRIGHT:    (C) 2001 by the GRASS Development Team
 *
 *               This program is free software under the GNU General Public
 *               License (>=v2). Read the file COPYING that comes with GRASS
 *               for details.
 *
 *****************************************************************************/

#include <stdio.h>

/***************************************************************
 * test_for_intersection (ax1,ay1,ax2,ay2,bx1,by1,bx2,by2)
 *   double ax1,ax2,ay1,ay2;
 *   double bx1,bx2,by1,by2;
 *
 * returns
 *   0 no intersection at all
 *   1 the line segments intersect at only one point
 *  -1 the line segments intersect at many points, i.e., overlapping
 *     segments from the same line
 *
 * find_intersection (ax1,ay1,ax2,ay2,bx1,by1,bx2,by2,x,y)
 *   double ax1,ax2,ay1,ay2;
 *   double bx1,bx2,by1,by2;
 *   double *x,*y;
 *
 * returns
 *   0 no intersection
 *   1 x,y set to (unique) intersection
 *  -1 lines overlap, no unique intersection
 *
 * Based on the following:
 *
 *    (ax2-ax1)r1 - (bx2-bx1)r2 = ax2 - ax1
 *    (ay2-ay1)r1 - (by2-by1)r2 = ay2 - ay1
 *
 * Solving for r1 and r2, if r1 and r2 are between 0 and 1,
 * then line segments (ax1,ay1)(ax2,ay2) and (bx1,by1)(bx2,by2)
 * intersect
 ****************************************************************/

#define D  ((ax2 - ax1) * (by1 - by2) - (ay2 - ay1) * (bx1 - bx2))

#define D1 ((bx1 - ax1) * (by1 - by2) - (by1 - ay1) * (bx1 - bx2))

#define D2 ((ax2 - ax1) * (by1 - ay1) - (ay2 - ay1) * (bx1 - ax1))

int dig_test_for_intersection(double ax1, double ay1, double ax2, double ay2,
                              double bx1, double by1, double bx2, double by2)
{
    register double d, d1, d2;
    double t;
    int switched;

    if (ax1 > ax2 || (ax1 == ax2 && ay1 > ay2)) {
        t = ax1;
        ax1 = ax2;
        ax2 = t;

        t = ay1;
        ay1 = ay2;
        ay2 = t;
    }

    if (bx1 > bx2 || (bx1 == bx2 && by1 > by2)) {
        t = bx1;
        bx1 = bx2;
        bx2 = t;

        t = by1;
        by1 = by2;
        by2 = t;
    }

    switched = 0;
    if (bx1 < ax1)
        switched = 1;
    else if (bx1 == ax1) {
        if (bx2 < ax2)
            switched = 1;
        else if (bx2 == ax2) {
            if (by1 < ay1)
                switched = 1;
            else if (by1 == ay1) {
                if (by2 < ay2)
                    switched = 1;
            }
        }
    }

    if (switched) {
        t = ax1;
        ax1 = bx1;
        bx1 = t;
        t = ax2;
        ax2 = bx2;
        bx2 = t;

        t = ay1;
        ay1 = by1;
        by1 = t;
        t = ay2;
        ay2 = by2;
        by2 = t;
    }

    d = D;
    d1 = D1;
    d2 = D2;

    if (d > 0)
        return (d1 >= 0 && d2 >= 0 && d >= d1 && d >= d2);
    if (d < 0)
        return (d1 <= 0 && d2 <= 0 && d <= d1 && d <= d2);

    /* lines are parallel */
    if (d1 || d2)
        return 0;

    /* segments are colinear. check for overlap */

    /* Collinear vertical */
    if (ax1 == ax2) {
        if (ay1 > ay2) {
            t = ay1;
            ay1 = ay2;
            ay2 = t;
        }
        if (by1 > by2) {
            t = by1;
            by1 = by2;
            by2 = t;
        }
        if (ay1 > by2)
            return 0;
        if (ay2 < by1)
            return 0;

        /* there is overlap */

        if (ay1 == by2 || ay2 == by1)
            return 1; /* endpoints only */

        return -1; /* true overlap   */
    }
    else {
        if (ax1 > ax2) {
            t = ax1;
            ax1 = ax2;
            ax2 = t;
        }
        if (bx1 > bx2) {
            t = bx1;
            bx1 = bx2;
            bx2 = t;
        }
        if (ax1 > bx2)
            return 0;
        if (ax2 < bx1)
            return 0;

        /* there is overlap */

        if (ax1 == bx2 || ax2 == bx1)
            return 1; /* endpoints only */

        return -1; /* true overlap   */
    }
    return 0; /* should not be reached */
}

int dig_find_intersection(double ax1, double ay1, double ax2, double ay2,
                          double bx1, double by1, double bx2, double by2,
                          double *x, double *y)
{
    register double d, r1, r2;
    double t;
    int switched;

    if (ax1 > ax2 || (ax1 == ax2 && ay1 > ay2)) {
        t = ax1;
        ax1 = ax2;
        ax2 = t;

        t = ay1;
        ay1 = ay2;
        ay2 = t;
    }

    if (bx1 > bx2 || (bx1 == bx2 && by1 > by2)) {
        t = bx1;
        bx1 = bx2;
        bx2 = t;

        t = by1;
        by1 = by2;
        by2 = t;
    }

    switched = 0;
    if (bx1 < ax1)
        switched = 1;
    else if (bx1 == ax1) {
        if (bx2 < ax2)
            switched = 1;
        else if (bx2 == ax2) {
            if (by1 < ay1)
                switched = 1;
            else if (by1 == ay1) {
                if (by2 < ay2)
                    switched = 1;
            }
        }
    }

    if (switched) {
        t = ax1;
        ax1 = bx1;
        bx1 = t;
        t = ax2;
        ax2 = bx2;
        bx2 = t;

        t = ay1;
        ay1 = by1;
        by1 = t;
        t = ay2;
        ay2 = by2;
        by2 = t;
    }

    d = D;

    if (d) {

        r1 = D1 / d;
        r2 = D2 / d;
        if (r1 < 0 || r1 > 1 || r2 < 0 || r2 > 1) {
            return 0;
        }
        *x = ax1 + r1 * (ax2 - ax1);
        *y = ay1 + r1 * (ay2 - ay1);
        return 1;
    }

    /* lines are parallel */
    if (D1 || D2) {
        return 0;
    }

    /* segments are colinear. check for overlap */

    /* Collinear vertical */
    if (ax1 == ax2) {
        if (ay1 > by2)
            return 0;
        if (ay2 < by1)
            return 0;

        /* there is overlap */

        if (ay1 == by2) {
            *x = ax1;
            *y = ay1;
            return 1; /* endpoints only */
        }
        if (ay2 == by1) {
            *x = ax2;
            *y = ay2;
            return 1; /* endpoints only */
        }

        /* overlap, no single intersection point */
        if (ay1 > by1 && ay1 < by2) {
            *x = ax1;
            *y = ay1;
        }
        else {
            *x = ax2;
            *y = ay2;
        }
        return -1;
    }
    else {
        if (ax1 > bx2)
            return 0;
        if (ax2 < bx1)
            return 0;

        /* there is overlap */

        if (ax1 == bx2) {
            *x = ax1;
            *y = ay1;
            return 1; /* endpoints only */
        }
        if (ax2 == bx1) {
            *x = ax2;
            *y = ay2;
            return 1; /* endpoints only */
        }

        /* overlap, no single intersection point */
        if (ax1 > bx1 && ax1 < bx2) {
            *x = ax1;
            *y = ay1;
        }
        else {
            *x = ax2;
            *y = ay2;
        }
        return -1;
    }

    return 0; /* should not be reached */
}
