/* * Copyright © 2009-2011 Rebecca G. Bettencourt / Kreative Software * <p> * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * <a href="http://www.mozilla.org/MPL/">http://www.mozilla.org/MPL/</a> * <p> * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the * License for the specific language governing rights and limitations * under the License. * <p> * Alternatively, the contents of this file may be used under the terms * of the GNU Lesser General Public License (the "LGPL License"), in which * case the provisions of LGPL License are applicable instead of those * above. If you wish to allow use of your version of this file only * under the terms of the LGPL License and not to allow others to use * your version of this file under the MPL, indicate your decision by * deleting the provisions above and replace them with the notice and * other provisions required by the LGPL License. If you do not delete * the provisions above, a recipient may use your version of this file * under either the MPL or the LGPL License. * @since PowerPaint 1.0 * @author Rebecca G. Bettencourt, Kreative Software */ package com.kreative.paint.geom; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.PathIterator; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; public class RegularPolygon implements Shape, Cloneable { private int sides; private int skips; private Point2D.Double center; private Point2D.Double endPoint1; private Point2D.Double endPoint2; private GeneralPath poly; public RegularPolygon(double centerX, double centerY, double endPointX, double endPointY, int numSides) { sides = numSides; skips = 1; center = new Point2D.Double(centerX, centerY); endPoint1 = new Point2D.Double(endPointX, endPointY); endPoint2 = null; poly = makePolygon(); } public RegularPolygon(double x1, double y1, double x2, double y2, int numSides, boolean fromCenter) { sides = numSides; skips = 1; if (fromCenter) { center = new Point2D.Double(x1, y1); endPoint1 = new Point2D.Double(x2, y2); endPoint2 = null; } else { center = null; endPoint1 = new Point2D.Double(x1, y1); endPoint2 = new Point2D.Double(x2, y2); } poly = makePolygon(); } public RegularPolygon(double centerX, double centerY, double endPointX, double endPointY, int numSides, int numSkips) { sides = numSides; skips = numSkips; center = new Point2D.Double(centerX, centerY); endPoint1 = new Point2D.Double(endPointX, endPointY); endPoint2 = null; poly = makePolygon(); } public RegularPolygon(double x1, double y1, double x2, double y2, int numSides, int numSkips, boolean fromCenter) { sides = numSides; skips = numSkips; if (fromCenter) { center = new Point2D.Double(x1, y1); endPoint1 = new Point2D.Double(x2, y2); endPoint2 = null; } else { center = null; endPoint1 = new Point2D.Double(x1, y1); endPoint2 = new Point2D.Double(x2, y2); } poly = makePolygon(); } public RegularPolygon clone() { if (center != null) { return new RegularPolygon(center.x, center.y, endPoint1.x, endPoint1.y, sides, skips, true); } else { return new RegularPolygon(endPoint1.x, endPoint1.y, endPoint2.x, endPoint2.y, sides, skips, false); } } public int getSides() { return sides; } public void setSides(int numSides) { sides = numSides; poly = makePolygon(); } public int getSkips() { return skips; } public void setSkips(int numSkips) { skips = numSkips; poly = makePolygon(); } public Point2D getCenterInternal() { return center; } public Point2D getCenter() { if (center != null) { double cx = center.x; double cy = center.y; return new Point2D.Double(cx, cy); } else { double ex = endPoint1.x; double ey = endPoint1.y; double s = Math.hypot(endPoint2.y - endPoint1.y, endPoint2.x - endPoint1.x); double t = Math.atan2(endPoint2.y - endPoint1.y, endPoint2.x - endPoint1.x); double cx = ex + s * Math.sin(Math.PI/sides + t) / (2.0 * Math.sin(Math.PI/sides)); double cy = ey - s * Math.cos(Math.PI/sides + t) / (2.0 * Math.sin(Math.PI/sides)); return new Point2D.Double(cx, cy); } } public void setCenter(double centerX, double centerY) { this.center = new Point2D.Double(centerX, centerY); this.endPoint2 = null; poly = makePolygon(); } public void setCenter(Point2D center) { this.center = new Point2D.Double(center.getX(), center.getY()); this.endPoint2 = null; poly = makePolygon(); } public void moveCenter(double ncx, double ncy) { Point2D c = getCenter(); double dx = endPoint1.x - c.getX(); double dy = endPoint1.y - c.getY(); center = new Point2D.Double(ncx, ncy); endPoint1 = new Point2D.Double(ncx+dx, ncy+dy); endPoint2 = null; poly = makePolygon(); } public void moveCenter(Point2D nc) { Point2D c = getCenter(); double dx = endPoint1.x - c.getX(); double dy = endPoint1.y - c.getY(); center = new Point2D.Double(nc.getX(), nc.getY()); endPoint1 = new Point2D.Double(nc.getX()+dx, nc.getY()+dy); endPoint2 = null; poly = makePolygon(); } public Point2D getFirstVertexInternal() { return endPoint1; } public Point2D getFirstVertex() { return new Point2D.Double(endPoint1.x, endPoint1.y); } public void setFirstVertex(double x, double y) { this.endPoint1 = new Point2D.Double(x, y); poly = makePolygon(); } public void setFirstVertex(Point2D vertex) { this.endPoint1 = new Point2D.Double(vertex.getX(), vertex.getY()); poly = makePolygon(); } public Point2D getSecondVertexInternal() { return endPoint2; } public Point2D getSecondVertex() { if (endPoint2 != null) { double ex = endPoint2.x; double ey = endPoint2.y; return new Point2D.Double(ex, ey); } else { double ex = endPoint1.x; double ey = endPoint1.y; double cx = center.x; double cy = center.y; double r = Math.hypot(ey - cy, ex - cx); double t = Math.atan2(ey - cy, ex - cx); double a = t + (Math.PI * 2.0 / (double)(sides)); double x = cx + r * Math.cos(a); double y = cy + r * Math.sin(a); return new Point2D.Double(x, y); } } public void setSecondVertex(double x, double y) { this.endPoint2 = new Point2D.Double(x, y); this.center = null; poly = makePolygon(); } public void setSecondVertex(Point2D vertex) { this.endPoint2 = new Point2D.Double(vertex.getX(), vertex.getY()); this.center = null; poly = makePolygon(); } private GeneralPath makePolygon() { GeneralPath p = new GeneralPath(); double ex, ey; double cx, cy; if (center != null) { ex = endPoint1.x; ey = endPoint1.y; cx = center.x; cy = center.y; } else { ex = endPoint1.x; ey = endPoint1.y; double s = Math.hypot(endPoint2.y - endPoint1.y, endPoint2.x - endPoint1.x); double t = Math.atan2(endPoint2.y - endPoint1.y, endPoint2.x - endPoint1.x); cx = ex + s * Math.sin(Math.PI/sides + t) / (2.0 * Math.sin(Math.PI/sides)); cy = ey - s * Math.cos(Math.PI/sides + t) / (2.0 * Math.sin(Math.PI/sides)); } double r = Math.hypot(ey - cy, ex - cx); double t = Math.atan2(ey - cy, ex - cx); for (int n = 0, j = 0; n < sides; j++) { for (int i = 0; n < sides && ((i == 0) || ((i % sides) != 0)); n++, i += skips) { double a = t + (Math.PI * (double)((i+j)*2) / (double)(sides)); double x = cx + r * Math.cos(a); double y = cy + r * Math.sin(a); if (i == 0) p.moveTo((float)x, (float)y); else p.lineTo((float)x, (float)y); } p.closePath(); } return p; } public boolean contains(Point2D p) { return poly.contains(p); } public boolean contains(Rectangle2D r) { return poly.contains(r); } public boolean contains(double x, double y) { return poly.contains(x, y); } public boolean contains(double x, double y, double w, double h) { return poly.contains(x, y, w, h); } public Rectangle getBounds() { return poly.getBounds(); } public Rectangle2D getBounds2D() { return poly.getBounds2D(); } public PathIterator getPathIterator(AffineTransform at) { return poly.getPathIterator(at); } public PathIterator getPathIterator(AffineTransform at, double flatness) { return poly.getPathIterator(at, flatness); } public boolean intersects(Rectangle2D r) { return poly.intersects(r); } public boolean intersects(double x, double y, double w, double h) { return poly.intersects(x, y, w, h); } public String toString() { return "com.kreative.paint.geom.RegularPolygon["+sides+","+skips+","+center+","+endPoint1+","+endPoint2+"]"; } }