/*********************************************************************** * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***********************************************************************/ package org.mt4j.components.visibleComponents.shapes; import org.mt4j.components.bounds.BoundsZPlaneRectangle; import org.mt4j.components.bounds.IBoundingShape; import org.mt4j.util.MTColor; import org.mt4j.util.math.Vector3D; import org.mt4j.util.math.Vertex; import processing.core.PApplet; /** * A simple ellipse shape. * * @author Christopher Ruff */ public class MTEllipse extends MTPolygon { /** The radius x. */ private float radiusX; /** The radius y. */ private float radiusY; /** The center point. */ private Vector3D centerPoint; /** The theta. */ private float theta; /** The degrees. */ private float degrees; private int segments; /** * Instantiates a new mT ellipse. * * @param pApplet the applet * @param centerPoint the center point * @param radiusX the radius x * @param radiusY the radius y */ public MTEllipse(PApplet pApplet, Vector3D centerPoint, float radiusX, float radiusY) { this(pApplet, centerPoint, radiusX, radiusY, 45); } /** * Instantiates a new mT ellipse. * * @param pApplet the applet * @param centerPoint the center point * @param radiusX the radius x * @param radiusY the radius y * @param segments the segments */ public MTEllipse(PApplet pApplet, Vector3D centerPoint, float radiusX, float radiusY, int segments) { super(new Vertex[0], pApplet); this.radiusX = radiusX; this.radiusY = radiusY; this.centerPoint = centerPoint; this.segments = segments; theta = 0.0f; degrees = (float)Math.toRadians(360); this.setStrokeWeight(1); this.setNoFill(false); this.setNoStroke(false); this.create(); this.setBoundsBehaviour(AbstractShape.BOUNDS_CHECK_THEN_GEOMETRY_CHECK); this.setName("unnamed MTEllipse"); } /** * Sets the degrees for the ellipse. 360 draws a full circle/ellipse * while smaller values only draw part of the circle/ellipse. * To take effect, <code>recreate()</code> has to be called. * * @param degrees the new degrees */ public void setDegrees(float degrees){ this.degrees = (float)Math.toRadians(degrees); } /** * Gets the degrees for the ellipse. 360 draws a full circle/ellipse * while smaller values only draw part of the circle/ellipse. * * @return the degrees */ public float getDegrees(){ return (float)Math.toDegrees(this.degrees); } /** * (Re-)creates the ellipse using its current settings. */ public void create(){ this.setVertices(this.getVertices(segments)); } @Override protected IBoundingShape computeDefaultBounds() { // super.computeDefaultBounds(); //FIXME if the ellipse is rotatet X or Y, the bounding shape doesent work anymore.. to be safe we //would have to use boundingshpere or box..but slower.. return new BoundsZPlaneRectangle(this); } /** * Gets the vertices. * * @param resolution the resolution * * @return the vertices */ protected Vertex[] getVertices(int resolution){ Vertex[] verts = new Vertex[resolution+1]; float t; float inc = degrees / (float)resolution; double cosTheta = Math.cos(theta); double sinTheta = Math.sin(theta); MTColor fillColor = this.getFillColor(); for (int i = 0; i < resolution; i++){ t = 0 + (i * inc); // float x = (float) (centerPoint.x + (radiusX * Math.cos(t) * cosTheta) //TODO remove theta stuff? oder enablen als parameter? // - (radiusY * Math.sin(t) * sinTheta) ); // float y = (float) (centerPoint.y + (radiusX * Math.cos(t) * sinTheta) // + (radiusY * Math.sin(t) * cosTheta) ); float x = (float) (centerPoint.x - (radiusX * Math.cos(t) * cosTheta) + (radiusY * Math.sin(t) * sinTheta) ); float y = (float) (centerPoint.y - (radiusX * Math.cos(t) * sinTheta) - (radiusY * Math.sin(t) * cosTheta) ); verts[i] = new Vertex(x, y, centerPoint.z, fillColor.getR(), fillColor.getG(), fillColor.getB(), fillColor.getAlpha()); } verts[verts.length-1] = (Vertex) verts[0].getCopy(); //NEED TO USE COPY BECAUSE TEX COORDS MAY GET SCALED DOUBLE IF SAME VERTEX OBJECT! // System.out.println("Points: " + verts.length); //Create tex coords float width = radiusX*2; float height = radiusY*2; float upperLeftX = centerPoint.x-radiusX; float upperLeftY = centerPoint.y-radiusY; for (int i = 0; i < verts.length; i++) { Vertex vertex = verts[i]; vertex.setTexCoordU((vertex.x-upperLeftX)/width); vertex.setTexCoordV((vertex.y-upperLeftY)/height); // System.out.println("TexU:" + vertex.getTexCoordU() + " TexV:" + vertex.getTexCoordV()); } return verts; } // public List<Vector3D> getVerticesAbsolute(int resolution){ // List<Vector3D> returnPts = new ArrayList<Vector3D>(); // // float t; // // float inc = (float)Math.toRadians(rangeAng) / (float)resolution; // for (int i = 0; i < resolution; i++) // { // t = minAng + (i * inc); // // float x = (float) (centerPt.x + (a * Math.cos(t) * Math.cos(theta)) // - (b * Math.sin(t) * Math.sin(theta)) ); // float y = (float) (centerPt.y + (a * Math.cos(t) * Math.sin(theta)) // + (b * Math.sin(t) * Math.cos(theta)) ); // } // // return returnPts; // } // // // // @Override // public Vector3D getGeometryIntersection(Ray ray) { // // TODO Auto-generated method stub // return null; // } // // // // @Override // public boolean isGeometryContainsPoint(Vector3D testPoint) { // // TODO Auto-generated method stub // return false; // } /* (non-Javadoc) * @see com.jMT.components.visibleComponents.shapes.MTPolygon#getCenterPointObjectSpace() */ @Override public Vector3D getCenterPointLocal() { Vector3D center = new Vector3D(this.centerPoint); return center; } //FIXME doesent work, seems to only get points in the shape of a outer rectangle /* public boolean isInsideEllipse(float ex,float ey,float w,float h,float px,float py) { //Determine and normalize quadrant. float dx = Math.abs(ex-px); float dy = Math.abs(ey-py); double l; //Shortcut if( dx > w/2 || dy > h/2 ) { return false; } //Calculate the semi-latus rectum of the ellipse at the given point l = Math.sqrt( (double)((1-((dx*dx)/(w*w))) * (h*h)) ); return dy < l; } */ }