diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/OrientedPoint2D.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/OrientedPoint2D.java new file mode 100644 index 000000000..9e663cb1c --- /dev/null +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/OrientedPoint2D.java @@ -0,0 +1,556 @@ +/* + * $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.geometry.d2; + +import org.eclipse.xtext.xbase.lib.Pure; + +import org.arakhne.afc.math.geometry.coordinatesystem.CoordinateSystem2D; +import org.arakhne.afc.vmutil.asserts.AssertMessages; + +/** A point 2D with two orientation vectors relative to the polyline: the direction and the normal to the point. + * + *

The orientation vectors have no physical existence, i.e. they exist only to represent the direction of the + * point and its normal when the point is part of a polyline. The normal vector is always perpendicular to the + * direction vector. The point stores its length on the polyline to avoid rounding errors at discretization. + * + * @param is the type of the general implementation. + * @param is the type of the implementation of this shape. + * @param is the type of the path elements. + * @param

is the type of the points. + * @param is the type of the vectors. + * @param is the type of the bounding boxes. + * @author $Author: tpiotrow$ + * @author $Author: sgalland$ + * @author $Author: olamotte$ + * @version $FullVersion$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ + */ +public interface OrientedPoint2D< + ST extends Shape2D, + IT extends OrientedPoint2D, + I extends PathIterator2D, + P extends Point2D, + V extends Vector2D, + B extends Shape2D> + extends Shape2D { + + /** Replies the X coordinate of the point. + * + * @return the x coordinate of the point. + */ + @Pure double getX(); + + /** Replies the X coordinate of the point. + * + * @return the x coordinate of the point. + */ + @Pure int ix(); + + /** Sets a new value in the X of the point. + * + * @param x the new value double x. + */ + void setX(int x); + + /** Sets a new value in the X of the point. + * + * @param x the new value double x. + */ + void setX(double x); + + /** Replies the Y coordinate of the point. + * + * @return the y coordinate of the point. + */ + @Pure double getY(); + + /** Replies the Y coordinate of the point. + * + * @return the y coordinate of the point. + */ + @Pure int iy(); + + /** Sets a new value in the Y of the point. + * @param y the new value double y. + */ + void setY(int y); + + /** Sets a new value in the Y of the point. + * @param y the new value double y. + */ + void setY(double y); + + /** Replies the X coordinate of the direction vector. + * If this point is not part of a polyline, the direction vector is null. + * + * @return the x coordinate of the direction vector. + */ + @Pure double getDirectionX(); + + /** Replies the X coordinate of the direction vector. + * If this point is not part of a polyline, the direction vector is null. + * + * @return the x coordinate of the direction vector. + */ + @Pure int idx(); + + /** Sets a new value in the X direction of the point. + * + * @param x the new value double x. + */ + void setDirectionX(int x); + + /** Sets a new value in the X direction of the point. + * + * @param x the new value double x. + */ + void setDirectionX(double x); + + /** Replies the Y coordinate of the direction vector. + * If this point is not part of a polyline, the direction vector is null. + * + * @return the y coordinate of the direction vector. + */ + @Pure double getDirectionY(); + + /** Replies the Y coordinate of the direction vector. + * If this point is not part of a polyline, the direction vector is null. + * + * @return the y coordinate of the direction vector. + */ + @Pure int idy(); + + /** Sets a new value in the Y direction of the point. + * + * @param y the new value double y. + */ + void setDirectionY(int y); + + /** Sets a new value in the Y direction of the point. + * + * @param y the new value double y. + */ + void setDirectionY(double y); + + /** Replies the X coordinate of the normal vector. + * If this point is not part of a polyline, the normal vector is null. + * + * @return the x coordinate of the normal vector. + */ + @Pure default double getNormalX() { + return -getDirectionY(); + } + + /** Replies the X coordinate of the normal vector. + * If this point is not part of a polyline, the normal vector is null. + * + * @return the x coordinate of the normal vector. + */ + @Pure default int inx() { + return -idy(); + } + + /** Replies the Y coordinate of the normal vector. + * If this point is not part of a polyline, the normal vector is null. + * + * @return the y coordinate of the normal vector. + */ + @Pure default double getNormalY() { + return getDirectionX(); + } + + /** Replies the Y coordinate of the normal vector. + * If this point is not part of a polyline, the normal vector is null. + * + * @return the y coordinate of the normal vector. + */ + @Pure default int iny() { + return idx(); + } + + /** Replies the geometrical length of this point on + * the polyline. + * + * @return the length of the point on the polyline + */ + @Pure double getLength(); + + /** Replies the geometrical length of this point on + * the polyline. + * + * @return the length of the point on the polyline + */ + @Pure int ilen(); + + /** Sets a new value for the length of the point. + * + * @param length the length of the point on the polyline. + */ + void setLength(int length); + + /** Sets a new value for the length of the point. + * + * @param length the length of the point on the polyline. + */ + void setLength(double length); + + @Override + default boolean contains(Point2D pt) { + return getX() == pt.getX() && getY() == pt.getY(); + } + + @Override + default boolean equalsToShape(IT shape) { + if (shape == null) { + return false; + } + if (shape == this) { + return true; + } + // We don't need to check normal vector because it depends of direction + return getX() == shape.getX() && getY() == shape.getY() + && getDirectionX() == shape.getDirectionX() + && getDirectionY() == shape.getDirectionY(); + } + + /** Replies this point. + * @return this point + */ + default P getPoint() { + return getGeomFactory().newPoint(getX(), getY()); + } + + @Override + default double getDistanceL1(Point2D pt) { + assert pt != null : AssertMessages.notNullParameter(); + return Point2D.getDistanceL1PointPoint(getX(), getY(), pt.getX(), pt.getY()); + } + + @Override + default double getDistanceLinf(Point2D pt) { + assert pt != null : AssertMessages.notNullParameter(); + return Point2D.getDistanceLinfPointPoint(getX(), getY(), pt.getX(), pt.getY()); + } + + @Override + default double getDistanceSquared(Point2D pt) { + assert pt != null : AssertMessages.notNullParameter(); + return Point2D.getDistanceSquaredPointPoint(getX(), getY(), pt.getX(), pt.getY()); + } + + @Override + default double getDistance(Point2D pt) { + assert pt != null : AssertMessages.notNullParameter(); + return Point2D.getDistancePointPoint(getX(), getY(), pt.getX(), pt.getY()); + } + + @Override + default P getClosestPointTo(Point2D point) { + return getPoint(); + } + + @Override + default P getFarthestPointTo(Point2D point) { + return getPoint(); + } + + @Override + default boolean isEmpty() { + return false; + } + + /** Change the point. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + */ + // No default implementation to ensure atomic change + void set(int x, int y); + + /** Change the point. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + */ + // No default implementation to ensure atomic change + void set(int x, int y, int length); + + /** Change the point and its orientation vector. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + // No default implementation to ensure atomic change + void set(int x, int y, int dirX, int dirY); + + /** Change the point and its orientation vector. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + // No default implementation to ensure atomic change + void set(int x, int y, int length, int dirX, int dirY); + + /** Change the point. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + */ + // No default implementation to ensure atomic change + void set(double x, double y); + + /** Change the point. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + */ + // No default implementation to ensure atomic change + void set(double x, double y, double length); + + /** Change the point and its orientation vector. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + // No default implementation to ensure atomic change + void set(double x, double y, double dirX, double dirY); + + /** Change the point and its orientation vector. + * + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + // No default implementation to ensure atomic change + void set(double x, double y, double length, double dirX, double dirY); + + @Override + default void set(IT shape) { + assert shape != null : AssertMessages.notNullParameter(); + set(shape.getX(), shape.getY(), shape.getDirectionX(), shape.getDirectionY()); + } + + @Override + default void clear() { + set(0, 0, 0, 0, 0); + } + + /** Turn this point about the given rotation angle around the origin point. + * + *

The rotation is done according to the trigonometric coordinate. + * A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @see #turn(double, OrientedPoint2D, OrientedPoint2D) + * @see #turnLeft(double) + * @see #turnRight(double) + */ + default void turn(double angle) { + turn(angle, this); + } + + /** Turn the given point about the given rotation angle around the origin point, and set this + * point with the result. + * + *

The rotation is done according to the trigonometric coordinate. + * A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the point to turn. + * @see #turn(double, OrientedPoint2D, OrientedPoint2D) + * @see #turn(double) + * @see #turnLeft(double) + * @see #turnRight(double) + */ + default void turn(double angle, OrientedPoint2D pointToTurn) { + assert pointToTurn != null : AssertMessages.notNullParameter(1); + final double sin = Math.sin(angle); + final double cos = Math.cos(angle); + final double x = cos * pointToTurn.getX() - sin * pointToTurn.getY(); + final double y = sin * pointToTurn.getX() + cos * pointToTurn.getY(); + set(x, y); + } + + /** Turn the given point about the given rotation angle around the origin point, and set this + * point with the result. + * + *

The rotation is done according to the trigonometric coordinate. + * A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the point to turn. + * @param origin the origin point. + * @see #turn(double, OrientedPoint2D) + * @see #turn(double) + * @see #turnLeft(double) + * @see #turnRight(double) + */ + default void turn(double angle, OrientedPoint2D pointToTurn, OrientedPoint2D origin) { + assert pointToTurn != null : AssertMessages.notNullParameter(1); + assert origin != null : AssertMessages.notNullParameter(2); + final double sin = Math.sin(angle); + final double cos = Math.cos(angle); + final double vx = pointToTurn.getX() - origin.getX(); + final double vy = pointToTurn.getY() - origin.getY(); + final double x = cos * vx - sin * vy; + final double y = sin * vx + cos * vy; + set(x + origin.getX(), y + origin.getY()); + } + + /** Turn this vector on the left around the origin when the given rotation angle is positive. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @see CoordinateSystem2D + * @see #turnLeft(double, OrientedPoint2D, OrientedPoint2D) + * @see #turn(double) + * @see #turnRight(double) + */ + default void turnLeft(double angle) { + turnLeft(angle, this); + } + + /** Turn the given vector on the left, and set this + * vector with the result. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the vector to turn. + * @see CoordinateSystem2D + * @see #turnLeft(double, OrientedPoint2D, OrientedPoint2D) + * @see #turn(double) + * @see #turnRight(double) + */ + default void turnLeft(double angle, OrientedPoint2D pointToTurn) { + assert pointToTurn != null : AssertMessages.notNullParameter(1); + final double sin = Math.sin(angle); + final double cos = Math.cos(angle); + final double x; + final double y; + if (CoordinateSystem2D.getDefaultCoordinateSystem().isRightHanded()) { + x = cos * pointToTurn.getX() - sin * pointToTurn.getY(); + y = sin * pointToTurn.getX() + cos * pointToTurn.getY(); + } else { + x = cos * pointToTurn.getX() + sin * pointToTurn.getY(); + y = -sin * pointToTurn.getX() + cos * pointToTurn.getY(); + } + set(x, y); + } + + /** Turn the given vector on the left, and set this + * vector with the result. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the vector to turn. + * @param origin the origin point. + * @see CoordinateSystem2D + * @see #turnLeft(double, OrientedPoint2D) + * @see #turn(double) + * @see #turnRight(double) + */ + default void turnLeft(double angle, OrientedPoint2D pointToTurn, OrientedPoint2D origin) { + assert pointToTurn != null : AssertMessages.notNullParameter(1); + assert origin != null : AssertMessages.notNullParameter(2); + final double sin = Math.sin(angle); + final double cos = Math.cos(angle); + final double vx = pointToTurn.getX() - origin.getX(); + final double vy = pointToTurn.getY() - origin.getY(); + final double x; + final double y; + if (CoordinateSystem2D.getDefaultCoordinateSystem().isRightHanded()) { + x = cos * vx - sin * vy; + y = sin * vx + cos * vy; + } else { + x = cos * vx + sin * vy; + y = -sin * vx + cos * vy; + } + set(x + origin.getX(), y + origin.getY()); + } + + /** Turn this vector on the right around the origin when the given rotation angle is positive. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @see CoordinateSystem2D + * @see #turn(double) + * @see #turnLeft(double) + */ + default void turnRight(double angle) { + turnLeft(-angle, this); + } + + /** Turn this vector on the right around the origin when the given rotation angle is positive. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the vector to turn. + * @see CoordinateSystem2D + * @see #turn(double) + * @see #turnLeft(double) + */ + default void turnRight(double angle, OrientedPoint2D pointToTurn) { + turnLeft(-angle, pointToTurn); + } + + /** Turn this vector on the right around the origin when the given rotation angle is positive. + * + *

A positive rotation angle corresponds to a left or right rotation + * according to the current {@link CoordinateSystem2D}. + * + * @param angle is the rotation angle in radians. + * @param pointToTurn the vector to turn. + * @param origin the origin point. + * @see CoordinateSystem2D + * @see #turn(double) + * @see #turnLeft(double) + */ + default void turnRight(double angle, OrientedPoint2D pointToTurn, + OrientedPoint2D origin) { + turnLeft(-angle, pointToTurn, origin); + } + +} diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/GeomFactory2afp.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/GeomFactory2afp.java index 4f70247a4..3621ee3e3 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/GeomFactory2afp.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/GeomFactory2afp.java @@ -176,6 +176,15 @@ E newArcPathElement(double startX, double startY, double targetX, double targetY */ OrientedPoint2afp newOrientedPoint(double x, double y); + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @param length the length of the point on the polyline. + * @return the new oriented point + */ + OrientedPoint2afp newOrientedPoint(double x, double y, double length); + /** Create an oriented point. * * @param x the x coordinate of the point. @@ -186,6 +195,17 @@ E newArcPathElement(double startX, double startY, double targetX, double targetY */ OrientedPoint2afp newOrientedPoint(double x, double y, double dirX, double dirY); + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX the x coordinate of the direction vector. + * @param dirY the y coordinate of the direction vector. + * @return the new oriented point + */ + OrientedPoint2afp newOrientedPoint(double x, double y, double length, double dirX, double dirY); + /** Replies the {@link PathIterator2afp} that is corresponding to the given element. * *

If the given element is already a {@link PathIterator2afp}, returns {@code this}. diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/OrientedPoint2afp.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/OrientedPoint2afp.java index a50720134..dac090b0d 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/OrientedPoint2afp.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/afp/OrientedPoint2afp.java @@ -20,23 +20,18 @@ package org.arakhne.afc.math.geometry.d2.afp; -import org.eclipse.xtext.xbase.lib.Pure; - import org.arakhne.afc.math.MathConstants; import org.arakhne.afc.math.MathUtil; import org.arakhne.afc.math.geometry.CrossingComputationType; import org.arakhne.afc.math.geometry.PathWindingRule; +import org.arakhne.afc.math.geometry.d2.OrientedPoint2D; import org.arakhne.afc.math.geometry.d2.Point2D; import org.arakhne.afc.math.geometry.d2.Shape2D; import org.arakhne.afc.math.geometry.d2.Transform2D; import org.arakhne.afc.math.geometry.d2.Vector2D; import org.arakhne.afc.vmutil.asserts.AssertMessages; -/** A point 2D with two orientation vectors relative to the polyline: the direction and the normal to the point. - * - *

The orientation vectors have no physical existence, i.e. they exist only to represent the direction of the - * point and its normal when the point is part of a polyline. The normal vector is always perpendicular to the - * direction vector.. +/** Fonctional interface representing a 2D oriented point on a plane. * * @param is the type of the general implementation. * @param is the type of the implementation of this shape. @@ -45,19 +40,20 @@ * @param is the type of the vectors. * @param is the type of the bounding boxes. * @author $Author: tpiotrow$ + * @author $Author: sgalland$ + * @author $Author: olamotte$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ -@SuppressWarnings("unused") -// TODO : add geometrical length public interface OrientedPoint2afp< ST extends Shape2afp, IT extends OrientedPoint2afp, IE extends PathElement2afp, P extends Point2D, V extends Vector2D, - B extends Rectangle2afp> extends Shape2afp { + B extends Rectangle2afp> + extends Shape2afp, OrientedPoint2D, P, V, B> { /** Iterator on the elements of the oriented points. * It replies : the point and the extremities of the @@ -69,6 +65,8 @@ public interface OrientedPoint2afp< * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ + // TODO : complete point iterator. The iterator may return only the point or the point and its + // orientation vectors. As such, it may or may not contain multiple moveto elements. class OrientedPointPathIterator implements PathIterator2afp { private int index; @@ -152,72 +150,6 @@ default PathIterator2afp getPathIterator(Transform2D transform) { return new OrientedPointPathIterator<>(this, transform); } - /** Replies the X coordinate of the point. - * - * @return the x coordinate of the point. - */ - @Pure double getX(); - - /** Replies the Y coordinate of the point. - * - * @return the y coordinate of the point. - */ - @Pure double getY(); - - /** Sets a new value in the X of the point. - * - * @param x the new value double x. - */ - void setX(double x); - - /** Sets a new value in the Y of the point. - * @param y the new value double y. - */ - void setY(double y); - - /** Replies the X coordinate of the direction vector. - * If this point is not part of a polyline, the direction vector is null. - * - * @return the x coordinate of the direction vector. - */ - @Pure double getDirectionX(); - - /** Replies the Y coordinate of the direction vector. - * If this point is not part of a polyline, the direction vector is null. - * - * @return the y coordinate of the direction vector. - */ - @Pure double getDirectionY(); - - /** Sets a new value in the X direction of the point. - * - * @param x the new value double x. - */ - void setDirectionX(double x); - - /** Sets a new value in the Y direction of the point. - * @param y the new value double y. - */ - void setDirectionY(double y); - - /** Replies the X coordinate of the normal vector. - * If this point is not part of a polyline, the normal vector is null. - * - * @return the x coordinate of the normal vector. - */ - @Pure default double getNormalX() { - return -getDirectionY(); - } - - /** Replies the Y coordinate of the normal vector. - * If this point is not part of a polyline, the normal vector is null. - * - * @return the y coordinate of the normal vector. - */ - @Pure default double getNormalY() { - return getDirectionX(); - } - @Override default boolean contains(double x, double y) { return x == getX() && y == getY(); @@ -240,27 +172,6 @@ default boolean contains(Point2D pt) { return getX() == pt.getX() && getY() == pt.getY(); } - @Override - default boolean equalsToShape(IT shape) { - if (shape == null) { - return false; - } - if (shape == this) { - return true; - } - // We don't need to check normal because it depends of direction - return getX() == shape.getX() && getY() == shape.getY() - && getDirectionX() == shape.getDirectionX() - && getDirectionY() == shape.getDirectionY(); - } - - /** Replies this point. - * @return this point - */ - default P getPoint() { - return getGeomFactory().newPoint(getX(), getY()); - } - @Override default P getClosestPointTo(Circle2afp circle) { return getPoint(); @@ -286,11 +197,6 @@ default P getClosestPointTo(Path2afp path) { return getPoint(); } - @Override - default P getClosestPointTo(Point2D point) { - return getPoint(); - } - @Override default P getClosestPointTo(Rectangle2afp rectangle) { return getPoint(); @@ -312,36 +218,12 @@ default P getClosestPointTo(Triangle2afp triangle) { } @Override - default P getClosestPointTo(Shape2D shape) { + default P getClosestPointTo(MultiShape2afp multishape) { return getPoint(); } @Override - default double getDistanceL1(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceL1PointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistanceLinf(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceLinfPointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistanceSquared(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceSquaredPointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistance(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistancePointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default P getFarthestPointTo(Point2D point) { + default P getClosestPointTo(Shape2D shape) { return getPoint(); } @@ -412,35 +294,6 @@ default boolean intersects(Triangle2afp triangle) { return triangle.contains(getX(), getY()); } - @Override - default boolean isEmpty() { - return false; - } - - /** Change the point. - * - * @param x x coordinate of the point. - * @param y y coordinate of the point. - */ - // No default implementation to ensure atomic change - void set(double x, double y); - - /** Change the point and its orientation vector. - * - * @param x x coordinate of the point. - * @param y y coordinate of the point. - * @param dirX x coordinate of the vector. - * @param dirY y coordinate of the vector. - */ - // No default implementation to ensure atomic change - void set(double x, double y, double dirX, double dirY); - - @Override - default void set(IT shape) { - assert shape != null : AssertMessages.notNullParameter(); - set(shape.getX(), shape.getY(), shape.getDirectionX(), shape.getDirectionY()); - } - @Override default void toBoundingBox(B box) { assert box != null : AssertMessages.notNullParameter(); @@ -473,8 +326,4 @@ default void translate(double dx, double dy) { set(getX() + dx, getY() + dy, getDirectionX() + dx, getDirectionY() + dy); } - @Override - default void clear() { - set(0, 0, 0, 0); - } } diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/GeomFactory2ai.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/GeomFactory2ai.java index 9ca532685..31d1d7966 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/GeomFactory2ai.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/GeomFactory2ai.java @@ -155,6 +155,44 @@ E newArcPathElement(int startX, int startY, int targetX, int targetY, int radiusX, int radiusY, double xAxisRotation, boolean largeArcFlag, boolean sweepFlag); + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @return the new oriented point + */ + OrientedPoint2ai newOrientedPoint(int x, int y); + + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @param length the length of the point on the polyline. + * @return the new oriented point + */ + OrientedPoint2ai newOrientedPoint(int x, int y, int length); + + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @param dirX the x coordinate of the direction vector. + * @param dirY the y coordinate of the direction vector. + * @return the new oriented point + */ + OrientedPoint2ai newOrientedPoint(int x, int y, int dirX, int dirY); + + /** Create an oriented point. + * + * @param x the x coordinate of the point. + * @param y the y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX the x coordinate of the direction vector. + * @param dirY the y coordinate of the direction vector. + * @return the new oriented point + */ + OrientedPoint2ai newOrientedPoint(int x, int y, int length, int dirX, int dirY); + /** Replies the {@link PathIterator2ai} that is corresponding to the given element. * *

If the given element is already a {@link PathIterator2ai}, returns {@code this}. diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPointShape2ai.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPoint2ai.java similarity index 52% rename from core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPointShape2ai.java rename to core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPoint2ai.java index 88ab60ecd..31f0c1a59 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPointShape2ai.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/ai/OrientedPoint2ai.java @@ -20,12 +20,14 @@ package org.arakhne.afc.math.geometry.d2.ai; -import org.eclipse.xtext.xbase.lib.Pure; +import java.util.Iterator; +import java.util.NoSuchElementException; import org.arakhne.afc.math.MathConstants; import org.arakhne.afc.math.MathUtil; import org.arakhne.afc.math.geometry.CrossingComputationType; import org.arakhne.afc.math.geometry.PathWindingRule; +import org.arakhne.afc.math.geometry.d2.OrientedPoint2D; import org.arakhne.afc.math.geometry.d2.Point2D; import org.arakhne.afc.math.geometry.d2.Shape2D; import org.arakhne.afc.math.geometry.d2.Transform2D; @@ -50,78 +52,157 @@ * @mavenartifactid $ArtifactId$ */ @SuppressWarnings("unused") -public interface OrientedPointShape2ai< +public interface OrientedPoint2ai< ST extends Shape2ai, - IT extends OrientedPointShape2ai, + IT extends OrientedPoint2ai, IE extends PathElement2ai, P extends Point2D, V extends Vector2D, - B extends Rectangle2ai> extends Shape2ai { - - /** Replies the X coordinate of the point. + B extends Rectangle2ai> + extends Shape2ai, OrientedPoint2D, P, V, B> { + /** Iterator on the elements of the oriented points. + * It replies : the point and the extremities of the + * two orientation vectors. * - * @return the x coordinate of the point. + * @param the type of the path elements. + * @author $Author: tpiotrow$ + * @version $FullVersion$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ */ - @Pure int getX(); + // TODO : complete point iterator. The iterator may return only the point or the point and its + // orientation vectors. As such, it may or may not contain multiple moveto elements. + class OrientedPointPathIterator implements PathIterator2ai { - /** Replies the Y coordinate of the point. - * - * @return the y coordinate of the point. - */ - @Pure int getY(); + private int index; - /** Sets a new value in the X of the point. - * - * @param x the new value double x. - */ - void setX(int x); + private OrientedPoint2ai point; - /** Sets a new value in the Y of the point. - * @param y the new value double y. - */ - void setY(int y); + private Transform2D transform; - /** Replies the X coordinate of the direction vector. - * If this point is not part of a polyline, the direction vector is null. - * - * @return the x coordinate of the direction vector. - */ - @Pure int getDirectionX(); + private int px; - /** Replies the Y coordinate of the direction vector. - * If this point is not part of a polyline, the direction vector is null. - * - * @return the y coordinate of the direction vector. - */ - @Pure int getDirectionY(); + private int py; - /** Sets a new value in the X direction of the point. - * - * @param x the new value double x. - */ - void setDirectionX(int x); + private int dx; - /** Sets a new value in the Y direction of the point. - * @param y the new value double y. - */ - void setDirectionY(int y); + private int dy; + + /** + * @param point the iterated oriented point. + * @param transform the transformation, or null. + */ + public OrientedPointPathIterator(OrientedPoint2ai point, Transform2D transform) { + assert point != null : AssertMessages.notNullParameter(); + this.point = point; + this.transform = transform == null || transform.isIdentity() ? null : transform; + this.px = point.ix(); + this.py = point.iy(); + this.dx = point.idx(); + this.dy = point.idy(); + } + + @Override + public PathWindingRule getWindingRule() { + return PathWindingRule.NON_ZERO; + } + + @Override + public boolean isPolyline() { + return false; + } + + @Override + public boolean isCurved() { + return false; + } + + @Override + public boolean isMultiParts() { + return true; + } + + @Override + public boolean isPolygon() { + return false; + } + + @Override + public boolean hasNext() { + return this.index <= 2; + } + + @Override + public T next() { + // TODO Auto-generated method stub + return null; + } + + @Override + public GeomFactory2ai getGeomFactory() { + return this.point.getGeomFactory(); + } + + @Override + public PathIterator2ai restartIterations() { + return new OrientedPointPathIterator<>(this.point, this.transform); + } - /** Replies the X coordinate of the normal vector. - * If this point is not part of a polyline, the normal vector is null. - * - * @return the x coordinate of the normal vector. - */ - @Pure default int getNormalX() { - return -getDirectionY(); } - /** Replies the Y coordinate of the normal vector. - * If this point is not part of a polyline, the normal vector is null. + /** Iterator on the points of this oriented point, which replies the point itself + * and the extremities of the orientation vectors. * - * @return the y coordinate of the normal vector. + * @param

the type of the points. + * @param the type of the vectors. + * @author $Author: tpiotrow$ + * @version $FullVersion$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ */ - @Pure default int getNormalY() { - return getDirectionX(); + class OrientedPointPointIterator

, V extends Vector2D> + implements Iterator

{ + private int index; + + private OrientedPoint2ai point; + + /** + * @param pt the oriented point to iterate on. + */ + public OrientedPointPointIterator(OrientedPoint2ai pt) { + assert pt != null : AssertMessages.notNullParameter(); + this.point = pt; + } + + @Override + public boolean hasNext() { + return this.index <= 2; + } + + @Override + public P next() { + switch (this.index++) { + case 0: + return this.point.getGeomFactory().newPoint(this.point.ix(), this.point.iy()); + case 1: + return this.point.getGeomFactory().newPoint(this.point.idx(), this.point.idy()); + case 2: + return this.point.getGeomFactory().newPoint(this.point.inx(), this.point.iny()); + default: + throw new NoSuchElementException(); + } + } + + } + + @Override + default PathIterator2ai getPathIterator(Transform2D transform) { + return new OrientedPointPathIterator<>(this, transform); + } + + @Override + default Iterator

getPointIterator() { + return new OrientedPointPointIterator<>(this); } @Override @@ -146,27 +227,6 @@ default boolean contains(Point2D pt) { return getX() == pt.getX() && getY() == pt.getY(); } - @Override - default boolean equalsToShape(IT shape) { - if (shape == null) { - return false; - } - if (shape == this) { - return true; - } - // We don't need to check normal because it depends of direction - return getX() == shape.getX() && getY() == shape.getY() - && getDirectionX() == shape.getDirectionX() - && getDirectionY() == shape.getDirectionY(); - } - - /** Replies this point. - * @return this point - */ - default P getPoint() { - return getGeomFactory().newPoint(getX(), getY()); - } - @Override default P getClosestPointTo(Circle2ai circle) { return getPoint(); @@ -177,11 +237,6 @@ default P getClosestPointTo(Path2ai path) { return getPoint(); } - @Override - default P getClosestPointTo(Point2D point) { - return getPoint(); - } - @Override default P getClosestPointTo(Rectangle2ai rectangle) { return getPoint(); @@ -198,44 +253,20 @@ default P getClosestPointTo(Shape2D shape) { } @Override - default double getDistanceL1(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceL1PointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistanceLinf(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceLinfPointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistanceSquared(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistanceSquaredPointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default double getDistance(Point2D pt) { - assert pt != null : AssertMessages.notNullParameter(); - return Point2D.getDistancePointPoint(getX(), getY(), pt.getX(), pt.getY()); - } - - @Override - default P getFarthestPointTo(Point2D point) { + default P getClosestPointTo(MultiShape2ai multishape) { return getPoint(); } @Override default boolean intersects(Circle2ai circle) { assert circle != null : AssertMessages.notNullParameter(); - return circle.contains(getX(), getY()); + return circle.contains(ix(), iy()); } @Override default boolean intersects(MultiShape2ai multishape) { assert multishape != null : AssertMessages.notNullParameter(); - return multishape.contains(getX(), getY()); + return multishape.contains(ix(), iy()); } @Override @@ -245,7 +276,7 @@ default boolean intersects(PathIterator2ai iterator) { final int crossings = Path2ai.computeCrossingsFromPoint( 0, iterator, - getX(), getY(), + ix(), iy(), CrossingComputationType.SIMPLE_INTERSECTION_WHEN_NOT_POLYGON); return crossings == MathConstants.SHAPE_INTERSECTS || (crossings & mask) != 0; @@ -254,35 +285,22 @@ default boolean intersects(PathIterator2ai iterator) { @Override default boolean intersects(Rectangle2ai rectangle) { assert rectangle != null : AssertMessages.notNullParameter(); - return rectangle.contains(getX(), getY()); + return rectangle.contains(ix(), iy()); } @Override default boolean intersects(Segment2ai segment) { assert segment != null : AssertMessages.notNullParameter(); - return segment.contains(getX(), getY()); - } - - @Override - default boolean isEmpty() { - return false; + return segment.contains(ix(), iy()); } - /** Change the point. - * - * @param x x coordinate of the point. - * @param y y coordinate of the point. - */ - // No default implementation to ensure atomic change - void set(double x, double y); - @Override default void toBoundingBox(B box) { assert box != null : AssertMessages.notNullParameter(); - final int x1 = MathUtil.min(getX(), getDirectionX(), getNormalX()); - final int y1 = MathUtil.min(getY(), getDirectionY(), getNormalY()); - final int x2 = MathUtil.max(getX(), getDirectionX(), getNormalX()); - final int y2 = MathUtil.max(getY(), getDirectionY(), getNormalY()); + final int x1 = MathUtil.min(ix(), idx(), inx()); + final int y1 = MathUtil.min(iy(), idy(), iny()); + final int x2 = MathUtil.max(ix(), idx(), inx()); + final int y2 = MathUtil.max(iy(), idy(), iny()); box.setFromCorners(x1, y1, x2, y2); } @@ -294,15 +312,13 @@ default void toBoundingBox(B box) { */ default void transforn(Transform2D transform) { assert transform != null : AssertMessages.notNullParameter(); - final Point2D p = new InnerComputationPoint2ai(getX(), getY()); + final Point2D p = new InnerComputationPoint2ai(ix(), iy()); transform.transform(p); - set(p.getX(), p.getY()); + set(p.ix(), p.iy()); } @Override default void translate(int dx, int dy) { - set(getX() + dx, getY() + dy); - setDirectionX(getDirectionX() + dx); - setDirectionY(getDirectionY() + dy); + set(ix() + dx, iy() + dy, idx() + dx, idy() + dy); } } diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/GeomFactory2d.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/GeomFactory2d.java index 968b24bcc..01288c94f 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/GeomFactory2d.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/GeomFactory2d.java @@ -175,11 +175,21 @@ public OrientedPoint2d newOrientedPoint(double x, double y) { return new OrientedPoint2d(x, y); } + @Override + public OrientedPoint2d newOrientedPoint(double x, double y, double length) { + return new OrientedPoint2d(x, y, length); + } + @Override public OrientedPoint2d newOrientedPoint(double x, double y, double dirX, double dirY) { return new OrientedPoint2d(x, y, dirX, dirY); } + @Override + public OrientedPoint2d newOrientedPoint(double x, double y, double length, double dirX, double dirY) { + return new OrientedPoint2d(x, y, length, dirX, dirY); + } + @Override public MultiShape2d newMultiShape() { return new MultiShape2d<>(); diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/OrientedPoint2d.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/OrientedPoint2d.java index 260fc0f7b..b4b8b4afc 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/OrientedPoint2d.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/d/OrientedPoint2d.java @@ -27,8 +27,8 @@ import org.arakhne.afc.math.geometry.d2.Vector2D; import org.arakhne.afc.math.geometry.d2.afp.OrientedPoint2afp; -/** - * TODO . +/** 2D oriented point with double precision floating-point numbers. + * * @author $Author: tpiotrow$ * @version $FullVersion$ * @mavengroupid $GroupId$ @@ -48,6 +48,8 @@ public class OrientedPoint2d private double dy; + private double len; + /** Construct an empty oriented point. */ public OrientedPoint2d() { @@ -61,6 +63,14 @@ public OrientedPoint2d(Point2D point) { this(point.getX(), point.getY()); } + /** Construct an oriented point from a point and its length on a polyline. + * @param point the point. + * @param length the length. + */ + public OrientedPoint2d(Point2D point, double length) { + this(point.getX(), point.getY(), length); + } + /** Construct an oriented point from the two given coordinates. * @param x x coordinate of the point. * @param y y coordinate of the point. @@ -69,6 +79,15 @@ public OrientedPoint2d(double x, double y) { set(x, y); } + /** Construct an oriented point from the two given coordinates and the length of the point on a polyline. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length + */ + public OrientedPoint2d(double x, double y, double length) { + set(x, y, length); + } + /** Construct an oriented point from a point and a direction vector. * @param point the point. * @param vector the direction vector. @@ -77,6 +96,15 @@ public OrientedPoint2d(Point2D point, Vector2D vector) { this(point.getX(), point.getY(), vector.getX(), vector.getY()); } + /** Construct an oriented point from a point, its length, and a direction vector. + * @param point the point. + * @param length the length of the point + * @param vector the direction vector. + */ + public OrientedPoint2d(Point2D point, double length, Vector2D vector) { + this(point.getX(), point.getY(), length, vector.getX(), vector.getY()); + } + /** Construct an oriented point from the two given coordinates. * @param x x coordinate of the point. * @param y y coordinate of the point. @@ -87,6 +115,17 @@ public OrientedPoint2d(double x, double y, double dirX, double dirY) { set(x, y, dirX, dirY); } + /** Construct an oriented point from the given coordinates. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + public OrientedPoint2d(double x, double y, double length, double dirX, double dirY) { + set(x, y, length, dirX, dirY); + } + @Pure @Override public int hashCode() { @@ -95,6 +134,7 @@ public int hashCode() { bits = 31 * bits + Double.hashCode(this.py); bits = 31 * bits + Double.hashCode(this.dx); bits = 31 * bits + Double.hashCode(this.dy); + bits = 31 * bits + Double.hashCode(this.len); final int b = (int) bits; return b ^ (b >> 31); } @@ -108,6 +148,8 @@ public String toString() { b.append(", "); //$NON-NLS-1$ b.append(getY()); b.append(")|("); //$NON-NLS-1$ + b.append(getLength()); + b.append(")|("); //$NON-NLS-1$ b.append(getDirectionX()); b.append(", "); //$NON-NLS-1$ b.append(getDirectionY()); @@ -133,6 +175,48 @@ public OrientedPoint2d createTransformedShape(Transform2D transform) { return getGeomFactory().newOrientedPoint(x1, y1, point.getX(), point.getY()); } + @Override + public void set(int x, int y) { + if (this.px != x || this.py != y) { + this.px = x; + this.py = y; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int length) { + if (this.px != x || this.py != y || this.len != length) { + this.px = x; + this.py = y; + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int dirX, int dirY) { + if (this.px != x || this.py != y || this.dx != dirX || this.dy != dirY) { + this.px = x; + this.py = y; + this.dx = dirX; + this.dy = dirY; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int length, int dirX, int dirY) { + if (this.px != x || this.py != y || this.len != length || this.dx != dirX || this.dy != dirY) { + this.px = x; + this.py = y; + this.dx = dirX; + this.dy = dirY; + this.len = length; + fireGeometryChange(); + } + } + @Override public void set(double x, double y) { if (this.px != x || this.py != y) { @@ -142,6 +226,16 @@ public void set(double x, double y) { } } + @Override + public void set(double x, double y, double length) { + if (this.px != x || this.py != y || this.len != length) { + this.px = x; + this.py = y; + this.len = length; + fireGeometryChange(); + } + } + @Override public void set(double x, double y, double dirX, double dirY) { if (this.px != x || this.py != y || this.dx != dirX || this.dy != dirY) { @@ -153,6 +247,26 @@ public void set(double x, double y, double dirX, double dirY) { } } + @Override + public void set(double x, double y, double length, double dirX, double dirY) { + if (this.px != x || this.py != y || this.len != length || this.dx != dirX || this.dy != dirY) { + this.px = x; + this.py = y; + this.dx = dirX; + this.dy = dirY; + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void setX(int x) { + if (this.px != x) { + this.px = x; + fireGeometryChange(); + } + } + @Override public void setX(double x) { if (this.px != x) { @@ -161,6 +275,14 @@ public void setX(double x) { } } + @Override + public void setY(int y) { + if (this.py != y) { + this.py = y; + fireGeometryChange(); + } + } + @Override public void setY(double y) { if (this.py != y) { @@ -169,6 +291,14 @@ public void setY(double y) { } } + @Override + public void setDirectionX(int dirX) { + if (this.dx != dirX) { + this.dx = dirX; + fireGeometryChange(); + } + } + @Override public void setDirectionX(double dirX) { if (this.dx != dirX) { @@ -177,6 +307,14 @@ public void setDirectionX(double dirX) { } } + @Override + public void setDirectionY(int dirY) { + if (this.dy != dirY) { + this.dy = dirY; + fireGeometryChange(); + } + } + @Override public void setDirectionY(double dirY) { if (this.dy != dirY) { @@ -185,23 +323,69 @@ public void setDirectionY(double dirY) { } } + @Override + public void setLength(int length) { + if (this.len != length) { + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void setLength(double length) { + if (this.len != length) { + this.len = length; + fireGeometryChange(); + } + } + @Override public double getX() { return this.px; } + @Override + public int ix() { + return (int) Math.round(this.px); + } + @Override public double getY() { return this.py; } + @Override + public int iy() { + return (int) Math.round(this.py); + } + @Override public double getDirectionX() { return this.dx; } + @Override + public int idx() { + return (int) Math.round(this.dx); + } + @Override public double getDirectionY() { return this.dy; } + + @Override + public int idy() { + return (int) Math.round(this.dy); + } + + @Override + public double getLength() { + return this.len; + } + + @Override + public int ilen() { + return (int) Math.round(this.len); + } } diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/GeomFactory2i.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/GeomFactory2i.java index 992cdd5bd..ebf9e5937 100644 --- a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/GeomFactory2i.java +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/GeomFactory2i.java @@ -164,6 +164,26 @@ public Segment2i newSegment(int x1, int y1, int x2, int y2) { return new Segment2i(x1, y1, x2, y2); } + @Override + public OrientedPoint2i newOrientedPoint(int x, int y) { + return new OrientedPoint2i(x, y); + } + + @Override + public OrientedPoint2i newOrientedPoint(int x, int y, int length) { + return new OrientedPoint2i(x, y, length); + } + + @Override + public OrientedPoint2i newOrientedPoint(int x, int y, int dirX, int dirY) { + return new OrientedPoint2i(x, y, dirX, dirY); + } + + @Override + public OrientedPoint2i newOrientedPoint(int x, int y, int length, int dirX, int dirY) { + return new OrientedPoint2i(x, y, length, dirX, dirY); + } + @Override public MultiShape2i newMultiShape() { return new MultiShape2i<>(); diff --git a/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/OrientedPoint2i.java b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/OrientedPoint2i.java new file mode 100644 index 000000000..63ecc2992 --- /dev/null +++ b/core/math/src/main/java/org/arakhne/afc/math/geometry/d2/i/OrientedPoint2i.java @@ -0,0 +1,391 @@ +/* + * $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.geometry.d2.i; + +import org.eclipse.xtext.xbase.lib.Pure; + +import org.arakhne.afc.math.geometry.d2.Point2D; +import org.arakhne.afc.math.geometry.d2.Transform2D; +import org.arakhne.afc.math.geometry.d2.Vector2D; +import org.arakhne.afc.math.geometry.d2.ai.OrientedPoint2ai; + +/** 2D oriented point with int precision floating-point numbers. + * + * @author $Author: tpiotrow$ + * @version $FullVersion$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ + */ +public class OrientedPoint2i + extends AbstractShape2i + implements OrientedPoint2ai, OrientedPoint2i, PathElement2i, Point2i, Vector2i, Rectangle2i> { + + private static final long serialVersionUID = 6296312122530686621L; + + private int px; + + private int py; + + private int dx; + + private int dy; + + private int len; + + /** Construct an empty oriented point. + */ + public OrientedPoint2i() { + // + } + + /** Construct an oriented point from a point. + * @param point the point. + */ + public OrientedPoint2i(Point2D point) { + this(point.ix(), point.iy()); + } + + /** Construct an oriented point from a point and its length on a polyline. + * @param point the point. + * @param length the length. + */ + public OrientedPoint2i(Point2D point, int length) { + this(point.ix(), point.iy(), length); + } + + /** Construct an oriented point from the two given coordinates. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + */ + public OrientedPoint2i(int x, int y) { + set(x, y); + } + + /** Construct an oriented point from the two given coordinates and the length of the point on a polyline. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length + */ + public OrientedPoint2i(int x, int y, int length) { + set(x, y, length); + } + + /** Construct an oriented point from a point and a direction vector. + * @param point the point. + * @param vector the direction vector. + */ + public OrientedPoint2i(Point2D point, Vector2D vector) { + this(point.ix(), point.iy(), vector.ix(), vector.iy()); + } + + /** Construct an oriented point from a point, its length, and a direction vector. + * @param point the point. + * @param length the length of the point + * @param vector the direction vector. + */ + public OrientedPoint2i(Point2D point, int length, Vector2D vector) { + this(point.ix(), point.iy(), length, vector.ix(), vector.iy()); + } + + /** Construct an oriented point from the two given coordinates. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + public OrientedPoint2i(int x, int y, int dirX, int dirY) { + set(x, y, dirX, dirY); + } + + /** Construct an oriented point from the given coordinates. + * @param x x coordinate of the point. + * @param y y coordinate of the point. + * @param length the length of the point on the polyline. + * @param dirX x coordinate of the vector. + * @param dirY y coordinate of the vector. + */ + public OrientedPoint2i(int x, int y, int length, int dirX, int dirY) { + set(x, y, length, dirX, dirY); + } + + @Pure + @Override + public int hashCode() { + long bits = 1; + bits = 31 * bits + Integer.hashCode(this.px); + bits = 31 * bits + Integer.hashCode(this.py); + bits = 31 * bits + Integer.hashCode(this.dx); + bits = 31 * bits + Integer.hashCode(this.dy); + bits = 31 * bits + Integer.hashCode(this.len); + final int b = (int) bits; + return b ^ (b >> 31); + } + + @Pure + @Override + public String toString() { + final StringBuilder b = new StringBuilder(); + b.append("("); //$NON-NLS-1$ + b.append(getX()); + b.append(", "); //$NON-NLS-1$ + b.append(getY()); + b.append(")|("); //$NON-NLS-1$ + b.append(getLength()); + b.append(")|("); //$NON-NLS-1$ + b.append(getDirectionX()); + b.append(", "); //$NON-NLS-1$ + b.append(getDirectionY()); + b.append(")|("); //$NON-NLS-1$ + b.append(getNormalX()); + b.append(", "); //$NON-NLS-1$ + b.append(getNormalY()); + b.append(")"); //$NON-NLS-1$ + return b.toString(); + } + + @Override + public OrientedPoint2i createTransformedShape(Transform2D transform) { + if (transform == null || transform.isIdentity()) { + return clone(); + } + final Point2i point = getGeomFactory().newPoint(ix(), iy()); + transform.transform(point); + final int x1 = point.ix(); + final int y1 = point.iy(); + point.set(idx(), idy()); + transform.transform(point); + return getGeomFactory().newOrientedPoint(x1, y1, point.ix(), point.iy()); + } + + @Override + public void set(int x, int y) { + if (this.px != x || this.py != y) { + this.px = x; + this.py = y; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int length) { + if (this.px != x || this.py != y || this.len != length) { + this.px = x; + this.py = y; + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int dirX, int dirY) { + if (this.px != x || this.py != y || this.dx != dirX || this.dy != dirY) { + this.px = x; + this.py = y; + this.dx = dirX; + this.dy = dirY; + fireGeometryChange(); + } + } + + @Override + public void set(int x, int y, int length, int dirX, int dirY) { + if (this.px != x || this.py != y || this.len != length || this.dx != dirX || this.dy != dirY) { + this.px = x; + this.py = y; + this.dx = dirX; + this.dy = dirY; + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void set(double x, double y) { + if (this.px != x || this.py != y) { + this.px = (int) Math.round(x); + this.py = (int) Math.round(y); + fireGeometryChange(); + } + } + + @Override + public void set(double x, double y, double length) { + if (this.px != x || this.py != y || this.len != length) { + this.px = (int) Math.round(x); + this.py = (int) Math.round(y); + this.len = (int) Math.round(length); + fireGeometryChange(); + } + } + + @Override + public void set(double x, double y, double dirX, double dirY) { + if (this.px != x || this.py != y || this.dx != dirX || this.dy != dirY) { + this.px = (int) Math.round(x); + this.py = (int) Math.round(y); + this.dx = (int) Math.round(dirX); + this.dy = (int) Math.round(dirY); + fireGeometryChange(); + } + } + + @Override + public void set(double x, double y, double length, double dirX, double dirY) { + if (this.px != x || this.py != y || this.len != length || this.dx != dirX || this.dy != dirY) { + this.px = (int) Math.round(x); + this.py = (int) Math.round(y); + this.dx = (int) Math.round(dirX); + this.dy = (int) Math.round(dirY); + this.len = (int) Math.round(length); + fireGeometryChange(); + } + } + + @Override + public void setX(int x) { + if (this.px != x) { + this.px = x; + fireGeometryChange(); + } + } + + @Override + public void setX(double x) { + if (this.px != x) { + this.px = (int) Math.round(x); + fireGeometryChange(); + } + } + + @Override + public void setY(int y) { + if (this.py != y) { + this.py = y; + fireGeometryChange(); + } + } + + @Override + public void setY(double y) { + if (this.py != y) { + this.py = (int) Math.round(y); + fireGeometryChange(); + } + } + + @Override + public void setDirectionX(int dirX) { + if (this.dx != dirX) { + this.dx = dirX; + fireGeometryChange(); + } + } + + @Override + public void setDirectionX(double dirX) { + if (this.dx != dirX) { + this.dx = (int) Math.round(dirX); + fireGeometryChange(); + } + } + + @Override + public void setDirectionY(int dirY) { + if (this.dy != dirY) { + this.dy = dirY; + fireGeometryChange(); + } + } + + @Override + public void setDirectionY(double dirY) { + if (this.dy != dirY) { + this.dy = (int) Math.round(dirY); + fireGeometryChange(); + } + } + + @Override + public void setLength(int length) { + if (this.len != length) { + this.len = length; + fireGeometryChange(); + } + } + + @Override + public void setLength(double length) { + if (this.len != length) { + this.len = (int) Math.round(length); + fireGeometryChange(); + } + } + + @Override + public double getX() { + return this.px; + } + + @Override + public int ix() { + return this.px; + } + + @Override + public double getY() { + return this.py; + } + + @Override + public int iy() { + return this.py; + } + + @Override + public double getDirectionX() { + return this.dx; + } + + @Override + public int idx() { + return this.dx; + } + + @Override + public double getDirectionY() { + return this.dy; + } + + @Override + public int idy() { + return this.dy; + } + + @Override + public double getLength() { + return this.len; + } + + @Override + public int ilen() { + return this.len; + } +}