/**
 * File          : PointsFour.java
 * Desc          : The four pebble problem
 * Hist
 *   2004-02-22  : @author Douglas Reay
 */

public class PointsFour implements Points {

    Point[] pebbles;
    int mydimensions;
    int mypebbles;
    Space myshape;

    /** Constructor */
    public PointsFour( int numPebbles, int numDimensions, Space shape ) {
        setup( numPebbles, numDimensions, shape );
    }

    /** See interface */
    public void setup( int numPebbles, int numDimensions, Space shape) {
        mydimensions = numDimensions;
        mypebbles = numPebbles;
        myshape = shape;
        pebbles = new Point[numPebbles];
        for( int loop = 0 ; loop < numPebbles ; loop++ ) {
            pebbles[loop] = shape.getPoint( numDimensions );
        }
    }


    /** See interface */
    public boolean isMatchPebbleInCenter() {
        for( int loop = 0 ; loop < mypebbles ; loop++ ) {
            Point[] remainder = new Point[mypebbles-1];
            for( int arg = 0 ; arg < loop ; arg++ ) {
                remainder[arg] = pebbles[arg];
            }
            for( int arg = loop ; arg < (mypebbles-1) ; arg++ ) {
                remainder[arg] = pebbles[arg+1];
            }
            if( isPebbleInCenter( pebbles[loop], remainder ) ) { return true; }
        }
        return false;
    }


    boolean isPebbleInCenter(Point T, Point[] remainder) {
        // from here on in, we are stuck with 4 pebbles and 2 dimensions
        // we probably ought to throw an error here if that is not so

        Point G = remainder[0];
        Point E = remainder[1];
        Point F = remainder[2];
        Point M = getMidPoint(remainder);

        // check test point T and mid point M are on same side 
        // of line for each of 3 lines
        if( ! isShareSide(M,T,G,E) ) { return false; }
        if( ! isShareSide(M,T,E,F) ) { return false; }
        if( ! isShareSide(M,T,F,G) ) { return false; }
        return true;
    }


    boolean isShareSide(Point M, Point T, Point J, Point K) {
        double Mx = M.get(Point.X);
        double My = M.get(Point.Y);
        double Tx = T.get(Point.X);
        double Ty = T.get(Point.Y);
        double Jx = J.get(Point.X);
        double Jy = J.get(Point.Y);
        double Kx = K.get(Point.X);
        double Ky = K.get(Point.Y);

        // deduce the line Y = ( constM * x ) + constC
        double constM = ( Ky - Kx ) / (Jy - Jx ); // will throw error if Jy = Jx
        double constC = Jy - ( constM * Jx );
        // System.out.print("\n("+Jx+","+Jy+") ("+Kx+","+Ky+")");
        // System.out.print("\nY = " + constM + " X + " + constC + "\n" );
        double YintersectforM = ( constM * Mx ) + constC;
        double YintersectforT = ( constM * Tx ) + constC;
	return( ( (YintersectforM - My) * (YintersectforT - Ty) ) > 0 );
    }


    Point getMidPoint(Point[] remainder) {
        double[] coords = new double[mydimensions];
        for( int dimension = 0 ; dimension < mydimensions ; dimension++ ) {
            double sum = 0.0;
            for( int loop = 0 ; loop < remainder.length ; loop++ ) {
                sum = sum + remainder[loop].get(dimension);
            }
            coords[dimension] = sum / remainder.length;
        }
        return new Point(coords);
    }
}

// End of File