/*
* $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.d3;
import org.eclipse.xtext.xbase.lib.Inline;
import org.eclipse.xtext.xbase.lib.Pure;
import org.arakhne.afc.math.MathUtil;
import org.arakhne.afc.vmutil.asserts.AssertMessages;
/** 3D Point.
*
* @param <RP> is the type of point that can be returned by this tuple.
* @param <RV> is the type of vector that can be returned by this tuple.
* @author $Author: sgalland$
* @author $Author: tpiotrow$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public interface Point3D<RP extends Point3D<? super RP, ? super RV>, RV extends Vector3D<? super RV, ? super RP>>
extends Tuple3D<RP> {
/**
* Replies if three points are colinear, ie. one the same line.
*
* <p>Trival approach is: points are collinear iff |AB| + |AC| = |BC|, where A B C are the three points.
*
* @param x1
* is the X coordinate of the first point
* @param y1
* is the Y coordinate of the first point
* @param z1
* is the Z coordinate of the first point
* @param x2
* is the X coordinate of the second point
* @param y2
* is the Y coordinate of the second point
* @param z2
* is the Z coordinate of the second point
* @param x3
* is the X coordinate of the third point
* @param y3
* is the Y coordinate of the third point
* @param z3
* is the Z coordinate of the third point
* @return <code>true</code> if the three given points are colinear.
* @since 3.0
* @see MathUtil#isEpsilonZero(double)
*/
@Pure
@SuppressWarnings("checkstyle:parameternumber")
static boolean isCollinearPoints(
double x1, double y1, double z1,
double x2, double y2, double z2,
double x3, double y3, double z3) {
final double dx1 = x2 - x1;
final double dy1 = y2 - y1;
final double dz1 = z2 - z1;
final double dx2 = x3 - x1;
final double dy2 = y3 - y1;
final double dz2 = z3 - z1;
final double cx = dy1 * dz2 - dy2 * dz1;
final double cy = dx2 * dz1 - dx1 * dz2;
final double cz = dx1 * dy2 - dx2 * dy1;
return MathUtil.isEpsilonZero(cx * cx + cy * cy + cz * cz);
}
/** Compute the distance between 2 points.
*
* @param x1 x position of the first point.
* @param y1 y position of the first point.
* @param z1 z position of the first point.
* @param x2 x position of the second point.
* @param y2 y position of the second point.
* @param z2 z position of the second point.
* @return the distance between given points.
* @see #getDistanceSquaredPointPoint(double, double, double, double, double, double)
* @see #getDistanceL1PointPoint(double, double, double, double, double, double)
*/
@Pure
@Inline(value = "Math.sqrt(($1 - $4) * ($1 - $4) + ($2 - $5) * ($2 - $5) + ($3 - $6) * ($3 - $6))",
imported = {Math.class})
static double getDistancePointPoint(double x1, double y1, double z1, double x2, double y2, double z2) {
final double dx = x1 - x2;
final double dy = y1 - y2;
final double dz = z1 - z2;
return Math.sqrt(dx * dx + dy * dy + dz * dz);
}
/** Compute the squared distance between 2 points.
*
* @param x1 x position of the first point.
* @param y1 y position of the first point.
* @param z1 z position of the first point.
* @param x2 x position of the second point.
* @param y2 y position of the second point.
* @param z2 z position of the second point.
* @return the squared distance between given points.
* @see #getDistancePointPoint(double, double, double, double, double, double)
* @see #getDistanceL1PointPoint(double, double, double, double, double, double)
*/
@Pure
@Inline(value = "($1 - $4) * ($1 - $4) + ($2 - $5) * ($2 - $5) + ($3 - $6) * ($3 - $6)")
static double getDistanceSquaredPointPoint(double x1, double y1, double z1, double x2, double y2, double z2) {
final double dx = x1 - x2;
final double dy = y1 - y2;
final double dz = z1 - z2;
return dx * dx + dy * dy + dz * dz;
}
/** Compute the L-1 (Manhattan) distance between 2 points.
* The L-1 distance is equal to abs(x1-x2) + abs(y1-y2) + abs(z1-z2).
*
* @param x1 x position of the first point.
* @param y1 y position of the first point.
* @param z1 z position of the first point.
* @param x2 x position of the second point.
* @param y2 y position of the second point.
* @param z2 z position of the second point.
* @return the distance between given points.
* @see #getDistancePointPoint(double, double, double, double, double, double)
* @see #getDistanceSquaredPointPoint(double, double, double, double, double, double)
*/
@Pure
@Inline(value = "Math.abs($1 - $4) + Math.abs($2 - $5) + Math.abs($3 - $6)",
imported = {Math.class})
static double getDistanceL1PointPoint(double x1, double y1, double z1, double x2, double y2, double z2) {
return Math.abs(x1 - x2) + Math.abs(y1 - y2) + Math.abs(z1 - z2);
}
/** Compute the L-infinite distance between 2 points.
* The L-infinite distance is equal to
* MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)].
*
* @param x1 x position of the first point.
* @param y1 y position of the first point.
* @param z1 z position of the first point.
* @param x2 x position of the second point.
* @param y2 y position of the second point.
* @param z2 z position of the second point.
* @return the distance between given points.
* @see #getDistancePointPoint(double, double, double, double, double, double)
* @see #getDistanceSquaredPointPoint(double, double, double, double, double, double)
*/
@Pure
@Inline(value = "MathUtil.max(Math.abs($1 - $4) + Math.abs($2 - $5) + Math.abs($3 - $6))",
imported = {Math.class, MathUtil.class})
static double getDistanceLinfPointPoint(double x1, double y1, double z1, double x2, double y2, double z2) {
return MathUtil.max(Math.abs(x1 - x2), Math.abs(y1 - y2), Math.abs(z1 - z2));
}
/**
* Computes the square of the distance between this point and point p1.
* @param point the other point
* @return the distance.
*/
@Pure
default double getDistanceSquared(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return getDistanceSquaredPointPoint(getX(), getY(), getZ(), point.getX(), point.getY(), point.getZ());
}
/**
* Computes the distance between this point and point p1.
* @param point the other point
* @return the distance.
*/
@Pure
default double getDistance(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return getDistancePointPoint(getX(), getY(), getZ(), point.getX(), point.getY(), point.getZ());
}
/**
* Computes the L-1 (Manhattan) distance between this point and
* point p1. The L-1 distance is equal to abs(x1-x2) + abs(y1-y2).
* @param point the other point
* @return the distance.
*/
@Pure
default double getDistanceL1(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return getDistanceL1PointPoint(getX(), getY(), getZ(), point.getX(), point.getY(), point.getZ());
}
/**
* Computes the L-infinite distance between this point and
* point p1. The L-infinite distance is equal to
* MAX[abs(x1-x2), abs(y1-y2)].
* @param point the other point
* @return the distance.
*/
@Pure
default double getDistanceLinf(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return getDistanceLinfPointPoint(getX(), getY(), getZ(), point.getX(), point.getY(), point.getZ());
}
/**
* Computes the L-1 (Manhattan) distance between this point and
* point p1. The L-1 distance is equal to abs(x1-x2) + abs(y1-y2) + abs(z1-z2).
* @param point the other point
* @return the distance.
*/
@Pure
default int getIdistanceL1(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return Math.abs(ix() - point.ix()) + Math.abs(iy() - point.iy()) + Math.abs(iz() - point.iz());
}
/**
* Computes the L-infinite distance between this point and
* point p1. The L-infinite distance is equal to
* MAX[abs(x1-x2), abs(y1-y2)].
* @param point the other point
* @return the distance.
*/
@Pure
default int getIdistanceLinf(Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
return MathUtil.max(Math.abs(ix() - point.ix()), Math.abs(iy() - point.iy()), Math.abs(iz() - point.iz()));
}
/**
* Sets the value of this tuple to the sum of tuples t1 and t2.
* @param point the first tuple
* @param vector the second tuple
*/
default void add(Point3D<?, ?> point, Vector3D<?, ?> vector) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(point.getX() + vector.getX(),
point.getY() + vector.getY(),
point.getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the sum of tuples t1 and t2.
* @param vector the first tuple
* @param point the second tuple
*/
default void add(Vector3D<?, ?> point, Point3D<?, ?> vector) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(point.getX() + vector.getX(),
point.getY() + vector.getY(),
point.getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the sum of itself and t1.
* @param vector the other tuple
*/
default void add(Vector3D<?, ?> vector) {
assert vector != null : AssertMessages.notNullParameter();
set(getX() + vector.getX(),
getY() + vector.getY(),
getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of tuple t1 plus tuple t2 (this = s*t1 + t2).
* @param scale the scalar value
* @param vector the tuple to be multipled
* @param point the tuple to be added
*/
default void scaleAdd(int scale, Vector3D<?, ?> vector, Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(scale * vector.getX() + point.getX(),
scale * vector.getY() + point.getY(),
scale * vector.getZ() + point.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of tuple t1 plus tuple t2 (this = s*t1 + t2).
* @param scale the scalar value
* @param vector the tuple to be multipled
* @param point the tuple to be added
*/
default void scaleAdd(double scale, Vector3D<?, ?> vector, Point3D<?, ?> point) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(scale * vector.getX() + point.getX(),
scale * vector.getY() + point.getY(),
scale * vector.getZ() + point.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of tuple t1 plus tuple t2 (this = s*t1 + t2).
* @param scale the scalar value
* @param point the tuple to be multipled
* @param vector the tuple to be added
*/
default void scaleAdd(int scale, Point3D<?, ?> point, Vector3D<?, ?> vector) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(scale * point.getX() + vector.getX(),
scale * point.getY() + vector.getY(),
scale * point.getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of tuple t1 plus tuple t2 (this = s*t1 + t2).
* @param scale the scalar value
* @param point the tuple to be multipled
* @param vector the tuple to be added
*/
default void scaleAdd(double scale, Point3D<?, ?> point, Vector3D<?, ?> vector) {
assert point != null : AssertMessages.notNullParameter();
assert vector != null : AssertMessages.notNullParameter();
set(scale * point.getX() + vector.getX(),
scale * point.getY() + vector.getY(),
scale * point.getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of itself and then adds tuple t1 (this = s*this + t1).
* @param scale the scalar value
* @param vector the tuple to be added
*/
default void scaleAdd(int scale, Vector3D<?, ?> vector) {
assert vector != null : AssertMessages.notNullParameter();
set(scale * getX() + vector.getX(),
scale * getY() + vector.getY(),
scale * getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the scalar multiplication
* of itself and then adds tuple t1 (this = s*this + t1).
* @param scale the scalar value
* @param vector the tuple to be added
*/
default void scaleAdd(double scale, Vector3D<?, ?> vector) {
assert vector != null : AssertMessages.notNullParameter();
set(scale * getX() + vector.getX(),
scale * getY() + vector.getY(),
scale * getZ() + vector.getZ());
}
/**
* Sets the value of this tuple to the difference
* of tuples t1 and t2 (this = t1 - t2).
* @param point the first tuple
* @param vector the second tuple
*/
default void sub(Point3D<?, ?> point, Vector3D<?, ?> vector) {
assert point != null : AssertMessages.notNullParameter(0);
assert vector != null : AssertMessages.notNullParameter(1);
set(point.getX() - vector.getX(),
point.getY() - vector.getY(),
point.getZ() - vector.getZ());
}
/**
* Sets the value of this tuple to the difference
* of itself and t1 (this = this - t1).
* @param vector the other tuple
*/
default void sub(Vector3D<?, ?> vector) {
assert vector != null : AssertMessages.notNullParameter();
set(getX() - vector.getX(),
getY() - vector.getY(),
getZ() - vector.getZ());
}
/** Replies an unmodifiable copy of this vector.
*
* @return an unmodifiable copy.
*/
@Pure
UnmodifiablePoint3D<?, ?> toUnmodifiable();
/** Replies the geometry factory associated to this point.
*
* @return the factory.
*/
@Pure
GeomFactory3D<RV, RP> getGeomFactory();
/** Sum of this point and a vector: {@code this + v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector to add
* @return the result.
* @see #add(Point3D, Vector3D)
*/
@Pure
default RP operator_plus(Vector3D<?, ?> v) {
assert v != null : AssertMessages.notNullParameter();
return getGeomFactory().newPoint(getX() + v.getX(), getY() + v.getY(), getZ() + v.getZ());
}
/** Increment this point with the given vector: {@code this += v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector to add
* @see #add(Vector3D)
*/
default void operator_add(Vector3D<?, ?> v) {
add(v);
}
/** the v vector to this point: {@code this - v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector to substract.
* @return the result.
* @see #sub(Point3D, Vector3D)
*/
@Pure
default RP operator_minus(Vector3D<?, ?> v) {
assert v != null : AssertMessages.notNullParameter();
return getGeomFactory().newPoint(getX() - v.getX(), getY() - v.getY(), getZ() - v.getZ());
}
/** the p point to this point: {@code this - p}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param pt the point to substract
* @return the vector from the p to this.
* @see Vector3D#sub(Point3D, Point3D)
*/
@Pure
default RV operator_minus(Point3D<?, ?> pt) {
assert pt != null : AssertMessages.notNullParameter();
return getGeomFactory().newVector(getX() - pt.getX(), getY() - pt.getY(), getZ() - pt.getZ());
}
/** the v vector to this: {@code this -= v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector to substract.
* @see #sub(Vector3D)
*/
default void operator_remove(Vector3D<?, ?> v) {
sub(v);
}
/** Replies if the given vector is equal to this vector: {@code this == v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector.
* @return test result.
* @see #equals(Tuple3D)
*/
@Pure
default boolean operator_equals(Tuple3D<?> v) {
return equals(v);
}
/** Replies if the given vector is different than this vector: {@code this != v}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param v the vector.
* @return test result.
* @see #equals(Tuple3D)
*/
@Pure
default boolean operator_notEquals(Tuple3D<?> v) {
return !equals(v);
}
/** Replies if the distance between this and the p point: {@code this .. p}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param pt the point.
* @return the distance.
* @see #getDistance(Point3D)
*/
@Pure
default double operator_upTo(Point3D<?, ?> pt) {
return getDistance(pt);
}
/** Replies the distance between this point and the given shape: {@code this .. s}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param shape the shape to test.
* @return the distance.
* @see Shape3D#getDistance(Point3D)
*/
@Pure
default double operator_upTo(Shape3D<?, ?, ?, ?, ?, ?> shape) {
return shape.getDistance(this);
}
/** If this point is epsilon equal to zero then reply p else reply this: {@code this ?: p}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param pt the point.
* @return the point.
*/
@Pure
default Point3D<? extends RP, ? extends RV> operator_elvis(Point3D<? extends RP, ? extends RV> pt) {
if (MathUtil.isEpsilonZero(getX()) && MathUtil.isEpsilonZero(getY()) && MathUtil.isEpsilonZero(getZ())) {
return pt;
}
return this;
}
/** Replies if the this point is inside the given shape: {@code this && s}
*
* <p>This function is an implementation of the "-" operator for
* the languages that defined or based on the
* <a href="https://www.eclipse.org/Xtext/">Xtext framework</a>.
*
* @param shape the shape to test.
* @return <code>true</code> if the point is inside the shape. Otherwise, <code>false</code>.
* @see Shape3D#contains(Point3D)
*/
@Pure
default boolean operator_and(Shape3D<?, ?, ?, ?, ?, ?> shape) {
return shape.contains(this);
}
// TODO : implements turn() methods
}