package fragmenter.util;

import Jama.Matrix;

import java.util.*;

/**
* This class is a class for outer nodes used in some segmentation algorithms.
*/
public class OuterNode extends Node {

	public OuterNode(Matrix vertex, int position, boolean valid) {
		this.v = vertex;
		this.neighbours = new HashSet<Node>();
		this.position = position;
		this.positionIsValid = valid;
	}

	public OuterNode(Matrix vertex) {
		this(vertex, 0, false);
	}

	@Override
	public List<Node> getNeighbours() {
		if (this.neighbours.size() < 3) {
			List<Node> lst = new LinkedList<Node>();
			lst.addAll(this.neighbours);
			return lst;
		}
		double maxAngle = 0;
		Node ref = null;
		for (Node node1 : this.neighbours) {
			for (Node node2 : this.neighbours) {
				if (!node1.equals(node2)) {
					double angle = this.getAngle(node1, node2);
					if (angle >= maxAngle) {
						maxAngle = angle;
						ref = node1;
					}
				}
			}
		}

		List<Node> rl = new LinkedList<Node>();
		rl.addAll(this.neighbours);
		Collections.sort(rl, new Comp(ref));
		return rl;
	}

	@Override
	protected double getAngle(Node node1, Node node2) {
		Matrix v1 = node1.getVertex().minus(this.v);
		Matrix v2 = node2.getVertex().minus(this.v);
		// calc scalar product
		Matrix v = v1.arrayTimes(v2);
		double scalar = v.get(0, 0) + v.get(1, 0) + v.get(2, 0);
		double inCos = scalar / (v1.norm2() * v2.norm2());
		if (Math.abs(inCos) > 1) {
			inCos = Math.signum(inCos);
		}
		double retVal = Math.acos(inCos);
		return retVal;
	}
}
