FreeFOAM The Cross-Platform CFD Toolkit
searchablePlate.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) 1991-2010 OpenCFD Ltd.
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 "searchablePlate.H"
28 #include <OpenFOAM/SortableList.H>
29 
30 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
31 
32 namespace Foam
33 {
34 
35 defineTypeNameAndDebug(searchablePlate, 0);
36 addToRunTimeSelectionTable(searchableSurface, searchablePlate, dict);
37 
38 }
39 
40 
41 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 
43 Foam::direction Foam::searchablePlate::calcNormal(const point& span)
44 {
45  direction normalDir = 3;
46 
47  for (direction dir = 0; dir < vector::nComponents; dir++)
48  {
49  if (span[dir] < 0)
50  {
51  FatalErrorIn("searchablePlate::calcNormal()")
52  << "Span should have two positive and one zero entry. Now:"
53  << span << exit(FatalError);
54  }
55  else if (span[dir] < VSMALL)
56  {
57  if (normalDir == 3)
58  {
59  normalDir = dir;
60  }
61  else
62  {
63  // Multiple zero entries. Flag and exit.
64  normalDir = 3;
65  break;
66  }
67  }
68  }
69 
70  if (normalDir == 3)
71  {
72  FatalErrorIn("searchablePlate::calcNormal()")
73  << "Span should have one and only zero entry. Now:" << span
74  << exit(FatalError);
75  }
76 
77  return normalDir;
78 }
79 
80 
81 // Returns miss or hit with face (always 0)
82 Foam::pointIndexHit Foam::searchablePlate::findNearest
83 (
84  const point& sample,
85  const scalar nearestDistSqr
86 ) const
87 {
88  // For every component direction can be
89  // left of min, right of max or inbetween.
90  // - outside points: project first one x plane (either min().x()
91  // or max().x()), then onto y plane and finally z. You should be left
92  // with intersection point
93  // - inside point: find nearest side (compare to mid point). Project onto
94  // that.
95 
96  // Project point on plane.
97  pointIndexHit info(true, sample, 0);
98  info.rawPoint()[normalDir_] = origin_[normalDir_];
99 
100  // Clip to edges if outside
101  for (direction dir = 0; dir < vector::nComponents; dir++)
102  {
103  if (dir != normalDir_)
104  {
105  if (info.rawPoint()[dir] < origin_[dir])
106  {
107  info.rawPoint()[dir] = origin_[dir];
108  }
109  else if (info.rawPoint()[dir] > origin_[dir]+span_[dir])
110  {
111  info.rawPoint()[dir] = origin_[dir]+span_[dir];
112  }
113  }
114  }
115 
116  // Check if outside. Optimisation: could do some checks on distance already
117  // on components above
118  if (magSqr(info.rawPoint() - sample) > nearestDistSqr)
119  {
120  info.setMiss();
121  info.setIndex(-1);
122  }
123 
124  return info;
125 }
126 
127 
128 Foam::pointIndexHit Foam::searchablePlate::findLine
129 (
130  const point& start,
131  const point& end
132 ) const
133 {
134  pointIndexHit info
135  (
136  true,
137  vector::zero,
138  0
139  );
140 
141  const vector dir(end-start);
142 
143  if (mag(dir[normalDir_]) < VSMALL)
144  {
145  info.setMiss();
146  info.setIndex(-1);
147  }
148  else
149  {
150  scalar t = (origin_[normalDir_]-start[normalDir_]) / dir[normalDir_];
151 
152  if (t < 0 || t > 1)
153  {
154  info.setMiss();
155  info.setIndex(-1);
156  }
157  else
158  {
159  info.rawPoint() = start+t*dir;
160  info.rawPoint()[normalDir_] = origin_[normalDir_];
161 
162  // Clip to edges
163  for (direction dir = 0; dir < vector::nComponents; dir++)
164  {
165  if (dir != normalDir_)
166  {
167  if (info.rawPoint()[dir] < origin_[dir])
168  {
169  info.setMiss();
170  info.setIndex(-1);
171  break;
172  }
173  else if (info.rawPoint()[dir] > origin_[dir]+span_[dir])
174  {
175  info.setMiss();
176  info.setIndex(-1);
177  break;
178  }
179  }
180  }
181  }
182  }
183 
184  // Debug
185  if (info.hit())
186  {
187  treeBoundBox bb(origin_, origin_+span_);
188  bb.min()[normalDir_] -= 1E-6;
189  bb.max()[normalDir_] += 1E-6;
190 
191  if (!bb.contains(info.hitPoint()))
192  {
193  FatalErrorIn("searchablePlate::findLine(..)")
194  << "bb:" << bb << endl
195  << "origin_:" << origin_ << endl
196  << "span_:" << span_ << endl
197  << "normalDir_:" << normalDir_ << endl
198  << "hitPoint:" << info.hitPoint()
199  << abort(FatalError);
200  }
201  }
202 
203  return info;
204 }
205 
206 
207 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
208 
209 Foam::searchablePlate::searchablePlate
210 (
211  const IOobject& io,
212  const point& origin,
213  const vector& span
214 )
215 :
216  searchableSurface(io),
217  origin_(origin),
218  span_(span),
219  normalDir_(calcNormal(span_))
220 {
221  if (debug)
222  {
223  Info<< "searchablePlate::searchablePlate :"
224  << " origin:" << origin_
225  << " origin+span:" << origin_+span_
226  << " normal:" << vector::componentNames[normalDir_]
227  << endl;
228  }
229 }
230 
231 
232 Foam::searchablePlate::searchablePlate
233 (
234  const IOobject& io,
235  const dictionary& dict
236 )
237 :
238  searchableSurface(io),
239  origin_(dict.lookup("origin")),
240  span_(dict.lookup("span")),
241  normalDir_(calcNormal(span_))
242 {
243  if (debug)
244  {
245  Info<< "searchablePlate::searchablePlate :"
246  << " origin:" << origin_
247  << " origin+span:" << origin_+span_
248  << " normal:" << vector::componentNames[normalDir_]
249  << endl;
250  }
251 }
252 
253 
254 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
255 
257 {}
258 
259 
260 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
261 
263 {
264  if (regions_.empty())
265  {
266  regions_.setSize(1);
267  regions_[0] = "region0";
268  }
269  return regions_;
270 }
271 
272 
273 void Foam::searchablePlate::findNearest
274 (
275  const pointField& samples,
276  const scalarField& nearestDistSqr,
277  List<pointIndexHit>& info
278 ) const
279 {
280  info.setSize(samples.size());
281 
282  forAll(samples, i)
283  {
284  info[i] = findNearest(samples[i], nearestDistSqr[i]);
285  }
286 }
287 
288 
289 void Foam::searchablePlate::findLine
290 (
291  const pointField& start,
292  const pointField& end,
293  List<pointIndexHit>& info
294 ) const
295 {
296  info.setSize(start.size());
297 
298  forAll(start, i)
299  {
300  info[i] = findLine(start[i], end[i]);
301  }
302 }
303 
304 
306 (
307  const pointField& start,
308  const pointField& end,
309  List<pointIndexHit>& info
310 ) const
311 {
312  findLine(start, end, info);
313 }
314 
315 
317 (
318  const pointField& start,
319  const pointField& end,
320  List<List<pointIndexHit> >& info
321 ) const
322 {
323  List<pointIndexHit> nearestInfo;
324  findLine(start, end, nearestInfo);
325 
326  info.setSize(start.size());
327  forAll(info, pointI)
328  {
329  if (nearestInfo[pointI].hit())
330  {
331  info[pointI].setSize(1);
332  info[pointI][0] = nearestInfo[pointI];
333  }
334  else
335  {
336  info[pointI].clear();
337  }
338  }
339 }
340 
341 
343 (
344  const List<pointIndexHit>& info,
345  labelList& region
346 ) const
347 {
348  region.setSize(info.size());
349  region = 0;
350 }
351 
352 
354 (
355  const List<pointIndexHit>& info,
357 ) const
358 {
359  normal.setSize(info.size());
360  normal = vector::zero;
361  forAll(normal, i)
362  {
363  normal[i][normalDir_] = 1.0;
364  }
365 }
366 
367 
369 (
370  const pointField& points,
371  List<volumeType>& volType
372 ) const
373 {
375  (
376  "searchableCollection::getVolumeType(const pointField&"
377  ", List<volumeType>&) const"
378  ) << "Volume type not supported for plate."
379  << exit(FatalError);
380 }
381 
382 
383 // ************************ vim: set sw=4 sts=4 et: ************************ //