### Eclipse Workspace Patch 1.0 #P org.eclipse.gef4.geometry Index: src/org/eclipse/gef4/geometry/Angle.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/Angle.java,v retrieving revision 1.2 diff -u -r1.2 Angle.java --- src/org/eclipse/gef4/geometry/Angle.java 10 Nov 2011 13:50:50 -0000 1.2 +++ src/org/eclipse/gef4/geometry/Angle.java 10 Nov 2011 14:57:14 -0000 @@ -102,6 +102,12 @@ } /** + * Constructs a new {@link Angle} object initialized with 0deg/0rad. + */ + public Angle() { + } + + /** * Overwritten with public visibility as proposed in {@link Cloneable}. */ @Override @@ -120,8 +126,24 @@ @Override public boolean equals(Object otherObj) { - Angle other = (Angle) otherObj; - return PrecisionUtils.equal(other.rad, this.rad); + if (otherObj != null && otherObj instanceof Angle) { + Angle other = (Angle) otherObj; + + double myRad = this.rad; + double otherRad = other.rad; + + final double hi = 1.5 * Math.PI; + final double lo = 0.5 * Math.PI; + + if (myRad > hi && otherRad < lo) { + otherRad += RAD_360; + } else if (myRad < lo && otherRad > hi) { + myRad += RAD_360; + } + + return PrecisionUtils.equal(myRad, otherRad); + } + return false; } /** @@ -137,6 +159,19 @@ } /** + * Returns a new {@link Angle} object representing this angle multiplied by + * the given factor. + * + * @param factor + * The multiplication factor. + * @return a new {@link Angle} object representing this angle multiplied by + * the given factor. + */ + public Angle getMultiplied(double factor) { + return Angle.fromRad(rad * factor); + } + + /** * Creates and returns a copy of this {@link Angle}. * * @return a copy of this {@link Angle} @@ -167,6 +202,19 @@ return Angle.fromRad(RAD_180 - rad); } + /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // calculating a better hashCode is not possible + return 0; + } + + /** + * Normalizes this {@link Angle} to the range from 0deg to 360deg or rather + * from 0 to 2pi. + */ private Angle normalize() { rad -= RAD_360 * Math.floor(rad / RAD_360); return this; @@ -208,7 +256,7 @@ */ @Override public String toString() { - return super.toString() + ": " + Double.toString(rad) + "rad (" - + Double.toString(deg()) + "deg)"; + return "Angle(" + Double.toString(rad) + "rad (" + + Double.toString(deg()) + "deg))"; } } Index: src/org/eclipse/gef4/geometry/Dimension.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/Dimension.java,v retrieving revision 1.4 diff -u -r1.4 Dimension.java --- src/org/eclipse/gef4/geometry/Dimension.java 31 Oct 2011 19:36:06 -0000 1.4 +++ src/org/eclipse/gef4/geometry/Dimension.java 10 Nov 2011 14:57:14 -0000 @@ -135,7 +135,7 @@ * Overwritten with public visibility as proposed in {@link Cloneable}. */ @Override - public Object clone() throws CloneNotSupportedException { + public Dimension clone() { return getCopy(); } @@ -281,6 +281,20 @@ } /** + * Creates a new Dimension with its width and height scaled by the specified + * values. + * + * @param widthFactor + * the value by which the width is to be scaled + * @param heightFactor + * the value by which the height is to be scaled + * @return a new dimension with the scale applied + */ + public Dimension getScaled(double widthFactor, double heightFactor) { + return getCopy().scale(widthFactor, heightFactor); + } + + /** * Creates and returns a new Dimension whose size will be reduced by the * width and height of the given Dimension. * @@ -294,7 +308,7 @@ /** * Creates and returns a new Dimension whose size will be reduced by the - * width and height of the given Dimension. + * given width and height. * * @param w * the value by which the width is to be reduced @@ -302,7 +316,7 @@ * the value by which the height is to be reduced * @return a new dimension representing the difference */ - public Dimension getShrinked(int w, int h) { + public Dimension getShrinked(double w, double h) { return getCopy().shrink(w, h); } @@ -334,7 +348,9 @@ */ @Override public int hashCode() { - return (int) (width * height) ^ (int) (width + height); + // calculating a better hashCode is not possible + return 0; + // return (int) (width * height) ^ (int) (width + height); } /** Index: src/org/eclipse/gef4/geometry/Point.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/Point.java,v retrieving revision 1.3 diff -u -r1.3 Point.java --- src/org/eclipse/gef4/geometry/Point.java 31 Oct 2011 19:36:06 -0000 1.3 +++ src/org/eclipse/gef4/geometry/Point.java 10 Nov 2011 14:57:14 -0000 @@ -126,7 +126,7 @@ * Overwritten with public visibility as proposed in {@link Cloneable}. */ @Override - public Object clone() throws CloneNotSupportedException { + public Point clone() { return getCopy(); } @@ -203,6 +203,19 @@ } /** + * Creates a new Point from this Point by scaling by the specified values. + * + * @param xFactor + * horizontal scale factor + * @param yFactor + * vertical scale factor + * @return A new Point + */ + public Point getScaled(double xFactor, double yFactor) { + return getCopy().scale(xFactor, yFactor); + } + + /** * Creates a new SWT {@link org.eclipse.swt.graphics.Point Point} from this * Point. * @@ -264,7 +277,9 @@ */ @Override public int hashCode() { - return (int) (x * y) ^ (int) (x + y); + // calculating a better hashCode is not possible + return 0; + // return (int) (x * y) ^ (int) (x + y); } /** Index: src/org/eclipse/gef4/geometry/euclidean/Straight.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/euclidean/Straight.java,v retrieving revision 1.4 diff -u -r1.4 Straight.java --- src/org/eclipse/gef4/geometry/euclidean/Straight.java 31 Oct 2011 19:36:06 -0000 1.4 +++ src/org/eclipse/gef4/geometry/euclidean/Straight.java 10 Nov 2011 14:57:14 -0000 @@ -41,10 +41,10 @@ * @param direction */ public Straight(Vector position, Vector direction) { - if (direction.isNull()) { - throw new IllegalArgumentException( - "direction has to be unequal to (0,0)"); //$NON-NLS-1$ - } + // if (direction.isNull()) { + // throw new IllegalArgumentException( + // "direction has to be unequal to (0,0)"); //$NON-NLS-1$ + // } this.position = position.clone(); this.direction = direction.clone(); } @@ -63,7 +63,7 @@ @Override public Straight clone() { - return new Straight(position, direction); + return getCopy(); } /** @@ -208,14 +208,21 @@ * {@link Straight}s. * * The returned angle is the opposite of the angle returned by the - * getAngleCCW(Straight other) method. + * getAngleCCW(Straight other) but for an angle of 0\u00b0. For an angle of + * 0\u00b0 both methods return an angle of 0 degrees. * * @param other * @return The clock-wise (CW) or negative angle spanned between the two * {@link Straight}s. */ public Angle getAngleCW(Straight other) { - return getAngleCCW(other).getOppositeSemi(); + Angle angle = getAngleCCW(other); + Angle angle0 = Angle.fromRad(0); + if (angle.equals(angle0)) { + // special-case 0°: CW/CCW does not matter + return angle0; + } + return angle.getOppositeSemi(); } /** @@ -288,9 +295,9 @@ double len = d.getLength(); if (!d.isNull()) { - Angle angleCCW = direction.getAngleCW(d); + Angle angleCW = direction.getAngleCW(d); - if (angleCCW.equals(Angle.fromDeg(90))) { + if (angleCW.equals(Angle.fromDeg(90))) { len = -len; } } @@ -303,8 +310,8 @@ * * The signed distance indicates on which side of the Straight the Vector * lies. If it is on the right side of this Straight's direction Vector, the - * signed distance is negative. If it is on the left side of this Straight's - * direction Vector, the signed distance is positive. + * signed distance is positive. If it is on the left side of this Straight's + * direction Vector, the signed distance is negative. * * @param vector * @return the signed distance of the given {@link Vector} to this Straight @@ -445,8 +452,11 @@ /** * @see java.lang.Object#hashCode() */ + @Override public int hashCode() { - return position.hashCode() + direction.hashCode(); + // calculating a better hashCode is not possible + return 0; + // return position.hashCode() + direction.hashCode(); } /** @@ -456,4 +466,13 @@ return "Straight: " + position.toString() + " + s * " + direction.toString(); //$NON-NLS-1$ } + /** + * Returns a copy of this {@link Straight} object. + * + * @return a copy of this {@link Straight} object. + */ + public Straight getCopy() { + return new Straight(position, direction); + } + } \ No newline at end of file Index: src/org/eclipse/gef4/geometry/euclidean/Vector.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/euclidean/Vector.java,v retrieving revision 1.6 diff -u -r1.6 Vector.java --- src/org/eclipse/gef4/geometry/euclidean/Vector.java 10 Nov 2011 09:23:19 -0000 1.6 +++ src/org/eclipse/gef4/geometry/euclidean/Vector.java 10 Nov 2011 14:57:14 -0000 @@ -93,24 +93,36 @@ } /** - * Clones the given Vector object. + * Clones the given {@link Vector} using {@link Vector#getCopy()}. + * + * @return a copy of this {@link Vector} object. */ @Override public Vector clone() { + return getCopy(); + } + + /** + * Returns a copy of this {@link Vector} object. + * + * @return a copy of this {@link Vector} object. + */ + public Vector getCopy() { return new Vector(x, y); } /** - * Calculates the magnitude of the cross product of this Vector with - * another. Represents the amount by which two Vectors are directionally - * different. Parallel Vectors return a value of 0. + * Calculates the magnitude of the cross product of this {@link Vector} with + * another. Normalized the {@link Vector}s before calculating the cross + * product. Represents the amount by which two {@link Vector}s are + * directionally different. Parallel {@link Vector}s return a value of 0. * * @param other * The {@link Vector} being compared * @return The dissimilarity */ public double getDissimilarity(Vector other) { - return Math.abs(getCrossProduct(other)); + return Math.abs(getNormalized().getCrossProduct(other.getNormalized())); } /** @@ -180,8 +192,20 @@ * @return the smallest {@link Angle} between the two Vectors. */ public Angle getAngle(Vector other) { - double cosAlpha = getDotProduct(other) - / (getLength() * other.getLength()); + double length = getLength() * other.getLength(); + if (length == 0) { + throw new ArithmeticException("Division by zero."); + } + + double cosAlpha = getDotProduct(other) / length; + + // compensate rounding effects + if (cosAlpha > 1) { + cosAlpha = 1; + } else if (cosAlpha < -1) { + cosAlpha = -1; + } + return Angle.fromRad(Math.acos(cosAlpha)); } @@ -246,6 +270,9 @@ * @return a new Vector */ public Vector getDivided(double factor) { + if (factor == 0) { + throw new ArithmeticException("division by zero"); + } return new Vector(x / factor, y / factor); } @@ -383,7 +410,9 @@ */ @Override public int hashCode() { - return (int) x + (int) y; + // calculating a better hashCode is not possible + return 0; + // return (int) x + (int) y; } /** Index: src/org/eclipse/gef4/geometry/shapes/CubicCurve.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/CubicCurve.java,v retrieving revision 1.5 diff -u -r1.5 CubicCurve.java --- src/org/eclipse/gef4/geometry/shapes/CubicCurve.java 31 Oct 2011 21:56:41 -0000 1.5 +++ src/org/eclipse/gef4/geometry/shapes/CubicCurve.java 10 Nov 2011 14:57:14 -0000 @@ -511,6 +511,15 @@ } /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // calculating a better hashCode is not possible + return 0; + } + + /** * @see org.eclipse.gef4.geometry.shapes.Geometry#intersects(Rectangle) */ public boolean intersects(Rectangle r) { Index: src/org/eclipse/gef4/geometry/shapes/Ellipse.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/Ellipse.java,v retrieving revision 1.12 diff -u -r1.12 Ellipse.java --- src/org/eclipse/gef4/geometry/shapes/Ellipse.java 31 Oct 2011 19:36:06 -0000 1.12 +++ src/org/eclipse/gef4/geometry/shapes/Ellipse.java 10 Nov 2011 14:57:14 -0000 @@ -269,7 +269,7 @@ * otherwise */ public Point[] getIntersections(Polygon polygon) { - List intersections = new ArrayList(); + HashSet intersections = new HashSet(); for (Line segment : polygon.getSegments()) { for (Point intersection : getIntersections(segment)) { @@ -475,9 +475,15 @@ return y; } + /** + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - return (int) ((x + height + 1) * (y + width + 1)) ^ (int) x ^ (int) y; + // calculating a better hashCode is not possible + return 0; + // return (int) ((x + height + 1) * (y + width + 1)) ^ (int) x ^ (int) + // y; } /** Index: src/org/eclipse/gef4/geometry/shapes/Line.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/Line.java,v retrieving revision 1.8 diff -u -r1.8 Line.java --- src/org/eclipse/gef4/geometry/shapes/Line.java 31 Oct 2011 19:36:06 -0000 1.8 +++ src/org/eclipse/gef4/geometry/shapes/Line.java 10 Nov 2011 14:57:15 -0000 @@ -111,7 +111,11 @@ return PrecisionUtils.equal(x1, this.x1) && PrecisionUtils.equal(y1, this.y1) && PrecisionUtils.equal(x2, this.x2) - && PrecisionUtils.equal(y2, this.y2); + && PrecisionUtils.equal(y2, this.y2) + || PrecisionUtils.equal(x2, this.x1) + && PrecisionUtils.equal(y2, this.y1) + && PrecisionUtils.equal(x1, this.x2) + && PrecisionUtils.equal(y1, this.y2); } @Override @@ -260,9 +264,14 @@ return y2; } + /** + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - return (int) x1 + (int) y1 + (int) x2 + (int) y2; + // calculating a better hashCode is not possible + return 0; + // return (int) x1 + (int) y1 + (int) x2 + (int) y2; } /** Index: src/org/eclipse/gef4/geometry/shapes/Polygon.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/Polygon.java,v retrieving revision 1.9 diff -u -r1.9 Polygon.java --- src/org/eclipse/gef4/geometry/shapes/Polygon.java 31 Oct 2011 19:36:06 -0000 1.9 +++ src/org/eclipse/gef4/geometry/shapes/Polygon.java 10 Nov 2011 14:57:15 -0000 @@ -13,6 +13,7 @@ package org.eclipse.gef4.geometry.shapes; import java.util.ArrayList; +import java.util.HashSet; import org.eclipse.gef4.geometry.Angle; import org.eclipse.gef4.geometry.Point; @@ -74,7 +75,7 @@ * Overwritten with public visibility as recommended in {@link Cloneable}. */ @Override - public Object clone() throws CloneNotSupportedException { + public Polygon clone() { return getCopy(); } @@ -118,7 +119,9 @@ if (line.intersects(segment)) { Point intersection = line.getIntersection(segment); if (intersection != null && !line.getP1().equals(intersection) - && !line.getP2().equals(intersection)) { + && !line.getP2().equals(intersection) + && !segment.getP1().equals(intersection) + && !segment.getP2().equals(intersection)) { // if we have a single intersection point and this does not // match one of the end points of the line, the line is not // contained @@ -137,7 +140,7 @@ * @return The points of intersection. */ public Point[] getIntersections(Line l) { - ArrayList intersections = new ArrayList(); + HashSet intersections = new HashSet(); for (Line segment : getSegments()) { Point poi = segment.getIntersection(l); @@ -157,7 +160,7 @@ * @return The points of intersection. */ public Point[] getIntersections(Polygon polygon) { - ArrayList intersections = new ArrayList(); + HashSet intersections = new HashSet(); for (Line segment : polygon.getSegments()) { for (Point poi : getIntersections(segment)) { @@ -176,7 +179,7 @@ * @return The points of intersection. */ public Point[] getIntersections(Polyline polyline) { - ArrayList intersections = new ArrayList(); + HashSet intersections = new HashSet(); for (Line segment : polyline.getSegments()) { for (Point poi : getIntersections(segment)) { @@ -195,7 +198,7 @@ * @return The points of intersection. */ public Point[] getIntersections(Rectangle rect) { - ArrayList intersections = new ArrayList(); + HashSet intersections = new HashSet(); for (Line segment : rect.getSegments()) { for (Point poi : getIntersections(segment)) { @@ -251,7 +254,16 @@ Vector v1 = new Vector(points[i]); Vector v2 = new Vector( points[i + 1 < points.length ? i + 1 : 0]); - Straight s2 = new Straight(v1, v2.getSubtracted(v1)); + Vector direction = v2.getSubtracted(v1); + + if (direction.isNull()) { + if (v1.equals(u1)) { + return true; + } + continue; + } + + Straight s2 = new Straight(v1, direction); // check whether the point is located on the current side if (s2.containsWithinSegment(v1, v2, u1)) { @@ -389,37 +401,84 @@ } /** + * Pair of {@link Line} segment and integer counter to count segments of + * {@link Polygon}s. + */ + private class SegmentCounter { + public Line segment; + public int count; + + public SegmentCounter(Line segment, int count) { + this.segment = segment; + this.count = count; + } + } + + /** + * List of {@link SegmentCounter}s to count segments of {@link Polygon}s. + */ + private class SegmentList { + public ArrayList segmentCounterList; + + public SegmentList() { + segmentCounterList = new ArrayList(); + } + + public SegmentCounter find(Line segment) { + for (SegmentCounter i : segmentCounterList) { + if (segment.equals(i.segment)) { + return i; + } + } + // segment not in list, create new segmentcounter for it + SegmentCounter newSegCounter = new SegmentCounter(segment, 0); + segmentCounterList.add(newSegCounter); + return newSegCounter; + } + } + + /** * Checks whether this {@link Polygon} and the one that is indirectly given - * via the given sequence of points are regarded to be equal. The + * via the given array of points are regarded to be equal. The * {@link Polygon}s will be regarded equal, if they are characterized by the * same segments. As a {@link Polygon} is always regarded to be closed, the * list of points may not have to correspond in each index value, they may - * also be shifted by a certain offset. + * also be shifted by a certain offset. Moreover, the vertices of two + * equally {@link Polygon}s may be reverted in order. * * @param points * an array of {@link Point} characterizing a {@link Polygon} to * be checked for equality * @return true if the sequence of points that characterize * this {@link Polygon} and the {@link Polygon} indirectly given via - * the sequence of points are regarded to form the same segments. + * the array of points are regarded to form the same segments. */ - public boolean equals(Point... points) { + public boolean equals(Point[] points) { if (points.length != this.points.length) { return false; } - // we have to shift the point list to decide on equality - for (int i = 0; i < this.points.length; i++) { - Point[] shiftedPoints = new Point[this.points.length]; - for (int j = 0; j < shiftedPoints.length; j++) { - int x = i + j < shiftedPoints.length ? i + j : i + j - - shiftedPoints.length; - shiftedPoints[j] = this.points[x].getCopy(); - } - if (PointListUtils.equals(shiftedPoints, points)) { - return true; + + // walk through the segments of this polygon and count them + SegmentList segments = new SegmentList(); + + for (Line seg : getSegments()) { + SegmentCounter sc = segments.find(seg); + sc.count++; + } + + // walk through the segments of the other polygon and decrement their + // counter + for (Line seg : new Polygon(points).getSegments()) { + SegmentCounter sc = segments.find(seg); + if (sc.count == 0) { + // if we add a new one or we delete one too often, these + // polygons are not equal + return false; } + sc.count--; } - return false; + + return true; } /** @@ -586,9 +645,14 @@ return getCopy().translate(pt); } + /** + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - return PointListUtils.getHashCode(points); + // calculating a better hashCode is not possible + return 0; + // return PointListUtils.getHashCode(points); } /** @@ -639,7 +703,7 @@ } } // no intersection, so we still need to check for containment - return contains(p) || p.contains(this); + return p.contains(this); } /** @@ -678,7 +742,7 @@ + ")"); stringBuffer.append(" -> "); } - stringBuffer.append(points[0]); + stringBuffer.append("(" + points[0].x + ", " + points[0].y + ")"); } else { stringBuffer.append(""); } Index: src/org/eclipse/gef4/geometry/shapes/Polyline.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/Polyline.java,v retrieving revision 1.5 diff -u -r1.5 Polyline.java --- src/org/eclipse/gef4/geometry/shapes/Polyline.java 20 Oct 2011 21:04:44 -0000 1.5 +++ src/org/eclipse/gef4/geometry/shapes/Polyline.java 10 Nov 2011 14:57:15 -0000 @@ -182,9 +182,13 @@ return new Polyline(t.getTransformed(points)); } + /** + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - return PointListUtils.getHashCode(points); + // calculating a better hashCode is not possible + return 0; } /** Index: src/org/eclipse/gef4/geometry/shapes/QuadraticCurve.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/QuadraticCurve.java,v retrieving revision 1.5 diff -u -r1.5 QuadraticCurve.java --- src/org/eclipse/gef4/geometry/shapes/QuadraticCurve.java 31 Oct 2011 21:56:41 -0000 1.5 +++ src/org/eclipse/gef4/geometry/shapes/QuadraticCurve.java 10 Nov 2011 14:57:15 -0000 @@ -157,6 +157,15 @@ } /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // calculating a better hashCode is not possible + return 0; + } + + /** * Sets the curve's control point. * * @param ctrl Index: src/org/eclipse/gef4/geometry/shapes/Rectangle.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/Rectangle.java,v retrieving revision 1.12 diff -u -r1.12 Rectangle.java --- src/org/eclipse/gef4/geometry/shapes/Rectangle.java 10 Nov 2011 13:50:50 -0000 1.12 +++ src/org/eclipse/gef4/geometry/shapes/Rectangle.java 10 Nov 2011 14:57:15 -0000 @@ -67,6 +67,12 @@ * the height of the new {@link Rectangle} */ public Rectangle(double x, double y, double width, double height) { + if (width < 0) { + width = 0; + } + if (height < 0) { + height = 0; + } this.x = x; this.y = y; this.width = width; @@ -703,9 +709,15 @@ return y; } + /** + * @see java.lang.Object#hashCode() + */ @Override public int hashCode() { - return (int) ((x + height + 1) * (y + width + 1)) ^ (int) x ^ (int) y; + // calculating a better hashCode is not possible + return 0; + // return (int) ((x + height + 1) * (y + width + 1)) ^ (int) x ^ (int) + // y; } /** @@ -858,6 +870,9 @@ * @return this for convenience */ public Rectangle setHeight(double height) { + if (height < 0) { + height = 0; + } this.height = height; return this; } @@ -913,6 +928,12 @@ * @return this Rectangle for convenience */ public Rectangle setSize(double w, double h) { + if (w < 0) { + w = 0; + } + if (h < 0) { + h = 0; + } width = w; height = h; return this; @@ -926,6 +947,9 @@ * @return this for convenience */ public Rectangle setWidth(double width) { + if (width < 0) { + width = 0; + } this.width = width; return this; } @@ -1096,12 +1120,18 @@ * */ public Rectangle union(double x, double y) { - double right = Math.max(this.x + width, x + width); - double bottom = Math.max(this.y + height, y + height); - this.x = Math.min(this.x, x); - this.y = Math.min(this.y, y); - this.width = right - this.x; - this.height = bottom - this.y; + if (x < this.x) { + this.width += this.x - x; + this.x = x; + } else if (x > this.x + this.width) { + this.width += x - this.x - this.width; + } + if (y < this.y) { + this.height += this.y - y; + this.y = y; + } else if (y > this.y + this.height) { + this.height += y - this.y - this.height; + } return this; } Index: src/org/eclipse/gef4/geometry/shapes/RoundedRectangle.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry/src/org/eclipse/gef4/geometry/shapes/RoundedRectangle.java,v retrieving revision 1.4 diff -u -r1.4 RoundedRectangle.java --- src/org/eclipse/gef4/geometry/shapes/RoundedRectangle.java 20 Oct 2011 21:04:44 -0000 1.4 +++ src/org/eclipse/gef4/geometry/shapes/RoundedRectangle.java 10 Nov 2011 14:57:15 -0000 @@ -209,6 +209,15 @@ } /** + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + // calculating a better hashCode is not possible + return 0; + } + + /** * @see Geometry#intersects(Rectangle) */ public boolean intersects(final Rectangle r) { #P org.eclipse.gef4.geometry.tests Index: src/org/eclipse/gef4/geometry/tests/AllTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/AllTests.java,v retrieving revision 1.4 diff -u -r1.4 AllTests.java --- src/org/eclipse/gef4/geometry/tests/AllTests.java 2 Nov 2011 20:06:31 -0000 1.4 +++ src/org/eclipse/gef4/geometry/tests/AllTests.java 10 Nov 2011 14:57:16 -0000 @@ -16,9 +16,9 @@ import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({ CubicCurveTests.class, DimensionTests.class, - EllipseTests.class, LineTests.class, PointTests.class, - PolygonTests.class, PolylineTests.class, +@SuiteClasses({ AngleTests.class, CubicCurveTests.class, DimensionTests.class, + EllipseTests.class, LineTests.class, PointListUtilsTests.class, + PointTests.class, PolygonTests.class, PolylineTests.class, PolynomCalculationUtilsTests.class, PrecisionUtilsTests.class, QuadraticCurveTests.class, RectangleTests.class, StraightTests.class, VectorTests.class }) Index: src/org/eclipse/gef4/geometry/tests/AngleTests.java =================================================================== RCS file: src/org/eclipse/gef4/geometry/tests/AngleTests.java diff -N src/org/eclipse/gef4/geometry/tests/AngleTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gef4/geometry/tests/AngleTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,132 @@ +/******************************************************************************* + * Copyright (c) 2011 itemis AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthias Wienand (itemis AG) - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.gef4.geometry.tests; + +import junit.framework.TestCase; + +import org.eclipse.gef4.geometry.Angle; +import org.eclipse.gef4.geometry.Angle.AngleUnit; +import org.eclipse.gef4.geometry.Point; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; + +public class AngleTests extends TestCase { + + private static final double PRECISION_FRACTION = TestUtils + .getPrecisionFraction(); + + private static final double UNRECOGNIZABLE_FRACTION = PRECISION_FRACTION + - PRECISION_FRACTION / 10; + + public void test_equals() { + Angle alpha = new Angle(Math.PI, AngleUnit.RAD); + Angle beta = new Angle(Math.PI, AngleUnit.RAD); + Angle gamma = new Angle(0, AngleUnit.RAD); + Angle delta = new Angle(2 * Math.PI, AngleUnit.RAD); + + assertTrue(alpha.equals(alpha)); + assertTrue(alpha.equals(beta)); + assertFalse(alpha.equals(gamma)); + assertFalse(alpha.equals(delta)); + assertTrue(gamma.equals(delta)); + assertTrue(delta.equals(gamma)); + assertFalse(alpha.equals(new Point())); + + alpha = new Angle(UNRECOGNIZABLE_FRACTION / 2, AngleUnit.RAD); + beta = new Angle(2 * Math.PI - UNRECOGNIZABLE_FRACTION / 2, + AngleUnit.RAD); + assertTrue(alpha.equals(beta)); + assertTrue(beta.equals(alpha)); + } + + public void test_constructors() { + Angle alpha = new Angle(180, AngleUnit.DEG); + assertTrue(alpha.equals(new Angle(Math.PI, AngleUnit.RAD))); + assertTrue(alpha.equals(Angle.fromDeg(180))); + assertTrue(alpha.equals(Angle.fromRad(Math.PI))); + assertTrue(new Angle().equals(Angle.fromRad(0))); + } + + public void test_copy() { + Angle alpha = Angle.fromRad(0.234); + assertTrue(alpha.equals(alpha.getCopy())); + assertTrue(alpha.equals(alpha.clone())); + assertTrue(alpha.getCopy().equals(alpha.clone())); + } + + public void test_deg() { + Angle alpha = new Angle(180, AngleUnit.DEG); + Angle beta = new Angle(Math.PI, AngleUnit.RAD); + + assertTrue(PrecisionUtils.equal(180, alpha.deg())); + assertTrue(PrecisionUtils.equal(180, beta.deg())); + + for (double rad = 0; rad <= 2 * Math.PI; rad += 0.1) { + assertTrue(Angle.fromDeg(Angle.fromRad(rad).deg()).equals( + Angle.fromRad(rad))); + } + } + + public void test_getAdded() { + Angle alpha = new Angle(180, AngleUnit.DEG); + Angle beta = new Angle(Math.PI, AngleUnit.RAD); + + assertTrue(alpha.getAdded(beta).equals(beta.getAdded(alpha))); + } + + public void test_getMultiplied() { + Angle alpha = Angle.fromDeg(180); + + assertTrue(alpha.getMultiplied(2).equals(Angle.fromDeg(360))); + } + + public void test_norm() { + Angle alpha = Angle.fromDeg(361); + Angle beta = Angle.fromDeg(1); + + assertTrue(alpha.equals(beta)); + assertTrue(PrecisionUtils.equal(alpha.deg(), beta.deg())); + assertTrue(PrecisionUtils.equal(alpha.rad(), beta.rad())); + } + + public void test_opposite() { + Angle alpha = Angle.fromDeg(180); + + assertTrue(alpha.equals(alpha.getOppositeFull())); + assertTrue(alpha.getOppositeSemi().equals(Angle.fromRad(0))); + } + + public void test_set() { + Angle alpha = Angle.fromDeg(0); + + alpha.setDeg(90); + assertTrue(PrecisionUtils.equal(alpha.deg(), 90)); + alpha.setDeg(450); + assertTrue(PrecisionUtils.equal(alpha.deg(), 90)); + alpha.setRad(Math.PI); + assertTrue(PrecisionUtils.equal(alpha.rad(), Math.PI)); + alpha.setRad(3 * Math.PI); + assertTrue(PrecisionUtils.equal(alpha.rad(), Math.PI)); + } + + public void test_toString() { + Angle alpha = Angle.fromDeg(0); + assertEquals("Angle(0.0rad (0.0deg))", alpha.toString()); + } + + public void test_unit() { + // to keep the coverage up + assertEquals(AngleUnit.DEG, AngleUnit.valueOf("DEG")); + assertEquals(AngleUnit.RAD, AngleUnit.valueOf("RAD")); + } + +} Index: src/org/eclipse/gef4/geometry/tests/DimensionTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/DimensionTests.java,v retrieving revision 1.1 diff -u -r1.1 DimensionTests.java --- src/org/eclipse/gef4/geometry/tests/DimensionTests.java 30 Aug 2011 20:43:48 -0000 1.1 +++ src/org/eclipse/gef4/geometry/tests/DimensionTests.java 10 Nov 2011 14:57:17 -0000 @@ -15,6 +15,7 @@ import junit.framework.TestCase; import org.eclipse.gef4.geometry.Dimension; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Dimension}. @@ -30,6 +31,28 @@ Dimension p1 = new Dimension(0.1, 0.1); Dimension p2 = new Dimension(0.2, 0.2); assertFalse(p1.equals(p2)); + + p1 = new Dimension(0.2, 0.2); + assertTrue(p1.equals(p2)); + + // wrong type + p1 = new Dimension(1, 1); + assertFalse(p1.equals(new org.eclipse.swt.graphics.Point(1, 1))); + } + + public void test_constructors() { + Dimension d0 = new Dimension(); + assertTrue(d0.equals(new Dimension(0, 0))); + assertTrue(d0.equals(d0)); + assertTrue(d0.equals(new Dimension(new org.eclipse.swt.graphics.Point( + 0, 0)))); + + Dimension d1 = new Dimension(10, 10); + assertTrue(d1.equals(new Dimension(new org.eclipse.swt.graphics.Point( + 10, 10)))); + + assertTrue(d1.equals(new Dimension(new org.eclipse.swt.graphics.Image( + new org.eclipse.swt.widgets.Display(), 10, 10)))); } /** @@ -38,5 +61,170 @@ public void test_getCopy() { Dimension p1 = new Dimension(0.1, 0.1); assertTrue(p1.equals(p1.getCopy())); + assertTrue(p1.equals(p1.clone())); + assertTrue(p1.getCopy().equals(p1.clone())); + } + + public void test_contains() { + Dimension d1 = new Dimension(0.1, 0.1); + Dimension d2 = new Dimension(0.2, 0.2); + + assertTrue(d2.contains(d1)); + assertFalse(d1.contains(d2)); + } + + public void test_expand() { + Dimension d1 = new Dimension(0.1, 0.1); + Dimension d2 = new Dimension(0.2, 0.2); + + Dimension dx = d1.getExpanded(d1); + d1.expand(d1); + assertTrue(dx.equals(d1)); + + assertTrue(d1.equals(d2)); + assertTrue(d1.contains(d2)); + assertTrue(d2.contains(d1)); + + dx = d1.getExpanded(d1.getWidth(), d1.getHeight()); + d1.expand(d1); + assertTrue(dx.equals(d1)); + + assertTrue(d1.contains(d2)); + assertFalse(d2.contains(d1)); } + + public void test_minmax() { + Dimension d1 = new Dimension(1, 2); + Dimension d2 = new Dimension(2, 1); + + Dimension di = new Dimension(1, 1); + Dimension da = new Dimension(2, 2); + + assertTrue(Dimension.min(d1, d2).equals(di)); + assertTrue(Dimension.max(d1, d2).equals(da)); + + assertTrue(Dimension.min(di, da).equals(di)); + assertTrue(Dimension.max(di, da).equals(da)); + + assertTrue(Dimension.min(da, da).equals(da)); + assertTrue(Dimension.max(di, di).equals(di)); + } + + public void test_shrink() { + Dimension d1 = new Dimension(0.2, 0.2); + Dimension d2 = new Dimension(0.4, 0.4); + + assertTrue(d2.contains(d1)); + assertFalse(d1.contains(d2)); + + Dimension dx = d2.getShrinked(d1); + d2.shrink(d1); + assertTrue(dx.equals(d2)); + + assertTrue(d2.contains(d1)); + assertTrue(d1.contains(d2)); + assertTrue(d2.equals(d1)); + + Dimension dy = new Dimension(0.1, 0.1); + dx = d2.getShrinked(dy.getWidth(), dy.getHeight()); + d2.shrink(dy); + assertTrue(dx.equals(d2)); + + assertFalse(d2.contains(d1)); + assertTrue(d1.contains(d2)); + } + + public void test_transpose() { + Dimension d1 = new Dimension(1, 1); + Dimension d2 = new Dimension(2, 2); + + assertTrue(d1.getTransposed().equals(d1)); + assertTrue(d2.getTransposed().equals(d2)); + + d1 = new Dimension(1, 2); + d2 = new Dimension(2, 1); + + assertTrue(d1.getTransposed().equals(d2)); + assertTrue(d2.getTransposed().equals(d1)); + } + + public void test_scale() { + Dimension d1 = new Dimension(1, 1); + Dimension d2 = new Dimension(2, 2); + + assertTrue(d1.getScaled(2).equals(d2)); + assertTrue(d2.getScaled(0.5).equals(d1)); + + d2 = new Dimension(10, 5); + assertTrue(d1.getScaled(10, 5).equals(d2)); + assertTrue(d2.getScaled(1f / 10f, 1f / 5f).equals(d1)); + } + + public void test_negate() { + assertTrue(new Dimension(1, 2).getNegated().equals( + new Dimension(-1, -2))); + assertTrue(new Dimension(-2, 1).getNegated().equals( + new Dimension(2, -1))); + assertTrue(new Dimension(1, -2).getNegated().equals( + new Dimension(-1, 2))); + assertTrue(new Dimension(-1, -2).getNegated().equals( + new Dimension(1, 2))); + } + + public void test_intersection() { + Dimension d1 = new Dimension(1, 2); + Dimension d2 = new Dimension(2, 1); + + Dimension di = new Dimension(1, 1); + Dimension da = new Dimension(2, 2); + + assertTrue(d1.getIntersected(d2).equals(di)); + assertTrue(di.getIntersected(da).equals(di)); + assertTrue(da.getIntersected(da).equals(da)); + + } + + public void test_union() { + Dimension d1 = new Dimension(1, 2); + Dimension d2 = new Dimension(2, 1); + + Dimension di = new Dimension(1, 1); + Dimension da = new Dimension(2, 2); + + assertTrue(d1.getUnioned(d2).equals(da)); + assertTrue(di.getUnioned(da).equals(da)); + assertTrue(di.getUnioned(di).equals(di)); + } + + public void test_empty() { + assertTrue(new Dimension(0, 0).isEmpty()); + assertTrue(new Dimension(-1, 1).isEmpty()); + assertTrue(new Dimension(1, -1).isEmpty()); + assertTrue(new Dimension(-1, -1).isEmpty()); + assertFalse(new Dimension(1, 1).isEmpty()); + } + + public void test_setters() { + Dimension d = new Dimension(); + + d.setWidth(10); + assertTrue(PrecisionUtils.equal(d.getWidth(), 10)); + + d.setHeight(5); + assertTrue(PrecisionUtils.equal(d.getHeight(), 5)); + + d.setSize(5, 10); + assertTrue(PrecisionUtils.equal(d.getWidth(), 5)); + assertTrue(PrecisionUtils.equal(d.getHeight(), 10)); + + d.setSize(new Dimension(-1, -1)); + assertTrue(PrecisionUtils.equal(d.getWidth(), -1)); + assertTrue(PrecisionUtils.equal(d.getHeight(), -1)); + } + + public void test_toString() { + Dimension d = new Dimension(); + assertEquals("Dimension(0.0, 0.0)", d.toString()); + } + } Index: src/org/eclipse/gef4/geometry/tests/LineTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/LineTests.java,v retrieving revision 1.1 diff -u -r1.1 LineTests.java --- src/org/eclipse/gef4/geometry/tests/LineTests.java 30 Aug 2011 20:43:48 -0000 1.1 +++ src/org/eclipse/gef4/geometry/tests/LineTests.java 10 Nov 2011 14:57:17 -0000 @@ -17,6 +17,8 @@ import org.eclipse.gef4.geometry.Point; import org.eclipse.gef4.geometry.euclidean.Straight; import org.eclipse.gef4.geometry.shapes.Line; +import org.eclipse.gef4.geometry.shapes.Rectangle; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Straight}. @@ -26,6 +28,180 @@ */ public class LineTests extends TestCase { + private static final double PRECISION_FRACTION = TestUtils + .getPrecisionFraction(); + + private static final double UNRECOGNIZABLE_FRACTION = PRECISION_FRACTION + - PRECISION_FRACTION / 10; + private static final double RECOGNIZABLE_FRACTION = PRECISION_FRACTION + + PRECISION_FRACTION / 10; + + public void test_equals() { + Line l1 = new Line(0, 0, 5, 0); + assertTrue(l1.equals(l1)); + assertTrue(l1.equals(new Line(0.0, 0.0, 5.0, 0.0))); + assertTrue(l1.equals(new Line(5.0, 0.0, 0.0, 0.0))); + assertFalse(l1.equals(new Line(0.1, 0.0, 5.0, 0.0))); + assertFalse(l1.equals(new Line(0.0, 0.1, 5.0, 0.0))); + assertFalse(l1.equals(new Line(0.0, 0.0, 5.1, 0.0))); + assertFalse(l1.equals(new Line(0.0, 0.0, 5.0, 0.1))); + assertFalse(l1.equals(new Point())); + assertFalse(l1.equals(null)); + + assertTrue(l1.equals(new Line(UNRECOGNIZABLE_FRACTION, + UNRECOGNIZABLE_FRACTION, 5.0 + UNRECOGNIZABLE_FRACTION, + UNRECOGNIZABLE_FRACTION))); + assertTrue(l1.equals(new Line(-UNRECOGNIZABLE_FRACTION, + -UNRECOGNIZABLE_FRACTION, 5.0 - UNRECOGNIZABLE_FRACTION, + -UNRECOGNIZABLE_FRACTION))); + assertFalse(l1.equals(new Line(RECOGNIZABLE_FRACTION, + RECOGNIZABLE_FRACTION, 5.0 + RECOGNIZABLE_FRACTION, + RECOGNIZABLE_FRACTION))); + assertFalse(l1.equals(new Line(-RECOGNIZABLE_FRACTION, + -RECOGNIZABLE_FRACTION, 5.0 - RECOGNIZABLE_FRACTION, + -RECOGNIZABLE_FRACTION))); + } + + public void test_hashCode() { + // hashCode() has to be the same for two equal()ly lines + // (I think this is impossible with the current PrecisionUtils.) + Line l1 = new Line(0, 0, 5, 0); + + assertEquals(l1.hashCode(), l1.hashCode()); + assertEquals(l1.hashCode(), new Line(0.0, 0.0, 5.0, 0.0).hashCode()); + + assertTrue(l1.hashCode() == new Line(UNRECOGNIZABLE_FRACTION, + UNRECOGNIZABLE_FRACTION, 5.0 + UNRECOGNIZABLE_FRACTION, + UNRECOGNIZABLE_FRACTION).hashCode()); + assertTrue(l1.hashCode() == new Line(-UNRECOGNIZABLE_FRACTION, + -UNRECOGNIZABLE_FRACTION, 5.0 - UNRECOGNIZABLE_FRACTION, + -UNRECOGNIZABLE_FRACTION).hashCode()); + } + + public void test_constructors() { + Line l1 = new Line(0, 0, 5, 0); + assertTrue(l1.equals(new Line(new Point(), new Point(5, 0)))); + } + + public void test_copy() { + Line l1 = new Line(0, 0, 5, 0); + assertTrue(l1.equals(l1.getCopy())); + assertTrue(l1.equals(l1.clone())); + assertTrue(l1.getCopy().equals(l1.clone())); + } + + public void test_getters() { + for (double x1 = -2; x1 <= 2; x1 += 0.2) { + for (double y1 = -2; y1 <= 2; y1 += 0.2) { + Point p1 = new Point(x1, y1); + + for (double x2 = -2; x2 <= 2; x2 += 0.2) { + for (double y2 = -2; y2 <= 2; y2 += 0.2) { + Point p2 = new Point(x2, y2); + Line line = new Line(p1, p2); + assertTrue(line.getP1().equals(p1)); + assertTrue(line.getP2().equals(p2)); + assertTrue(PrecisionUtils.equal(line.getX1(), p1.x)); + assertTrue(PrecisionUtils.equal(line.getX2(), p2.x)); + assertTrue(PrecisionUtils.equal(line.getY1(), p1.y)); + assertTrue(PrecisionUtils.equal(line.getY2(), p2.y)); + + Point[] points = line.getPoints(); + assertTrue(points[0].equals(p1)); + assertTrue(points[1].equals(p2)); + } + } + } + } + } + + public void test_setters() { + for (double x1 = -2; x1 <= 2; x1 += 0.2) { + for (double y1 = -2; y1 <= 2; y1 += 0.2) { + Point p1 = new Point(x1, y1); + + for (double x2 = -2; x2 <= 2; x2 += 0.2) { + for (double y2 = -2; y2 <= 2; y2 += 0.2) { + Point p2 = new Point(x2, y2); + + Line line = new Line(new Point(-5, -5), new Point(-10, + -10)); + + assertFalse(line.getP1().equals(p1)); + assertFalse(line.getP2().equals(p2)); + + line.setP1(p1); + line.setP2(p2); + + assertTrue(line.getP1().equals(p1)); + assertTrue(line.getP2().equals(p2)); + + line.setX1(-5); + line.setY1(-5); + assertTrue(line.getP1().equals(new Point(-5, -5))); + + line.setX2(5); + line.setY2(5); + assertTrue(line.getP2().equals(new Point(5, 5))); + + Line l2 = new Line(p1, p2); + line.setLine(l2); + assertTrue(line.equals(l2)); + + l2 = new Line(p2, p1); + line.setLine(p2, p1); + assertTrue(line.equals(l2)); + + line.setLine(0, 1, 2, 3); + assertTrue(line.equals(new Line(0, 1, 2, 3))); + } + } + } + } + } + + public void test_contains_Point() { + Line l1 = new Line(0, 0, 5, 0); + assertTrue(l1.contains(l1.getP1())); + assertTrue(l1.contains(l1.getP2())); + for (double x = -5; x <= 10; x += 0.1) { + assertTrue(l1.contains(new Point(x, 0)) == (PrecisionUtils + .smallerEqual(0, x) && PrecisionUtils.smallerEqual(x, 5))); + } + + l1 = new Line(0, 0, 0, 0); + assertTrue(l1.contains(l1.getP1())); + assertTrue(l1.contains(l1.getP2())); + assertFalse(l1.contains(new Point(1, 1))); + } + + public void test_contains_Rect() { + assertFalse(new Line(0, 0, 5, 0).contains(new Rectangle())); + assertFalse(new Line(0, 0, 5, 0).contains(new Rectangle(0, 0, 5, 0))); + assertFalse(new Line(0, 0, 5, 0).contains(new Rectangle(1, 1, 1, 1))); + } + + public void test_getBounds() { + Line l1 = new Line(0, 0, 5, 0); + Rectangle bounds = l1.getBounds(); + assertTrue(bounds.getLeft().equals(l1.getP1())); + assertTrue(bounds.getRight().equals(l1.getP2())); + assertTrue(bounds.getTopLeft().equals(l1.getP1())); + assertTrue(bounds.getBottomLeft().equals(l1.getP1())); + assertTrue(bounds.getTopRight().equals(l1.getP2())); + assertTrue(bounds.getBottomRight().equals(l1.getP2())); + + l1 = new Line(-5, -5, 5, 5); + bounds = l1.getBounds(); + assertTrue(bounds.getTopLeft().equals(l1.getP1())); + assertTrue(bounds.getBottomRight().equals(l1.getP2())); + + l1 = new Line(-5, 5, 5, -5); + bounds = l1.getBounds(); + assertTrue(bounds.getBottomLeft().equals(l1.getP1())); + assertTrue(bounds.getTopRight().equals(l1.getP2())); + } + public void test_intersects_with_Line() { // simple intersection Line l1 = new Line(0, 0, 4, 4); @@ -42,6 +218,22 @@ Line l4 = new Line(2, 2, 6, 6); assertTrue(l1.intersects(l4)); assertTrue(l4.intersects(l1)); + + // one line is a single point + Line l5 = new Line(1, 1, 1, 1); + assertTrue(l5.intersects(l1)); + assertTrue(l1.intersects(l5)); + + // straights would intersect, but these lines do not + Line l6 = new Line(4, 0, 5, 4); + assertFalse(l6.intersects(l1)); + assertFalse(l1.intersects(l6)); + } + + public void test_intersects_with_Rect() { + Line l1 = new Line(0, 0, 4, 4); + Rectangle r1 = new Rectangle(0, 4, 4, 4); + assertTrue(l1.intersects(r1)); } public void test_getIntersection_with_Line() { @@ -61,5 +253,44 @@ Line l4 = new Line(2, 2, 6, 6); assertTrue(l1.getIntersection(l4) == null); assertTrue(l4.getIntersection(l1) == null); + + // lines overlap in one end point + Line l5 = new Line(4, 4, 6, 6); + assertTrue(l1.getIntersection(l5).equals(new Point(4, 4))); + assertTrue(l5.getIntersection(l1).equals(new Point(4, 4))); + l5 = new Line(6, 6, 4, 4); + assertTrue(l1.getIntersection(l5).equals(new Point(4, 4))); + assertTrue(l5.getIntersection(l1).equals(new Point(4, 4))); + + Line l6 = new Line(-1, -1, 0, 0); + assertTrue(l1.getIntersection(l6).equals(new Point())); + assertTrue(l6.getIntersection(l1).equals(new Point())); + l6 = new Line(0, 0, -1, -1); + assertTrue(l1.getIntersection(l6).equals(new Point())); + assertTrue(l6.getIntersection(l1).equals(new Point())); + + // lines do not intersect + Line l7 = new Line(4, 0, 5, 4); + assertNull(l1.getIntersection(l7)); + assertNull(l7.getIntersection(l1)); } + + public void test_toSWTPointArray() { + Line l1 = new Line(0.9, 0.1, 1.1, 2.9); + int[] ints = l1.toSWTPointArray(); + assertEquals(0, ints[0]); + assertEquals(0, ints[1]); + assertEquals(1, ints[2]); + assertEquals(2, ints[3]); + } + + public void test_toPath() { + // TODO: how do you do this? + } + + public void test_toString() { + Line l1 = new Line(0, 0, 5, 0); + assertEquals("Line: (0.0, 0.0) -> (5.0, 0.0)", l1.toString()); + } + } Index: src/org/eclipse/gef4/geometry/tests/PointListUtilsTests.java =================================================================== RCS file: src/org/eclipse/gef4/geometry/tests/PointListUtilsTests.java diff -N src/org/eclipse/gef4/geometry/tests/PointListUtilsTests.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/gef4/geometry/tests/PointListUtilsTests.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,156 @@ +/******************************************************************************* + * Copyright (c) 2011 itemis AG and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthias Wienand (itemis AG) - initial API and implementation + * + *******************************************************************************/ + +package org.eclipse.gef4.geometry.tests; + +import java.util.ArrayList; + +import junit.framework.TestCase; + +import org.eclipse.gef4.geometry.Point; +import org.eclipse.gef4.geometry.shapes.Line; +import org.eclipse.gef4.geometry.shapes.Rectangle; +import org.eclipse.gef4.geometry.utils.PointListUtils; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; + +public class PointListUtilsTests extends TestCase { + + public void test_copy() { + Point[] points = new Point[10]; + for (int i = 0; i < 10; i++) { + points[i] = new Point(i * i, i + i); + } + + Point[] copy = PointListUtils.getCopy(points); + + for (int i = 0; i < 10; i++) { + assertTrue(points[i].equals(copy[i])); + } + } + + public void test_bounds() { + Point[] points = new Point[9]; + for (int x = -4; x <= 4; x++) { + double y = (1f / 3f) * x * x * x + 2f * x * x - (3f / 2f) * x - 1f + / 5f; + points[x + 4] = new Point(x, y); + } + + Rectangle bounds = PointListUtils.getBounds(points); + + assertTrue(bounds.getTopLeft().equals(-4, points[4].y)); + assertTrue(bounds.getBottomRight().equals(4, points[8].y)); + + bounds = PointListUtils.getBounds(new Point[] {}); + + assertTrue(bounds.getTopLeft().equals(new Point(0, 0))); + assertTrue(bounds.getBottomRight().equals(new Point(0, 0))); + } + + public void test_equals() { + Point[] pPoints = new Point[5]; + ArrayList qPoints = new ArrayList(); + + for (int i = 0; i < 5; i++) { + pPoints[i] = new Point(i, i); + qPoints.add(new Point(i, i)); + } + + assertTrue(PointListUtils.equals(pPoints, + qPoints.toArray(new Point[] {}))); + + qPoints.add(new Point()); + assertFalse(PointListUtils.equals(pPoints, + qPoints.toArray(new Point[] {}))); + + qPoints.remove(5); + assertTrue(PointListUtils.equals(pPoints, + qPoints.toArray(new Point[] {}))); + + qPoints.get(2).setX(-1); + assertFalse(PointListUtils.equals(pPoints, + qPoints.toArray(new Point[] {}))); + } + + public void test_translate() { + Point[] points = new Point[5]; + + for (int i = 0; i < 5; i++) { + points[i] = new Point(i, i); + } + + PointListUtils.translate(points, 1, -1); + + for (int i = 0; i < 5; i++) { + assertTrue(PrecisionUtils.equal(points[i].x, i + 1)); + assertTrue(PrecisionUtils.equal(points[i].y, i - 1)); + } + } + + public void test_toCoordinatesArray() { + Point[] points = new Point[5]; + + for (int i = 0; i < 5; i++) { + points[i] = new Point(i, i); + } + + double[] coords = PointListUtils.toCoordinatesArray(points); + + for (int i = 0; i < 10; i += 2) { + assertTrue(PrecisionUtils.equal(points[i / 2].x, coords[i])); + assertTrue(PrecisionUtils.equal(points[i / 2].y, coords[i + 1])); + } + } + + public void test_toIntegerArray() { + double[] doubles = new double[10]; + + for (int i = 0; i < 10; i++) { + doubles[i] = (double) i / 2f; + } + + int[] ints = PointListUtils.toIntegerArray(doubles); + + for (int i = 0; i < 10; i++) { + assertTrue(PrecisionUtils.equal(ints[i], (int) doubles[i])); + } + } + + public void test_toSegmentsArray() { + Point[] points = new Point[5]; + + for (int i = 0; i < points.length; i++) { + points[i] = new Point(i, i); + } + + Line[] segments = PointListUtils.toSegmentsArray(points, false); + assertTrue(PrecisionUtils.equal(segments.length, points.length - 1)); + + for (int i = 0; i < segments.length; i++) { + assertTrue(segments[i].getP1().equals(points[i])); + assertTrue(segments[i].getP2().equals(points[i + 1])); + } + + segments = PointListUtils.toSegmentsArray(points, true); + assertTrue(PrecisionUtils.equal(segments.length, points.length)); + + for (int i = 0; i < segments.length; i++) { + assertTrue(segments[i].getP1().equals(points[i])); + if (i == points.length - 1) { + assertTrue(segments[i].getP2().equals(points[0])); + } else { + assertTrue(segments[i].getP2().equals(points[i + 1])); + } + } + } + +} Index: src/org/eclipse/gef4/geometry/tests/PointTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/PointTests.java,v retrieving revision 1.1 diff -u -r1.1 PointTests.java --- src/org/eclipse/gef4/geometry/tests/PointTests.java 30 Aug 2011 20:43:48 -0000 1.1 +++ src/org/eclipse/gef4/geometry/tests/PointTests.java 10 Nov 2011 14:57:18 -0000 @@ -13,7 +13,9 @@ import junit.framework.TestCase; +import org.eclipse.gef4.geometry.Dimension; import org.eclipse.gef4.geometry.Point; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Point}. @@ -49,12 +51,98 @@ assertTrue(new Point(4, 7).equals(4, 7)); assertFalse(new Point(3, 6).equals(3, 7)); assertFalse(new Point(3, 6).equals(4, 6)); + assertTrue(new Point(1.0, 2.0).equals(new Point(1, 2))); + + // wrong type + assertFalse(new Point(1, 2).equals(new org.eclipse.swt.graphics.Point( + 1, 2))); + } + + public void test_constructors() { + Point p0 = new Point(0, 0); + assertTrue(new Point().equals(p0)); + assertTrue(new Point().equals(new Point(p0))); + + Point p1 = new Point(10, 20); + assertTrue(new Point(10.0, 20.0).equals(p1)); + + org.eclipse.swt.graphics.Point swtPoint = new org.eclipse.swt.graphics.Point( + 10, 20); + assertTrue(p1.equals(new Point(swtPoint))); + assertTrue(new Point(10.0, 20.0).equals(new Point(swtPoint))); + + } + + public void test_getCopy() { + Point p0 = new Point(0, 0); + Point p1 = new Point(10, 20); + + assertTrue(p0.getCopy().equals(p0)); + assertTrue(p0.clone().equals(p0)); + assertTrue(p0.getCopy().equals(p0.clone())); + + assertTrue(p1.getCopy().equals(p1)); + assertTrue(p1.clone().equals(p1)); + assertTrue(p1.getCopy().equals(p1.clone())); + } + + public void test_xy() { + Point p = new Point(1.234, 2.987); + assertTrue(PrecisionUtils.equal(p.x, 1.234)); + assertTrue(PrecisionUtils.equal(p.x, p.x())); + assertTrue(PrecisionUtils.equal(p.y, 2.987)); + assertTrue(PrecisionUtils.equal(p.y, p.y())); + } + + public void test_getDistance() { + Point p = new Point(4, 3); + assertTrue(PrecisionUtils.equal(p.getDistance(new Point()), 5)); + + Point q = new Point(104, 3); + assertTrue(PrecisionUtils.equal(p.getDistance(q), 100)); + + q = new Point(4, 13); + assertTrue(PrecisionUtils.equal(p.getDistance(q), 10)); + } + + public void test_toSWT() { + Point p = new Point(); + assertTrue(p.equals(new Point(p.toSWTPoint()))); + + p = new Point(1, 2); + assertTrue(p.equals(new Point(p.toSWTPoint()))); + } + + public void test_scale() { + Point p = new Point(1, 1); + Point q = new Point(2, 2); + + assertTrue(p.getScaled(2).equals(q)); + assertTrue(q.getScaled(0.5).equals(p)); + + q = new Point(3, 6); + assertTrue(p.getScaled(3, 6).equals(q)); + assertTrue(q.getScaled(1f / 3f, 1f / 6f).equals(p)); + } + + public void test_negate() { + assertTrue(new Point(1, 2).getNegated().equals(new Point(-1, -2))); + assertTrue(new Point(-1, 2).getNegated().equals(new Point(1, -2))); + assertTrue(new Point(1, -2).getNegated().equals(new Point(-1, 2))); + assertTrue(new Point(-1, -2).getNegated().equals(new Point(1, 2))); } public void test_translate() { Point p1 = new Point(3, 6); - p1.translate(new Point(4711, 567)); + Point px = new Point(4711, 567); + p1.translate(px); assertTrue(p1.equals(4714, 573)); + p1.translate(px.negate()); + + assertTrue(p1.getTranslated(3, 0).equals(new Point(6, 6))); + assertTrue(p1.getTranslated(p1).equals(new Point(6, 12))); + assertTrue(p1.getTranslated(new Dimension(10, 2)).equals( + new Point(13, 8))); } public void test_setX() { @@ -77,4 +165,16 @@ p.setLocation(new Point(4711, 678)); assertTrue(p.equals(4711, 678)); } + + public void test_transpose() { + assertTrue(new Point(1, 2).getTransposed().equals(new Point(2, 1))); + assertTrue(new Point(2, 1).getTransposed().equals(new Point(1, 2))); + assertTrue(new Point(1, 1).getTransposed().equals(new Point(1, 1))); + } + + public void test_toString() { + Point p = new Point(); + assertEquals("Point(0.0, 0.0)", p.toString()); + } + } Index: src/org/eclipse/gef4/geometry/tests/PolygonTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/PolygonTests.java,v retrieving revision 1.2 diff -u -r1.2 PolygonTests.java --- src/org/eclipse/gef4/geometry/tests/PolygonTests.java 30 Aug 2011 21:19:21 -0000 1.2 +++ src/org/eclipse/gef4/geometry/tests/PolygonTests.java 10 Nov 2011 14:57:18 -0000 @@ -14,8 +14,12 @@ import junit.framework.TestCase; +import org.eclipse.gef4.geometry.Angle; import org.eclipse.gef4.geometry.Point; +import org.eclipse.gef4.geometry.shapes.Ellipse; +import org.eclipse.gef4.geometry.shapes.Line; import org.eclipse.gef4.geometry.shapes.Polygon; +import org.eclipse.gef4.geometry.shapes.Polyline; import org.eclipse.gef4.geometry.shapes.Rectangle; /** @@ -41,11 +45,165 @@ new Point(0, 4), new Point(2, 4), new Point(2, 2), new Point(4, 2), new Point(4, 4), new Point(6, 4), new Point(6, 0)); + private static final double PRECISION_FRACTION = TestUtils + .getPrecisionFraction(); + + private static final double UNRECOGNIZABLE_FRACTION = PRECISION_FRACTION + - PRECISION_FRACTION / 10; + + private static final double RECOGNIZABLE_FRACTION = PRECISION_FRACTION + + PRECISION_FRACTION / 10; + + public void test_equals() { + // check all permutations are regarded + assertEquals(RHOMB, RHOMB); + assertEquals(RHOMB, new Polygon(new Point(2, 0), new Point(4, 2), + new Point(2, 4), new Point(0, 2))); + assertTrue(RHOMB.equals(new Point[] { new Point(2, 0), new Point(4, 2), + new Point(2, 4), new Point(0, 2) })); + assertEquals(RHOMB, new Polygon(new Point(4, 2), new Point(2, 4), + new Point(0, 2), new Point(2, 0))); + assertTrue(RHOMB.equals(new Point[] { new Point(4, 2), new Point(2, 4), + new Point(0, 2), new Point(2, 0) })); + assertEquals(RHOMB, new Polygon(new Point(2, 4), new Point(0, 2), + new Point(2, 0), new Point(4, 2))); + assertTrue(RHOMB.equals(new Point[] { new Point(2, 4), new Point(0, 2), + new Point(2, 0), new Point(4, 2) })); + assertEquals(RHOMB, new Polygon(new Point(0, 2), new Point(2, 0), + new Point(4, 2), new Point(2, 4))); + assertTrue(RHOMB.equals(new Point[] { new Point(0, 2), new Point(2, 0), + new Point(4, 2), new Point(2, 4) })); + + // check reverse + assertEquals(RHOMB, new Polygon(new Point(0, 2), new Point(2, 4), + new Point(4, 2), new Point(2, 0))); + assertEquals(RHOMB, new Polygon(new Point(2, 0), new Point(0, 2), + new Point(2, 4), new Point(4, 2))); + assertEquals(RHOMB, new Polygon(new Point(4, 2), new Point(2, 0), + new Point(0, 2), new Point(2, 4))); + assertEquals(RHOMB, new Polygon(new Point(2, 4), new Point(4, 2), + new Point(2, 0), new Point(0, 2))); + + // check other type + assertFalse(RHOMB.equals(new Point())); + + // check unequal polygon + assertFalse(RHOMB.equals(new Polygon(new Point(), new Point(1, 1), + new Point(0, 2)))); + assertFalse(RHOMB.equals(new Point[] { new Point(), new Point(1, 1), + new Point(0, 2) })); + assertFalse(RHOMB.equals(new Polygon(new Point(), new Point(1, 1), + new Point(0, 2), new Point(-1, 1)))); + assertFalse(RHOMB.equals(new Point[] { new Point(), new Point(1, 1), + new Point(0, 2), new Point(-1, 1) })); + + // check degenerated case: + assertFalse(new Polygon(new Point(), new Point(1, 0), new Point(), + new Point(1, 0), new Point(), new Point(2, 0)) + .equals(new Polygon(new Point(), new Point(1, 0), new Point(), + new Point(2, 0), new Point(), new Point(2, 0)))); + } + + public void test_constructors() { + assertEquals(RHOMB, new Polygon(new Point(2, 0), new Point(4, 2), + new Point(2, 4), new Point(0, 2))); + assertEquals(RHOMB, new Polygon(new Point[] { new Point(2, 0), + new Point(4, 2), new Point(2, 4), new Point(0, 2) })); + assertEquals(RHOMB, new Polygon(2, 0, 4, 2, 2, 4, 0, 2)); + assertEquals(RHOMB, + new Polygon(new double[] { 2, 0, 4, 2, 2, 4, 0, 2 })); + } + + public void test_copy() { + assertEquals(RHOMB, RHOMB.getCopy()); + assertEquals(RHOMB, RHOMB.clone()); + assertEquals(RHOMB.getCopy(), RHOMB.clone()); + } + + public void test_getPoints() { + assertEquals(RHOMB, new Polygon(RHOMB.getPoints())); + assertEquals(RECTANGLE, new Polygon(RECTANGLE.getPoints())); + assertEquals(CONCAVE_PENTAGON, + new Polygon(CONCAVE_PENTAGON.getPoints())); + assertEquals(CONCAVE_OCTAGON, new Polygon(CONCAVE_OCTAGON.getPoints())); + assertFalse(RECTANGLE.equals(new Polygon(RHOMB.getPoints()))); + } + + public void test_getCoordinates() { + assertEquals(RHOMB, new Polygon(RHOMB.getCoordinates())); + assertEquals(RECTANGLE, new Polygon(RECTANGLE.getCoordinates())); + assertEquals(CONCAVE_PENTAGON, + new Polygon(CONCAVE_PENTAGON.getCoordinates())); + assertEquals(CONCAVE_OCTAGON, + new Polygon(CONCAVE_OCTAGON.getCoordinates())); + assertFalse(RECTANGLE.equals(new Polygon(RHOMB.getCoordinates()))); + } + + public void test_getBounds() { + assertEquals(RECTANGLE, RECTANGLE.getBounds().toPolygon()); + } + + public void test_getSegments() { + Rectangle bounds = RECTANGLE.getBounds(); + + for (Line s1 : bounds.getSegments()) { + boolean foundIt = false; + for (Line s2 : RECTANGLE.getSegments()) { + if (s1.equals(s2)) { + foundIt = true; + break; + } + } + assertTrue(foundIt); + } + } + + public void test_getTranslated() { + assertTrue(RHOMB.equals(RHOMB.getTranslated(new Point()))); + assertTrue(RHOMB.equals(RHOMB.getTranslated(0, 0))); + assertTrue(RHOMB.equals(RHOMB.getTranslated(new Point( + UNRECOGNIZABLE_FRACTION, 0)))); + assertTrue(RHOMB.equals(RHOMB.getTranslated(new Point(0, + UNRECOGNIZABLE_FRACTION)))); + assertTrue(RHOMB.equals(RHOMB.getTranslated(new Point( + UNRECOGNIZABLE_FRACTION, UNRECOGNIZABLE_FRACTION)))); + assertTrue(RHOMB + .equals(RHOMB.getTranslated(UNRECOGNIZABLE_FRACTION, 0))); + assertTrue(RHOMB + .equals(RHOMB.getTranslated(0, UNRECOGNIZABLE_FRACTION))); + assertTrue(RHOMB.equals(RHOMB.getTranslated(UNRECOGNIZABLE_FRACTION, + UNRECOGNIZABLE_FRACTION))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point(1, 0)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point(0, 1)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point(1, 1)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(1, 0))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(0, 1))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(1, 1))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point( + RECOGNIZABLE_FRACTION, 0)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point(9, + RECOGNIZABLE_FRACTION)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(new Point( + RECOGNIZABLE_FRACTION, RECOGNIZABLE_FRACTION)))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(RECOGNIZABLE_FRACTION, 0))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(9, RECOGNIZABLE_FRACTION))); + assertFalse(RHOMB.equals(RHOMB.getTranslated(RECOGNIZABLE_FRACTION, + RECOGNIZABLE_FRACTION))); + } + + public void test_contains_Point_special() { + assertFalse(new Polygon(new Point[] {}).contains(new Point())); + assertFalse(new Polygon(new Point()).contains(new Point(1, 1))); + assertTrue(new Polygon(new Point(1, 1)).contains(1, 1)); + assertFalse(new Polygon(new Point(), new Point(1, 1)).contains(1, 0)); + assertTrue(new Polygon(new Point(), new Point(1, 1)).contains(0, 0)); + } + /** * Testing points inside/outside the rhomb located in top half. Excluding * points of RHOMB border - separate test present for it */ - public void testPointContainmentForTopRhombHalfPoints() { + public void test_contains_Point_TopRhombHalfPoints() { assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(0, 1))); assertTrue("This point is inside the rhomb", @@ -58,7 +216,7 @@ * Testing points inside/outside the rhomb located in bottop half. Excluding * points of RHOMB border - separate test present for it */ - public void testPointContainmentForBottomRhombHalfPoints() { + public void test_contains_Point_BottomRhombHalfPoints() { assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(0, 3))); assertTrue("This point is inside the rhomb", @@ -71,7 +229,7 @@ * Testing points inside/outside the rhomb located on the equator. Excluding * points of RHOMB border - separate test present for it */ - public void testPointContainmentForRhombEquatorPoints() { + public void test_contains_Point_RhombEquatorPoints() { assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(-1, 2))); assertTrue("This point is inside the rhomb", @@ -84,7 +242,7 @@ * Testing points outside the rhomb located on top horizontal tangent line. * Excluding points of RHOMB border - separate test present for it */ - public void testPointContainmentForTopRhombTangentPoints() { + public void test_contains_Point_TopRhombTangentPoints() { assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(0, 0))); assertFalse("This point is outside the rhomb", @@ -95,14 +253,14 @@ * Testing points outside the rhomb located on bottom horizontal tangent * line. Excluding points of RHOMB border - separate test present for it */ - public void testPointContainmentForBottomRhombTangentPoints() { + public void test_contains_Point_BottomRhombTangentPoints() { assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(0, 4))); assertFalse("This point is outside the rhomb", RHOMB.contains(new Point(4, 4))); } - public void testPointContainmentForRectangleBorderPoints() { + public void test_contains_Point_RectangleBorderPoints() { assertTrue("This point is a corner point of the rectangle", RECTANGLE.contains(new Point(0, 0))); assertTrue("This point is on the side of the rectangle", @@ -117,15 +275,10 @@ RECTANGLE.contains(new Point(2, 0))); } - public void testRectangleContainmentForRectangle() { - assertTrue("The rectangle contains itself", RECTANGLE.getBounds() - .equals((new Rectangle(new Point(0, 0), new Point(2, 2))))); - } - /** * Testing points of RHOMB border - all vertexes + one point on the edge */ - public void testPointContainmentForRhombBorderPoints() { + public void test_contains_Point_RhombBorderPoints() { assertTrue("This point is inside the rhomb", RHOMB.contains(new Point(0, 2))); assertTrue("This point is inside the rhomb", @@ -141,7 +294,7 @@ * Excluding points of CONCAVE_PENTAGON border - separate test present for * it */ - public void testPointContainmentForConcavePentagonEquatorPoints() { + public void test_contains_Point_ConcavePentagonEquatorPoints() { assertFalse("This point is outside the pentagon", CONCAVE_PENTAGON.contains(new Point(-1, 6))); assertTrue("This point is inside the pentagon", @@ -159,7 +312,7 @@ * Excluding points of CONCAVE_PENTAGON border - separate test present for * it */ - public void testPointContainmentForTopConcavePentagonTangentPoints() { + public void test_contains_Point_TopConcavePentagonTangentPoints() { assertFalse("This point is outside the pentagon", CONCAVE_PENTAGON.contains(new Point(-1, 8))); assertFalse("This point is outside the pentagon", @@ -173,7 +326,7 @@ * tangent. Excluding points of CONCAVE_PENTAGON border - separate test * present for it */ - public void testPointContainmentForBottomConcavePentagonTangentPoints() { + public void test_contains_Point_BottomConcavePentagonTangentPoints() { assertFalse("This point is outside the pentagon", CONCAVE_PENTAGON.contains(new Point(-1, 4))); assertTrue("This point is inside the pentagon", @@ -188,7 +341,7 @@ * Testing points of CONCAVE_PENTAGON border - all vertexes + points on * concave edges */ - public void testPointContainmentForConcavePentagonBorderPoints() { + public void test_contains_Point_ConcavePentagonBorderPoints() { assertTrue("This point is inside the pentagon", CONCAVE_PENTAGON.contains(new Point(0, 8))); assertTrue("This point is inside the pentagon", @@ -205,7 +358,7 @@ * Testing points located of the horizontal line containing one of the * "concave" edges */ - public void testPointContainmentForConcaveOctagonBottomTangentPoints() { + public void test_contains_Point_ConcaveOctagonBottomTangentPoints() { assertFalse("This point is outside the octagon", CONCAVE_OCTAGON.contains(new Point(-1, 2))); assertTrue("This point is inside the octagon", @@ -224,7 +377,42 @@ CONCAVE_OCTAGON.contains(new Point(7, 2))); } - public void testRectangleContainmentForRhomb() { + public void test_contains_Line() { + assertFalse(RHOMB.contains(new Line(-1, 1, 1, -1))); + assertFalse(RHOMB.contains(new Line(-1, 2, 2, 2))); + assertFalse(RHOMB.contains(new Line(2, 2, 5, 2))); + assertTrue(RHOMB.contains(new Line(0, 2, 2, 0))); + assertTrue(RHOMB.contains(new Line(0, 2, 2, 4))); + assertTrue(RHOMB.contains(new Line(0, 2, 2, 2))); + assertTrue(RHOMB.contains(new Line(1, 2, 3, 2))); + assertTrue(new Polygon(new Point(), new Point(0, 5), new Point(5, 5), + new Point(5, 0), new Point(2.5, 2.5)).contains(new Line(1, 2.5, + 4, 2.5))); + assertFalse(new Polygon(new Point(), new Point(0, 5), new Point(5, 5), + new Point(5, 0), new Point(2.5, 2.5)).contains(new Line(1, 2, + 4, 2))); + } + + public void test_intersects_Line() { + assertFalse(RHOMB.intersects(new Line(-1, 1, 1, -1))); + assertTrue(RHOMB.intersects(new Line(-1, 2, 2, 2))); + assertTrue(RHOMB.intersects(new Line(2, 2, 5, 2))); + assertTrue(RHOMB.intersects(new Line(0, 2, 2, 0))); + assertTrue(RHOMB.intersects(new Line(0, 2, 2, 4))); + assertTrue(RHOMB.intersects(new Line(0, 2, 2, 2))); + assertTrue(RHOMB.intersects(new Line(1, 2, 3, 2))); + assertTrue(new Polygon(new Point(), new Point(0, 5), new Point(5, 5), + new Point(5, 0), new Point(2.5, 2.5)).intersects(new Line(1, + 2.5, 4, 2.5))); + assertTrue(RHOMB.intersects(new Line(-1, 2, 5, 2))); + } + + public void test_contains_Rectangle_Rectangle() { + assertTrue("The rectangle contains itself", RECTANGLE.getBounds() + .equals((new Rectangle(new Point(0, 0), new Point(2, 2))))); + } + + public void test_contains_Rectangle_Rhomb() { assertTrue("This rectangle is inside the rhomb", RHOMB.contains(new Rectangle(1.5, 1.5, 1, 1))); assertTrue("This rectangle is inside the rhomb", @@ -233,7 +421,7 @@ RHOMB.contains(new Rectangle(0, 0, 2, 2))); } - public void testRectangleIntersectionForRhomb() { + public void test_intersects_Rectangle_Rhomb() { assertTrue( "This rectangle is inside the rhomb and does therefore intersect it", RHOMB.intersects(new Rectangle(1.5, 1.5, 1, 1))); @@ -251,11 +439,23 @@ RHOMB.intersects(new Rectangle(-2, 0, 2, 2))); } - public void testPolygonIntersectionForRhomb() { + public void test_getIntersections_Rectangle() { + assertEquals(4, RHOMB.getIntersections(RHOMB.getBounds()).length); + } + + public void test_intersects_Polygon_Rhomb() { assertTrue( "The rhomb intersects itself, because it touches/contains itself", RHOMB.intersects(RHOMB)); + assertTrue( + "The rhomb intersects its shrinked self, because its shrinked self is fully contained by the rhomb", + RHOMB.intersects(RHOMB.getCopy().scale(0.5, new Point(2, 2)))); + + assertTrue( + "The rhomb intersects its expanded self, because its expanded self fully contains the rhomb", + RHOMB.intersects(RHOMB.getCopy().scale(2, new Point(2, 2)))); + assertTrue(RHOMB.contains(new Point(4, 2))); assertTrue(RHOMB.getTranslated(new Point(4, 0)).contains( new Point(4, 2))); @@ -266,22 +466,89 @@ RHOMB.intersects(RHOMB.getTranslated(2, 0))); } - public void testGetCopy() { - Polygon tmp = RHOMB.getCopy(); - tmp.translate(4, 4); - assertFalse(tmp.equals(RHOMB)); + public void test_getIntersections_Polygon() { + // TODO: something's wrong... debug this test + assertEquals(2, RHOMB.getIntersections(RECTANGLE).length); + assertEquals(4, + RHOMB.getIntersections(RHOMB.getBounds().toPolygon()).length); } - public void testEquals() { - // check all permutations are regarded - assertEquals(RHOMB, RHOMB); - assertEquals(RHOMB, new Polygon(new Point(2, 0), new Point(4, 2), - new Point(2, 4), new Point(0, 2))); - assertEquals(RHOMB, new Polygon(new Point(4, 2), new Point(2, 4), - new Point(0, 2), new Point(2, 0))); - assertEquals(RHOMB, new Polygon(new Point(2, 4), new Point(0, 2), - new Point(2, 0), new Point(4, 2))); - assertEquals(RHOMB, new Polygon(new Point(0, 2), new Point(2, 0), - new Point(4, 2), new Point(2, 4))); + public void test_contains_Polyline() { + assertTrue(RHOMB.contains(new Polyline(0, 2, 2, 2))); + } + + public void test_intersects_Polyline() { + assertFalse(RHOMB.intersects(new Polyline(0, 0, -1, -1))); + assertTrue(RHOMB.intersects(new Polyline(0, 0, 0, 4))); + assertTrue(RHOMB.intersects(new Polyline(0, 0, 0, 4, 4, 4))); + assertTrue(RHOMB.intersects(new Polyline(0, 0, 0, 4, 4, 4, 2, 2))); + assertTrue(RHOMB.intersects(new Polyline(0, 0, 0, 4, 4, 4, 2, 2, 4, 0))); + assertTrue(RHOMB.intersects(new Polyline(0, 0, 0, 4, 4, 4, 2, 2, 4, 0, + 0, 0))); + } + + public void test_getIntersections_Polyline() { + assertEquals(1, RHOMB.getIntersections(new Polyline(0, 0, 0, 4)).length); + assertEquals(2, + RHOMB.getIntersections(new Polyline(0, 0, 0, 4, 4, 4)).length); + assertEquals( + 3, + RHOMB.getIntersections(new Polyline(0, 0, 0, 4, 4, 4, 2, 2)).length); + assertEquals(4, RHOMB.getIntersections(new Polyline(0, 0, 0, 4, 4, 4, + 2, 2, 4, 0)).length); + assertEquals(5, RHOMB.getIntersections(new Polyline(0, 0, 0, 4, 4, 4, + 2, 2, 4, 0, 0, 0)).length); } + + public void test_contains_Ellipse() { + assertTrue(RHOMB.contains(new Ellipse(1, 1, 2, 2))); + assertFalse(RHOMB.contains(new Ellipse(0, 0, 4, 4))); + } + + public void test_intersects_Ellipse() { + assertTrue(RHOMB.intersects(new Ellipse(0, 0, 4, 4))); + } + + public void test_getIntersections_Ellipse() { + assertTrue(new Polygon(RHOMB.getIntersections(new Ellipse(0, 0, 4, 4))) + .getBounds().equals(RHOMB.getBounds())); + } + + public void test_rotateCW() { + assertEquals(RHOMB, + RHOMB.getCopy().rotateCW(Angle.fromDeg(90), new Point(2, 2))); + + assertEquals( + RHOMB.getCopy().rotateCW(Angle.fromDeg(45), new Point(2, 2)), + RHOMB.getCopy().rotateCW(Angle.fromDeg(90 + 45), + new Point(2, 2))); + } + + public void test_rotateCCW() { + assertEquals(RHOMB, + RHOMB.getCopy().rotateCCW(Angle.fromDeg(90), new Point(2, 2))); + + assertEquals( + RHOMB.getCopy().rotateCCW(Angle.fromDeg(45), new Point(2, 2)), + RHOMB.getCopy().rotateCCW(Angle.fromDeg(90 + 45), + new Point(2, 2))); + } + + public void test_toSWTPointArray() { + double[] coords = RHOMB.getCoordinates(); + int[] ints = RHOMB.toSWTPointArray(); + assertEquals(coords.length, ints.length); + for (int i = 0; i < coords.length; i++) { + assertEquals((int) coords[i], ints[i]); + } + } + + public void test_toString() { + assertEquals("Polygon: ", + new Polygon(new Point[] {}).toString()); + assertEquals( + "Polygon: (0.0, 2.0) -> (2.0, 0.0) -> (4.0, 2.0) -> (2.0, 4.0) -> (0.0, 2.0)", + RHOMB.toString()); + } + } Index: src/org/eclipse/gef4/geometry/tests/PolynomCalculationUtilsTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/PolynomCalculationUtilsTests.java,v retrieving revision 1.1 diff -u -r1.1 PolynomCalculationUtilsTests.java --- src/org/eclipse/gef4/geometry/tests/PolynomCalculationUtilsTests.java 31 Oct 2011 22:17:46 -0000 1.1 +++ src/org/eclipse/gef4/geometry/tests/PolynomCalculationUtilsTests.java 10 Nov 2011 14:57:18 -0000 @@ -121,7 +121,23 @@ } public void test_get_cubic_roots() { - double[] solutions = PolynomCalculationUtils.getCubicRoots(1, 1, 1, 0); + double[] solutions = PolynomCalculationUtils.getCubicRoots(0, 0, 1, 0); + assertEquals("fallthrough", 1, solutions.length); + assertTrue("fallthrough", PrecisionUtils.equal(solutions[0], 0)); + + solutions = PolynomCalculationUtils.getCubicRoots(1, 0, 1, 0); + Arrays.sort(solutions); + assertEquals("three real solutions", 3, solutions.length); + assertTrue("x1 = -1", PrecisionUtils.equal(solutions[0], -1)); + assertTrue("x2 = 0", PrecisionUtils.equal(solutions[1], 0)); + assertTrue("x3 = 1", PrecisionUtils.equal(solutions[2], 1)); + + solutions = PolynomCalculationUtils.getCubicRoots(1, 0, -1, 0); + Arrays.sort(solutions); + assertEquals("one real solution", 1, solutions.length); + assertTrue("x1 = 0", PrecisionUtils.equal(solutions[0], 0)); + + solutions = PolynomCalculationUtils.getCubicRoots(1, 1, 1, 0); Arrays.sort(solutions); assertEquals("one real solution", 1, solutions.length); assertTrue("x^3 + x^2 + x = 0 <=> x(x^2 + x + 1) = 0 => x = 0", Index: src/org/eclipse/gef4/geometry/tests/RectangleTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/RectangleTests.java,v retrieving revision 1.3 diff -u -r1.3 RectangleTests.java --- src/org/eclipse/gef4/geometry/tests/RectangleTests.java 31 Oct 2011 19:36:10 -0000 1.3 +++ src/org/eclipse/gef4/geometry/tests/RectangleTests.java 10 Nov 2011 14:57:18 -0000 @@ -15,9 +15,13 @@ import junit.framework.TestCase; +import org.eclipse.gef4.geometry.Angle; import org.eclipse.gef4.geometry.Dimension; import org.eclipse.gef4.geometry.Point; +import org.eclipse.gef4.geometry.shapes.Line; +import org.eclipse.gef4.geometry.shapes.Polygon; import org.eclipse.gef4.geometry.shapes.Rectangle; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Rectangle}. @@ -38,33 +42,53 @@ private static final double RECOGNIZABLE_FRACTION = PRECISION_FRACTION + PRECISION_FRACTION / 10; - public void testBorderPointsCalculation() { - Rectangle rect = new Rectangle(1, 2, 3, 4); - assertEquals(rect.getTopLeft(), new Point(1, 2)); - assertEquals(rect.getTop(), new Point(2.5, 2)); - assertEquals(rect.getTopRight(), new Point(4, 2)); - assertEquals(rect.getLeft(), new Point(1, 4)); - assertEquals(rect.getRight(), new Point(4, 4)); - assertEquals(rect.getBottomLeft(), new Point(1, 6)); - assertEquals(rect.getBottom(), new Point(2.5, 6)); - assertEquals(rect.getBottomRight(), new Point(4, 6)); - assertEquals(rect.getCenter(), new Point(2.5, 4)); + private interface IAction { + void action(Rectangle rect, Point tl, Point br); } - public void test_clone() { - Rectangle preciseRect = new Rectangle(-9.486614173228347, - -34.431496062992125, 41.99055118110236, 25.92755905511811); - Rectangle clone = (Rectangle) preciseRect.clone(); - assertTrue(preciseRect.equals(clone)); - assertFalse(preciseRect == clone); + private interface IPairAction { + void action(Rectangle r1, Rectangle r2); } - public void test_getCopy() { - Rectangle preciseRect = new Rectangle(-9.486614173228347, - -34.431496062992125, 41.99055118110236, 25.92755905511811); - Rectangle copy = preciseRect.getCopy(); - assertTrue(preciseRect.equals(copy)); - assertFalse(preciseRect == copy); + private void forRectangles(IAction action) { + for (double x1 = -2; x1 <= 2; x1 += 0.4) { + for (double y1 = -2; y1 <= 2; y1 += 0.4) { + Point p1 = new Point(x1, y1); + for (double x2 = -2; x2 <= 2; x2 += 0.4) { + for (double y2 = -2; y2 <= 2; y2 += 0.4) { + Point p2 = new Point(x2, y2); + action.action(new Rectangle(p1, p2), Point.min(p1, p2), + Point.max(p1, p2)); + } + } + } + } + } + + private void forRectanglePairs(IPairAction action) { + for (double x11 = -2; x11 <= 2.4; x11 += 1.1) { + for (double y11 = -2; y11 <= 2.4; y11 += 1.1) { + Point p11 = new Point(x11, y11); + for (double x12 = -2; x12 <= 2.4; x12 += 1.1) { + for (double y12 = -2; y12 <= 2.4; y12 += 1.1) { + Point p12 = new Point(x12, y12); + Rectangle r1 = new Rectangle(p11, p12); + for (double x21 = -2; x21 <= 2.4; x21 += 1.1) { + for (double y21 = -2; y21 <= 2.4; y21 += 1.1) { + Point p21 = new Point(x21, y21); + for (double x22 = -2; x22 <= 2.4; x22 += 1.1) { + for (double y22 = -2; y22 <= 2.4; y22 += 1.1) { + Point p22 = new Point(x22, y22); + Rectangle r2 = new Rectangle(p21, p22); + action.action(r1, r2); + } + } + } + } + } + } + } + } } public void test_new() { @@ -83,6 +107,196 @@ Rectangle rect4 = new Rectangle(0, 0, 10, 10); assertEquals(rect3, rect4); + + // TODO: how about negative width/height? + assertEquals(new Rectangle(), new Rectangle(0, 0, -10, -10)); + assertEquals(new Rectangle(5, 5, 0, 10), new Rectangle(5, 5, -10, 10)); + assertEquals(new Rectangle(5, 5, 10, 0), new Rectangle(5, 5, 10, -10)); + + assertEquals(new Rectangle(), new Rectangle(new Rectangle(0, 0, -10, + -10))); + assertEquals(new Rectangle(5, 5, 0, 10), new Rectangle(new Rectangle(5, + 5, -10, 10))); + assertEquals(new Rectangle(5, 5, 10, 0), new Rectangle(new Rectangle(5, + 5, 10, -10))); + + assertEquals(new Rectangle(), new Rectangle( + new org.eclipse.swt.graphics.Rectangle(0, 0, -10, -10))); + assertEquals(new Rectangle(5, 5, 0, 10), new Rectangle( + new org.eclipse.swt.graphics.Rectangle(5, 5, -10, 10))); + assertEquals(new Rectangle(5, 5, 10, 0), new Rectangle( + new org.eclipse.swt.graphics.Rectangle(5, 5, 10, -10))); + + assertEquals(new Rectangle(), new Rectangle(new Point(0, 0), + new Dimension(-10, -10))); + assertEquals(new Rectangle(5, 5, 0, 10), new Rectangle(new Point(5, 5), + new Dimension(-10, 10))); + assertEquals(new Rectangle(5, 5, 10, 0), new Rectangle(new Point(5, 5), + new Dimension(10, -10))); + + assertEquals(new Rectangle(-10, -10, 10, 10), new Rectangle(new Point( + 0, 0), new Point(-10, -10))); + assertEquals(new Rectangle(-10, 5, 15, 5), new Rectangle( + new Point(5, 5), new Point(-10, 10))); + assertEquals(new Rectangle(5, -10, 5, 15), new Rectangle( + new Point(5, 5), new Point(10, -10))); + } + + public void test_clone() { + Rectangle preciseRect = new Rectangle(-9.486614173228347, + -34.431496062992125, 41.99055118110236, 25.92755905511811); + Rectangle clone = (Rectangle) preciseRect.clone(); + assertTrue(preciseRect.equals(clone)); + assertFalse(preciseRect == clone); + } + + public void test_getCopy() { + Rectangle preciseRect = new Rectangle(-9.486614173228347, + -34.431496062992125, 41.99055118110236, 25.92755905511811); + Rectangle copy = preciseRect.getCopy(); + assertTrue(preciseRect.equals(copy)); + assertFalse(preciseRect == copy); + } + + public void test_isEmpty() { + assertFalse(new Rectangle(0, 0, 10, 10).isEmpty()); + assertTrue(new Rectangle(0, 0, 0, 10).isEmpty()); + assertTrue(new Rectangle(0, 0, 10, 0).isEmpty()); + assertTrue(new Rectangle(0, 0, -10, 10).isEmpty()); + assertTrue(new Rectangle(0, 0, 10, -10).isEmpty()); + assertTrue(new Rectangle(0, 0, UNRECOGNIZABLE_FRACTION, 10).isEmpty()); + assertTrue(new Rectangle(0, 0, 10, UNRECOGNIZABLE_FRACTION).isEmpty()); + assertFalse(new Rectangle(0, 0, RECOGNIZABLE_FRACTION, 10).isEmpty()); + assertFalse(new Rectangle(0, 0, 10, RECOGNIZABLE_FRACTION).isEmpty()); + } + + public void testBorderPointsCalculation() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + Point to = new Point((tl.x + br.x) / 2, tl.y); + Point le = new Point(tl.x, (tl.y + br.y) / 2); + Point tr = new Point(br.x, tl.y); + Point ri = new Point(br.x, le.y); + Point bl = new Point(tl.x, br.y); + Point bo = new Point(to.x, br.y); + Point ce = new Point(to.x, le.y); + assertEquals(tl, rect.getTopLeft()); + assertEquals(to, rect.getTop()); + assertEquals(tr, rect.getTopRight()); + assertEquals(le, rect.getLeft()); + assertEquals(ri, rect.getRight()); + assertEquals(bl, rect.getBottomLeft()); + assertEquals(bo, rect.getBottom()); + assertEquals(br, rect.getBottomRight()); + assertEquals(ce, rect.getCenter()); + } + }); + } + + public void test_getBounds() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + assertEquals(rect, rect.getBounds()); + } + }); + } + + public void test_getSize() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + assertEquals(new Dimension(br.x - tl.x, br.y - tl.y), + rect.getSize()); + } + }); + } + + public void test_getLocation() { + Rectangle r1 = new Rectangle(5, 10, 1, 2); + + assertEquals(new Point(5, 10), r1.getLocation()); + } + + public void test_setBounds() { + Rectangle r = new Rectangle(); + + r.setBounds(new Rectangle(10, 10, 10, 10)); + assertEquals(new Point(10, 10), r.getTopLeft()); + assertEquals(new Point(20, 20), r.getBottomRight()); + + r.setBounds(new Point(-5, -5), new Dimension(5, 5)); + assertEquals(new Point(-5, -5), r.getTopLeft()); + assertEquals(new Point(), r.getBottomRight()); + + r.setBounds(3, 2, 1, 0); + assertEquals(new Point(3, 2), r.getTopLeft()); + assertEquals(new Point(4, 2), r.getBottomRight()); + } + + public void test_setSize() { + Rectangle r = new Rectangle(); + + r.setSize(new Dimension(10, 20)); + assertEquals(new Point(), r.getTopLeft()); + assertEquals(new Point(10, 20), r.getBottomRight()); + + r.setSize(5, -10); + assertEquals(new Point(), r.getTopLeft()); + assertEquals(new Point(5, 0), r.getBottomRight()); + } + + public void test_setters() { + Rectangle r = new Rectangle(); + + r.setX(10); + assertTrue(PrecisionUtils.equal(10, r.getX())); + + r.setY(1); + assertTrue(PrecisionUtils.equal(1, r.getY())); + + r.setWidth(5); + assertTrue(PrecisionUtils.equal(5, r.getWidth())); + + r.setHeight(6); + assertTrue(PrecisionUtils.equal(6, r.getHeight())); + + r.setWidth(-10); + assertTrue(PrecisionUtils.equal(0, r.getWidth())); + + r.setHeight(-1); + assertTrue(PrecisionUtils.equal(0, r.getHeight())); + } + + public void test_getTransposed() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + assertEquals( + new Rectangle(tl.y, tl.x, br.y - tl.y, br.x - tl.x), + rect.getTransposed()); + } + }); + } + + public void test_getTranslated() { + Rectangle r1 = new Rectangle(1, 2, 3, 4); + + assertEquals(new Rectangle(0, 3, 3, 4), + r1.getTranslated(new Point(-1, 1))); + assertEquals(new Rectangle(0, 3, 3, 4), r1.getTranslated(-1, 1)); + } + + public void test_getSegments() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + Line[] segments = rect.getSegments(); + // segments are top, right, bottom, left. in order. + Point tr = tl.getTranslated(br.x - tl.x, 0); + Point bl = tl.getTranslated(0, br.y - tl.y); + assertEquals(new Line(tl, tr), segments[0]); + assertEquals(new Line(tr, br), segments[1]); + assertEquals(new Line(br, bl), segments[2]); + assertEquals(new Line(bl, tl), segments[3]); + } + }); } public void test_contains_Point() { @@ -209,16 +423,121 @@ assertFalse(recognizableExpanded.equals(recognizableShrinked)); } + public void test_getIntersected() { + Rectangle r1 = new Rectangle(0, 0, 10, 10); + + // check no intersection, containment, partial intersection and identity + + assertEquals(new Rectangle(), + r1.getIntersected(new Rectangle(-20, -20, 5, 5))); + assertEquals(new Rectangle(5, 5, 5, 5), + r1.getIntersected(new Rectangle(5, 5, 10, 10))); + assertEquals(new Rectangle(2, 2, 6, 6), + r1.getIntersected(new Rectangle(2, 2, 6, 6))); + assertEquals(r1, r1.getIntersected(r1)); + } + + public void test_union() { + // check union behaves like constructor + Point p1 = new Point(0, 0); + Point p2 = new Point(10, 10); + + Rectangle origRect = new Rectangle(); + origRect.setLocation(p1); + origRect.union(p2); + + assertEquals(origRect, new Rectangle(p1, p2)); + + Point p3 = new Point(5, 5); + assertEquals(origRect, new Rectangle(p1, p3).union(origRect)); + } + + public void test_getUnioned_with_Point() { + Rectangle r1 = new Rectangle(1, 2, 2, 2); + + // check union with coordinates left, on-left, center, on-right, right + // and above, on-top, center, on-bottom, below, respectively + + assertEquals(new Rectangle(0, 1, 3, 3), r1.getUnioned(new Point(0, 1))); + assertEquals(new Rectangle(0, 2, 3, 2), r1.getUnioned(new Point(0, 2))); + assertEquals(new Rectangle(0, 2, 3, 2), r1.getUnioned(new Point(0, 3))); + assertEquals(new Rectangle(0, 2, 3, 2), r1.getUnioned(new Point(0, 4))); + assertEquals(new Rectangle(0, 2, 3, 3), r1.getUnioned(new Point(0, 5))); + + assertEquals(new Rectangle(1, 1, 2, 3), r1.getUnioned(new Point(1, 1))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(1, 2))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(1, 3))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(1, 4))); + assertEquals(new Rectangle(1, 2, 2, 3), r1.getUnioned(new Point(1, 5))); + + assertEquals(new Rectangle(1, 1, 2, 3), r1.getUnioned(new Point(2, 1))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(2, 2))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(2, 3))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(2, 4))); + assertEquals(new Rectangle(1, 2, 2, 3), r1.getUnioned(new Point(2, 5))); + + assertEquals(new Rectangle(1, 1, 2, 3), r1.getUnioned(new Point(3, 1))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(3, 2))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(3, 3))); + assertEquals(new Rectangle(1, 2, 2, 2), r1.getUnioned(new Point(3, 4))); + assertEquals(new Rectangle(1, 2, 2, 3), r1.getUnioned(new Point(3, 5))); + + assertEquals(new Rectangle(1, 1, 3, 3), r1.getUnioned(new Point(4, 1))); + assertEquals(new Rectangle(1, 2, 3, 2), r1.getUnioned(new Point(4, 2))); + assertEquals(new Rectangle(1, 2, 3, 2), r1.getUnioned(new Point(4, 3))); + assertEquals(new Rectangle(1, 2, 3, 2), r1.getUnioned(new Point(4, 4))); + assertEquals(new Rectangle(1, 2, 3, 3), r1.getUnioned(new Point(4, 5))); + } + + public void test_getUnioned_with_Rectangle() { + Rectangle r1 = new Rectangle(1, 2, 2, 2); + + // containment + Rectangle contained = new Rectangle(1.5, 2.5, 1, 1); + assertEquals(r1, r1.getUnioned(contained)); + Rectangle contains = new Rectangle(0, 1, 4, 4); + assertEquals(contains, r1.getUnioned(contains)); + + // corners + Rectangle tl = new Rectangle(0, 1, 2, 2); + assertEquals(new Rectangle(0, 1, 3, 3), r1.getUnioned(tl)); + Rectangle tr = new Rectangle(2, 1, 2, 2); + assertEquals(new Rectangle(1, 1, 3, 3), r1.getUnioned(tr)); + Rectangle bl = new Rectangle(0, 3, 2, 2); + assertEquals(new Rectangle(0, 2, 3, 3), r1.getUnioned(bl)); + Rectangle br = new Rectangle(2, 3, 2, 2); + assertEquals(new Rectangle(1, 2, 3, 3), r1.getUnioned(br)); + } + public void test_scale() { Rectangle rect = new Rectangle(-9.486614173228347, -34.431496062992125, 41.99055118110236, 25.92755905511811); rect.scale(26.458333333333332); rect.scale(1.0 / 26.458333333333332); - assertEquals(-9.486614173228347, rect.getX(), 0); - assertEquals(-34.431496062992125, rect.getY(), 0); - assertEquals(41.99055118110236, rect.getWidth(), 0); - assertEquals(25.92755905511811, rect.getHeight(), 0); + assertTrue(PrecisionUtils.equal(-9.486614173228347, rect.getX())); + assertTrue(PrecisionUtils.equal(-34.431496062992125, rect.getY())); + assertTrue(PrecisionUtils.equal(41.99055118110236, rect.getWidth())); + assertTrue(PrecisionUtils.equal(25.92755905511811, rect.getHeight())); + } + + public void test_getScaled() { + Rectangle rect = new Rectangle(-9.486614173228347, -34.431496062992125, + 41.99055118110236, 25.92755905511811).getScaled( + 26.458333333333332).getScaled(1.0 / 26.458333333333332); + + assertTrue(PrecisionUtils.equal(-9.486614173228347, rect.getX())); + assertTrue(PrecisionUtils.equal(-34.431496062992125, rect.getY())); + assertTrue(PrecisionUtils.equal(41.99055118110236, rect.getWidth())); + assertTrue(PrecisionUtils.equal(25.92755905511811, rect.getHeight())); + + rect = new Rectangle(-9.486614173228347, -34.431496062992125, + 41.99055118110236, 25.92755905511811).getScaled(2, 0); + + assertTrue(PrecisionUtils.equal(-9.486614173228347, rect.getX())); + assertTrue(PrecisionUtils.equal(-34.431496062992125, rect.getY())); + assertTrue(PrecisionUtils.equal(2 * 41.99055118110236, rect.getWidth())); + assertTrue(PrecisionUtils.equal(0, rect.getHeight())); } public void test_shrink() { @@ -259,24 +578,83 @@ assertEquals(preciseRect, recognizableShrinked); } + private Polygon fromRectangle(double x, double y, double w, double h) { + return new Polygon(x, y, x + w, y, x + w, y + h, x, y + h); + } + + public void test_getRotatedCW() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + Polygon expected = fromRectangle(tl.x - rect.getHeight(), tl.y, + rect.getHeight(), rect.getWidth()); + Polygon rotatedCW = rect.getRotatedCW(Angle.fromDeg(90), + rect.getLocation()); + + // DEBUG + // if (!expected.equals(rotatedCW)) + // throw new IllegalStateException(""); + + assertEquals(expected, rotatedCW); + } + }); + } + + public void test_getRotatedCCW() { + forRectangles(new IAction() { + public void action(Rectangle rect, Point tl, Point br) { + assertEquals( + fromRectangle(tl.x, tl.y - rect.getWidth(), + rect.getHeight(), rect.getWidth()), + rect.getRotatedCCW(Angle.fromDeg(90), + rect.getLocation())); + } + }); + } + + public void test_intersects_with_Line() { + Rectangle r1 = new Rectangle(-5, -5, 10, 10); + + for (Line seg : r1.getSegments()) { + assertTrue(r1.intersects(seg)); + } + + assertTrue(r1 + .intersects(new Line(r1.getTopLeft(), r1.getBottomRight()))); + assertTrue(r1.intersects(new Line(r1.getTop(), r1.getBottom()))); + + assertTrue(r1.intersects(new Line(-10, 0, 10, 0))); + assertFalse(r1.intersects(new Line(-10, 0, -6, 0))); + assertFalse(r1.intersects(new Line(0, -10, 0, -6))); + assertFalse(r1.intersects(new Line(10, 0, 6, 0))); + assertFalse(r1.intersects(new Line(0, 10, 0, 6))); + } + + public void test_intersects_with_Rectangle() { + forRectanglePairs(new IPairAction() { + public void action(Rectangle r1, Rectangle r2) { + assertTrue(r1.intersects(r2) != r1.getIntersected(r2).isEmpty()); + } + }); + } + + public void test_toPolygon() { + Point[] points = new Point[] { new Point(10, 10), + new Point(10 + 25, 10), new Point(10 + 25, 10 + 50), + new Point(10, 10 + 50) }; + Rectangle r = new Rectangle(points[0], points[2]); + Polygon pr = new Polygon(points); + assertTrue(pr.equals(r.toPolygon())); + } + public void test_toSWTRectangle() { org.eclipse.swt.graphics.Rectangle r = new org.eclipse.swt.graphics.Rectangle( 1, 2, 3, 4); assertEquals(r, new Rectangle(r).toSWTRectangle()); } - public void test_union() { - // check union behaves like constructor - Point p1 = new Point(0, 0); - Point p2 = new Point(10, 10); - - Rectangle origRect = new Rectangle(); - origRect.setLocation(p1); - origRect.union(p2); - - assertEquals(origRect, new Rectangle(p1, p2)); - - Point p3 = new Point(5, 5); - assertEquals(origRect, new Rectangle(p1, p3).union(origRect)); + public void test_toString() { + Rectangle r = new Rectangle(); + assertEquals("Rectangle: (0.0, 0.0, 0.0, 0.0)", r.toString()); } + } Index: src/org/eclipse/gef4/geometry/tests/StraightTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/StraightTests.java,v retrieving revision 1.2 diff -u -r1.2 StraightTests.java --- src/org/eclipse/gef4/geometry/tests/StraightTests.java 31 Oct 2011 19:36:10 -0000 1.2 +++ src/org/eclipse/gef4/geometry/tests/StraightTests.java 10 Nov 2011 14:57:18 -0000 @@ -20,6 +20,7 @@ import org.eclipse.gef4.geometry.Point; import org.eclipse.gef4.geometry.euclidean.Straight; import org.eclipse.gef4.geometry.euclidean.Vector; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Straight}. @@ -29,6 +30,105 @@ */ public class StraightTests extends TestCase { + public void test_equals() { + Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); + Straight s2 = new Straight(new Vector(4, 4), new Vector(2, 2)); + assertTrue(s1.equals(s2)); + assertTrue(s2.equals(s1)); + assertFalse(s1.equals(new Straight(new Vector(2, 0), s1.direction))); + + // wrong type + assertFalse(s1.equals(new Point())); + } + + public void test_constructors() { + Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); + Straight s2 = new Straight(new Point(0, 0), new Point(3, 3)); + assertTrue(s1.equals(s2)); + + s1 = new Straight(new Vector(1, 2), new Vector(3, 4)); + s2 = new Straight(new Point(1, 2), new Point(3, 4)); + assertFalse(s1.equals(s2)); + + } + + public void test_getCopy() { + Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); + + assertTrue(s1.getCopy().equals(s1)); + assertTrue(s1.clone().equals(s1)); + assertTrue(s1.getCopy().equals(s1.clone())); + } + + public void test_isParallelTo_with_Straight() { + Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); + Straight s2 = new Straight(new Vector(0, 4), new Vector(2, 2)); + assertTrue(s1.isParallelTo(s2)); + + s1 = new Straight(new Vector(0, 0), new Vector(5, 5)); + s2 = new Straight(new Vector(0, 5), new Vector(0, 5)); + assertFalse(s1.isParallelTo(s2)); + } + + public void test_contains() { + Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); + + assertTrue(s1.contains(new Vector(0, 0))); + assertTrue(s1.contains(new Vector(1, 1))); + assertTrue(s1.contains(new Vector(2, 2))); + assertTrue(s1.contains(new Vector(-1, -1))); + assertTrue(s1.contains(new Vector(-2, -2))); + assertFalse(s1.contains(new Vector(0, 1))); + assertFalse(s1.contains(new Vector(-1, 0))); + } + + public void test_containsWithinSegment() { + Straight s1 = new Straight(new Point(), new Point(0, -1)); + + boolean thrown = false; + try { + s1.containsWithinSegment(new Vector(0, 0), new Vector(1, 2), + new Vector(0, 1)); + } catch (IllegalArgumentException x) { + thrown = true; + } + assertTrue(thrown); + + thrown = false; + try { + s1.containsWithinSegment(new Vector(1, 2), new Vector(0, 0), + new Vector(0, 1)); + } catch (IllegalArgumentException x) { + thrown = true; + } + assertTrue(thrown); + + assertTrue(s1.containsWithinSegment(new Vector(0, 0), + new Vector(0, 10), new Vector(0, 0))); + assertTrue(s1.containsWithinSegment(new Vector(0, 0), + new Vector(0, -10), new Vector(0, 0))); + assertTrue(s1.containsWithinSegment(new Vector(0, 0), new Vector(0, 0), + new Vector(0, 0))); + assertTrue(s1.containsWithinSegment(new Vector(0, 0), + new Vector(0, 10), new Vector(0, 5))); + assertTrue(s1.containsWithinSegment(new Vector(0, 0), + new Vector(0, -10), new Vector(0, -5))); + assertFalse(s1.containsWithinSegment(new Vector(0, 1), + new Vector(0, 10), new Vector(0, 0))); + assertFalse(s1.containsWithinSegment(new Vector(0, -1), new Vector(0, + -10), new Vector(0, 0))); + assertFalse(s1.containsWithinSegment(new Vector(0, 0), + new Vector(0, 10), new Vector(0, -5))); + assertFalse(s1.containsWithinSegment(new Vector(0, 0), new Vector(0, + -10), new Vector(0, 5))); + + s1 = new Straight(new Point(), new Point(1, 0)); + assertTrue(s1.containsWithinSegment(new Vector(0, 0), new Vector(3, 0), + new Vector(2, 0))); + assertFalse(s1.containsWithinSegment(new Vector(0, 0), + new Vector(3, 0), new Vector(5, 0))); + } + public void test_getIntersection_with_Straight() { // test integer precision Vector p = new Vector(1, 1); @@ -37,12 +137,15 @@ Vector b = new Vector(1, -1); Straight s1 = new Straight(p, a); Straight s2 = new Straight(q, b); + assertTrue(s1.intersects(s2)); Vector intersection = s1.getIntersection(s2); assertTrue(intersection.equals(new Vector(3, 2))); assertTrue(s1.contains(intersection)); assertTrue(s2.contains(intersection)); // check straight does not intersect itself + assertFalse(s1.intersects(s1)); + assertFalse(s2.intersects(s2)); assertNull(new Straight(p, a).getIntersection(new Straight(p, a))); // test double precision @@ -52,6 +155,7 @@ b = new Vector(new Point(0, 5), new Point(5, 0)); s1 = new Straight(p, a); s2 = new Straight(q, b); + assertTrue(s1.intersects(s2)); intersection = s1.getIntersection(s2); assertTrue(intersection.equals(new Vector(2.5, 2.5))); assertTrue(s1.contains(intersection)); @@ -63,6 +167,7 @@ Point p4 = new Point(0, 3); s1 = new Straight(p1, p2); s2 = new Straight(p3, p4); + assertTrue(s1.intersects(s2)); intersection = s1.getIntersection(s2); assertTrue(intersection.equals(new Vector(0, 1))); assertTrue(s1.contains(intersection)); @@ -81,32 +186,137 @@ assertNotNull(intersection); assertTrue(s1.contains(intersection)); assertTrue(s2.contains(intersection)); - } - public void test_isParallelTo_with_Straight() { - Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); - Straight s2 = new Straight(new Vector(0, 4), new Vector(2, 2)); - assertTrue(s1.isParallelTo(s2)); + // test no intersection + p1 = new Point(0, 10); + p2 = new Point(10, 10); + p3 = new Point(0, 5); + p4 = new Point(10, 5); - s1 = new Straight(new Vector(0, 0), new Vector(5, 5)); - s2 = new Straight(new Vector(0, 5), new Vector(0, 5)); - assertFalse(s1.isParallelTo(s2)); + s1 = new Straight(p1, p2); + s2 = new Straight(p3, p4); + + assertFalse(s1.intersects(s2)); + assertFalse(s2.intersects(s1)); + + intersection = s1.getIntersection(s2); + assertNull(intersection); + } + + public void test_intersectsWithinSegment() { + Straight s1 = new Straight(new Point(), new Point(10, 10)); + Straight s2 = new Straight(new Point(), new Point(-10, 10)); + + boolean thrown = false; + try { + s1.intersectsWithinSegment(new Vector(0, 0), new Vector(0, 1), s2); + } catch (IllegalArgumentException x) { + thrown = true; + } + assertTrue(thrown); + + thrown = false; + try { + s1.intersectsWithinSegment(new Vector(1, 0), new Vector(0, 0), s2); + } catch (IllegalArgumentException x) { + thrown = true; + } + assertTrue(thrown); + + assertTrue("fallthrough", s1.intersectsWithinSegment(new Vector(0, 0), + new Vector(0, 0), s2)); + assertTrue(s1.intersectsWithinSegment(new Vector(-1, -1), new Vector(0, + 0), s2)); + assertTrue(s1.intersectsWithinSegment(new Vector(1, 1), + new Vector(0, 0), s2)); + assertTrue(s1.intersectsWithinSegment(new Vector(-1, -1), new Vector(1, + 1), s2)); + assertFalse(s1.intersectsWithinSegment(new Vector(-1, -1), new Vector( + -20, -20), s2)); + assertFalse(s1.intersectsWithinSegment(new Vector(1, 1), new Vector(20, + 20), s2)); + assertFalse(s1.intersectsWithinSegment(new Vector(-20, -20), + new Vector(20, 20), new Straight(new Vector(10, 0), new Vector( + 10, 10)))); } public void test_getAngle_withStraight() { Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); Straight s2 = new Straight(new Vector(0, 4), new Vector(2, 2)); assertTrue(s1.getAngle(s2).equals(Angle.fromDeg(0))); + assertTrue(s1.getAngleCW(s2).equals(Angle.fromDeg(0))); + assertTrue(s1.getAngleCCW(s2).equals(Angle.fromDeg(0))); s1 = new Straight(new Vector(0, 0), new Vector(5, 5)); s2 = new Straight(new Vector(0, 5), new Vector(0, 5)); - assertTrue(s1.getAngle(s2).equals(Angle.fromDeg(45))); // rounding - // effects + assertTrue(s1.getAngle(s2).equals(Angle.fromDeg(45))); + assertTrue(s1.getAngleCW(s2).equals(Angle.fromDeg(45))); + assertTrue(s1.getAngleCCW(s2).equals(Angle.fromDeg(135))); } - public void test_equals() { - Straight s1 = new Straight(new Vector(0, 0), new Vector(3, 3)); - Straight s2 = new Straight(new Vector(4, 4), new Vector(2, 2)); - assertTrue(s1.equals(s2)); + public void test_getProjection() { + Straight s1 = new Straight(new Point(), new Point(0, 1)); + + for (int i = 0; i < 10; i++) { + Vector v = new Vector(i + 1, i - 1); + assertTrue(s1.getProjection(v).equals(new Vector(0, i - 1))); + } + } + + public void test_getDistance() { + Straight s1 = new Straight(new Point(), new Point(0, 1)); + + for (int i = 0; i < 10; i++) { + Vector v = new Vector(i + 1, i - 1); + assertTrue(PrecisionUtils.equal(s1.getDistance(v), i + 1)); + } } + + public void test_getSignedDistance() { + Straight s1 = new Straight(new Point(), new Point(0, -1)); + + for (int i = -5; i <= 0; i++) { + Vector v = new Vector(i, 0); + assertTrue(PrecisionUtils.equal(s1.getSignedDistanceCW(v), i)); + assertTrue(PrecisionUtils.equal(s1.getSignedDistanceCCW(v), -i)); + } + + for (int i = 0; i <= 5; i++) { + Vector v = new Vector(i, 0); + assertTrue(PrecisionUtils.equal(s1.getSignedDistanceCW(v), i)); + assertTrue(PrecisionUtils.equal(s1.getSignedDistanceCCW(v), -i)); + } + } + + public void test_toString() { + Straight s1 = new Straight(new Point(), new Point(0, -1)); + assertEquals("Straight: Vector: [0.0,0.0] + s * Vector: [0.0,-1.0]", + s1.toString()); + } + + public void test_parameter_point() { + // normalized direction vector, so that one can comprehend the + // parameter's value + Straight s1 = new Straight(new Point(), new Point(0, -1)); + + assertTrue(PrecisionUtils.equal(s1.getParameterAt(new Point()), 0)); + assertTrue(PrecisionUtils.equal(s1.getParameterAt(new Point(0, -1)), 1)); + assertTrue(PrecisionUtils.equal(s1.getParameterAt(new Point(0, 1)), -1)); + + assertTrue(s1.getPointAt(0).equals(new Point())); + assertTrue(s1.getPointAt(2).equals(new Point(0, -2))); + assertTrue(s1.getPointAt(-2).equals(new Point(0, 2))); + + s1 = new Straight(new Point(), new Point(1, 0)); + + assertTrue(PrecisionUtils.equal(s1.getParameterAt(new Point()), 0)); + assertTrue(PrecisionUtils.equal(s1.getParameterAt(new Point(2, 0)), 2)); + assertTrue(PrecisionUtils + .equal(s1.getParameterAt(new Point(-2, 0)), -2)); + + assertTrue(s1.getPointAt(0).equals(new Point())); + assertTrue(s1.getPointAt(1).equals(new Point(1, 0))); + assertTrue(s1.getPointAt(-1).equals(new Point(-1, 0))); + } + } Index: src/org/eclipse/gef4/geometry/tests/VectorTests.java =================================================================== RCS file: /cvsroot/tools/org.eclipse.gef/GEF4/plugins/org.eclipse.gef4.geometry.tests/src/org/eclipse/gef4/geometry/tests/VectorTests.java,v retrieving revision 1.4 diff -u -r1.4 VectorTests.java --- src/org/eclipse/gef4/geometry/tests/VectorTests.java 31 Oct 2011 19:36:10 -0000 1.4 +++ src/org/eclipse/gef4/geometry/tests/VectorTests.java 10 Nov 2011 14:57:18 -0000 @@ -14,8 +14,10 @@ import junit.framework.TestCase; +import org.eclipse.gef4.geometry.Angle; import org.eclipse.gef4.geometry.Point; import org.eclipse.gef4.geometry.euclidean.Vector; +import org.eclipse.gef4.geometry.utils.PrecisionUtils; /** * Unit tests for {@link Vector}. @@ -34,7 +36,42 @@ private static final double RECOGNIZABLE_FRACTION = PRECISION_FRACTION + PRECISION_FRACTION / 10; - public void test_Equals() { + private interface VectorAction { + void action(Vector a); + } + + private void forVectors(VectorAction action) { + for (double x = -2; x <= 2; x += 0.2) { + for (double y = -2; y <= 2; y += 0.2) { + Vector a = new Vector(x, y); + action.action(a); + } + } + } + + private abstract class VectorPairAction { + public void action(Vector a, Vector b) { + } + + public Vector alterA(Vector a) { + return a; + } + } + + private void forVectorPairs(VectorPairAction action) { + for (double x1 = -2; x1 <= 2; x1 += 0.2) { + for (double y1 = -2; y1 <= 2; y1 += 0.2) { + Vector a = action.alterA(new Vector(x1, y1)); + for (double x2 = -2; x2 <= 2; x2 += 0.2) { + for (double y2 = -2; y2 <= 2; y2 += 0.2) { + action.action(a, new Vector(x2, y2)); + } + } + } + } + } + + public void test_equals() { Vector a = new Vector(3, 2); Vector b = new Vector(2, -2); assertTrue(a.equals(a)); @@ -46,18 +83,352 @@ RECOGNIZABLE_FRACTION)))); } + public void test_constructors() { + Vector a = new Vector(1, 2); + assertTrue(a.equals(new Vector(new Point(1, 2)))); + assertTrue(a.equals(new Vector(new Point(), new Point(1, 2)))); + assertTrue(a.equals(new Vector(new Point(1, 2), new Point(2, 4)))); + assertTrue(a.equals(new Vector(new Vector(0, 0), new Vector(1, 2)))); + assertTrue(a.equals(new Vector(new Vector(-1, -2), new Vector(0, 0)))); + } + + public void test_copy() { + Vector a = new Vector(1, 2); + + assertTrue(a.getCopy().equals(a)); + assertTrue(a.clone().equals(a)); + assertTrue(a.getCopy().equals(a.clone())); + } + + public void test_isNull() { + forVectors(new VectorAction() { + public void action(Vector a) { + assertTrue(a.isNull() == (PrecisionUtils.equal(a.x, 0) && PrecisionUtils + .equal(a.y, 0))); + } + }); + } + + public void test_isHorizontal() { + forVectors(new VectorAction() { + public void action(Vector a) { + assertTrue(a.isHorizontal() != PrecisionUtils.equal(a.x, 0)); + } + }); + } + + public void test_isVertical() { + forVectors(new VectorAction() { + public void action(Vector a) { + assertTrue(a.isVertical() != PrecisionUtils.equal(a.y, 0)); + } + }); + } + + public void test_getAdded() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(a.getAdded(b).equals( + new Vector(a.x + b.x, a.y + b.y))); + } + }); + } + + public void test_getSubtracted() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(a.getSubtracted(b).equals( + new Vector(a.x - b.x, a.y - b.y))); + } + }); + } + + public void test_getMultiplied() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(a.getMultiplied(b.x).equals( + new Vector(a.x * b.x, a.y * b.x))); + assertTrue(a.getMultiplied(b.y).equals( + new Vector(a.x * b.y, a.y * b.y))); + } + }); + } + + public void test_getDivided() { + forVectors(new VectorAction() { + public void action(Vector a) { + for (double r = -2; r <= 2; r += 0.2) { + // TODO: no PrecisionUtils in getDivided() + assertTrue(r != 0); + assertTrue(a.getDivided(r).equals( + new Vector(a.x / r, a.y / r))); + } + + boolean thrown = false; + try { + a.getDivided(0); + } catch (ArithmeticException _) { + thrown = true; + } + assertTrue(thrown); + } + }); + } + + public void test_getAveraged() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(a.getAveraged(b).equals( + a.getAdded(b).getMultiplied(0.5))); + } + }); + } + public void test_getLength() { assertEquals(new Vector(3, 4).getLength(), 5.0d); + + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + if (a.isNull()) { + assertTrue(PrecisionUtils.equal(a.getLength(), 0)); + } else if (b.isNull()) { + assertTrue(PrecisionUtils.equal(b.getLength(), 0)); + } else { + assertTrue(PrecisionUtils.equal(a.getDivided(a.getLength()) + .getLength(), (b.getDivided(b.getLength()) + .getLength()))); + } + } + }); + } + + public void test_getDotProduct() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(PrecisionUtils.equal(a.getDotProduct(b), a.x * b.x + + a.y * b.y)); + } + }); + } + + public void test_getCrossProduct() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(PrecisionUtils.equal(a.getCrossProduct(b), a.x * b.y + - a.y * b.x)); + } + }); } public void test_getOrthoComplement() { Vector a = new Vector(3, -5); assertTrue(a.getOrthogonalComplement().equals(new Vector(5, 3))); + + forVectors(new VectorAction() { + public void action(Vector a) { + assertTrue(PrecisionUtils.equal(a.getOrthogonalComplement() + .getDotProduct(a), 0)); + } + }); } - public void test_getDotProduct() { - Vector a = new Vector(3, 2); - Vector b = new Vector(2, -2); - assertTrue(a.getDotProduct(b) == 2); + public void test_getAngle() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(PrecisionUtils.equal( + a.getDotProduct(b), + a.getLength() * b.getLength() + * Math.cos(a.getAngle(b).rad()))); + } + }); + + // test for the ArithmeticException is case of a null-vector + for (Vector a : new Vector[] { new Vector(1, 2), new Vector(0, 0) }) { + for (Vector b : new Vector[] { new Vector(0, 0), new Vector(1, 2) }) { + boolean thrown = a.getLength() != 0 && b.getLength() != 0; + try { + a.getAngle(b); + } catch (ArithmeticException x) { + thrown = true; + } + assertTrue(thrown); + } + } + } + + public void test_getAngleCW() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + Angle alphaCW = a.getAngleCW(b); + + Angle alpha = a.getAngle(b); + if (a.getCrossProduct(b) < 0) { + alpha = alpha.getOppositeFull(); + } + + assertTrue(alpha.equals(alphaCW)); + } + }); + } + + public void test_getAngleCCW() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + Angle alpha = a.getAngle(b); + Angle alphaCCW = a.getAngleCCW(b); + + if (a.getCrossProduct(b) > 0) { + alpha = alpha.getOppositeFull(); + } + + assertTrue(alpha.equals(alphaCCW)); + } + }); + } + + public void test_rotateCW() { + forVectors(new VectorAction() { + public void action(Vector a) { + for (double alpha = 0; alpha <= 4 * Math.PI; alpha += 0.1) { + Angle angle = Angle.fromRad(alpha); + Vector rotated = a.getRotatedCW(angle); + double x = a.x * Math.cos(alpha) - a.y * Math.sin(alpha); + double y = a.x * Math.sin(alpha) + a.y * Math.cos(alpha); + assertTrue(rotated.equals(new Vector(x, y))); + + a.rotateCW(angle); + assertTrue(rotated.equals(a)); + } + } + }); + } + + public void test_rotateCCW() { + forVectors(new VectorAction() { + public void action(Vector a) { + for (double alpha = 0; alpha <= 4 * Math.PI; alpha += 0.1) { + Angle angle = Angle.fromRad(alpha); + Vector rotated = a.getRotatedCCW(angle); + double nAlpha = angle.getOppositeFull().rad(); + double x = a.x * Math.cos(nAlpha) - a.y * Math.sin(nAlpha); + double y = a.x * Math.sin(nAlpha) + a.y * Math.cos(nAlpha); + assertTrue(rotated.equals(new Vector(x, y))); + + a.rotateCCW(angle); + assertTrue(rotated.equals(a)); + } + } + }); + } + + public void test_getNormalized() { + final Vector x = new Vector(1, 0); + + forVectors(new VectorAction() { + public void action(Vector a) { + assertTrue(a.x != 0); + assertTrue(a.y != 0); + + Vector normalized = a.getNormalized(); + Angle origAlpha = a.getAngleCW(x); + Angle normAlpha = normalized.getAngleCW(x); + + assertTrue(PrecisionUtils.equal(normalized.getLength(), 1)); + assertTrue(PrecisionUtils.equal(origAlpha.rad(), + normAlpha.rad())); + } + }); + } + + public void test_getSimilarity() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(PrecisionUtils.equal(a.getSimilarity(b), + Math.abs(a.getDotProduct(b)))); + } + }); + } + + public void test_getDissimilarity() { + Vector vx = new Vector(5, 0); + Vector vy = new Vector(0, 5); + Vector vxy = new Vector(5, 5); + + // cross product uses vectors's lengths! + assertTrue(vx.getDissimilarity(vy) > vx.getDissimilarity(vxy)); + // note: no PrecisionUtils here, because we need "is really greater" + + // TODO: normalize the vectors first, so that they get comparable. + + // the description of the method is mistakable: + // 1) does it mean that an angle of 180° returns the same dissimilarity + // as an angle of 0° + // 2) or does it mean that an angle of 180° returns the highest + // dissimilarity? + // + // the following code expects the first case + + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(PrecisionUtils.equal( + a.getDissimilarity(b), + Math.abs(a.getNormalized().getCrossProduct( + b.getNormalized())))); + } + }); + } + + public void test_isParallelTo() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + Angle alpha = a.getAngle(b); + alpha.setRad(alpha.rad() * 2d); + + // DEBUG + // if (a.isParallelTo(b) != alpha.equals(Angle.fromRad(0))) + // throw new IllegalStateException(""); + + assertTrue(a.isParallelTo(b) == alpha.equals(Angle.fromRad(0))); + } + }); + } + + public void test_isOrthogonalTo() { + forVectorPairs(new VectorPairAction() { + @Override + public void action(Vector a, Vector b) { + assertTrue(a.isOrthogonalTo(b) == PrecisionUtils.equal( + a.getDotProduct(b), 0)); + } + }); } + + public void test_toPoint() { + forVectors(new VectorAction() { + public void action(Vector a) { + Point p = a.toPoint(); + assertTrue(PrecisionUtils.equal(a.x, p.x)); + assertTrue(PrecisionUtils.equal(a.y, p.y)); + } + }); + } + + public void test_toString() { + Vector a = new Vector(0, 0); + assertEquals("Vector: [0.0,0.0]", a.toString()); + } + }