/** * Returns the unoriented smallest angle between two vectors. * The computed angle will be in the range [0, Pi). * * @param tip1 the tip of one vector * @param tail the tail of each vector * @param tip2 the tip of the other vector * @return the angle between tail-tip1 and tail-tip2 */ public static double angleBetween(Coordinate tip1, Coordinate tail, Coordinate tip2) { double a1 = angle(tail, tip1); double a2 = angle(tail, tip2); return diff(a1, a2); }
/** * Tests whether a triangle is acute. A triangle is acute iff all interior * angles are acute. This is a strict test - right triangles will return * <tt>false</tt> A triangle which is not acute is either right or obtuse. * <p> * Note: this implementation is not robust for angles very close to 90 * degrees. * * @param a * a vertex of the triangle * @param b * a vertex of the triangle * @param c * a vertex of the triangle * @return true if the triangle is acute */ public static boolean isAcute(Coordinate a, Coordinate b, Coordinate c) { if (!Angle.isAcute(a, b, c)) return false; if (!Angle.isAcute(b, c, a)) return false; if (!Angle.isAcute(c, a, b)) return false; return true; }
private static Coordinate pointWithMinAngleWithSegment(Coordinate[] pts, Coordinate P, Coordinate Q) { double minAng = Double.MAX_VALUE; Coordinate minAngPt = null; for (int i = 0; i < pts.length; i++) { Coordinate p = pts[i]; if (p == P) continue; if (p == Q) continue; double ang = Angle.angleBetween(P, p, Q); if (ang < minAng) { minAng = ang; minAngPt = p; } } return minAngPt; } }
double ang0 = Angle.angle(basePt, seg0.p0); double angDiff = Angle.angleBetweenOriented(seg0.p0, basePt, seg1.p1); double midAng = Angle.normalize(ang0 + angDiffHalf); double mitreMidAng = Angle.normalize(midAng + Math.PI);
/** * Returns the oriented smallest angle between two vectors. * The computed angle will be in the range (-Pi, Pi]. * A positive result corresponds to a counterclockwise * (CCW) rotation * from v1 to v2; * a negative result corresponds to a clockwise (CW) rotation; * a zero result corresponds to no rotation. * * @param tip1 the tip of v1 * @param tail the tail of each vector * @param tip2 the tip of v2 * @return the angle between v1 and v2, relative to v1 */ public static double angleBetweenOriented(Coordinate tip1, Coordinate tail, Coordinate tip2) { double a1 = angle(tail, tip1); double a2 = angle(tail, tip2); double angDel = a2 - a1; // normalize, maintaining orientation if (angDel <= -Math.PI) return angDel + PI_TIMES_2; if (angDel > Math.PI) return angDel - PI_TIMES_2; return angDel; }
public void testNormalize() throws Exception { assertEquals(Angle.normalize(0.0), 0.0, TOLERANCE); assertEquals(Angle.normalize(-0.5*Math.PI), -0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(-Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalize(-1.5*Math.PI), .5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(-2*Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalize(-2.5*Math.PI), -0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(-3*Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalize(-4 * Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalize(0.5*Math.PI), 0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalize(1.5*Math.PI), -0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(2*Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalize(2.5*Math.PI), 0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalize(3*Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalize(4 * Math.PI), 0.0, TOLERANCE); }
/** * Creates an AffineTransformation defined by a pair of control vectors. A * control vector consists of a source point and a destination point, which is * the image of the source point under the desired transformation. The * computed transformation is a combination of one or more of a uniform scale, * a rotation, and a translation (i.e. there is no shear component and no * reflection) * * @param src0 * @param src1 * @param dest0 * @param dest1 * @return the computed transformation, or null if the control vectors do not determine a well-defined transformation */ public static AffineTransformation createFromControlVectors(Coordinate src0, Coordinate src1, Coordinate dest0, Coordinate dest1) { Coordinate rotPt = new Coordinate(dest1.x - dest0.x, dest1.y - dest0.y); double ang = Angle.angleBetweenOriented(src1, src0, rotPt); double srcDist = src1.distance(src0); double destDist = dest1.distance(dest0); if (srcDist == 0.0) return null; double scale = destDist / srcDist; AffineTransformation trans = AffineTransformation.translationInstance( -src0.x, -src0.y); trans.rotate(ang); trans.scale(scale, scale); trans.translate(dest0.x, dest0.y); return trans; }
public double angle(Vector2D v) { return Angle.diff(v.angle(), angle()); }
public void testNormalizePositive() throws Exception { assertEquals(Angle.normalizePositive(0.0), 0.0, TOLERANCE); assertEquals(Angle.normalizePositive(-0.5*Math.PI), 1.5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(-Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(-1.5*Math.PI), .5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(-2*Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalizePositive(-2.5*Math.PI), 1.5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(-3*Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(-4 * Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalizePositive(0.5*Math.PI), 0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(1.5*Math.PI), 1.5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(2*Math.PI), 0.0, TOLERANCE); assertEquals(Angle.normalizePositive(2.5*Math.PI), 0.5*Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(3*Math.PI), Math.PI, TOLERANCE); assertEquals(Angle.normalizePositive(4 * Math.PI), 0.0, TOLERANCE); }
/** * Computes the interior angle between two segments of a ring. The ring is * assumed to be oriented in a clockwise direction. The computed angle will be * in the range [0, 2Pi] * * @param p0 * a point of the ring * @param p1 * the next point of the ring * @param p2 * the next point of the ring * @return the interior angle based at <code>p1</code> */ public static double interiorAngle(Coordinate p0, Coordinate p1, Coordinate p2) { double anglePrev = Angle.angle(p1, p0); double angleNext = Angle.angle(p1, p2); return Math.abs(angleNext - anglePrev); }
double ang = Angle.angleBetweenOriented(src1, src0, rotPt);
public void testAngle() throws Exception { assertEquals(Angle.angle(new Coordinate(10,0)), 0.0, TOLERANCE); assertEquals(Angle.angle(new Coordinate(10,10)), Math.PI/4, TOLERANCE); assertEquals(Angle.angle(new Coordinate(0,10)), Math.PI/2, TOLERANCE); assertEquals(Angle.angle(new Coordinate(-10,10)), 0.75*Math.PI, TOLERANCE); assertEquals(Angle.angle(new Coordinate(-10,0)), Math.PI, TOLERANCE); assertEquals(Angle.angle(new Coordinate(-10,-0.1)), -3.131592986903128, TOLERANCE); assertEquals(Angle.angle(new Coordinate(-10,-10)), -0.75*Math.PI, TOLERANCE); }
public void testIsAcute() throws Exception { assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(5,10)), true); assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(5,-10)), true); // angle of 0 assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(10,0)), true); assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(-5,10)), false); assertEquals(Angle.isAcute(new Coordinate(10,0), new Coordinate(0,0), new Coordinate(-5,-10)), false); }