1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
29 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
31 // Calculate base point and unit normal vector from plane equation
32 void Foam::plane::calcPntAndVec(const scalarList& C)
34 if (mag(C[0]) > VSMALL)
36 basePoint_ = vector((-C[3]/C[0]), 0, 0);
40 if (mag(C[1]) > VSMALL)
42 basePoint_ = vector(0, (-C[3]/C[1]), 0);
46 if (mag(C[2]) > VSMALL)
48 basePoint_ = vector(0, 0, (-C[3]/C[2]));
52 FatalErrorIn("void plane::calcPntAndVec(const scalarList&)")
53 << "At least one plane coefficient must have a value"
59 unitVector_ = vector(C[0], C[1], C[2]);
60 scalar magUnitVector(mag(unitVector_));
62 if (magUnitVector < VSMALL)
64 FatalErrorIn("void plane::calcPntAndVec(const scalarList&)")
65 << "Plane normal defined with zero length"
69 unitVector_ /= magUnitVector;
73 void Foam::plane::calcPntAndVec
80 basePoint_ = (point1 + point2 + point3)/3;
81 vector line12 = point1 - point2;
82 vector line23 = point2 - point3;
87 || mag(line23) < VSMALL
88 || mag(point3-point1) < VSMALL
93 "void plane::calcPntAndVec\n"
99 ) << "Bad points:" << point1 << ' ' << point2 << ' ' << point3
100 << abort(FatalError);
103 unitVector_ = line12 ^ line23;
104 scalar magUnitVector(mag(unitVector_));
106 if (magUnitVector < VSMALL)
110 "void plane::calcPntAndVec\n"
116 ) << "Plane normal defined with zero length" << nl
117 << "Bad points:" << point1 << ' ' << point2 << ' ' << point3
118 << abort(FatalError);
121 unitVector_ /= magUnitVector;
125 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
127 // Construct from normal vector through the origin
128 Foam::plane::plane(const vector& normalVector)
130 unitVector_(normalVector),
131 basePoint_(vector::zero)
133 scalar magUnitVector(mag(unitVector_));
135 if (magUnitVector > VSMALL)
137 unitVector_ /= magUnitVector;
141 FatalErrorIn("plane::plane(const vector&)")
142 << "plane normal has zero length. basePoint:" << basePoint_
143 << abort(FatalError);
148 // Construct from point and normal vector
149 Foam::plane::plane(const point& basePoint, const vector& normalVector)
151 unitVector_(normalVector),
152 basePoint_(basePoint)
154 scalar magUnitVector(mag(unitVector_));
156 if (magUnitVector > VSMALL)
158 unitVector_ /= magUnitVector;
162 FatalErrorIn("plane::plane(const point&, const vector&)")
163 << "plane normal has zero length. basePoint:" << basePoint_
164 << abort(FatalError);
169 // Construct from plane equation
170 Foam::plane::plane(const scalarList& C)
176 // Construct from three points
184 calcPntAndVec(a, b, c);
188 // Construct from dictionary
189 Foam::plane::plane(const dictionary& dict)
191 unitVector_(vector::zero),
192 basePoint_(point::zero)
194 const word planeType(dict.lookup("planeType"));
196 if (planeType == "planeEquation")
198 const dictionary& subDict = dict.subDict("planeEquationDict");
201 C[0] = readScalar(subDict.lookup("a"));
202 C[1] = readScalar(subDict.lookup("b"));
203 C[2] = readScalar(subDict.lookup("c"));
204 C[3] = readScalar(subDict.lookup("d"));
209 else if (planeType == "embeddedPoints")
211 const dictionary& subDict = dict.subDict("embeddedPoints");
213 point point1(subDict.lookup("point1"));
214 point point2(subDict.lookup("point2"));
215 point point3(subDict.lookup("point3"));
217 calcPntAndVec(point1, point2, point3);
219 else if (planeType == "pointAndNormal")
221 const dictionary& subDict = dict.subDict("pointAndNormalDict");
223 basePoint_ = subDict.lookup("basePoint");
224 unitVector_ = subDict.lookup("normalVector");
225 unitVector_ /= mag(unitVector_);
231 "plane::plane(const dictionary&)",
233 ) << "Invalid plane type: " << planeType
234 << abort(FatalIOError);
239 // Construct from Istream. Assumes point and normal vector.
240 Foam::plane::plane(Istream& is)
245 scalar magUnitVector(mag(unitVector_));
247 if (magUnitVector > VSMALL)
249 unitVector_ /= magUnitVector;
253 FatalErrorIn("plane::plane(Istream& is)")
254 << "plane normal has zero length. basePoint:" << basePoint_
255 << abort(FatalError);
260 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
262 // Return plane normal vector
263 const Foam::vector& Foam::plane::normal() const
269 // Return plane base point
270 const Foam::point& Foam::plane::refPoint() const
276 // Return coefficients for plane equation: ax + by + cz + d = 0
277 Foam::FixedList<Foam::scalar, 4> Foam::plane::planeCoeffs() const
279 FixedList<scalar, 4> C(4);
281 scalar magX = mag(unitVector_.x());
282 scalar magY = mag(unitVector_.y());
283 scalar magZ = mag(unitVector_.z());
290 C[1] = unitVector_.y()/unitVector_.x();
291 C[2] = unitVector_.z()/unitVector_.x();
295 C[0] = unitVector_.x()/unitVector_.z();
296 C[1] = unitVector_.y()/unitVector_.z();
304 C[0] = unitVector_.x()/unitVector_.y();
306 C[2] = unitVector_.z()/unitVector_.y();
310 C[0] = unitVector_.x()/unitVector_.z();
311 C[1] = unitVector_.y()/unitVector_.z();
316 C[3] = - C[0] * basePoint_.x()
317 - C[1] * basePoint_.y()
318 - C[2] * basePoint_.z();
324 // Return nearest point in the plane for the given point
325 Foam::point Foam::plane::nearestPoint(const point& p) const
327 return p - unitVector_*((p - basePoint_) & unitVector_);
331 // Return distance from the given point to the plane
332 Foam::scalar Foam::plane::distance(const point& p) const
334 return mag((p - basePoint_) & unitVector_);
338 // Cutting point for plane and line defined by origin and direction
339 Foam::scalar Foam::plane::normalIntersect
345 scalar denom = stabilise((dir & unitVector_), VSMALL);
347 return ((basePoint_ - pnt0) & unitVector_)/denom;
351 // Cutting line of two planes
352 Foam::plane::ray Foam::plane::planeIntersect(const plane& plane2) const
354 // Mathworld plane-plane intersection. Assume there is a point on the
355 // intersection line with z=0 and solve the two plane equations
356 // for that (now 2x2 equation in x and y)
357 // Better: use either z=0 or x=0 or y=0.
359 const vector& n1 = normal();
360 const vector& n2 = plane2.normal();
362 const point& p1 = refPoint();
363 const point& p2 = plane2.refPoint();
368 vector dir = n1 ^ n2;
370 // Determine zeroed out direction (can be x,y or z) by looking at which
371 // has the largest component in dir.
372 scalar magX = mag(dir.x());
373 scalar magY = mag(dir.y());
374 scalar magZ = mag(dir.z());
376 direction iZero, i1, i2;
412 pt[i1] = (n2[i2]*n1p1 - n1[i2]*n2p2) / (n1[i1]*n2[i2] - n2[i1]*n1[i2]);
413 pt[i2] = (n2[i1]*n1p1 - n1[i1]*n2p2) / (n1[i2]*n2[i1] - n1[i1]*n2[i2]);
419 // Cutting point of three planes
420 Foam::point Foam::plane::planePlaneIntersect
426 FixedList<scalar, 4> coeffs1(planeCoeffs());
427 FixedList<scalar, 4> coeffs2(plane2.planeCoeffs());
428 FixedList<scalar, 4> coeffs3(plane3.planeCoeffs());
432 coeffs1[0],coeffs1[1],coeffs1[2],
433 coeffs2[0],coeffs2[1],coeffs2[2],
434 coeffs3[0],coeffs3[1],coeffs3[2]
437 vector b(coeffs1[3],coeffs2[3],coeffs3[3]);
439 return (inv(a) & (-b));
443 void Foam::plane::writeDict(Ostream& os) const
445 os.writeKeyword("planeType") << "pointAndNormal"
446 << token::END_STATEMENT << nl;
447 os << indent << "pointAndNormalDict" << nl
448 << indent << token::BEGIN_BLOCK << incrIndent << nl;
449 os.writeKeyword("basePoint") << basePoint_ << token::END_STATEMENT << nl;
450 os.writeKeyword("normalVector") << unitVector_ << token::END_STATEMENT
452 os << decrIndent << indent << token::END_BLOCK << endl;
456 // * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
458 bool Foam::operator==(const plane& a, const plane& b)
460 if (a.basePoint_ == b.basePoint_ && a.unitVector_ == b.unitVector_)
470 bool Foam::operator!=(const plane& a, const plane& b)
476 // * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
478 Foam::Ostream& Foam::operator<<(Ostream& os, const plane& a)
480 os << a.unitVector_ << token::SPACE << a.basePoint_;
486 // ************************************************************************* //