/*  This file is part of the source code for 3D-XplorMath-J, Version 1.0 (January 2008).
 *  Copyright (c) 2008 The 3D-XplorMath Consortium (http://3d-xplormath.org).
 *  This source code is released under a BSD License, which allows redistribution   
 *  in source and binary form, with or without modification, provided copyright
 *  and license information are included, and with no warranty or guarantee of
 *  any kind.  For details, see http://3d-xplormath.org/j/source/BSDLicense.txt
 */
 
 package vmm.core.render;

import java.awt.Graphics2D;
import java.awt.geom.GeneralPath;
import java.awt.geom.Point2D;

import vmm.core.Transform;

public class Curve2D extends GeometryElement2D {
	
	private double[] x,y;
	
	boolean closed;
	
	public Curve2D(Point2D[] points, int startindex, int endindex) {
		while (points[startindex] == null && startindex < endindex)
			startindex++;
		while (points[endindex] == null && startindex < endindex)
			endindex--;
		boolean gap = false;
		x = new double[endindex - startindex + 1];
		y = new double[endindex - startindex + 1];

		for (int i = startindex; i <= endindex; i++)
			if (points[i] == null || Double.isNaN(points[i].getY())) {
				x[i-startindex] = Double.NaN;
				gap = true;
			}
			else {
				x[i-startindex] = points[i].getX();
				y[i-startindex] = points[i].getY();
			}
		if (!gap && Math.abs(x[x.length-1] - x[0]) + Math.abs(y[y.length-1] - y[0]) < 1e-8)
			closed = true;
		else
			closed = false;
	}
	
	public Curve2D(Point2D[] points) {
		this(points,0,points.length-1);
	}

	protected void draw(Transform transform, Graphics2D g) {
		if (x.length < 2)
			return;
		GeneralPath curve = new GeneralPath();
		double maxJumpX = Math.abs(transform.getXmax() - transform.getXmin())/4;
		double maxJumpY = Math.abs(transform.getYmax() - transform.getYmin())/4;
		if (transform.appliedTransform2D())
			maxJumpX = maxJumpY = Math.max(maxJumpX,maxJumpY);
		Point2D.Float tempPoint = new Point2D.Float();
		boolean starting = true;
		boolean jumped = false;
		int i;
		for (i = 0; i < x.length-1; i++) {
			if (! Double.isNaN(x[i]) ) {
				if (starting) {
					tempPoint.setLocation(x[i],y[i]);
					transform.windowToDrawingCoords(tempPoint);
					curve.moveTo(tempPoint.x, tempPoint.y);
					starting = false;
				}
				else if (Math.abs(x[i] - x[i-1]) > maxJumpX || Math.abs(y[i] - y[i-1]) > maxJumpY) {
				    jumped = true;
				    starting = true;
				}
				else {
					tempPoint.setLocation(x[i],y[i]);
					transform.windowToDrawingCoords(tempPoint);
					curve.lineTo(tempPoint.x, tempPoint.y);
				}
			}
		}
		// i == points.length-1
		if (closed && !jumped && Math.abs(x[i] - x[i-1]) <= maxJumpX && Math.abs(y[i] - y[i-1]) <= maxJumpY)
			curve.closePath();
		else if (!starting) {
			tempPoint.setLocation(x[i],y[i]);
			transform.windowToDrawingCoords(tempPoint);
			curve.lineTo(tempPoint.x, tempPoint.y);
		}
		g.draw(curve);
	}

}
