/*
* $Id$
*
* Copyright (C) 2010-2013 Christophe BOHRHAUER.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* This program is free software; you can redistribute it and/or modify
*/
package org.arakhne.afc.math.geometry.d3.continuous;
import org.arakhne.afc.math.MathUtil;
import org.arakhne.afc.math.geometry.d3.FunctionalPoint3D;
import org.arakhne.afc.math.geometry.d3.FunctionalVector3D;
import org.arakhne.afc.math.geometry.d3.Point3D;
import org.arakhne.afc.math.geometry.d3.Vector3D;
import org.eclipse.xtext.xbase.lib.Pure;
/** This class represents a 3D plane.
* <p>
* <math xmlns="http://www.w3.org/1998/Math/MathML"><mi>P</mi></math>
* be the point we wish to lie in the plane, and let
* <math><mover><mi>n</mi><mo>⃗</mo></mover></math>
* be a nonzero normal vector to the plane.
* The desired plane is the set of all points
* <math><mi mathvariant="bold">r</mi></math> such that
* <math>
* <mover>
* <mi>n</mi>
* <mo>⃗</mo>
* </mover>
* <mo>⋅</mo>
* <mfenced separators="">
* <mi>r</mi>
* <mo>-</mo>
* <mi>p</mi>
* </mfenced>
* <mo>=</mo>
* <mn>0</mn>
* </math>.
* <p>
* If we write
* <math>
* <mrow>
* <mover>
* <mi>n</mi><mo>⃗</mo>
* </mover>
* <mo>=</mo>
* <mfenced close="]" open="[">
* <mtable>
* <mtr><mtd><mi>a</mi></mtd></mtr>
* <mtr><mtd><mi>b</mi></mtd></mtr>
* <mtr><mtd><mi>c</mi></mtd></mtr>
* </mtable>
* </mfenced>
* </mrow>
* </math>,<br>
* <math>
* <mrow>
* <mi mathvariant="bold">r</mi>
* <mo>=</mo>
* <mfenced>
* <mi>x</mi><mi>y</mi><mi>z</mi>
* </mfenced>
* </mrow>
* </math>, and
* <math><mi>d</mi></math> as the dot product
* <math>
* <mrow>
* <mover>
* <mi>n</mi><mo>⃗</mo>
* </mover>
* <mo>⋅</mo>
* <mi mathvariant="bold">p</mi>
* <mo>=</mo><mo>-</mo><mi>d</mi>
* </mrow>
* </math>,<br>
* then the plane <math><mi>Π</mi></math> is determined by the condition:<br>
* <math>
* <mrow>
* <mi>Π</mi><mo>:</mo><mi>a</mi><mo>.</mo><mi>x</mi>
* <mo>+</mo>
* <mi>b</mi><mo>.</mo><mi>y</mi>
* <mo>+</mo>
* <mi>c</mi><mo>.</mo><mi>z</mi>
* <mo>+</mo>
* <mi>d</mi><mo>=</mo><mn>0</mn>
* </mrow>
* </math>
* <p>
* The normal to the plane is the vector
* <math><mfenced><mi>a</mi><mi>b</mi><mi>c</mi></mfenced></math>.
*
* Given three points in space
* <math><mfenced><msub><mi>x</mi><mn>1</mn></msub></mi><msub><mi>y</mi><mn>1</mn></msub><msub><mi>z</mi><mn>1</mn></msub></mfenced></math>,
* <math><mfenced><msub><mi>x</mi><mn>2</mn></msub></mi><msub><mi>y</mi><mn>2</mn></msub><msub><mi>z</mi><mn>2</mn></msub></mfenced></math> and
* <math><mfenced><msub><mi>x</mi><mn>3</mn></msub></mi><msub><mi>y</mi><mn>3</mn></msub><msub><mi>z</mi><mn>3</mn></msub></mfenced></math>,
* the equation of the plane through these points is
* given by the following determinants.
* <p>
* <math>
* <mrow>
* <mi>a</mi><mo>=</mo>
* <mfenced close="∣ " open="∣ ">
* <mtable>
* <mtr>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>y</mi><mn>1</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>1</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>y</mi><mn>2</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>2</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>y</mi><mn>3</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>3</mn></msub></mtd>
* </mtr>
* </mtable>
* </mfenced>
* </mrow>
* </math>
* <math>
* <mrow>
* <mi>b</mi><mo>=</mo>
* <mfenced close="∣ " open="∣ ">
* <mtable>
* <mtr>
* <mtd><msub><mi>x</mi><mn>1</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>z</mi><mn>1</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>2</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>z</mi><mn>2</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>3</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* <mtd><msub><mi>z</mi><mn>3</mn></msub></mtd>
* </mtr>
* </mtable>
* </mfenced>
* </mrow>
* </math>
* <math>
* <mrow>
* <mi>c</mi><mo>=</mo>
* <mfenced close="∣ " open="∣ ">
* <mtable>
* <mtr>
* <mtd><msub><mi>x</mi><mn>1</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>1</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>2</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>2</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>3</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>3</mn></msub></mtd>
* <mtd><mn>1</mn></mtd>
* </mtr>
* </mtable>
* </mfenced>
* </mrow>
* </math>
* <math>
* <mrow>
* <mi>d</mi><mo>=</mo><mo>-</mo>
* <mfenced close="∣ " open="∣ ">
* <mtable>
* <mtr>
* <mtd><msub><mi>x</mi><mn>1</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>1</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>1</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>2</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>2</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>2</mn></msub></mtd>
* </mtr>
* <mtr>
* <mtd><msub><mi>x</mi><mn>3</mn></msub></mtd>
* <mtd><msub><mi>y</mi><mn>3</mn></msub></mtd>
* <mtd><msub><mi>z</mi><mn>3</mn></msub></mtd>
* </mtr>
* </mtable>
* </mfenced>
* </mrow>
* </math>
*
* @author $Author: cbohrhauer$
* @author $Author: sgalland$
* @author $Author: hjaffali$
* @version $FullVersion$
* @mavengroupid $GroupId$
* @mavenartifactid $ArtifactId$
*/
public abstract class AbstractPlane4F extends AbstractPlane3D<AbstractPlane4F> {
private static final long serialVersionUID = 3765029151610752644L;
/** Replies the intersection factor of the given segment
* when it is intersecting the plane.
* <p>
* If the segment and the plane are not intersecting, this
* function replies {@link Double#NaN}.
* If the segment and the plane are intersecting, two cases:<ol>
* <li>the segment is coplanar to the plane, then this function replies
* {@link Double#POSITIVE_INFINITY}.</li>
* <li>the segment and the plane have a single point of intersection,
* then this function replies the factor of the line's equation that
* permits to retreive the intersection point from the segment definition.
* </ol>
*
* @param a first component of the plane equation.
* @param b second component of the plane equation.
* @param c third component of the plane equation.
* @param d fourth component of the plane equation.
* @param sx1 x coordinate of the first point of the segment.
* @param sy1 y coordinate of the first point of the segment.
* @param sz1 z coordinate of the first axis of the oriented box.
* @param sx2 x coordinate of the second point of the segment.
* @param sy2 y coordinate of the second point of the segment.
* @param sz2 z coordinate of the second axis of the oriented box.
* @return the factor that permits to compute the intersection point,
* {@link Double#NaN} when no intersection, {@link Double#POSITIVE_INFINITY}
* when an infinite number of intersection points.
*/
@Pure
public static double getIntersectionFactorPlaneSegment(
double a, double b, double c, double d,
double sx1, double sy1, double sz1,
double sx2, double sy2, double sz2) {
double denom = a * (sx2 - sx1) + b * (sy2 - sy1) + c * (sz2 - sz1);
if (denom == 0.) {
// Segment and triangle's plane are parallel
// Compute the distance between a point of the segment and the plane.
double dist = a * sx1 + b * sy1 + c * sz1 + d;
if (MathUtil.isEpsilonZero(dist)) {
return Double.POSITIVE_INFINITY;
}
} else {
double factor = (-a * sx1 - b * sy1 - c * sz1 - d) / denom;
if (factor >= 0. && factor <= 1.) {
return factor;
}
}
return Double.NaN;
}
/**
* Replies the projection on the plane of a point.
* <p>
* <strong>First Approach: arithmetic resolution</strong>
* <p>
* Let <math xmlns="http://www.w3.org/1998/Math/MathML"><mover><mrow><mi>u</mi></mrow><mo stretchy="false">→</mo></mover></math> a vector colinear to the line <math><mi mathvariant="normal">Δ</mi></math> with components <math><mo stretchy="false">(</mo><msub><mi>x</mi><mi>u</mi></msub><mo>,</mo><msub><mi>y</mi><mi>u</mi></msub> <mo>,</mo><msub><mi>z</mi><mi>u</mi></msub><mo stretchy="false">)</mo></math>.<br>
* Let the equation of the plane <math><mi mathvariant="normal">Π</mi></math> as <math><mi>a</mi><mo>.</mo><mi>x</mi><mo>+</mo><mi>b</mi><mo>.</mo><mi>y</mi><mo>+</mo><mi>c</mi><mo>.</mo> <mi>z</mi><mo>+</mo><mi>d</mi><mo>=</mo><mn>0</mn></math><br>
* Let the point <math><mi>A</mi></math> at coordinates <math><mo stretchy="false">(</mo><msub><mi>x</mi><mi>A</mi></msub><mo>,</mo><msub><mi>y</mi><mi>A</mi></msub> <mo>,</mo><msub><mi>z</mi><mi>A</mi></msub><mo stretchy="false">)</mo></math> and its projection point <math><msup><mi>A</mi><mo>′</mo></msup></math> at coordinates <math><mo stretchy="false">(</mo><msub><mi>x</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub>
* <mo>,</mo><msub><mi>y</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub> <mo>,</mo><msub><mi>z</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub><mo stretchy="false">)</mo></math>.
* <p>
* Since <math><mo stretchy="false">(</mo><mi>A</mi><msup><mi>A</mi><mo>′</mo></msup><mo stretchy="false">)</mo></math> is parallel to <math><mi mathvariant="normal">Δ</mi></math>, a scalar <math><mi>k</mi></math> exists such as <math><mover><mrow><mi>A</mi><mrow><mi>A</mi><msup><mo>′</mo></msup></mrow></mrow><mo stretchy="true">→</mo></mover> <mo>=</mo><mi>k</mi><mo>⋅</mo><mover><mi>u</mi><mo
* stretchy="false">→</mo></mover></math><br>
* that <math><mrow><mo>{</mo><mtable><mtr><mtd><msub><mi>x</mi> <mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub> <mo>−</mo><msub><mi>x</mi><mi>A</mi></msub><mo>=</mo> <mi>k</mi><mo>⋅</mo><msub><mi>x</mi><mi>u</mi></msub> </mtd></mtr><mtr><mtd><msub><mi>y</mi><mrow><msup><mi>A</mi> <mo>′</mo></msup></mrow></msub><mo>−</mo><msub> <mi>y</mi><mi>A</mi></msub><mo>=</mo><mi>k</mi>
* <mo>⋅</mo><msub><mi>y</mi><mi>u</mi></msub></mtd></mtr> <mtr><mtd><msub><mi>z</mi><mrow><msup><mi>A</mi><mo>′</mo> </msup></mrow></msub><mo>−</mo><msub><mi>z</mi><mi>A</mi> </msub><mo>=</mo><mi>k</mi><mo>⋅</mo><msub><mi>z</mi> <mi>u</mi></msub></mtd></mtr></mtable></mrow></math>.
* <p>
*
* In addition, <math><msup><mi>A</mi><mo>′</mo></msup></math> is on <math><mi mathvariant="normal">Π</mi></math>, what means that <math> <mi>a</mi><mo>.</mo><msub><mi>x</mi><mrow><msup><mi>A</mi> <mo>′</mo></msup></mrow></msub><mo>+</mo><mi>b</mi> <mo>.</mo><msub><mi>y</mi><mrow><msup><mi>A</mi><mo>′</mo> </msup></mrow></msub><mo>+</mo><mi>c</mi><mo>.</mo> <msub><mi>z</mi><mrow><msup><mi>A</mi><mo>′</mo></msup>
* </mrow></msub><mo>+</mo><mi>d</mi><mo>=</mo><mn>0</mn> </math>.
* <p>
* The result is a system of 4 equations with 4 unknown variables: <math><msub><mi>x</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub><math>, <math><msub><mi>y</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub><math>, <math><msub><mi>z</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow></msub><math> and <math><mi>k</mi><math>.
* <p>
* <math> <mrow><mo>{</mo><mtable><mtr><mtd><msub><mi>x</mi><mrow> <msup><mi>A</mi><mo>′</mo></msup></mrow></msub> <mo>=</mo><mfrac><mrow><mi>b</mi><mo>⋅</mo><mo stretchy="false">(</mo><msub><mi>x</mi><mi>A</mi></msub><msub> <mi>y</mi><mi>u</mi></msub><mo>−</mo><msub><mi>y</mi> <mi>A</mi></msub><msub><mi>x</mi><mi>u</mi></msub><mo stretchy="false">)</mo><mo>+</mo><mi>c</mi><mo>⋅</mo> <mo
* stretchy="false">(</mo><msub><mi>x</mi><mi>A</mi></msub> <msub><mi>z</mi><mi>u</mi></msub><mo>−</mo><msub><mi>z</mi> <mi>A</mi></msub><msub><mi>x</mi><mi>u</mi></msub><mo stretchy="false">)</mo><mo>−</mo><mi>d</mi><mo>⋅</mo> <msub><mi>x</mi><mi>u</mi></msub></mrow><mrow><mi>a</mi> <mo>⋅</mo><msub><mi>x</mi><mi>u</mi></msub><mo>+</mo> <mi>b</mi><mo>⋅</mo><msub><mi>y</mi><mi>u</mi></msub>
* <mo>+</mo><mi>c</mi><mo>⋅</mo><msub><mi>z</mi> <mi>u</mi></msub></mrow></mfrac></mtd></mtr><mtr><mtd><msub> <mi>y</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow> </msub><mo>=</mo><mfrac><mrow><mi>a</mi><mo>⋅</mo> <mo stretchy="false">(</mo><msub><mi>y</mi><mi>A</mi></msub> <msub><mi>x</mi><mi>u</mi></msub><mo>−</mo><msub><mi>x</mi> <mi>A</mi></msub><msub><mi>y</mi><mi>u</mi></msub><mo
* stretchy="false">)</mo><mo>+</mo><mi>c</mi><mo>⋅</mo> <mo stretchy="false">(</mo><msub><mi>y</mi><mi>A</mi></msub> <msub><mi>z</mi><mi>u</mi></msub><mo>−</mo><msub><mi>z</mi> <mi>A</mi></msub><msub><mi>y</mi><mi>u</mi></msub><mo stretchy="false">)</mo><mo>−</mo><mi>d</mi><mo>⋅</mo> <msub><mi>y</mi><mi>u</mi></msub></mrow><mrow><mi>a</mi> <mo>⋅</mo><msub><mi>x</mi><mi>u</mi></msub><mo>+</mo>
* <mi>b</mi><mo>⋅</mo><msub><mi>y</mi><mi>u</mi></msub> <mo>+</mo><mi>c</mi><mo>⋅</mo><msub><mi>z</mi> <mi>u</mi></msub></mrow></mfrac></mtd></mtr><mtr><mtd><msub> <mi>z</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow> </msub><mo>=</mo><mfrac><mrow><mi>a</mi><mo>⋅</mo> <mo stretchy="false">(</mo><msub><mi>z</mi><mi>A</mi></msub> <msub><mi>x</mi><mi>u</mi></msub><mo>−</mo><msub><mi>x</mi>
* <mi>A</mi></msub><msub><mi>z</mi><mi>u</mi></msub><mo stretchy="false">)</mo><mo>+</mo><mi>b</mi><mo>⋅</mo> <mo stretchy="false">(</mo><msub><mi>z</mi><mi>A</mi></msub> <msub><mi>y</mi><mi>u</mi></msub><mo>−</mo><msub><mi>y</mi> <mi>A</mi></msub><msub><mi>z</mi><mi>u</mi></msub><mo stretchy="false">)</mo><mo>−</mo><mi>d</mi><mo>⋅</mo> <msub><mi>z</mi><mi>u</mi></msub></mrow><mrow><mi>a</mi>
* <mo>⋅</mo><msub><mi>x</mi><mi>u</mi></msub><mo>+</mo> <mi>b</mi><mo>⋅</mo><msub><mi>y</mi><mi>u</mi></msub> <mo>+</mo><mi>c</mi><mo>⋅</mo><msub><mi>z</mi> <mi>u</mi></msub></mrow></mfrac></mtd></mtr></mtable></mrow> </math>
* <p>
* In the case of an orthogonal projection and if the reference axis are orthonormal, one can choose <math><msub><mi>x</mi><mi>u</mi></msub><mo>=</mo><mi>a</mi></math>, <math><msub><mi>y</mi><mi>u</mi></msub><mo>=</mo><mi>b</mi></math>, <math><msub><mi>z</mi><mi>u</mi></msub><mo>=</mo><mi>c</mi></math>, then:
* <p>
* <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><mrow> <mo>{</mo><mtable><mtr><mtd><msub><mi>x</mi><mrow><msup> <mi>A</mi><mo>′</mo></msup></mrow></msub><mo>=</mo> <mfrac><mrow><mo stretchy="false">(</mo><msup><mi>b</mi><mn>2</mn> </msup><mo>+</mo><msup><mi>c</mi><mn>2</mn></msup><mo stretchy="false">)</mo><mo>⋅</mo><msub><mi>x</mi><mi>A</mi> </msub><mo>−</mo><mi>a</mi><mi>b</mi><mo>⋅</mo>
* <msub><mi>y</mi><mi>A</mi></msub><mo>−</mo><mi>a</mi> <mi>c</mi><mo>⋅</mo><msub><mi>z</mi><mi>A</mi></msub> <mo>−</mo><mi>d</mi><mo>⋅</mo><mi>a</mi></mrow> <mrow><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo><msup> <mi>b</mi><mn>2</mn></msup><mo>+</mo><msup><mi>c</mi> <mn>2</mn></msup></mrow></mfrac></mtd></mtr><mtr><mtd><msub> <mi>y</mi><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow>
* </msub><mo>=</mo><mfrac><mrow><mo>−</mo><mi>a</mi> <mi>b</mi><mo>⋅</mo><msub><mi>x</mi><mi>A</mi></msub> <mo>+</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mn>2</mn> </msup><mo>+</mo><msup><mi>c</mi><mn>2</mn></msup><mo stretchy="false">)</mo><mo>⋅</mo><msub><mi>y</mi><mi>A</mi> </msub><mo>−</mo><mi>b</mi><mi>c</mi><mo>⋅</mo> <msub><mi>z</mi><mi>A</mi></msub><mo>−</mo><mi>d</mi>
* <mo>⋅</mo><mi>b</mi></mrow><mrow><msup><mi>a</mi><mn>2</mn> </msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup> <mo>+</mo><msup><mi>c</mi><mn>2</mn></msup></mrow> </mfrac></mtd></mtr><mtr><mtd><msub><mi>z</mi><mrow><msup><mi>A</mi> <mo>′</mo></msup></mrow></msub><mo>=</mo><mfrac> <mrow><mo>−</mo><mi>a</mi><mi>c</mi><mo>⋅</mo> <msub><mi>x</mi><mi>A</mi></msub><mo>−</mo><mi>b</mi>
* <mi>c</mi><mo>⋅</mo><msub><mi>y</mi><mi>A</mi></msub> <mo>+</mo><mo stretchy="false">(</mo><msup><mi>a</mi><mn>2</mn> </msup><mo>+</mo><msup><mi>b</mi><mn>2</mn></msup><mo stretchy="false">)</mo><mo>⋅</mo><msub><mi>z</mi><mi>A</mi> </msub><mo>−</mo><mi>d</mi><mo>⋅</mo><mi>c</mi> </mrow><mrow><msup><mi>a</mi><mn>2</mn></msup><mo>+</mo> <msup><mi>b</mi><mn>2</mn></msup><mo>+</mo><msup><mi>c</mi>
* <mn>2</mn></msup></mrow></mfrac></mtd></mtr></mtable></mrow> </math>
* <p>
* <strong>Second Approach: vectorial resolution</strong>
* <p>
* Let the normal of the plane be <math><mover><mi>n</mi><mo stretchy="false">→</mo></mover></math> with the coordinates <math><mo stretchy="false">(</mo><msub><mi>n</mi><mi>x</mi></msub><mo>,</mo> <msub><mi>n</mi><mi>y</mi></msub><mo>,</mo><msub><mi>n</mi><mi>z</mi></msub> <mo stretchy="false">)</mo></math>.<br>
* Let <math><mi>A</mi></math> the point of coordinates <math><mo stretchy="false">(</mo><msub><mi>A</mi><mi>x</mi></msub><mo>,</mo> <msub><mi>A</mi><mi>y</mi></msub><mo>,</mo><msub><mi>A</mi><mi>z</mi></msub> <mo stretchy="false">)</mo></math> and its projection on the plane <math><msup><mi>A</mi><mo>′</mo></msup></math> with the coordinates <math><mo
* stretchy="false">(</mo><msub><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow><mi>x</mi></msub> <mo>,</mo><msub><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow><mi>y</mi></msub> <mo>,</mo><msub><mrow><msup><mi>A</mi><mo>′</mo></msup></mrow><mi>z</mi></msub> <mo stretchy="false">)</mo></math>.
* <p>
* Let <math><mi>s</mi></math> the distance between the point <math><mi>A</mi></math> and the nearest point on the plane, ie. the point <math><msup><mi>A</mi><mo>′</mo></msup></math> such as: <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><mi>s</mi><mo>=</mo> <mi>a</mi><mo>.</mo><msub><mi>A</mi><mi>x</mi></msub> <mo>+</mo><mi>b</mi><mo>.</mo><msub><mi>A</mi><mi>y</mi> </msub><mo>+</mo><mi>c</mi><mo>.</mo><msub><mi>A</mi>
* <mi>z</mi></msub><mo>+</mo><mi>d</mi></math>. If <math><mi>s</mi></math> is positive, the point is in the front of the plane. If <math><mi>s</mi></math> is negative, the point is behind the plane.
* <p>
* Consequently <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"><msup><mi>A</mi> <mo>′</mo></msup><mo>=</mo><mi>A</mi><mo>−</mo> <mfrac><mrow><mi>s</mi></mrow><mrow><mo stretchy="false">|</mo> <mover><mrow><mrow><mi>n</mi></mrow></mrow><mo stretchy="false">→</mo></mover><mo stretchy="false">|</mo> </mrow></mfrac><mover><mrow><mrow><mi>n</mi></mrow></mrow><mo stretchy="false">→</mo></mover></math>.
* <p>
* <math display="block" xmlns="http://www.w3.org/1998/Math/MathML"> <mrow> <mo>{</mo> <mtable> <mtr> <mtd> <msub> <mi>x</mi> <mrow> <msup> <mi>A</mi> <mo>′</mo> </msup> </mrow> </msub> <mo>=</mo> <msub> <mi>x</mi> <mi>A</mi> </msub> <mo>−</mo> <mfrac> <mrow> <mi>s</mi> </mrow> <mrow> <mo stretchy="false">|</mo> <mover> <mrow> <mrow> <mi>n</mi> </mrow> </mrow> <mo stretchy="false">→</mo> </mover> <mo
* stretchy="false">|</mo> </mrow> </mfrac> <msub> <mi>n</mi> <mi>x</mi> </msub> </mtd> </mtr> <mtr> <mtd> <msub> <mi>y</mi> <mrow> <msup> <mi>A</mi> <mo>′</mo> </msup> </mrow> </msub> <mo>=</mo> <msub> <mi>y</mi> <mi>A</mi> </msub> <mo>−</mo> <mfrac> <mrow> <mi>s</mi> </mrow> <mrow> <mo stretchy="false">|</mo> <mover> <mrow> <mrow> <mi>n</mi> </mrow> </mrow> <mo stretchy="false">→</mo> </mover> <mo
* stretchy="false">|</mo> </mrow> </mfrac> <msub> <mi>n</mi> <mi>y</mi> </msub> </mtd> </mtr> <mtr> <mtd> <msub> <mi>z</mi> <mrow> <msup> <mi>A</mi> <mo>′</mo> </msup> </mrow> </msub> <mo>=</mo> <msub> <mi>z</mi> <mi>A</mi> </msub> <mo>−</mo> <mfrac> <mrow> <mi>s</mi> </mrow> <mrow> <mo stretchy="false">|</mo> <mover> <mrow> <mrow> <mi>n</mi> </mrow> </mrow> <mo stretchy="false">→</mo> </mover> <mo
* stretchy="false">|</mo> </mrow> </mfrac> <msub> <mi>n</mi> <mi>z</mi> </msub> </mtd> </mtr> </mtable> </mrow> </math>
*
* @param a the a component of the plane equation.
* @param b the b component of the plane equation.
* @param c the c component of the plane equation.
* @param d the d component of the plane equation.
* @param x the x coordinate of the project to project on the plane.
* @param y the y coordinate of the project to project on the plane.
* @param z the z coordinate of the project to project on the plane.
* @return the projection of the specified point on the plane.
*/
@Pure
public static Point3d computePointProjection(
double a, double b, double c, double d,
double x, double y, double z) {
// Arithmetic resolution
/*
* plane.normalize();
*
* Vector3d n = plane.getNormal(); double d = plane.getEquationComponentD(); // normalization apply that a*a+b*b+c*c = 1
*
* double xaprime = (n.y*n.y+n.z*n.z)*px -n.x*n.y*py -n.x*n.z*pz -d*n.x;
*
* double yaprime = -n.x*n.y*px +(n.x*n.x+n.z*n.z)*py +n.y*n.z*pz -d*n.y;
*
* double zaprime = -n.x*n.z*px +n.y*n.z*py +(n.x*n.x+n.y*n.y)*pz -d*n.z;
*
* return new Point3d(xaprime,yaprime,zaprime);
*/
// Vectorial resolution
Vector3d invnormal = new Vector3d(-a, -b, -c);
invnormal.normalize();
// Distance between the point and the plane
double distance = a * x + b * y + c * z + d;
double xaprime = x + distance * invnormal.getX();
double yaprime = y + distance * invnormal.getY();
double zaprime = z + distance * invnormal.getZ();
return new Point3d(xaprime, yaprime, zaprime);
}
/** Clear buffered values.
*/
abstract protected void clearBufferedValues();
/** {@inheritDoc}
*/
@Override
public void negate() {
this.set(-getEquationComponentA(), -getEquationComponentB(),- getEquationComponentC(), getEquationComponentD());
}
/** {@inheritDoc}
*/
@Override
public void absolute() {
this.set(Math.abs(getEquationComponentA()), Math.abs(getEquationComponentB()), Math.abs(getEquationComponentC()), Math.abs(getEquationComponentD()));
}
/** {@inheritDoc}
*/
@Override
public AbstractPlane4F normalize() {
double t = Math.sqrt(this.getEquationComponentA()*this.getEquationComponentA()+this.getEquationComponentB()*this.getEquationComponentB()+this.getEquationComponentC()*this.getEquationComponentC());
this.set(getEquationComponentA()/t, getEquationComponentB()/t, getEquationComponentC()/t, getEquationComponentD()/t);
return this;
}
/** {@inheritDoc}
*/
@Override
abstract public void set(Plane3D<?> plane);
/** Set this pane to be coplanar with all the three specified points.
*
* @param p1x is a point on the plane
* @param p1y is a point on the plane
* @param p1z is a point on the plane
* @param p2x is a point on the plane
* @param p2y is a point on the plane
* @param p2z is a point on the plane
* @param p3x is a point on the plane
* @param p3y is a point on the plane
* @param p3z is a point on the plane
*/
abstract public void set(double p1x, double p1y, double p1z, double p2x, double p2y, double p2z, double p3x, double p3y, double p3z);
/** Set this pane to be coplanar with all the three specified points.
*
* @param p1 is a point on the plane
* @param p2 is a point on the plane
* @param p3 is a point on the plane
*/
abstract public void set(Point3D p1, Point3D p2, Point3D p3);
/** Set this pane with the given factors.
*
* @param a is the first factor of the plane equation.
* @param b is the first factor of the plane equation.
* @param c is the first factor of the plane equation.
* @param d is the first factor of the plane equation.
*/
abstract public void set(double a, double b, double c, double d);
/** {@inheritDoc}
*/
@Pure
@Override
abstract public FunctionalVector3D getNormal();
/** {@inheritDoc}
*/
@Pure
@Override
abstract public double getEquationComponentA();
/** {@inheritDoc}
*/
@Pure
@Override
abstract public double getEquationComponentB();
/** {@inheritDoc}
*/
@Pure
@Override
abstract public double getEquationComponentC();
/** {@inheritDoc}
*/
@Pure
@Override
abstract public double getEquationComponentD();
abstract protected void setEquationComponentC(double z);
abstract protected void setEquationComponentB(double y);
abstract protected void setEquationComponentA(double x);
abstract protected void setEquationComponentD(double w);
/** {@inheritDoc}
*/
@Pure
@Override
public double distanceTo(double x, double y, double z) {
return this.getEquationComponentA() * x + this.getEquationComponentB() * y + this.getEquationComponentC() * z + this.getEquationComponentD();
}
/** {@inheritDoc}
*/
@Override
public void clear() {
this.set(0f,0f,0f,0f);
}
@Override
abstract public void setPivot(double x, double y, double z);
/** Replies the pivot point around which the rotation must be done.
*
* @return a reference on the buffered pivot point.
*/
abstract public FunctionalPoint3D getPivot();
@Pure
@Override
abstract public FunctionalPoint3D getProjection(double x, double y, double z);
/** Apply the given transformation matrix on the plane.
* The pivot point used for transforming this plane with
* the given matrix is given by {@link #getPivot()}.
*
* @param transform the transformation matrix.
*/
public void transform(Transform3D transform) {
transform(transform, null);
}
/** Apply the given transformation matrix on the plane.
*
* @param transform the transformation matrix.
* @param pivot the pivot point.
*/
public void transform(Transform3D transform, Point3D pivot) {
Point3D refPoint = (pivot == null) ? getPivot() : pivot;
Vector3f v = new Vector3f(this.getEquationComponentA(),this.getEquationComponentB(),this.getEquationComponentC());
transform.transform(v);
// Update the plane equation according
// to the desired normal (computed from
// the identity vector and the rotations).
// a.x + b.y + c.z + d = 0
// where (x,y,z) is the translation point
this.set(v.getX(),v.getY(),v.getZ(),- (this.getEquationComponentA()*(refPoint.getX()+transform.m03) +
this.getEquationComponentB()*(refPoint.getY()+transform.m13) +
this.getEquationComponentC()*(refPoint.getZ()+transform.m23)));
clearBufferedValues();
}
/** Translate the pivot point of the plane.
*
* @param translation the translation to apply.
*/
public void translate(Vector3D translation) {
translate(translation.getX(), translation.getY(), translation.getZ());
}
/** Translate the pivot point of the plane.
*
* @param dx the translation to apply.
* @param dy the translation to apply.
* @param dz the translation to apply.
*/
public void translate(double dx, double dy, double dz) {
// Compute the reference point for the plane
// (usefull for translation)
Point3f refPoint = (Point3f) getPivot();
// a.x + b.y + c.z + d = 0
// where (x,y,z) is the translation point
setPivot(refPoint.getX()+dx,refPoint.getY()+dy,refPoint.getZ()+dz);
}
/** Rotate the plane around the pivot point.
*
* @param rotation the rotation to apply.
*/
public void rotate(Quaternion rotation) {
rotate(rotation, null);
}
/** Rotate the plane around the given pivot point.
*
* @param rotation the rotation to apply.
* @param pivot the pivot point.
*/
public void rotate(Quaternion rotation, Point3D pivot) {
Point3D currentPivot = getPivot();
// Update the plane equation according
// to the desired normal (computed from
// the identity vector and the rotations).
Transform3D m = new Transform3D();
m.setRotation(rotation);
Vector3f v = new Vector3f(this.getEquationComponentA(),this.getEquationComponentB(),this.getEquationComponentC());
m.transform(v);
this.setEquationComponentA(v.getX());
this.setEquationComponentB(v.getY());
this.setEquationComponentC(v.getZ());
if (pivot==null) {
// a.x + b.y + c.z + d = 0
// where (x,y,z) is the translation point
this.setEquationComponentD( - (this.getEquationComponentA()*currentPivot.getX() +
this.getEquationComponentB()*currentPivot.getY() +
this.getEquationComponentC()*currentPivot.getZ()));
}
else {
// Compute the new point
Point3f nP = new Point3f(
currentPivot.getX() - pivot.getX(),
currentPivot.getY() - pivot.getY(),
currentPivot.getZ() - pivot.getZ());
m.transform(nP);
nP.setX(nP.getX() + pivot.getX());
nP.setY(nP.getY() + pivot.getY());
nP.setZ(nP.getZ() + pivot.getZ());
// a.x + b.y + c.z + d = 0
// where (x,y,z) is the translation point
this.setEquationComponentD( - (this.getEquationComponentA()*nP.getX() +
this.getEquationComponentB()*nP.getY() +
this.getEquationComponentC()*nP.getZ()));
}
clearBufferedValues();
}
/** Rotate the plane with the given angle around the given axis.
* The rotation is done around the pivot point.
*
* @param axis the rotation axis.
* @param angle the rotation angle.
*/
public void rotate(Vector3D axis, double angle) {
Quaternion q = new Quaternion();
q.setAxisAngle(axis, angle);
rotate(q, null);
}
/** Rotate the plane with the given angle around the given axis.
* The rotation is done around the pivot point.
*
* @param axis the rotation axis.
* @param angle the rotation angle.
* @param pivot the pivot point.
*/
public void rotate(Vector3D axis, double angle, Point3D pivot) {
Quaternion q = new Quaternion();
q.setAxisAngle(axis, angle);
rotate(q, pivot);
}
@SuppressWarnings("static-method")
@Pure
public boolean isValid() {
// TODO Auto-generated method stub
return false;
}
@Pure
public boolean equals(Plane4f plane) {
return (plane.a == this.getEquationComponentA() && plane.b == this.getEquationComponentB() && plane.c == this.getEquationComponentC() && plane.d == this.getEquationComponentD());
}
@Pure
@Override
public boolean equals(Object t1) {
try {
AbstractPlane4F m2 = (AbstractPlane4F) t1;
return (m2.getEquationComponentA() == this.getEquationComponentA() && m2.getEquationComponentB() == this.getEquationComponentB() && m2.getEquationComponentC() == this.getEquationComponentC() && m2.getEquationComponentD() == this.getEquationComponentD());
} catch (ClassCastException | NullPointerException e1) {
return false;
}
}
@Pure
@Override
public int hashCode() {
// TODO Auto-generated method stub
return super.hashCode();
}
}