package devASD.templateProject;



import jv.geom.PgPointSet;
import jv.geom.PgPolygon;
import jv.geom.PgPolygonSet;
import jv.number.PuDouble;
import jv.project.PjProject;
import jv.vecmath.PdVector;

/**
 * Here is a template you may use to create your own project with JavaView.
 * You just have to change a few lines according to your project name and goal.
 * These lines are highlighted with this comment : //TODO To modify : [Explanation of what to modify]
 * 
 * See PaTemplateProject for more information on the architecture of a JVproject.
 * 
 * You are of course supposed to modify all the comments according to the JavaDoc rules to explain
 * what each elements of this file is for.
 * 
 * 
 * This class contains the main fields : geometry and settings.
 * It also contains the main methods, which define what the project does, and also the methods
 * called when the user changes something (by the IP class).
 * 
 * 
 * @see			jv.geom.PgPointSet
 * @see			jv.project.PjProject
 * @author		you
 * @version		now, 1.00 created (ms)
 */

//TODO To modify : Name
public class PjTemplateProject extends PjProject {
	
	//TODO To modify : fields according to your wills
	protected	PgPointSet		m_geom;			// Point Cloud
	protected 	PgPolygon 	m_geom2;
	protected	PuDouble		m_stepSize;		// Step Size of the animation steps
	protected 	boolean			m_checkBoxState; //As its name says
	protected 	int				m_choice;
	
	
	/**
	 * Constructor, without arguments to allow loading of project from menu.
	 */
	public PjTemplateProject() {
		//TODO To modify : Name
		super("Template Project to help you");
		
		//TODO To modify : initialization
		m_geom = new PgPointSet(2);				// Create an own geometry
		m_geom.setName("Geometry");				// Optionally, give it a name
		// Create integers with given label and this project as parent, i.e. sliders
		// are now children of this project and send update(Object) to project whenever they change.
		m_stepSize = new PuDouble("Step Size:", this);

		init();	// Call to init() is required.
	}
	
	/**
	 * Do initialization of data structures; method is also used to reset instances.
	 */
	public void init() {
		super.init();
		
		//TODO To modify : Initialization
		// Initialize bounds and values.	
		m_stepSize.setDefBounds(0, 1.0, 0.01, 0.1);
		m_stepSize.setDefValue(0.1);
		m_stepSize.init();
		
		m_choice = 1;
		m_geom2 = new PgPolygon();
		m_geom2.computeCircle(10,10);
		
		InitializePointCloud();
	}
	
	/**
	 * Start project, e.g. start an animation. Method is called once when project is
	 * selected in PvViewer#selectProject(). Method is optional. For example, if an
	 * applet calls the start() method of PvViewer, then PvViewer tries to invoke
	 * the start() method of the currently selected project.
	 */
	//TODO To modify : how your project start
	public void start() {
		if(m_choice == 1)
			addGeometry(m_geom);
		else
			addGeometry(m_geom2);
		selectGeometry(m_geom);

		super.start();
	}

	/**
	 * Update method of project to react on changes in its panel or of its children.
	 * This method is optional, but required if project is parent of a child.
	 * Project becomes parent if child calls <code>child.setParent(this)</code> with
	 * this project as argument. For example, see the constructor of MyProject.
	 * Project must react on child events, or forward them to its superclass.
	 * <p>
	 * Catch events of integer children and recompute surface.
	 */	
	//TODO To modify : how your project is updated
	public boolean update(Object event) {
		if (event == m_stepSize) {
			return super.update(this);
		}
		removeGeometries();
		start();
		return super.update(event);
	}
	
	
	
	//TODO To modify : The rest of the file according to your project
	//*********************************************************************************************//
	
	/**
	 * Initialize the point cloud.
	 */
	private void InitializePointCloud() {
		
		m_geom.init();
		
		double t = 1;
		
		m_geom.addVertex(new PdVector(0,0));
		m_geom.addVertex(new PdVector(0,t/2));
		m_geom.addVertex(new PdVector(0,t*3/2));
		m_geom.addVertex(new PdVector(0,2*t));
		m_geom.addVertex(new PdVector(t,t*3/2));
		m_geom.addVertex(new PdVector(t,t/2));
		
		m_geom.update(m_geom);
	}

	/**
	 * Perform an animation step, i.e. move all particles according to a specified gradient
	 * direction.
	 */
	public void step() {
		for (int i=0; i<m_geom.getNumVertices(); i++) {
			PdVector point = m_geom.getVertex(i);
			PdVector direction = gradientDirection(point);
			direction.multScalar(m_stepSize.getValue());
			point.add(direction);
		}
		m_geom.update(m_geom);
	}
	
	/**
	 * For a given point, compute the direction into which it moves according to the given
	 * height field, i.e. the negative gradient direction, scaling according to step size
	 * has to be applied afterwards.
	 * @param point	The point at which to compute the direction given by the height field.
	 * @return Direction into which to move the point.
	 */
	private PdVector gradientDirection(PdVector point) {
		// height-function: x^2+y^2
		// gradient: (2x,2y)
		return new PdVector(-2*point.getEntry(0),-2*point.getEntry(1));
	}
}

