// file: $USFS/class/polygon/v1.0/polygon_inside_0.cc
//

// isip include files
//
#include "polygon.h"
#include "polygon_constants.h"

// define macros used for comparing two expressions
// 
#define MIN(a,b) ((a) < (b) ? (a):(b))
#define MAX(a,b) ((a) > (b) ? (a):(b))

// method: is_inside_cc
//
// arguments:
//  int_4 x_val: (input) coordinate of x for the pixel being tested
//  int_4 y_val: (input) coordinate of y for the pixel being tested
//
// return:
//  a logical_1 value indicating if the pixel is inside the polygon or not
//
// this method determines if a point is inside a polygon or not.
// we use the following strategy: loop through all edges of the polygon,
// count the number of the edges that intersect a ray extending vertically
// upwards from the point to infinity. if the intersection number is odd,
// then the point is inside the polygon. this method is lifted from the
// following tk program: double TkPolygonToPoint(polyPtr, numPoints, pointPtr)
//
logical_1 Polygon::is_inside_cc(int_4 x_val_a, int_4 y_val_a) {

  // declare local variables
  //
  int_4 intersections = 0;	
  logical_1 inside_polygon = ISIP_FALSE;

  for (int_4 count = 0; count < num_vertices_d; count++) {

    int_4 vertex1_x = vertices_d[count * 2];
    int_4 vertex1_y = vertices_d[count * 2 + 1];
    int_4 vertex2_x = vertices_d[(count * 2 + 2) % (num_vertices_d * 2)];
    int_4 vertex2_y = vertices_d[(count * 2 + 3) % (num_vertices_d * 2)];
          
    if (vertex1_x == vertex2_x) {

      // vertical edge
      // only check if the point is on the edge
      // if so, no need to continue the program
      //
      if ((x_val_a == vertex1_x)
	  && (y_val_a >= MIN(vertex1_y, vertex2_y))
	  && (y_val_a <= MAX(vertex1_y, vertex2_y))) {

	inside_polygon = ISIP_TRUE;

	// exit gracefully
	//
	return inside_polygon;
      }
    }
    else {

      // parameters for the current edge
      // assume a line equation of the form y = m1 * x + b1
      //
      float_8 m1 = (float_8)(vertex2_y - vertex1_y)
	           / (float_8)(vertex2_x - vertex1_x);
      float_8 b1 = vertex1_y - m1 * vertex1_x;

      // the projection of the point on the edge
      //
      float_8 y = (m1 * x_val_a + b1);
	    
      if ((y > y_val_a)
	  && (x_val_a >= MIN(vertex1_x, vertex2_x))
	  && (x_val_a < MAX(vertex1_x, vertex2_x))) {
	
	// the point is below the edge
	//
	intersections++;
      }
      else if ((y == (float_8)y_val_a)
	       && (x_val_a >= MIN(vertex1_x, vertex2_x))
	       && (x_val_a <= MAX(vertex1_x, vertex2_x))) {

	// the point is on the edge
	//
	inside_polygon = ISIP_TRUE;

	// exit gracefully
	//
	return inside_polygon;
      }	       
    }
  }

  // if the number of intersections is odd, the point is inside the polygon
  //
  if (intersections & 0x1) {
    inside_polygon = ISIP_TRUE;
  }

  // exit gracefully
  //
  return inside_polygon;
}
