

// Beenish Chaudry
// 274b-ac
// Cross: This program uses computes determinants to figure out whether the two
// line segments provided by the user intersect each other 


//*****************************************************************
//                       SUMMARY:

//  Crossing:
//  a. Proper Crossing: 
//
//     \    /
//      \  /
//       \/
//       /\
//      /  \
//

//  b. Improper Crossing (When three of the end points are collinear)
//
//      |
//      |
//      |--------
//      |
//      | 

//******************************************************************


#include <stdio.h>

// ********* Constants defined

#define DIM 2
#define X 0
#define Y 1

typedef enum {FALSE, TRUE} bool;
typedef float Point[DIM]; /* defines a point in 2D */ 


// ********* Function Declaration

void Welcome(void);       
bool CrossSeg (Point, Point, Point, Point);
bool CrossProp (Point, Point, Point, Point);
bool Between (Point, Point, Point);
bool Collinear (Point, Point, Point);
bool Left (Point, Point, Point);
float Det (Point, Point, Point);


// ********* Main Code

main () {

  Point a, b, c, d;    /* Coordinates of the line segments */
  int n, i= 0, j;      /* various counters */

  Welcome(); /* prints greeting */

  printf ("How many data sets are you going to enter? ");
  scanf ("%d", &n);

  while (i < n) {
    printf ("\nPlease enter the coordinates of point a.\n");
    for (j=0;j<2;j++) scanf ("%f", &a[j]);
    printf ("\nPlease enter the coordinates of point b.\n");
    for (j=0;j<2;j++) scanf ("%f", &b[j]);

    printf ("\nPlease enter the coordinates of point c.\n");
    for (j=0;j<2;j++) scanf ("%f", &c[j]);
    printf ("\nPlease enter the coordinates of point d.\n");
    for (j=0;j<2;j++) scanf ("%f", &d[j]);
    
    if (CrossSeg (a, b, c, d))
      printf ("The segments intersect!\n");
    else
      printf ("The segments do not intersect!\n");

    i++;
  }//end of while

} //end of main code


//******************************************
// Welcome: Prints greeting on the screen
//******************************************

void Welcome () {
    
    printf ("\n************************************************\n");
    printf ("             SEGMENTS CROSS?");
    printf ("\n************************************************\n");
}


//********************************************************
// CrossSeg: Two segments intersect iff they intersect properly,
// or one endpoint of one segment lies between the two endpoints
// of the other segment
//********************************************************

bool CrossSeg (Point a, Point b, Point c, Point d) {

  //if intersection is proper, return true
  if (CrossProp (a, b, c, d))
    return TRUE;
  
  //else if the intersection is improper, return true
  else if (   Between (a, b, c)
           || Between (a, b, d)
           || Between (c, d, a)
           || Between (c, d, b)
          )
    return TRUE;
  else
    return FALSE;

}


//**************************************************************
// CrossProp: This function checks the proper intersection of the 
// segments. Two segments intersect in their interiors, then 
// c and d should be split apart by the line containing ab, ie
// c is on one side and d is on the other, and vice versa.
// It is important to know that no three of the four endpoints are 
// collinear.
//**************************************************************

bool CrossProp (Point a, Point b, Point c, Point d) {

  // if not proper crossing, return false
  if (Collinear (a, b, c) ||
      Collinear (a, b, d) ||
      Collinear (c, d, a) ||
      Collinear (c, d, b) 
      )
  return FALSE;

  return
    (Left (a, b, c) ^ Left (a, b, d)) && 
    (Left (c, d, a) ^ Left (c, d, b));

}


//**************************************************************
// Between: This function allows us to check if the point 
// c lies on the line ab.
// If ab is not vertical, then c lies on ab iff the x coordinate
// of c falls in the interval determined by the x coordinates 
// of a and b. 
// If ab is vertical, then c lies on ab iff the y coordinate of
// c falls in the interval determined by the y coordinates of
// a and b
//***************************************************************

bool Between (Point a, Point b, Point c) {

// we will only check betweenness of c when we know it lies on the
// line containing ab
  if (! Collinear (a, b, c))
    return FALSE;

  // if not vertical, check betweenness on x; else on y
  if (a[X] != b[X])
    return ((a[X] <= c[X]) && (c[X] <= b[X])) ||
           ((a[X] >= c[X]) && (c[X] >= b[X]));

  else
    return ((a[Y] <= c[Y]) && (c[Y] <= b[Y])) ||
           ((a[Y] >= c[Y]) && (c[Y] >= b[Y]));

}


//*******************************************************
// Collinear: This function returns true if all the three 
// points lie on the same line
//*******************************************************

bool Collinear (Point a, Point b, Point c) {

 return Det (a, b, c) == 0;
}


//**************************************************************
// Left: Returns true if the area of the triangle created by the
// three points is positive
//**************************************************************

bool Left (Point a, Point b, Point c) {

  return Det (a, b, c) > 0;
}


//********************************************************
// Det: This function returns the area of the triangle formed
// by the three points
//********************************************************

float Det (Point a, Point b, Point c) {

  return
    (a[X]*b[Y] + a[Y]*c[X] + b[X]*c[Y] - 
     c[X]*b[Y] - a[X]*c[Y] - b[X]*a[Y]);
} 

