/* * $Id$ * * Copyright (C) 2010-2013 Hamza JAFFALI. * * 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 java.lang.ref.WeakReference; import java.util.concurrent.Callable; import org.arakhne.afc.math.geometry.d3.FunctionalVector3D; import org.arakhne.afc.math.geometry.d3.Point3D; import org.arakhne.afc.math.geometry.d3.Tuple3D; import org.arakhne.afc.math.geometry.d3.Vector3D; import org.eclipse.xtext.xbase.lib.Pure; import javafx.beans.binding.Bindings; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleDoubleProperty; /**This class represents a 3D plane. * * @author $Author: hjaffali$ * @version $FullVersion$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ */ public class Plane4d extends AbstractPlane4F { private static final long serialVersionUID = -934785950628401429L; /** equation coefficient A. */ protected DoubleProperty aProperty; /** equation coefficient B. */ protected DoubleProperty bProperty; /** equation coefficient C. */ protected DoubleProperty cProperty; /** equation coefficient D. */ protected DoubleProperty dProperty; /** Cached pivot point. */ private transient WeakReference<Point3d> cachedPivot = null; /** * */ public Plane4d() { this(1,0,0,0); } /** * @param a is the plane equation coefficient * @param b is the plane equation coefficient * @param c is the plane equation coefficient * @param d is the plane equation coefficient */ public Plane4d(double a, double b, double c, double d) { this.aProperty = new SimpleDoubleProperty(a); this.bProperty = new SimpleDoubleProperty(b); this.cProperty = new SimpleDoubleProperty(c); this.dProperty = new SimpleDoubleProperty(d); normalize(); } /** * @param a is the plane equation coefficient * @param b is the plane equation coefficient * @param c is the plane equation coefficient * @param d is the plane equation coefficient */ public Plane4d(DoubleProperty a, DoubleProperty b, DoubleProperty c, DoubleProperty d) { this.aProperty = a; this.bProperty = b; this.cProperty = c; this.dProperty = d; normalize(); } /** * @param normal is the normal of the plane. * @param p is a point which lies on the plane. */ public Plane4d(Vector3D normal, Point3D p) { this(normal.getX(), normal.getY(), normal.getZ(), p.getX(), p.getY(), p.getZ()); } /**The dProperty is binded to the properties of a,b,c coefficients, and to the Point3d point in parameter. * * If the point moves, the coefficient d will change. On the other hand, if the d coefficient change, the * point will not be affected * * @param normal is the normal of the plane. * @param p is a point which lies on the plane. */ public Plane4d(Vector3d normal, Point3d p) { this.aProperty = normal.xProperty; this.bProperty = normal.yProperty; this.cProperty = normal.zProperty; normalize(); // a.x + b.y + c.z + d = 0 // where (x,y,z) is the translation point this.dProperty = new SimpleDoubleProperty(); this.dProperty.bind(Bindings.createDoubleBinding(new Callable<Double>() { @Override public Double call() throws Exception { return new Double(- (Plane4d.this.aProperty.doubleValue()*p.xProperty.doubleValue()+ Plane4d.this.bProperty.doubleValue()*p.yProperty.doubleValue() + Plane4d.this.cProperty.doubleValue()*p.zProperty.doubleValue())); } }, this.aProperty, this.bProperty, this.cProperty,p.xProperty,p.yProperty,p.zProperty)); } /** * @param a is the plane equation coefficient * @param b is the plane equation coefficient * @param c is the plane equation coefficient * @param px is the x coordinate of a point which lies on the plane. * @param py is the x coordinate of a point which lies on the plane. * @param pz is the x coordinate of a point which lies on the plane. */ public Plane4d(double a, double b, double c, double px, double py, double pz) { this.aProperty = new SimpleDoubleProperty(a); this.bProperty = new SimpleDoubleProperty(b); this.cProperty = new SimpleDoubleProperty(c); normalize(); // a.x + b.y + c.z + d = 0 // where (x,y,z) is the translation point this.dProperty = new SimpleDoubleProperty(- (this.getEquationComponentA()*px + this.getEquationComponentB()*py + this.getEquationComponentC()*pz)); } /** * @param plane is the plane to copy */ public Plane4d(Plane3D<?> plane) { this(plane.getEquationComponentA(),plane.getEquationComponentB(),plane.getEquationComponentC(),plane.getEquationComponentD()); } /** * @param plane is the plane to bind properties */ public Plane4d(Plane4d plane) { this(plane.aProperty,plane.bProperty,plane.cProperty,plane.dProperty); } /** * @param p1 is a point on the plane * @param p2 is a point on the plane * @param p3 is a point on the plane */ public Plane4d(Tuple3D<?> p1, Tuple3D<?> p2, Tuple3D<?> p3) { set(p1.getX(), p1.getY(), p1.getZ(), p2.getX(), p2.getY(), p2.getZ(), p3.getX(), p3.getY(), p3.getZ()); } /** * @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 */ public Plane4d(double p1x, double p1y, double p1z, double p2x, double p2y, double p2z, double p3x, double p3y, double p3z) { this(); set(p1x, p1y, p1z, p2x, p2y, p2z, p3x, p3y, p3z); } /** {@inheritDoc} */ @Override public void set(Plane3D<?> plane) { this.aProperty.set(plane.getEquationComponentA()); this.bProperty.set(plane.getEquationComponentB()); this.cProperty.set(plane.getEquationComponentC()); this.dProperty.set(plane.getEquationComponentD()); normalize(); } /** 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 */ @Override public void set(double p1x, double p1y, double p1z, double p2x, double p2y, double p2z, double p3x, double p3y, double p3z) { Vector3d v = new Vector3d(); FunctionalVector3D.crossProduct( p2x-p1x, p2y-p1y, p2z-p1z, p3x-p1x, p3y-p1y, p3z-p1z, v); this.aProperty.set(v.getX()); this.bProperty.set(v.getY()); this.cProperty.set(v.getZ()); this.dProperty.set(- (this.getEquationComponentA() * p1x + this.getEquationComponentB() * p1y + this.getEquationComponentC() * p1z)); normalize(); } /** 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 */ @Override public void set(Point3D p1, Point3D p2, Point3D p3) { set(p1.getX(), p1.getY(), p1.getZ(), p2.getX(), p2.getY(), p2.getZ(), p3.getX(), p3.getY(), p3.getZ()); } /** 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. */ public void set(double a, double b, double c, double d) { this.aProperty.set(a); this.bProperty.set(b); this.cProperty.set(c); this.dProperty.set(d); clearBufferedValues(); } /** {@inheritDoc} */ @Pure @Override public Vector3d getNormal() { return new Vector3d(this.aProperty,this.bProperty,this.cProperty); } /** {@inheritDoc} */ @Pure public Vector3f getNormalWithoutProperties() { return new Vector3f(this.getEquationComponentA(),this.getEquationComponentB(),this.getEquationComponentC()); } /** {@inheritDoc} */ @Pure @Override public double getEquationComponentA() { return this.aProperty.doubleValue(); } /** {@inheritDoc} */ @Pure @Override public double getEquationComponentB() { return this.bProperty.doubleValue(); } /** {@inheritDoc} */ @Pure @Override public double getEquationComponentC() { return this.cProperty.doubleValue(); } /** {@inheritDoc} */ @Pure @Override public double getEquationComponentD() { return this.dProperty.doubleValue(); } @Override public void setPivot(double x, double y, double z) { clearBufferedValues(); // a.x + b.y + c.z + d = 0 // where (x,y,z) is the translation point this.unBindEquationComponentD(); this.dProperty.set(- (this.getEquationComponentA()*x + this.getEquationComponentB()*y + this.getEquationComponentC()*z)); this.cachedPivot = new WeakReference<>(new Point3d(x, y, z)); } public void setPivotProperties(Point3d pivot) { clearBufferedValues(); // a.x + b.y + c.z + d = 0 // where (x,y,z) is the translation point this.unBindEquationComponentD(); this.dProperty.bind(Bindings.createDoubleBinding(new Callable<Double>() { @Override public Double call() throws Exception { return new Double(- (Plane4d.this.aProperty.doubleValue()*pivot.xProperty.doubleValue()+ Plane4d.this.bProperty.doubleValue()*pivot.yProperty.doubleValue() + Plane4d.this.cProperty.doubleValue()*pivot.zProperty.doubleValue())); } }, this.aProperty, this.bProperty, this.cProperty,pivot.xProperty,pivot.yProperty,pivot.zProperty)); this.cachedPivot = new WeakReference<>(pivot); } /** Replies the pivot point around which the rotation must be done. * * @return a reference on the buffered pivot point. */ @Override public Point3d getPivot() { Point3d pivot = this.cachedPivot == null ? null : this.cachedPivot.get(); if (pivot==null) { pivot = getProjection(0., 0., 0.); this.cachedPivot = new WeakReference<>(pivot); } return pivot; } /** Unbind the d equation component from the previous point */ protected void unBindEquationComponentD() { this.dProperty.unbind(); } /** Clear buffered values. */ @Override protected void clearBufferedValues() { this.cachedPivot = null; } @Pure @Override public Point3d getProjection(double x, double y, double z) { return computePointProjection( getEquationComponentA(), getEquationComponentB(), getEquationComponentC(), getEquationComponentD(), x, y, z); } @Override protected void setEquationComponentC(double z) { this.cProperty.set(z); } @Override protected void setEquationComponentB(double y) { this.bProperty.set(y); } @Override protected void setEquationComponentA(double x) { this.aProperty.set(x); } @Override protected void setEquationComponentD(double w) { this.dProperty.set(w); } protected void setEquationComponentCProperty(DoubleProperty c) { this.cProperty = c; } protected void setEquationComponentBProperty(DoubleProperty b) { this.bProperty = b; } protected void setEquationComponentAProperty(DoubleProperty a) { this.aProperty = a; } protected void setEquationComponentDProperty(DoubleProperty d) { this.dProperty = d; } }