/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ package com.revolsys.geometry.model.util; import com.revolsys.geometry.algorithm.CGAlgorithms; import com.revolsys.geometry.model.Point; import com.revolsys.geometry.util.Triangles; /** * Represents a planar triangle, and provides methods for calculating various * properties of triangles. * * @version 1.7 */ public class TriangleImpl { /** * Computes the circumcentre of a triangle. The circumcentre is the centre of * the circumcircle, the smallest circle which encloses the triangle. It is * also the common intersection point of the perpendicular bisectors of the * sides of the triangle, and is the only point which has equal distance to * all three vertices of the triangle. * * @param a * a vertx of the triangle * @param b * a vertx of the triangle * @param c * a vertx of the triangle * @return the circumcentre of the triangle */ /* * // original non-robust algorithm public static Coordinate circumcentre(Point a, Point b, Point * c) { // compute the perpendicular bisector of chord ab HCoordinate cab = * perpendicularBisector(a, b); // compute the perpendicular bisector of chord bc HCoordinate cbc * = perpendicularBisector(b, c); // compute the intersection of the bisectors (circle radii) * HCoordinate hcc = new HCoordinate(cab, cbc); Point cc = null; try { cc = new * Coordinate(hcc.getX(), hcc.getY()); } catch (NotRepresentableException ex) { // MD - not sure * what we can do to prevent this (robustness problem) // Idea - can we condition which edges we * choose? throw new IllegalStateException(ex.getMessage()); } //System.out.println( "Acc = " + * a.distance(cc) + ", Bcc = " + b.distance(cc) + ", Ccc = " + c.distance(cc) ); return cc; } */ /** * The coordinates of the vertices of the triangle */ public Point p0, p1, p2; /** * Creates a new triangle with the given vertices. * * @param p0 * a vertex * @param p1 * a vertex * @param p2 * a vertex */ public TriangleImpl(final Point p0, final Point p1, final Point p2) { this.p0 = p0; this.p1 = p1; this.p2 = p2; } /** * Computes the 2D area of this triangle. The area value is always * non-negative. * * @return the area of this triangle * * @see #signedArea() */ public double area() { return Triangles.area(this.p0, this.p1, this.p2); } /** * Computes the 3D area of this triangle. The value computed is alway * non-negative. * * @return the 3D area of this triangle */ public double area3D() { return Triangles.area3D(this.p0, this.p1, this.p2); } /** * Computes the centroid (centre of mass) of this triangle. This is also the * point at which the triangle's three medians intersect (a triangle median is * the segment from a vertex of the triangle to the midpoint of the opposite * side). The centroid divides each median in a ratio of 2:1. * <p> * The centroid always lies within the triangle. * * @return the centroid of this triangle */ public Point centroid() { return Triangles.centroid(this.p0, this.p1, this.p2); } /** * Computes the circumcentre of this triangle. The circumcentre is the centre * of the circumcircle, the smallest circle which encloses the triangle. It is * also the common intersection point of the perpendicular bisectors of the * sides of the triangle, and is the only point which has equal distance to * all three vertices of the triangle. * <p> * The circumcentre does not necessarily lie within the triangle. * <p> * This method uses an algorithm due to J.R.Shewchuk which uses normalization * to the origin to improve the accuracy of computation. (See <i>Lecture Notes * on Geometric Robustness</i>, Jonathan Richard Shewchuk, 1999). * * @return the circumcentre of this triangle */ public Point circumcentre() { return Triangles.circumcentre(this.p0, this.p1, this.p2); } /** * Computes the incentre of this triangle. The <i>incentre</i> of a triangle * is the point which is equidistant from the sides of the triangle. It is * also the point at which the bisectors of the triangle's angles meet. It is * the centre of the triangle's <i>incircle</i>, which is the unique circle * that is tangent to each of the triangle's three sides. * * @return the point which is the inCentre of this triangle */ public Point inCentre() { return Triangles.inCentre(this.p0, this.p1, this.p2); } /** * Computes the Z-value (elevation) of an XY point on a three-dimensional * plane defined by this triangle (whose vertices must have Z-values). This * triangle must not be degenerate (in other words, the triangle must enclose * a non-zero area), and must not be parallel to the Z-axis. * <p> * This method can be used to interpolate the Z-value of a point inside this * triangle (for example, of a TIN facet with elevations on the vertices). * * @param p * the point to compute the Z-value of * @return the computed Z-value (elevation) of the point */ public double interpolateZ(final Point p) { if (p == null) { throw new IllegalArgumentException("Supplied point is null."); } return Triangles.interpolateZ(p, this.p0, this.p1, this.p2); } /** * Tests whether this 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. * * @return true if this triangle is acute */ public boolean isAcute() { return Triangles.isAcute(this.p0, this.p1, this.p2); } /** * Computes the length of the longest side of this triangle * * @return the length of the longest side of this triangle */ public double longestSideLength() { return Triangles.longestSideLength(this.p0, this.p1, this.p2); } /** * Computes the signed 2D area of this triangle. The area value is positive if * the triangle is oriented CW, and negative if it is oriented CCW. * <p> * The signed area value can be used to determine point orientation, but the * implementation in this method is susceptible to round-off errors. Use * {@link CGAlgorithms#orientationIndex(Coordinate, Coordinate, Coordinate)} * for robust orientation calculation. * * @return the signed 2D area of this triangle * * @see CGAlgorithms#orientationIndex(Coordinate, Coordinate, Coordinate) */ public double signedArea() { return Triangles.signedArea(this.p0, this.p1, this.p2); } }