Problem:
Counter-Clockwise

For given three points p0, p1, p2, print

COUNTER_CLOCKWISE

if p0, p1, p2 make a counterclockwise turn (1),

CLOCKWISE

if p0, p1, p2 make a clockwise turn (2),

ONLINE_BACK

if p2 is on a line p2, p0, p1 in this order (3),

ONLINE_FRONT

if p2 is on a line p0, p1, p2 in this order (4),

ON_SEGMENT

if p2 is on a segment p0p1 (5).

Input

xp0 yp0 xp1 yp1
q
xp20 yp20
xp21 yp21
...
xp2q-1 yp2q-1

In the first line, integer coordinates of p0 and p1 are given. Then, q queries are given for integer coordinates of p2.

Output

For each query, print the above mentioned status.

Constraints

1 ≤ q ≤ 1000

-10000 ≤ xi, yi ≤ 10000

p0 and p1 are not identical.

Sample Input 1

0 0 2 0
2
-1 1
-1 -1

Sample Output 1

COUNTER_CLOCKWISE
CLOCKWISE

Sample Input 2

0 0 2 0
3
-1 0
0 0
3 0

Sample Output 2

ONLINE_BACK
ON_SEGMENT
ONLINE_FRONT

Solution in JAVA (judge verdict: Accepted)


import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Main {

	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		String[] tmpArray = br.readLine().split(" ");
		double px1 = Double.parseDouble(tmpArray[0]);
		double py1 = Double.parseDouble(tmpArray[1]);
		double px2 = Double.parseDouble(tmpArray[2]);
		double py2 = Double.parseDouble(tmpArray[3]);

		Point2D p1 = new Point2D.Double(px1, py1);
		Point2D p2 = new Point2D.Double(px2, py2);

		int q = Integer.parseInt(br.readLine());

		for(int i = 0; i < q; i++){
			tmpArray = br.readLine().split(" ");
			double x = Double.parseDouble(tmpArray[0]);
			double y = Double.parseDouble(tmpArray[1]);

			Point2D p = new Point2D.Double(x,y);

			int result = checkClockwise(p, p1, p2);

			switch (result) {
			case COUNTER_CLOCKWISE:
				System.out.println("COUNTER_CLOCKWISE");
				break;

			case CLOCKWISE:
				System.out.println("CLOCKWISE");
				break;

			case ONLINE_BACK:
				System.out.println("ONLINE_BACK");
				break;

			case ONLINE_FRONT:
				System.out.println("ONLINE_FRONT");
				break;

			case ON_SEGMENT:
				System.out.println("ON_SEGMENT");
				break;

			default:
				break;
			}
		}

	}

	static final int COUNTER_CLOCKWISE = 1;
	static final int CLOCKWISE = 2;
	static final int ONLINE_BACK = 3;
	static final int ONLINE_FRONT = 4;
	static final int ON_SEGMENT = 5;
	static final double EPS = 0.00000001;

	//p1,p2が作るベクトルに対してpの位置関係を調べる
	static int checkClockwise(Point2D p, Point2D p1, Point2D p2){
		if(p1.getX() > p2.getX() || (p1.getX() == p2.getX() && p1.getY() > p2.getY())){
			AffineTransform rotate = AffineTransform.getQuadrantRotateInstance(2);
			Point2D tmp = null;
			p = rotate.transform(p, tmp);
			p1 = rotate.transform(p1, tmp);
			p2 = rotate.transform(p2, tmp);

//			System.out.println(p);
		}

		double theta = Math.PI/2;

		//直線のなす角が90度ではないときはここで計算
		if(p1.getX() != p2.getX()){
			theta = Math.atan((p1.getY() - p2.getY()) / (p1.getX() - p2.getX()));
		}


		AffineTransform affine;// = AffineTransform.getTranslateInstance(p1.getX(), p1.getY());
//		affine.concatenate(AffineTransform.getRotateInstance(theta));
//		affine.concatenate(new AffineTransform(1, 0, 0, -1, 0, 0));
		affine = AffineTransform.getRotateInstance(-theta);
		affine.concatenate(AffineTransform.getTranslateInstance(-p1.getX(), -p1.getY()));

		Point2D pD = new Point2D.Double();
		pD = affine.transform(p, pD);
		Point2D p2D = new Point2D.Double();
		p2D = affine.transform(p2, p2D);

		if(pD.getY() > EPS){
			return COUNTER_CLOCKWISE;
		}
		else if(pD.getY() < -EPS){
			return CLOCKWISE;
		}
		else if(pD.getX() < 0){
			return ONLINE_BACK;
		}
		else if(pD.getX() > p2D.getX()){
			return ONLINE_FRONT;
		}
		else {
			return ON_SEGMENT;
		}

	}

}