001: /*
002: * The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
003: * for visualizing and manipulating spatial features with geometry and attributes.
004: *
005: * JUMP is Copyright (C) 2003 Vivid Solutions
006: *
007: * This program implements extensions to JUMP and is
008: * Copyright (C) 2004 Integrated Systems Analysts, Inc.
009: *
010: * This program is free software; you can redistribute it and/or
011: * modify it under the terms of the GNU General Public License
012: * as published by the Free Software Foundation; either version 2
013: * of the License, or (at your option) any later version.
014: *
015: * This program is distributed in the hope that it will be useful,
016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
018: * GNU General Public License for more details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with this program; if not, write to the Free Software
022: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
023: *
024: * For more information, contact:
025: *
026: * Integrated Systems Analysts, Inc.
027: * 630C Anchors St., Suite 101
028: * Fort Walton Beach, Florida
029: * USA
030: *
031: * (850)862-7321
032: */
033:
034: package org.openjump.core.geomutils;
035:
036: import com.vividsolutions.jts.geom.Coordinate;
037: import com.vividsolutions.jts.geom.CoordinateList;
038: import com.vividsolutions.jts.geom.GeometryFactory;
039: import com.vividsolutions.jts.geom.LineString;
040: import com.vividsolutions.jts.geom.Polygon;
041:
042: public class Arc extends java.lang.Object {
043: protected Coordinate center = new Coordinate(0, 0);
044: protected Coordinate start = new Coordinate(0, 0);
045: protected double radius = 0.0;
046: protected double angle = 0.0;
047: protected double arcTolerance = 0.1;
048:
049: public Arc(Coordinate center, Coordinate start, double angle) {
050: this .center = center;
051: this .start = start;
052: this .angle = angle;
053: radius = Math.sqrt(center.distance(start)
054: * center.distance(start));
055: }
056:
057: public void setArcTolerance(double arcTolerance) {
058: this .arcTolerance = arcTolerance;
059: }
060:
061: public Polygon getPoly() {
062: if (angle == 360.0) {
063: CoordinateList polyCoords = arcAnglePts(angle, start,
064: center);
065: return new GeometryFactory().createPolygon(
066: new GeometryFactory().createLinearRing(polyCoords
067: .toCoordinateArray()), null);
068: } else {
069: CoordinateList polyCoords = new CoordinateList();
070: polyCoords.add(center);
071: polyCoords.add(start);
072: CoordinateList coordinates = arcAnglePts(angle, start,
073: center);
074: polyCoords.add(coordinates.toCoordinateArray(), true);
075: polyCoords.add(center);
076: return new GeometryFactory().createPolygon(
077: new GeometryFactory().createLinearRing(polyCoords
078: .toCoordinateArray()), null);
079: }
080: }
081:
082: public LineString getLineString() {
083: CoordinateList coordinates = arcAnglePts(angle, start, center);
084: return new GeometryFactory().createLineString(coordinates
085: .toCoordinateArray());
086: }
087:
088: public CoordinateList getCoordinates() {
089: return arcAnglePts(angle, start, center);
090: }
091:
092: protected CoordinateList arcAnglePts(double angle, Coordinate pt,
093: Coordinate center) {
094: CoordinateList coordinates = new CoordinateList();
095: int n = getPtsFromTolerance(center.distance(pt), angle,
096: arcTolerance);
097: if (n < 3)
098: n = 3;
099: double ai = angle / n;
100: coordinates.add(new Coordinate(pt));
101:
102: for (int i = 1; i < n; i++) //add all but the last one
103: {
104: Coordinate p2 = GeoUtils.rotPt(pt, center, ai * i);
105: coordinates.add(new Coordinate(p2));
106: }
107:
108: if (angle == 360.0) {
109: coordinates.add(new Coordinate(pt)); //close the circle
110: } else {
111: coordinates.add(new Coordinate(GeoUtils.rotPt(pt, center,
112: angle))); //add the last point
113: }
114: return coordinates;
115: }
116:
117: protected int getPtsFromTolerance(double radius, double angle,
118: double tolerance) {
119: //Tolerance is the distance from the center of a chord to the arc
120: //For the given arc, this function will return the number of points
121: //that is needed to draw the arc with the given tolerance
122:
123: final double epsilon = 0.00001;
124: int n;
125:
126: if (radius < epsilon) {
127: n = 1;
128: } else {
129: if ((tolerance / radius) > 0.333) {
130: n = 1;
131: } else {
132: double theta = Math.toDegrees(2 * Math
133: .acos((radius - tolerance) / radius));
134: if (theta < epsilon) {
135: n = 0;
136: } else {
137: n = (int) Math.floor(Math.abs(angle) / theta) + 1;
138: }
139: }
140: }
141: return n;
142: }
143: }
|