/*
* $Id$
* This file is a part of the Arakhne Foundation Classes, http://www.arakhne.org/afc
*
* Copyright (c) 2000-2012 Stephane GALLAND.
* Copyright (c) 2005-10, Multiagent Team, Laboratoire Systemes et Transports,
* Universite de Technologie de Belfort-Montbeliard.
* Copyright (c) 2013-2016 The original authors, and other authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.arakhne.afc.math.continous.object2d;
import java.util.NoSuchElementException;
import org.arakhne.afc.math.MathConstants;
import org.arakhne.afc.math.generic.PathWindingRule;
import org.arakhne.afc.math.generic.Point2D;
import org.arakhne.afc.math.generic.Vector2D;
import org.arakhne.afc.math.geometry.d2.afp.Segment2afp;
import org.arakhne.afc.math.geometry.d2.d.Rectangle2d;
import org.arakhne.afc.math.matrix.Transform2D;
import org.arakhne.afc.vmutil.ReflectionUtil;
/** 2D rectangle with floating-point points.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
* @deprecated see {@link Rectangle2d}
*/
@Deprecated
@SuppressWarnings("all")
public class Rectangle2f extends AbstractRectangularShape2f<Rectangle2f> {
private static final long serialVersionUID = 8716296371653330467L;
/** Replies if two rectangles are intersecting.
*
* @param x1 is the first corner of the first rectangle.
* @param y1 is the first corner of the first rectangle.
* @param x2 is the second corner of the first rectangle.
* @param y2 is the second corner of the first rectangle.
* @param x3 is the first corner of the second rectangle.
* @param y3 is the first corner of the second rectangle.
* @param x4 is the second corner of the second rectangle.
* @param y4 is the second corner of the second rectangle.
* @return <code>true</code> if the two shapes are intersecting; otherwise
* <code>false</code>
*/
public static boolean intersectsRectangleRectangle(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
assert(x1<=x2);
assert(y1<=y2);
assert(x3<=x4);
assert(y3<=y4);
return x2 > x3
&&
x1 < x4
&&
y2 > y3
&&
y1 < y4;
}
/** Replies if two rectangles are intersecting.
*
* @param x1 is the first corner of the rectangle.
* @param y1 is the first corner of the rectangle.
* @param x2 is the second corner of the rectangle.
* @param y2 is the second corner of the rectangle.
* @param x3 is the first point of the line.
* @param y3 is the first point of the line.
* @param x4 is the second point of the line.
* @param y4 is the second point of the line.
* @return <code>true</code> if the two shapes are intersecting; otherwise
* <code>false</code>
*/
public static boolean intersectsRectangleLine(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
int a, b;
a = Segment2afp.ccw(x3, y3, x4, y4, x1, y1, 0);
b = Segment2afp.ccw(x3, y3, x4, y4, x2, y1, 0);
if (a!=b && b!=0) return true;
b = Segment2afp.ccw(x3, y3, x4, y4, x2, y2, 0);
if (a!=b && b!=0) return true;
b = Segment2afp.ccw(x3, y3, x4, y4, x1, y2, 0);
return (a!=b && b!=0);
}
private static final int CS_INSIDE = 0; // 0000
private static final int CS_LEFT = 1; // 0001
private static final int CS_RIGHT = 2; // 0010
private static final int CS_BOTTOM = 4; // 0100
private static final int CS_TOP = 8; // 1000
private static int getCohenSutherlandRegion(float x1, float y1, float x2, float y2, float px, float py) {
int region = CS_INSIDE;
if (px<x1) {
region |= CS_LEFT;
}
else if (px>x2) {
region |= CS_RIGHT;
}
if (py<y1) {
region |= CS_BOTTOM;
}
else if (py>y2) {
region |= CS_TOP;
}
return region;
}
/** Replies if two rectangles are intersecting.
*
* @param x1 is the first corner of the rectangle.
* @param y1 is the first corner of the rectangle.
* @param x2 is the second corner of the rectangle.
* @param y2 is the second corner of the rectangle.
* @param x3 is the first point of the segment.
* @param y3 is the first point of the segment.
* @param x4 is the second point of the segment.
* @param y4 is the second point of the segment.
* @return <code>true</code> if the two shapes are intersecting; otherwise
* <code>false</code>
*/
public static boolean intersectsRectangleSegment(float x1, float y1, float x2, float y2, float x3, float y3, float x4, float y4) {
float px1 = x3;
float py1 = y3;
float px2 = x4;
float py2 = y4;
// Cohen–Sutherland algorithm
int r1 = getCohenSutherlandRegion(x1, y1, x2, y2, px1, py1);
int r2 = getCohenSutherlandRegion(x1, y1, x2, y2, px2, py2);
boolean accept = false;
while (true) {
if ((r1 | r2)==0) {
// Bitwise OR is 0. Trivially accept and get out of loop
accept = true;
break;//to speed up the algorithm
}
if ((r1 & r2)!=0) {
// Bitwise AND is not 0. Trivially reject and get out of loop
break;
}
// failed both tests, so calculate the line segment to clip
// from an outside point to an intersection with clip edge
float x, y;
// At least one endpoint is outside the clip rectangle; pick it.
int outcodeOut = r1!=0 ? r1 : r2;
// Now find the intersection point;
// use formulas y = y0 + slope * (x - x0), x = x0 + (1 / slope) * (y - y0)
if ((outcodeOut & CS_TOP)!=0) { // point is above the clip rectangle
x = px1 + (px2 - px1) * (y2 - py1) / (py2 - py1);
y = y2;
}
else if ((outcodeOut & CS_BOTTOM)!=0) { // point is below the clip rectangle
x = px1 + (px2 - px1) * (y1- py1) / (py2 - py1);
y = y1;
}
else if ((outcodeOut & CS_RIGHT)!=0) { // point is to the right of clip rectangle
y = py1 + (py2 - py1) * (x2 - px1) / (px2 - px1);
x = x2;
}
else {
//else if ((outcodeOut & CS_LEFT)!=0) { // point is to the left of clip rectangle
y = py1 + (py2 - py1) * (x1 - px1) / (px2 - px1);
x = x1;
}
//NOTE:*****************************************************************************************
/* if you follow this algorithm exactly(at least for c#), then you will fall into an infinite loop
in case a line crosses more than two segments. to avoid that problem, leave out the last else
if(outcodeOut & LEFT) and just make it else*/
//**********************************************************************************************
// Now we move outside point to intersection point to clip
// and get ready for next pass.
if (outcodeOut == r1) {
px1 = x;
py1 = y;
r1 = getCohenSutherlandRegion(x1, y1, x2, y2, px1, py1);
}
else {
px2 = x;
py2 = y;
r2 = getCohenSutherlandRegion(x1, y1, x2, y2, px2, py2);
}
}
return accept;
}
/** Compute the union of r1 and r2.
*
* @param dest is the union.
* @param r1
* @param r2
*/
public static void union(Rectangle2f dest, Rectangle2f r1, Rectangle2f r2) {
dest.setFromCorners(
Math.min(r1.getMinX(), r2.getMinX()),
Math.min(r1.getMinY(), r2.getMinY()),
Math.max(r1.getMaxX(), r2.getMaxX()),
Math.max(r1.getMaxY(), r2.getMaxY()));
}
/** Replies if a rectangle is inside in the rectangle.
*
* @param rx1 is the lowest corner of the enclosing-candidate rectangle.
* @param ry1 is the lowest corner of the enclosing-candidate rectangle.
* @param rwidth1 is the width of the enclosing-candidate rectangle.
* @param rheight1 is the height of the enclosing-candidate rectangle.
* @param rx2 is the lowest corner of the inner-candidate rectangle.
* @param ry2 is the lowest corner of the inner-candidate rectangle.
* @param rwidth2 is the width of the inner-candidate rectangle.
* @param rheight2 is the height of the inner-candidate rectangle.
* @return <code>true</code> if the given rectangle is inside the ellipse;
* otherwise <code>false</code>.
*/
public static boolean containsRectangleRectangle(float rx1, float ry1, float rwidth1, float rheight1, float rx2, float ry2, float rwidth2, float rheight2) {
if (rwidth1<=0f || rwidth2<=0f || rheight1<=0 || rheight2<=0f) {
return false;
}
return (rx2 >= rx1 &&
ry2 >= ry1 &&
(rx2 + rwidth2) <= rx1 + rwidth1 &&
(ry2 + rheight2) <= ry1 + rheight1);
}
/** Compute the intersection of r1 and r2.
*
* @param dest is the intersection.
* @param r1
* @param r2
*/
public static void intersection(Rectangle2f dest, Rectangle2f r1, Rectangle2f r2) {
float x1 = Math.max(r1.getMinX(), r2.getMinX());
float y1 = Math.max(r1.getMinY(), r2.getMinY());
float x2 = Math.min(r1.getMaxX(), r2.getMaxX());
float y2 = Math.min(r1.getMaxY(), r2.getMaxY());
if (x1<=x2 && y1<=y2) {
dest.setFromCorners(x1, y1, x2, y2);
}
else {
dest.set(0, 0, 0, 0);
}
}
/**
*/
public Rectangle2f() {
//
}
/**
* @param min is the min corner of the rectangle.
* @param max is the max corner of the rectangle.
*/
public Rectangle2f(Point2f min, Point2f max) {
super(min, max);
}
/**
* @param x
* @param y
* @param width
* @param height
*/
public Rectangle2f(float x, float y, float width, float height) {
super(x, y, width, height);
}
/**
* @param r
*/
public Rectangle2f(Rectangle2f r) {
super(r);
}
@Override
public void set(Shape2f s) {
s.toBoundingBox(this);
}
/** {@inheritDoc}
*/
@Override
public Rectangle2f toBoundingBox() {
return this;
}
/** {@inheritDoc}
*/
@Override
public float distanceSquared(Point2D p) {
float dx;
if (p.getX()<getMinX()) {
dx = getMinX() - p.getX();
}
else if (p.getX()>getMaxX()) {
dx = p.getX() - getMaxX();
}
else {
dx = 0f;
}
float dy;
if (p.getY()<getMinY()) {
dy = getMinY() - p.getY();
}
else if (p.getY()>getMaxY()) {
dy = p.getY() - getMaxY();
}
else {
dy = 0f;
}
return dx*dx+dy*dy;
}
/** {@inheritDoc}
*/
@Override
public float distanceL1(Point2D p) {
float dx;
if (p.getX()<getMinX()) {
dx = getMinX() - p.getX();
}
else if (p.getX()>getMaxX()) {
dx = p.getX() - getMaxX();
}
else {
dx = 0f;
}
float dy;
if (p.getY()<getMinY()) {
dy = getMinY() - p.getY();
}
else if (p.getY()>getMaxY()) {
dy = p.getY() - getMaxY();
}
else {
dy = 0f;
}
return dx + dy;
}
/** {@inheritDoc}
*/
@Override
public float distanceLinf(Point2D p) {
float dx;
if (p.getX()<getMinX()) {
dx = getMinX() - p.getX();
}
else if (p.getX()>getMaxX()) {
dx = p.getX() - getMaxX();
}
else {
dx = 0f;
}
float dy;
if (p.getY()<getMinY()) {
dy = getMinY() - p.getY();
}
else if (p.getY()>getMaxY()) {
dy = p.getY() - getMaxY();
}
else {
dy = 0f;
}
return Math.max(dx, dy);
}
/** {@inheritDoc}
*/
@Override
public boolean contains(float x, float y) {
return (x>=getMinX() && x<=getMaxX())
&&
(y>=getMinY() && y<=getMaxY());
}
@Override
public boolean contains(Rectangle2f r) {
return containsRectangleRectangle(
getMinX(), getMinY(), getWidth(), getHeight(),
r.getMinX(), r.getMinY(), r.getWidth(), r.getHeight());
}
/** {@inheritDoc}
*/
@Override
public Point2D getClosestPointTo(Point2D p) {
float x;
int same = 0;
if (p.getX()<getMinX()) {
x = getMinX();
}
else if (p.getX()>getMaxX()) {
x = getMaxX();
}
else {
x = p.getX();
++same;
}
float y;
if (p.getY()<getMinY()) {
y = getMinY();
}
else if (p.getY()>getMaxY()) {
y = getMaxY();
}
else {
y = p.getY();
++same;
}
if (same==2) return p;
return new Point2f(x,y);
}
/** Add the given coordinate in the rectangle.
* <p>
* The corners of the rectangles are moved to
* enclosed the given coordinate.
*
* @param p
*/
public void add(Point2D p) {
add(p.getX(), p.getY());
}
/** Add the given coordinate in the rectangle.
* <p>
* The corners of the rectangles are moved to
* enclosed the given coordinate.
*
* @param x
* @param y
*/
public void add(float x, float y) {
if (x<getMinX()) {
setMinX(x);
}
else if (x>getMaxX()) {
setMaxX(x);
}
if (y<getMinY()) {
setMinY(y);
}
else if (y>getMaxY()) {
setMaxY(y);
}
}
/** Compute and replies the union of this rectangle and the given rectangle.
* This function does not change this rectangle.
* <p>
* It is equivalent to (where <code>ur</code> is the union):
* <pre><code>
* Rectangle2f ur = new Rectangle2f();
* Rectangle2f.union(ur, this, r);
* </code></pre>
*
* @param r
* @return the union of this rectangle and the given rectangle.
* @see #union(Rectangle2f, Rectangle2f, Rectangle2f)
* @see #setUnion(Rectangle2f)
*/
public Rectangle2f createUnion(Rectangle2f r) {
Rectangle2f rr = new Rectangle2f();
union(rr, this, r);
return rr;
}
/** Compute and replies the intersection of this rectangle and the given rectangle.
* This function does not change this rectangle.
* <p>
* It is equivalent to (where <code>ir</code> is the intersection):
* <pre><code>
* Rectangle2f ir = new Rectangle2f();
* Rectangle2f.intersection(ir, this, r);
* </code></pre>
*
* @param r
* @return the union of this rectangle and the given rectangle.
* @see #intersection(Rectangle2f, Rectangle2f, Rectangle2f)
* @see #setIntersection(Rectangle2f)
*/
public Rectangle2f createIntersection(Rectangle2f r) {
Rectangle2f rr = new Rectangle2f();
intersection(rr, this, r);
return rr;
}
/** Compute the union of this rectangle and the given rectangle and
* change this rectangle with the result of the union.
* <p>
* It is equivalent to:
* <pre><code>
* Rectangle2f.union(this, this, r);
* </code></pre>
*
* @param r
* @see #union(Rectangle2f, Rectangle2f, Rectangle2f)
* @see #createUnion(Rectangle2f)
*/
public void setUnion(Rectangle2f r) {
union(this, this, r);
}
/** Compute the intersection of this rectangle and the given rectangle.
* This function changes this rectangle.
* <p>
* It is equivalent to:
* <pre><code>
* Rectangle2f.intersection(this, this, r);
* </code></pre>
*
* @param r
* @see #intersection(Rectangle2f, Rectangle2f, Rectangle2f)
* @see #createIntersection(Rectangle2f)
*/
public void setIntersection(Rectangle2f r) {
intersection(this, this, r);
}
@Override
public PathIterator2f getPathIterator(Transform2D transform) {
if (transform==null) {
return new CopyPathIterator(
getMinX(), getMinY(),
getMaxX(), getMaxY());
}
return new TransformPathIterator(
getMinX(), getMinY(),
getMaxX(), getMaxY(),
transform);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj instanceof Rectangle2f) {
Rectangle2f rr2d = (Rectangle2f) obj;
return ((getMinX() == rr2d.getMinX()) &&
(getMinY() == rr2d.getMinY()) &&
(getWidth() == rr2d.getWidth()) &&
(getHeight() == rr2d.getHeight()));
}
return false;
}
@Override
public int hashCode() {
long bits = 1L;
bits = 31L * bits + floatToIntBits(getMinX());
bits = 31L * bits + floatToIntBits(getMinY());
bits = 31L * bits + floatToIntBits(getMaxX());
bits = 31L * bits + floatToIntBits(getMaxY());
return (int) (bits ^ (bits >> 32));
}
@Override
public boolean intersects(Rectangle2f s) {
return intersectsRectangleRectangle(
getMinX(), getMinY(),
getMaxX(), getMaxY(),
s.getMinX(), s.getMinY(),
s.getMaxX(), s.getMaxY());
}
@Override
public boolean intersects(Ellipse2f s) {
return Ellipse2f.intersectsEllipseRectangle(
s.getMinX(), s.getMinY(),
s.getMaxX(), s.getMaxY(),
getMinX(), getMinY(),
getMaxX(), getMaxY());
}
@Override
public boolean intersects(Circle2f s) {
return Circle2f.intersectsCircleRectangle(
s.getX(), s.getY(),
s.getRadius(),
getMinX(), getMinY(),
getMaxX(), getMaxY());
}
@Override
public boolean intersects(Segment2f s) {
return intersectsRectangleSegment(
getMinX(), getMinY(),
getMaxX(), getMaxY(),
s.getX1(), s.getY1(),
s.getX2(), s.getY2());
}
@Override
public boolean intersects(Path2f s) {
return intersects(s.getPathIterator((float) MathConstants.SPLINE_APPROXIMATION_RATIO));
}
@Override
public boolean intersects(PathIterator2f s) {
// Copied from AWT API
if (isEmpty()) return false;
int mask = (s.getWindingRule() == PathWindingRule.NON_ZERO ? -1 : 2);
int crossings = Path2f.computeCrossingsFromRect(
s,
getMinX(), getMinY(), getMaxX(), getMaxY(),
false, true);
return (crossings == MathConstants.SHAPE_INTERSECTS ||
(crossings & mask) != 0);
}
@Override
public String toString() {
return ReflectionUtil.toString(this);
}
/** Move this rectangle to avoid collision
* with the reference rectangle.
*
* @param reference is the rectangle to avoid collision with.
* @return the displacement vector.
*/
public Vector2D avoidCollisionWith(Rectangle2f reference) {
float dx1 = reference.getMaxX() - getMinX();
float dx2 = getMaxX() - reference.getMinX();
float dy1 = reference.getMaxY() - getMinY();
float dy2 = getMaxY() - reference.getMinY();
float absdx1 = Math.abs(dx1);
float absdx2 = Math.abs(dx2);
float absdy1 = Math.abs(dy1);
float absdy2 = Math.abs(dy2);
float dx = 0;
float dy = 0;
if (dx1>=0 && absdx1<=absdx2 && absdx1<=absdy1 && absdx1<=absdy2) {
// Move according to dx1
dx = dx1;
}
else if (dx2>=0 && absdx2<=absdx1 && absdx2<=absdy1 && absdx2<=absdy2) {
// Move according to dx2
dx = - dx2;
}
else if (dy1>=0 && absdy1<=absdx1 && absdy1<=absdx2 && absdy1<=absdy2) {
// Move according to dy1
dy = dy1;
}
else {
// Move according to dy2
dy = - dy2;
}
set(
getMinX()+dx,
getMinY()+dy,
getWidth(),
getHeight());
return new Vector2f(dx, dy);
}
/** Move this rectangle to avoid collision
* with the reference rectangle.
*
* @param reference is the rectangle to avoid collision with.
* @param displacementDirection is the direction of the allowed displacement.
* @return the displacement vector.
*/
public Vector2D avoidCollisionWith(Rectangle2f reference, Vector2D displacementDirection) {
if (displacementDirection==null || displacementDirection.lengthSquared()==0f)
return avoidCollisionWith(reference);
float dx1 = reference.getMaxX() - getMinX();
float dx2 = reference.getMinX() - getMaxX();
float dy1 = reference.getMaxY() - getMinY();
float dy2 = reference.getMinY() - getMaxY();
float absdx1 = Math.abs(dx1);
float absdx2 = Math.abs(dx2);
float absdy1 = Math.abs(dy1);
float absdy2 = Math.abs(dy2);
float dx, dy;
if (displacementDirection.getX()<0) {
dx = -Math.min(absdx1, absdx2);
}
else {
dx = Math.min(absdx1, absdx2);
}
if (displacementDirection.getY()<0) {
dy = -Math.min(absdy1, absdy2);
}
else {
dy = Math.min(absdy1, absdy2);
}
set(
getMinX()+dx,
getMinY()+dy,
getWidth(),
getHeight());
displacementDirection.set(dx, dy);
return displacementDirection;
}
/** Iterator on the path elements of the rectangle.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private static class CopyPathIterator implements PathIterator2f {
private final float x1;
private final float y1;
private final float x2;
private final float y2;
private int index = 0;
/**
* @param x1
* @param y1
* @param x2
* @param y2
*/
public CopyPathIterator(float x1, float y1, float x2, float y2) {
this.x1 = Math.min(x1, x2);
this.y1 = Math.min(y1, y2);
this.x2 = Math.max(x1, x2);
this.y2 = Math.max(y1, y2);
if (Math.abs(this.x1-this.x2)<=0f || Math.abs(this.y1-this.y2)<=0f) {
this.index = 6;
}
}
@Override
public boolean hasNext() {
return this.index<=5;
}
@Override
public PathElement2f next() {
int idx = this.index;
++this.index;
switch(idx) {
case 0:
return new PathElement2f.MovePathElement2f(
this.x1, this.y1);
case 1:
return new PathElement2f.LinePathElement2f(
this.x1, this.y1,
this.x2, this.y1);
case 2:
return new PathElement2f.LinePathElement2f(
this.x2, this.y1,
this.x2, this.y2);
case 3:
return new PathElement2f.LinePathElement2f(
this.x2, this.y2,
this.x1, this.y2);
case 4:
return new PathElement2f.LinePathElement2f(
this.x1, this.y2,
this.x1, this.y1);
case 5:
return new PathElement2f.ClosePathElement2f(
this.x1, this.y1,
this.x1, this.y1);
default:
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public PathWindingRule getWindingRule() {
return PathWindingRule.NON_ZERO;
}
@Override
public boolean isPolyline() {
return true;
}
}
/** Iterator on the path elements of the rectangle.
*
* @author $Author: sgalland$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
private static class TransformPathIterator implements PathIterator2f {
private final Transform2D transform;
private final float x1;
private final float y1;
private final float x2;
private final float y2;
private int index = 0;
private final Point2D p1 = new Point2f();
private final Point2D p2 = new Point2f();
/**
* @param x1
* @param y1
* @param x2
* @param y2
* @param transform
*/
public TransformPathIterator(float x1, float y1, float x2, float y2, Transform2D transform) {
this.transform = transform;
this.x1 = Math.min(x1, x2);
this.y1 = Math.min(y1, y2);
this.x2 = Math.max(x1, x2);
this.y2 = Math.max(y1, y2);
if (Math.abs(this.x1-this.x2)<=0f || Math.abs(this.y1-this.y2)<=0f) {
this.index = 6;
}
}
@Override
public boolean hasNext() {
return this.index<=5;
}
@Override
public PathElement2f next() {
int idx = this.index;
++this.index;
switch(idx) {
case 0:
this.p2.set(this.x1, this.y1);
if (this.transform!=null) {
this.transform.transform(this.p2);
}
return new PathElement2f.MovePathElement2f(
this.p2.getX(), this.p2.getY());
case 1:
this.p1.set(this.p2);
this.p2.set(this.x2, this.y1);
if (this.transform!=null) {
this.transform.transform(this.p2);
}
return new PathElement2f.LinePathElement2f(
this.p1.getX(), this.p1.getY(),
this.p2.getX(), this.p2.getY());
case 2:
this.p1.set(this.p2);
this.p2.set(this.x2, this.y2);
if (this.transform!=null) {
this.transform.transform(this.p2);
}
return new PathElement2f.LinePathElement2f(
this.p1.getX(), this.p1.getY(),
this.p2.getX(), this.p2.getY());
case 3:
this.p1.set(this.p2);
this.p2.set(this.x1, this.y2);
if (this.transform!=null) {
this.transform.transform(this.p2);
}
return new PathElement2f.LinePathElement2f(
this.p1.getX(), this.p1.getY(),
this.p2.getX(), this.p2.getY());
case 4:
this.p1.set(this.p2);
this.p2.set(this.x1, this.y1);
if (this.transform!=null) {
this.transform.transform(this.p2);
}
return new PathElement2f.LinePathElement2f(
this.p1.getX(), this.p1.getY(),
this.p2.getX(), this.p2.getY());
case 5:
return new PathElement2f.ClosePathElement2f(
this.p2.getX(), this.p2.getY(),
this.p2.getX(), this.p2.getY());
default:
throw new NoSuchElementException();
}
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
@Override
public PathWindingRule getWindingRule() {
return PathWindingRule.NON_ZERO;
}
@Override
public boolean isPolyline() {
return true;
}
}
}