/* * $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 java.io.Serializable; import java.util.Objects; import org.eclipse.xtext.xbase.lib.Pure; import org.arakhne.afc.math.Unefficient; import org.arakhne.afc.vmutil.asserts.AssertMessages; /** 3D shape. * * @param <ST> is the type of the general implementation. * @param <IT> is the type of the implementation of this shape. * @param <I> is the type of the iterator used to obtain the elements of the path. * @param <P> is the type of the points. * @param <V> is the type of the vectors. * @param <B> is the type of the bounding boxes. * @author $Author: sgalland$ * @author $Author: hjaffali$ * @author $Author: tpiotrow$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ public interface Shape3D< ST extends Shape3D<?, ?, I, P, V, B>, IT extends Shape3D<?, ?, I, P, V, B>, I extends PathIterator3D<?>, P extends Point3D<? super P, ? super V>, V extends Vector3D<? super V, ? super P>, B extends Shape3D<?, ?, I, P, V, B>> extends Cloneable, Serializable { /** Replies the geometry factory associated to this point. * * @return the factory. */ @Pure GeomFactory3D<V, P> getGeomFactory(); /** Replies if this shape is empty. * The semantic associated to the state "empty" * depends on the implemented shape. See the * subclasses for details. * * @return <code>true</code> if the shape is empty; * <code>false</code> otherwise. */ @Pure boolean isEmpty(); /** Clone this shape. * * @return the clone. */ @Pure IT clone(); /** Replies this shape as the same path iterator as the given one. * * <p>The equality test does not flatten the paths. It means that * is function has is functionnality equivalent to: <pre><code> * PathIterator2D it = this.getPathIterator(); * while (it.hasNext() && pathIterator.hasNext()) { * PathElement2D e1 = it.next(); * PathElement2D e2 = it.next(); * if (!e1.equals(e2)) return false; * } * return !it.hasNext() && !pathIterator.hasNext(); * </code></pre> * * @param pathIterator the path iterator to compare to the one of this shape. * @return <code>true</code> if the path iterator of this shape replies the same * elements as the given path iterator. */ @Pure default boolean equalsToPathIterator(PathIterator3D<?> pathIterator) { final I localIterator = getPathIterator(); if (pathIterator == null) { return false; } PathElement3D element1; PathElement3D element2; while (localIterator.hasNext() && pathIterator.hasNext()) { element1 = localIterator.next(); element2 = pathIterator.next(); if (!Objects.equals(element1, element2)) { return false; } } return !localIterator.hasNext() && !pathIterator.hasNext(); } /** Replies this shape is equal to the given shape. * * @param shape the shape to compare to. * @return <code>true</code> if this shape is equal is equal to the given path. */ @Pure boolean equalsToShape(IT shape); /** Reset this shape to be equivalent to * an just-created instance of this shape type. */ void clear(); /** Replies if the given point is inside this shape. * * @param point the point to search for. * @return <code>true</code> if the given shape is intersecting this * shape, otherwise <code>false</code>. */ @Pure boolean contains(Point3D<?, ?> point); /** Replies if this shape is inside the given shape. * * <p>You must use the containing functions with a specific parameter type in place of * this general function. Indeed, the implementation of this function is unefficient due * to the tests against the types of the given shape, and the cast operators. * * @param shape the shape to compare to. * @return <code>true</code> if the given shape is inside this shape; * <code>false</code> otherwise. */ @Pure @Unefficient boolean contains(Shape3D<?, ?, ?, ?, ?, ?> shape); /** Replies the point on the shape that is closest to the given point. * * @param point the point. * @return the closest point on the shape; or the point itself * if it is inside the shape. */ @Pure P getClosestPointTo(Point3D<?, ?> point); /** Replies the point on the shape that is closest to the given shape. * * <p>If the two shapes are intersecting, the replied point is always at the intersection * of the two shapes. This function does not enforce the meaning of the replied point * in the case of shape intersection. In other words, this function is warranting that * the reply point is the either the penetration point, nor a perimeter point, nor any point * with a specific meaning. * * @param shape the shape. * @return the closest point on the shape. */ @Pure @Unefficient P getClosestPointTo(Shape3D<?, ?, ?, ?, ?, ?> shape); /** Replies the point on the shape that is farthest the given point. * * @param point the point. * @return the farthest point on the shape. */ @Pure P getFarthestPointTo(Point3D<?, ?> point); /** Replies the minimal distance from this shape to the given point. * * @param point the point. * @return the minimal distance between this shape and the point. */ @Pure default double getDistance(Point3D<?, ?> point) { assert point != null : AssertMessages.notNullParameter(); return Math.sqrt(getDistanceSquared(point)); } /** Replies the minimal distance from this shape to the given shape. * * @param shape the shape. * @return the minimal distance between this shape and the given shape. */ @Pure @Unefficient default double getDistance(Shape3D<?, ?, ?, ?, ?, ?> shape) { assert shape != null : AssertMessages.notNullParameter(); return Math.sqrt(getDistanceSquared(shape)); } /** Replies the squared value of the minimal distance from this shape to the given point. * * @param point the point. * @return squared value of the minimal distance between this shape and the point. */ @Pure double getDistanceSquared(Point3D<?, ?> point); /** Replies the squared value of the minimal distance from this shape to the given shape. * * @param shape the shape. * @return squared value of the minimal distance between this shape and the given shape. */ @Pure @Unefficient double getDistanceSquared(Shape3D<?, ?, ?, ?, ?, ?> shape); /** * Computes the L-1 (Manhattan) distance between this shape and * point p1. The L-1 distance is equal to abs(x1-x2) + abs(y1-y2). * @param point the point * @return the distance. */ @Pure double getDistanceL1(Point3D<?, ?> point); /** * Computes the L-infinite distance between this shape and * point p1. The L-infinite distance is equal to * MAX[abs(x1-x2), abs(y1-y2), abs(z1-z2)]. * @param point the point. * @return the distance. */ @Pure double getDistanceLinf(Point3D<?, ?> point); /** Set this shape with the attributes of the given shape. * * @param shape the shape. */ void set(IT shape); /** Replies an iterator on the path elements. * * <p>The iterator for this class is not multi-threaded safe. * * @return an iterator on the path elements. */ @Pure default I getPathIterator() { return getPathIterator(null); } /** Replies the elements of the paths. * * @param transform is the transformation to apply to the path. * @return the elements of the path. */ @Pure I getPathIterator(Transform3D transform); /** Apply the transformation to the shape and reply the result. * This function does not change the current shape. * * @param transform is the transformation to apply to the shape. * @return the result of the transformation. */ @Pure ST createTransformedShape(Transform3D transform); /** Translate the shape. * * @param vector the translation vector */ void translate(Vector3D<?, ?> vector); /** Replies the bounding box of this shape. * * @return the bounding box of this shape. */ @Pure B toBoundingBox(); /** Replies the bounds of the shape. * * @param box is set with the bounds of the shape. */ void toBoundingBox(B box); /** Replies if this shape is intersecting the given shape. * * <p>You must use the intersection functions with a specific parameter type in place of * this general function. Indeed, the implementation of this function is unefficient due * to the tests against the types of the given shape, and the cast operators. * * @param shape the shape to compare to * @return <code>true</code> if this shape is intersecting the given shape; * <code>false</code> if there is no intersection. */ @Pure @Unefficient boolean intersects(Shape3D<?, ?, ?, ?, ?, ?> shape); /** Translate this shape by adding 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 * @see #translate(Vector3D) */ default void operator_add(Vector3D<?, ?> v) { translate(v); } /** Create a new shape by translating this shape of 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 * @return the transformed shape. * @see #translate(Vector3D) */ @Pure default IT operator_plus(Vector3D<?, ?> v) { final IT clone = clone(); clone.translate(v); return clone; } /** Translate this shape by substracting 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 * @see #translate(Vector3D) */ default void operator_remove(Vector3D<?, ?> v) { final Vector3D<?, ?> negate = getGeomFactory().newVector(); negate.negate(v); translate(negate); } /** Create a new shape by translating this shape of 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 * @return the transformed shape. * @see #translate(Vector3D) */ @Pure default IT operator_minus(Vector3D<?, ?> v) { final IT clone = clone(); final Vector3D<?, ?> negate = getGeomFactory().newVector(); negate.negate(v); clone.translate(negate); return clone; } /** Create a new shape by applying the given transformation: {@code this * t} * * <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 t the transformation * @return the transformed shape. * @see #createTransformedShape(Transform3D) */ @Pure default ST operator_multiply(Transform3D t) { return createTransformedShape(t); } /** Replies if the given point is inside the shape: {@code this && b} * * <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 point the point to test. * @return <code>true</code> if the point is inside the shape. Otherwise, <code>false</code>. * @see #createTransformedShape(Transform3D) */ @Pure default boolean operator_and(Point3D<?, ?> point) { return contains(point); } /** Replies if the given shape has an intersection with this shape: {@code this && b} * * <p>You must use the intersection functions with a specific parameter type in place of * this general function. Indeed, the implementation of this function is unefficient due * to the tests against the types of the given shape, and the cast operators. * * <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 shapes are intersecting. Otherwise, <code>false</code>. * @see #intersects(Shape3D) */ @Pure @Unefficient default boolean operator_and(Shape3D<?, ?, ?, ?, ?, ?> shape) { return intersects(shape); } /** Replies the distance between the given point and this shape: {@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 test. * @return the distance. * @see #getDistance(Point3D) */ @Pure default double operator_upTo(Point3D<?, ?> pt) { return getDistance(pt); } }