/* * (c) Copyright 2010-2011 AgileBirds * * This file is part of OpenFlexo. * * OpenFlexo is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * OpenFlexo 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>. * */ package org.openflexo.fge.geom; import java.awt.geom.AffineTransform; import java.awt.geom.RoundRectangle2D; import java.util.List; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.fge.geom.FGEArc.ArcType; import org.openflexo.fge.geom.area.FGEArea; import org.openflexo.fge.geom.area.FGEEmptyArea; import org.openflexo.fge.geom.area.FGEExclusiveOrArea; import org.openflexo.fge.geom.area.FGEHalfLine; import org.openflexo.fge.geom.area.FGEHalfPlane; import org.openflexo.fge.geom.area.FGEIntersectionArea; import org.openflexo.fge.geom.area.FGESubstractionArea; import org.openflexo.fge.geom.area.FGEUnionArea; import org.openflexo.fge.graphics.FGEGraphics; public class FGERoundRectangle extends RoundRectangle2D.Double implements FGEGeometricObject<FGERoundRectangle>, FGEShape<FGERoundRectangle> { private static final Logger logger = Logger.getLogger(FGERoundRectangle.class.getPackage().getName()); protected Filling _filling; public FGERoundRectangle() { this(0, 0, 0, 0, 0, 0, Filling.NOT_FILLED); } public FGERoundRectangle(double aX, double aY, double aWidth, double aHeight, double anArcWidth, double anArcHeight) { this(aX, aY, aWidth, aHeight, anArcWidth, anArcHeight, Filling.NOT_FILLED); } public FGERoundRectangle(double aX, double aY, double aWidth, double aHeight, double anArcWidth, double anArcHeight, Filling filling) { super(aX, aY, aWidth, aHeight, anArcWidth, anArcHeight); if (aWidth < 0) { x = x + aWidth; aWidth = -aWidth; } if (aHeight < 0) { y = y + aHeight; aHeight = -aHeight; } _filling = filling; } public FGERoundRectangle(FGEPoint p1, FGEPoint p2, double anArcWidth, double anArcHeight, Filling filling) { this(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y), anArcWidth, anArcHeight, filling); } @Override public boolean getIsFilled() { return _filling == Filling.FILLED; } @Override public void setIsFilled(boolean filled) { _filling = filled ? Filling.FILLED : Filling.NOT_FILLED; } @Override public FGEPoint getCenter() { return new FGEPoint(getCenterX(), getCenterY()); } /** * Creates a new object of the same class and with the same contents as this object. * * @return a clone of this instance. * @exception OutOfMemoryError * if there is not enough memory. * @see java.lang.Cloneable * @since 1.2 */ @Override public FGERoundRectangle clone() { return (FGERoundRectangle) super.clone(); } public FGEPoint getNorthWestPt() { return getNorth().getP1(); } public FGEPoint getNorthPt() { return getNorth().getMiddle(); } public FGEPoint getNorthEastPt() { return getNorth().getP2(); } public FGEPoint getSouthWestPt() { return getSouth().getP1(); } public FGEPoint getSouthPt() { return getSouth().getMiddle(); } public FGEPoint getSouthEastPt() { return getSouth().getP2(); } public FGEPoint getEastPt() { return getEast().getMiddle(); } public FGEPoint getWestPt() { return getWest().getMiddle(); } public FGESegment getNorth() { return new FGESegment(getX(), getY(), getX() + getWidth(), getY()); } public FGESegment getSouth() { return new FGESegment(getX(), getY() + getHeight(), getX() + getWidth(), getY() + getHeight()); } public FGESegment getEast() { return new FGESegment(getX() + getWidth(), getY(), getX() + getWidth(), getY() + getHeight()); } public FGESegment getWest() { return new FGESegment(getX(), getY(), getX(), getY() + getHeight()); } public FGESegment getArcExcludedNorth() { return new FGESegment(getX() + arcwidth / 2, getY(), getX() + getWidth() - arcwidth / 2, getY()); } public FGESegment getArcExcludedSouth() { return new FGESegment(getX() + arcwidth / 2, getY() + getHeight(), getX() + getWidth() - arcwidth / 2, getY() + getHeight()); } public FGESegment getArcExcludedEast() { return new FGESegment(getX() + getWidth(), getY() + archeight / 2, getX() + getWidth(), getY() - archeight / 2 + getHeight()); } public FGESegment getArcExcludedWest() { return new FGESegment(getX(), getY() + archeight / 2, getX(), getY() + getHeight() - archeight / 2); } public List<FGESegment> getFrameSegments() { Vector<FGESegment> returned = new Vector<FGESegment>(); returned.add(getNorth()); returned.add(getSouth()); returned.add(getEast()); returned.add(getWest()); return returned; } @Override public FGEPoint getNearestPoint(FGEPoint aPoint) { if (getIsFilled() && containsPoint(aPoint)) { return aPoint.clone(); } return nearestOutlinePoint(aPoint); } @Override public FGEPoint nearestOutlinePoint(FGEPoint aPoint) { FGEPoint returned = null; double distSq, minimalDistanceSq = java.lang.Double.POSITIVE_INFINITY; FGESegment north = getNorth(); FGESegment south = getSouth(); FGESegment east = getEast(); FGESegment west = getWest(); FGEPoint p = north.getNearestPointOnSegment(aPoint); distSq = FGEPoint.distanceSq(p, aPoint); if (distSq < minimalDistanceSq) { returned = p; minimalDistanceSq = distSq; } p = south.getNearestPointOnSegment(aPoint); distSq = FGEPoint.distanceSq(p, aPoint); if (distSq < minimalDistanceSq) { returned = p; minimalDistanceSq = distSq; } p = east.getNearestPointOnSegment(aPoint); distSq = FGEPoint.distanceSq(p, aPoint); if (distSq < minimalDistanceSq) { returned = p; minimalDistanceSq = distSq; } p = west.getNearestPointOnSegment(aPoint); distSq = FGEPoint.distanceSq(p, aPoint); if (distSq < minimalDistanceSq) { returned = p; minimalDistanceSq = distSq; } if (returned == null) { returned = new FGEPoint(0, 0); } if (getNorthWestRoundBounds().containsPoint(returned)) { // System.out.println("nearestOutlinePoint() in NW"); return getNorthWestRound().nearestOutlinePoint(aPoint); } if (getSouthWestRoundBounds().containsPoint(returned)) { // System.out.println("nearestOutlinePoint() in SW"); return getSouthWestRound().nearestOutlinePoint(aPoint); } if (getNorthEastRoundBounds().containsPoint(returned)) { // System.out.println("nearestOutlinePoint() in NE"); return getNorthEastRound().nearestOutlinePoint(aPoint); } if (getSouthEastRoundBounds().containsPoint(returned)) { // System.out.println("nearestOutlinePoint() in SE"); return getSouthEastRound().nearestOutlinePoint(aPoint); } return returned; } /** * Return nearest point from point "from" following supplied orientation * * Returns null if no intersection was found * * @param from * point from which we are coming to area * @param orientation * orientation we are coming from * @return */ @Override public FGEPoint nearestPointFrom(FGEPoint from, SimplifiedCardinalDirection orientation) { FGEHalfLine hl = FGEHalfLine.makeHalfLine(from, orientation); FGEArea intersection = computeLineIntersection(hl); if (intersection instanceof FGEEmptyArea) { return null; } else if (intersection instanceof FGEPoint) { return (FGEPoint) intersection; } else if (intersection instanceof FGEUnionArea) { double minimalDistanceSq = java.lang.Double.POSITIVE_INFINITY; FGEPoint returned = null; for (FGEArea a : ((FGEUnionArea) intersection).getObjects()) { if (a instanceof FGEPoint) { double distSq = FGEPoint.distanceSq(from, (FGEPoint) a); if (distSq < minimalDistanceSq) { returned = (FGEPoint) a; minimalDistanceSq = distSq; } } } return returned; } else if (intersection instanceof FGESegment) { FGEPoint p1, p2; p1 = ((FGESegment) intersection).getP1(); p2 = ((FGESegment) intersection).getP2(); if (FGEPoint.distanceSq(from, p1) < FGEPoint.distanceSq(from, p2)) { return p1; } else { return p2; } } else { logger.warning("Unexpected area: " + intersection); return null; } /*if (getNorthWestRoundBounds().contains(returned)) { //System.out.println("outlineIntersect() in NW"); return getNorthWestRound().nearestPointFrom(returned,orientation); } if (getSouthWestRoundBounds().contains(returned)) { //System.out.println("outlineIntersect() in SW"); return getSouthWestRound().nearestPointFrom(returned,orientation); } if (getNorthEastRoundBounds().contains(returned)) { //System.out.println("outlineIntersect() in NE"); return getNorthEastRound().nearestPointFrom(returned,orientation); } if (getSouthEastRoundBounds().contains(returned)) { //System.out.println("outlineIntersect() in SE"); return getSouthEastRound().nearestPointFrom(returned,orientation); }*/ // return returned; } protected FGEArc getNorthWestRound() { return new FGEArc(x, y, arcwidth, archeight, 90, 90); } protected FGEArc getFilledNorthWestRound() { return new FGEArc(x, y, arcwidth, archeight, 90, 90, ArcType.PIE); } protected FGEArc getSouthWestRound() { return new FGEArc(x, y + height - archeight, arcwidth, archeight, 180, 90); } protected FGEArc getFilledSouthWestRound() { return new FGEArc(x, y + height - archeight, arcwidth, archeight, 180, 90, ArcType.PIE); } protected FGEArc getNorthEastRound() { return new FGEArc(x + width - arcwidth, y, arcwidth, archeight, 0, 90); } protected FGEArc getFilledNorthEastRound() { return new FGEArc(x + width - arcwidth, y, arcwidth, archeight, 0, 90, ArcType.PIE); } protected FGEArc getSouthEastRound() { return new FGEArc(x + width - arcwidth, y + height - archeight, arcwidth, archeight, -90, 90); } protected FGEArc getFilledSouthEastRound() { return new FGEArc(x + width - arcwidth, y + height - archeight, arcwidth, archeight, -90, 90, ArcType.PIE); } protected FGERectangle getNorthWestRoundBounds() { return getNorthWestRound().getBoundingBox(); } protected FGERectangle getSouthWestRoundBounds() { return getSouthWestRound().getBoundingBox(); } protected FGERectangle getNorthEastRoundBounds() { return getNorthEastRound().getBoundingBox(); } protected FGERectangle getSouthEastRoundBounds() { return getSouthEastRound().getBoundingBox(); } private FGEArea computeRectangleIntersection(FGERoundRectangle rect) { Vector<FGEPoint> pts = new Vector<FGEPoint>() { @Override public synchronized boolean add(FGEPoint o) { if (!contains(o)) { return super.add(o); } return false; } }; List<FGESegment> sl = rect.getFrameSegments(); for (FGESegment seg : sl) { FGEArea a = intersect(seg); if (a instanceof FGEPoint) { pts.add((FGEPoint) a); } else if (a instanceof FGESegment) { pts.add(((FGESegment) a).getP1()); pts.add(((FGESegment) a).getP2()); } else if (a instanceof FGEUnionArea) { for (FGEArea a2 : ((FGEUnionArea) a).getObjects()) { if (a2 instanceof FGEPoint) { pts.add((FGEPoint) a2); } if (a2 instanceof FGESegment) { pts.add(((FGESegment) a2).getP1()); pts.add(((FGESegment) a2).getP2()); } } } } FGEPoint ne, nw, se, sw; ne = new FGEPoint(x + width, y); nw = new FGEPoint(x, y); se = new FGEPoint(x + width, y + height); sw = new FGEPoint(x, y + height); if (rect.containsPoint(ne)) { pts.add(ne); } if (rect.containsPoint(nw)) { pts.add(nw); } if (rect.containsPoint(se)) { pts.add(se); } if (rect.containsPoint(sw)) { pts.add(sw); } if (pts.size() == 0) { return new FGEEmptyArea(); } else if (pts.size() == 2) { return new FGESegment(pts.firstElement(), pts.elementAt(1)); } else if (pts.size() != 4) { logger.warning("Strange situation here while computeRectangleIntersection between " + this + " and " + rect); } double minx = java.lang.Double.POSITIVE_INFINITY; double miny = java.lang.Double.POSITIVE_INFINITY; double maxx = java.lang.Double.NEGATIVE_INFINITY; double maxy = java.lang.Double.NEGATIVE_INFINITY; for (FGEPoint p : pts) { if (p.x < minx) { minx = p.x; } if (p.y < miny) { miny = p.y; } if (p.x > maxx) { maxx = p.x; } if (p.y > maxy) { maxy = p.y; } } return new FGERoundRectangle(minx, miny, maxx - minx, maxy - miny, arcwidth, archeight, Filling.FILLED); } private FGEArea computeHalfPlaneIntersection(FGEHalfPlane hp) { if (hp.containsArea(this)) { return this.clone(); } FGEArea computeLineIntersection = computeLineIntersection(hp.line); if (computeLineIntersection instanceof FGEEmptyArea) { return new FGEEmptyArea(); } else { if (logger.isLoggable(Level.FINE)) { logger.fine("computeHalfPlaneIntersection() for rectangle when halfplane cross rectangle"); } FGEArea a = computeLineIntersection; Vector<FGEPoint> pts = new Vector<FGEPoint>(); if (a instanceof FGEUnionArea && ((FGEUnionArea) a).isUnionOfPoints() && ((FGEUnionArea) a).getObjects().size() == 2) { pts.add((FGEPoint) ((FGEUnionArea) a).getObjects().firstElement()); pts.add((FGEPoint) ((FGEUnionArea) a).getObjects().elementAt(1)); } else if (a instanceof FGESegment) { if (getArcExcludedEast().containsArea(a) || getArcExcludedWest().containsArea(a) || getArcExcludedNorth().containsArea(a) || getArcExcludedSouth().containsArea(a)) { return a; } pts.add(((FGESegment) a).getP1()); pts.add(((FGESegment) a).getP2()); } FGEPoint ne, nw, se, sw; ne = new FGEPoint(x + width, y); nw = new FGEPoint(x, y); se = new FGEPoint(x + width, y + height); sw = new FGEPoint(x, y + height); if (hp.containsPoint(ne) && !pts.contains(ne)) { pts.add(ne); } if (hp.containsPoint(nw) && !pts.contains(nw)) { pts.add(nw); } if (hp.containsPoint(se) && !pts.contains(se)) { pts.add(se); } if (hp.containsPoint(sw) && !pts.contains(sw)) { pts.add(sw); } if (getIsFilled()) { return FGEPolygon.makeArea(Filling.FILLED, pts); } else { return new FGEUnionArea(pts); } } } private FGEArea computeLineIntersection(FGEAbstractLine line) { FGERectangle rectangle = new FGERectangle(x, y, width, height, _filling); FGEArea returned = rectangle.intersect(line); if (returned instanceof FGEEmptyArea) { return returned; } else if (returned instanceof FGEPoint) { FGEPoint p = (FGEPoint) returned; if (containsPoint(p)) { return p; } if (getNorthEastRoundBounds().containsPoint(p)) { return getNorthEastRound().intersect(line); } if (getSouthEastRoundBounds().containsPoint(p)) { return getSouthEastRound().intersect(line); } if (getNorthWestRoundBounds().containsPoint(p)) { return getNorthWestRound().intersect(line); } if (getSouthWestRoundBounds().containsPoint(p)) { return getSouthWestRound().intersect(line); } return new FGEEmptyArea(); } else { FGEPoint p1; FGEPoint p2; if (returned instanceof FGEUnionArea && ((FGEUnionArea) returned).isUnionOfPoints()) { p1 = (FGEPoint) ((FGEUnionArea) returned).getObjects().firstElement(); p2 = (FGEPoint) ((FGEUnionArea) returned).getObjects().elementAt(1); if (containsPoint(p1) && containsPoint(p2)) { return returned; } } else if (returned instanceof FGESegment) { p1 = ((FGESegment) returned).getP1(); p2 = ((FGESegment) returned).getP2(); boolean p1Contained = containsPoint(p1); boolean p2Contained = containsPoint(p2); if (p1Contained && p2Contained) { return returned; } else if (p1Contained || p2Contained) { FGEPoint contained = p1Contained ? p1 : p2; FGEArea p = getNorthEastRound().intersect(returned); if (p instanceof FGEPoint) { return new FGESegment(contained, (FGEPoint) p); } p = getNorthWestRound().intersect(returned); if (p instanceof FGEPoint) { return new FGESegment(contained, (FGEPoint) p); } p = getSouthEastRound().intersect(returned); if (p instanceof FGEPoint) { return new FGESegment(contained, (FGEPoint) p); } p = getSouthWestRound().intersect(returned); if (p instanceof FGEPoint) { return new FGESegment(contained, (FGEPoint) p); } } else { FGEArea area = getNorthEastRound().intersect(returned); FGEPoint p = null; if (area instanceof FGEPoint) { if (p != null) { return new FGESegment(p, (FGEPoint) area); } else { p = (FGEPoint) area; } } area = getNorthWestRound().intersect(returned); if (area instanceof FGEPoint) { if (p != null) { return new FGESegment(p, (FGEPoint) area); } else { p = (FGEPoint) area; } } area = getSouthEastRound().intersect(returned); if (area instanceof FGEPoint) { if (p != null) { return new FGESegment(p, (FGEPoint) area); } else { p = (FGEPoint) area; } } area = getSouthWestRound().intersect(returned); if (area instanceof FGEPoint) { if (p != null) { return new FGESegment(p, (FGEPoint) area); } else { p = (FGEPoint) area; } } if (p != null) { return p; } else { return new FGEEmptyArea(); } } } else { logger.warning("Unexpected " + returned); return new FGEEmptyArea(); } FGEArea newP1 = p1; FGEArea newP2 = p2; if (getNorthEastRoundBounds().containsPoint(p1)) { newP1 = getNorthEastRound().intersect(line); } if (getSouthEastRoundBounds().containsPoint(p1)) { newP1 = getSouthEastRound().intersect(line); } if (getNorthWestRoundBounds().containsPoint(p1)) { newP1 = getNorthWestRound().intersect(line); } if (getSouthWestRoundBounds().containsPoint(p1)) { newP1 = getSouthWestRound().intersect(line); } if (getNorthEastRoundBounds().containsPoint(p2)) { newP2 = getNorthEastRound().intersect(line); } if (getSouthEastRoundBounds().containsPoint(p2)) { newP2 = getSouthEastRound().intersect(line); } if (getNorthWestRoundBounds().containsPoint(p2)) { newP2 = getNorthWestRound().intersect(line); } if (getSouthWestRoundBounds().containsPoint(p2)) { newP2 = getSouthWestRound().intersect(line); } if (newP1 instanceof FGEPoint) { if (newP2 instanceof FGEPoint) { if (returned instanceof FGEUnionArea) { return new FGEUnionArea(newP1, newP2); } else if (returned instanceof FGESegment) { return new FGESegment((FGEPoint) newP1, (FGEPoint) newP2); } } else if (newP2 instanceof FGEEmptyArea) { return newP1; } } else if (newP1 instanceof FGEEmptyArea) { if (newP2 instanceof FGEPoint) { return newP2; } else { return new FGEEmptyArea(); } } else if (newP1 instanceof FGEUnionArea && ((FGEUnionArea) newP1).isUnionOfPoints() && newP2 instanceof FGEUnionArea && ((FGEUnionArea) newP2).isUnionOfPoints() && newP1.equals(newP2)) { return newP1; } logger.warning("Unexpected " + returned + " newP1=" + newP1 + " newP2=" + newP2); return new FGEEmptyArea(); } } @Override public FGEArea exclusiveOr(FGEArea area) { return new FGEExclusiveOrArea(this, area); } @Override public FGEArea intersect(FGEArea area) { if (area.containsArea(this)) { return this.clone(); } if (containsArea(area)) { return area.clone(); } if (area instanceof FGEAbstractLine) { return computeLineIntersection((FGEAbstractLine) area); } if (area instanceof FGERoundRectangle) { return computeRectangleIntersection((FGERoundRectangle) area); } if (area instanceof FGEHalfPlane) { return computeHalfPlaneIntersection((FGEHalfPlane) area); } FGEIntersectionArea returned = new FGEIntersectionArea(this, area); if (returned.isDevelopable()) { return returned.makeDevelopped(); } else { return returned; } } @Override public FGEArea substract(FGEArea area, boolean isStrict) { return new FGESubstractionArea(this, area, isStrict); } @Override public FGEArea union(FGEArea area) { if (containsArea(area)) { return clone(); } if (area.containsArea(this)) { return area.clone(); } return new FGEUnionArea(this, area); } @Override public List<FGEPoint> getControlPoints() { Vector<FGEPoint> returned = new Vector<FGEPoint>(); returned.add(new FGEPoint(x, y)); returned.add(new FGEPoint(x + width, y)); returned.add(new FGEPoint(x, y + height)); returned.add(new FGEPoint(x + width, y + height)); returned.add(getNorth().getMiddle()); returned.add(getEast().getMiddle()); returned.add(getWest().getMiddle()); returned.add(getSouth().getMiddle()); return returned; } @Override public boolean containsPoint(FGEPoint p) { if (p.x >= getX() - EPSILON && p.x <= getX() + getWidth() + EPSILON && p.y >= getY() - EPSILON && p.y <= getY() + getHeight() + EPSILON) { if (!getIsFilled()) { FGESegment north = getArcExcludedNorth(); FGESegment south = getArcExcludedSouth(); FGESegment west = getArcExcludedWest(); FGESegment east = getArcExcludedEast(); return north.contains(p) || south.contains(p) || east.contains(p) || west.contains(p) || getNorthEastRound().contains(p) || getNorthWestRound().contains(p) || getSouthEastRound().contains(p) || getSouthWestRound().contains(p); } else { if (new FGERectangle(new FGEPoint(getX(), getY() + archeight / 2), new FGEDimension(getWidth(), getHeight() - archeight), Filling.FILLED).contains(p)) { return true; } if (new FGERectangle(new FGEPoint(getX() + arcwidth / 2, getY()), new FGEDimension(getWidth() - arcwidth, getHeight()), Filling.FILLED).contains(p)) { return true; } return getFilledNorthEastRound().containsPoint(p) || getFilledNorthWestRound().containsPoint(p) || getFilledSouthEastRound().containsPoint(p) || getFilledSouthWestRound().containsPoint(p); } } return false; } @Override public boolean containsLine(FGEAbstractLine l) { if (l instanceof FGEHalfLine) { return false; } if (l instanceof FGESegment) { return containsPoint(l.getP1()) && containsPoint(l.getP2()); } return false; } @Override public boolean containsArea(FGEArea a) { if (a instanceof FGEPoint) { return containsPoint((FGEPoint) a); } if (a instanceof FGESegment) { return containsPoint(((FGESegment) a).getP1()) && containsPoint(((FGESegment) a).getP2()); } if (a instanceof FGEShape) { return FGEShape.AreaComputation.isShapeContainedInArea((FGEShape<?>) a, this); } return false; } @Override public FGEArea transform(AffineTransform t) { // TODO: not valid for AffineTransform containing rotations FGEPoint p1 = new FGEPoint(getX(), getY()).transform(t); FGEPoint p2 = new FGEPoint(getX() + getWidth(), getY() + getHeight()).transform(t); // TODO: if transformation contains a rotation, turn into a regular polygon // arcwidth,archeight must also be computed according to this rotation return new FGERoundRectangle(Math.min(p1.x, p2.x), Math.min(p1.y, p2.y), Math.abs(p1.x - p2.x), Math.abs(p1.y - p2.y), arcwidth * t.getScaleX(), archeight * t.getScaleY(), _filling); } @Override public void paint(FGEGraphics g) { if (getIsFilled()) { g.useDefaultBackgroundStyle(); g.fillRoundRect(getX(), getY(), getWidth(), getHeight(), arcwidth, archeight); } /*getNorthWestRoundBounds().paint(g); getSouthWestRoundBounds().paint(g); getNorthEastRoundBounds().paint(g); getSouthEastRoundBounds().paint(g);*/ /*getFilledNorthWestRound().paint(g); getFilledSouthWestRound().paint(g); getFilledNorthEastRound().paint(g); getFilledSouthEastRound().paint(g);*/ /*new FGERectangle( new FGEPoint(getX(),getY()+archeight/2), new FGEDimension(getWidth(),getHeight()-archeight),Filling.FILLED) .paint(g); new FGERectangle( new FGEPoint(getX()+arcwidth/2,getY()), new FGEDimension(getWidth()-arcwidth,getHeight()),Filling.FILLED) .paint(g);*/ g.useDefaultForegroundStyle(); g.drawRoundRect(getX(), getY(), getWidth(), getHeight(), arcwidth, archeight); } @Override public String toString() { return "FGERoundRectangle: (" + x + "," + y + "," + width + "," + height + "," + arcwidth + "," + archeight + ")"; } @Override public String getStringRepresentation() { return toString(); } @Override public FGERectangle getBoundingBox() { return new FGERectangle(x, y, width, height); } @Override public boolean equals(Object obj) { if (obj instanceof FGERoundRectangle) { FGERoundRectangle p = (FGERoundRectangle) obj; if (getIsFilled() != p.getIsFilled()) { return false; } return Math.abs(getX() - p.getX()) <= EPSILON && Math.abs(getY() - p.getY()) <= EPSILON && Math.abs(getWidth() - p.getWidth()) <= EPSILON && Math.abs(getHeight() - p.getHeight()) <= EPSILON && Math.abs(getArcWidth() - p.getArcWidth()) <= EPSILON && Math.abs(getArcHeight() - p.getArcHeight()) <= EPSILON; } return super.equals(obj); } @Override public FGEArea getOrthogonalPerspectiveArea(SimplifiedCardinalDirection orientation) { return getAnchorAreaFrom(orientation).getOrthogonalPerspectiveArea(orientation); } @Override public FGEArea getAnchorAreaFrom(SimplifiedCardinalDirection orientation) { if (orientation == SimplifiedCardinalDirection.NORTH) { FGEArc northWestRound = getNorthWestRound(); northWestRound.extent = 45; FGEArc northEastRound = getNorthEastRound(); northEastRound.extent = 45; northEastRound.start += 45; return new FGEUnionArea(getArcExcludedNorth(), northWestRound, northEastRound); } else if (orientation == SimplifiedCardinalDirection.SOUTH) { // return getSouth(); FGEArc southWestRound = getSouthWestRound(); southWestRound.start += 45; southWestRound.extent = 45; FGEArc southEastRound = getSouthEastRound(); southEastRound.extent = 45; return new FGEUnionArea(getArcExcludedSouth(), southWestRound, southEastRound); } else if (orientation == SimplifiedCardinalDirection.EAST) { // return getEast(); FGEArc northEastRound = getNorthEastRound(); northEastRound.extent = 45; FGEArc southEastRound = getSouthEastRound(); southEastRound.extent = 45; southEastRound.start += 45; return new FGEUnionArea(getArcExcludedEast(), northEastRound, southEastRound); } else if (orientation == SimplifiedCardinalDirection.WEST) { // return getWest(); FGEArc northWestRound = getNorthWestRound(); northWestRound.extent = 45; northWestRound.start += 45; FGEArc southWestRound = getSouthWestRound(); southWestRound.extent = 45; return new FGEUnionArea(getArcExcludedWest(), northWestRound, southWestRound); } logger.warning("Unexpected: " + orientation); return null; } /** * This area is finite, so always return true */ @Override public final boolean isFinite() { return true; } /** * This area is finite, so always return null */ @Override public final FGERectangle getEmbeddingBounds() { return new FGERectangle(x, y, width, height, Filling.FILLED); } }