/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.draw2d.geometry;
/**
* @author Frank Shaka
*/
public class PrecisionPolygon {
private PrecisionPointList points;
public PrecisionPolygon() {
this.points = new PrecisionPointList();
}
public PrecisionPolygon(int size) {
this.points = new PrecisionPointList(size);
}
public PrecisionPolygon(PrecisionPointList points) {
this.points = points.getCopy();
}
public PrecisionPointList getPoints() {
return points;
}
public boolean contains(PrecisionPoint toTest, boolean outline) {
translate(-toTest.x, -toTest.y);
int t1, t2;
PrecisionPoint prev = getPoint(points.size() - 1);
t1 = prev.x >= 0 ? (prev.y >= 0 ? 0 : 3) : (prev.y >= 0 ? 1 : 2); // ��������
int sum = 0, i = 0;
if (prev.x != 0 || prev.y != 0) {
for (; i < points.size(); i++) {
PrecisionPoint current = getPoint(i);
if ((current.x == 0 && current.y == 0) && outline)
break; // �����������
double f = current.y * prev.x - current.x * prev.y; // ������
if (f == 0 && prev.x * current.x <= 0
&& prev.y * current.y <= 0 && outline)
break; // ���ڱ���
t2 = current.x >= 0 ? (current.y >= 0 ? 0 : 3)
: (current.y >= 0 ? 1 : 2); // ��������
if (t2 == (t1 + 1) % 4)
sum += 1; // ���1
else if (t2 == (t1 + 3) % 4)
sum -= 1;// ���2
else if (t2 == (t1 + 2) % 4)// ���3
{
if (f > 0)
sum += 2;
else
sum -= 2;
}
t1 = t2;
prev = current;
}
}
boolean result = ((i < points.size() && outline) || sum > 0);
translate(toTest.x, toTest.y);
return result;
}
public PrecisionPointList intersect(PrecisionLine line, double tolerance) {
PrecisionPointList result = new PrecisionPointList();
for (int i = 0; i < points.size(); i++) {
PrecisionLine l = getLine(i);
PrecisionPoint p = l.intersect(line, tolerance);
if (p != null)
result.addPoint(p);
}
return result;
}
public PrecisionPointList intersect(PrecisionLine line) {
return intersect(line, PrecisionLine.DEFAULT_TOLERANCE);
}
public PrecisionPoint intersectFarthest(PrecisionLine line, double tolerance) {
PrecisionPoint result = null;
for (int i = 0; i < points.size(); i++) {
PrecisionLine l = getLine(i);
PrecisionPoint p = l.intersect(line, tolerance);
if (p != null) {
if (result == null
|| (p != null && p.getDistance2(line.getOrigin()) > result
.getDistance2(line.getOrigin()))) {
result = p;
}
}
}
return result;
}
public PrecisionPoint intersectFarthest(PrecisionLine line) {
return intersectFarthest(line, PrecisionLine.DEFAULT_TOLERANCE);
}
public PrecisionPoint intersectNearest(PrecisionLine line, double tolerance) {
PrecisionPoint result = null;
for (int i = 0; i < points.size(); i++) {
PrecisionLine l = getLine(i);
PrecisionPoint p = l.intersect(line, tolerance);
if (p != null) {
if (result == null
|| p.getDistance2(line.getOrigin()) < result
.getDistance2(line.getOrigin())) {
result = p;
}
}
}
return result;
}
public PrecisionPoint intersectNearest(PrecisionLine line) {
return intersectNearest(line, PrecisionLine.DEFAULT_TOLERANCE);
}
/**
* @param index
* @return
*/
public PrecisionLine getLine(int index) {
if (index < 0 || index >= points.size())
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + points.size()); //$NON-NLS-1$ //$NON-NLS-2$
PrecisionPoint origin = points.getPoint(index);
PrecisionPoint terminus;
if (index < points.size() - 1)
terminus = points.getPoint(index + 1);
else
terminus = points.getPoint(0);
return new PrecisionLine(origin, terminus);
}
public PrecisionPolygon getCopy() {
return new PrecisionPolygon(points.getCopy());
}
public void addAll(PrecisionPointList source) {
points.addAll(source);
}
public void addPoint(double x, double y) {
points.addPoint(x, y);
}
public void addPoint(PrecisionPoint p) {
points.addPoint(p);
}
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof PrecisionPolygon))
return false;
PrecisionPolygon p = (PrecisionPolygon) obj;
return p.points.equals(points);
}
public PrecisionRectangle getBounds() {
return points.getBounds();
}
public PrecisionPoint getFirstPoint() {
return points.getFirstPoint();
}
public PrecisionPoint getLastPoint() {
return points.getLastPoint();
}
public PrecisionPoint getMidPoint() {
return points.getMidPoint();
}
public PrecisionPoint getPoint(int index) {
return points.getPoint(index);
}
public int hashCode() {
return points.hashCode();
}
public void insertPoint(PrecisionPoint p, int index) {
points.insertPoint(p, index);
}
public void removeAllPoints() {
points.removeAllPoints();
}
public PrecisionPoint removePoint(int index) {
return points.removePoint(index);
}
public void reverse() {
points.reverse();
}
public void scale(double amount) {
points.scale(amount);
}
public void setPoint(PrecisionPoint p, int index) {
points.setPoint(p, index);
}
public void setSize(int newSize) {
points.setSize(newSize);
}
public int size() {
return points.size();
}
public PrecisionPoint[] toArray() {
return points.toArray();
}
public String toString() {
return points.toString();
}
public void translate(double dx, double dy) {
points.translate(dx, dy);
}
public void translate(PrecisionDimension d) {
points.translate(d);
}
public static final PrecisionPolygon createFromRect(PrecisionRectangle r) {
PrecisionPolygon result = new PrecisionPolygon();
result.addPoint(r.getTopLeft());
result.addPoint(r.getTopRight());
result.addPoint(r.getBottomRight());
result.addPoint(r.getBottomLeft());
return result;
}
}