001: /*
002: * The contents of this file are subject to the terms of the Common Development
003: * and Distribution License (the License). You may not use this file except in
004: * compliance with the License.
005: *
006: * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
007: * or http://www.netbeans.org/cddl.txt.
008: *
009: * When distributing Covered Code, include this CDDL Header Notice in each file
010: * and include the License file at http://www.netbeans.org/cddl.txt.
011: * If applicable, add the following below the CDDL Header, with the fields
012: * enclosed by brackets [] replaced by your own identifying information:
013: * "Portions Copyrighted [year] [name of copyright owner]"
014: *
015: * The Original Software is NetBeans. The Initial Developer of the Original
016: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
017: * Microsystems, Inc. All Rights Reserved.
018: */
019:
020: package org.netbeans.modules.bpel.design.geometry;
021:
022: import java.awt.Rectangle;
023: import java.awt.Shape;
024: import java.awt.geom.AffineTransform;
025: import java.awt.geom.PathIterator;
026: import java.awt.geom.Point2D;
027: import java.awt.geom.Rectangle2D;
028:
029: /**
030: *
031: * @author anjeleevich
032: */
033: public class Triangle implements Shape {
034:
035: private double[] coords = new double[8];
036:
037: private double minX = Double.NaN;
038: private double minY = 0.0;
039:
040: private double maxX = 0.0;
041: private double maxY = 0.0;
042:
043: public Triangle(double x1, double y1, double x2, double y2,
044: double x3, double y3) {
045: coords[0] = x1;
046: coords[1] = y1;
047: coords[2] = x2;
048: coords[3] = y2;
049: coords[4] = x3;
050: coords[5] = y3;
051: coords[6] = x1;
052: coords[7] = y1;
053: }
054:
055: private final void calculateBounds() {
056: if (minX != minX) {
057: maxX = minX = coords[0];
058: maxY = minY = coords[1];
059:
060: for (int i = 2; i < 6; i += 2) {
061: double x = coords[i];
062: double y = coords[i + 1];
063:
064: if (x < minX)
065: minX = x;
066: if (y < minY)
067: minY = y;
068:
069: if (maxX < x)
070: maxX = x;
071: if (maxY < y)
072: maxY = y;
073: }
074: }
075: }
076:
077: public Rectangle getBounds() {
078: calculateBounds();
079: int x = (int) Math.floor(minX);
080: int y = (int) Math.floor(minY);
081: return new Rectangle(x, y, (int) Math.ceil(maxX) - x,
082: (int) Math.ceil(maxY) - y);
083: }
084:
085: public Rectangle2D getBounds2D() {
086: calculateBounds();
087: return new Rectangle2D.Double(minX, minY, maxX - minX, maxY
088: - minY);
089: }
090:
091: public boolean contains(double px, double py) {
092: calculateBounds();
093:
094: if (px < minX || maxX < px)
095: return false;
096: if (py < minY || maxY < py)
097: return false;
098:
099: double x0 = coords[0];
100: double y0 = coords[1];
101:
102: px -= x0;
103: py -= y0;
104:
105: double x1 = coords[2] - x0;
106: double y1 = coords[3] - y0;
107:
108: double x2 = coords[4] - x0;
109: double y2 = coords[5] - y0;
110:
111: double lenSq1 = x1 * x1 + y1 * y1;
112: double lenSq2 = x2 * x2 + y1 * y2;
113:
114: double dotPr12 = x2 * x1 + y2 * y1;
115: double dotPr1 = px * x1 + py * y1;
116: double dotPr2 = px * x2 + py * y2;
117:
118: double det = lenSq1 * lenSq2 - dotPr12 * dotPr12;
119: double a1 = -(dotPr12 * dotPr2 - lenSq2 * dotPr1) / det;
120: double a2 = (lenSq1 * dotPr2 - dotPr12 * dotPr1) / det;
121:
122: double sum = a1 + a2;
123:
124: return (0.0 <= a1 && a1 <= 1.0) && (0.0 <= a2 && a2 <= 1.0)
125: && (sum <= 1.0);
126: }
127:
128: public boolean contains(Point2D p) {
129: return contains(p.getX(), p.getY());
130: }
131:
132: public boolean intersects(double x, double y, double w, double h) {
133: calculateBounds();
134:
135: double x1 = Math.min(x, x + w);
136: double y1 = Math.min(y, y + h);
137:
138: double x2 = x1 + Math.abs(w);
139: double y2 = y1 + Math.abs(h);
140:
141: return (Math.max(x1, minX) <= Math.min(x2, maxX))
142: && (Math.max(y1, minY) <= Math.min(y2, maxY));
143: }
144:
145: public boolean intersects(Rectangle2D r) {
146: return intersects(r.getX(), r.getY(), r.getWidth(), r
147: .getHeight());
148: }
149:
150: public boolean contains(double x, double y, double w, double h) {
151: return contains(x, y) && contains(x + w, y)
152: && contains(y, y + h) && contains(x + w, y + h);
153: }
154:
155: public boolean contains(Rectangle2D r) {
156: return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
157: }
158:
159: public PathIterator getPathIterator(AffineTransform at) {
160: return new TrianglePathIterator(at);
161: }
162:
163: public PathIterator getPathIterator(AffineTransform at,
164: double flatness) {
165: return new TrianglePathIterator(at);
166: }
167:
168: private class TrianglePathIterator implements PathIterator {
169:
170: private int index = 0;
171: private AffineTransform at;
172:
173: public TrianglePathIterator(AffineTransform at) {
174: this .at = at;
175: }
176:
177: public int getWindingRule() {
178: return PathIterator.WIND_NON_ZERO;
179: }
180:
181: public boolean isDone() {
182: return (index > 8);
183: }
184:
185: public void next() {
186: index += 2;
187: }
188:
189: public int currentSegment(float[] coords) {
190: if (index >= 8) {
191: return PathIterator.SEG_CLOSE;
192: }
193:
194: coords[0] = (float) Triangle.this .coords[index];
195: coords[1] = (float) Triangle.this .coords[index + 1];
196:
197: if (at != null) {
198: at.transform(coords, 0, coords, 0, 1);
199: }
200:
201: return (index == 0) ? PathIterator.SEG_MOVETO
202: : PathIterator.SEG_LINETO;
203: }
204:
205: public int currentSegment(double[] coords) {
206: if (index >= 8) {
207: return PathIterator.SEG_CLOSE;
208: }
209:
210: coords[0] = Triangle.this .coords[index];
211: coords[1] = Triangle.this .coords[index + 1];
212:
213: if (at != null) {
214: at.transform(coords, 0, coords, 0, 1);
215: }
216:
217: return (index == 0) ? PathIterator.SEG_MOVETO
218: : PathIterator.SEG_LINETO;
219: }
220: }
221: }
|