surfaceFeatures.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) 2011-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 "surfaceFeatures.H"
27 #include "triSurface.H"
28 #include "indexedOctree.H"
29 #include "treeDataEdge.H"
30 #include "treeDataPoint.H"
31 #include "meshTools.H"
32 #include "linePointRef.H"
33 #include "OFstream.H"
34 #include "IFstream.H"
35 #include "unitConversion.H"
36 #include "EdgeMap.H"
37 
38 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
39 
40 namespace Foam
41 {
42 defineTypeNameAndDebug(surfaceFeatures, 0);
43 
45 }
46 
47 
48 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
49 
50 //- Get nearest point on edge and classify position on edge.
52 (
53  const point& start,
54  const point& end,
55  const point& sample
56 )
57 {
58  pointHit eHit = linePointRef(start, end).nearestDist(sample);
59 
60  // Classification of position on edge.
61  label endPoint;
62 
63  if (eHit.hit())
64  {
65  // Nearest point is on edge itself.
66  // Note: might be at or very close to endpoint. We should use tolerance
67  // here.
68  endPoint = -1;
69  }
70  else
71  {
72  // Nearest point has to be one of the end points. Find out
73  // which one.
74  if
75  (
76  mag(eHit.rawPoint() - start)
77  < mag(eHit.rawPoint() - end)
78  )
79  {
80  endPoint = 0;
81  }
82  else
83  {
84  endPoint = 1;
85  }
86  }
87 
88  return pointIndexHit(eHit.hit(), eHit.rawPoint(), endPoint);
89 }
90 
91 
92 // Go from selected edges only to a value for every edge
94  const
95 {
96  List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
97 
98  // Region edges first
99  for (label i = 0; i < externalStart_; i++)
100  {
101  edgeStat[featureEdges_[i]] = REGION;
102  }
103 
104  // External edges
105  for (label i = externalStart_; i < internalStart_; i++)
106  {
107  edgeStat[featureEdges_[i]] = EXTERNAL;
108  }
109 
110  // Internal edges
111  for (label i = internalStart_; i < featureEdges_.size(); i++)
112  {
113  edgeStat[featureEdges_[i]] = INTERNAL;
114  }
115 
116  return edgeStat;
117 }
118 
119 
120 // Set from value for every edge
122 (
123  const List<edgeStatus>& edgeStat,
124  const scalar includedAngle
125 )
126 {
127  // Count
128 
129  label nRegion = 0;
130  label nExternal = 0;
131  label nInternal = 0;
132 
133  forAll(edgeStat, edgeI)
134  {
135  if (edgeStat[edgeI] == REGION)
136  {
137  nRegion++;
138  }
139  else if (edgeStat[edgeI] == EXTERNAL)
140  {
141  nExternal++;
142  }
143  else if (edgeStat[edgeI] == INTERNAL)
144  {
145  nInternal++;
146  }
147  }
148 
149  externalStart_ = nRegion;
150  internalStart_ = externalStart_ + nExternal;
151 
152 
153  // Copy
154 
155  featureEdges_.setSize(internalStart_ + nInternal);
156 
157  label regionI = 0;
158  label externalI = externalStart_;
159  label internalI = internalStart_;
160 
161  forAll(edgeStat, edgeI)
162  {
163  if (edgeStat[edgeI] == REGION)
164  {
165  featureEdges_[regionI++] = edgeI;
166  }
167  else if (edgeStat[edgeI] == EXTERNAL)
168  {
169  featureEdges_[externalI++] = edgeI;
170  }
171  else if (edgeStat[edgeI] == INTERNAL)
172  {
173  featureEdges_[internalI++] = edgeI;
174  }
175  }
176 
177  const scalar minCos = Foam::cos(degToRad(180.0 - includedAngle));
178 
179  calcFeatPoints(edgeStat, minCos);
180 }
181 
182 
183 //construct feature points where more than 2 feature edges meet
185 (
186  const List<edgeStatus>& edgeStat,
187  const scalar minCos
188 )
189 {
190  DynamicList<label> featurePoints(surf_.nPoints()/1000);
191 
192  const labelListList& pointEdges = surf_.pointEdges();
193  const edgeList& edges = surf_.edges();
194  const pointField& localPoints = surf_.localPoints();
195 
196  forAll(pointEdges, pointI)
197  {
198  const labelList& pEdges = pointEdges[pointI];
199 
200  label nFeatEdges = 0;
201 
202  forAll(pEdges, i)
203  {
204  if (edgeStat[pEdges[i]] != NONE)
205  {
206  nFeatEdges++;
207  }
208  }
209 
210  if (nFeatEdges > 2)
211  {
212  featurePoints.append(pointI);
213  }
214  else if (nFeatEdges == 2)
215  {
216  // Check the angle between the two edges
217  DynamicList<vector> edgeVecs(2);
218 
219  forAll(pEdges, i)
220  {
221  const label edgeI = pEdges[i];
222 
223  if (edgeStat[edgeI] != NONE)
224  {
225  edgeVecs.append(edges[edgeI].vec(localPoints));
226  edgeVecs.last() /= mag(edgeVecs.last());
227  }
228  }
229 
230  if (mag(edgeVecs[0] & edgeVecs[1]) < minCos)
231  {
232  featurePoints.append(pointI);
233  }
234  }
235  }
236 
237  featurePoints_.transfer(featurePoints);
238 }
239 
240 
242 (
243  const labelListList& edgeFaces,
244  List<edgeStatus>& edgeStat,
245  const scalar minCos,
246  const bool geometricTestOnly
247 ) const
248 {
249  const vectorField& faceNormals = surf_.faceNormals();
250  const pointField& points = surf_.points();
251 
252  // Special case: minCos=1
253  bool selectAll = (mag(minCos-1.0) < SMALL);
254 
255  forAll(edgeFaces, edgeI)
256  {
257  const labelList& eFaces = edgeFaces[edgeI];
258 
259  if (eFaces.size() != 2)
260  {
261  // Non-manifold. What to do here? Is region edge? external edge?
262  edgeStat[edgeI] = REGION;
263  }
264  else
265  {
266  label face0 = eFaces[0];
267  label face1 = eFaces[1];
268 
269  if
270  (
271  !geometricTestOnly
272  && surf_[face0].region() != surf_[face1].region()
273  )
274  {
275  edgeStat[edgeI] = REGION;
276  }
277  else if
278  (
279  selectAll
280  || ((faceNormals[face0] & faceNormals[face1]) < minCos)
281  )
282  {
283  // Check if convex or concave by looking at angle
284  // between face centres and normal
285  vector f0Tof1 =
286  surf_[face1].centre(points)
287  - surf_[face0].centre(points);
288 
289  if ((f0Tof1 & faceNormals[face0]) >= 0.0)
290  {
291  edgeStat[edgeI] = INTERNAL;
292  }
293  else
294  {
295  edgeStat[edgeI] = EXTERNAL;
296  }
297  }
298  }
299  }
300 }
301 
302 
303 // Returns next feature edge connected to pointI with correct value.
305 (
306  const List<edgeStatus>& edgeStat,
307  const labelList& featVisited,
308  const label unsetVal,
309  const label prevEdgeI,
310  const label vertI
311 ) const
312 {
313  const labelList& pEdges = surf_.pointEdges()[vertI];
314 
315  label nextEdgeI = -1;
316 
317  forAll(pEdges, i)
318  {
319  label edgeI = pEdges[i];
320 
321  if
322  (
323  edgeI != prevEdgeI
324  && edgeStat[edgeI] != NONE
325  && featVisited[edgeI] == unsetVal
326  )
327  {
328  if (nextEdgeI == -1)
329  {
330  nextEdgeI = edgeI;
331  }
332  else
333  {
334  // More than one feature edge to choose from. End of segment.
335  return -1;
336  }
337  }
338  }
339 
340  return nextEdgeI;
341 }
342 
343 
344 // Finds connected feature edges by walking from prevEdgeI in direction of
345 // prevPointI. Marks feature edges visited in featVisited by assigning them
346 // the current feature line number. Returns cumulative length of edges walked.
347 // Works in one of two modes:
348 // - mark : step to edges with featVisited = -1.
349 // Mark edges visited with currentFeatI.
350 // - clear : step to edges with featVisited = currentFeatI
351 // Mark edges visited with -2 and erase from feature edges.
353 (
354  const bool mark,
355  const List<edgeStatus>& edgeStat,
356  const label startEdgeI,
357  const label startPointI,
358  const label currentFeatI,
359  labelList& featVisited
360 )
361 {
362  label edgeI = startEdgeI;
363 
364  label vertI = startPointI;
365 
366  scalar visitedLength = 0.0;
367 
368  label nVisited = 0;
369 
370  if (findIndex(featurePoints_, startPointI) >= 0)
371  {
372  // Do not walk across feature points
373 
374  return labelScalar(nVisited, visitedLength);
375  }
376 
377  //
378  // Now we have:
379  // edgeI : first edge on this segment
380  // vertI : one of the endpoints of this segment
381  //
382  // Start walking, marking off edges (in featVisited)
383  // as we go along.
384  //
385 
386  label unsetVal;
387 
388  if (mark)
389  {
390  unsetVal = -1;
391  }
392  else
393  {
394  unsetVal = currentFeatI;
395  }
396 
397  do
398  {
399  // Step to next feature edge with value unsetVal
400  edgeI = nextFeatEdge(edgeStat, featVisited, unsetVal, edgeI, vertI);
401 
402  if (edgeI == -1 || edgeI == startEdgeI)
403  {
404  break;
405  }
406 
407  // Mark with current value. If in clean mode also remove feature edge.
408 
409  if (mark)
410  {
411  featVisited[edgeI] = currentFeatI;
412  }
413  else
414  {
415  featVisited[edgeI] = -2;
416  }
417 
418 
419  // Step to next vertex on edge
420  const edge& e = surf_.edges()[edgeI];
421 
422  vertI = e.otherVertex(vertI);
423 
424 
425  // Update cumulative length
426  visitedLength += e.mag(surf_.localPoints());
427 
428  nVisited++;
429 
430  if (nVisited > surf_.nEdges())
431  {
432  Warning<< "walkSegment : reached iteration limit in walking "
433  << "feature edges on surface from edge:" << startEdgeI
434  << " vertex:" << startPointI << nl
435  << "Returning with large length" << endl;
436 
437  return labelScalar(nVisited, GREAT);
438  }
439  }
440  while (true);
441 
442  return labelScalar(nVisited, visitedLength);
443 }
444 
445 
446 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
447 
449 :
450  surf_(surf),
451  featurePoints_(0),
452  featureEdges_(0),
453  externalStart_(0),
454  internalStart_(0)
455 {}
456 
457 
458 // Construct from components.
460 (
461  const triSurface& surf,
462  const labelList& featurePoints,
463  const labelList& featureEdges,
464  const label externalStart,
465  const label internalStart
466 )
467 :
468  surf_(surf),
469  featurePoints_(featurePoints),
470  featureEdges_(featureEdges),
471  externalStart_(externalStart),
472  internalStart_(externalStart)
473 {}
474 
475 
476 // Construct from surface, angle and min length
478 (
479  const triSurface& surf,
480  const scalar includedAngle,
481  const scalar minLen,
482  const label minElems,
483  const bool geometricTestOnly
484 )
485 :
486  surf_(surf),
487  featurePoints_(0),
488  featureEdges_(0),
489  externalStart_(0),
490  internalStart_(0)
491 {
492  findFeatures(includedAngle, geometricTestOnly);
493 
494  if (minLen > 0 || minElems > 0)
495  {
496  trimFeatures(minLen, minElems, includedAngle);
497  }
498 }
499 
500 
501 //- Construct from dictionary
503 (
504  const triSurface& surf,
505  const dictionary& featInfoDict
506 )
507 :
508  surf_(surf),
509  featurePoints_(featInfoDict.lookup("featurePoints")),
510  featureEdges_(featInfoDict.lookup("featureEdges")),
511  externalStart_(readLabel(featInfoDict.lookup("externalStart"))),
512  internalStart_(readLabel(featInfoDict.lookup("internalStart")))
513 {}
514 
515 
516 //- Construct from file
518 (
519  const triSurface& surf,
520  const fileName& fName
521 )
522 :
523  surf_(surf),
524  featurePoints_(0),
525  featureEdges_(0),
526  externalStart_(0),
527  internalStart_(0)
528 {
529  IFstream str(fName);
530 
531  dictionary featInfoDict(str);
532 
533  featureEdges_ = labelList(featInfoDict.lookup("featureEdges"));
534  featurePoints_ = labelList(featInfoDict.lookup("featurePoints"));
535  externalStart_ = readLabel(featInfoDict.lookup("externalStart"));
536  internalStart_ = readLabel(featInfoDict.lookup("internalStart"));
537 }
538 
539 
541 (
542  const triSurface& surf,
543  const pointField& points,
544  const edgeList& edges,
545  const scalar mergeTol,
546  const bool geometricTestOnly
547 )
548 :
549  surf_(surf),
550  featurePoints_(0),
551  featureEdges_(0),
552  externalStart_(0),
553  internalStart_(0)
554 {
555  // Match edge mesh edges with the triSurface edges
556 
557  const labelListList& surfEdgeFaces = surf_.edgeFaces();
558  const edgeList& surfEdges = surf_.edges();
559 
560  scalar mergeTolSqr = sqr(mergeTol);
561 
562  EdgeMap<label> dynFeatEdges(2*edges.size());
563  DynamicList<labelList> dynFeatureEdgeFaces(edges.size());
564 
565  labelList edgeLabel;
566 
567  nearestFeatEdge
568  (
569  edges,
570  points,
571  mergeTolSqr,
572  edgeLabel // label of surface edge or -1
573  );
574 
575  label count = 0;
576  forAll(edgeLabel, sEdgeI)
577  {
578  const label sEdge = edgeLabel[sEdgeI];
579 
580  if (sEdge == -1)
581  {
582  continue;
583  }
584 
585  dynFeatEdges.insert(surfEdges[sEdge], count++);
586  dynFeatureEdgeFaces.append(surfEdgeFaces[sEdge]);
587  }
588 
589  // Find whether an edge is external or internal
590  List<edgeStatus> edgeStat(dynFeatEdges.size(), NONE);
591 
592  classifyFeatureAngles
593  (
594  dynFeatureEdgeFaces,
595  edgeStat,
596  GREAT,
597  geometricTestOnly
598  );
599 
600  // Transfer the edge status to a list encompassing all edges in the surface
601  // so that calcFeatPoints can be used.
602  List<edgeStatus> allEdgeStat(surf_.nEdges(), NONE);
603 
604  forAll(allEdgeStat, eI)
605  {
606  EdgeMap<label>::const_iterator iter = dynFeatEdges.find(surfEdges[eI]);
607 
608  if (iter != dynFeatEdges.end())
609  {
610  allEdgeStat[eI] = edgeStat[iter()];
611  }
612  }
613 
614  edgeStat.clear();
615  dynFeatEdges.clear();
616 
617  setFromStatus(allEdgeStat, GREAT);
618 }
619 
620 
621 //- Construct as copy
623 :
624  surf_(sf.surface()),
625  featurePoints_(sf.featurePoints()),
626  featureEdges_(sf.featureEdges()),
627  externalStart_(sf.externalStart()),
628  internalStart_(sf.internalStart())
629 {}
630 
631 
632 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
633 
635 (
636  const bool regionEdges,
637  const bool externalEdges,
638  const bool internalEdges
639 ) const
640 {
641  DynamicList<label> selectedEdges;
642 
643  if (regionEdges)
644  {
645  selectedEdges.setCapacity(selectedEdges.size() + nRegionEdges());
646 
647  for (label i = 0; i < externalStart_; i++)
648  {
649  selectedEdges.append(featureEdges_[i]);
650  }
651  }
652 
653  if (externalEdges)
654  {
655  selectedEdges.setCapacity(selectedEdges.size() + nExternalEdges());
656 
657  for (label i = externalStart_; i < internalStart_; i++)
658  {
659  selectedEdges.append(featureEdges_[i]);
660  }
661  }
662 
663  if (internalEdges)
664  {
665  selectedEdges.setCapacity(selectedEdges.size() + nInternalEdges());
666 
667  for (label i = internalStart_; i < featureEdges_.size(); i++)
668  {
669  selectedEdges.append(featureEdges_[i]);
670  }
671  }
672 
673  return selectedEdges.shrink();
674 }
675 
676 
678 (
679  const scalar includedAngle,
680  const bool geometricTestOnly
681 )
682 {
683  scalar minCos = Foam::cos(degToRad(180.0 - includedAngle));
684 
685  // Per edge whether is feature edge.
686  List<edgeStatus> edgeStat(surf_.nEdges(), NONE);
687 
688  classifyFeatureAngles
689  (
690  surf_.edgeFaces(),
691  edgeStat,
692  minCos,
693  geometricTestOnly
694  );
695 
696  setFromStatus(edgeStat, includedAngle);
697 }
698 
699 
700 // Remove small strings of edges. First assigns string number to
701 // every edge and then works out the length of them.
703 (
704  const scalar minLen,
705  const label minElems,
706  const scalar includedAngle
707 )
708 {
709  // Convert feature edge list to status per edge.
710  List<edgeStatus> edgeStat(toStatus());
711 
712 
713  // Mark feature edges according to connected lines.
714  // -1: unassigned
715  // -2: part of too small a feature line
716  // >0: feature line number
717  labelList featLines(surf_.nEdges(), -1);
718 
719  // Current featureline number.
720  label featI = 0;
721 
722  // Current starting edge
723  label startEdgeI = 0;
724 
725  do
726  {
727  // Find unset featureline
728  for (; startEdgeI < edgeStat.size(); startEdgeI++)
729  {
730  if
731  (
732  edgeStat[startEdgeI] != NONE
733  && featLines[startEdgeI] == -1
734  )
735  {
736  // Found unassigned feature edge.
737  break;
738  }
739  }
740 
741  if (startEdgeI == edgeStat.size())
742  {
743  // No unset feature edge found. All feature edges have line number
744  // assigned.
745  break;
746  }
747 
748  featLines[startEdgeI] = featI;
749 
750  const edge& startEdge = surf_.edges()[startEdgeI];
751 
752  // Walk 'left' and 'right' from startEdge.
753  labelScalar leftPath =
754  walkSegment
755  (
756  true, // 'mark' mode
757  edgeStat,
758  startEdgeI, // edge, not yet assigned to a featureLine
759  startEdge[0], // start of edge
760  featI, // Mark value
761  featLines // Mark for all edges
762  );
763 
764  labelScalar rightPath =
765  walkSegment
766  (
767  true,
768  edgeStat,
769  startEdgeI,
770  startEdge[1], // end of edge
771  featI,
772  featLines
773  );
774 
775  if
776  (
777  (
778  leftPath.len_
779  + rightPath.len_
780  + startEdge.mag(surf_.localPoints())
781  < minLen
782  )
783  || (leftPath.n_ + rightPath.n_ + 1 < minElems)
784  )
785  {
786  // Rewalk same route (recognizable by featLines == featI)
787  // to reset featLines.
788 
789  featLines[startEdgeI] = -2;
790 
791  walkSegment
792  (
793  false, // 'clean' mode
794  edgeStat,
795  startEdgeI, // edge, not yet assigned to a featureLine
796  startEdge[0], // start of edge
797  featI, // Unset value
798  featLines // Mark for all edges
799  );
800 
801  walkSegment
802  (
803  false,
804  edgeStat,
805  startEdgeI,
806  startEdge[1], // end of edge
807  featI,
808  featLines
809  );
810  }
811  else
812  {
813  featI++;
814  }
815  }
816  while (true);
817 
818  // Unmark all feature lines that have featLines=-2
819  forAll(featureEdges_, i)
820  {
821  label edgeI = featureEdges_[i];
822 
823  if (featLines[edgeI] == -2)
824  {
825  edgeStat[edgeI] = NONE;
826  }
827  }
828 
829  // Convert back to edge labels
830  setFromStatus(edgeStat, includedAngle);
831 
832  return featLines;
833 }
834 
835 
837 {
838 
839  dictionary featInfoDict;
840  featInfoDict.add("externalStart", externalStart_);
841  featInfoDict.add("internalStart", internalStart_);
842  featInfoDict.add("featureEdges", featureEdges_);
843  featInfoDict.add("featurePoints", featurePoints_);
844 
845  featInfoDict.write(writeFile);
846 }
847 
848 
849 void Foam::surfaceFeatures::write(const fileName& fName) const
850 {
851  OFstream str(fName);
852 
853  writeDict(str);
854 }
855 
856 
857 void Foam::surfaceFeatures::writeObj(const fileName& prefix) const
858 {
859  OFstream regionStr(prefix + "_regionEdges.obj");
860  Pout<< "Writing region edges to " << regionStr.name() << endl;
861 
862  label verti = 0;
863  for (label i = 0; i < externalStart_; i++)
864  {
865  const edge& e = surf_.edges()[featureEdges_[i]];
866 
867  meshTools::writeOBJ(regionStr, surf_.localPoints()[e[0]]); verti++;
868  meshTools::writeOBJ(regionStr, surf_.localPoints()[e[1]]); verti++;
869  regionStr << "l " << verti-1 << ' ' << verti << endl;
870  }
871 
872 
873  OFstream externalStr(prefix + "_externalEdges.obj");
874  Pout<< "Writing external edges to " << externalStr.name() << endl;
875 
876  verti = 0;
877  for (label i = externalStart_; i < internalStart_; i++)
878  {
879  const edge& e = surf_.edges()[featureEdges_[i]];
880 
881  meshTools::writeOBJ(externalStr, surf_.localPoints()[e[0]]); verti++;
882  meshTools::writeOBJ(externalStr, surf_.localPoints()[e[1]]); verti++;
883  externalStr << "l " << verti-1 << ' ' << verti << endl;
884  }
885 
886  OFstream internalStr(prefix + "_internalEdges.obj");
887  Pout<< "Writing internal edges to " << internalStr.name() << endl;
888 
889  verti = 0;
890  for (label i = internalStart_; i < featureEdges_.size(); i++)
891  {
892  const edge& e = surf_.edges()[featureEdges_[i]];
893 
894  meshTools::writeOBJ(internalStr, surf_.localPoints()[e[0]]); verti++;
895  meshTools::writeOBJ(internalStr, surf_.localPoints()[e[1]]); verti++;
896  internalStr << "l " << verti-1 << ' ' << verti << endl;
897  }
898 
899  OFstream pointStr(prefix + "_points.obj");
900  Pout<< "Writing feature points to " << pointStr.name() << endl;
901 
902  forAll(featurePoints_, i)
903  {
904  label pointI = featurePoints_[i];
905 
906  meshTools::writeOBJ(pointStr, surf_.localPoints()[pointI]);
907  }
908 }
909 
910 
911 // Get nearest vertex on patch for every point of surf in pointSet.
913 (
914  const labelList& pointLabels,
915  const pointField& samples,
916  const scalarField& maxDistSqr
917 ) const
918 {
919  // Build tree out of all samples.
920 
921  // Note: cannot be done one the fly - gcc4.4 compiler bug.
922  treeBoundBox bb(samples);
923 
925  (
926  treeDataPoint(samples), // all information needed to do checks
927  bb, // overall search domain
928  8, // maxLevel
929  10, // leafsize
930  3.0 // duplicity
931  );
932 
933  // From patch point to surface point
934  Map<label> nearest(2*pointLabels.size());
935 
936  const pointField& surfPoints = surf_.localPoints();
937 
938  forAll(pointLabels, i)
939  {
940  label surfPointI = pointLabels[i];
941 
942  const point& surfPt = surfPoints[surfPointI];
943 
944  pointIndexHit info = ppTree.findNearest
945  (
946  surfPt,
947  maxDistSqr[i]
948  );
949 
950  if (!info.hit())
951  {
953  << "Problem for point "
954  << surfPointI << " in tree " << ppTree.bb()
955  << abort(FatalError);
956  }
957 
958  label sampleI = info.index();
959 
960  if (magSqr(samples[sampleI] - surfPt) < maxDistSqr[sampleI])
961  {
962  nearest.insert(sampleI, surfPointI);
963  }
964  }
965 
966 
967  if (debug)
968  {
969  //
970  // Dump to obj file
971  //
972 
973  Pout<< endl
974  << "Dumping nearest surface feature points to nearestSamples.obj"
975  << endl
976  << "View this Lightwave-OBJ file with e.g. javaview" << endl
977  << endl;
978 
979  OFstream objStream("nearestSamples.obj");
980 
981  label vertI = 0;
982  forAllConstIter(Map<label>, nearest, iter)
983  {
984  meshTools::writeOBJ(objStream, samples[iter.key()]); vertI++;
985  meshTools::writeOBJ(objStream, surfPoints[iter()]); vertI++;
986  objStream<< "l " << vertI-1 << ' ' << vertI << endl;
987  }
988  }
989 
990  return nearest;
991 }
992 
993 
994 // Get nearest sample point for regularly sampled points along
995 // selected edges. Return map from sample to edge label
997 (
998  const labelList& selectedEdges,
999  const pointField& samples,
1000  const scalarField& sampleDist,
1001  const scalarField& maxDistSqr,
1002  const scalar minSampleDist
1003 ) const
1004 {
1005  const pointField& surfPoints = surf_.localPoints();
1006  const edgeList& surfEdges = surf_.edges();
1007 
1008  scalar maxSearchSqr = max(maxDistSqr);
1009 
1010  //Note: cannot be done one the fly - gcc4.4 compiler bug.
1011  treeBoundBox bb(samples);
1012 
1014  (
1015  treeDataPoint(samples), // all information needed to do checks
1016  bb, // overall search domain
1017  8, // maxLevel
1018  10, // leafsize
1019  3.0 // duplicity
1020  );
1021 
1022  // From patch point to surface edge.
1023  Map<label> nearest(2*selectedEdges.size());
1024 
1025  forAll(selectedEdges, i)
1026  {
1027  label surfEdgeI = selectedEdges[i];
1028 
1029  const edge& e = surfEdges[surfEdgeI];
1030 
1031  if (debug && (i % 1000) == 0)
1032  {
1033  Pout<< "looking at surface feature edge " << surfEdgeI
1034  << " verts:" << e << " points:" << surfPoints[e[0]]
1035  << ' ' << surfPoints[e[1]] << endl;
1036  }
1037 
1038  // Normalized edge vector
1039  vector eVec = e.vec(surfPoints);
1040  scalar eMag = mag(eVec);
1041  eVec /= eMag;
1042 
1043 
1044  //
1045  // Sample along edge
1046  //
1047 
1048  bool exit = false;
1049 
1050  // Coordinate along edge (0 .. eMag)
1051  scalar s = 0.0;
1052 
1053  while (true)
1054  {
1055  point edgePoint(surfPoints[e.start()] + s*eVec);
1056 
1057  pointIndexHit info = ppTree.findNearest
1058  (
1059  edgePoint,
1060  maxSearchSqr
1061  );
1062 
1063  if (!info.hit())
1064  {
1065  // No point close enough to surface edge.
1066  break;
1067  }
1068 
1069  label sampleI = info.index();
1070 
1071  if (magSqr(info.hitPoint() - edgePoint) < maxDistSqr[sampleI])
1072  {
1073  nearest.insert(sampleI, surfEdgeI);
1074  }
1075 
1076  if (exit)
1077  {
1078  break;
1079  }
1080 
1081  // Step to next sample point using local distance.
1082  // Truncate to max 1/minSampleDist samples per feature edge.
1083  s += max(minSampleDist*eMag, sampleDist[sampleI]);
1084 
1085  if (s >= (1-minSampleDist)*eMag)
1086  {
1087  // Do one more sample, at edge endpoint
1088  s = eMag;
1089  exit = true;
1090  }
1091  }
1092  }
1093 
1094 
1095 
1096  if (debug)
1097  {
1098  // Dump to obj file
1099 
1100  Pout<< "Dumping nearest surface edges to nearestEdges.obj\n"
1101  << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
1102 
1103  OFstream objStream("nearestEdges.obj");
1104 
1105  label vertI = 0;
1106  forAllConstIter(Map<label>, nearest, iter)
1107  {
1108  const label sampleI = iter.key();
1109 
1110  meshTools::writeOBJ(objStream, samples[sampleI]); vertI++;
1111 
1112  const edge& e = surfEdges[iter()];
1113 
1114  point nearPt =
1115  e.line(surfPoints).nearestDist(samples[sampleI]).rawPoint();
1116 
1117  meshTools::writeOBJ(objStream, nearPt); vertI++;
1118 
1119  objStream<< "l " << vertI-1 << ' ' << vertI << endl;
1120  }
1121  }
1122 
1123  return nearest;
1124 }
1125 
1126 
1127 // Get nearest edge on patch for regularly sampled points along the feature
1128 // edges. Return map from patch edge to feature edge.
1129 //
1130 // Q: using point-based sampleDist and maxDist (distance to look around
1131 // each point). Should they be edge-based e.g. by averaging or max()?
1134  const labelList& selectedEdges,
1135  const edgeList& sampleEdges,
1136  const labelList& selectedSampleEdges,
1137  const pointField& samplePoints,
1138  const scalarField& sampleDist,
1139  const scalarField& maxDistSqr,
1140  const scalar minSampleDist
1141 ) const
1142 {
1143  // Build tree out of selected sample edges.
1145  (
1146  treeDataEdge
1147  (
1148  false,
1149  sampleEdges,
1150  samplePoints,
1151  selectedSampleEdges
1152  ), // geometric info container for edges
1153  treeBoundBox(samplePoints), // overall search domain
1154  8, // maxLevel
1155  10, // leafsize
1156  3.0 // duplicity
1157  );
1158 
1159  const pointField& surfPoints = surf_.localPoints();
1160  const edgeList& surfEdges = surf_.edges();
1161 
1162  scalar maxSearchSqr = max(maxDistSqr);
1163 
1164  Map<pointIndexHit> nearest(2*sampleEdges.size());
1165 
1166  //
1167  // Loop over all selected edges. Sample at regular intervals. Find nearest
1168  // sampleEdges (using octree)
1169  //
1170 
1171  forAll(selectedEdges, i)
1172  {
1173  label surfEdgeI = selectedEdges[i];
1174 
1175  const edge& e = surfEdges[surfEdgeI];
1176 
1177  if (debug && (i % 1000) == 0)
1178  {
1179  Pout<< "looking at surface feature edge " << surfEdgeI
1180  << " verts:" << e << " points:" << surfPoints[e[0]]
1181  << ' ' << surfPoints[e[1]] << endl;
1182  }
1183 
1184  // Normalized edge vector
1185  vector eVec = e.vec(surfPoints);
1186  scalar eMag = mag(eVec);
1187  eVec /= eMag;
1188 
1189 
1190  //
1191  // Sample along edge
1192  //
1193 
1194  bool exit = false;
1195 
1196  // Coordinate along edge (0 .. eMag)
1197  scalar s = 0.0;
1198 
1199  while (true)
1200  {
1201  point edgePoint(surfPoints[e.start()] + s*eVec);
1202 
1203  pointIndexHit info = ppTree.findNearest
1204  (
1205  edgePoint,
1206  maxSearchSqr
1207  );
1208 
1209  if (!info.hit())
1210  {
1211  // No edge close enough to surface edge.
1212  break;
1213  }
1214 
1215  label index = info.index();
1216 
1217  label sampleEdgeI = ppTree.shapes().edgeLabels()[index];
1218 
1219  const edge& e = sampleEdges[sampleEdgeI];
1220 
1221  if (magSqr(info.hitPoint() - edgePoint) < maxDistSqr[e.start()])
1222  {
1223  nearest.insert
1224  (
1225  sampleEdgeI,
1226  pointIndexHit(true, edgePoint, surfEdgeI)
1227  );
1228  }
1229 
1230  if (exit)
1231  {
1232  break;
1233  }
1234 
1235  // Step to next sample point using local distance.
1236  // Truncate to max 1/minSampleDist samples per feature edge.
1237  // s += max(minSampleDist*eMag, sampleDist[e.start()]);
1238  s += 0.01*eMag;
1239 
1240  if (s >= (1-minSampleDist)*eMag)
1241  {
1242  // Do one more sample, at edge endpoint
1243  s = eMag;
1244  exit = true;
1245  }
1246  }
1247  }
1248 
1249 
1250  if (debug)
1251  {
1252  // Dump to obj file
1253 
1254  Pout<< "Dumping nearest surface feature edges to nearestEdges.obj\n"
1255  << "View this Lightwave-OBJ file with e.g. javaview\n" << endl;
1256 
1257  OFstream objStream("nearestEdges.obj");
1258 
1259  label vertI = 0;
1260  forAllConstIter(Map<pointIndexHit>, nearest, iter)
1261  {
1262  const label sampleEdgeI = iter.key();
1263 
1264  const edge& sampleEdge = sampleEdges[sampleEdgeI];
1265 
1266  // Write line from edgeMid to point on feature edge
1267  meshTools::writeOBJ(objStream, sampleEdge.centre(samplePoints));
1268  vertI++;
1269 
1270  meshTools::writeOBJ(objStream, iter().rawPoint());
1271  vertI++;
1272 
1273  objStream<< "l " << vertI-1 << ' ' << vertI << endl;
1274  }
1275  }
1276 
1277  return nearest;
1278 }
1279 
1280 
1281 // Get nearest surface edge for every sample. Return in form of
1282 // labelLists giving surfaceEdge label&intersectionpoint.
1285  const labelList& selectedEdges,
1286  const pointField& samples,
1287  scalar searchSpanSqr, // Search span
1288  labelList& edgeLabel,
1289  labelList& edgeEndPoint,
1290  pointField& edgePoint
1291 ) const
1292 {
1293  edgeLabel.setSize(samples.size());
1294  edgeEndPoint.setSize(samples.size());
1295  edgePoint.setSize(samples.size());
1296 
1297  const pointField& localPoints = surf_.localPoints();
1298 
1299  treeBoundBox searchDomain(localPoints);
1300  searchDomain.inflate(0.1);
1301 
1303  (
1304  treeDataEdge
1305  (
1306  false,
1307  surf_.edges(),
1308  localPoints,
1309  selectedEdges
1310  ), // all information needed to do geometric checks
1311  searchDomain, // overall search domain
1312  8, // maxLevel
1313  10, // leafsize
1314  3.0 // duplicity
1315  );
1316 
1317  forAll(samples, i)
1318  {
1319  const point& sample = samples[i];
1320 
1321  pointIndexHit info = ppTree.findNearest
1322  (
1323  sample,
1324  searchSpanSqr
1325  );
1326 
1327  if (!info.hit())
1328  {
1329  edgeLabel[i] = -1;
1330  }
1331  else
1332  {
1333  edgeLabel[i] = selectedEdges[info.index()];
1334 
1335  // Need to recalculate to classify edgeEndPoint
1336  const edge& e = surf_.edges()[edgeLabel[i]];
1337 
1338  pointIndexHit pHit = edgeNearest
1339  (
1340  localPoints[e.start()],
1341  localPoints[e.end()],
1342  sample
1343  );
1344 
1345  edgePoint[i] = pHit.rawPoint();
1346  edgeEndPoint[i] = pHit.index();
1347  }
1348  }
1349 }
1350 
1351 
1352 // Get nearest point on nearest feature edge for every sample (is edge)
1355  const labelList& selectedEdges,
1356 
1357  const edgeList& sampleEdges,
1358  const labelList& selectedSampleEdges,
1359  const pointField& samplePoints,
1360 
1361  const vector& searchSpan, // Search span
1362  labelList& edgeLabel, // label of surface edge or -1
1363  pointField& pointOnEdge, // point on above edge
1364  pointField& pointOnFeature // point on sample edge
1365 ) const
1366 {
1367  edgeLabel.setSize(selectedSampleEdges.size());
1368  pointOnEdge.setSize(selectedSampleEdges.size());
1369  pointOnFeature.setSize(selectedSampleEdges.size());
1370 
1371  treeBoundBox searchDomain(surf_.localPoints());
1372 
1374  (
1375  treeDataEdge
1376  (
1377  false,
1378  surf_.edges(),
1379  surf_.localPoints(),
1380  selectedEdges
1381  ), // all information needed to do geometric checks
1382  searchDomain, // overall search domain
1383  8, // maxLevel
1384  10, // leafsize
1385  3.0 // duplicity
1386  );
1387 
1388  forAll(selectedSampleEdges, i)
1389  {
1390  const edge& e = sampleEdges[selectedSampleEdges[i]];
1391 
1392  linePointRef edgeLine = e.line(samplePoints);
1393 
1394  point eMid(edgeLine.centre());
1395 
1396  treeBoundBox tightest(eMid - searchSpan, eMid + searchSpan);
1397 
1398  pointIndexHit info = ppTree.findNearest
1399  (
1400  edgeLine,
1401  tightest,
1402  pointOnEdge[i]
1403  );
1404 
1405  if (!info.hit())
1406  {
1407  edgeLabel[i] = -1;
1408  }
1409  else
1410  {
1411  edgeLabel[i] = selectedEdges[info.index()];
1412 
1413  pointOnFeature[i] = info.hitPoint();
1414  }
1415  }
1416 }
1417 
1418 
1421  const edgeList& edges,
1422  const pointField& points,
1423  scalar searchSpanSqr, // Search span
1424  labelList& edgeLabel
1425 ) const
1426 {
1427  edgeLabel = labelList(surf_.nEdges(), -1);
1428 
1429  treeBoundBox searchDomain(points);
1430  searchDomain.inflate(0.1);
1431 
1433  (
1434  treeDataEdge
1435  (
1436  false,
1437  edges,
1438  points,
1439  identity(edges.size())
1440  ), // all information needed to do geometric checks
1441  searchDomain, // overall search domain
1442  8, // maxLevel
1443  10, // leafsize
1444  3.0 // duplicity
1445  );
1446 
1447  const edgeList& surfEdges = surf_.edges();
1448  const pointField& surfLocalPoints = surf_.localPoints();
1449 
1450  forAll(surfEdges, edgeI)
1451  {
1452  const edge& sample = surfEdges[edgeI];
1453 
1454  const point& startPoint = surfLocalPoints[sample.start()];
1455  const point& midPoint = sample.centre(surfLocalPoints);
1456 
1457  pointIndexHit infoMid = ppTree.findNearest
1458  (
1459  midPoint,
1460  searchSpanSqr
1461  );
1462 
1463  if (infoMid.hit())
1464  {
1465  const vector surfEdgeDir = midPoint - startPoint;
1466 
1467  const edge& featEdge = edges[infoMid.index()];
1468  const vector featEdgeDir = featEdge.vec(points);
1469 
1470  // Check that the edges are nearly parallel
1471  if (mag(surfEdgeDir ^ featEdgeDir) < parallelTolerance)
1472  {
1473  edgeLabel[edgeI] = edgeI;
1474  }
1475  }
1476  }
1477 }
1478 
1479 
1480 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
1481 
1483 {
1484  // Check for assignment to self
1485  if (this == &rhs)
1486  {
1488  << "Attempted assignment to self"
1489  << abort(FatalError);
1490  }
1491 
1492  if (&surf_ != &rhs.surface())
1493  {
1495  << "Operating on different surfaces"
1496  << abort(FatalError);
1497  }
1498 
1499  featurePoints_ = rhs.featurePoints();
1500  featureEdges_ = rhs.featureEdges();
1501  externalStart_ = rhs.externalStart();
1502  internalStart_ = rhs.internalStart();
1503 }
1504 
1505 
1506 // ************************************************************************* //
Foam::line::centre
Point centre() const
Return centre (centroid)
Definition: lineI.H:73
Foam::surfaceFeatures::edgeNearest
static pointIndexHit edgeNearest(const point &start, const point &end, const point &sample)
Return nearest point on edge (start..end). Also classify nearest:
Definition: surfaceFeatures.C:52
Foam::surfaceFeatures::surf_
const triSurface & surf_
Reference to surface.
Definition: surfaceFeatures.H:106
meshTools.H
Foam::surfaceFeatures::internalStart
label internalStart() const
Start of internal edges.
Definition: surfaceFeatures.H:251
Foam::surfaceFeatures::writeDict
void writeDict(Ostream &) const
Write as dictionary.
Definition: surfaceFeatures.C:836
Foam::PointIndexHit::index
label index() const
Return index.
Definition: PointIndexHit.H:111
Foam::surfaceFeatures::parallelTolerance
static const scalar parallelTolerance
Tolerance for determining whether two vectors are parallel.
Definition: surfaceFeatures.H:100
Foam::surfaceFeatures::nearestFeatEdge
void nearestFeatEdge(const edgeList &edges, const pointField &points, scalar searchSpanSqr, labelList &edgeLabel) const
Find nearest feature edge to each surface edge. Uses the.
Definition: surfaceFeatures.C:1420
Foam::surfaceFeatures::externalStart_
label externalStart_
Start of external edges in featureEdges_.
Definition: surfaceFeatures.H:115
Foam::PointHit::hit
bool hit() const
Is there a hit.
Definition: PointHit.H:120
Foam::surfaceFeatures::INTERNAL
@ INTERNAL
Definition: surfaceFeatures.H:77
Foam::surfaceFeatures::nearestSamples
Map< label > nearestSamples(const labelList &selectedPoints, const pointField &samples, const scalarField &maxDistSqr) const
Find nearest sample for selected surface points.
Definition: surfaceFeatures.C:913
Foam::fileName
A class for handling file names.
Definition: fileName.H:69
Foam::surfaceFeatures::selectFeatureEdges
labelList selectFeatureEdges(const bool regionEdges, const bool externalEdges, const bool internalEdges) const
Helper function: select a subset of featureEdges_.
Definition: surfaceFeatures.C:635
Foam::labelList
List< label > labelList
A List of labels.
Definition: labelList.H:56
Foam::surfaceFeatures::toStatus
List< edgeStatus > toStatus() const
From member feature edges to status per edge.
Definition: surfaceFeatures.C:93
Foam::surfaceFeatures::nearestEdges
Map< pointIndexHit > nearestEdges(const labelList &selectedEdges, const edgeList &sampleEdges, const labelList &selectedSampleEdges, const pointField &samplePoints, const scalarField &sampleDist, const scalarField &maxDistSqr, const scalar minSampleDist=0.1) const
Like nearestSamples but now gets nearest point on.
Definition: surfaceFeatures.C:1133
forAll
#define forAll(list, i)
Loop across all elements in list.
Definition: UList.H:406
Foam::PointHit
This class describes the interaction of a face and a point. It carries the info of a successful hit a...
Definition: PointHit.H:51
Foam::findIndex
label findIndex(const ListType &, typename ListType::const_reference, const label start=0)
Find first occurence of given element and return index,.
Foam::IFstream
Input from file stream.
Definition: IFstream.H:81
Foam::edge::mag
scalar mag(const pointField &) const
Return scalar magnitude.
Definition: edgeI.H:163
Foam::DynamicList< label >
Foam::meshTools::writeOBJ
void writeOBJ(Ostream &os, const point &pt)
Write obj representation of point.
Definition: meshTools.C:203
Foam::edge::vec
vector vec(const pointField &) const
Return the vector (end - start)
Definition: edgeI.H:157
Foam::boundBox::inflate
void inflate(const scalar s)
Inflate box by factor*mag(span) in all dimensions.
Definition: boundBox.C:210
Foam::sin
dimensionedScalar sin(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:255
surfaceFeatures.H
Foam::PointHit::rawPoint
const Point & rawPoint() const
Return point with no checking.
Definition: PointHit.H:158
Foam::PrimitivePatch::nEdges
label nEdges() const
Return number of edges in patch.
Definition: PrimitivePatchTemplate.H:299
Foam::treeBoundBox
Standard boundBox + extra functionality for use in octree.
Definition: treeBoundBox.H:75
Foam::Warning
messageStream Warning
indexedOctree.H
Foam::dictionary::lookup
ITstream & lookup(const word &, bool recursive=false, bool patternMatch=true) const
Find and return an entry data stream.
Definition: dictionary.C:449
Foam::edge
An edge is a list of two point labels. The functionality it provides supports the discretisation on a...
Definition: edge.H:58
Foam::PointIndexHit::hit
bool hit() const
Is there a hit.
Definition: PointIndexHit.H:105
Foam::HashTable::insert
bool insert(const Key &, const T &newElmt)
Insert a new hashedEntry.
Definition: HashTableI.H:80
Foam::Map
A HashTable to objects of type <T> with a label key.
Definition: PrimitivePatchTemplate.H:68
unitConversion.H
Unit conversion functions.
Foam::midPoint
Mid-point interpolation (weighting factors = 0.5) scheme class.
Definition: midPoint.H:50
Foam::indexedOctree::shapes
const Type & shapes() const
Reference to shape.
Definition: indexedOctree.H:449
Foam::surfaceFeatures::REGION
@ REGION
Definition: surfaceFeatures.H:75
Foam::endl
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:251
Foam::surfaceFeatures::labelScalar::len_
scalar len_
Definition: surfaceFeatures.H:88
Foam::mag
dimensioned< scalar > mag(const dimensioned< Type > &)
Foam::edge::centre
point centre(const pointField &) const
Return centre (centroid)
Definition: edgeI.H:151
Foam::surfaceFeatures::calcFeatPoints
void calcFeatPoints(const List< edgeStatus > &edgeStat, const scalar minCos)
Construct feature points where more than 2 feature edges meet.
Definition: surfaceFeatures.C:185
Foam::treeDataPoint
Holds (reference to) pointField. Encapsulation of data needed for octree searches....
Definition: treeDataPoint.H:59
forAllConstIter
forAllConstIter(PtrDictionary< phaseModel >, mixture.phases(), phase)
Definition: pEqn.H:39
OFstream.H
Foam::surfaceFeatures::featureEdges_
labelList featureEdges_
Labels of edges that are features.
Definition: surfaceFeatures.H:112
Foam::surfaceFeatures::EXTERNAL
@ EXTERNAL
Definition: surfaceFeatures.H:76
Foam::surfaceFeatures::featurePoints
const labelList & featurePoints() const
Return feature point list.
Definition: surfaceFeatures.H:233
Foam::surfaceFeatures::surfaceFeatures
surfaceFeatures(const triSurface &)
Construct from surface.
Definition: surfaceFeatures.C:448
samples
scalarField samples(nIntervals, 0)
Foam::surfaceFeatures::NONE
@ NONE
Definition: surfaceFeatures.H:74
Foam::PointIndexHit
This class describes the interaction of (usually) a face and a point. It carries the info of a succes...
Definition: PointIndexHit.H:53
Foam::PointIndexHit::rawPoint
const Point & rawPoint() const
Return point with no checking.
Definition: PointIndexHit.H:143
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
Foam::Field
Pre-declare SubField and related Field type.
Definition: Field.H:57
treeDataPoint.H
Foam::triSurface
Triangulated surface description with patch information.
Definition: triSurface.H:57
Foam::nl
static const char nl
Definition: Ostream.H:260
Foam::PointIndexHit::hitPoint
const Point & hitPoint() const
Return hit point.
Definition: PointIndexHit.H:117
Foam::DynamicList::setCapacity
void setCapacity(const label)
Alter the size of the underlying storage.
Definition: DynamicListI.H:109
Foam::surfaceFeatures
Holds feature edges/points of surface.
Definition: surfaceFeatures.H:68
Foam::indexedOctree
Non-pointer based hierarchical recursive searching.
Definition: treeDataTriSurface.H:47
Foam::Vector::centre
const Vector< Cmpt > & centre(const Foam::List< Vector< Cmpt > > &) const
Return *this (used for point which is a typedef to Vector<scalar>.
Definition: VectorI.H:106
Foam::surfaceFeatures::nearestSurfEdge
void nearestSurfEdge(const labelList &selectedEdges, const pointField &samples, scalar searchSpanSqr, labelList &edgeLabel, labelList &edgeEndPoint, pointField &edgePoint) const
Find nearest surface edge (out of selectedEdges) for.
Definition: surfaceFeatures.C:1284
Foam::treeDataEdge
Holds data for octree to work on an edges subset.
Definition: treeDataEdge.H:53
Foam::DynamicList::shrink
DynamicList< T, SizeInc, SizeMult, SizeDiv > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:258
Foam::surfaceFeatures::featureEdges
const labelList & featureEdges() const
Return feature edge list.
Definition: surfaceFeatures.H:239
IFstream.H
Foam::surfaceFeatures::nextFeatEdge
label nextFeatEdge(const List< edgeStatus > &edgeStat, const labelList &featVisited, const label unsetVal, const label prevEdgeI, const label vertI) const
Choose next unset feature edge.
Definition: surfaceFeatures.C:305
Foam::identity
labelList identity(const label len)
Create identity map (map[i] == i) of given length.
Definition: ListOps.C:104
Foam::surfaceFeatures::operator=
void operator=(const surfaceFeatures &)
Definition: surfaceFeatures.C:1482
Foam::FatalError
error FatalError
Foam::dictionary
A list of keyword definitions, which are a keyword followed by any number of values (e....
Definition: dictionary.H:137
Foam::HashTable::size
label size() const
Return number of elements in table.
Definition: HashTableI.H:65
Foam::surfaceFeatures::walkSegment
labelScalar walkSegment(const bool mark, const List< edgeStatus > &edgeStat, const label startEdgeI, const label startPointI, const label currentFeatI, labelList &featVisited)
Walk connected feature edges. Marks edges in featVisited.
Definition: surfaceFeatures.C:353
Foam::surfaceFeatures::writeObj
void writeObj(const fileName &prefix) const
Write to separate OBJ files (region, external, internal edges,.
Definition: surfaceFeatures.C:857
treeDataEdge.H
Foam
Namespace for OpenFOAM.
Definition: combustionModel.C:30
Foam::abort
errorManip< error > abort(error &err)
Definition: errorManip.H:131
sf
volScalarField sf(fieldObject, mesh)
Foam::e
const double e
Elementary charge.
Definition: doubleFloat.H:94
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::HashTable::find
iterator find(const Key &)
Find and return an iterator set at the hashedEntry.
Foam::surfaceFeatures::setFromStatus
void setFromStatus(const List< edgeStatus > &edgeStat, const scalar includedAngle)
Set from status per edge.
Definition: surfaceFeatures.C:122
Foam::DynamicList::append
DynamicList< T, SizeInc, SizeMult, SizeDiv > & append(const T &)
Append an element at the end of the list.
Foam::exit
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:124
Foam::OFstream
Output to file stream.
Definition: OFstream.H:81
Foam::surfaceFeatures::trimFeatures
labelList trimFeatures(const scalar minLen, const label minElems, const scalar includedAngle)
Delete small sets of edges. Edges are stringed up and any.
Definition: surfaceFeatures.C:703
Foam::indexedOctree::bb
const treeBoundBox & bb() const
Top bounding box.
Definition: indexedOctree.H:468
Foam::surfaceFeatures::surface
const triSurface & surface() const
Definition: surfaceFeatures.H:227
Foam::max
dimensioned< Type > max(const dimensioned< Type > &, const dimensioned< Type > &)
Foam::List::setSize
void setSize(const label)
Reset size of List.
Foam::EdgeMap< label >
Foam::linePointRef
line< point, const point & > linePointRef
Line using referred points.
Definition: linePointRef.H:45
FatalErrorInFunction
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:318
Foam::sqr
dimensionedSymmTensor sqr(const dimensionedVector &dv)
Definition: dimensionedSymmTensor.C:49
Foam::pointIndexHit
PointIndexHit< point > pointIndexHit
Definition: pointIndexHit.H:42
Foam::edge::start
label start() const
Return start vertex label.
Definition: edgeI.H:81
Foam::Pout
prefixOSstream Pout(cout, "Pout")
Definition: IOstreams.H:53
Foam::HashTable::clear
void clear()
Clear all entries from table.
Definition: HashTable.C:473
Foam::Vector< scalar >
Foam::surfaceFeatures::labelScalar::n_
label n_
Definition: surfaceFeatures.H:87
Foam::List
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: HashTable.H:59
points
const pointField & points
Definition: gmvOutputHeader.H:1
Foam::List::clear
void clear()
Clear the list, i.e. set size to zero.
Definition: List.C:379
Foam::surface
Definition: surface.H:55
EdgeMap.H
Foam::readLabel
label readLabel(Istream &is)
Definition: label.H:64
Foam::line
A line primitive.
Definition: line.H:56
Foam::surfaceFeatures::labelScalar
Label and scalar; used in path walking.
Definition: surfaceFeatures.H:84
Foam::surfaceFeatures::internalStart_
label internalStart_
Start of internal edges in featureEdges_.
Definition: surfaceFeatures.H:118
Foam::indexedOctree::findNearest
void findNearest(const label nodeI, const linePointRef &ln, treeBoundBox &tightest, label &nearestShapeI, point &linePoint, point &nearestPoint, const FindNearestOp &fnOp) const
Find nearest point to line.
Definition: indexedOctree.C:590
Foam::surfaceFeatures::write
void write(const fileName &fName) const
Write as dictionary to file.
Definition: surfaceFeatures.C:849
Foam::OFstream::name
const fileName & name() const
Return the name of the stream.
Definition: OFstream.H:118
Foam::List::size
void size(const label)
Override size to be inconsistent with allocated storage.
Foam::Ostream
An Ostream is an abstract base class for all output systems (streams, files, token lists,...
Definition: Ostream.H:53
Foam::surfaceFeatures::classifyFeatureAngles
void classifyFeatureAngles(const labelListList &edgeFaces, List< edgeStatus > &edgeStat, const scalar minCos, const bool geometricTestOnly) const
Classify the angles of the feature edges.
Definition: surfaceFeatures.C:242
Foam::surfaceFeatures::findFeatures
void findFeatures(const scalar includedAngle, const bool geometricTestOnly)
Find feature edges using provided included angle.
Definition: surfaceFeatures.C:678
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(combustionModel, 0)
pointLabels
labelList pointLabels(nPoints, -1)
Foam::magSqr
dimensioned< scalar > magSqr(const dimensioned< Type > &)
Foam::dictionary::add
bool add(entry *, bool mergeEntry=false)
Add a new entry.
Definition: dictionary.C:729
Foam::dictionary::write
void write(Ostream &, const bool subDict=true) const
Write dictionary, normally with sub-dictionary formatting.
Definition: dictionaryIO.C:173
linePointRef.H
Foam::degToRad
scalar degToRad(const scalar deg)
Conversion from degrees to radians.
Definition: unitConversion.H:45
Foam::cos
dimensionedScalar cos(const dimensionedScalar &ds)
Definition: dimensionedScalar.C:256
Foam::surfaceFeatures::externalStart
label externalStart() const
Start of external edges.
Definition: surfaceFeatures.H:245