1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 1991-2009 OpenCFD Ltd.
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 \*---------------------------------------------------------------------------*/
29 #include "octreeDataFaceList.H"
32 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
34 defineTypeNameAndDebug(Foam::octreeDataFaceList, 0);
36 Foam::scalar Foam::octreeDataFaceList::tol = 1E-6;
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 void Foam::octreeDataFaceList::calcBb()
43 allBb_.setSize(faceLabels_.size());
46 vector(GREAT, GREAT, GREAT),
47 vector(-GREAT, -GREAT, -GREAT)
50 forAll (faceLabels_, faceLabelI)
52 label faceI = faceLabels_[faceLabelI];
55 treeBoundBox& myBb = allBb_[faceLabelI];
57 const face& f = mesh_.localFaces()[faceI];
61 const point& coord = mesh_.localPoints()[f[fp]];
63 myBb.min() = min(myBb.min(), coord);
64 myBb.max() = max(myBb.max(), coord);
69 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
71 // Construct from all faces in bMesh
72 Foam::octreeDataFaceList::octreeDataFaceList(const bMesh& mesh)
75 faceLabels_(mesh_.size()),
78 forAll(faceLabels_, faceI)
80 faceLabels_[faceI] = faceI;
83 // Generate tight fitting bounding box
88 // Construct from selected faces in bMesh
89 Foam::octreeDataFaceList::octreeDataFaceList
92 const labelList& faceLabels
96 faceLabels_(faceLabels),
97 allBb_(faceLabels.size())
99 // Generate tight fitting bounding box
106 Foam::octreeDataFaceList::octreeDataFaceList(const octreeDataFaceList& shapes)
108 mesh_(shapes.mesh()),
109 faceLabels_(shapes.faceLabels()),
110 allBb_(shapes.allBb())
114 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
116 Foam::octreeDataFaceList::~octreeDataFaceList()
120 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
123 Foam::label Foam::octreeDataFaceList::getSampleType
125 const octree<octreeDataFaceList>& oc,
129 // Need to determine whether sample is 'inside' or 'outside'
130 // Done by finding nearest face. This gives back a face which is
131 // guaranteed to contain nearest point. This point can be
132 // - in interior of face: compare to face normal
133 // - on edge of face: compare to edge normal
134 // - on point of face: compare to point normal
135 // Unfortunately the octree does not give us back the intersection point
136 // or where on the face it has hit so we have to recreate all that
140 // Find nearest face to sample
141 treeBoundBox tightest(treeBoundBox::greatBox);
143 scalar tightestDist = GREAT;
145 label index = oc.findNearest(sample, tightest, tightestDist);
151 "octreeDataFaceList::getSampleType"
152 "(octree<octreeDataFaceList>&, const point&)"
153 ) << "Could not find " << sample << " in octree."
154 << abort(FatalError);
157 label faceI = faceLabels_[index];
159 // Get actual intersection point on face
163 Pout<< "getSampleType : sample:" << sample
164 << " nearest face:" << faceI;
167 const face& f = mesh_.localFaces()[faceI];
169 const pointField& points = mesh_.localPoints();
171 pointHit curHit = f.nearestPoint(sample, points);
174 // 1] Check whether sample is above face
179 // Simple case. Compare to face normal.
183 Pout<< " -> face hit:" << curHit.hitPoint()
184 << " comparing to face normal " << mesh_.faceNormals()[faceI]
187 return octree<octreeDataFaceList>::getVolType
189 mesh_.faceNormals()[faceI],
190 sample - curHit.hitPoint()
196 Pout<< " -> face miss:" << curHit.missPoint();
200 // 2] Check whether intersection is on one of the face vertices or
204 // typical dimension as sqrt of face area.
205 scalar typDim = sqrt(mag(f.normal(points))) + VSMALL;
209 if ((mag(points[f[fp]] - curHit.missPoint())/typDim) < tol)
211 // Face intersection point equals face vertex fp
215 Pout<< " -> face point hit :" << points[f[fp]]
216 << " point normal:" << mesh_.pointNormals()[f[fp]]
218 << mag(points[f[fp]] - curHit.missPoint())/typDim
221 return octree<octreeDataFaceList>::getVolType
223 mesh_.pointNormals()[f[fp]],
224 sample - curHit.missPoint()
230 point ctr(f.centre(points));
232 if ((mag(ctr - curHit.missPoint())/typDim) < tol)
234 // Face intersection point equals face centre. Normal at face centre
235 // is already average of face normals
239 Pout<< " -> centre hit:" << ctr
241 << mag(ctr - curHit.missPoint())/typDim
245 return octree<octreeDataFaceList>::getVolType
247 mesh_.faceNormals()[faceI],
248 sample - curHit.missPoint()
254 // 3] Get the 'real' edge the face intersection is on
257 const labelList& myEdges = mesh_.faceEdges()[faceI];
259 forAll(myEdges, myEdgeI)
261 const edge& e = mesh_.edges()[myEdges[myEdgeI]];
264 line<point, const point&>
268 ).nearestDist(sample);
273 edgePoint = edgeHit.hitPoint();
277 edgePoint = edgeHit.missPoint();
281 if ((mag(edgePoint - curHit.missPoint())/typDim) < tol)
283 // Face intersection point lies on edge e
285 // Calculate edge normal (wrong: uses face normals instead of
287 const labelList& myFaces = mesh_.edgeFaces()[myEdges[myEdgeI]];
289 vector edgeNormal(vector::zero);
291 forAll(myFaces, myFaceI)
293 edgeNormal += mesh_.faceNormals()[myFaces[myFaceI]];
298 Pout<< " -> real edge hit point:" << edgePoint
299 << " comparing to edge normal:" << edgeNormal
303 // Found face intersection point on this edge. Compare to edge
305 return octree<octreeDataFaceList>::getVolType
308 sample - curHit.missPoint()
315 // 4] Get the internal edge (vertex - faceCentre) the face intersection
322 line<point, const point&>
326 ).nearestDist(sample);
331 edgePoint = edgeHit.hitPoint();
335 edgePoint = edgeHit.missPoint();
338 if ((mag(edgePoint - curHit.missPoint())/typDim) < tol)
340 // Face intersection point lies on edge between two face triangles
342 // Calculate edge normal as average of the two triangle normals
343 label fpPrev = f.rcIndex(fp);
344 label fpNext = f.fcIndex(fp);
346 vector e = points[f[fp]] - ctr;
347 vector ePrev = points[f[fpPrev]] - ctr;
348 vector eNext = points[f[fpNext]] - ctr;
350 vector nLeft = ePrev ^ e;
351 nLeft /= mag(nLeft) + VSMALL;
353 vector nRight = e ^ eNext;
354 nRight /= mag(nRight) + VSMALL;
358 Pout<< " -> internal edge hit point:" << edgePoint
359 << " comparing to edge normal "
360 << 0.5*(nLeft + nRight)
364 // Found face intersection point on this edge. Compare to edge
366 return octree<octreeDataFaceList>::getVolType
368 0.5*(nLeft + nRight),
369 sample - curHit.missPoint()
376 Pout<< "Did not find sample " << sample
377 << " anywhere related to nearest face " << faceI << endl
382 Pout<< " vertex:" << f[fp] << " coord:" << points[f[fp]]
387 // Can't determine status of sample with respect to nearest face.
389 // - tolerances are wrong. (if e.g. face has zero area)
390 // - or (more likely) surface is not closed.
392 return octree<octreeDataFaceList>::UNKNOWN;
396 bool Foam::octreeDataFaceList::overlaps
399 const treeBoundBox& sampleBb
402 return sampleBb.overlaps(allBb_[index]);
406 bool Foam::octreeDataFaceList::contains
414 "octreeDataFaceList::contains(const label, const point&)"
420 bool Foam::octreeDataFaceList::intersects
425 point& intersectionPoint
428 label faceI = faceLabels_[index];
430 const face& f = mesh_.localFaces()[faceI];
432 const vector dir(end - start);
434 // Disable picking up intersections behind us.
435 scalar oldTol = intersection::setPlanarTol(0.0);
443 intersection::HALF_RAY,
447 intersection::setPlanarTol(oldTol);
449 if (inter.hit() && inter.distance() <= mag(dir))
451 intersectionPoint = inter.hitPoint();
462 bool Foam::octreeDataFaceList::findTightest
466 treeBoundBox& tightest
469 // Get nearest and furthest away vertex
471 allBb_[index].calcExtremities(sample, myNear, myFar);
473 const point dist = myFar - sample;
474 scalar myFarDist = mag(dist);
476 point tightestNear, tightestFar;
477 tightest.calcExtremities(sample, tightestNear, tightestFar);
479 scalar tightestFarDist = mag(tightestFar - sample);
481 if (tightestFarDist < myFarDist)
483 // Keep current tightest.
488 // Construct bb around sample and myFar
489 const point dist2(fabs(dist.x()), fabs(dist.y()), fabs(dist.z()));
491 tightest.min() = sample - dist2;
492 tightest.max() = sample + dist2;
499 // Determine numerical value of sign of sample compared to shape at index
500 Foam::scalar Foam::octreeDataFaceList::calcSign
507 label faceI = faceLabels_[index];
509 const face& f = mesh_.localFaces()[faceI];
511 point ctr = f.centre(mesh_.localPoints());
513 vector vec = sample - ctr;
515 vec /= mag(vec) + VSMALL;
517 return mesh_.faceNormals()[faceI] & vec;
521 // Calculate nearest point on/in shapei
522 Foam::scalar Foam::octreeDataFaceList::calcNearest
529 label faceI = faceLabels_[index];
531 const face& f = mesh_.localFaces()[faceI];
533 pointHit nearHit = f.nearestPoint(sample, mesh_.localPoints());
537 nearest = nearHit.hitPoint();
541 nearest = nearHit.missPoint();
546 point ctr = f.centre(mesh_.localPoints());
548 scalar sign = mesh_.faceNormals()[faceI] & (sample - nearest);
550 Pout<< "octreeDataFaceList::calcNearest : "
551 << "sample:" << sample
552 << " faceI:" << faceI
555 << " nearest point:" << nearest
556 << " distance to face:" << nearHit.distance()
559 return nearHit.distance();
563 void Foam::octreeDataFaceList::write
569 os << faceLabels_[index] << " " << allBb_[index];
573 // ************************************************************************* //