/* * Copyright (c) 2003-2009 jMonkeyEngine * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of 'jMonkeyEngine' nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package automenta.spacenet.space.geom.text3d.math; public class PlanarEdge { final public static float TWO_PI = (float)(Math.PI * 2.0); final public static float FLT_EPSILON = 1.1920928955078125E-7f; private PlanarVertex orig; private PlanarEdge twin; private PlanarEdge next; private PlanarEdge prev; float angle = -1; boolean realedge; PlanarEdge(PlanarVertex orig, boolean realedge) { this.orig = orig; this.realedge = realedge; } public boolean isRealEdge() { return realedge; } public PlanarVertex getOrigin() { return orig; } /** * Calculated the angle from this edge to the given edge (counter clockwise), the result is in the interval [0;2*PI). * * @param edge * @return */ public float angleCounterClockWise(PlanarEdge edge) { if(this == edge) throw new RuntimeException("You are trying to find the angle after adding an edge..."); //float myangle = FastMath.atan2(getDX(), getDY()); float e_angle = edge.getAngle(); //FastMath.atan2(edge.getDX(), edge.getDY()); while(e_angle < getAngle()) e_angle += TWO_PI; while(e_angle > getAngle()+TWO_PI) e_angle -= TWO_PI; if(e_angle == getAngle()) { // We have the same angle, then the unreal edges are on the outer rim, hence the angle is 2 PI and not 0, if(!isRealEdge()) e_angle += TWO_PI; } return e_angle - getAngle(); } float getDX() { return twin.orig.point.getXf() - orig.point.getXf(); } float getDY() { return twin.orig.point.getYf() - orig.point.getYf(); } float getAngle() { return angle; } public PlanarVertex getDestination() { return twin.orig; } PlanarEdge getNext() { return next; } void setNext(PlanarEdge next) { this.next = next; next.prev = this; /* if(isRealEdge() != next.isRealEdge()) { logger.info("\nReal/Unreal edges bound in next/prev relation:"); logger.info("Edge(prev):"+this); logger.info("Edge(next):"+next); } else { logger.info("\nCorrect bound in next/prev relation:"); logger.info("== Edge(prev):"+this); logger.info("== Edge(next):"+next); } */ } PlanarEdge getPrev() { return prev; } PlanarEdge getTwin() { return twin; } void setTwin(PlanarEdge twin) { this.twin = twin; twin.twin = this; angle = (float) Math.atan2(getDY(), getDX()); twin.angle = (float) Math.atan2(twin.getDY(), twin.getDX()); float limit = FLT_EPSILON*4; float anglediff = (float)(Math.abs(angleCounterClockWise(twin) - Math.PI)); // if(anglediff > limit) // { // throw new GeometricException("Two twins do not have opposite angles: "+angleCounterClockWise(twin)+" != "+Math.PI+" : ("+anglediff+" > "+limit+")"); // } } }