triangle.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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
19  for more details.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "triangle.H"
27 #include "triPoints.H"
28 #include "plane.H"
29 
30 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
31 
32 template<class Point, class PointRef>
33 template<class AboveOp, class BelowOp>
35 (
36  const plane& pl,
37  const triPoints& tri,
38  AboveOp& aboveOp,
39  BelowOp& belowOp
40 )
41 {
42  // distance to cutting plane
44 
45  // determine how many of the points are above the cutting plane
46  label nPos = 0;
47  label posI = -1;
48  label negI = -1;
49  forAll(tri, i)
50  {
51  d[i] = ((tri[i] - pl.refPoint()) & pl.normal());
52 
53  if (d[i] > 0)
54  {
55  nPos++;
56  posI = i;
57  }
58  else
59  {
60  negI = i;
61  }
62  }
63 
64  if (nPos == 3)
65  {
66  aboveOp(tri);
67  }
68  else if (nPos == 2)
69  {
70  // point under the plane
71  label i0 = negI;
72 
73  // indices of remaining points
74  label i1 = d.fcIndex(i0);
75  label i2 = d.fcIndex(i1);
76 
77  // determine the two intersection points
78  point p01 = planeIntersection(d, tri, i0, i1);
79  point p02 = planeIntersection(d, tri, i0, i2);
80 
81  aboveOp(triPoints(tri[i1], tri[i2], p02));
82  aboveOp(triPoints(tri[i1], p02, p01));
83  belowOp(triPoints(tri[i0], p01, p02));
84  }
85  else if (nPos == 1)
86  {
87  // point above the plane
88  label i0 = posI;
89 
90  // indices of remaining points
91  label i1 = d.fcIndex(i0);
92  label i2 = d.fcIndex(i1);
93 
94  // determine the two intersection points
95  point p01 = planeIntersection(d, tri, i0, i1);
96  point p02 = planeIntersection(d, tri, i0, i2);
97 
98  belowOp(triPoints(tri[i1], tri[i2], p02));
99  belowOp(triPoints(tri[i1], p02, p01));
100  aboveOp(triPoints(tri[i0], p01, p02));
101  }
102  else
103  {
104  // All below
105  belowOp(tri);
106  }
107 }
108 
109 
110 template<class Point, class PointRef>
111 template<class AboveOp, class BelowOp>
113 (
114  const plane& pl,
115  AboveOp& aboveOp,
116  BelowOp& belowOp
117 ) const
118 {
119  triSliceWithPlane(pl, triPoints(a_, b_, c_), aboveOp, belowOp);
120 }
121 
122 
123 template<class Point, class PointRef>
124 template<class InsideOp, class OutsideOp>
126 (
127  const vector& n,
128  const triangle<Point, PointRef>& tgt,
129  InsideOp& insideOp,
130  OutsideOp& outsideOp
131 ) const
132 {
133  // There are two possibilities with this algorithm - we either cut
134  // the outside triangles with all the edges or not (and keep them
135  // as disconnected triangles). In the first case
136  // we cannot do any evaluation short cut so we've chosen not to re-cut
137  // the outside triangles.
138 
139 
140  triIntersectionList insideTrisA;
141  label nInsideA = 0;
142  storeOp insideOpA(insideTrisA, nInsideA);
143 
144  triIntersectionList outsideTrisA;
145  label nOutsideA = 0;
146  storeOp outsideOpA(outsideTrisA, nOutsideA);
147 
148 
149  const triPoints thisTri(a_, b_, c_);
150 
151 
152  // Cut original triangle with tgt edge 0.
153  // From *this to insideTrisA, outsideTrisA.
154  {
155  scalar s = Foam::mag(tgt.b() - tgt.a());
156  const plane pl0(tgt.a(), tgt.b(), tgt.b() + s*n);
157  triSliceWithPlane(pl0, thisTri, insideOpA, outsideOpA);
158  }
159 
160  // Shortcut if nothing cut
161 
162  if (insideOpA.nTris_ == 0)
163  {
164  outsideOp(thisTri);
165  return;
166  }
167 
168  if (outsideOpA.nTris_ == 0)
169  {
170  insideOp(thisTri);
171  return;
172  }
173 
174 
175  // Cut all triangles with edge 1.
176  // From insideTrisA to insideTrisB, outsideTrisA
177 
178  triIntersectionList insideTrisB;
179  label nInsideB = 0;
180  storeOp insideOpB(insideTrisB, nInsideB);
181 
182  //triIntersectionList outsideTrisB;
183  //label nOutsideB = 0;
184  //storeOp outsideOpB(outsideTrisB, nOutsideB);
185 
186  {
187  scalar s = Foam::mag(tgt.c() - tgt.b());
188  const plane pl0(tgt.b(), tgt.c(), tgt.c() + s*n);
189 
190  for (label i = 0; i < insideOpA.nTris_; i++)
191  {
192  const triPoints& tri = insideOpA.tris_[i];
193  triSliceWithPlane(pl0, tri, insideOpB, outsideOpA);
194  }
195 
198  //for (label i = 0; i < outsideOpA.nTris_; i++)
199  //{
200  // const triPoints& tri = outsideOpA.tris_[i];
201  // triSliceWithPlane(pl0, tri, outsideOpB, outsideOpB);
202  //}
203  }
204 
205 
206  // Cut all triangles with edge 2.
207  // From insideTrisB to insideTrisA, outsideTrisA
208  {
209  scalar s = Foam::mag(tgt.a() - tgt.c());
210  const plane pl0(tgt.c(), tgt.a(), tgt.a() + s*n);
211 
212  insideOpA.nTris_ = 0;
213  //outsideOpA.nTris_ = 0;
214  for (label i = 0; i < insideOpB.nTris_; i++)
215  {
216  const triPoints& tri = insideOpB.tris_[i];
217  triSliceWithPlane(pl0, tri, insideOpA, outsideOpA);
218  }
219 
222  //for (label i = 0; i < outsideOpB.nTris_; i++)
223  //{
224  // const triPoints& tri = outsideOpB.tris_[i];
225  // triSliceWithPlane(pl0, tri, outsideOpA, outsideOpA);
226  //}
227  }
228 
229  // Transfer from A to argument
230  for (label i = 0; i < insideOpA.nTris_; i++)
231  {
232  insideOp(insideOpA.tris_[i]);
233  }
234 
235  for (label i = 0; i < outsideOpA.nTris_; i++)
236  {
237  outsideOp(outsideOpA.tris_[i]);
238  }
239 }
240 
241 
242 // ************************************************************************* //
Foam::plane::normal
const vector & normal() const
Return plane normal.
Definition: plane.C:248
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
triangle.H
triPoints.H
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::FixedList::fcIndex
label fcIndex(const label i) const
Return the forward circular index, i.e. the next index.
Definition: FixedListI.H:115
Foam::plane
Geometric class that creates a 2D plane and can return the intersection point between a line and the ...
Definition: plane.H:60
Foam::triangle
A triangle primitive used to calculate face normals and swept volumes.
Definition: triangle.H:59
n
label n
Definition: TABSMDCalcMethod2.H:31
Foam::triPoints
Triangle storage. Null constructable (unfortunately triangle<point, point> is not)
Definition: triPoints.H:49
Foam::triangle::c
const Point & c() const
Return third vertex.
Definition: triangleI.H:95
Foam::label
intWM_LABEL_SIZE_t label
A label is an int32_t or int64_t as specified by the pre-processor macro WM_LABEL_SIZE.
Definition: label.H:59
plane.H
Foam::triangle::a
const Point & a() const
Return first vertex.
Definition: triangleI.H:83
Foam::triangle::triSliceWithPlane
static void triSliceWithPlane(const plane &pl, const triPoints &tri, AboveOp &aboveOp, BelowOp &belowOp)
Helper: slice triangle with plane.
Definition: triangle.C:35
Foam::triangle::b
const Point & b() const
Return second vertex.
Definition: triangleI.H:89
s
gmvFile<< "tracers "<< particles.size()<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().x()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().y()<< " ";}gmvFile<< nl;forAllConstIter(Cloud< passiveParticle >, particles, iter){ gmvFile<< iter().position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
Foam::storeOp::tris_
DynamicList< triPoints > & tris_
Definition: isoSurface.C:52
Foam::Vector< scalar >
Foam::triangle::sliceWithPlane
void sliceWithPlane(const plane &pl, AboveOp &aboveOp, BelowOp &belowOp) const
Decompose triangle into triangles above and below plane.
Definition: triangle.C:113
Foam::FixedList< scalar, 3 >
Foam::plane::refPoint
const point & refPoint() const
Return or return plane base point.
Definition: plane.C:255
Foam::storeOp
Definition: isoSurface.C:49
Foam::triangle::triangleOverlap
void triangleOverlap(const vector &n, const triangle< Point, PointRef > &tri, InsideOp &insideOp, OutsideOp &outsideOp) const
Decompose triangle into triangles inside and outside.
Definition: triangle.C:126