xmsgrid  1.0
XmUGrid.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
6 //------------------------------------------------------------------------------
7 
8 //----- Included files ---------------------------------------------------------
9 
10 // 1. Precompiled header
11 
12 // 2. My own header
13 #include <xmsgrid/ugrid/XmUGrid.h>
14 
15 // 3. Standard library headers
16 #include <cmath>
17 
18 // 4. External library headers
19 #include <boost/container/flat_set.hpp>
20 
21 // 5. Shared code headers
22 #include <xmscore/misc/XmConst.h>
23 #include <xmscore/misc/XmError.h>
24 #include <xmscore/misc/XmLog.h>
25 #include <xmscore/misc/xmstype.h>
26 #include <xmscore/stl/set.h>
27 
28 // 6. Non-shared code headers
29 #include <xmsgrid/geometry/geoms.h>
31 #include <xmsgrid/ugrid/XmEdge.h>
32 
33 //----- Forward declarations ---------------------------------------------------
34 
35 //----- External globals -------------------------------------------------------
36 
37 //----- Namespace declaration --------------------------------------------------
38 
39 //----- Constants / Enumerations -----------------------------------------------
40 
41 //----- Classes / Structs ------------------------------------------------------
42 
43 //----- Class / Function definitions -------------------------------------------
44 
46 namespace xms
47 {
51 {
52 public:
54  Impl() = default;
56  Impl(const Impl&) = default;
60  Impl& operator=(const Impl& a_xmUGrid) = default;
61 
62  // Misc
63  bool GetModified() const;
64  void SetUnmodified();
65  void SetUseCache(bool a_useCache);
66 
67  // Points
68 
69  int GetPointCount() const;
70 
71  const VecPt3d& GetLocations() const;
72  void SetLocations(const VecPt3d& a_locations);
73 
74  Pt3d GetPointLocation(int a_pointIdx) const;
75  bool SetPointLocation(int a_pointIdx, const Pt3d& a_location);
76 
77  Pt3d GetPointXy0(int a_pointIdx) const;
78  VecPt3d GetPointsLocations(const VecInt& a_points) const;
79 
80  void GetExtents(Pt3d& a_min, Pt3d& a_max) const;
81 
82  int GetPointAdjacentCellCount(int a_pointIdx) const;
83  VecInt GetPointAdjacentCells(int a_pointIdx) const; // cells associated with point
84  void GetPointAdjacentCells(int a_pointIdx, VecInt& a_adjacentCells) const;
85 
86  VecInt GetPointsAdjacentCells(const VecInt& a_points) const;
87  void GetPointsAdjacentCells(const int* a_pointIdxs,
88  int a_numpointIdxs,
89  VecInt& a_commonCellIdxs) const;
90  void GetPointsAdjacentCells(const VecInt& a_pointIdxs, VecInt& a_commonCellIdxs) const;
91  void GetPointsAdjacentCells(int a_pointIdx1, int a_pointIdx2, VecInt& a_adjacentCellIdxs) const;
92  bool IsValidPointChange(int a_changedPtIdx, const Pt3d& a_newPosition) const;
93 
94  // Cells
95  int GetCellCount() const;
96 
97  int GetCellPointCount(int a_cellIdx) const;
98  VecInt GetCellPoints(int a_cellIdx) const;
99  bool GetCellPoints(int a_cellIdx, VecInt& a_cellPoints) const;
100  void GetCellLocations(int a_cellIdx, VecPt3d& a_cellLocations) const;
101 
102  XmUGridCellType GetCellType(int a_cellIdx) const;
103  std::vector<int> GetDimensionCounts() const;
104  int GetCellDimension(int a_cellIdx) const;
105  void GetCellExtents(int a_cellIdx, Pt3d& a_min, Pt3d& a_max) const;
106 
107  const VecInt& GetCellstream() const;
108  bool SetCellstream(const VecInt& a_cellstream);
109  bool GetCellCellstream(int a_cellIdx, VecInt& a_cellstream) const;
110 
111  VecInt GetCellAdjacentCells(int a_cellIdx) const;
112  void GetCellAdjacentCells(int a_cellIdx, VecInt& a_cellNeighbors) const;
113  bool GetCellPlanViewPolygon(int a_cellIdx, VecPt3d& a_polygon) const;
114  bool GetCellCentroid(int a_cellIdx, Pt3d& a_centroid) const;
115 
116  // Edges
117  int GetCellEdgeCount(int a_cellIdx) const;
118  XmEdge GetCellEdge(int a_cellIdx, int a_edgeIdx) const;
119  VecInt GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx) const;
120  void GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx, VecInt& a_adjacentCellIdxs) const;
121  int GetCell2dEdgeAdjacentCell(int a_cellIdx, int a_edgeIdx) const;
122  void GetEdgeAdjacentCells(const XmEdge& a_edge, VecInt& a_adjacentCellIdxs) const;
123 
124  VecInt GetEdgeAdjacentCells(const XmEdge& a_edge) const;
125 
126  std::vector<XmEdge> GetCellEdges(int a_cellIdx) const;
127  void GetCellEdges(int a_cellIdx, std::vector<XmEdge>& a_edges) const;
128  void GetPointAdjacentPoints(int a_pointIdx, VecInt& a_edgePoints) const;
129  void GetPointAdjacentLocations(int a_pointIdx, VecPt3d& a_edgePoints) const;
130 
131  // Faces
132  int GetCell3dFaceCount(int a_cellIdx) const;
133  int GetCell3dFacePointCount(int a_cellIdx, int a_faceIdx) const;
134 
135  VecInt GetCell3dFacePoints(int a_cellIdx, int a_faceIdx) const;
136  void GetCell3dFacePoints(int a_cellIdx, int a_faceIdx, VecInt& a_facePtIdxs) const;
137  VecInt2d GetCell3dFacesPoints(int a_cellIdx) const;
138 
139  int GetCell3dFaceAdjacentCell(int a_cellIdx, int a_faceIdx) const;
140  bool GetCell3dFaceAdjacentCell(int a_cellIdx,
141  int a_faceIdx,
142  int& a_neighborCell,
143  int& a_neighborFace) const;
144 
145  XmUGridFaceOrientation GetCell3dFaceOrientation(int a_cellIdx, int a_faceIdx) const;
146  XmUGridFaceOrientation FaceOrientation(int a_cellIdx, int a_faceIdx) const;
147  XmUGridFaceOrientation VerticalOrientationFromOpposing(int a_cellIdx, int a_faceIdx) const;
148  bool IsSideFace(int a_cellIdx, int a_faceIdx) const;
149  XmUGridFaceOrientation ConnectedTopOrBottom(int a_cellIdx, int a_faceIdx) const;
150  XmUGridFaceOrientation GetOrientationFromArea(int a_cellIdx, int a_faceIdx) const;
151 
152 private:
153  void UpdateLinks(); // Calls UpdateCellLinks & UpdatePointLinks
154  void UpdateCellLinks();
155  void UpdatePointLinks();
156 
157  void SetModified();
158 
159  bool IsCellValidWithPointChange(int a_cellIdx,
160  int a_changedPtIdx,
161  const Pt3d& a_newPosition) const;
162  bool IsValidCellIdx(int a_cellIdx) const;
163 
164  static int DimensionFromCellType(XmUGridCellType a_cellType);
165 
166  int GetNumberOfItemsForCell(int a_cellIdx) const;
167 
168  // Optimized for efficiency
169  void GetCellCellstream(int a_cellIdx, const int** a_start, int& a_length) const;
170 
171  int GetNumberOfPolyhedronEdges(int a_cellIdx) const;
172  static void GetUniquePointsFromPolyhedronCellstream(const VecInt& a_cellstream,
173  int a_numCellItems,
174  int& a_currIdx,
175  VecInt& a_uniqueGetCellPoints,
176  VecInt& a_pointLastUsedIdx);
177  static bool GetUniquePointsFromPolyhedronSingleCellstream(const VecInt& a_cellstream,
178  VecInt& a_cellPoints);
180  const int* a_start,
181  int& a_length,
182  boost::container::flat_set<XmEdge>& a_cellEdges,
183  int& a_currIdx);
184 
185  bool GetPlanViewPolygon2d(int a_cellIdx, VecPt3d& a_polygon) const;
186  bool GetPlanViewPolygon3d(int a_cellIdx, VecPt3d& a_polygon) const;
187 
188  bool IsFaceSide(const VecInt& a_facePts) const; // plan view
189  bool GetCellXySegments(int cellIdx, VecPt3d& a_segments) const; // plan view
190  void GetEdgesOfFace(const VecInt& a_face, std::vector<XmEdge>& a_edges) const;
191  bool DoEdgesCrossWithPointChange(int a_changedPtIdx,
192  const Pt3d& a_newPosition,
193  const std::vector<XmEdge>& a_edges) const;
194  void GetExtentsFromPoints(const VecPt3d& a_locations, Pt3d& a_min, Pt3d& a_max) const;
195  bool GetFaceXySegments(int a_cellIdx, int a_faceIdx, VecPt3d& a_segments) const; // plan view
196 
197  void CalculateCacheValues() const;
198  void ClearCacheValues();
199  int GetCell3dFaceCountNoCache(int a_cellIdx) const;
200  int GetCell3dFaceAdjacentCellNoCache(int a_cellIdx, int a_faceIdx) const;
201  XmUGridFaceOrientation GetCell3dFaceOrientationNoCache(int a_cellIdx, int a_faceIdx) const;
202  bool GetNextFaceColumn(const VecInt& a_facePoints,
203  int a_starti,
204  int& a_columnBegin,
205  int& a_columnEnd) const;
206  void GetFacePointSegments(const VecInt& a_facePts,
207  int a_columnBegin,
208  int a_columnEnd,
209  VecPt3d& a_segments) const;
210  XmUGridFaceOrientation FaceOrientationWithFail(int a_cellIdx, int a_faceIdx) const;
211 
215  };
216 
223  bool m_modified = false;
225  bool m_useCache = true;
231 };
232 
233 //----- Internal functions -----------------------------------------------------
234 namespace
235 {
236 const char* CELLSTREAM_OFFSETS = "CELLSTREAM_OFFSETS";
237 const char* POINTS_TO_CELLS = "POINTS_TO_CELLS";
238 const char* POINTS_TO_CELLS_OFFSETS = "POINTS_TO_CELLS_OFFSETS";
239 
240 typedef std::vector<XmEdge> VecEdge;
241 
242 //------------------------------------------------------------------------------
246 //------------------------------------------------------------------------------
247 const VecEdge& iGetEdgeOffsetTable(int a_cellType)
248 {
249  static const VecEdge fg_empty;
250  static const VecEdge fg_line = {{0, 1}};
251  static const VecEdge fg_triangle = {{0, 1}, {1, 2}, {2, 0}};
252  static const VecEdge fg_pixel = {{0, 1}, {1, 3}, {3, 2}, {2, 0}};
253  static const VecEdge fg_quad = {{0, 1}, {1, 2}, {2, 3}, {3, 0}};
254  static const VecEdge fg_tetra = {{0, 1}, {1, 2}, {2, 0}, {0, 3}, {1, 3}, {2, 3}};
255  static const VecEdge fg_wedge = {{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5},
256  {5, 3}, {0, 3}, {1, 4}, {2, 5}};
257  static const VecEdge fg_voxel = {{0, 1}, {1, 3}, {2, 3}, {0, 2}, {4, 5}, {5, 7},
258  {6, 7}, {4, 6}, {0, 4}, {1, 5}, {2, 6}, {3, 7}};
259  static const VecEdge fg_hexahedron = {{0, 1}, {1, 2}, {3, 2}, {0, 3}, {4, 5}, {5, 6},
260  {7, 6}, {4, 7}, {0, 4}, {1, 5}, {3, 7}, {2, 6}};
261  static const VecEdge fg_pyramid = {{0, 1}, {1, 2}, {2, 3}, {3, 0},
262  {0, 4}, {1, 4}, {2, 4}, {3, 4}};
263  static const VecEdge fg_pentagonalPrism = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 0},
264  {5, 6}, {6, 7}, {7, 8}, {8, 9}, {9, 5},
265  {0, 5}, {1, 6}, {2, 7}, {3, 8}, {4, 9}};
266  static const VecEdge fg_hexagonalPrism = {{0, 1}, {1, 2}, {2, 3}, {3, 4}, {4, 5}, {5, 0},
267  {6, 7}, {7, 8}, {8, 9}, {9, 10}, {10, 11}, {11, 6},
268  {0, 6}, {1, 7}, {2, 8}, {3, 9}, {4, 10}, {5, 11}};
269 
270  switch (a_cellType)
271  {
272  // invalid
273  case XMU_INVALID_CELL_TYPE:
274  return fg_empty;
275 
276  // 0D
277  case XMU_EMPTY_CELL:
278  case XMU_VERTEX:
279  case XMU_POLY_VERTEX:
280  case XMU_CONVEX_POINT_SET: // Special class of cells formed by convex group of
281  // points
282  return fg_empty;
283 
284  // 1D
285  case XMU_LINE:
286  return fg_line;
287 
288  // 2D
289  case XMU_TRIANGLE:
290  return fg_triangle;
291  case XMU_PIXEL:
292  return fg_pixel;
293  case XMU_QUAD:
294  return fg_quad;
295 
296  case XMU_POLYGON:
297  // should be using cell stream
298  XM_ASSERT(0);
299  return fg_empty;
300 
301  // 2D Not yet supported
302  case XMU_QUADRATIC_EDGE:
303  case XMU_PARAMETRIC_CURVE:
304  case XMU_HIGHER_ORDER_EDGE:
305  case XMU_CUBIC_LINE: // Cubic, isoparametric cell
306  case XMU_TRIANGLE_STRIP:
307  case XMU_QUADRATIC_TRIANGLE:
308  case XMU_BIQUADRATIC_TRIANGLE:
309  case XMU_HIGHER_ORDER_TRIANGLE:
310  case XMU_HIGHER_ORDER_POLYGON:
311  case XMU_QUADRATIC_POLYGON:
312  case XMU_PARAMETRIC_SURFACE:
313  case XMU_PARAMETRIC_TRI_SURFACE:
314  case XMU_PARAMETRIC_QUAD_SURFACE:
315  XM_ASSERT(0);
316  return fg_empty;
317 
318  // 3D dimensions
319  case XMU_TETRA:
320  return fg_tetra;
321  case XMU_WEDGE:
322  return fg_wedge;
323  case XMU_VOXEL:
324  return fg_voxel;
325  case XMU_HEXAHEDRON:
326  return fg_hexahedron;
327  case XMU_PYRAMID:
328  return fg_pyramid;
329  case XMU_PENTAGONAL_PRISM:
330  return fg_pentagonalPrism;
331  case XMU_HEXAGONAL_PRISM:
332  return fg_hexagonalPrism;
333  case XMU_POLYHEDRON:
334  // should be using cell stream
335  XM_ASSERT(0);
336  return fg_empty;
337 
338  // 3D Not yet supported
339  case XMU_QUADRATIC_TETRA:
340  case XMU_HIGHER_ORDER_TETRAHEDRON:
341  case XMU_QUADRATIC_WEDGE:
342  case XMU_QUADRATIC_LINEAR_WEDGE:
343  case XMU_BIQUADRATIC_QUADRATIC_WEDGE:
344  case XMU_HIGHER_ORDER_WEDGE:
345  case XMU_QUADRATIC_HEXAHEDRON:
346  case XMU_TRIQUADRATIC_HEXAHEDRON:
347  case XMU_BIQUADRATIC_QUADRATIC_HEXAHEDRON:
348  case XMU_HIGHER_ORDER_HEXAHEDRON:
349  case XMU_QUADRATIC_PYRAMID:
350  case XMU_HIGHER_ORDER_PYRAMID:
351  case XMU_PARAMETRIC_TETRA_REGION:
352  case XMU_PARAMETRIC_HEX_REGION:
353  XM_ASSERT(0);
354  return fg_empty;
355  default:
356  XM_ASSERT(0);
357  return fg_empty;
358  }
359 
360  XM_ASSERT(0);
361  return fg_empty;
362 } // iGetEdgeOffsetTable
363 //------------------------------------------------------------------------------
367 //------------------------------------------------------------------------------
368 const VecInt2d& iGetFaceOffsetTable(int a_cellType)
369 {
370  static const VecInt2d fg_empty;
371  static const VecInt2d fg_tetra = {{0, 1, 3}, {1, 2, 3}, {2, 0, 3}, {0, 2, 1}};
372  static const VecInt2d fg_wedge = {{0, 1, 2}, {3, 5, 4}, {0, 3, 4, 1}, {1, 4, 5, 2}, {2, 5, 3, 0}};
373  static const VecInt2d fg_voxel = {{0, 4, 6, 2}, {1, 3, 7, 5}, {0, 1, 5, 4},
374  {2, 6, 7, 3}, {0, 2, 3, 1}, {4, 5, 7, 6}};
375  static const VecInt2d fg_hexahedron = {{0, 4, 7, 3}, {1, 2, 6, 5}, {0, 1, 5, 4},
376  {3, 7, 6, 2}, {0, 3, 2, 1}, {4, 5, 6, 7}};
377  static const VecInt2d fg_pyramid = {{0, 3, 2, 1}, {0, 1, 4}, {1, 2, 4}, {2, 3, 4}, {3, 0, 4}};
378  static const VecInt2d fg_pentagonalPrism = {{0, 4, 3, 2, 1}, {5, 6, 7, 8, 9}, {0, 1, 6, 5},
379  {1, 2, 7, 6}, {2, 3, 8, 7}, {3, 4, 9, 8},
380  {4, 0, 5, 9}};
381  static const VecInt2d fg_hexagonalPrism = {
382  {0, 5, 4, 3, 2, 1}, {6, 7, 8, 9, 10, 11}, {0, 1, 7, 6}, {1, 2, 8, 7},
383  {2, 3, 9, 8}, {3, 4, 10, 9}, {4, 5, 11, 10}, {5, 0, 6, 11}};
384 
385  switch (a_cellType)
386  {
387  // invalid
388  // 0D
389  // 1D
390  case XMU_INVALID_CELL_TYPE:
391  case XMU_EMPTY_CELL:
392  case XMU_VERTEX:
393  case XMU_POLY_VERTEX:
394  case XMU_CONVEX_POINT_SET: // Special class of cells formed by convex group of
395  // points
396  case XMU_LINE:
397  case XMU_TRIANGLE:
398  case XMU_PIXEL:
399  case XMU_QUAD:
400  case XMU_POLYGON:
401  case XMU_POLY_LINE:
402  case XMU_QUADRATIC_EDGE:
403  case XMU_PARAMETRIC_CURVE:
404  case XMU_HIGHER_ORDER_EDGE:
405  case XMU_CUBIC_LINE: // Cubic, isoparametric cell
406  case XMU_TRIANGLE_STRIP:
407  case XMU_QUADRATIC_TRIANGLE:
408  case XMU_BIQUADRATIC_TRIANGLE:
409  case XMU_HIGHER_ORDER_TRIANGLE:
410  case XMU_HIGHER_ORDER_POLYGON:
411  case XMU_QUADRATIC_POLYGON:
412  case XMU_PARAMETRIC_SURFACE:
413  case XMU_PARAMETRIC_TRI_SURFACE:
414  case XMU_PARAMETRIC_QUAD_SURFACE:
415  return fg_empty;
416 
417  // 3D dimensions
418  case XMU_TETRA:
419  return fg_tetra;
420  case XMU_WEDGE:
421  return fg_wedge;
422  case XMU_VOXEL:
423  return fg_voxel;
424  case XMU_HEXAHEDRON:
425  return fg_hexahedron;
426  case XMU_PYRAMID:
427  return fg_pyramid;
428  case XMU_PENTAGONAL_PRISM:
429  return fg_pentagonalPrism;
430  case XMU_HEXAGONAL_PRISM:
431  return fg_hexagonalPrism;
432  case XMU_POLYHEDRON:
433  // should be using cell stream
434  XM_ASSERT(0);
435  return fg_empty;
436 
437  // 3D Not yet supported
438  case XMU_QUADRATIC_TETRA:
439  case XMU_HIGHER_ORDER_TETRAHEDRON:
440  case XMU_QUADRATIC_WEDGE:
441  case XMU_QUADRATIC_LINEAR_WEDGE:
442  case XMU_BIQUADRATIC_QUADRATIC_WEDGE:
443  case XMU_HIGHER_ORDER_WEDGE:
444  case XMU_QUADRATIC_HEXAHEDRON:
445  case XMU_TRIQUADRATIC_HEXAHEDRON:
446  case XMU_BIQUADRATIC_QUADRATIC_HEXAHEDRON:
447  case XMU_HIGHER_ORDER_HEXAHEDRON:
448  case XMU_QUADRATIC_PYRAMID:
449  case XMU_HIGHER_ORDER_PYRAMID:
450  case XMU_PARAMETRIC_TETRA_REGION:
451  case XMU_PARAMETRIC_HEX_REGION:
452  XM_ASSERT(0);
453  return fg_empty;
454  default:
455  XM_ASSERT(0);
456  return fg_empty;
457  }
458 
459  XM_ASSERT(0);
460  return fg_empty;
461 } // iGetFaceOffsetTable
462 //------------------------------------------------------------------------------
468 //------------------------------------------------------------------------------
469 bool iPointInSegmentBounds(const Pt3d& a_location, const Pt3d& a_first, const Pt3d& a_second)
470 {
471  bool inBounds = a_location.x >= std::min(a_first.x, a_second.x) &&
472  a_location.y >= std::min(a_first.y, a_second.y) &&
473  a_location.x <= std::max(a_first.x, a_second.x) &&
474  a_location.y <= std::max(a_first.y, a_second.y);
475  return inBounds;
476 } // iPointInSegmentBounds
477 //------------------------------------------------------------------------------
481 //------------------------------------------------------------------------------
482 template <typename T>
483 std::vector<T> iGetUniquePoints(const std::vector<T>& a_segments)
484 {
485  std::vector<T> points = a_segments;
486  std::sort(points.begin(), points.end());
487  auto pIt = std::unique(points.begin(), points.end());
488  points.resize(pIt - points.begin());
489  return points;
490 } // iGetUniquePoints
491 //------------------------------------------------------------------------------
495 //------------------------------------------------------------------------------
496 template <typename T>
497 void iBuildPolygon(std::vector<std::pair<T, T>>& a_segs, std::vector<T>& a_polygon)
498 {
499  xms::VecChar placed(a_segs.size(), false);
500  a_polygon.push_back(a_segs[0].first);
501  a_polygon.push_back(a_segs[0].second);
502  placed[0] = true;
503  for (size_t i = 1; i != a_segs.size(); ++i)
504  {
505  T& toMatch = a_polygon.back();
506  for (size_t j = 1; j != a_segs.size(); ++j)
507  {
508  if (!placed[j])
509  {
510  if (a_segs[j].first == toMatch)
511  {
512  a_polygon.push_back(a_segs[j].second);
513  placed[j] = true;
514  }
515  else if (a_segs[j].second == toMatch)
516  {
517  a_polygon.push_back(a_segs[j].first);
518  placed[j] = true;
519  }
520  }
521  }
522  }
523 } // iBuildPolygon
524 //------------------------------------------------------------------------------
529 //------------------------------------------------------------------------------
530 template <typename T>
531 std::vector<std::pair<T, T>> iGetUniqueSegments(const std::vector<T>& a_segments)
532 {
533  std::vector<std::pair<T, T>> segs;
534  for (size_t i = 0; i < a_segments.size(); i += 2)
535  {
536  T a = a_segments[i];
537  T b = a_segments[i + 1];
538  if (a < b)
539  segs.push_back(std::pair<T, T>(a, b));
540  else
541  segs.push_back(std::pair<T, T>(b, a));
542  }
543  std::sort(segs.begin(), segs.end());
544  auto segIt = std::unique(segs.begin(), segs.end());
545  segs.resize(segIt - segs.begin());
546  return segs;
547 } // iGetUniqueSegments
548 //------------------------------------------------------------------------------
553 //------------------------------------------------------------------------------
554 void iMergeSegmentsToPoly(const VecPt3d& a_segments, VecPt3d& a_polygon)
555 {
556  if (a_segments.empty())
557  return;
558 
559  VecPt3d points = iGetUniquePoints(a_segments);
560  std::vector<std::pair<Pt3d, Pt3d>> segs = iGetUniqueSegments(a_segments);
561 
562  // if any point is on any other segment split up the segment
563  for (auto& point : points)
564  {
565  size_t segsSize = segs.size();
566  for (size_t i = 0; i < segsSize; ++i)
567  {
568  Pt3d pt1 = segs[i].first;
569  Pt3d pt2 = segs[i].second;
570  if (point != pt1 && point != pt2 && iPointInSegmentBounds(point, pt1, pt2))
571  {
572  Pt3d diff = pt1 - pt2;
573  double distance = std::max(fabs(diff.x), fabs(diff.y));
574  double tolerance = distance / 1.0e6;
575  if (gmOnLineWithTol(pt1, pt2, point.x, point.y, tolerance))
576  {
577  segs.emplace_back(point, pt2);
578  segs[i].second = point;
579  }
580  }
581  }
582  }
583  std::sort(segs.begin(), segs.end());
584  auto segIt = std::unique(segs.begin(), segs.end());
585  segs.resize(segIt - segs.begin());
586 
587  iBuildPolygon(segs, a_polygon);
588 
589  if (a_polygon.size() > 3 && a_polygon.front() == a_polygon.back())
590  {
591  a_polygon.pop_back();
592  double area = gmPolygonArea(&a_polygon[0], (int)a_polygon.size());
593  if (area < 0)
594  std::reverse(a_polygon.begin(), a_polygon.end());
595  }
596  else
597  {
598  XM_ASSERT(0);
599  a_polygon.clear();
600  }
601 } // iMergeSegmentsToPoly
602 
603 } // namespace
604 
610 //------------------------------------------------------------------------------
613 //------------------------------------------------------------------------------
615 {
616  return m_modified;
617 } // XmUGrid::Impl::GetModified
618 //------------------------------------------------------------------------------
620 //------------------------------------------------------------------------------
622 {
623  m_modified = false;
624 } // XmUGrid::Impl::SetUnmodified
625 //------------------------------------------------------------------------------
627 //------------------------------------------------------------------------------
629 {
630  ClearCacheValues();
631  m_modified = true;
632 } // XmUGrid::Impl::SetModified
633 //------------------------------------------------------------------------------
636 //------------------------------------------------------------------------------
637 void XmUGrid::Impl::SetUseCache(bool a_useCache)
638 {
639  m_useCache = a_useCache;
640 } // XmUGrid::Impl::SetUseCache
641 // Points
642 //------------------------------------------------------------------------------
645 //------------------------------------------------------------------------------
647 {
648  return (int)m_locations.size();
649 } // XmUGrid::Impl::GetPointCount
650 //------------------------------------------------------------------------------
653 //------------------------------------------------------------------------------
655 {
656  return m_locations;
657 } // XmUGrid::Impl::GetLocations
658 //------------------------------------------------------------------------------
661 //------------------------------------------------------------------------------
662 void XmUGrid::Impl::SetLocations(const VecPt3d& a_locations)
663 {
664  m_locations = a_locations;
665  SetModified();
666 } // XmUGrid::Impl::SetLocations
667 //------------------------------------------------------------------------------
671 //------------------------------------------------------------------------------
673 {
674  if (a_pointIdx >= 0 && a_pointIdx < m_locations.size())
675  return m_locations[a_pointIdx];
676  return Pt3d();
677 } // XmUGrid::Impl::GetPointLocation
678 //------------------------------------------------------------------------------
683 //------------------------------------------------------------------------------
684 bool XmUGrid::Impl::SetPointLocation(int a_pointIdx, const Pt3d& a_location)
685 {
686  if (a_pointIdx >= 0 && a_pointIdx < m_locations.size())
687  {
688  m_locations[a_pointIdx] = a_location;
689  SetModified();
690  return true;
691  }
692  return false;
693 } // XmUGrid::Impl::SetPointLocation
694 
695 //------------------------------------------------------------------------------
699 //------------------------------------------------------------------------------
700 Pt3d XmUGrid::Impl::GetPointXy0(int a_pointIdx) const
701 {
702  Pt3d pt = GetPointLocation(a_pointIdx);
703  pt.z = 0.0;
704  return pt;
705 } // XmUGrid::Impl::GetPointXy0
706 
707 //------------------------------------------------------------------------------
711 //------------------------------------------------------------------------------
713 {
714  VecPt3d point3d;
715  for (auto point : a_points)
716  {
717  point3d.push_back(GetPointLocation(point));
718  }
719  return point3d;
720 } // XmUGrid::Impl::GetPointsLocations
721 
722 //------------------------------------------------------------------------------
726 //------------------------------------------------------------------------------
727 void XmUGrid::Impl::GetExtents(Pt3d& a_min, Pt3d& a_max) const
728 {
729  GetExtentsFromPoints(m_locations, a_min, a_max);
730 } // XmUGrid::Impl::GetExtents
731 
732 //------------------------------------------------------------------------------
736 //------------------------------------------------------------------------------
738 {
739  if (a_pointIdx < 0 || a_pointIdx >= m_locations.size())
740  return 0;
741  int numCells = m_pointsToCells[m_pointIdxToPointsToCells[a_pointIdx]];
742  return numCells;
743 } // XmUGrid::Impl::GetPointAdjacentCellCount
744 
745 //------------------------------------------------------------------------------
749 //------------------------------------------------------------------------------
751 {
752  VecInt cellsOfPoint;
753  GetPointAdjacentCells(a_pointIdx, cellsOfPoint);
754  return cellsOfPoint;
755 } // XmUGrid::Impl::GetPointAdjacentCells
756 //------------------------------------------------------------------------------
761 //------------------------------------------------------------------------------
762 void XmUGrid::Impl::GetPointAdjacentCells(int a_pointIdx, VecInt& a_adjacentCells) const
763 {
764  a_adjacentCells.clear();
765  int numCells = GetPointAdjacentCellCount(a_pointIdx);
766  for (int cellIdx = 0; cellIdx < numCells; cellIdx++)
767  {
768  a_adjacentCells.push_back(m_pointsToCells[m_pointIdxToPointsToCells[a_pointIdx] + cellIdx + 1]);
769  }
770 } // XmUGrid::Impl::GetPointAdjacentCells
771 //------------------------------------------------------------------------------
775 //------------------------------------------------------------------------------
777 {
778  VecInt commonCells;
779  if (!a_points.empty())
780  GetPointsAdjacentCells(&a_points[0], (int)a_points.size(), commonCells);
781  return commonCells;
782 } // XmUGrid::Impl::GetPointsAdjacentCells
783 //------------------------------------------------------------------------------
788 //------------------------------------------------------------------------------
789 void XmUGrid::Impl::GetPointsAdjacentCells(const int* a_pointIdxs,
790  int a_numPointIdxs,
791  VecInt& a_commonCellIdxs) const
792 {
793  a_commonCellIdxs.clear();
794  if (a_numPointIdxs == 0)
795  return;
796  a_commonCellIdxs = GetPointAdjacentCells(a_pointIdxs[0]);
797  for (int i = 1; i < a_numPointIdxs; ++i)
798  {
799  VecInt tempAssociatedCells = GetPointAdjacentCells(a_pointIdxs[i]);
800  VecInt remove;
801  for (int j = 0; j < a_commonCellIdxs.size(); ++j)
802  {
803  bool found = false;
804  for (int tempAssociatedCell : tempAssociatedCells)
805  {
806  if (a_commonCellIdxs[j] == tempAssociatedCell)
807  {
808  found = true;
809  break;
810  }
811  }
812  if (!found)
813  remove.push_back(j);
814  }
815  for (int j = (int)remove.size() - 1; j >= 0; --j)
816  {
817  a_commonCellIdxs.erase(a_commonCellIdxs.begin() + remove[j]);
818  }
819  if (a_commonCellIdxs.empty())
820  break;
821  }
822 } // XmUGrid::Impl::GetPointsAdjacentCells
823 //------------------------------------------------------------------------------
827 //------------------------------------------------------------------------------
829  VecInt& a_adjacentCellIdxs) const
830 {
831  if (!a_pointIdxs.empty())
832  GetPointsAdjacentCells(&a_pointIdxs[0], (int)a_pointIdxs.size(), a_adjacentCellIdxs);
833 } // XmUGrid::Impl::GetPointsAdjacentCells
834 //------------------------------------------------------------------------------
839 //------------------------------------------------------------------------------
841  int a_pointIdx2,
842  VecInt& a_adjacentCellIdxs) const
843 {
844  int points[] = {a_pointIdx1, a_pointIdx2};
845  GetPointsAdjacentCells(points, 2, a_adjacentCellIdxs);
846 } // XmUGrid::Impl::GetPointsAdjacentCells
847 // Cells
848 //------------------------------------------------------------------------------
851 //------------------------------------------------------------------------------
853 {
854  if (m_cellIdxToStreamIdx.empty())
855  return 0;
856  else
857  return (int)m_cellIdxToStreamIdx.size() - 1;
858 } // XmUGrid::Impl::GetCellCount
859 //------------------------------------------------------------------------------
863 //------------------------------------------------------------------------------
864 int XmUGrid::Impl::GetCellPointCount(int a_cellIdx) const
865 {
866  int pointCount = 0;
867  if (GetCellType(a_cellIdx) == XMU_POLYHEDRON)
868  {
869  boost::container::flat_set<int> uniqueIdxs;
870  const int* cellstream = nullptr;
871  int streamLength;
872  GetCellCellstream(a_cellIdx, &cellstream, streamLength);
873  if (cellstream)
874  {
875  int currIdx = 1;
876  int numFaces = cellstream[currIdx++];
877  for (int faceIdx = 0; faceIdx < numFaces; faceIdx++)
878  {
879  int numPoints = cellstream[currIdx++];
880  for (int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
881  {
882  int point = cellstream[currIdx++];
883  uniqueIdxs.insert(point);
884  }
885  }
886  }
887  pointCount = (int)uniqueIdxs.size();
888  }
889  else
890  {
891  pointCount = GetNumberOfItemsForCell(a_cellIdx);
892  }
893 
894  return pointCount;
895 } // XmUGrid::Impl::GetCellPointCount
896 //------------------------------------------------------------------------------
900 //------------------------------------------------------------------------------
902 {
903  VecInt pointsOfCell;
904  GetCellPoints(a_cellIdx, pointsOfCell);
905  return pointsOfCell;
906 } // XmUGrid::Impl::GetCellPoints
907 //------------------------------------------------------------------------------
912 //------------------------------------------------------------------------------
913 bool XmUGrid::Impl::GetCellPoints(int a_cellIdx, VecInt& a_cellPoints) const
914 {
915  a_cellPoints.clear();
916  VecInt cellstream;
917  if (GetCellCellstream(a_cellIdx, cellstream))
918  {
919  XM_ENSURE_TRUE_NO_ASSERT(!cellstream.empty(), false);
920  int cellType = cellstream[0];
921  if (cellType == XMU_POLYHEDRON)
922  {
923  GetUniquePointsFromPolyhedronSingleCellstream(cellstream, a_cellPoints);
924  return true;
925  }
926  else if (cellType == XMU_PIXEL)
927  {
928  a_cellPoints.push_back(cellstream[2]);
929  a_cellPoints.push_back(cellstream[3]);
930  a_cellPoints.push_back(cellstream[5]);
931  a_cellPoints.push_back(cellstream[4]);
932  return true;
933  }
934  else
935  {
936  a_cellPoints.assign(cellstream.begin() + 2, cellstream.end());
937  return true;
938  }
939  }
940  return false;
941 } // XmUGrid::Impl::GetCellPoints
942 
943 //------------------------------------------------------------------------------
947 //------------------------------------------------------------------------------
948 void XmUGrid::Impl::GetCellLocations(int a_cellIdx, VecPt3d& a_cellLocations) const
949 {
950  VecInt ptIdxs = GetCellPoints(a_cellIdx);
951  a_cellLocations = GetPointsLocations(ptIdxs);
952 } // XmUGrid::Impl::GetCellPoints
953 
954 //------------------------------------------------------------------------------
958 //------------------------------------------------------------------------------
960 {
961  if (a_cellIdx < 0 || m_cellIdxToStreamIdx.size() < 2 ||
962  a_cellIdx > m_cellIdxToStreamIdx.size() - 2)
963  {
964  return XMU_INVALID_CELL_TYPE;
965  }
966  else
967  {
968  int cellStart = m_cellIdxToStreamIdx[a_cellIdx];
969 #if _DEBUG
970  if ((m_cellstream[cellStart] > XMU_PYRAMID) && (m_cellstream[cellStart] != XMU_POLYHEDRON) ||
971  (m_cellstream[cellStart] == XMU_TRIANGLE_STRIP))
972  {
973  assert("UNSUPPORTED TYPE!");
974  }
975 #endif
976  return (XmUGridCellType)m_cellstream[cellStart];
977  }
978 } // XmUGrid::Impl::GetCellType
979 //------------------------------------------------------------------------------
982 //------------------------------------------------------------------------------
983 std::vector<int> XmUGrid::Impl::GetDimensionCounts() const
984 {
985  if (!m_cellDimensionCounts.empty())
986  {
987  return m_cellDimensionCounts;
988  }
989  else
990  {
991  m_cellDimensionCounts.clear();
992  m_cellDimensionCounts.resize(4, 0);
993  int itemp = 0;
994  int cellCount = GetCellCount();
995  for (int i = 0; i < cellCount; i++)
996  {
997  itemp = GetCellDimension(i);
998  if (itemp >= 0)
999  {
1000  m_cellDimensionCounts[itemp]++;
1001  }
1002  }
1003  return m_cellDimensionCounts;
1004  }
1005 } // XmUGrid::Impl::GetDimensionCounts
1006 //------------------------------------------------------------------------------
1011 //------------------------------------------------------------------------------
1012 int XmUGrid::Impl::GetCellDimension(int a_cellIdx) const
1013 {
1014  return DimensionFromCellType(GetCellType(a_cellIdx));
1015 } // XmUGrid::Impl::GetCellDimension
1016 
1017 //------------------------------------------------------------------------------
1022 //------------------------------------------------------------------------------
1023 void XmUGrid::Impl::GetCellExtents(int a_cellIdx, Pt3d& a_min, Pt3d& a_max) const
1024 {
1025  VecPt3d pts;
1026  GetCellLocations(a_cellIdx, pts);
1027  GetExtentsFromPoints(pts, a_min, a_max);
1028 } // XmUGrid::Impl::GetCellExtents
1029 
1030 //------------------------------------------------------------------------------
1033 //------------------------------------------------------------------------------
1035 {
1036  return m_cellstream;
1037 } // XmUGrid::Impl::GetCellstream
1038 //------------------------------------------------------------------------------
1050 //------------------------------------------------------------------------------
1051 bool XmUGrid::Impl::SetCellstream(const VecInt& a_cellstream)
1052 {
1053  if (IsValidCellstream(a_cellstream))
1054  {
1055  m_cellstream = a_cellstream;
1056  UpdateLinks();
1057  SetModified();
1058  return true;
1059  }
1060  else
1061  {
1062  XM_LOG(xmlog::error, "Invalid cell stream data.");
1063  return false;
1064  }
1065 } // XmUGrid::Impl::SetCellstream
1066 //------------------------------------------------------------------------------
1072 //------------------------------------------------------------------------------
1073 bool XmUGrid::Impl::GetCellCellstream(int a_cellIdx, VecInt& a_cellstream) const
1074 {
1075  a_cellstream.clear();
1076  if (a_cellIdx < 0 || m_cellIdxToStreamIdx.size() < 2 ||
1077  a_cellIdx > m_cellIdxToStreamIdx.size() - 2)
1078  {
1079  return false;
1080  }
1081  int startIndex(m_cellIdxToStreamIdx[a_cellIdx]), endIndex(m_cellIdxToStreamIdx[a_cellIdx + 1]);
1082  a_cellstream.assign(m_cellstream.begin() + startIndex, m_cellstream.begin() + endIndex);
1083  return true;
1084 } // XmUGrid::Impl::GetCellCellstream
1085 
1086 //------------------------------------------------------------------------------
1090 //------------------------------------------------------------------------------
1092 {
1093  VecInt neighbors;
1094  GetCellAdjacentCells(a_cellIdx, neighbors);
1095  return neighbors;
1096 } // XmUGrid::Impl::GetCellAdjacentCells
1097 //------------------------------------------------------------------------------
1101 //------------------------------------------------------------------------------
1102 void XmUGrid::Impl::GetCellAdjacentCells(int a_cellIdx, VecInt& a_cellNeighbors) const
1103 {
1104  a_cellNeighbors.clear();
1105  VecInt pointsOfCell;
1106  pointsOfCell = GetCellPoints(a_cellIdx);
1107  for (int pointIdx : pointsOfCell)
1108  {
1109  VecInt associatedCells = GetPointAdjacentCells(pointIdx);
1110  for (int associatedCell : associatedCells)
1111  {
1112  if (associatedCell != a_cellIdx)
1113  {
1114  bool found(false);
1115  for (int a_cellNeighbor : a_cellNeighbors)
1116  {
1117  if (a_cellNeighbor == associatedCell)
1118  {
1119  found = true;
1120  }
1121  }
1122  if (!found)
1123  {
1124  a_cellNeighbors.push_back(associatedCell);
1125  }
1126  }
1127  }
1128  }
1129 } // XmUGrid::Impl::GetCellAdjacentCells
1130 //------------------------------------------------------------------------------
1136 //------------------------------------------------------------------------------
1137 bool XmUGrid::Impl::GetCellPlanViewPolygon(int a_cellIdx, VecPt3d& a_polygon) const
1138 {
1139  a_polygon.clear();
1140  if (!IsValidCellIdx(a_cellIdx))
1141  return false;
1142  int dimension = GetCellDimension(a_cellIdx);
1143  if (dimension == 3)
1144  return GetPlanViewPolygon3d(a_cellIdx, a_polygon);
1145  else if (dimension == 2)
1146  return GetPlanViewPolygon2d(a_cellIdx, a_polygon);
1147  else
1148  return false;
1149 } // XmUGrid::Impl::GetCellPlanViewPolygon
1150 
1151 //------------------------------------------------------------------------------
1156 //------------------------------------------------------------------------------
1157 bool XmUGrid::Impl::GetCellCentroid(int a_cellIdx, Pt3d& a_centroid) const
1158 {
1159  VecPt3d polyPoints;
1160  bool retVal = true;
1161  Pt3d centroid = Pt3d(0.0, 0.0, 0.0);
1162  if (GetCellPlanViewPolygon(a_cellIdx, polyPoints))
1163  {
1164  centroid = gmComputePolygonCentroid(polyPoints);
1165  }
1166  else if (!IsValidCellIdx(a_cellIdx))
1167  {
1168  retVal = false;
1169  }
1170  else
1171  {
1172  VecPt3d cellPoints;
1173  GetCellLocations(a_cellIdx, cellPoints);
1174  for (Pt3d& pt : cellPoints)
1175  {
1176  centroid += pt;
1177  }
1178  centroid /= (double)cellPoints.size();
1179  }
1180  a_centroid = centroid;
1181  return retVal;
1182 } // XmUGrid::Impl::GetCellCentroid
1183 //------------------------------------------------------------------------------
1189 //------------------------------------------------------------------------------
1191  int a_changedPtIdx,
1192  const Pt3d& a_newPosition) const
1193 {
1194  if (GetCellDimension(a_cellIdx) == 2)
1195  {
1196  std::vector<XmEdge> edges = GetCellEdges(a_cellIdx);
1197  return !DoEdgesCrossWithPointChange(a_changedPtIdx, a_newPosition, edges);
1198  }
1199  else if (GetCellDimension(a_cellIdx) == 3)
1200  {
1201  // Go through the affected faces and if they are not a side face
1202  // check if the edges cross each other
1203  VecInt2d faces = GetCell3dFacesPoints(a_cellIdx);
1204  for (int faceIdx = 0; faceIdx < faces.size(); faceIdx++)
1205  {
1206  bool faceIsAffected = false;
1207  for (int ptIdx = 0; ptIdx < faces[faceIdx].size(); ptIdx++)
1208  {
1209  if (faces[faceIdx][ptIdx] == a_changedPtIdx)
1210  {
1211  faceIsAffected = true;
1212  }
1213  }
1214  if (faceIsAffected)
1215  {
1216  std::vector<XmEdge> edges;
1217  GetEdgesOfFace(faces[faceIdx], edges);
1218  if (DoEdgesCrossWithPointChange(a_changedPtIdx, a_newPosition, edges))
1219  return false;
1220  }
1221  }
1222  }
1223  return true;
1224 } // XmUGrid::Impl::IsCellValidWithPointChange
1225 //------------------------------------------------------------------------------
1229 //------------------------------------------------------------------------------
1230 bool XmUGrid::Impl::IsValidCellIdx(int a_cellIdx) const
1231 {
1232  return a_cellIdx >= 0 && a_cellIdx < GetCellCount();
1233 } // XmUGrid::Impl::IsValidCellIdx
1234 //------------------------------------------------------------------------------
1239 //------------------------------------------------------------------------------
1240 bool XmUGrid::Impl::IsValidPointChange(int a_changedPtIdx, const Pt3d& a_newPosition) const
1241 {
1242  bool validChange = false;
1243  if (a_changedPtIdx >= 0 && a_changedPtIdx < m_locations.size())
1244  {
1245  validChange = true;
1246  VecInt affectedCells = GetPointAdjacentCells(a_changedPtIdx);
1247  for (int affectedCell : affectedCells)
1248  {
1249  if (!IsCellValidWithPointChange(affectedCell, a_changedPtIdx, a_newPosition))
1250  {
1251  validChange = false;
1252  break;
1253  }
1254  }
1255  }
1256  return validChange;
1257 } // XmUGrid::Impl::IsValidPointChange
1258 //------------------------------------------------------------------------------
1262 //------------------------------------------------------------------------------
1263 void XmUGrid::Impl::GetEdgesOfFace(const VecInt& a_face, std::vector<XmEdge>& a_edges) const
1264 {
1265  a_edges.reserve(a_face.size());
1266  for (int i = 1; i < a_face.size(); ++i)
1267  {
1268  a_edges.emplace_back(a_face[i - 1], a_face[i]);
1269  }
1270  if (a_edges.size() > 1)
1271  a_edges.emplace_back(a_face[a_face.size() - 1], a_face[0]);
1272 } // XmUGrid::Impl::GetEdgesOfFace
1273 
1274 //------------------------------------------------------------------------------
1280 //------------------------------------------------------------------------------
1282  const Pt3d& a_newPosition,
1283  const std::vector<XmEdge>& a_edges) const
1284 {
1285  std::vector<std::pair<Pt3d, Pt3d>> changedEdges;
1286  std::vector<std::pair<Pt3d, Pt3d>> unChangedEdges;
1287  for (const auto& edge : a_edges)
1288  {
1289  if (edge.GetFirst() == a_changedPtIdx)
1290  {
1291  changedEdges.emplace_back(a_newPosition, GetPointLocation(edge.GetSecond()));
1292  }
1293  else if (edge.GetSecond() == a_changedPtIdx)
1294  {
1295  changedEdges.emplace_back(GetPointLocation(edge.GetFirst()), a_newPosition);
1296  }
1297  else
1298  {
1299  unChangedEdges.emplace_back(GetPointLocation(edge.GetFirst()),
1300  GetPointLocation(edge.GetSecond()));
1301  }
1302  }
1303  for (const auto& changedEdge : changedEdges)
1304  {
1305  for (const auto& unChangedEdge : unChangedEdges)
1306  {
1307  if (gmLinesCross(changedEdge.first, changedEdge.second, unChangedEdge.first,
1308  unChangedEdge.second))
1309  return true;
1310  }
1311  }
1312  return false;
1313 } // XmUGrid::Impl::DoEdgesCrossWithPointChange
1314 // Edges
1315 //------------------------------------------------------------------------------
1319 //------------------------------------------------------------------------------
1320 int XmUGrid::Impl::GetCellEdgeCount(int a_cellIdx) const
1321 {
1322  int cellType(GetCellType(a_cellIdx));
1323  switch (cellType)
1324  {
1325  // invalid
1326  case XMU_INVALID_CELL_TYPE:
1327  return -1;
1328  break;
1329 
1330  case XMU_POLY_LINE:
1331  return GetNumberOfItemsForCell(a_cellIdx) - 1;
1332  break;
1333 
1334  case XMU_POLYGON:
1335  return GetNumberOfItemsForCell(a_cellIdx);
1336  break;
1337 
1338  case XMU_POLYHEDRON:
1339  return GetNumberOfPolyhedronEdges(a_cellIdx);
1340  break;
1341 
1342  default:
1343  {
1344  const VecEdge& edgeTable = iGetEdgeOffsetTable(cellType);
1345  if (!edgeTable.empty())
1346  return (int)edgeTable.size();
1347  break;
1348  }
1349  }
1350 
1351  XM_ASSERT(0);
1352  return -1;
1353 } // XmUGrid::Impl::GetCellEdgeCount
1354 //------------------------------------------------------------------------------
1359 //------------------------------------------------------------------------------
1360 XmEdge XmUGrid::Impl::GetCellEdge(int a_cellIdx, int a_edgeIdx) const
1361 {
1362  XmEdge edge;
1363  if (a_edgeIdx < 0)
1364  return edge;
1365 
1366  const int* cellstream = nullptr;
1367  int streamLength;
1368  GetCellCellstream(a_cellIdx, &cellstream, streamLength);
1369  if (cellstream)
1370  {
1371  if (streamLength < 4)
1372  return edge;
1373 
1374  int cellType = cellstream[0];
1375  switch (cellType)
1376  {
1377  case XMU_POLY_LINE:
1378  case XMU_POLYGON:
1379  {
1380  int numPoints = cellstream[1];
1381  const int* cellPoints = cellstream + 2;
1382  int idx1 = cellPoints[a_edgeIdx];
1383  int idx2 = cellPoints[(a_edgeIdx + 1) % numPoints];
1384  edge = XmEdge(idx1, idx2);
1385  break;
1386  }
1387 
1388  case XMU_POLYHEDRON:
1389  {
1390  boost::container::flat_set<XmEdge> cellEdges;
1391  int currIdx = 2;
1392  GetUniqueEdgesFromPolyhedronCellstream(cellstream, streamLength, cellEdges, currIdx);
1393 
1394  if (a_edgeIdx < (int)cellEdges.size())
1395  edge = *(cellEdges.begin() + a_edgeIdx);
1396  break;
1397  }
1398 
1399  default:
1400  {
1401  const VecEdge& edgeTable = iGetEdgeOffsetTable(cellType);
1402  if (a_edgeIdx < (int)edgeTable.size())
1403  {
1404  const XmEdge& edgeOffset = edgeTable[a_edgeIdx];
1405  const int* cellPoints = cellstream + 2;
1406  int idx1 = cellPoints[edgeOffset.GetFirst()];
1407  int idx2 = cellPoints[edgeOffset.GetSecond()];
1408  edge = XmEdge(idx1, idx2);
1409  }
1410  break;
1411  }
1412  }
1413  }
1414 
1415  return edge;
1416 } // XmUGrid::Impl::GetCellEdge
1417 //------------------------------------------------------------------------------
1422 //------------------------------------------------------------------------------
1423 VecInt XmUGrid::Impl::GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx) const
1424 {
1425  VecInt adjacentCells;
1426  GetCellEdgeAdjacentCells(a_cellIdx, a_edgeIdx, adjacentCells);
1427  return adjacentCells;
1428 } // XmUGrid::Impl::GetCellEdgeAdjacentCells
1429 //------------------------------------------------------------------------------
1435 //------------------------------------------------------------------------------
1437  int a_edgeIdx,
1438  VecInt& a_adjacentCellIdxs) const
1439 {
1440  a_adjacentCellIdxs.clear();
1441  VecInt adjacentCells;
1442  VecInt cellNeighbors = GetCellAdjacentCells(a_cellIdx);
1443  if (cellNeighbors.empty())
1444  {
1445  return;
1446  }
1447  if (a_edgeIdx < 0 || a_edgeIdx >= GetCellEdgeCount(a_cellIdx))
1448  {
1449  return;
1450  }
1451 
1452  XmEdge currEdge, neighborEdge;
1453  currEdge = GetCellEdge(a_cellIdx, a_edgeIdx);
1454  for (int cellNeighbor : cellNeighbors)
1455  {
1456  for (int k(0); k < GetCellEdgeCount(cellNeighbor); k++)
1457  {
1458  neighborEdge = GetCellEdge(cellNeighbor, k);
1459  if (currEdge.IsEquivalent(neighborEdge))
1460  {
1461  a_adjacentCellIdxs.push_back(cellNeighbor);
1462  }
1463  }
1464  }
1465 } // XmUGrid::Impl::GetCellEdgeAdjacentCells
1466 //------------------------------------------------------------------------------
1471 //------------------------------------------------------------------------------
1472 int XmUGrid::Impl::GetCell2dEdgeAdjacentCell(int a_cellIdx, int a_edgeIdx) const
1473 {
1474  if (GetCellDimension(a_cellIdx) != 2)
1475  return -1;
1476 
1477  XmEdge edge = GetCellEdge(a_cellIdx, a_edgeIdx);
1478  int pointIdx = edge.GetFirst();
1479 
1480  int adjCellCount = GetPointAdjacentCellCount(pointIdx);
1481  for (int cellIdx = 0; cellIdx < adjCellCount; cellIdx++)
1482  {
1483  int adjacentCell = m_pointsToCells[m_pointIdxToPointsToCells[pointIdx] + cellIdx + 1];
1484  if (adjacentCell == a_cellIdx)
1485  continue;
1486 
1487  int edgeCount = GetCellEdgeCount(adjacentCell);
1488  for (int adjacentEdgeIdx = 0; adjacentEdgeIdx < edgeCount; ++adjacentEdgeIdx)
1489  {
1490  XmEdge adjacentEdge = GetCellEdge(adjacentCell, adjacentEdgeIdx);
1491  if (adjacentEdge.IsEquivalent(edge))
1492  return adjacentCell;
1493  }
1494  }
1495 
1496  return -1;
1497 } // XmUGrid::Impl::GetCell2dEdgeAdjacentCell
1498 //------------------------------------------------------------------------------
1502 //------------------------------------------------------------------------------
1503 void XmUGrid::Impl::GetEdgeAdjacentCells(const XmEdge& a_edge, VecInt& a_adjacentCellIdxs) const
1504 {
1505  a_adjacentCellIdxs.clear();
1506  GetPointsAdjacentCells(a_edge.GetFirst(), a_edge.GetSecond(), a_adjacentCellIdxs);
1507 } // XmUGrid::Impl::GetEdgeAdjacentCells
1508 //------------------------------------------------------------------------------
1512 //------------------------------------------------------------------------------
1514 {
1515  VecInt adjacentCellIdxs;
1516  GetEdgeAdjacentCells(a_edge, adjacentCellIdxs);
1517  return adjacentCellIdxs;
1518 } // XmUGrid::Impl::GetEdgeAdjacentCells
1519 //------------------------------------------------------------------------------
1523 //------------------------------------------------------------------------------
1524 std::vector<XmEdge> XmUGrid::Impl::GetCellEdges(int a_cellIdx) const
1525 {
1526  std::vector<XmEdge> edges;
1527  GetCellEdges(a_cellIdx, edges);
1528  return edges;
1529 } // XmUGrid::Impl::GetCellEdges
1530 //------------------------------------------------------------------------------
1534 //------------------------------------------------------------------------------
1535 void XmUGrid::Impl::GetCellEdges(int a_cellIdx, std::vector<XmEdge>& a_edges) const
1536 {
1537  a_edges.clear();
1538  int numEdges = GetCellEdgeCount(a_cellIdx);
1539  for (int i = 0; i < numEdges; ++i)
1540  {
1541  a_edges.push_back(GetCellEdge(a_cellIdx, i));
1542  }
1543 } // XmUGrid::Impl::GetCellEdges
1544 
1545 //------------------------------------------------------------------------------
1549 //------------------------------------------------------------------------------
1550 void XmUGrid::Impl::GetPointAdjacentPoints(int a_pointIdx, VecInt& a_edgePoints) const
1551 {
1552  a_edgePoints.clear();
1553  VecInt associatedCells = GetPointAdjacentCells(a_pointIdx);
1554  if (associatedCells.empty())
1555  {
1556  return;
1557  }
1558  for (int associatedCell : associatedCells)
1559  {
1560  for (int j = 0; j < GetCellEdgeCount(associatedCell); ++j)
1561  {
1562  XmEdge temp = GetCellEdge(associatedCell, j);
1563  if (temp.GetFirst() == a_pointIdx)
1564  {
1565  a_edgePoints.push_back(temp.GetSecond());
1566  }
1567  else if (temp.GetSecond() == a_pointIdx)
1568  {
1569  a_edgePoints.push_back(temp.GetFirst());
1570  }
1571  }
1572  }
1573  std::sort(a_edgePoints.begin(), a_edgePoints.end());
1574  auto it = std::unique(a_edgePoints.begin(), a_edgePoints.end());
1575  a_edgePoints.erase(it, a_edgePoints.end());
1576 } // XmUGrid::Impl::GetPointAdjacentPoints
1577 
1578 //------------------------------------------------------------------------------
1582 //------------------------------------------------------------------------------
1583 void XmUGrid::Impl::GetPointAdjacentLocations(int a_pointIdx, VecPt3d& a_edgePoints) const
1584 {
1585  VecInt edgePtIdxs;
1586  GetPointAdjacentPoints(a_pointIdx, edgePtIdxs);
1587  a_edgePoints = GetPointsLocations(edgePtIdxs);
1588 } // XmUGrid::Impl::GetPointAdjacentLocations
1589 
1590 // Faces
1591 //------------------------------------------------------------------------------
1595 //------------------------------------------------------------------------------
1596 int XmUGrid::Impl::GetCell3dFaceCount(int a_cellIdx) const
1597 {
1598  if (m_useCache)
1599  {
1600  CalculateCacheValues();
1601  int faceCount = IsValidCellIdx(a_cellIdx) ? m_numberOfFaces[a_cellIdx] : -1;
1602  return faceCount;
1603  }
1604  else
1605  {
1606  return GetCell3dFaceCountNoCache(a_cellIdx);
1607  }
1608 } // XmUGrid::Impl::GetCell3dFaceCount
1609 
1610 //------------------------------------------------------------------------------
1615 //------------------------------------------------------------------------------
1616 int XmUGrid::Impl::GetCell3dFacePointCount(int a_cellIdx, int a_faceIdx) const
1617 {
1618  if (!IsValidCellIdx(a_cellIdx))
1619  {
1620  return -1;
1621  }
1622 
1623  int cellType = GetCellType(a_cellIdx);
1624  if (cellType == XMU_POLYHEDRON)
1625  {
1626  const int* cellstream;
1627  int length;
1628  GetCellCellstream(a_cellIdx, &cellstream, length);
1629  if (cellstream != nullptr)
1630  {
1631  auto currItem = cellstream;
1632  currItem++; // skip cell type
1633  int numFaces = *currItem++;
1634  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
1635  {
1636  int numFacePoints = *currItem++;
1637  if (a_faceIdx == faceIdx)
1638  {
1639  return numFacePoints;
1640  }
1641  currItem += numFacePoints;
1642  }
1643  }
1644  }
1645  else
1646  {
1647  const VecInt2d& faceTable = iGetFaceOffsetTable(cellType);
1648  if (a_faceIdx >= 0 && a_faceIdx < (int)faceTable.size())
1649  {
1650  return (int)faceTable[a_faceIdx].size();
1651  }
1652  }
1653 
1654  return 0;
1655 } // XmUGrid::Impl::GetCell3dFacePointCount
1656 
1657 //------------------------------------------------------------------------------
1662 //------------------------------------------------------------------------------
1663 VecInt XmUGrid::Impl::GetCell3dFacePoints(int a_cellIdx, int a_faceIdx) const
1664 {
1665  VecInt facePoints;
1666  GetCell3dFacePoints(a_cellIdx, a_faceIdx, facePoints);
1667  return facePoints;
1668 } // XmUGrid::Impl::GetCell3dFacePoints
1669 //------------------------------------------------------------------------------
1674 //------------------------------------------------------------------------------
1675 void XmUGrid::Impl::GetCell3dFacePoints(int a_cellIdx, int a_faceIdx, VecInt& a_facePtIdxs) const
1676 {
1677  a_facePtIdxs.clear();
1678  if (a_faceIdx < 0)
1679  {
1680  return;
1681  }
1682 
1683  const int* cellstream = nullptr;
1684  int streamLength;
1685  GetCellCellstream(a_cellIdx, &cellstream, streamLength);
1686  if (!cellstream)
1687  return;
1688 
1689  int cellType = *cellstream++;
1690  if (cellType == XMU_POLYHEDRON)
1691  {
1692  int numFaces = *cellstream++;
1693  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
1694  {
1695  int numFacePoints = *cellstream++;
1696  if (faceIdx == a_faceIdx)
1697  {
1698  a_facePtIdxs.assign(cellstream, cellstream + numFacePoints);
1699  break;
1700  }
1701  cellstream += numFacePoints;
1702  }
1703  }
1704  else
1705  {
1706  const VecInt2d& faceTable = iGetFaceOffsetTable(cellType);
1707  if (a_faceIdx < (int)faceTable.size())
1708  {
1709  if (cellstream)
1710  {
1711  const int* cellPoints = ++cellstream;
1712  const VecInt& faceOffsets = faceTable[a_faceIdx];
1713  for (auto offset : faceOffsets)
1714  {
1715  int idx = cellPoints[offset];
1716  a_facePtIdxs.push_back(idx);
1717  }
1718  }
1719  }
1720  }
1721 } // XmUGrid::Impl::GetCell3dFacePoints
1722 //------------------------------------------------------------------------------
1726 //------------------------------------------------------------------------------
1728 {
1729  int numFaces = GetCell3dFaceCount(a_cellIdx);
1730 
1731  VecInt2d faces(numFaces);
1732  for (int i(0); i < numFaces; i++)
1733  {
1734  faces[i] = GetCell3dFacePoints(a_cellIdx, i);
1735  }
1736  return faces;
1737 } // XmUGrid::Impl::GetCell3dFacesPoints
1738 //------------------------------------------------------------------------------
1743 //------------------------------------------------------------------------------
1744 int XmUGrid::Impl::GetCell3dFaceAdjacentCell(int a_cellIdx, int a_faceIdx) const
1745 {
1746  if (m_useCache)
1747  {
1748  CalculateCacheValues();
1749  int faceNeighbor = -1;
1750  int numFaces = GetCell3dFaceCount(a_cellIdx);
1751  if (a_faceIdx >= 0 && a_faceIdx < numFaces)
1752  {
1753  int faceOffset = m_cellFaceOffset[a_cellIdx];
1754  if (faceOffset >= 0)
1755  {
1756  faceOffset += a_faceIdx;
1757  faceNeighbor = m_faceNeighbor[faceOffset];
1758  if (faceNeighbor == NEEDS_CALCULATION)
1759  {
1760  faceNeighbor = GetCell3dFaceAdjacentCellNoCache(a_cellIdx, a_faceIdx);
1761  m_faceNeighbor[faceOffset] = faceNeighbor;
1762  }
1763  else
1764  {
1765  faceNeighbor = m_faceNeighbor[faceOffset];
1766  }
1767  }
1768  }
1769  return faceNeighbor;
1770  }
1771  else
1772  {
1773  return GetCell3dFaceAdjacentCellNoCache(a_cellIdx, a_faceIdx);
1774  }
1775 } // XmUGrid::Impl::GetCell3dFaceAdjacentCell
1776 //------------------------------------------------------------------------------
1784 //------------------------------------------------------------------------------
1786  int a_faceIdx,
1787  int& a_neighborCell,
1788  int& a_neighborFace) const
1789 {
1790  a_neighborCell = GetCell3dFaceAdjacentCell(a_cellIdx, a_faceIdx);
1791  if (a_neighborCell < 0)
1792  {
1793  a_neighborCell = a_neighborFace = -1;
1794  return false;
1795  }
1796  VecInt cellFacePts = GetCell3dFacePoints(a_cellIdx, a_faceIdx);
1797  for (int faceIdx(0); faceIdx < GetCell3dFaceCount(a_neighborCell); faceIdx++)
1798  {
1799  VecInt curCellFacePts = GetCell3dFacePoints(a_neighborCell, faceIdx);
1800  if (cellFacePts.size() == curCellFacePts.size())
1801  {
1802  int cellFacePtsIdx(0);
1803  for (; cellFacePtsIdx < (int)cellFacePts.size(); ++cellFacePtsIdx)
1804  {
1805  bool found = false;
1806  for (int curCellFacePt : curCellFacePts)
1807  {
1808  if (cellFacePts[cellFacePtsIdx] == curCellFacePt)
1809  {
1810  found = true;
1811  break;
1812  }
1813  }
1814  if (!found)
1815  break; // This face is not the face we are l.
1816  }
1817  if (cellFacePtsIdx == (int)cellFacePts.size()) // Every point is found
1818  {
1819  a_neighborFace = faceIdx;
1820  a_neighborFace = faceIdx;
1821  return true;
1822  }
1823  }
1824  }
1825  a_neighborCell = a_neighborFace = -1;
1826  return false;
1827 } // XmUGrid::Impl::GetCell3dFaceAdjacentCell
1828 //------------------------------------------------------------------------------
1833 //------------------------------------------------------------------------------
1835 {
1836  if (m_useCache)
1837  {
1838  CalculateCacheValues();
1839  int faceOrientation = XMU_ORIENTATION_UNKNOWN;
1840  int numFaces = GetCell3dFaceCount(a_cellIdx);
1841  if (a_faceIdx >= 0 && a_faceIdx < numFaces)
1842  {
1843  int faceOffset = m_cellFaceOffset[a_cellIdx];
1844  if (faceOffset >= 0)
1845  {
1846  faceOffset += a_faceIdx;
1847  faceOrientation = m_faceOrientation[faceOffset];
1848  if (faceOrientation == NEEDS_CALCULATION)
1849  {
1850  faceOrientation = (int)GetCell3dFaceOrientationNoCache(a_cellIdx, a_faceIdx);
1851  m_faceOrientation[faceOffset] = faceOrientation;
1852  }
1853  else
1854  {
1855  faceOrientation = m_faceOrientation[faceOffset];
1856  }
1857  }
1858  }
1859  return (XmUGridFaceOrientation)faceOrientation;
1860  }
1861  else
1862  {
1863  return GetCell3dFaceOrientationNoCache(a_cellIdx, a_faceIdx);
1864  }
1865 } // XmUGrid::Impl::GetCell3dFaceOrientation
1866 //------------------------------------------------------------------------------
1871 //------------------------------------------------------------------------------
1872 XmUGridFaceOrientation XmUGrid::Impl::FaceOrientation(int a_cellIdx, int a_faceIdx) const
1873 {
1874  XmUGridFaceOrientation orientation = FaceOrientationWithFail(a_cellIdx, a_faceIdx);
1875  if (orientation == XMU_ORIENTATION_UNKNOWN)
1876  {
1877  // Is there any way to know if we reach this point? First face top and next
1878  // bottom? What about multi-panel top with no cell above?
1879  // XM_ASSERT(0);
1880  orientation = VerticalOrientationFromOpposing(a_cellIdx, a_faceIdx);
1881  }
1882 
1883  XM_ASSERT(orientation != XMU_ORIENTATION_UNKNOWN);
1884  return orientation;
1885 } // XmUGrid::Impl::FaceOrientation
1886 //------------------------------------------------------------------------------
1889 //------------------------------------------------------------------------------
1891 {
1892  UpdateCellLinks();
1893  UpdatePointLinks();
1894 } // XmUGrid::Impl::UpdateLinks
1895 //------------------------------------------------------------------------------
1897 //------------------------------------------------------------------------------
1899 {
1900  m_cellIdxToStreamIdx.clear();
1901 
1902  int currIdx = 0;
1903  if (m_cellstream.empty())
1904  {
1905  m_cellIdxToStreamIdx.push_back(currIdx);
1906  return;
1907  }
1908 
1909  int numItems = (int)m_cellstream.size();
1910  while (currIdx < numItems)
1911  {
1912  m_cellIdxToStreamIdx.push_back(currIdx);
1913 
1914  // get cell type
1915  int cellType = m_cellstream[currIdx++];
1916  if (currIdx >= numItems)
1917  return;
1918 
1919  // get the number of items
1920  int numPoints = m_cellstream[currIdx++];
1921  if (currIdx >= numItems)
1922  return;
1923 
1924  if (cellType == XMU_POLYHEDRON)
1925  {
1926  int numFaces = numPoints;
1927  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
1928  {
1929  int numFacePoints = m_cellstream[currIdx++];
1930  currIdx += numFacePoints;
1931  }
1932  }
1933  else
1934  {
1935  currIdx += numPoints;
1936  }
1937  }
1938 
1939  m_cellIdxToStreamIdx.push_back(currIdx);
1940 } // XmUGrid::Impl::UpdateCellLinks
1941 //------------------------------------------------------------------------------
1943 //------------------------------------------------------------------------------
1945 {
1946  m_pointIdxToPointsToCells.clear();
1947  m_pointIdxToPointsToCells.resize(m_locations.size(), 0);
1948  m_pointsToCells.clear();
1949 
1950  // get number of cells for each point
1951  int numStreamItems = (int)m_cellstream.size();
1952  int cellIdx = 0;
1953  int currIdx = 0;
1954  VecInt pointLastUsedIdx(m_locations.size(), -1);
1955  VecInt cellPoints;
1956  while (currIdx < numStreamItems)
1957  {
1958  // get cell type
1959  int cellType = m_cellstream[currIdx++];
1960  if (currIdx >= numStreamItems)
1961  return;
1962 
1963  // get the number of items (points or faces depending on cell type)
1964  int numCellItems = m_cellstream[currIdx++];
1965  if (currIdx >= numStreamItems)
1966  return;
1967 
1968  if (cellType == XMU_POLYHEDRON)
1969  {
1970  GetUniquePointsFromPolyhedronCellstream(m_cellstream, numCellItems, currIdx, cellPoints,
1971  pointLastUsedIdx);
1972 
1973  // Deemed to be slower than flat set-- Left only as a warning to others!
1974  // std::stable_sort(cellPoints.begin(), cellPoints.end());
1975  // auto uniqueEnd = std::unique(cellPoints.begin(), cellPoints.end());
1976 
1977  // flat set deemed to be slower than marking when a point was last used (pointLastUsedIdx)
1978 
1979  // for (auto pt = cellPoints.begin(); pt != uniqueEnd; ++pt)
1980  for (auto cellPoint : cellPoints)
1981  {
1982  m_pointIdxToPointsToCells[cellPoint] += 1;
1983  }
1984  }
1985  else
1986  {
1987  // iterate on points
1988  int numPoints = numCellItems;
1989  for (int ptIdx = 0; ptIdx < numPoints; ++ptIdx)
1990  {
1991  int pt = m_cellstream[currIdx++];
1992  m_pointIdxToPointsToCells[pt] += 1;
1993  }
1994  }
1995 
1996  ++cellIdx;
1997  }
1998  m_pointIdxToPointsToCells.push_back(0);
1999 
2000  // change array of counts to array of offsets
2001  int currCount = 0;
2002  for (auto& item : m_pointIdxToPointsToCells)
2003  {
2004  int count = item + 1;
2005  item = currCount;
2006  currCount += count;
2007  }
2008 
2009  cellIdx = 0;
2010  currIdx = 0;
2011  m_pointsToCells.resize(currCount, 0);
2012  std::fill(pointLastUsedIdx.begin(), pointLastUsedIdx.end(), -1);
2013  while (currIdx < numStreamItems)
2014  {
2015  // get cell type
2016  int cellType = m_cellstream[currIdx++];
2017  if (currIdx >= numStreamItems)
2018  return;
2019 
2020  // get the number of items (points or faces depending on cell type)
2021  int numCellItems = m_cellstream[currIdx++];
2022  if (currIdx >= numStreamItems)
2023  return;
2024 
2025  if (cellType == XMU_POLYHEDRON)
2026  {
2027  GetUniquePointsFromPolyhedronCellstream(m_cellstream, numCellItems, currIdx, cellPoints,
2028  pointLastUsedIdx);
2029 
2030  // Deemed to be slower than flat set-- Left only as a warning to others!
2031  // std::stable_sort(cellPoints.begin(), cellPoints.end());
2032  // auto uniqueEnd = std::unique(cellPoints.begin(), cellPoints.end());
2033 
2034  // for (auto pt = cellPoints.begin(); pt != uniqueEnd; ++pt)
2035  for (auto cellPoint : cellPoints)
2036  {
2037  int countIdx = m_pointIdxToPointsToCells[cellPoint];
2038  int& count = m_pointsToCells[countIdx]; // point's cell count
2039  ++count; // incrementing point's cell count
2040  int updateIdx = countIdx + count;
2041  m_pointsToCells[updateIdx] = cellIdx;
2042  }
2043  }
2044  else
2045  {
2046  // iterate on points
2047  int numPoints = numCellItems;
2048  for (int ptIdx = 0; ptIdx < numPoints; ++ptIdx)
2049  {
2050  int pt = m_cellstream[currIdx++];
2051  int countIdx = m_pointIdxToPointsToCells[pt];
2052  int& count = m_pointsToCells[countIdx]; // point's cell count
2053  ++count; // incrementing point's cell count
2054  int updateIdx = countIdx + count;
2055  m_pointsToCells[updateIdx] = cellIdx;
2056  }
2057  }
2058 
2059  ++cellIdx;
2060  }
2061 } // XmUGrid::Impl::UpdatePointLinks
2062 //------------------------------------------------------------------------------
2066 //------------------------------------------------------------------------------
2068 {
2069  switch (a_cellType)
2070  {
2071  // invalid
2072  case XMU_INVALID_CELL_TYPE:
2073  return -1;
2074  break;
2075 
2076  // 0D
2077  case XMU_EMPTY_CELL:
2078  case XMU_VERTEX:
2079  case XMU_POLY_VERTEX:
2080  case XMU_CONVEX_POINT_SET: // Special class of cells formed by convex group of
2081  // points
2082  return 0;
2083  break;
2084 
2085  // 1D
2086  case XMU_LINE:
2087  case XMU_POLY_LINE:
2088 
2089  case XMU_QUADRATIC_EDGE:
2090  case XMU_PARAMETRIC_CURVE:
2091  case XMU_HIGHER_ORDER_EDGE:
2092  case XMU_CUBIC_LINE: // Cubic, isoparametric cell
2093  return 1;
2094  break;
2095  // 2D
2096  case XMU_TRIANGLE:
2097  case XMU_TRIANGLE_STRIP:
2098  case XMU_POLYGON:
2099  case XMU_PIXEL:
2100  case XMU_QUAD:
2101 
2102  case XMU_QUADRATIC_TRIANGLE:
2103  case XMU_QUADRATIC_QUAD:
2104  case XMU_BIQUADRATIC_QUAD:
2105  case XMU_QUADRATIC_LINEAR_QUAD:
2106  case XMU_BIQUADRATIC_TRIANGLE:
2107  case XMU_QUADRATIC_POLYGON:
2108 
2109  case XMU_PARAMETRIC_SURFACE:
2110  case XMU_PARAMETRIC_TRI_SURFACE:
2111  case XMU_PARAMETRIC_QUAD_SURFACE:
2112 
2113  case XMU_HIGHER_ORDER_TRIANGLE:
2114  case XMU_HIGHER_ORDER_QUAD:
2115  case XMU_HIGHER_ORDER_POLYGON:
2116 
2117  return 2;
2118  break;
2119 
2120  // assuming the rest are 3D
2121  default:
2122  return 3;
2123  break;
2124 #if 0 // Remaining definitions
2125  XMU_TETRA = 10,
2126  XMU_VOXEL = 11,
2127  XMU_HEXAHEDRON = 12,
2128  XMU_WEDGE = 13,
2129  XMU_PYRAMID = 14,
2130  XMU_PENTAGONAL_PRISM = 15,
2131  XMU_HEXAGONAL_PRISM = 16,
2132 
2133  // Quadratic, isoparametric cells
2134  XMU_QUADRATIC_TETRA = 24,
2135  XMU_QUADRATIC_HEXAHEDRON = 25,
2136  XMU_QUADRATIC_WEDGE = 26,
2137  XMU_QUADRATIC_PYRAMID = 27,
2138  XMU_TRIQUADRATIC_HEXAHEDRON = 29,
2139  XMU_QUADRATIC_LINEAR_WEDGE = 31,
2140  XMU_BIQUADRATIC_QUADRATIC_WEDGE = 32,
2141  XMU_BIQUADRATIC_QUADRATIC_HEXAHEDRON = 33,
2142 
2143  // Polyhedron cell (consisting of polygonal faces)
2144  XMU_POLYHEDRON = 42,
2145 
2146  // Higher order cells in parametric form
2147  XMU_PARAMETRIC_TETRA_REGION = 55,
2148  XMU_PARAMETRIC_HEX_REGION = 56,
2149 
2150  // Higher order cells
2151  XMU_HIGHER_ORDER_TETRAHEDRON = 64,
2152  XMU_HIGHER_ORDER_WEDGE = 65,
2153  XMU_HIGHER_ORDER_PYRAMID = 66,
2154  XMU_HIGHER_ORDER_HEXAHEDRON = 67,
2155 #endif
2156  }
2157  return -1;
2158 
2159 } // XmUGrid::Impl::DimensionFromCellType
2160 
2161 //------------------------------------------------------------------------------
2166 //------------------------------------------------------------------------------
2168 {
2169  int cellType = GetCellType(a_cellIdx);
2170  if (cellType == XMU_INVALID_CELL_TYPE)
2171  {
2172  return 0;
2173  }
2174  else if (cellType != XMU_POLYHEDRON)
2175  {
2176  // Number of points is right after cell type
2177  int startIndex = m_cellIdxToStreamIdx[a_cellIdx];
2178  return m_cellstream[startIndex + 1];
2179  }
2180  else
2181  { // Polyhedron case, same value is number of faces
2182  int startIndex = m_cellIdxToStreamIdx[a_cellIdx];
2183  return m_cellstream[startIndex + 1];
2184  }
2185 } // XmUGrid::Impl::GetNumberOfItemsForCell
2186 //------------------------------------------------------------------------------
2192 //------------------------------------------------------------------------------
2193 void XmUGrid::Impl::GetCellCellstream(int a_cellIdx, const int** a_start, int& a_length) const
2194 {
2195  int cellType = GetCellType(a_cellIdx);
2196  if (cellType == XMU_INVALID_CELL_TYPE)
2197  {
2198  *a_start = nullptr;
2199  a_length = 0;
2200  }
2201  else
2202  {
2203  int startIndex = m_cellIdxToStreamIdx[a_cellIdx];
2204  int nextCellIndex = m_cellIdxToStreamIdx[a_cellIdx + 1];
2205  *a_start = &m_cellstream[startIndex];
2206  a_length = nextCellIndex - startIndex;
2207  }
2208 } // XmUGrid::Impl::GetCellCellstream
2209 //------------------------------------------------------------------------------
2213 //------------------------------------------------------------------------------
2215 {
2216  const int* cellstream;
2217  int streamLength;
2218  GetCellCellstream(a_cellIdx, &cellstream, streamLength);
2219  if (cellstream && streamLength > 0 && cellstream[0] == XMU_POLYHEDRON)
2220  {
2221  boost::container::flat_set<XmEdge> edges;
2222  int currItem = 2;
2223  while (currItem < streamLength)
2224  {
2225  GetUniqueEdgesFromPolyhedronCellstream(cellstream, streamLength, edges, currItem);
2226  }
2227  return (int)edges.size();
2228  }
2229  return 0;
2230 } // XmUGrid::Impl::GetNumberOfPolyhedronEdges
2231 //------------------------------------------------------------------------------
2243 //------------------------------------------------------------------------------
2245  int a_numCellItems,
2246  int& a_currIdx,
2247  VecInt& a_uniqueGetCellPoints,
2248  VecInt& a_pointLastUsedIdx)
2249 {
2250  int stable = a_currIdx;
2251  a_uniqueGetCellPoints.clear();
2252  int numFaces = a_numCellItems;
2253  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
2254  {
2255  int numFacePoints = a_cellstream[a_currIdx++];
2256  for (int ptIdx = 0; ptIdx < numFacePoints; ++ptIdx)
2257  {
2258  int pt = a_cellstream[a_currIdx++];
2259  if (a_pointLastUsedIdx[pt] < stable)
2260  {
2261  a_pointLastUsedIdx[pt] = stable;
2262  a_uniqueGetCellPoints.push_back(pt);
2263  }
2264  }
2265  }
2266 } // XmUGrid::Impl::GetUniquePointsFromPolyhedronCellstream
2267 //------------------------------------------------------------------------------
2272 //------------------------------------------------------------------------------
2274  VecInt& a_cellPoints)
2275 {
2276  a_cellPoints.clear();
2277  if (a_cellstream.size() < 2)
2278  {
2279  return false;
2280  }
2281 
2282  auto currItem = a_cellstream.begin();
2283  int cellType = *currItem++;
2284  if (cellType != XMU_POLYHEDRON)
2285  {
2286  return false;
2287  }
2288 
2289  int numFaces = *currItem++;
2290  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
2291  {
2292  int numFacePoints = *currItem++;
2293  for (int ptIdx = 0; ptIdx < numFacePoints; ++ptIdx)
2294  {
2295  int pt = *currItem++;
2296  if (std::find(a_cellPoints.begin(), a_cellPoints.end(), pt) == a_cellPoints.end())
2297  {
2298  a_cellPoints.push_back(pt);
2299  }
2300  }
2301  }
2302 
2303  return true;
2304 } // XmUGrid::Impl::GetUniquePointsFromPolyhedronSingleCellstream
2305 //------------------------------------------------------------------------------
2315 //------------------------------------------------------------------------------
2317  const int* a_start,
2318  int& a_length,
2319  boost::container::flat_set<XmEdge>& a_cellEdges,
2320  int& a_currIdx)
2321 {
2322  int numFaces = a_start[1];
2323  for (int i(0); i < numFaces; i++)
2324  {
2325  int numPoints = a_start[a_currIdx++];
2326  for (int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
2327  {
2328  int pt1Idx = pointIdx;
2329  int pt2Idx = (pointIdx + 1) % numPoints;
2330  // The % operator will reset the index back 0 so the final loop will
2331  // provide the last and first point
2332  int pt1 = a_start[a_currIdx + pt1Idx];
2333  int pt2 = a_start[a_currIdx + pt2Idx];
2334  // We want unique edges, so we add the lower point index first
2335  if (pt1 < pt2)
2336  a_cellEdges.insert(XmEdge(pt1, pt2));
2337  else
2338  a_cellEdges.insert(XmEdge(pt2, pt1));
2339  }
2340  a_currIdx += numPoints;
2341  }
2342 } // XmUGrid::Impl::GetUniqueEdgesFromPolyhedronCellstream
2343 //------------------------------------------------------------------------------
2348 //------------------------------------------------------------------------------
2349 bool XmUGrid::Impl::GetPlanViewPolygon2d(int a_cellIdx, VecPt3d& a_polygon) const
2350 {
2351  GetCellLocations(a_cellIdx, a_polygon);
2352  if (!a_polygon.empty())
2353  {
2354  return true;
2355  }
2356  return false;
2357 } // XmUGrid::Impl::GetPlanViewPolygon2d
2358 //------------------------------------------------------------------------------
2363 //------------------------------------------------------------------------------
2364 bool XmUGrid::Impl::GetPlanViewPolygon3d(int a_cellIdx, VecPt3d& a_polygon) const
2365 {
2366  VecPt3d segments;
2367  if (GetCellXySegments(a_cellIdx, segments))
2368  {
2369  // Prismatic cell
2370  iMergeSegmentsToPoly(segments, a_polygon);
2371  return true;
2372  }
2373  else
2374  {
2375  // Non-prismatic cell
2376  VecInt uniquePoints = GetCellPoints(a_cellIdx);
2377  VecPt3d cellPoints(uniquePoints.size());
2378  for (int i(0); i < uniquePoints.size(); i++)
2379  {
2380  cellPoints[i] = GetPointLocation(uniquePoints[i]);
2381  cellPoints[i].z = 0.0; // Insist that our z values are 0.0 for plan view
2382  }
2383  gmGetConvexHull(cellPoints, a_polygon, false);
2384  return true;
2385  }
2386  return false;
2387 } // XmUGrid::Impl::GetPlanViewPolygon3d
2388 //------------------------------------------------------------------------------
2393 //------------------------------------------------------------------------------
2394 bool XmUGrid::Impl::IsFaceSide(const VecInt& a_facePts) const
2395 {
2396  // if any face point has same x and y as any other face point then
2397  // the face is a side face
2398  if (a_facePts.size() > 2)
2399  {
2400  Pt3d ptLast = GetPointLocation(a_facePts[0]);
2401  for (size_t facePtIdx = 1; facePtIdx < a_facePts.size(); ++facePtIdx)
2402  {
2403  Pt3d ptCurr = GetPointLocation(a_facePts[facePtIdx]);
2404  if ((ptLast.x == ptCurr.x) && (ptLast.y == ptCurr.y))
2405  return true;
2406 
2407  ptLast = ptCurr;
2408  }
2409  }
2410  return false;
2411 } // XmUGrid::Impl::IsFaceSide
2412 //------------------------------------------------------------------------------
2417 //------------------------------------------------------------------------------
2418 bool XmUGrid::Impl::GetCellXySegments(int a_cellIdx, VecPt3d& a_segments) const
2419 {
2420  bool foundSideFace = false;
2421  for (int faceIdx = 0; faceIdx < GetCell3dFaceCount(a_cellIdx); ++faceIdx)
2422  {
2423  VecInt ptIdxs = GetCell3dFacePoints(a_cellIdx, faceIdx);
2424  if (IsFaceSide(ptIdxs))
2425  {
2426  foundSideFace = true;
2427  if (!GetFaceXySegments(a_cellIdx, faceIdx, a_segments))
2428  {
2429  return false;
2430  }
2431  }
2432  }
2433  return foundSideFace;
2434 } // XmUGrid::Impl::GetCellXySegments
2435 
2436 //------------------------------------------------------------------------------
2442 //------------------------------------------------------------------------------
2443 void XmUGrid::Impl::GetExtentsFromPoints(const VecPt3d& a_locations, Pt3d& a_min, Pt3d& a_max) const
2444 {
2445  a_min.x = a_min.y = a_min.z = xms::XM_DBL_HIGHEST;
2446  a_max.x = a_max.y = a_max.z = xms::XM_DBL_LOWEST;
2447  for (const Pt3d& pt : a_locations)
2448  {
2449  gmAddToExtents(pt, a_min, a_max);
2450  }
2451 } // XmUGrid::Impl::GetExtentsFromPoints
2452 
2453 //------------------------------------------------------------------------------
2459 //------------------------------------------------------------------------------
2460 bool XmUGrid::Impl::GetFaceXySegments(int a_cellIdx, int a_faceIdx, VecPt3d& a_segments) const
2461 {
2462  VecInt facePts;
2463  GetCell3dFacePoints(a_cellIdx, a_faceIdx, facePts);
2464  if (facePts.empty())
2465  return false;
2466 
2467  int column1Begin, column1End;
2468  if (!GetNextFaceColumn(facePts, 0, column1Begin, column1End))
2469  return false;
2470 
2471  int column2Begin, column2End;
2472  if (!GetNextFaceColumn(facePts, column1End, column2Begin, column2End))
2473  return false;
2474 
2475  GetFacePointSegments(facePts, column1End, column2Begin, a_segments);
2476  GetFacePointSegments(facePts, column2End, column1Begin, a_segments);
2477  return true;
2478 } // XmUGrid::Impl::GetFaceXySegments
2479 //------------------------------------------------------------------------------
2481 //------------------------------------------------------------------------------
2483 {
2484  if (m_numberOfFaces.empty() && GetCellCount() != 0)
2485  {
2486  int cellCount = GetCellCount();
2487  m_numberOfFaces.assign(cellCount, 0);
2488  m_cellFaceOffset.assign(cellCount + 1, 0);
2489  int faceCount = 0;
2490  for (int cellIdx = 0; cellIdx < cellCount; ++cellIdx)
2491  {
2492  int numberOfFaces = GetCell3dFaceCountNoCache(cellIdx);
2493  m_numberOfFaces[cellIdx] = numberOfFaces;
2494  faceCount += numberOfFaces;
2495  m_cellFaceOffset[cellIdx + 1] = faceCount;
2496  }
2497 
2498  m_faceOrientation.assign(faceCount, NEEDS_CALCULATION);
2499  m_faceNeighbor.assign(faceCount, NEEDS_CALCULATION);
2500  }
2501 } // XmUGrid::Impl::CalculateCacheValues
2502 //------------------------------------------------------------------------------
2504 //------------------------------------------------------------------------------
2506 {
2507  m_numberOfFaces.clear();
2508  m_cellFaceOffset.clear();
2509  m_faceOrientation.clear();
2510  m_faceNeighbor.clear();
2511  m_cellDimensionCounts.clear();
2512 } // XmUGrid::Impl::ClearCacheValues
2513 //------------------------------------------------------------------------------
2517 //------------------------------------------------------------------------------
2519 {
2520  if (!IsValidCellIdx(a_cellIdx))
2521  return -1;
2522 
2523  int cellType(GetCellType(a_cellIdx));
2524  switch (cellType)
2525  {
2526  case XMU_POLYHEDRON:
2527  return GetNumberOfItemsForCell(a_cellIdx);
2528  break;
2529 
2530  default:
2531  {
2532  const VecInt2d& faceTable = iGetFaceOffsetTable(cellType);
2533  return (int)faceTable.size();
2534  break;
2535  }
2536  }
2537 
2538  return 0;
2539 } // XmUGrid::Impl::GetCell3dFaceCountNoCache
2540 //------------------------------------------------------------------------------
2545 //------------------------------------------------------------------------------
2546 int XmUGrid::Impl::GetCell3dFaceAdjacentCellNoCache(int a_cellIdx, int a_faceIdx) const
2547 {
2548  VecInt cellFace = GetCell3dFacePoints(a_cellIdx, a_faceIdx);
2549  if (cellFace.empty())
2550  return -1;
2551  VecInt neighborCellFace = GetPointsAdjacentCells(cellFace);
2552  if (neighborCellFace.size() <= 1)
2553  return -1;
2554  if (neighborCellFace.size() > 2)
2555  {
2556  assert("Cell definitions are invalid; more than 2 cells found sharing the same face.");
2557  }
2558  for (int i : neighborCellFace)
2559  {
2560  if (i != a_cellIdx)
2561  {
2562  return i;
2563  }
2564  }
2565  return -1;
2566 } // XmUGrid::Impl::GetCell3dFaceAdjacentCellNoCache
2567 //------------------------------------------------------------------------------
2572 //------------------------------------------------------------------------------
2574  int a_faceIdx) const
2575 {
2576  XmUGridFaceOrientation faceOrientation = FaceOrientation(a_cellIdx, a_faceIdx);
2577  return faceOrientation;
2578 } // XmUGrid::Impl::GetCell3dFaceOrientationNoCache
2579 //------------------------------------------------------------------------------
2587 //------------------------------------------------------------------------------
2588 bool XmUGrid::Impl::GetNextFaceColumn(const VecInt& a_facePoints,
2589  int a_starti,
2590  int& a_columnBegin,
2591  int& a_columnEnd) const
2592 {
2593  int facePointsSize = (int)a_facePoints.size();
2594 
2595  // find next start of column of points (matching x/y values)
2596  Pt3d lastPt = GetPointXy0(a_facePoints[a_starti]);
2597  int lasti = a_starti;
2598  int i = (a_starti + 1) % facePointsSize;
2599  Pt3d pt;
2600  bool found = false;
2601  while (!found && i != a_starti)
2602  {
2603  pt = GetPointXy0(a_facePoints[i]);
2604  if (pt == lastPt)
2605  {
2606  a_columnBegin = lasti;
2607  found = true;
2608  }
2609  lastPt = pt;
2610  lasti = i;
2611  i = (i + 1) % facePointsSize;
2612  }
2613 
2614  if (!found)
2615  {
2616  // should have found first pair of points with matching x/y values
2617  return false;
2618  }
2619 
2620  // find end of column of points
2621  found = false;
2622  while (!found && i != a_columnBegin)
2623  {
2624  pt = GetPointXy0(a_facePoints[i]);
2625  if (pt != lastPt)
2626  {
2627  a_columnEnd = lasti;
2628  found = true;
2629  }
2630  else
2631  {
2632  lastPt = pt;
2633  lasti = i;
2634  i = (i + 1) % facePointsSize;
2635  }
2636  }
2637 
2638  if (!found)
2639  {
2640  // should have found end of points with matching x/y values
2641  return false;
2642  }
2643 
2644  return true;
2645 } // XmUGrid::Impl::GetNextFaceColumn
2646 
2647 //------------------------------------------------------------------------------
2653 //------------------------------------------------------------------------------
2655  int a_columnBegin,
2656  int a_columnEnd,
2657  VecPt3d& a_segments) const
2658 {
2659  int i = a_columnBegin;
2660  while (i != a_columnEnd)
2661  {
2662  Pt3d p = GetPointXy0(a_facePts[i]);
2663  a_segments.push_back(p);
2664  if (i != a_columnBegin)
2665  a_segments.push_back(p);
2666  i = (i + 1) % a_facePts.size();
2667  }
2668  a_segments.push_back(GetPointXy0(a_facePts[i]));
2669 } // XmUGrid::Impl::GetFacePointSegments
2670 //------------------------------------------------------------------------------
2677 //------------------------------------------------------------------------------
2679 {
2680  // if first face point has same x and y as any other face point then
2681  // the face is a side face
2682  if (IsSideFace(a_cellIdx, a_faceIdx))
2683  return XMU_ORIENTATION_SIDE;
2684 
2685  // else if face connected to cell lower idx cell then top face
2686  // else if face connected to cell higher idx cell then bottom face
2687  XmUGridFaceOrientation orientation = ConnectedTopOrBottom(a_cellIdx, a_faceIdx);
2688  if (orientation != XMU_ORIENTATION_UNKNOWN)
2689  return orientation;
2690 
2691  // else use sign of area to determine up or down
2692  orientation = GetOrientationFromArea(a_cellIdx, a_faceIdx);
2693  if (orientation != XMU_ORIENTATION_UNKNOWN)
2694  return orientation;
2695 
2696  return XMU_ORIENTATION_UNKNOWN;
2697 } // XmUGrid::Impl::FaceOrientationWithFail
2698 //------------------------------------------------------------------------------
2703 //------------------------------------------------------------------------------
2705  int a_faceIdx) const
2706 {
2707  XmUGridFaceOrientation orientation = XMU_ORIENTATION_UNKNOWN;
2708 
2709  // Assume only 1 top and bottom. Find other face that's top or bottom and
2710  // give answer as opposite. Otherwise first top other is bottom.
2711  bool firstUnknown = false;
2712  bool foundTop = false;
2713  bool foundBot = false;
2714  for (int face = 0; face < GetCell3dFaceCount(a_cellIdx); ++face)
2715  {
2716  int orientation = FaceOrientationWithFail(a_cellIdx, face);
2717  if (orientation == XMU_ORIENTATION_UNKNOWN)
2718  {
2719  if (a_faceIdx == face)
2720  firstUnknown = true;
2721  }
2722  else if (orientation == XMU_ORIENTATION_TOP)
2723  foundTop = true;
2724  else if (orientation == XMU_ORIENTATION_BOTTOM)
2725  foundBot = true;
2726  }
2727 
2728  if (foundTop)
2729  orientation = XMU_ORIENTATION_BOTTOM;
2730  else if (foundBot)
2731  orientation = XMU_ORIENTATION_TOP;
2732  else if (firstUnknown)
2733  orientation = XMU_ORIENTATION_TOP;
2734  else
2735  orientation = XMU_ORIENTATION_BOTTOM;
2736  return orientation;
2737 } // XmUGrid::Impl::VerticalOrientationFromOpposing
2738 //------------------------------------------------------------------------------
2743 //------------------------------------------------------------------------------
2744 bool XmUGrid::Impl::IsSideFace(int a_cellIdx, int a_faceIdx) const
2745 {
2746  VecInt facePts;
2747  GetCell3dFacePoints(a_cellIdx, a_faceIdx, facePts);
2748 
2749  // if any face point has same x and y as any other face point then
2750  // the face is a side face
2751  if (!facePts.empty())
2752  {
2753  Pt3d ptLast = GetPointXy0(facePts[0]);
2754  for (size_t facePtIdx = 1; facePtIdx < facePts.size(); ++facePtIdx)
2755  {
2756  Pt3d ptCurr = GetPointXy0(facePts[facePtIdx]);
2757  if (ptLast == ptCurr)
2758  return true;
2759 
2760  ptLast = ptCurr;
2761  }
2762  }
2763 
2764  return false;
2765 } // XmUGrid::Impl::IsSideFace
2766 //------------------------------------------------------------------------------
2772 //------------------------------------------------------------------------------
2774 {
2775  int adjacentCellIdx = GetCell3dFaceAdjacentCell(a_cellIdx, a_faceIdx);
2776  if (adjacentCellIdx != XM_NONE && adjacentCellIdx < a_cellIdx)
2777  return XMU_ORIENTATION_TOP;
2778  else if (adjacentCellIdx != XM_NONE && adjacentCellIdx > a_cellIdx)
2779  return XMU_ORIENTATION_BOTTOM;
2780  return XMU_ORIENTATION_UNKNOWN;
2781 } // ConnectedTopOrBottom
2782 //------------------------------------------------------------------------------
2789 //------------------------------------------------------------------------------
2791 {
2792  VecInt facePtIdxs;
2793  GetCell3dFacePoints(a_cellIdx, a_faceIdx, facePtIdxs);
2794  VecPt3d facePts;
2795  for (int facePtIdx : facePtIdxs)
2796  facePts.push_back(GetPointXy0(facePtIdx));
2797  double area = gmPolygonArea(&facePts[0], facePts.size());
2798  if (area > 0.0)
2799  return XMU_ORIENTATION_TOP;
2800  else if (area < 0.0)
2801  return XMU_ORIENTATION_BOTTOM;
2802  return XMU_ORIENTATION_UNKNOWN;
2803 } // XmUGrid::Impl::GetOrientationFromArea
2804 
2870 //------------------------------------------------------------------------------
2873 //------------------------------------------------------------------------------
2874 std::shared_ptr<XmUGrid> XmUGrid::New()
2875 {
2876  std::shared_ptr<XmUGrid> ugrid(new XmUGrid());
2877  return ugrid;
2878 } // XmUGrid::New
2879 //------------------------------------------------------------------------------
2884 //------------------------------------------------------------------------------
2885 std::shared_ptr<XmUGrid> XmUGrid::New(const VecPt3d& a_locations, const VecInt& a_cellstream)
2886 {
2887  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New();
2888  ugrid->SetLocations(a_locations);
2889  ugrid->SetCellstream(a_cellstream);
2890  return ugrid;
2891 } // XmUGrid::New
2892 //------------------------------------------------------------------------------
2894 //------------------------------------------------------------------------------
2896 : m_impl(new Impl)
2897 {
2898 } // XmUGrid::XmUGrid
2899 //------------------------------------------------------------------------------
2902 //------------------------------------------------------------------------------
2903 XmUGrid::XmUGrid(const XmUGrid& a_xmUGrid)
2904 : m_impl(new Impl)
2905 {
2906  *m_impl = *a_xmUGrid.m_impl;
2907 } // XmUGrid::XmUGrid
2908 //------------------------------------------------------------------------------
2911 //------------------------------------------------------------------------------
2913 : XmUGrid()
2914 {
2915  Swap(a_xmUGrid);
2916 } // XmUGrid::XmUGrid
2917 //------------------------------------------------------------------------------
2919 //------------------------------------------------------------------------------
2921 {
2922 } // XmUGrid::~XmUGrid
2923 //------------------------------------------------------------------------------
2927 //------------------------------------------------------------------------------
2929 {
2930  Swap(a_xmUGrid);
2931  return *this;
2932 } // XmUGrid::operator=
2933 //------------------------------------------------------------------------------
2936 //------------------------------------------------------------------------------
2937 void XmUGrid::Swap(XmUGrid& a_xmUGrid)
2938 {
2939  std::swap(m_impl, a_xmUGrid.m_impl);
2940 } // XmUGrid::Swap
2941 //------------------------------------------------------------------------------
2946 //------------------------------------------------------------------------------
2947 bool XmUGrid::IsValidCellstream(const VecInt& a_cellstream)
2948 {
2949  if (a_cellstream.empty())
2950  return true;
2951 
2952  int numItems = (int)a_cellstream.size();
2953  int currIdx = 0;
2954  while (currIdx < numItems)
2955  {
2956  // get cell type
2957  int cellType = a_cellstream[currIdx++];
2958  if (currIdx >= numItems)
2959  return false;
2960 
2961  // get the number of points
2962  int numPoints = a_cellstream[currIdx++];
2963  if (currIdx >= numItems)
2964  return false;
2965 
2966  switch (cellType)
2967  {
2968  case XMU_EMPTY_CELL:
2969  if (numPoints != 0)
2970  return false;
2971  break;
2972  case XMU_VERTEX:
2973  if (numPoints != 1)
2974  return false;
2975  currIdx += numPoints;
2976  break;
2977  case XMU_LINE:
2978  if (numPoints != 2)
2979  return false;
2980  currIdx += numPoints;
2981  break;
2982  case XMU_TRIANGLE:
2983  if (numPoints != 3)
2984  return false;
2985  currIdx += numPoints;
2986  break;
2987  case XMU_PIXEL:
2988  case XMU_QUAD:
2989  case XMU_TETRA:
2990  if (numPoints != 4)
2991  return false;
2992  currIdx += numPoints;
2993  break;
2994  case XMU_PYRAMID:
2995  if (numPoints != 5)
2996  return false;
2997  currIdx += numPoints;
2998  break;
2999  case XMU_WEDGE:
3000  case XMU_PENTAGONAL_PRISM:
3001  if (numPoints != 6)
3002  return false;
3003  currIdx += numPoints;
3004  break;
3005  case XMU_HEXAGONAL_PRISM:
3006  if (numPoints != 7)
3007  return false;
3008  currIdx += numPoints;
3009  break;
3010  case XMU_VOXEL:
3011  case XMU_HEXAHEDRON:
3012  if (numPoints != 8)
3013  return false;
3014  currIdx += numPoints;
3015  break;
3016  case XMU_POLY_VERTEX:
3017  if (numPoints < 1)
3018  return false;
3019  currIdx += numPoints;
3020  break;
3021  case XMU_POLY_LINE:
3022  if (numPoints < 2)
3023  return false;
3024  currIdx += numPoints;
3025  break;
3026  case XMU_TRIANGLE_STRIP:
3027  case XMU_POLYGON:
3028  if (numPoints < 3)
3029  return false;
3030  currIdx += numPoints;
3031  break;
3032  case XMU_POLYHEDRON:
3033  {
3034  int numFaces = numPoints;
3035  if (numFaces < 3)
3036  return false;
3037  for (int faceIdx = 0; faceIdx < numFaces; ++faceIdx)
3038  {
3039  if (currIdx >= numItems)
3040  return false;
3041  int numPoints = a_cellstream[currIdx++];
3042  if (numPoints < 3)
3043  return false;
3044  currIdx += numPoints;
3045  }
3046  }
3047  break;
3048  default:
3049  currIdx += numPoints;
3050  break;
3051  }
3052 
3053  if (currIdx > numItems)
3054  return false;
3055  }
3056 
3057  return true;
3058 } // XmUGrid::IsValidCellstream
3059 
3060 //------------------------------------------------------------------------------
3063 //------------------------------------------------------------------------------
3065 {
3066  return m_impl->GetModified();
3067 } // XmUGrid::GetModified
3068 
3069 //------------------------------------------------------------------------------
3071 //------------------------------------------------------------------------------
3073 {
3074  m_impl->SetUnmodified();
3075 } // XmUGrid::SetUnmodified
3076 
3077 //------------------------------------------------------------------------------
3080 //------------------------------------------------------------------------------
3081 void XmUGrid::SetUseCache(bool a_useCache)
3082 {
3083  m_impl->SetUseCache(a_useCache);
3084 } // XmUGrid::SetUseCache
3085 
3086 // Points
3087 
3088 //------------------------------------------------------------------------------
3091 //------------------------------------------------------------------------------
3093 {
3094  return m_impl->GetPointCount();
3095 } // XmUGrid::GetPointCount
3096 
3097 //------------------------------------------------------------------------------
3100 //------------------------------------------------------------------------------
3102 {
3103  return m_impl->GetLocations();
3104 } // XmUGrid::GetLocations
3105 
3106 //------------------------------------------------------------------------------
3109 //------------------------------------------------------------------------------
3110 void XmUGrid::SetLocations(const VecPt3d& a_locations)
3111 {
3112  m_impl->SetLocations(a_locations);
3113 } // XmUGrid::SetLocations
3114 
3115 //------------------------------------------------------------------------------
3119 //------------------------------------------------------------------------------
3120 Pt3d XmUGrid::GetPointLocation(int a_pointIdx) const
3121 {
3122  return m_impl->GetPointLocation(a_pointIdx);
3123 } // XmUGrid::GetPointLocation
3124 
3125 //------------------------------------------------------------------------------
3130 //------------------------------------------------------------------------------
3131 bool XmUGrid::SetPointLocation(int a_pointIdx, const Pt3d& a_location)
3132 {
3133  return m_impl->SetPointLocation(a_pointIdx, a_location);
3134 } // XmUGrid::SetPointLocation
3135 
3136 //------------------------------------------------------------------------------
3140 //------------------------------------------------------------------------------
3141 Pt3d XmUGrid::GetPointXy0(int a_pointIdx) const
3142 {
3143  return m_impl->GetPointXy0(a_pointIdx);
3144 } // XmUGrid::GetPointXy0
3145 
3146 //------------------------------------------------------------------------------
3150 //------------------------------------------------------------------------------
3152 {
3153  return m_impl->GetPointsLocations(a_points);
3154 } // XmUGrid::GetPointsLocations
3155 
3156 //------------------------------------------------------------------------------
3160 //------------------------------------------------------------------------------
3161 void XmUGrid::GetExtents(Pt3d& a_min, Pt3d& a_max) const
3162 {
3163  m_impl->GetExtents(a_min, a_max);
3164 } // XmUGrid::GetExtents
3165 
3166 //------------------------------------------------------------------------------
3170 //------------------------------------------------------------------------------
3171 int XmUGrid::GetPointAdjacentCellCount(int a_pointIdx) const
3172 {
3173  return m_impl->GetPointAdjacentCellCount(a_pointIdx);
3174 } // XmUGrid::GetPointAdjacentCellCount
3175 
3176 //------------------------------------------------------------------------------
3180 //------------------------------------------------------------------------------
3182 {
3183  return m_impl->GetPointAdjacentCells(a_pointIdx);
3184 } // XmUGrid::GetPointAdjacentCells
3185 
3186 //------------------------------------------------------------------------------
3191 //------------------------------------------------------------------------------
3192 void XmUGrid::GetPointAdjacentCells(int a_pointIdx, VecInt& a_adjacentCells) const
3193 {
3194  m_impl->GetPointAdjacentCells(a_pointIdx, a_adjacentCells);
3195 } // XmUGrid::GetPointAdjacentCells
3196 
3197 //------------------------------------------------------------------------------
3201 //------------------------------------------------------------------------------
3203 {
3204  return m_impl->GetPointsAdjacentCells(a_points);
3205 } // XmUGrid::GetPointsAdjacentCells
3206 
3207 //------------------------------------------------------------------------------
3212  const VecInt& a_pointIdxs,
3213  //------------------------------------------------------------------------------
3214  VecInt& a_adjacentCellIdxs) const
3215 {
3216  m_impl->GetPointsAdjacentCells(a_pointIdxs, a_adjacentCellIdxs);
3217 } // XmUGrid::GetPointsAdjacentCells
3218 
3219 //------------------------------------------------------------------------------
3225  int a_pointIdx1,
3226  int a_pointIdx2,
3227  //------------------------------------------------------------------------------
3228  VecInt& a_adjacentCellIdxs) const
3229 {
3230  m_impl->GetPointsAdjacentCells(a_pointIdx1, a_pointIdx2, a_adjacentCellIdxs);
3231 } // XmUGrid::GetPointsAdjacentCells
3232 
3233 //------------------------------------------------------------------------------
3238 //------------------------------------------------------------------------------
3239 bool XmUGrid::IsValidPointChange(int a_changedPtIdx, const Pt3d& a_newPosition) const
3240 {
3241  return m_impl->IsValidPointChange(a_changedPtIdx, a_newPosition);
3242 } // XmUGrid::IsValidPointChange
3243 
3244 //------------------------------------------------------------------------------
3247 //------------------------------------------------------------------------------
3249 {
3250  return m_impl->GetCellCount();
3251 } // XmUGrid::GetCellCount
3252 
3253 //------------------------------------------------------------------------------
3257 //------------------------------------------------------------------------------
3258 int XmUGrid::GetCellPointCount(int a_cellIdx) const
3259 {
3260  return m_impl->GetCellPointCount(a_cellIdx);
3261 } // XmUGrid::GetCellPointCount
3262 
3263 //------------------------------------------------------------------------------
3267 //------------------------------------------------------------------------------
3268 VecInt XmUGrid::GetCellPoints(int a_cellIdx) const
3269 {
3270  return m_impl->GetCellPoints(a_cellIdx);
3271 } // XmUGrid::GetCellPoints
3272 
3273 //------------------------------------------------------------------------------
3278 //------------------------------------------------------------------------------
3279 bool XmUGrid::GetCellPoints(int a_cellIdx, VecInt& a_cellPoints) const
3280 {
3281  return m_impl->GetCellPoints(a_cellIdx, a_cellPoints);
3282 } // XmUGrid::GetCellPoints
3283 
3284 //------------------------------------------------------------------------------
3288 //------------------------------------------------------------------------------
3289 void XmUGrid::GetCellLocations(int a_cellIdx, VecPt3d& a_cellLocations) const
3290 {
3291  m_impl->GetCellLocations(a_cellIdx, a_cellLocations);
3292 } // XmUGrid::GetCellLocations
3293 
3294 //------------------------------------------------------------------------------
3298 //------------------------------------------------------------------------------
3300 {
3301  return m_impl->GetCellType(a_cellIdx);
3302 } // XmUGrid::GetCellType
3303 
3304 //------------------------------------------------------------------------------
3307 //------------------------------------------------------------------------------
3308 std::vector<int> XmUGrid::GetDimensionCounts() const
3309 {
3310  return m_impl->GetDimensionCounts();
3311 } // XmUGrid::GetDimensionCounts
3312 
3313 //------------------------------------------------------------------------------
3318 //------------------------------------------------------------------------------
3319 int XmUGrid::GetCellDimension(int a_cellIdx) const
3320 {
3321  return m_impl->GetCellDimension(a_cellIdx);
3322 } // XmUGrid::GetCellDimension
3323 
3324 //------------------------------------------------------------------------------
3329 //------------------------------------------------------------------------------
3330 void XmUGrid::GetCellExtents(int a_cellIdx, Pt3d& a_min, Pt3d& a_max) const
3331 {
3332  m_impl->GetCellExtents(a_cellIdx, a_min, a_max);
3333 } // XmUGrid::GetCellExtents
3334 
3335 //------------------------------------------------------------------------------
3345 //------------------------------------------------------------------------------
3347 {
3348  return m_impl->GetCellstream();
3349 } // XmUGrid::GetCellstream
3350 
3351 //------------------------------------------------------------------------------
3356 //------------------------------------------------------------------------------
3357 bool XmUGrid::SetCellstream(const VecInt& a_cellstream)
3358 {
3359  return m_impl->SetCellstream(a_cellstream);
3360 } // XmUGrid::SetCellstream
3361 
3362 //------------------------------------------------------------------------------
3368 //------------------------------------------------------------------------------
3369 bool XmUGrid::GetCellCellstream(int a_cellIdx, VecInt& a_cellstream) const
3370 {
3371  return m_impl->GetCellCellstream(a_cellIdx, a_cellstream);
3372 } // XmUGrid::GetCellCellstream
3373 
3374 //------------------------------------------------------------------------------
3378 //------------------------------------------------------------------------------
3380 {
3381  return m_impl->GetCellAdjacentCells(a_cellIdx);
3382 } // XmUGrid::GetCellAdjacentCells
3383 
3384 //------------------------------------------------------------------------------
3388 //------------------------------------------------------------------------------
3389 void XmUGrid::GetCellAdjacentCells(int a_cellIdx, VecInt& a_cellNeighbors) const
3390 {
3391  m_impl->GetCellAdjacentCells(a_cellIdx, a_cellNeighbors);
3392 } // XmUGrid::GetCellAdjacentCells
3393 
3394 //------------------------------------------------------------------------------
3400 //------------------------------------------------------------------------------
3401 bool XmUGrid::GetCellPlanViewPolygon(int a_cellIdx, VecPt3d& a_polygon) const
3402 {
3403  return m_impl->GetCellPlanViewPolygon(a_cellIdx, a_polygon);
3404 } // XmUGrid::GetCellPlanViewPolygon
3405 
3406 //------------------------------------------------------------------------------
3411 //------------------------------------------------------------------------------
3412 bool XmUGrid::GetCellCentroid(int a_cellIdx, Pt3d& a_centroid) const
3413 {
3414  return m_impl->GetCellCentroid(a_cellIdx, a_centroid);
3415 } // XmUGrid::GetCellCentroid
3416 
3417 //------------------------------------------------------------------------------
3421 //------------------------------------------------------------------------------
3422 int XmUGrid::GetCellEdgeCount(int a_cellIdx) const
3423 {
3424  return m_impl->GetCellEdgeCount(a_cellIdx);
3425 } // XmUGrid::GetCellEdgeCount
3426 
3427 //------------------------------------------------------------------------------
3432 //------------------------------------------------------------------------------
3433 XmEdge XmUGrid::GetCellEdge(int a_cellIdx, int a_edgeIdx) const
3434 {
3435  return m_impl->GetCellEdge(a_cellIdx, a_edgeIdx);
3436 } // XmUGrid::GetCellEdge
3437 
3438 //------------------------------------------------------------------------------
3443 //------------------------------------------------------------------------------
3444 VecInt XmUGrid::GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx) const
3445 {
3446  return m_impl->GetCellEdgeAdjacentCells(a_cellIdx, a_edgeIdx);
3447 } // XmUGrid::GetCellEdgeAdjacentCells
3448 
3449 //------------------------------------------------------------------------------
3455 //------------------------------------------------------------------------------
3457  int a_edgeIdx,
3458  VecInt& a_adjacentCellIdxs) const
3459 {
3460  m_impl->GetCellEdgeAdjacentCells(a_cellIdx, a_edgeIdx, a_adjacentCellIdxs);
3461 } // XmUGrid::GetCellEdgeAdjacentCells
3462 
3463 //------------------------------------------------------------------------------
3468 //------------------------------------------------------------------------------
3469 int XmUGrid::GetCell2dEdgeAdjacentCell(int a_cellIdx, int a_edgeIdx) const
3470 {
3471  return m_impl->GetCell2dEdgeAdjacentCell(a_cellIdx, a_edgeIdx);
3472 } // XmUGrid::GetCell2dEdgeAdjacentCell
3473 
3474 //------------------------------------------------------------------------------
3478 //------------------------------------------------------------------------------
3479 void XmUGrid::GetEdgeAdjacentCells(const XmEdge& a_edge, VecInt& a_adjacentCellIdxs) const
3480 {
3481  m_impl->GetEdgeAdjacentCells(a_edge, a_adjacentCellIdxs);
3482 } // XmUGrid::GetEdgeAdjacentCells
3483 
3484 //------------------------------------------------------------------------------
3488 //------------------------------------------------------------------------------
3490 {
3491  return m_impl->GetEdgeAdjacentCells(a_edge);
3492 } // XmUGrid::GetEdgeAdjacentCells
3493 
3494 //------------------------------------------------------------------------------
3498 //------------------------------------------------------------------------------
3499 std::vector<XmEdge> XmUGrid::GetCellEdges(int a_cellIdx) const
3500 {
3501  return m_impl->GetCellEdges(a_cellIdx);
3502 } // XmUGrid::GetCellEdges
3503 
3504 //------------------------------------------------------------------------------
3508 //------------------------------------------------------------------------------
3509 void XmUGrid::GetCellEdges(int a_cellIdx, std::vector<XmEdge>& a_edges) const
3510 {
3511  m_impl->GetCellEdges(a_cellIdx, a_edges);
3512 } // XmUGrid::GetCellEdges
3513 
3514 //------------------------------------------------------------------------------
3518 //------------------------------------------------------------------------------
3519 void XmUGrid::GetPointAdjacentPoints(int a_pointIdx, VecInt& a_edgePoints) const
3520 {
3521  m_impl->GetPointAdjacentPoints(a_pointIdx, a_edgePoints);
3522 } // XmUGrid::GetPointAdjacentPoints
3523 
3524 //------------------------------------------------------------------------------
3528 //------------------------------------------------------------------------------
3529 void XmUGrid::GetPointAdjacentLocations(int a_pointIdx, VecPt3d& a_edgePoints) const
3530 {
3531  m_impl->GetPointAdjacentLocations(a_pointIdx, a_edgePoints);
3532 } // XmUGrid::GetPointAdjacentLocations
3533 
3534 // Faces
3535 
3536 //------------------------------------------------------------------------------
3540 //------------------------------------------------------------------------------
3541 int XmUGrid::GetCell3dFaceCount(int a_cellIdx) const
3542 {
3543  return m_impl->GetCell3dFaceCount(a_cellIdx);
3544 } // XmUGrid::GetCell3dFaceCount
3545 //------------------------------------------------------------------------------
3550 //------------------------------------------------------------------------------
3551 int XmUGrid::GetCell3dFacePointCount(int a_cellIdx, int a_faceIdx) const
3552 {
3553  return m_impl->GetCell3dFacePointCount(a_cellIdx, a_faceIdx);
3554 } // XmUGrid::GetCell3dFacePointCount
3555 
3556 //------------------------------------------------------------------------------
3561 //------------------------------------------------------------------------------
3562 VecInt XmUGrid::GetCell3dFacePoints(int a_cellIdx, int a_faceIdx) const
3563 {
3564  return m_impl->GetCell3dFacePoints(a_cellIdx, a_faceIdx);
3565 } // XmUGrid::GetCell3dFacePoints
3566 
3567 //------------------------------------------------------------------------------
3573 //------------------------------------------------------------------------------
3574 void XmUGrid::GetCell3dFacePoints(int a_cellIdx, int a_faceIdx, VecInt& a_facePtIdxs) const
3575 {
3576  m_impl->GetCell3dFacePoints(a_cellIdx, a_faceIdx, a_facePtIdxs);
3577 } // XmUGrid::GetCell3dFacePoints
3578 
3579 //------------------------------------------------------------------------------
3583 //------------------------------------------------------------------------------
3585 {
3586  return m_impl->GetCell3dFacesPoints(a_cellIdx);
3587 } // XmUGrid::GetCell3dFacesPoints
3588 
3589 //------------------------------------------------------------------------------
3594 //------------------------------------------------------------------------------
3595 int XmUGrid::GetCell3dFaceAdjacentCell(int a_cellIdx, int a_faceIdx) const
3596 {
3597  return m_impl->GetCell3dFaceAdjacentCell(a_cellIdx, a_faceIdx);
3598 } // XmUGrid::GetCell3dFaceAdjacentCell
3599 
3600 //------------------------------------------------------------------------------
3608 //------------------------------------------------------------------------------
3610  int a_faceIdx,
3611  int& a_neighborCell,
3612  int& a_neighborFace) const
3613 {
3614  return m_impl->GetCell3dFaceAdjacentCell(a_cellIdx, a_faceIdx, a_neighborCell, a_neighborFace);
3615 } // XmUGrid::GetCell3dFaceAdjacentCell
3616 
3617 //------------------------------------------------------------------------------
3622 //------------------------------------------------------------------------------
3624 {
3625  return m_impl->GetCell3dFaceOrientation(a_cellIdx, a_faceIdx);
3626 } // XmUGrid::GetCell3dFaceOrientation
3627 
3628 //------------------------------------------------------------------------------
3639 std::shared_ptr<XmUGrid> TEST_XmUGrid1Left90Tri()
3640 {
3641  VecPt3d points = {{0, 0, 0}, {20, 0, 0}, {0, 20, 0}};
3642 
3643  // Cell type (5), number of points (3), point numbers, counterclockwise
3644  std::vector<int> cells = {5, 3, 0, 1, 2};
3645 
3646  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
3647 
3648  return ugrid;
3649 } // TEST_UGrid1Left90Tri
3650 //------------------------------------------------------------------------------
3662 std::shared_ptr<XmUGrid> TEST_XmUGridSimpleQuad()
3663 {
3664  VecPt3d points = {{0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0},
3665  {20, 0, 0}, {0, -10, 0}, {10, -10, 0}, {20, -10, 0}};
3666 
3667  // Cell type (9), number of points (4), point numbers, counterclockwise
3668  VecInt cellstream = {XMU_QUAD, 4, 0, 3, 4, 1, XMU_QUAD, 4, 1, 4, 5, 2,
3669  XMU_QUAD, 4, 3, 6, 7, 4, XMU_QUAD, 4, 4, 7, 8, 5};
3670 
3671  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cellstream);
3672  return ugrid;
3673 } // TEST_XmUGridSimpleQuad
3674 
3675 //------------------------------------------------------------------------------
3678 //------------------------------------------------------------------------------
3679 std::shared_ptr<XmUGrid> TEST_XmUGrid2dLinear()
3680 {
3681  // clang-format off
3683  VecPt3d points = { { 0, 0, 0 }, { 10, 0, 0 }, { 20, 0, 0 }, { 30, 0, 0 }, { 40, 0, 0 },
3684  {0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {40, 10, 0}, {0, 20, 0},
3685  {10, 20, 0}, {20, 20, 0}, {30, 20, 0}, {40, 20, 0}};
3686 
3687  // Cell type (5), number of points (3), point numbers, counterclockwise
3688  std::vector<int> cells = {(int)XMU_QUAD, 4, 0, 1, 6, 5, // 0
3689  (int)XMU_PIXEL, 4, 1, 2, 6, 7, // 1
3690  (int)XMU_TRIANGLE, 3, 2, 3, 7, // 2
3691  (int)XMU_POLYGON, 6, 3, 4, 8, 13, 12, 7, // 3
3692  (int)XMU_POLY_LINE, 3, 7, 11, 10, // 4
3693  (int)XMU_LINE, 2, 5, 9}; // 5
3695  // clang-format on
3696 
3697  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
3698 
3699  return ugrid;
3700 } // TEST_XmUGrid2dLinear
3701 //------------------------------------------------------------------------------
3704 //------------------------------------------------------------------------------
3705 std::shared_ptr<XmUGrid> TEST_XmUGrid3dLinear()
3706 {
3707  // clang-format off
3709  VecPt3d points = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {30, 0, 0}, {40, 0, 0},
3710  {0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {30, 10, 0}, {40, 10, 0},
3711  {0, 20, 0}, {10, 20, 0}, {20, 20, 0}, {30, 20, 0}, {40, 20, 0},
3712  {0, 0, 10}, {10, 0, 10}, {20, 0, 10}, {30, 0, 10}, {40, 0, 10},
3713  {0, 10, 10}, {10, 10, 10}, {20, 10, 10}, {30, 10, 10}, {40, 10, 10},
3714  {0, 20, 10}, {10, 20, 10}, {20, 20, 10}, {30, 20, 10}, {40, 20, 10}};
3715 
3716  // Cell type (5), number of points (3), point numbers, counterclockwise
3717  std::vector<int> cells = {(int)XMU_TETRA, 4, 0, 1, 5, 15,
3718  (int)XMU_VOXEL, 8, 1, 2, 6, 7, 16, 17, 21, 22,
3719  (int)XMU_HEXAHEDRON, 8, 2, 3, 8, 7, 17, 18, 23, 22,
3720  (int)XMU_POLYHEDRON, 6, // A polyhedron with 6 faces
3721  4, 9, 8, 13, 14, // Bottom face with 4 points : 9, 8, 13, 14
3722  4, 8, 9, 24, 23, // Front face with 4 points : 8, 9, 24, 23
3723  4, 9, 14, 29, 24, // Right face with 4 points : 9, 14, 29, 28
3724  4, 14, 13, 28, 29, // Back face with 4 points : 14, 13, 28, 29
3725  4, 8, 13, 28, 23, // Left face with 4 points : 13, 8, 23, 28
3726  4, 23, 24, 29, 28, // Top face with 4 points : 23, 24, 29, 28
3727  (int)XMU_WEDGE, 6, 3, 4, 18, 8, 9, 23,
3728  (int)XMU_PYRAMID, 5, 5, 6, 11, 10, 20};
3730  // clang-format on
3731 
3732  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
3733 
3734  return ugrid;
3735 } // TEST_XmUGrid3dLinear
3736 //------------------------------------------------------------------------------
3739 //------------------------------------------------------------------------------
3740 std::shared_ptr<XmUGrid> TEST_XmUGridHexagonalPolyhedron()
3741 {
3742  VecPt3d points = {
3743  {0, 0, 10}, {10, 0, 10}, {10, 10, 10}, {0, 10, 10},
3744  {0, 0, 0}, {10, 0, 0}, {10, 10, 0}, {0, 10, 0},
3745  };
3746 
3747  // clang-format off
3748 
3749  // Cell type (5), number of points (3), point numbers, counterclockwise
3750  std::vector<int> cells = {(int)XMU_POLYHEDRON, 6,
3751  4, 0, 1, 2, 3,
3752  4, 4, 5, 7, 2,
3753  4, 5, 6, 2, 1,
3754  4, 6, 7, 3, 2,
3755  4, 7, 4, 0, 3,
3756  4, 4, 7, 6, 5};
3757  // clang-format on
3758 
3759  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cells);
3760 
3761  return ugrid;
3762 } // TEST_XmUGridHexagonalPolyhedron
3763 //------------------------------------------------------------------------------
3768 //------------------------------------------------------------------------------
3769 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildQuadUGrid(int a_rows, int a_cols)
3770 {
3771  Pt3d origin(0.0, 0.0, 0.0);
3772  return TEST_XmUBuildQuadUGrid(a_rows, a_cols, origin);
3773 } // TEST_XmUBuildQuadUGrid
3774 //------------------------------------------------------------------------------
3780 //------------------------------------------------------------------------------
3781 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildQuadUGrid(int a_rows, int a_cols, const xms::Pt3d& a_origin)
3782 {
3783  VecPt3d points;
3784  points.reserve(a_rows * a_cols);
3785  for (int i = 0; i < a_rows; ++i)
3786  {
3787  for (int j = 0; j < a_cols; ++j)
3788  {
3789  points.push_back(Pt3d(j + a_origin.x, a_rows - i + a_origin.y));
3790  }
3791  }
3792 
3793  VecInt cells;
3794  cells.reserve((a_rows - 1) * (a_cols - 1) * 6);
3795  for (int i = 0; i < a_rows - 1; ++i)
3796  {
3797  for (int j = 0; j < a_cols - 1; ++j)
3798  {
3799  cells.push_back(XMU_QUAD);
3800  cells.push_back(4);
3801  cells.push_back(j + a_cols * i);
3802  cells.push_back(j + a_cols * (i + 1));
3803  cells.push_back(j + 1 + a_cols * (i + 1));
3804  cells.push_back(j + 1 + a_cols * i);
3805  }
3806  }
3807 
3808  return XmUGrid::New(points, cells);
3809 } // TEST_XmUBuildQuadUGrid
3810 //------------------------------------------------------------------------------
3816 //------------------------------------------------------------------------------
3817 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildHexahedronUgrid(int a_rows, int a_cols, int a_lays)
3818 {
3819  Pt3d origin(0.0, 0.0, 0.0);
3820  return TEST_XmUBuildHexahedronUgrid(a_rows, a_cols, a_lays, origin);
3821 } // TEST_XmUBuildHexahedronUgrid
3822 //------------------------------------------------------------------------------
3829 //------------------------------------------------------------------------------
3830 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildHexahedronUgrid(int a_rows,
3831  int a_cols,
3832  int a_lays,
3833  const xms::Pt3d& a_origin)
3834 {
3835  VecPt3d points;
3836  points.reserve(a_rows * a_cols);
3837  for (int k = 0; k < a_lays; ++k)
3838  {
3839  for (int i = 0; i < a_rows; ++i)
3840  {
3841  for (int j = 0; j < a_cols; ++j)
3842  {
3843  points.push_back(
3844  Pt3d(j + a_origin.x, a_rows - i - 1 + a_origin.y, a_lays - k - 1 + a_origin.z));
3845  }
3846  }
3847  }
3848 
3849  VecInt cells;
3850  cells.reserve((a_rows - 1) * (a_cols - 1) * (a_lays - 1) * 10);
3851  int numInLayer = a_rows * a_cols;
3852  for (int k = 0; k < a_lays - 1; ++k)
3853  {
3854  int layOffset = numInLayer * k;
3855  for (int i = 0; i < a_rows - 1; ++i)
3856  {
3857  for (int j = 0; j < a_cols - 1; ++j)
3858  {
3859  cells.push_back(XMU_HEXAHEDRON);
3860  cells.push_back(8);
3861 
3862  cells.push_back(j + a_cols * i + layOffset);
3863  cells.push_back(j + 1 + a_cols * i + layOffset);
3864  cells.push_back(j + 1 + a_cols * (i + 1) + layOffset);
3865  cells.push_back(j + a_cols * (i + 1) + layOffset);
3866 
3867  cells.push_back(j + a_cols * i + layOffset + numInLayer);
3868  cells.push_back(j + 1 + a_cols * i + layOffset + numInLayer);
3869  cells.push_back(j + 1 + a_cols * (i + 1) + layOffset + numInLayer);
3870  cells.push_back(j + a_cols * (i + 1) + layOffset + numInLayer);
3871  }
3872  }
3873  }
3874  return XmUGrid::New(points, cells);
3875 } // TEST_XmUBuildHexahedronUgrid
3876 //------------------------------------------------------------------------------
3882 //------------------------------------------------------------------------------
3883 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildPolyhedronUgrid(int a_rows, int a_cols, int a_lays)
3884 {
3885  Pt3d origin(0.0, 0.0, 0.0);
3886  return TEST_XmUBuildPolyhedronUgrid(a_rows, a_cols, a_lays, origin);
3887 } // TEST_XmUBuildPolyhedronUgrid
3888 //------------------------------------------------------------------------------
3895 //------------------------------------------------------------------------------
3896 std::shared_ptr<xms::XmUGrid> TEST_XmUBuildPolyhedronUgrid(int a_rows,
3897  int a_cols,
3898  int a_lays,
3899  const xms::Pt3d& a_origin)
3900 {
3901  VecPt3d points;
3902  points.reserve(a_rows * a_cols);
3903  for (int k = 0; k < a_lays; ++k)
3904  {
3905  for (int i = 0; i < a_rows; ++i)
3906  {
3907  for (int j = 0; j < a_cols; ++j)
3908  {
3909  points.push_back(Pt3d(j + a_origin.x, a_rows - i + a_origin.y, a_lays - k + a_origin.z));
3910  }
3911  }
3912  }
3913 
3914  VecInt cells;
3915  cells.reserve((a_rows - 1) * (a_cols - 1) * (a_lays - 1) * 10);
3916  int numInLayer = a_rows * a_cols;
3917  for (int k = 0; k < a_lays - 1; ++k)
3918  {
3919  int layOffset = numInLayer * k;
3920  for (int i = 0; i < a_rows - 1; ++i)
3921  {
3922  for (int j = 0; j < a_cols - 1; ++j)
3923  {
3924  int pt0 = j + a_cols * i + layOffset;
3925  int pt1 = j + 1 + a_cols * i + layOffset;
3926  int pt2 = j + a_cols * (i + 1) + layOffset;
3927  int pt3 = j + 1 + a_cols * (i + 1) + layOffset;
3928  int pt4 = pt0 + numInLayer;
3929  int pt5 = pt1 + numInLayer;
3930  int pt6 = pt2 + numInLayer;
3931  int pt7 = pt3 + numInLayer;
3932 
3933  cells.push_back(XMU_POLYHEDRON);
3934  cells.push_back(6);
3935  // front
3936  cells.push_back(4);
3937  cells.push_back(pt2);
3938  cells.push_back(pt6);
3939  cells.push_back(pt7);
3940  cells.push_back(pt3);
3941  // right
3942  cells.push_back(4);
3943  cells.push_back(pt1);
3944  cells.push_back(pt5);
3945  cells.push_back(pt7);
3946  cells.push_back(pt3);
3947  // back
3948  cells.push_back(4);
3949  cells.push_back(pt0);
3950  cells.push_back(pt1);
3951  cells.push_back(pt5);
3952  cells.push_back(pt4);
3953  // left
3954  cells.push_back(4);
3955  cells.push_back(pt0);
3956  cells.push_back(pt4);
3957  cells.push_back(pt6);
3958  cells.push_back(pt2);
3959  // top
3960  cells.push_back(4);
3961  cells.push_back(pt0);
3962  cells.push_back(pt2);
3963  cells.push_back(pt3);
3964  cells.push_back(pt1);
3965  // bottom
3966  cells.push_back(4);
3967  cells.push_back(pt4);
3968  cells.push_back(pt5);
3969  cells.push_back(pt7);
3970  cells.push_back(pt6);
3971  }
3972  }
3973  }
3974  return XmUGrid::New(points, cells);
3975 } // TEST_XmUBuildPolyhedronUgrid
3976 //------------------------------------------------------------------------------
3979 //------------------------------------------------------------------------------
3980 std::shared_ptr<xms::XmUGrid> TEST_XmUBuild3DChevronUgrid()
3981 {
3982  VecPt3d ugridPoints = {{0.0, 0.0, 0.0}, {20.0, 10.0, 0.0}, {40.0, 0.0, 0.0},
3983  {20.0, 50.0, 0.0}, {0.0, 0.0, 10.0}, {20.0, 10.0, 10.0},
3984  {40.0, 0.0, 10.0}, {20.0, 50.0, 10.0}};
3985  // clang-format off
3986  VecInt ugridCell = { (int)XMU_POLYHEDRON, 6,
3987  4, 0, 3, 2, 1,
3988  4, 4, 5, 6, 7,
3989  4, 0, 1, 5, 4,
3990  4, 1, 2, 6, 5,
3991  4, 2, 3, 7, 6,
3992  4, 3, 0, 4, 7};
3993  // clang-format on
3994 
3995  return XmUGrid::New(ugridPoints, ugridCell);
3996 } // TEST_XmUBuild3DChevronUgrid
3997 
3998 } // namespace xms
3999 
4000 #ifdef CXX_TEST
4001 //------------------------------------------------------------------------------
4002 // Unit Tests
4003 //------------------------------------------------------------------------------
4004 #include <xmsgrid/ugrid/XmUGrid.t.h>
4005 
4006 #include <xmscore/testing/TestTools.h>
4007 
4008 using namespace xms;
4009 
4014 
4015 //------------------------------------------------------------------------------
4017 //------------------------------------------------------------------------------
4019 {
4020  std::shared_ptr<XmUGrid> xmUGrid = TEST_XmUGrid1Left90Tri();
4021 
4022  // test copy constructor
4023  XmUGrid grid1(*xmUGrid);
4024  TS_ASSERT_EQUALS(xmUGrid->GetLocations(), grid1.GetLocations());
4025 
4026  // test move constructor
4027  XmUGrid grid2(std::move(grid1));
4028  TS_ASSERT(grid1.GetLocations().empty());
4029  TS_ASSERT_EQUALS(xmUGrid->GetLocations(), grid2.GetLocations());
4030 
4031  // test assignment operator
4032  grid1 = grid2;
4033  TS_ASSERT_EQUALS(xmUGrid->GetLocations(), grid1.GetLocations());
4034  TS_ASSERT_EQUALS(xmUGrid->GetLocations(), grid2.GetLocations());
4035 } // XmUGridUnitTests::testOperators
4036 
4038 //------------------------------------------------------------------------------
4040 //------------------------------------------------------------------------------
4042 {
4043  // test empty UGrid
4044  std::shared_ptr<XmUGrid> emptyUGrid = XmUGrid::New();
4045  VecPt3d points = emptyUGrid->GetLocations();
4046  TS_ASSERT_EQUALS(0, points.size());
4047 
4048  VecInt cellstream = emptyUGrid->GetCellstream();
4049  TS_ASSERT(XmUGrid::IsValidCellstream(cellstream));
4050  TS_ASSERT_EQUALS(0, cellstream.size());
4051 
4052  // test adding points and cell stream
4053 
4054  // 0----1----2
4055  // | | |
4056  // 3----4----5
4057  // | | |
4058  // 6----7----8
4059 
4060  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New();
4061 
4062  points = {{0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0},
4063  {20, 0, 0}, {0, -10, 0}, {10, -10, 0}, {20, -10, 0}};
4064 
4065  // Cell type (9), number of points (4), point numbers, counterclockwise
4066  cellstream = {9, 4, 0, 3, 4, 1, 9, 4, 1, 4, 5, 2, 9, 4, 3, 6, 7, 4, 9, 4, 4, 7, 8, 5};
4067 
4068  TS_ASSERT(!ugrid->GetModified());
4069  ugrid->SetLocations(points);
4070  VecPt3d pointsOut = ugrid->GetLocations();
4071  TS_ASSERT_EQUALS(points, pointsOut);
4072  TS_ASSERT(ugrid->GetModified());
4073 
4074  ugrid->SetUnmodified();
4075  TS_ASSERT(!ugrid->GetModified());
4076  TS_ASSERT(ugrid->SetCellstream(cellstream));
4077  VecInt cellstreamOut = ugrid->GetCellstream();
4078  TS_ASSERT_EQUALS(cellstream, cellstreamOut);
4079  TS_ASSERT(ugrid->GetModified());
4080 
4081  // Test invalid cell streams
4082  cellstream = {-1};
4083  TS_ASSERT(!XmUGrid::IsValidCellstream(cellstream));
4084  cellstream = {9, 4, 0, 3, 4};
4085  TS_ASSERT(!XmUGrid::IsValidCellstream(cellstream));
4086  cellstream = {9, 3, 0, 3, 4, 1};
4087  TS_ASSERT(!XmUGrid::IsValidCellstream(cellstream));
4088 
4089  // Test adding cellstream then points (should fail)
4090  std::shared_ptr<XmUGrid> ugridBadOrder = XmUGrid::New();
4091  TS_ASSERT(!ugridBadOrder->SetCellstream(cellstream));
4092 
4093 } // XmUGridUnitTests::testUGridStreams
4095 
4096 //------------------------------------------------------------------------------
4098 //------------------------------------------------------------------------------
4100 {
4101  // 0----1----2
4102  // | | |
4103  // 3----4----5
4104  // | | |
4105  // 6----7----8
4106 
4108  VecPt3d points = {{0, 10, 0}, {10, 10, 10}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0},
4109  {20, 0, 0}, {0, -10, 0}, {10, -10, 0}, {20, -10, 0}};
4110 
4111  // Cell type (9), number of points (4), point numbers, counterclockwise
4112  VecInt cellstream = {9, 4, 0, 3, 4, 1, 9, 4, 1, 4, 5, 2, 9, 4, 3, 6, 7, 4, 9, 4, 4, 7, 8, 5};
4113 
4114  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cellstream);
4116 
4117  TS_ASSERT_EQUALS(Pt3d(), ugrid->GetPointLocation(-1));
4118  for (int i = 0; i < (int)points.size(); i++)
4119  {
4120  TS_ASSERT_EQUALS(points[i], ugrid->GetPointLocation(i));
4121  }
4122  TS_ASSERT_EQUALS(Pt3d(10, 10, 0), ugrid->GetPointXy0(1));
4123  TS_ASSERT_EQUALS(Pt3d(), ugrid->GetPointLocation((int)points.size()));
4124  TS_ASSERT(ugrid->GetModified());
4125 
4126  ugrid->SetUnmodified();
4127  TS_ASSERT(!ugrid->GetModified());
4128  TS_ASSERT(!ugrid->SetPointLocation(-1, Pt3d()));
4129  TS_ASSERT(!ugrid->SetPointLocation((int)points.size(), Pt3d()));
4130  TS_ASSERT(!ugrid->GetModified());
4131 
4132  TS_ASSERT(ugrid->SetPointLocation(0, Pt3d(-10, 10, 0)));
4133  TS_ASSERT_EQUALS(Pt3d(-10, 10, 0), ugrid->GetPointLocation(0));
4134  TS_ASSERT(ugrid->GetModified());
4135 } // XmUGridUnitTests::testGetSetPoint
4136 //------------------------------------------------------------------------------
4138 //------------------------------------------------------------------------------
4140 {
4141  // 0-----1-----2
4142  // | 0 | 1 |
4143  // 3-----4-----5
4144  // | 2 | 3 |
4145  // 6-----7-----8
4146 
4147  VecPt3d points = {{0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0},
4148  {20, 0, 0}, {0, -10, 0}, {10, -10, 0}, {20, -10, 0}};
4149 
4150  VecInt cell0 = {9, 4, 0, 3, 4, 1}, cell1 = {9, 4, 1, 4, 5, 2}, cell2 = {9, 4, 3, 6, 7, 4},
4151  cell3 = {9, 4, 4, 7, 8, 5};
4152  // Cell type (9), number of points (4), point numbers, counterclockwise
4153  VecInt cellstream;
4154  cellstream.insert(cellstream.end(), cell0.begin(), cell0.end());
4155  cellstream.insert(cellstream.end(), cell1.begin(), cell1.end());
4156  cellstream.insert(cellstream.end(), cell2.begin(), cell2.end());
4157  cellstream.insert(cellstream.end(), cell3.begin(), cell3.end());
4158 
4159  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cellstream);
4160  VecInt cellResult;
4161 
4162  TS_ASSERT_EQUALS(false, ugrid->GetCellCellstream(-1, cellResult));
4163 
4164  TS_ASSERT_EQUALS(true, ugrid->GetCellCellstream(0, cellResult));
4165  TS_ASSERT_EQUALS(cell0, cellResult);
4166  TS_ASSERT_EQUALS(true, ugrid->GetCellCellstream(1, cellResult));
4167  TS_ASSERT_EQUALS(cell1, cellResult);
4168  TS_ASSERT_EQUALS(true, ugrid->GetCellCellstream(2, cellResult));
4169  TS_ASSERT_EQUALS(cell2, cellResult);
4170  TS_ASSERT_EQUALS(true, ugrid->GetCellCellstream(3, cellResult));
4171  TS_ASSERT_EQUALS(cell3, cellResult);
4172 
4173  TS_ASSERT_EQUALS(false, ugrid->GetCellCellstream((int)points.size(), cellResult));
4174 
4175 } // XmUGridUnitTests::testGetCellCellstream
4176 //------------------------------------------------------------------------------
4178 //------------------------------------------------------------------------------
4180 {
4181  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4182  TS_REQUIRE_NOT_NULL(ugrid2d);
4183  TS_ASSERT_EQUALS(14, ugrid2d->GetPointCount());
4184  TS_ASSERT_EQUALS(6, ugrid2d->GetCellCount());
4185  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid2d->GetCellType(-1));
4186  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid2d->GetCellType(6));
4187  TS_ASSERT_EQUALS(XMU_QUAD, ugrid2d->GetCellType(0));
4188  TS_ASSERT_EQUALS(XMU_PIXEL, ugrid2d->GetCellType(1));
4189  TS_ASSERT_EQUALS(XMU_TRIANGLE, ugrid2d->GetCellType(2));
4190  TS_ASSERT_EQUALS(XMU_POLYGON, ugrid2d->GetCellType(3));
4191  TS_ASSERT_EQUALS(XMU_POLY_LINE, ugrid2d->GetCellType(4));
4192  TS_ASSERT_EQUALS(XMU_LINE, ugrid2d->GetCellType(5));
4193 
4194  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4195  TS_REQUIRE_NOT_NULL(ugrid3d);
4196 
4197  TS_ASSERT_EQUALS(30, ugrid3d->GetPointCount());
4198  TS_ASSERT_EQUALS(6, ugrid3d->GetCellCount());
4199  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid3d->GetCellType(-1));
4200  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid3d->GetCellType(6));
4201  TS_ASSERT_EQUALS(XMU_TETRA, ugrid3d->GetCellType(0));
4202  TS_ASSERT_EQUALS(XMU_VOXEL, ugrid3d->GetCellType(1));
4203  TS_ASSERT_EQUALS(XMU_HEXAHEDRON, ugrid3d->GetCellType(2));
4204  TS_ASSERT_EQUALS(XMU_POLYHEDRON, ugrid3d->GetCellType(3));
4205  TS_ASSERT_EQUALS(XMU_WEDGE, ugrid3d->GetCellType(4));
4206  TS_ASSERT_EQUALS(XMU_PYRAMID, ugrid3d->GetCellType(5));
4207 } // XmUGridUnitTests::testGetCellType
4208 //------------------------------------------------------------------------------
4210 //------------------------------------------------------------------------------
4212 {
4213  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4214  TS_REQUIRE_NOT_NULL(ugrid2d);
4215 
4216  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid2d->GetCellDimension(-1));
4217  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid2d->GetCellDimension(6));
4218  TS_ASSERT_EQUALS(2, ugrid2d->GetCellDimension(0));
4219  TS_ASSERT_EQUALS(2, ugrid2d->GetCellDimension(1));
4220  TS_ASSERT_EQUALS(2, ugrid2d->GetCellDimension(2));
4221  TS_ASSERT_EQUALS(2, ugrid2d->GetCellDimension(3));
4222  TS_ASSERT_EQUALS(1, ugrid2d->GetCellDimension(4));
4223  TS_ASSERT_EQUALS(1, ugrid2d->GetCellDimension(5));
4224 
4225  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4226  TS_REQUIRE_NOT_NULL(ugrid3d);
4227 
4228  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid3d->GetCellDimension(-1));
4229  TS_ASSERT_EQUALS(XMU_INVALID_CELL_TYPE, ugrid3d->GetCellDimension(6));
4230  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(0));
4231  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(1));
4232  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(2));
4233  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(3));
4234  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(4));
4235  TS_ASSERT_EQUALS(3, ugrid3d->GetCellDimension(5));
4236 
4237  // Test Dimension Counts
4238  std::vector<int> twoDResults(4, 0), threeDResults(4, 0);
4239  twoDResults[1] = 2;
4240  twoDResults[2] = 4;
4241  threeDResults[3] = 6;
4242  TS_ASSERT_EQUALS(twoDResults, ugrid2d->GetDimensionCounts());
4243  TS_ASSERT_EQUALS(threeDResults, ugrid3d->GetDimensionCounts());
4244 
4245  // Test GetDimensionCounts with an empty grid
4246  std::shared_ptr<XmUGrid> emptyUgrid = XmUGrid::New();
4247  std::vector<int> emptyResults = emptyUgrid->GetDimensionCounts();
4248  TS_ASSERT_EQUALS(VecInt(4, 0), emptyResults);
4249 } // XmUGridUnitTests::testGetCellDimension
4250 //------------------------------------------------------------------------------
4252 //------------------------------------------------------------------------------
4254 {
4255  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4256  TS_REQUIRE_NOT_NULL(ugrid2d);
4257 
4258  Pt3d min, max;
4259  Pt3d expectedMin = {0.0, 0.0, 0.0}, expectMax = {40.0, 20.0, 0.0};
4260  ugrid2d->GetExtents(min, max);
4261  TS_ASSERT_EQUALS(expectedMin, min);
4262  TS_ASSERT_EQUALS(expectMax, max);
4263 
4264  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4265  TS_REQUIRE_NOT_NULL(ugrid3d);
4266 
4267  expectedMin = {0.0, 0.0, 0.0};
4268  expectMax = {40.0, 20.0, 10.0};
4269  ugrid3d->GetExtents(min, max);
4270  TS_ASSERT_EQUALS(expectedMin, min);
4271  TS_ASSERT_EQUALS(expectMax, max);
4272 
4273  Pt3d origin(-25.0, -25.0, -15.0);
4274  std::shared_ptr<XmUGrid> ugridBuild = TEST_XmUBuildHexahedronUgrid(51, 51, 31, origin);
4275  TS_REQUIRE_NOT_NULL(ugridBuild);
4276 
4277  expectedMin = {-25.0, -25.0, -15.0};
4278  expectMax = {25.0, 25.0, 15.0};
4279  ugridBuild->GetExtents(min, max);
4280  TS_ASSERT_EQUALS(expectedMin, min);
4281  TS_ASSERT_EQUALS(expectMax, max);
4282 } // XmUGridUnitTests::testGetExtents
4283 //------------------------------------------------------------------------------
4285 //------------------------------------------------------------------------------
4287 {
4288  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4289  TS_REQUIRE_NOT_NULL(ugrid2d);
4290 
4291  TS_ASSERT_EQUALS(-1, ugrid2d->GetCellEdgeCount(-1));
4292  TS_ASSERT_EQUALS(-1, ugrid2d->GetCellEdgeCount(6));
4293  TS_ASSERT_EQUALS(4, ugrid2d->GetCellEdgeCount(0));
4294  TS_ASSERT_EQUALS(4, ugrid2d->GetCellEdgeCount(1));
4295  TS_ASSERT_EQUALS(3, ugrid2d->GetCellEdgeCount(2));
4296  TS_ASSERT_EQUALS(6, ugrid2d->GetCellEdgeCount(3));
4297  TS_ASSERT_EQUALS(2, ugrid2d->GetCellEdgeCount(4));
4298  TS_ASSERT_EQUALS(1, ugrid2d->GetCellEdgeCount(5));
4299 
4300  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4301  TS_REQUIRE_NOT_NULL(ugrid3d);
4302 
4303  TS_ASSERT_EQUALS(-1, ugrid3d->GetCellEdgeCount(-1));
4304  TS_ASSERT_EQUALS(-1, ugrid3d->GetCellEdgeCount(6));
4305  TS_ASSERT_EQUALS(6, ugrid3d->GetCellEdgeCount(0));
4306  TS_ASSERT_EQUALS(12, ugrid3d->GetCellEdgeCount(1));
4307  TS_ASSERT_EQUALS(12, ugrid3d->GetCellEdgeCount(2));
4308  TS_ASSERT_EQUALS(12, ugrid3d->GetCellEdgeCount(3));
4309  TS_ASSERT_EQUALS(9, ugrid3d->GetCellEdgeCount(4));
4310  TS_ASSERT_EQUALS(8, ugrid3d->GetCellEdgeCount(5));
4311 
4312 } // XmUGridUnitTests::testGetCellEdgeCount
4313 
4315 //------------------------------------------------------------------------------
4317 //------------------------------------------------------------------------------
4319 {
4320  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4321  TS_REQUIRE_NOT_NULL(ugrid2d);
4322 
4323  // test 1D and 2D cells
4324  TS_ASSERT_EQUALS(-1, ugrid2d->GetCell3dFaceCount(-1));
4325  for (int cellIdx = 0; cellIdx < ugrid2d->GetCellCount(); ++cellIdx)
4326  {
4327  TS_ASSERT_EQUALS(0, ugrid2d->GetCell3dFaceCount(cellIdx));
4328  }
4329  TS_ASSERT_EQUALS(-1, ugrid2d->GetCell3dFaceCount(ugrid2d->GetCellCount()));
4330 
4331  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4332  TS_REQUIRE_NOT_NULL(ugrid3d);
4333 
4334  // test 3D cells
4335  TS_ASSERT_EQUALS(-1, ugrid3d->GetCell3dFaceCount(-1));
4336  TS_ASSERT_EQUALS(-1, ugrid3d->GetCell3dFaceCount(6));
4337  TS_ASSERT_EQUALS(4, ugrid3d->GetCell3dFaceCount(0));
4338  TS_ASSERT_EQUALS(6, ugrid3d->GetCell3dFaceCount(1));
4339  TS_ASSERT_EQUALS(6, ugrid3d->GetCell3dFaceCount(2));
4340  TS_ASSERT_EQUALS(6, ugrid3d->GetCell3dFaceCount(3));
4341  TS_ASSERT_EQUALS(5, ugrid3d->GetCell3dFaceCount(4));
4342  TS_ASSERT_EQUALS(5, ugrid3d->GetCell3dFaceCount(5));
4343 } // XmUGridUnitTests::testGetCell3dFaceCount
4345 
4346 //------------------------------------------------------------------------------
4348 //------------------------------------------------------------------------------
4350 {
4351  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4352  TS_REQUIRE_NOT_NULL(ugrid2d);
4353 
4354  // test 1D and 2D cells - should return 0 for valid cell index
4355  TS_ASSERT_EQUALS(-1, ugrid2d->GetCell3dFacePointCount(-1, 0));
4356  TS_ASSERT_EQUALS(0, ugrid2d->GetCell3dFacePointCount(1, 0));
4357  TS_ASSERT_EQUALS(-1, ugrid2d->GetCell3dFacePointCount(ugrid2d->GetCellCount(), 0));
4358 
4359  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4360  TS_REQUIRE_NOT_NULL(ugrid3d);
4361 
4362  // test 3D cells
4363  TS_ASSERT_EQUALS(-1, ugrid3d->GetCell3dFacePointCount(-1, 0));
4364  TS_ASSERT_EQUALS(-1, ugrid3d->GetCell3dFacePointCount(6, 0));
4365  TS_ASSERT_EQUALS(4, ugrid3d->GetCell3dFacePointCount(1, 3));
4366  TS_ASSERT_EQUALS(4, ugrid3d->GetCell3dFacePointCount(3, 2));
4367 } // XmUGridUnitTests::testGetCell3dFacePointCount
4368 //------------------------------------------------------------------------------
4370 //------------------------------------------------------------------------------
4372 {
4373  // 0----1----2
4374  // | | |
4375  // 3----4----5
4376 
4377  VecPt3d points = {{0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0}, {20, 0, 0}};
4378 
4379  VecInt cellstream = {XMU_QUAD, 4, 0, 3, 4, 1, XMU_QUAD, 4, 1, 4, 5, 2};
4380 
4381  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(points, cellstream);
4382 
4383  VecInt cellEmpty = {};
4384  VecInt cellZero = {0};
4385  VecInt cellZeroAndOne = {0, 1};
4386  VecInt cellOne = {1};
4387 
4388  TS_ASSERT_EQUALS(cellEmpty, ugrid->GetPointAdjacentCells(-1));
4389  TS_ASSERT_EQUALS(cellZero, ugrid->GetPointAdjacentCells(0));
4390  TS_ASSERT_EQUALS(cellZeroAndOne, ugrid->GetPointAdjacentCells(1));
4391  TS_ASSERT_EQUALS(cellOne, ugrid->GetPointAdjacentCells(2));
4392  TS_ASSERT_EQUALS(cellZero, ugrid->GetPointAdjacentCells(3));
4393  TS_ASSERT_EQUALS(cellZeroAndOne, ugrid->GetPointAdjacentCells(4));
4394  TS_ASSERT_EQUALS(cellOne, ugrid->GetPointAdjacentCells(5));
4395  TS_ASSERT_EQUALS(cellEmpty, ugrid->GetPointAdjacentCells(6));
4396 
4397  TS_ASSERT_EQUALS(0, ugrid->GetPointAdjacentCellCount(-1));
4398  TS_ASSERT_EQUALS(1, ugrid->GetPointAdjacentCellCount(0));
4399  TS_ASSERT_EQUALS(2, ugrid->GetPointAdjacentCellCount(1));
4400  TS_ASSERT_EQUALS(1, ugrid->GetPointAdjacentCellCount(2));
4401  TS_ASSERT_EQUALS(1, ugrid->GetPointAdjacentCellCount(3));
4402  TS_ASSERT_EQUALS(2, ugrid->GetPointAdjacentCellCount(4));
4403  TS_ASSERT_EQUALS(1, ugrid->GetPointAdjacentCellCount(5));
4404  TS_ASSERT_EQUALS(0, ugrid->GetPointAdjacentCellCount(6));
4405 
4406 } // XmUGridUnitTests::testGetPointAdjacentCellsSimple
4407 
4408 //------------------------------------------------------------------------------
4410 //------------------------------------------------------------------------------
4412 {
4413  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4414  TS_REQUIRE_NOT_NULL(ugrid2d);
4415 
4416  VecInt2d cellsFor2DPoints = {{0}, // point 0
4417  {0, 1}, // point 1
4418  {1, 2}, // point 2
4419  {2, 3}, // point 3
4420  {3}, // point 4
4421  {0, 5}, // point 5
4422  {0, 1}, // point 6
4423  {1, 2, 3, 4}, // point 7
4424  {3}, // point 8
4425  {5}, // point 9
4426  {4}, // point 10
4427  {4}, // point 11
4428  {3}, // point 12
4429  {3}}; // point 13
4430 
4431  // test 1D and 2D cells
4432  for (int i(0); i < cellsFor2DPoints.size(); i++)
4433  {
4434  TS_ASSERT_EQUALS(cellsFor2DPoints[i], ugrid2d->GetPointAdjacentCells(i));
4435  }
4436 
4437  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4438  TS_REQUIRE_NOT_NULL(ugrid3d);
4439 
4440  VecInt2d cellsFor3DPoints = {{0}, // point 0
4441  {0, 1}, // point 1
4442  {1, 2}, // point 2
4443  {2, 4}, // point 3
4444  {4}, // point 4
4445  {0, 5}, // point 5
4446  {1, 5}, // point 6
4447  {1, 2}, // point 7
4448  {2, 3, 4}, // point 8
4449  {3, 4}, // point 9
4450  {5}, // point 10
4451  {5}, // point 11
4452  {}, // point 12
4453  {3}, // point 13
4454  {3}, // point 14
4455  {0}, // point 15
4456  {1}, // point 16
4457  {1, 2}, // point 17
4458  {2, 4}, // point 18
4459  {}, // point 19
4460  {5}, // point 20
4461  {1}, // point 21
4462  {1, 2}, // point 22
4463  {2, 3, 4}, // point 23
4464  {3}, // point 24
4465  {}, // point 25
4466  {}, // point 26
4467  {}, // point 27
4468  {3}, // point 28
4469  {3}, // point 29
4470  {}}; // point 30
4471 
4472  // test 3D cells
4473  for (int i(0); i < cellsFor3DPoints.size(); i++)
4474  {
4475  if (cellsFor3DPoints[i] != ugrid3d->GetPointAdjacentCells(i))
4476  {
4477  TS_FAIL(i);
4478  }
4479  TS_ASSERT_EQUALS(cellsFor3DPoints[i], ugrid3d->GetPointAdjacentCells(i));
4480  }
4481 
4482 } // XmUGridUnitTests::testGetPointAdjacentCells
4483 //------------------------------------------------------------------------------
4485 //------------------------------------------------------------------------------
4487 {
4488  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4489  TS_REQUIRE_NOT_NULL(ugrid);
4490 
4491  VecInt2d expectedGetCellPoints = {{0, 3, 4, 1}, {1, 4, 5, 2}, {3, 6, 7, 4}, {4, 7, 8, 5}};
4492  VecInt2d cellPoints;
4493  VecInt cellPoint1D;
4494  TS_ASSERT(!ugrid->GetCellPoints(-1, cellPoint1D));
4495  TS_ASSERT(!ugrid->GetCellPoints(5, cellPoint1D));
4496 
4497  for (int i(0); i < ugrid->GetCellCount(); i++)
4498  {
4499  TS_ASSERT(ugrid->GetCellPoints(i, cellPoint1D));
4500  cellPoints.push_back(cellPoint1D);
4501  TS_ASSERT_EQUALS(expectedGetCellPoints[i], cellPoints[i]);
4502  }
4503 
4504  expectedGetCellPoints = {{0, 1, 6, 5}, {1, 2, 7, 6}, {2, 3, 7},
4505  {3, 4, 8, 13, 12, 7}, {7, 11, 10}, {5, 9}};
4506  cellPoints.clear();
4507  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4508  TS_REQUIRE_NOT_NULL(ugrid2d);
4509 
4510  for (int i(0); i < ugrid2d->GetCellCount(); i++)
4511  {
4512  TS_ASSERT(ugrid2d->GetCellPoints(i, cellPoint1D));
4513  cellPoints.push_back(cellPoint1D);
4514  TS_ASSERT_EQUALS(expectedGetCellPoints[i], cellPoints[i]);
4515  }
4516 
4517  expectedGetCellPoints = {{0, 1, 5, 15},
4518  {1, 2, 6, 7, 16, 17, 21, 22},
4519  {2, 3, 8, 7, 17, 18, 23, 22},
4520  {9, 8, 13, 14, 24, 23, 29, 28},
4521  {3, 4, 18, 8, 9, 23},
4522  {5, 6, 11, 10, 20}};
4523  VecInt expectedPointCounts = {4, 8, 8, 8, 6, 5};
4524  cellPoints.clear();
4525  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4526  TS_REQUIRE_NOT_NULL(ugrid3d);
4527 
4528  for (int i(0); i < ugrid3d->GetCellCount(); i++)
4529  {
4530  TS_ASSERT(ugrid3d->GetCellPoints(i, cellPoint1D));
4531  cellPoints.push_back(cellPoint1D);
4532  TS_ASSERT_EQUALS(expectedGetCellPoints[i], cellPoints[i]);
4533  TS_ASSERT_EQUALS(expectedPointCounts[i], ugrid3d->GetCellPointCount(i));
4534  }
4535 
4536 } // XmUGridUnitTests::testGetCellPoints
4537 
4538 //------------------------------------------------------------------------------
4540 //------------------------------------------------------------------------------
4542 {
4543  // 0-----1-----2
4544  // | 0 | 1 |
4545  // 3-----4-----5
4546  // | 2 | 3 |
4547  // 6-----7-----8
4548 
4549  // 2D shape (simple)
4550  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4551  TS_REQUIRE_NOT_NULL(ugrid);
4552 
4553  {
4554  XmEdge edge0(0, 3), edge1(3, 4), edge2(4, 1), edge3(1, 0); // cell 0
4555  XmEdge edge4(1, 4), edge5(4, 5), edge6(5, 2), edge7(2, 1); // cell 1
4556  XmEdge edge8(3, 6), edge9(6, 7), edge10(7, 4), edge11(4, 3); // cell 2
4557  XmEdge edge12(4, 7), edge13(7, 8), edge14(8, 5), edge15(5, 4); // cell 3
4558  XmEdge emptyEdge;
4559  std::vector<std::vector<XmEdge>> expectedCellsCellEdges;
4560  std::vector<XmEdge> emptyVec = {emptyEdge};
4561  std::vector<XmEdge> cellEdges;
4562 
4563  cellEdges.push_back(ugrid->GetCellEdge(0, -1));
4564  TS_ASSERT_EQUALS(emptyVec, cellEdges);
4565 
4566  cellEdges.clear();
4567  cellEdges.push_back(ugrid->GetCellEdge(0, ugrid->GetCellEdgeCount(0)));
4568  TS_ASSERT_EQUALS(emptyVec, cellEdges);
4569 
4570  cellEdges.clear();
4571  expectedCellsCellEdges = {{edge0, edge1, edge2, edge3},
4572  {edge4, edge5, edge6, edge7},
4573  {edge8, edge9, edge10, edge11},
4574  {edge12, edge13, edge14, edge15}};
4575  for (int i(0); i < ugrid->GetCellCount(); i++)
4576  {
4577  for (int j(0); j < ugrid->GetCellEdgeCount(i); j++)
4578  {
4579  cellEdges.push_back(ugrid->GetCellEdge(i, j));
4580  }
4581  TS_ASSERT_EQUALS(expectedCellsCellEdges[i], cellEdges);
4582  cellEdges.clear();
4583  }
4584  }
4586  {
4587  XmEdge edge0(0, 1), edge1(1, 6), edge2(6, 5), edge3(5, 0); // Quad
4588  XmEdge edge4(1, 2), edge5(2, 7), edge6(7, 6), edge7(6, 1); // Pixel
4589  XmEdge edge8(2, 3), edge9(3, 7), edge10(7, 2); // Triangle
4590  XmEdge edge11(3, 4), edge12(4, 8), edge13(8, 13), edge14(13, 12), edge15(12, 7),
4591  edge16(7, 3); // Polygon
4592  XmEdge edge17(7, 11), edge18(11, 10); // PolyLine
4593  XmEdge edge19(5, 9); // Line
4594 
4595  // 2D Shapes
4596  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4597  TS_REQUIRE_NOT_NULL(ugrid2d);
4598 
4599  std::vector<std::vector<XmEdge>> expectedCellsCellEdges;
4600  expectedCellsCellEdges = {{edge0, edge1, edge2, edge3},
4601  {edge4, edge5, edge6, edge7},
4602  {edge8, edge9, edge10},
4603  {edge11, edge12, edge13, edge14, edge15, edge16},
4604  {edge17, edge18},
4605  {edge19}};
4606  std::vector<XmEdge> cellEdges;
4607  for (int i(0); i < ugrid2d->GetCellCount(); i++)
4608  {
4609  for (int j(0); j < ugrid2d->GetCellEdgeCount(i); j++)
4610  {
4611  cellEdges.push_back(ugrid2d->GetCellEdge(i, j));
4612  }
4613  TS_ASSERT_EQUALS(expectedCellsCellEdges[i], cellEdges);
4614  cellEdges.clear();
4615  }
4616  }
4618 
4620  {
4621  // 3D Shapes
4622  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4623  TS_REQUIRE_NOT_NULL(ugrid3d);
4624 
4625  // clang-format off
4626  std::vector<std::vector<XmEdge>> expectedCellsCellEdges =
4627  {
4628  {{0, 1}, {1, 5}, {5, 0}, {0, 15}, {1, 15}, {5, 15}}, // XMU_TETRA
4629  {{1, 2}, {2, 7}, {6, 7}, {1, 6}, {16, 17}, {17, 22}, {21, 22}, {16, 21}, {1, 16}, {2, 17}, {6, 21}, {7, 22}}, // XMU_VOXEL
4630  {{2, 3}, {3, 8}, {7, 8}, {2, 7}, {17, 18}, {18, 23}, {22, 23}, {17, 22}, {2, 17}, {3, 18}, {7, 22}, {8, 23}}, // XMU_HEXAHEDRON
4631  {{8, 9}, {8, 13}, {8, 23}, {9, 14}, {9, 24}, {13, 14}, {13, 28}, {14, 29}, {23, 24}, {23, 28}, {24, 29}, {28, 29}}, // XMU_POLYHEDRON
4632  {{3, 4}, {4, 18}, {18, 3}, {8, 9}, {9, 23}, {23, 8}, {3, 8}, {4, 9}, {18, 23}}, // XMU_WEDGE
4633  {{5, 6}, {6, 11}, {11, 10}, {10, 5}, {5, 20}, {6, 20}, {11, 20}, {10, 20}} // XMU_PYRAMID
4634  };
4635  // clang-format on
4636  std::vector<XmEdge> cellEdges;
4637  for (int i(0); i < ugrid3d->GetCellCount(); i++)
4638  {
4639  for (int j(0); j < ugrid3d->GetCellEdgeCount(i); j++)
4640  {
4641  cellEdges.push_back(ugrid3d->GetCellEdge(i, j));
4642  }
4643  TS_ASSERT_EQUALS(expectedCellsCellEdges[i], cellEdges);
4644  cellEdges.clear();
4645  }
4646  }
4648 } // XmUGridUnitTests::testGetCellEdge
4649 
4650 //------------------------------------------------------------------------------
4652 //------------------------------------------------------------------------------
4654 {
4655  // 0-----1-----2
4656  // | 0 | 1 |
4657  // 3-----4-----5
4658  // | 2 | 3 |
4659  // 6-----7-----8
4660 
4661  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4662  TS_REQUIRE_NOT_NULL(ugrid);
4663 
4664  VecInt expectedCells;
4665  VecInt points = {-1, 0};
4666  VecInt retrievedCells;
4667  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4668  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4669 
4670  points = {0, -1};
4671  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4672  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4673 
4674  points = {0, 8};
4675  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4676  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4677  expectedCells.clear();
4678  points.clear();
4679  retrievedCells.clear();
4680 
4681  expectedCells = {0, 2};
4682  points = {3, 4};
4683  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4684  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4685  expectedCells.clear();
4686  points.clear();
4687  retrievedCells.clear();
4688 
4689  expectedCells = {0};
4690  points = {0, 3};
4691  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4692  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4693  expectedCells.clear();
4694  points.clear();
4695  retrievedCells.clear();
4696 
4697  points = {3, 4, 5};
4698  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4699  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4700  expectedCells.clear();
4701  points.clear();
4702  retrievedCells.clear();
4703 
4704  points = {ugrid->GetPointCount(), 0};
4705  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4706  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4707 
4708  points = {0, ugrid->GetPointCount()};
4709  retrievedCells = ugrid->GetPointsAdjacentCells(points);
4710  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4711 
4712 } // XmUGridUnitTests::testGetPointsAdjacentCells
4713 
4715 //------------------------------------------------------------------------------
4717 //------------------------------------------------------------------------------
4719 {
4720  // 0-----1-----2
4721  // | 0 | 1 |
4722  // 3-----4-----5
4723  // | 2 | 3 |
4724  // 6-----7-----8
4725 
4726  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4727  TS_REQUIRE_NOT_NULL(ugrid);
4728 
4729  VecInt expectedCells;
4730 
4731  VecInt retrievedCells;
4732  retrievedCells = ugrid->GetCellAdjacentCells(-1);
4733  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4734  retrievedCells = ugrid->GetCellAdjacentCells(0);
4735  expectedCells = {2, 1, 3};
4736  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4737  expectedCells.clear();
4738  retrievedCells = ugrid->GetCellAdjacentCells(4);
4739  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4740  expectedCells.clear();
4741  retrievedCells = ugrid->GetCellAdjacentCells(5);
4742  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4743  expectedCells.clear();
4744  retrievedCells.clear();
4745 
4746  // 2D Shapes
4747  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4748  TS_REQUIRE_NOT_NULL(ugrid2d);
4749 
4750  expectedCells = {1, 5};
4751  retrievedCells = ugrid2d->GetCellAdjacentCells(0);
4752  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4753  expectedCells = {0, 2, 3, 4};
4754  retrievedCells = ugrid2d->GetCellAdjacentCells(1);
4755  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4756  expectedCells = {1, 3, 4};
4757  retrievedCells = ugrid2d->GetCellAdjacentCells(2);
4758  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4759  expectedCells = {2, 1, 4};
4760  retrievedCells = ugrid2d->GetCellAdjacentCells(3);
4761  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4762  expectedCells = {1, 2, 3};
4763  retrievedCells = ugrid2d->GetCellAdjacentCells(4);
4764  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4765  expectedCells = {0};
4766  retrievedCells = ugrid2d->GetCellAdjacentCells(5);
4767  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4768 
4769  // 3D Shapes
4770  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4771  TS_REQUIRE_NOT_NULL(ugrid3d);
4772 
4773  expectedCells = {1, 5};
4774  retrievedCells = ugrid3d->GetCellAdjacentCells(0);
4775  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4776  expectedCells = {0, 2, 5};
4777  retrievedCells = ugrid3d->GetCellAdjacentCells(1);
4778  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4779  expectedCells = {1, 4, 3};
4780  retrievedCells = ugrid3d->GetCellAdjacentCells(2);
4781  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4782  expectedCells = {4, 2};
4783  retrievedCells = ugrid3d->GetCellAdjacentCells(3);
4784  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4785  expectedCells = {2, 3};
4786  retrievedCells = ugrid3d->GetCellAdjacentCells(4);
4787  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4788  expectedCells = {0, 1};
4789  retrievedCells = ugrid3d->GetCellAdjacentCells(5);
4790  TS_ASSERT_EQUALS(expectedCells, retrievedCells);
4791 
4792 } // XmUGridUnitTests::testGetCellAdjacentCells
4794 
4795 //------------------------------------------------------------------------------
4797 //------------------------------------------------------------------------------
4799 {
4800  // 0-----1-----2
4801  // | 0 | 1 |
4802  // 3-----4-----5
4803  // | 2 | 3 |
4804  // 6-----7-----8
4805 
4806  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4807  TS_REQUIRE_NOT_NULL(ugrid);
4808 
4809  VecInt expectedFail;
4810  VecInt2d expectedCells = {{}, {2}, {1}, {}};
4811  VecInt expected2dCells = {-1, 2, 1, -1};
4812 
4813  int adjacentCell;
4814  VecInt adjacentCells = ugrid->GetCellEdgeAdjacentCells(0, -1);
4815  TS_ASSERT_EQUALS(expectedFail, adjacentCells);
4816  adjacentCell = ugrid->GetCell2dEdgeAdjacentCell(0, -1);
4817  TS_ASSERT_EQUALS(-1, adjacentCell);
4818 
4819  for (int i(0); i < ugrid->GetCellEdgeCount(0); i++)
4820  {
4821  adjacentCells = ugrid->GetCellEdgeAdjacentCells(0, i);
4822  TS_ASSERT_EQUALS(expectedCells[i], adjacentCells);
4823 
4824  adjacentCell = ugrid->GetCell2dEdgeAdjacentCell(0, i);
4825  TS_ASSERT_EQUALS(expected2dCells[i], adjacentCell);
4826  }
4827  adjacentCells = ugrid->GetCellEdgeAdjacentCells(0, ugrid->GetCellEdgeCount(0));
4828  TS_ASSERT_EQUALS(expectedFail, adjacentCells);
4829  adjacentCell = ugrid->GetCell2dEdgeAdjacentCell(0, ugrid->GetCellEdgeCount(0));
4830  TS_ASSERT_EQUALS(-1, adjacentCell);
4831 
4832  // Test a cell in the middle of an hexahedron grid
4833  std::shared_ptr<XmUGrid> hexUgrid = TEST_XmUBuildHexahedronUgrid(5, 5, 5);
4834  TS_REQUIRE_NOT_NULL(hexUgrid);
4835 
4836  expectedCells = {{2, 6, 18}, {6, 7, 23}, {6, 10, 26}, {5, 6, 21},
4837  {18, 34, 38}, {23, 38, 39}, {26, 38, 42}, {21, 37, 38},
4838  {17, 18, 21}, {18, 19, 23}, {21, 26, 25}, {23, 26, 27}};
4839 
4840  for (int i(0); i < hexUgrid->GetCellEdgeCount(22); i++)
4841  {
4842  adjacentCells = hexUgrid->GetCellEdgeAdjacentCells(22, i);
4843  TS_ASSERT_EQUALS(expectedCells[i], adjacentCells);
4844  }
4845 } // XmUGridUnitTests::testGetCellEdgeAdjacentCells
4846 //------------------------------------------------------------------------------
4848 //------------------------------------------------------------------------------
4850 {
4851  // 0-----1-----2
4852  // | 0 | 1 |
4853  // 3-----4-----5
4854  // | 2 | 3 |
4855  // 6-----7-----8
4856 
4857  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
4858  TS_REQUIRE_NOT_NULL(ugrid);
4859 
4860  VecInt expectedFail;
4861  VecInt2d expectedCells = {{0, 1}, {0, 2}, {0}};
4862  std::vector<XmEdge> edges = {{1, 4}, {3, 4}, {0, 3}};
4863 
4864  VecInt adjacentCells = ugrid->GetEdgeAdjacentCells(XmEdge(-1, -1));
4865  TS_ASSERT_EQUALS(expectedFail, adjacentCells);
4866  for (int i(0); i < edges.size(); i++)
4867  {
4868  adjacentCells = ugrid->GetEdgeAdjacentCells(edges[i]);
4869  TS_ASSERT_EQUALS(expectedCells[i], adjacentCells);
4870  }
4871 
4872  XmEdge badEdge(0, ugrid->GetPointCount());
4873  adjacentCells = ugrid->GetEdgeAdjacentCells(badEdge);
4874  TS_ASSERT_EQUALS(expectedFail, adjacentCells);
4875 
4876 } // XmUGridUnitTests::testEdgeAdjacentCells
4877 
4878 //------------------------------------------------------------------------------
4880 //------------------------------------------------------------------------------
4882 {
4883  // 2D Tests, include the bounds check
4884  VecInt emptyCellFaces = {};
4885  VecInt2d expectedCellFaces = {// XMU_QUAD
4886  {},
4887  // XMU_PIXEL
4888  {},
4889  // XMU_TRIANGLE
4890  {},
4891  // XMU_POLYGON
4892  {},
4893  // XMU_POLY_LINE
4894  {},
4895  // XMU_LINE
4896  {}};
4897  VecInt cellFaces;
4898 
4899  // 2D Shapes
4900  std::shared_ptr<XmUGrid> ugrid2d = TEST_XmUGrid2dLinear();
4901  TS_REQUIRE_NOT_NULL(ugrid2d);
4902 
4903  cellFaces = ugrid2d->GetCell3dFacePoints(-1, 0);
4904  TS_ASSERT_EQUALS(emptyCellFaces, cellFaces);
4905  cellFaces = ugrid2d->GetCell3dFacePoints(0, -1);
4906  TS_ASSERT_EQUALS(emptyCellFaces, cellFaces);
4907 
4908  for (int i(0); i < ugrid2d->GetCellCount(); i++)
4909  {
4910  cellFaces = ugrid2d->GetCell3dFacePoints(i, 0);
4911  TS_ASSERT_EQUALS(expectedCellFaces[i], cellFaces);
4912  }
4913 
4914  cellFaces = ugrid2d->GetCell3dFacePoints(ugrid2d->GetCellCount(), 0);
4915  TS_ASSERT_EQUALS(emptyCellFaces, cellFaces);
4916  cellFaces = ugrid2d->GetCell3dFacePoints(0, 1);
4917  TS_ASSERT_EQUALS(emptyCellFaces, cellFaces);
4918 
4919  // 3D Shapes
4920  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
4921  TS_REQUIRE_NOT_NULL(ugrid3d);
4922 
4923  expectedCellFaces = {// Tetra
4924  {0, 1, 15},
4925  {1, 5, 15},
4926  {5, 0, 15},
4927  {0, 5, 1},
4928  // Voxel
4929  {1, 16, 21, 6},
4930  {2, 7, 22, 17},
4931  {1, 2, 17, 16},
4932  {6, 21, 22, 7},
4933  {1, 6, 7, 2},
4934  {16, 17, 22, 21},
4935  // Hexahedron
4936  {2, 17, 22, 7},
4937  {3, 8, 23, 18},
4938  {2, 3, 18, 17},
4939  {7, 22, 23, 8},
4940  {2, 7, 8, 3},
4941  {17, 18, 23, 22},
4942  // Polyhedron
4943  {9, 8, 13, 14},
4944  {8, 9, 24, 23},
4945  {9, 14, 29, 24},
4946  {14, 13, 28, 29},
4947  {8, 13, 28, 23},
4948  {23, 24, 29, 28},
4949  // Wedge
4950  {3, 4, 18},
4951  {8, 23, 9},
4952  {3, 8, 9, 4},
4953  {4, 9, 23, 18},
4954  {18, 23, 8, 3},
4955  // Pyramid
4956  {5, 10, 11, 6},
4957  {5, 6, 20},
4958  {6, 11, 20},
4959  {11, 10, 20},
4960  {10, 5, 20}};
4961  int currId(0);
4962  for (int i(0); i < ugrid3d->GetCellCount(); i++)
4963  {
4964  for (int j(0); j < ugrid3d->GetCell3dFaceCount(i); j++, currId++)
4965  {
4966  cellFaces = ugrid3d->GetCell3dFacePoints(i, j);
4967  TS_ASSERT_EQUALS(expectedCellFaces[currId], cellFaces);
4968  }
4969  }
4970 } // XmUGridUnitTests::testGetCell3dFacePoints
4971 
4973 //------------------------------------------------------------------------------
4975 //------------------------------------------------------------------------------
4977 {
4978  // 2 hexahedrons
4979  int rows = 3;
4980  int cols = 2;
4981  int lays = 2;
4982 
4983  std::shared_ptr<xms::XmUGrid> grid = TEST_XmUBuildHexahedronUgrid(rows, cols, lays);
4984  TS_REQUIRE_NOT_NULL(grid);
4985 
4986  // clang-format off
4987  VecInt expectedNeighbor = {-1, -1, -1, 1, -1, -1, -1, -1, 0, -1, -1, -1};
4988  VecInt expectedFace = {-1, -1, -1, 2, -1, -1, -1, -1, 3, -1, -1, -1};
4989  // clang-format on
4990 
4991  int expectedIdx = 0;
4992  int neighborCellIdx;
4993 
4994  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(-1, 0);
4995  TS_ASSERT_EQUALS(-1, neighborCellIdx);
4996  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(0, -1);
4997  TS_ASSERT_EQUALS(-1, neighborCellIdx);
4998 
4999  for (int cellIdx = 0; cellIdx < grid->GetCellCount(); cellIdx++)
5000  {
5001  for (int faceIdx = 0; faceIdx < grid->GetCell3dFaceCount(cellIdx); faceIdx++, expectedIdx++)
5002  {
5003  // Check first function
5004  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx);
5005  TS_ASSERT_EQUALS(expectedNeighbor[expectedIdx], neighborCellIdx);
5006 
5007  // Check overload function
5008  int neighborFaceIdx = -1;
5009  grid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx, neighborCellIdx, neighborFaceIdx);
5010  TS_ASSERT_EQUALS(expectedNeighbor[expectedIdx], neighborCellIdx);
5011  TS_ASSERT_EQUALS(expectedFace[expectedIdx], neighborFaceIdx);
5012 
5013  // Check that faces are the same
5014  VecInt expectedFacePt = grid->GetCell3dFacePoints(cellIdx, faceIdx);
5015  std::sort(expectedFacePt.begin(), expectedFacePt.end());
5016  VecInt neighborFacePt = grid->GetCell3dFacePoints(neighborCellIdx, neighborFaceIdx);
5017  std::sort(neighborFacePt.begin(), neighborFacePt.end());
5018  if (!expectedFacePt.empty() && !neighborFacePt.empty())
5019  {
5020  TS_ASSERT_EQUALS(expectedFacePt, neighborFacePt);
5021  }
5022  }
5023  }
5024  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(grid->GetCellCount(), 0);
5025  TS_ASSERT_EQUALS(-1, neighborCellIdx);
5026  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(0, grid->GetCellCount());
5027  TS_ASSERT_EQUALS(-1, neighborCellIdx);
5028 
5029  rows = 3;
5030  cols = 3;
5031  lays = 3;
5032  grid = TEST_XmUBuildHexahedronUgrid(rows, cols, lays);
5033  TS_REQUIRE_NOT_NULL(grid);
5034 
5035  expectedNeighbor.clear();
5036  // clang-format off
5037  expectedNeighbor = {-1, 1, -1, 2, -1, 4, 0, -1, -1, 3, -1, 5, -1, 3, 0, -1, -1, 6, 2, -1, 1, -1, -1, 7, -1, 5, -1, 6, 0, -1, 4, -1, -1, 7, 1, -1, -1, 7, 4, -1, 2, -1, 6, -1, 5, -1, 3, -1};
5038  expectedFace = {-1, 0, -1, 2, -1, 4, 1, -1, -1, 2, -1, 4, -1, 0, 3, -1, -1, 4, 1, -1, 3, -1, -1, 4, -1, 0, -1, 2, 5, -1, 1, -1, -1, 2, 5, -1, -1, 0, 3, -1, 5, -1, 1, -1, 3, -1, 5, -1};
5039  // clang-format on
5040 
5041  expectedIdx = 0;
5042  for (int cellIdx = 0; cellIdx < grid->GetCellCount(); ++cellIdx)
5043  {
5044  for (int faceIdx = 0; faceIdx < grid->GetCell3dFaceCount(cellIdx); faceIdx++, expectedIdx++)
5045  {
5046  // Check first function
5047  neighborCellIdx = grid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx);
5048  TS_ASSERT_EQUALS(expectedNeighbor[expectedIdx], neighborCellIdx);
5049 
5050  // Check overload function
5051  int neighborFaceIdx = -1;
5052  grid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx, neighborCellIdx, neighborFaceIdx);
5053  TS_ASSERT_EQUALS(expectedNeighbor[expectedIdx], neighborCellIdx);
5054  TS_ASSERT_EQUALS(expectedFace[expectedIdx], neighborFaceIdx);
5055 
5056  // Check that faces are the same
5057  VecInt expectedFacePt = grid->GetCell3dFacePoints(cellIdx, faceIdx);
5058  std::sort(expectedFacePt.begin(), expectedFacePt.end());
5059  VecInt neighborFacePt = grid->GetCell3dFacePoints(neighborCellIdx, neighborFaceIdx);
5060  std::sort(neighborFacePt.begin(), neighborFacePt.end());
5061  if (!expectedFacePt.empty() && !neighborFacePt.empty())
5062  {
5063  TS_ASSERT_EQUALS(expectedFacePt, neighborFacePt);
5064  }
5065  }
5066  }
5067 } // XmUGridUnitTests::testGetCell3dFaceAdjacentCell
5069 
5071 //------------------------------------------------------------------------------
5073 //------------------------------------------------------------------------------
5075 {
5076  // 0-----1-----2
5077  // | 0 | 1 |
5078  // 3-----4-----5
5079  // | 2 | 3 |
5080  // 6-----7-----8
5081 
5082  std::shared_ptr<xms::XmUGrid> grid = TEST_XmUGridSimpleQuad();
5083  TS_REQUIRE_NOT_NULL(grid);
5084 
5085  VecInt attachedIdxs;
5086  grid->GetPointAdjacentPoints(0, attachedIdxs);
5087  VecInt expectedIdxs = {1, 3};
5088  TS_ASSERT_EQUALS(expectedIdxs, attachedIdxs);
5089  grid->GetPointAdjacentPoints(3, attachedIdxs);
5090  expectedIdxs = {0, 4, 6};
5091  TS_ASSERT_EQUALS(expectedIdxs, attachedIdxs);
5092  grid->GetPointAdjacentPoints(4, attachedIdxs);
5093  expectedIdxs = {1, 3, 5, 7};
5094  TS_ASSERT_EQUALS(expectedIdxs, attachedIdxs);
5095  VecPt3d attachedPts;
5096  grid->GetPointAdjacentLocations(0, attachedPts);
5097  VecPt3d expectedPts = {{10, 10, 0}, {0, 0, 0}};
5098  TS_ASSERT_EQUALS(expectedPts, attachedPts);
5099  grid->GetPointAdjacentLocations(3, attachedPts);
5100  expectedPts = {{0, 10, 0}, {10, 0, 0}, {0, -10, 0}};
5101  TS_ASSERT_EQUALS(expectedPts, attachedPts);
5102  grid->GetPointAdjacentLocations(4, attachedPts);
5103  expectedPts = {{10, 10, 0}, {0, 0, 0}, {20, 0, 0}, {10, -10, 0}};
5104  TS_ASSERT_EQUALS(expectedPts, attachedPts);
5105 } // XmUGridUnitTests::testGetPointAdjacentPoints
5107 
5109 //------------------------------------------------------------------------------
5111 //------------------------------------------------------------------------------
5113 {
5114  // 2d
5115  std::shared_ptr<xms::XmUGrid> grid2d = TEST_XmUGrid2dLinear();
5116  TS_REQUIRE_NOT_NULL(grid2d);
5117 
5118  VecPt3d2d expectedPolygons{
5119  {{0, 0, 0}, {10, 0, 0}, {10, 10, 0}, {0, 10, 0}},
5120  {{10, 0, 0}, {20, 0, 0}, {20, 10, 0}, {10, 10, 0}},
5121  {{20, 0, 0}, {30, 0, 0}, {20, 10, 0}},
5122  {{30, 0, 0}, {40, 0, 0}, {40, 10, 0}, {40, 20, 0}, {30, 20, 0}, {20, 10, 0}},
5123  {},
5124  {}};
5125  VecPt3d viewPolygon;
5126  VecPt3d empty;
5127  // Bounds testing
5128  TS_ASSERT(!grid2d->GetCellPlanViewPolygon(-1, viewPolygon));
5129  TS_ASSERT_EQUALS(empty, viewPolygon);
5130  TS_ASSERT(!grid2d->GetCellPlanViewPolygon(grid2d->GetCellCount(), viewPolygon));
5131  TS_ASSERT_EQUALS(empty, viewPolygon);
5132  // Regular testing
5133  for (int i = 0; i < grid2d->GetCellCount(); ++i)
5134  {
5135  // Should return true for the first 4 cells, and false for the last 2
5136  TS_ASSERT(grid2d->GetCellPlanViewPolygon(i, viewPolygon) != i >= 4);
5137  TS_ASSERT_EQUALS(expectedPolygons[i], viewPolygon);
5138  }
5139 
5140  // 3d
5141  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
5142  TS_REQUIRE_NOT_NULL(ugrid3d);
5143 
5144  expectedPolygons = {{{0, 0, 0}, {10, 0, 0}, {0, 10, 0}},
5145  {{20, 0, 0}, {20, 10, 0}, {10, 10, 0}, {10, 0, 0}},
5146  {{30, 0, 0}, {30, 10, 0}, {20, 10, 0}, {20, 0, 0}},
5147  {{40, 10, 0}, {40, 20, 0}, {30, 20, 0}, {30, 10, 0}},
5148  {{30, 0, 0}, {40, 0, 0}, {40, 10, 0}, {30, 10, 0}},
5149  {{0, 10, 0}, {10, 10, 0}, {10, 20, 0}, {0, 20, 0}}};
5150 
5151  for (int i = 0; i < ugrid3d->GetCellCount(); ++i)
5152  {
5153  TS_ASSERT(ugrid3d->GetCellPlanViewPolygon(i, viewPolygon));
5154  TS_ASSERT_EQUALS(expectedPolygons[i], viewPolygon);
5155  }
5156 
5157  std::shared_ptr<xms::XmUGrid> chevronUgrid = TEST_XmUBuild3DChevronUgrid();
5158  TS_REQUIRE_NOT_NULL(chevronUgrid);
5159 
5160  expectedPolygons = {{{0.0, 0.0, 0.0}, {20.0, 10.0, 0.0}, {40.0, 0.0, 0.0}, {20.0, 50.0, 0.0}}};
5161  TS_ASSERT(chevronUgrid->GetCellPlanViewPolygon(0, viewPolygon));
5162  TS_ASSERT_EQUALS(expectedPolygons[0], viewPolygon);
5163 
5164 } // XmUGridUnitTests::testGetCellPlanViewPolygon
5166 
5167 //------------------------------------------------------------------------------
5169 //------------------------------------------------------------------------------
5171 {
5172  // 3d - For vertically prismatic cells returns the unique plan view points for side faces
5173  // in sorted order. For cells that aren't vertically prismatic returns an empty vector.
5174  VecPt3d points = {
5175  {0, 0, 0}, {1, 0, 0}, {2, 0, 0}, {0, 0, 1}, {1, 0, 1},
5176  {2, 0, 1}, {0, 0, 2}, {2, 0, 2}, // front face
5177  {0, 1, 2}, {1, 1, 2}, {2, 1, 2}, // points midway back
5178  {0, 2, 0}, {2, 2, 0}, {0, 2, 2}, {1, 2, 2}, {2, 2, 2}, // back points
5179  {4, 2, 0}, {3, 1, 2} // tetrahedron
5180  };
5181  // clang-format off
5182  VecInt cells = {
5183  XMU_POLYHEDRON, 10, // hexahedron split into smaller faces
5184  4, 0, 1, 4, 3, // hex front - lower left face
5185  4, 1, 2, 5, 4, // hex front - lower right face
5186  5, 3, 4, 5, 7, 6, // hex front - top face
5187  5, 6, 7, 10, 9, 8, // hex top - front face
5188  4, 8, 9, 14, 13, // hex top - left back face
5189  4, 9, 10, 15, 14, // hex top - right back face
5190  6, 0, 3, 6, 8, 13, 11, // hex left
5191  6, 2, 12, 15, 10, 7, 5, // hex right
5192  5, 0, 11, 12, 2, 1, // hex bottom
5193  5, 11, 13, 14, 15, 12, // hex back
5194  XMU_TETRA, 4, 2, 16, 12, 17 // tetrahedron with
5195  };
5196  // clang-format on
5197  std::shared_ptr<XmUGrid> ugrid3d = XmUGrid::New(points, cells);
5198  TS_REQUIRE_NOT_NULL(ugrid3d);
5199 
5200  // vertically prismatic
5201  VecPt3d cellPoints;
5202  ugrid3d->GetCellPlanViewPolygon(0, cellPoints);
5203  VecPt3d expectedGetCellPoints = {{1, 0, 0}, {2, 0, 0}, {2, 1, 0}, {2, 2, 0},
5204  {1, 2, 0}, {0, 2, 0}, {0, 1, 0}, {0, 0, 0}};
5205  TS_ASSERT_EQUALS(expectedGetCellPoints, cellPoints);
5206 
5207  // not vertically prismatic
5208  ugrid3d->GetCellPlanViewPolygon(1, cellPoints);
5209  expectedGetCellPoints = {{2, 0, 0}, {4, 2, 0}, {2, 2, 0}};
5210  TS_ASSERT_EQUALS(expectedGetCellPoints, cellPoints);
5211 } // XmUGridUnitTests::testGetCellPlanViewPolygonMultiSideFace
5212 //------------------------------------------------------------------------------
5214 //------------------------------------------------------------------------------
5216 {
5217  // 0-----1-----2
5218  // | 0 | 1 |
5219  // 3-----4-----5
5220  // | 2 | 3 |
5221  // 6-----7-----8
5222 
5223  // VecPt3d points = { { 0, 10, 0 }, { 10, 10, 0 }, { 20, 10, 0 }, { 0, 0, 0 }, { 10, 0, 0 },
5224  //{ 20, 0, 0 }, { 0, -10, 0 }, { 10, -10, 0 }, { 20, -10, 0 } };
5225 
5226  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5227  TS_REQUIRE_NOT_NULL(ugrid);
5228 
5229  Pt3d validPt = {5.0, 5.0, 0.0};
5230  Pt3d invalid = {500.0, 500.0, 0.0};
5231 
5232  TS_ASSERT(ugrid->IsValidPointChange(4, validPt));
5233  TS_ASSERT(!ugrid->IsValidPointChange(4, invalid));
5234 
5235  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUBuildHexahedronUgrid(4, 4, 4);
5236 
5237  validPt = ugrid3d->GetPointLocation(21);
5238  validPt.x += 0.5;
5239  validPt.y += 0.5;
5240  validPt.z += 0.5;
5241  TS_ASSERT(ugrid3d->IsValidPointChange(21, validPt));
5242  TS_ASSERT(!ugrid3d->IsValidPointChange(21, invalid));
5243 
5244  TS_ASSERT(ugrid->SetPointLocation(4, validPt));
5245  TS_ASSERT(ugrid->SetPointLocation(4, invalid));
5246  TS_ASSERT(ugrid3d->SetPointLocation(21, validPt));
5247  TS_ASSERT(ugrid3d->SetPointLocation(21, invalid));
5248 } // XmUGridUnitTests::testIsCellValidWithPointChange
5249 
5251 //------------------------------------------------------------------------------
5253 //------------------------------------------------------------------------------
5255 {
5256  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5257  TS_REQUIRE_NOT_NULL(ugrid);
5258 
5259  // Test GetPointCount
5260  TS_ASSERT_EQUALS(ugrid->GetPointCount(), 9);
5261  VecPt3d points = {{0, 10, 0}, {10, 10, 0}, {20, 10, 0}, {0, 0, 0}, {10, 0, 0},
5262  {20, 0, 0}, {0, -10, 0}, {10, -10, 0}, {20, -10, 0}};
5263 
5264  // Test Locations
5265  TS_ASSERT_EQUALS(ugrid->GetLocations(), points);
5266  for (int i = 0; i < points.size(); ++i)
5267  {
5268  TS_ASSERT_EQUALS(points[i], ugrid->GetPointLocation(i));
5269  }
5270 
5271  // Test SetPointLocation & GetPointLocation
5272  Pt3d invalid = {100, 100, 100};
5273  Pt3d valid = {5, 5, 5};
5274  TS_ASSERT(!ugrid->IsValidPointChange(4, invalid));
5275  TS_ASSERT(ugrid->SetPointLocation(4, valid));
5276  TS_ASSERT_EQUALS(valid, ugrid->GetPointLocation(4));
5277 
5278  VecInt pointIndices = {0, 3, 6};
5279  VecPt3d expectedPoints = {{0, 10, 0}, {0, 0, 0}, {0, -10, 0}};
5280  VecPt3d pointsPt3d;
5281 
5282  // Test GetPointsLocations
5283  pointsPt3d = ugrid->GetPointsLocations(pointIndices);
5284  TS_ASSERT_EQUALS(expectedPoints, pointsPt3d);
5285 
5286  // Test GetExtents
5287  Pt3d min, max, expectedMin = {0, -10, 0}, expectedMax = {20, 10, 5};
5288  ugrid->GetExtents(min, max);
5289  TS_ASSERT_EQUALS(expectedMin, min);
5290  TS_ASSERT_EQUALS(expectedMax, max);
5291 
5292  // Test GetPointAdjacentCells
5293  VecInt expectedCells = {0, 2};
5294  VecInt cellsAssociated = ugrid->GetPointAdjacentCells(3);
5295  TS_ASSERT_EQUALS(expectedCells, cellsAssociated);
5296 
5297  // Test GetPointsAdjacentCells
5298  VecInt expectedCommonCells = {0, 1};
5299  VecInt pointIndex = {1};
5300  VecInt commonCells = ugrid->GetPointsAdjacentCells(pointIndex);
5301  TS_ASSERT_EQUALS(expectedCells, cellsAssociated);
5302 
5303 } // XmUGridUnitTests::testPointFunctions
5305 
5307 //------------------------------------------------------------------------------
5309 //------------------------------------------------------------------------------
5311 {
5312  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5313  TS_REQUIRE_NOT_NULL(ugrid);
5314 
5315  // Test GetCellPoints
5316  VecInt pointsOfCell = ugrid->GetCellPoints(0);
5317  VecInt expectedPoints = {0, 3, 4, 1};
5318  TS_ASSERT_EQUALS(expectedPoints, pointsOfCell);
5319  // Test overload
5320  ugrid->GetCellPoints(0, pointsOfCell);
5321  TS_ASSERT_EQUALS(expectedPoints, pointsOfCell);
5322  VecPt3d locations;
5323  ugrid->GetCellLocations(0, locations);
5324  VecPt3d expectedLocations = {{0, 10, 0}, {0, 0, 0}, {10, 0, 0}, {10, 10, 0}};
5325  TS_ASSERT_EQUALS(expectedLocations, locations);
5326 
5327  // Test GetCellExtents
5328  Pt3d min, max;
5329  ugrid->GetCellExtents(0, min, max);
5330  TS_ASSERT_EQUALS(Pt3d(0, 0, 0), min);
5331  TS_ASSERT_EQUALS(Pt3d(10, 10, 0), max);
5332 
5333  // Test GetCellType
5334  TS_ASSERT_EQUALS(XMU_QUAD, ugrid->GetCellType(0));
5335 
5336  // Test GetDimensionCounts
5337  VecInt expectedDimensions = {0, 0, 4, 0};
5338  TS_ASSERT_EQUALS(expectedDimensions, ugrid->GetDimensionCounts());
5339 
5340  // Test GetCellDimension
5341  TS_ASSERT_EQUALS(2, ugrid->GetCellDimension(0));
5342 
5343  // Test GetCellCentroid
5344  Pt3d centroid;
5345  TS_ASSERT(ugrid->GetCellCentroid(0, centroid));
5346  TS_ASSERT_EQUALS(Pt3d(5, 5, 0), centroid);
5347 } // XmUGridUnitTests::testCellFunctions
5350 //------------------------------------------------------------------------------
5352 //------------------------------------------------------------------------------
5354 {
5355  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5356  TS_REQUIRE_NOT_NULL(ugrid);
5357 
5358  // Test GetCellstream
5359  VecInt cellstream = ugrid->GetCellstream();
5360  VecInt expectedCellstream = {XMU_QUAD, 4, 0, 3, 4, 1, XMU_QUAD, 4, 1, 4, 5, 2,
5361  XMU_QUAD, 4, 3, 6, 7, 4, XMU_QUAD, 4, 4, 7, 8, 5};
5362  TS_ASSERT_EQUALS(expectedCellstream, cellstream);
5363 
5364  // Test GetCellCellstream
5365  ugrid->GetCellCellstream(0, cellstream);
5366  expectedCellstream = {XMU_QUAD, 4, 0, 3, 4, 1};
5367  TS_ASSERT_EQUALS(expectedCellstream, cellstream);
5368 
5369 } // XmUGridUnitTests::testCellstreamFunctions
5372 //------------------------------------------------------------------------------
5374 //------------------------------------------------------------------------------
5376 {
5377  // 0-----1-----2
5378  // | 0 | 1 |
5379  // 3-----4-----5
5380  // | 2 | 3 |
5381  // 6-----7-----8
5382  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5383  TS_REQUIRE_NOT_NULL(ugrid);
5384 
5385  // Get Adjacent Cells from cell and edge
5386  VecInt2d expectedCells = {{}, {2}, {1}, {}};
5387  VecInt expected2dCells = {-1, 2, 1, -1};
5388  int adjacentCell;
5389  VecInt adjacentCells;
5390  for (int i(0); i < ugrid->GetCellEdgeCount(0); i++)
5391  {
5392  adjacentCells = ugrid->GetCellEdgeAdjacentCells(0, i);
5393  TS_ASSERT_EQUALS(expectedCells[i], adjacentCells);
5394  // For 2D cells only
5395  adjacentCell = ugrid->GetCell2dEdgeAdjacentCell(0, i);
5396  TS_ASSERT_EQUALS(expected2dCells[i], adjacentCell);
5397  }
5398 
5399  // Get Adjacent cells from given Edge
5400  VecInt2d expectedCellsFromEdge = {{0, 1}, {0, 2}, {0}};
5401  std::vector<XmEdge> edges = {{1, 4}, {3, 4}, {0, 3}};
5402  adjacentCells = ugrid->GetEdgeAdjacentCells(XmEdge(-1, -1));
5403  for (int i(0); i < edges.size(); i++)
5404  {
5405  adjacentCells = ugrid->GetEdgeAdjacentCells(edges[i]);
5406  TS_ASSERT_EQUALS(expectedCellsFromEdge[i], adjacentCells);
5407  }
5408 } // XmUGridUnitTests::testCellAdjacentCellFunctions
5411 //------------------------------------------------------------------------------
5413 //------------------------------------------------------------------------------
5415 {
5416  std::shared_ptr<XmUGrid> ugrid = TEST_XmUGridSimpleQuad();
5417  TS_REQUIRE_NOT_NULL(ugrid);
5418 
5419  // Test GetCellEdges
5420  std::vector<XmEdge> edges = ugrid->GetCellEdges(0);
5421  std::vector<XmEdge> expectededges = {{0, 3}, {3, 4}, {4, 1}, {1, 0}};
5422  TS_ASSERT_EQUALS(expectededges, edges);
5423 
5424 } // XmUGridUnitTests::testCellEdges
5427 //------------------------------------------------------------------------------
5429 //------------------------------------------------------------------------------
5431 {
5432  // 3D Shapes
5433  std::shared_ptr<XmUGrid> ugrid3d = TEST_XmUGrid3dLinear();
5434  TS_REQUIRE_NOT_NULL(ugrid3d);
5435 
5436  VecInt cellFace;
5437  VecInt2d expectedCellFaces = {// Tetra
5438  {0, 1, 15},
5439  {1, 5, 15},
5440  {5, 0, 15},
5441  {0, 5, 1},
5442  // Voxel
5443  {1, 16, 21, 6},
5444  {2, 7, 22, 17},
5445  {1, 2, 17, 16},
5446  {6, 21, 22, 7},
5447  {1, 6, 7, 2},
5448  {16, 17, 22, 21},
5449  // Hexahedron
5450  {2, 17, 22, 7},
5451  {3, 8, 23, 18},
5452  {2, 3, 18, 17},
5453  {7, 22, 23, 8},
5454  {2, 7, 8, 3},
5455  {17, 18, 23, 22},
5456  // Polyhedron
5457  {9, 8, 13, 14},
5458  {8, 9, 24, 23},
5459  {9, 14, 29, 24},
5460  {14, 13, 28, 29},
5461  {8, 13, 28, 23},
5462  {23, 24, 29, 28},
5463  // Wedge
5464  {3, 4, 18},
5465  {8, 23, 9},
5466  {3, 8, 9, 4},
5467  {4, 9, 23, 18},
5468  {18, 23, 8, 3},
5469  // Pyramid
5470  {5, 10, 11, 6},
5471  {5, 6, 20},
5472  {6, 11, 20},
5473  {11, 10, 20},
5474  {10, 5, 20}};
5475  int expectedIdx = 0;
5476  for (int i(0); i < ugrid3d->GetCellCount(); i++)
5477  {
5478  for (int j(0); j < ugrid3d->GetCell3dFaceCount(i); j++, expectedIdx++)
5479  {
5480  cellFace = ugrid3d->GetCell3dFacePoints(i, j);
5481  TS_ASSERT_EQUALS(expectedCellFaces[expectedIdx], cellFace);
5482  }
5483  }
5484 
5485  VecInt2d cellFaces;
5486  expectedIdx = 0;
5487  for (int i(0); i < ugrid3d->GetCellCount(); i++)
5488  {
5489  cellFaces = ugrid3d->GetCell3dFacesPoints(i);
5490  TS_ASSERT_EQUALS(cellFaces.size(), ugrid3d->GetCell3dFaceCount(i));
5491  for (int j(0); j < ugrid3d->GetCell3dFaceCount(i); j++, expectedIdx++)
5492  {
5493  TS_ASSERT_EQUALS(expectedCellFaces[expectedIdx], cellFaces[j]);
5494  }
5495  }
5496 
5497  VecInt faceOrientations;
5498  for (int cellIdx = 0; cellIdx < ugrid3d->GetCellCount(); ++cellIdx)
5499  {
5500  for (int faceIdx = 0; faceIdx < ugrid3d->GetCell3dFaceCount(cellIdx); ++faceIdx)
5501  {
5502  faceOrientations.push_back(ugrid3d->GetCell3dFaceOrientation(cellIdx, faceIdx));
5503  }
5504  }
5505 
5506  VecInt expectedFaceOrientations = {
5507  // Tetra
5508  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_TOP, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_BOTTOM,
5509  // Voxel
5510  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5511  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_TOP,
5512  // Hexahedron
5513  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5514  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_TOP,
5515  // Polyhedron
5516  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5517  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_TOP,
5518  // Wedge
5519  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_TOP,
5520  XMU_ORIENTATION_SIDE,
5521  // Pyramid
5522  XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_TOP, XMU_ORIENTATION_TOP,
5523  XMU_ORIENTATION_SIDE};
5524 
5525  TS_ASSERT_EQUALS(expectedFaceOrientations, faceOrientations);
5526 } // XmUGridUnitTests::testCell3dFaceFunctions
5528 //------------------------------------------------------------------------------
5530 //------------------------------------------------------------------------------
5532 {
5533  std::shared_ptr<XmUGrid> xmUGrid = TEST_XmUBuildHexahedronUgrid(2, 2, 2, Pt3d());
5534  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 0));
5535  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 1));
5536  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 2));
5537  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 3));
5538  TS_ASSERT_EQUALS(XMU_ORIENTATION_TOP, xmUGrid->GetCell3dFaceOrientation(0, 4));
5539  TS_ASSERT_EQUALS(XMU_ORIENTATION_BOTTOM, xmUGrid->GetCell3dFaceOrientation(0, 5));
5540  xmUGrid = TEST_XmUBuildPolyhedronUgrid(2, 2, 2, Pt3d());
5541  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 0));
5542  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 1));
5543  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 2));
5544  TS_ASSERT_EQUALS(XMU_ORIENTATION_SIDE, xmUGrid->GetCell3dFaceOrientation(0, 3));
5545  TS_ASSERT_EQUALS(XMU_ORIENTATION_TOP, xmUGrid->GetCell3dFaceOrientation(0, 4));
5546  TS_ASSERT_EQUALS(XMU_ORIENTATION_BOTTOM, xmUGrid->GetCell3dFaceOrientation(0, 5));
5547 } // XmUGridUnitTests::testGetCell3dFaceOrientationHexahedrons
5548 //------------------------------------------------------------------------------
5552 //------------------------------------------------------------------------------
5554 {
5555  // clang-format off
5556  // vertically prismatic concave cell
5557  VecPt3d nodes = {
5558  Pt3d(1620022.8468, 6134363.759, 0), Pt3d(1620009.9411, 6134414.9476, 0),
5559  Pt3d(1619994.9996, 6134289.4991, 0), Pt3d(1619866.1047, 6134542.8755, 0),
5560  Pt3d(1619745.5374, 6134167.0467, 0), Pt3d(1619829.9996, 6134192.9991, 0),
5561  Pt3d(1619773.3077, 6134545.2322, 0), Pt3d(1619710.0815, 6134182.8542, 0),
5562  Pt3d(1619693.1618, 6134208.2547, 0), Pt3d(1619645.5529, 6134438.0278, 0),
5563  Pt3d(1619774.9993, 6134371.9982, 0), Pt3d(1620022.8468, 6134363.759, -10),
5564  Pt3d(1620009.9411, 6134414.9476, -10), Pt3d(1619994.9996, 6134289.4991, -10),
5565  Pt3d(1619866.1047, 6134542.8755, -10), Pt3d(1619745.5374, 6134167.0467, -10),
5566  Pt3d(1619829.9996, 6134192.9991, -10), Pt3d(1619773.3077, 6134545.2322, -10),
5567  Pt3d(1619710.0815, 6134182.8542, -10), Pt3d(1619693.1618, 6134208.2547, -10),
5568  Pt3d(1619645.5529, 6134438.0278, -10), Pt3d(1619774.9993, 6134371.9982, -10) };
5569  VecInt elements = {
5570  XMU_POLYHEDRON,
5571  13, // number of faces
5572  11, 5, 10, 2, 0, 1, 3, 6, 9, 8, 7, 4, // top
5573  11, 16, 15, 18, 19, 20, 17, 14, 12, 11, 13, 21, // bottom
5574  4, 5, 16, 21, 10, // sides
5575  4, 10, 21, 13, 2,
5576  4, 2, 13, 11, 0,
5577  4, 0, 11, 12, 1,
5578  4, 1, 12, 14, 3,
5579  4, 3, 14, 17, 6,
5580  4, 6, 17, 20, 9,
5581  4, 9, 20, 19, 8,
5582  4, 8, 19, 18, 7,
5583  4, 7, 18, 15, 4,
5584  4, 4, 1, 16, 5
5585  };
5586  // clang-format on
5587 
5588  std::shared_ptr<XmUGrid> xmUGrid = XmUGrid::New(nodes, elements);
5589  VecInt actual;
5590  for (int faceIdx = 0; faceIdx < xmUGrid->GetCell3dFaceCount(0); ++faceIdx)
5591  {
5592  actual.push_back(xmUGrid->GetCell3dFaceOrientation(0, faceIdx));
5593  }
5594  VecInt expected = {XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM, XMU_ORIENTATION_SIDE,
5595  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5596  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5597  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5598  XMU_ORIENTATION_SIDE};
5599  TS_ASSERT_EQUALS(expected, actual);
5600 } // XmUGridUnitTests::testFaceOrientationConcaveCell
5601 //------------------------------------------------------------------------------
5603 //------------------------------------------------------------------------------
5605 {
5606  std::shared_ptr<XmUGrid> xmUGrid = TEST_XmUBuildHexahedronUgrid(2, 3, 2);
5607 
5608  VecInt2d expectedNeighbors = {{-1, 1, -1, -1, -1, -1}, {0, -1, -1, -1, -1, -1}};
5609  VecInt2d expectedOrientations = {
5610  {XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5611  XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM},
5612  {XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5613  XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM}};
5614 
5615  // test four times, to fill the cache, read from the cache, turn off the cache,
5616  // and turn on the cache
5617  bool useCacheValues[] = {true, true, false, true};
5618  for (bool useCacheValue : useCacheValues)
5619  {
5620  xmUGrid->SetUseCache(useCacheValue);
5621  for (int cellIdx = 0; cellIdx < xmUGrid->GetCellCount(); ++cellIdx)
5622  {
5623  TS_ASSERT_EQUALS(6, xmUGrid->GetCell3dFaceCount(cellIdx));
5624  for (int faceIdx = 0; faceIdx < xmUGrid->GetCell3dFaceCount(cellIdx); ++faceIdx)
5625  {
5626  int neighbor = xmUGrid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx);
5627  TS_ASSERT_EQUALS(expectedNeighbors[cellIdx][faceIdx], neighbor);
5628  int orientation = (int)xmUGrid->GetCell3dFaceOrientation(cellIdx, faceIdx);
5629  TS_ASSERT_EQUALS(expectedOrientations[cellIdx][faceIdx], orientation);
5630  }
5631  }
5632  }
5633 
5634  // change to different points and cells and test again
5635  expectedNeighbors = {{-1, 1, -1, -1, -1, -1}, {0, 2, -1, -1, -1, -1}, {1, -1, -1, -1, -1, -1}};
5636  expectedOrientations = {{XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5637  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM},
5638  {XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5639  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM},
5640  {XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE, XMU_ORIENTATION_SIDE,
5641  XMU_ORIENTATION_SIDE, XMU_ORIENTATION_TOP, XMU_ORIENTATION_BOTTOM}};
5642  std::shared_ptr<XmUGrid> newXmUGrid = TEST_XmUBuildHexahedronUgrid(2, 4, 2);
5643  xmUGrid->SetLocations(newXmUGrid->GetLocations());
5644  xmUGrid->SetCellstream(newXmUGrid->GetCellstream());
5645  for (bool useCacheValue : useCacheValues)
5646  {
5647  xmUGrid->SetUseCache(useCacheValue);
5648  for (int cellIdx = 0; cellIdx < xmUGrid->GetCellCount(); ++cellIdx)
5649  {
5650  TS_ASSERT_EQUALS(6, xmUGrid->GetCell3dFaceCount(cellIdx));
5651  for (int faceIdx = 0; faceIdx < xmUGrid->GetCell3dFaceCount(cellIdx); ++faceIdx)
5652  {
5653  int neighbor = xmUGrid->GetCell3dFaceAdjacentCell(cellIdx, faceIdx);
5654  TS_ASSERT_EQUALS(expectedNeighbors[cellIdx][faceIdx], neighbor);
5655  int orientation = (int)xmUGrid->GetCell3dFaceOrientation(cellIdx, faceIdx);
5656  TS_ASSERT_EQUALS(expectedOrientations[cellIdx][faceIdx], orientation);
5657  }
5658  }
5659  }
5660 } // XmUGridUnitTests::testCell3dFunctionCaching
5661 //------------------------------------------------------------------------------
5663 //------------------------------------------------------------------------------
5664 //#define SPEEDTEST
5665 #ifdef SPEEDTEST
5666 #include <boost/timer/timer.hpp>
5667 #endif
5669 {
5670 #ifdef SPEEDTEST
5671  int rows = 1000;
5672  int cols = 500;
5673  int lays = 4;
5674 
5675  // std::shared_ptr<xms::XmUGrid> grid = TEST_XmUBuildQuadUGrid(rows, cols);
5676  // std::shared_ptr<xms::XmUGrid> grid = TEST_XmUBuildHexahedronUgrid(rows, cols, lays);
5677  std::shared_ptr<xms::XmUGrid> grid = TEST_XmUBuildPolyhedronUgrid(rows, cols, lays);
5678 
5679  {
5680  boost::timer::cpu_timer timer;
5681  std::shared_ptr<XmUGrid> ugrid = XmUGrid::New(grid->GetLocations(), grid->GetCellstream());
5682  std::cerr << timer.format() << '\n';
5683  }
5684 
5685 #endif
5686 } // XmUGridUnitTests::testLargeUGridLinkSpeed
5687 
5688 #endif
Cached value needs to be calculated.
Definition: XmUGrid.cpp:214
void testUGridStreams()
[snip_test_UGrid_Streams]
Definition: XmUGrid.cpp:4041
std::shared_ptr< XmUGrid > TEST_XmUGrid1Left90Tri()
Builds a 1 cell (left 90 degree triangle) 2D XmUGrid for testing.
Definition: XmUGrid.cpp:3639
VecInt GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx) const
Get the index of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:3444
bool gmOnLineWithTol(const Pt3d &p1, const Pt3d &p2, const double x, const double y, const double tol)
Determines if a point (x,y) is on the line defined by p1 and p2. Assumes p1 and p2 aren&#39;t the same...
Definition: geoms.cpp:732
std::shared_ptr< XmUGrid > TEST_XmUGrid3dLinear()
Builds an XmUGrid with supported 3D linear cells for testing.
Definition: XmUGrid.cpp:3705
void SetLocations(const VecPt3d &a_locations)
Set UGrid points.
Definition: XmUGrid.cpp:662
int GetPointAdjacentCellCount(int a_pointIdx) const
Get the number of cells that use a point.
Definition: XmUGrid.cpp:737
VecInt GetCellAdjacentCells(int a_cellIdx) const
Get the cells neighboring a cell (cells associated with any of it&#39;s points)
Definition: XmUGrid.cpp:3379
#define XM_LOG(A, B)
bool SetCellstream(const VecInt &a_cellstream)
Set the ugrid cells for the entire UGrid using a cell stream.
Definition: XmUGrid.cpp:3357
bool GetCellCentroid(int a_cellIdx, Pt3d &a_centroid) const
Get the centroid location of a cell.
Definition: XmUGrid.cpp:3412
Pt3d GetPointXy0(int a_pointIdx) const
Get the X, Y location of a point.
Definition: XmUGrid.cpp:700
XmEdge GetCellEdge(int a_cellIdx, int a_edgeIdx) const
Get the points of a cell.
Definition: XmUGrid.cpp:1360
Contains the XmUGrid Class and supporting data types.
std::shared_ptr< xms::XmUGrid > TEST_XmUBuildHexahedronUgrid(int a_rows, int a_cols, int a_lays)
Builds a UGrid of Quads at 1 spacing for rows & cols specified.
Definition: XmUGrid.cpp:3817
void testCellEdges()
Test various cell functions.
Definition: XmUGrid.cpp:5414
void testGetPointAdjacentCellsSimple()
Test getting the cells attached to points.
Definition: XmUGrid.cpp:4371
Implementation for XmUGrid.
Definition: XmUGrid.cpp:50
std::vector< int > VecInt
int GetCellDimension(int a_cellIdx) const
Get the dimension of the specified cell.
Definition: XmUGrid.cpp:1012
void testGetCellPlanViewPolygonMultiSideFace()
[snip_test_GetCellPlanViewPolygon]
Definition: XmUGrid.cpp:5170
int GetCell3dFacePointCount(int a_cellIdx, int a_faceIdx) const
Get the number of face points for a given cell and face.
Definition: XmUGrid.cpp:1616
VecInt m_faceOrientation
For vertically prismatic cell is face top, side, bottom.
Definition: XmUGrid.cpp:228
bool DoEdgesCrossWithPointChange(int a_changedPtIdx, const Pt3d &a_newPosition, const std::vector< XmEdge > &a_edges) const
Gets whether or not edges cross with a point change.
Definition: XmUGrid.cpp:1281
XmUGrid & operator=(XmUGrid a_xmUGrid)
Assignment operator.
Definition: XmUGrid.cpp:2928
int GetCellEdgeCount(int a_cellIdx) const
Get the number of edges for a cell.
Definition: XmUGrid.cpp:3422
void testGetPointAdjacentPoints()
[snip_test_GetCell3dFaceAdjacentCell]
Definition: XmUGrid.cpp:5074
int GetCell2dEdgeAdjacentCell(int a_cellIdx, int a_edgeIdx) const
Get the index of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:1472
#define XM_NONE
Pt3d GetPointXy0(int a_pointIdx) const
Get the X, Y location of a point.
Definition: XmUGrid.cpp:3141
VecInt2d GetCell3dFacesPoints(int a_cellIdx) const
Get the faces of a cell.
Definition: XmUGrid.cpp:1727
void testGetCell3dFaceOrientationHexahedrons()
[snip_test_Cell3dFaceFunctions]
Definition: XmUGrid.cpp:5531
static void GetUniquePointsFromPolyhedronCellstream(const VecInt &a_cellstream, int a_numCellItems, int &a_currIdx, VecInt &a_uniqueGetCellPoints, VecInt &a_pointLastUsedIdx)
Get the unique points in a flat set.
Definition: XmUGrid.cpp:2244
bool SetCellstream(const VecInt &a_cellstream)
Set the ugrid cells for the entire UGrid using a cell stream.
Definition: XmUGrid.cpp:1051
Pt3d GetPointLocation(int a_pointIdx) const
Get the point.
Definition: XmUGrid.cpp:672
std::shared_ptr< xms::XmUGrid > TEST_XmUBuildPolyhedronUgrid(int a_rows, int a_cols, int a_lays)
Builds a UGrid of Quads at 1 spacing for rows & cols specified.
Definition: XmUGrid.cpp:3883
XmUGridCellType
Matches cell types from VTK (see vtkCellType.h)
Definition: XmUGrid.h:33
Impl & operator=(const Impl &a_xmUGrid)=default
Default ssignment operator.
void testGetPointAdjacentCells()
Test getting cells adjacent to a point.
Definition: XmUGrid.cpp:4411
std::shared_ptr< XmUGrid > TEST_XmUGridSimpleQuad()
Builds a 2 cell (Quad) 2D XmUGrid for testing.
Definition: XmUGrid.cpp:3662
VecInt GetPointsAdjacentCells(const VecInt &a_points) const
Gets the common cells from a vector of points.
Definition: XmUGrid.cpp:3202
void testGetCellType()
Test getting number of points, cells, and cell type.
Definition: XmUGrid.cpp:4179
XmUGridCellType GetCellType(int a_cellIdx) const
Get the cell type of a specified cell.
Definition: XmUGrid.cpp:959
void testGetCellPoints()
Test getting a vector of point indices for a cell.
Definition: XmUGrid.cpp:4486
void GetExtents(Pt3d &a_min, Pt3d &a_max) const
Get extents of all points in UGrid.
Definition: XmUGrid.cpp:727
VecInt m_pointsToCells
Definition: XmUGrid.cpp:220
bool IsValidPointChange(int a_changedPtIdx, const Pt3d &a_newPosition) const
Determine whether adjacent cells are valid after a point is moved.
Definition: XmUGrid.cpp:3239
Pt3d GetPointLocation(int a_pointIdx) const
Get the point.
Definition: XmUGrid.cpp:3120
int GetCell3dFaceAdjacentCell(int a_cellIdx, int a_faceIdx) const
Get the cell face neighbors for given cell and face index.
Definition: XmUGrid.cpp:1744
const VecPt3d & GetLocations() const
Get vector of UGrid points.
Definition: XmUGrid.cpp:3101
int GetCell3dFaceCount(int a_cellIdx) const
Get the number of cell faces for given cell.
Definition: XmUGrid.cpp:1596
const VecInt & GetCellstream() const
Get cell stream vector for the entire UGrid.
Definition: XmUGrid.cpp:1034
bool IsValidCellIdx(int a_cellIdx) const
Determine if a cell index is valid.
Definition: XmUGrid.cpp:1230
bool GetCellXySegments(int cellIdx, VecPt3d &a_segments) const
Get the XY segments of a cell.
Definition: XmUGrid.cpp:2418
bool IsValidPointChange(int a_changedPtIdx, const Pt3d &a_newPosition) const
Determine whether adjacent cells are valid after a point is moved.
Definition: XmUGrid.cpp:1240
int GetCellDimension(int a_cellIdx) const
Get the dimension of the specified cell.
Definition: XmUGrid.cpp:3319
std::shared_ptr< XmUGrid > TEST_XmUGrid2dLinear()
Builds an XmUGrid with supported 1D and 2D linear cells for testing.
Definition: XmUGrid.cpp:3679
void gmGetConvexHull(const VecPt3d &a_pts, VecPt3d &a_hull, bool a_includeOn)
Calculate convex hull using Monotone chain aka Andrew&#39;s algorithm.
Definition: geoms.cpp:2211
int GetSecond() const
Get the second index.
Definition: XmEdge.cpp:119
bool SetPointLocation(int a_pointIdx, const Pt3d &a_location)
Set the point.
Definition: XmUGrid.cpp:684
bool m_useCache
Are we using caching for some calls?
Definition: XmUGrid.cpp:225
#define XM_ENSURE_TRUE_NO_ASSERT(...)
static bool GetUniquePointsFromPolyhedronSingleCellstream(const VecInt &a_cellstream, VecInt &a_cellPoints)
Get the unique points for cell stream of a single polyhedron cell.
Definition: XmUGrid.cpp:2273
std::unique_ptr< Impl > m_impl
implementation
Definition: XmUGrid.h:194
VecInt GetCellAdjacentCells(int a_cellIdx) const
Get the cells neighboring a cell (cells associated with any of it&#39;s points)
Definition: XmUGrid.cpp:1091
void GetExtentsFromPoints(const VecPt3d &a_locations, Pt3d &a_min, Pt3d &a_max) const
Function to get the extents from a list of points. Will be removed after geometry library is built...
Definition: XmUGrid.cpp:2443
bool IsSideFace(int a_cellIdx, int a_faceIdx) const
Determines if a cell face is a vertical side face.
Definition: XmUGrid.cpp:2744
int GetCellEdgeCount(int a_cellIdx) const
Get the number of edges for a cell.
Definition: XmUGrid.cpp:1320
Code to calculate the convex hull of a set of points in two dimensions.
void SetUseCache(bool a_useCache)
Turn on or off use of caching to speed up some operations.
Definition: XmUGrid.cpp:3081
void testGetCellAdjacentCells()
[snip_test_GetCellAdjacentCells]
Definition: XmUGrid.cpp:4718
void GetCellExtents(int a_cellIdx, Pt3d &a_min, Pt3d &a_max) const
Get the extents of the given cell.
Definition: XmUGrid.cpp:1023
void Swap(XmUGrid &a_xmUGrid)
Swap data between two XmUGrids.
Definition: XmUGrid.cpp:2937
void testGetSetPoint()
[snip_test_UGrid_Streams]
Definition: XmUGrid.cpp:4099
int GetCellCount() const
Get the number of cells.
Definition: XmUGrid.cpp:3248
void testCellstreamFunctions()
Test various cell functions.
Definition: XmUGrid.cpp:5353
bool IsEquivalent(const XmEdge &a_edge) const
Test if edge is the same ignoring direction.
Definition: XmEdge.cpp:136
VecInt m_faceNeighbor
Cache for Face neighbor.
Definition: XmUGrid.cpp:229
void UpdateLinks()
Update internal links to navigate between associated points and cells.
Definition: XmUGrid.cpp:1890
void testGetCell3dFacePoints()
Test retrieving Cell Face.
Definition: XmUGrid.cpp:4881
VecInt GetPointAdjacentCells(int a_pointIdx) const
Get the cells that are associated with the specified point.
Definition: XmUGrid.cpp:750
double gmPolygonArea(const Pt3d *pts, size_t npoints)
Compute 2d planview projection of area of polygon.
Definition: geoms.cpp:1537
int GetCell3dFaceCount(int a_cellIdx) const
Get the number of cell faces for given cell.
Definition: XmUGrid.cpp:3541
int GetPointCount() const
Get the number of points.
Definition: XmUGrid.cpp:646
VecInt m_cellDimensionCounts
Cache for cell dimension counts.
Definition: XmUGrid.cpp:230
std::vector< VecInt > VecInt2d
void SetUnmodified()
Resets the modified flag to false.
Definition: XmUGrid.cpp:3072
VecInt GetCellEdgeAdjacentCells(int a_cellIdx, int a_edgeIdx) const
Get the index of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:1423
bool IsFaceSide(const VecInt &a_facePts) const
Get whether the cell face is of a side orientation. Only works for plan view prismatic cells...
Definition: XmUGrid.cpp:2394
bool m_modified
Has UGrid been modified since last SetUnmodified call?
Definition: XmUGrid.cpp:224
void testGetCellEdge()
Test iterating through the edges of cells.
Definition: XmUGrid.cpp:4541
VecInt m_cellIdxToStreamIdx
Indexes for each cell in the cell stream.
Definition: XmUGrid.cpp:219
VecPt3d m_locations
UGrid point locations.
Definition: XmUGrid.cpp:217
Functions dealing with geometry.
std::vector< XmEdge > GetCellEdges(int a_cellIdx) const
Get the Edges of a cell.
Definition: XmUGrid.cpp:1524
bool GetCellCellstream(int a_cellIdx, VecInt &a_cellstream) const
Get cell stream vector for a single cell.
Definition: XmUGrid.cpp:1073
void testCellFunctions()
[snip_test_PointFunctions]
Definition: XmUGrid.cpp:5310
bool IsCellValidWithPointChange(int a_cellIdx, int a_changedPtIdx, const Pt3d &a_newPosition) const
Determine whether a cell is valid after a point is moved.
Definition: XmUGrid.cpp:1190
std::vector< int > GetDimensionCounts() const
Count all number of the cells with each dimenion (0, 1, 2, 3)
Definition: XmUGrid.cpp:3308
VecInt GetPointsAdjacentCells(const VecInt &a_points) const
Gets the common cells from a vector of points.
Definition: XmUGrid.cpp:776
void testCell3dFaceFunctions()
Test various get face functions.
Definition: XmUGrid.cpp:5430
bool GetCellCentroid(int a_cellIdx, Pt3d &a_centroid) const
Get the centroid location of a cell.
Definition: XmUGrid.cpp:1157
std::shared_ptr< XmUGrid > TEST_XmUGridHexagonalPolyhedron()
Builds a 1 cell hexagon with cell type polyhedron.
Definition: XmUGrid.cpp:3740
void testGetExtents()
Test getting the extents of a UGrid.
Definition: XmUGrid.cpp:4253
void GetCellExtents(int a_cellIdx, Pt3d &a_min, Pt3d &a_max) const
Get the extents of the given cell.
Definition: XmUGrid.cpp:3330
bool GetModified() const
Returns the modified flag. Gets set when points or cells get changed.
Definition: XmUGrid.cpp:614
void GetPointAdjacentLocations(int a_pointIdx, VecPt3d &a_edgePoints) const
Given a point gets point locations attached to the point by an edge.
Definition: XmUGrid.cpp:1583
VecInt m_cellFaceOffset
Cache for offset to m_faceOrientation and m_faceNeighbor.
Definition: XmUGrid.cpp:227
int GetCellPointCount(int a_cellIdx) const
Get the number of cell points (including polyhedron).
Definition: XmUGrid.cpp:3258
void GetEdgesOfFace(const VecInt &a_face, std::vector< XmEdge > &a_edges) const
Get the edges of a cell given a face.
Definition: XmUGrid.cpp:1263
void testOperators()
Test constructors and assignment operator.
Definition: XmUGrid.cpp:4018
Impl()=default
Default constructor.
VecInt GetCell3dFacePoints(int a_cellIdx, int a_faceIdx) const
Get the cell face for given cell and face index.
Definition: XmUGrid.cpp:1663
XmUGridFaceOrientation FaceOrientation(int a_cellIdx, int a_faceIdx) const
Find the orientation of a given 3D cell face.
Definition: XmUGrid.cpp:1872
VecInt GetPointAdjacentCells(int a_pointIdx) const
Get the cells that are associated with the specified point.
Definition: XmUGrid.cpp:3181
bool GetCellPlanViewPolygon(int a_cellIdx, VecPt3d &a_polygon) const
Get a plan view polygon of a specified cell.
Definition: XmUGrid.cpp:1137
bool GetModified() const
Returns the modified flag. Gets set when points or cells get changed.
Definition: XmUGrid.cpp:3064
void UpdateCellLinks()
Update internal link from cells to cell stream index.
Definition: XmUGrid.cpp:1898
VecInt m_numberOfFaces
Cache for number of cell faces.
Definition: XmUGrid.cpp:226
void testGetCellCellstream()
Test Getting a cell stream.
Definition: XmUGrid.cpp:4139
VecInt GetCellPoints(int a_cellIdx) const
Get the points of a cell (including polyhedron)
Definition: XmUGrid.cpp:901
void GetCellLocations(int a_cellIdx, VecPt3d &a_cellLocations) const
Get locations of cell points.
Definition: XmUGrid.cpp:3289
static int DimensionFromCellType(XmUGridCellType a_cellType)
Get the dimension given the cell type (0d, 1d, 2d, or 3d).
Definition: XmUGrid.cpp:2067
XmEdge GetCellEdge(int a_cellIdx, int a_edgeIdx) const
Get the points of a cell.
Definition: XmUGrid.cpp:3433
void GetPointAdjacentPoints(int a_pointIdx, VecInt &a_edgePoints) const
Given a point gets point indices attached to the point by an edge.
Definition: XmUGrid.cpp:1550
VecInt m_cellstream
UGrid cell stream.
Definition: XmUGrid.cpp:218
void testGetCell3dFaceAdjacentCell()
[snip_test_GetCell3dFaceAdjacentCell]
Definition: XmUGrid.cpp:4976
int GetNumberOfPolyhedronEdges(int a_cellIdx) const
Get the number of edges for a polyhedron cell.
Definition: XmUGrid.cpp:2214
std::shared_ptr< xms::XmUGrid > TEST_XmUBuildQuadUGrid(int a_rows, int a_cols)
Builds a UGrid of Quads at 1 spacing for rows & cols specified.
Definition: XmUGrid.cpp:3769
Two integer values representing an edge of an XmUGrid. By default has a direction. Can be sorted to have minimum index first.
Definition: XmEdge.h:33
Geometry for an unstructured grid. An XmUGrid is defined as a vector of 3d points and a stream of cel...
Definition: XmUGrid.h:115
void UpdatePointLinks()
Update internal links from points to associated cells.
Definition: XmUGrid.cpp:1944
XmUGridCacheHolder
Constant for when a cached integer item needs to be calculated.
Definition: XmUGrid.cpp:213
#define TS_REQUIRE_NOT_NULL(pointer)
XmUGridFaceOrientation
The orientation of a 3D face must be one of these.
Definition: XmUGrid.h:104
void GetCellLocations(int a_cellIdx, VecPt3d &a_cellLocations) const
Get locations of cell points.
Definition: XmUGrid.cpp:948
std::shared_ptr< xms::XmUGrid > TEST_XmUBuild3DChevronUgrid()
Builds a UGrid with one 3D Chevron polyhedron.
Definition: XmUGrid.cpp:3980
XmUGridFaceOrientation GetCell3dFaceOrientationNoCache(int a_cellIdx, int a_faceIdx) const
Get the orientation of the face of a vertically prismatic cell.
Definition: XmUGrid.cpp:2573
void SetUseCache(bool a_useCache)
Turn on or off use of caching.
Definition: XmUGrid.cpp:637
#define XM_ASSERT(x)
void testCell3dFunctionCaching()
Test caching to speed up a few 3D cell getters.
Definition: XmUGrid.cpp:5604
void GetExtents(Pt3d &a_min, Pt3d &a_max) const
Get extents of all points in UGrid.
Definition: XmUGrid.cpp:3161
void SetLocations(const VecPt3d &a_locations)
Set UGrid points.
Definition: XmUGrid.cpp:3110
XMS Namespace.
Definition: geoms.cpp:34
bool GetCellPlanViewPolygon(int a_cellIdx, VecPt3d &a_polygon) const
Get a plan view polygon of a specified cell.
Definition: XmUGrid.cpp:3401
static bool IsValidCellstream(const VecInt &a_cellstream)
Check a cell stream to make sure it&#39;s valid. Compares cell type against expected number of points...
Definition: XmUGrid.cpp:2947
std::vector< int > GetDimensionCounts() const
Count all number of the cells with each dimension (0, 1, 2, 3)
Definition: XmUGrid.cpp:983
int GetPointAdjacentCellCount(int a_pointIdx) const
Get the number of cells that use a point.
Definition: XmUGrid.cpp:3171
XmUGridFaceOrientation GetCell3dFaceOrientation(int a_cellIdx, int a_faceIdx) const
Get the orientation of the face of a vertically prismatic cell.
Definition: XmUGrid.cpp:1834
XmUGridFaceOrientation VerticalOrientationFromOpposing(int a_cellIdx, int a_faceIdx) const
Find vertical orientation of a given 3D cell face from opposing face.
Definition: XmUGrid.cpp:2704
const VecInt & GetCellstream() const
Get cell stream vector for the entire UGrid. A cellstream is defined as follows: Polyhedrons: Cell ty...
Definition: XmUGrid.cpp:3346
void GetFacePointSegments(const VecInt &a_facePts, int a_columnBegin, int a_columnEnd, VecPt3d &a_segments) const
Get plan view segments of face points.
Definition: XmUGrid.cpp:2654
std::vector< VecPt3d > VecPt3d2d
VecInt GetCellPoints(int a_cellIdx) const
Get the points of a cell (including polyhedron)
Definition: XmUGrid.cpp:3268
static void GetUniqueEdgesFromPolyhedronCellstream(const int *a_start, int &a_length, boost::container::flat_set< XmEdge > &a_cellEdges, int &a_currIdx)
Get the unique edges in a flat set for a given polyhedron.
Definition: XmUGrid.cpp:2316
int GetCell3dFaceCountNoCache(int a_cellIdx) const
Get the number of cell faces for given cell.
Definition: XmUGrid.cpp:2518
bool gmLinesCross(const Pt3d &a_segment1Point1, const Pt3d &a_segment1Point2, const Pt3d &a_segment2Point1, const Pt3d &a_segment2Point2)
Determine whether 2 line segments cross. The segments may touch at the end points.
Definition: geoms.cpp:1013
int GetNumberOfItemsForCell(int a_cellIdx) const
Get number of items given cell. For polyhedron number of items is number of faces. For other cell types it is number of points.
Definition: XmUGrid.cpp:2167
bool GetFaceXySegments(int a_cellIdx, int a_faceIdx, VecPt3d &a_segments) const
Get the Xy locations of Face Points.
Definition: XmUGrid.cpp:2460
bool GetPlanViewPolygon3d(int a_cellIdx, VecPt3d &a_polygon) const
Get a plan view polygon of a specified 3D cell.
Definition: XmUGrid.cpp:2364
XmUGrid()
Constructor.
Definition: XmUGrid.cpp:2895
VecInt GetCell3dFacePoints(int a_cellIdx, int a_faceIdx) const
Get the cell face for given cell and face index.
Definition: XmUGrid.cpp:3562
~XmUGrid()
Destructor.
Definition: XmUGrid.cpp:2920
void ClearCacheValues()
Clear cached so they will be recalculated.
Definition: XmUGrid.cpp:2505
void gmAddToExtents(const Pt3d &a_pt, Pt3d &a_min, Pt3d &a_max)
Compares a_pt to a_min and a_max. If a_pt is less than a_min or greater than a_max, a_min and a_max are updated.
Definition: geoms.cpp:787
void testGetCell3dFaceCount()
[snip_test_GetNumberOfCellFaces]
Definition: XmUGrid.cpp:4318
int GetCell2dEdgeAdjacentCell(int a_cellIdx, int a_edgeIdx) const
Get the index of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:3469
void testEdgeAdjacentCells()
Test retrieving Adjacent Cell.
Definition: XmUGrid.cpp:4849
void testGetCellEdgeAdjacentCells()
[snip_test_GetCellAdjacentCells]
Definition: XmUGrid.cpp:4798
bool GetPlanViewPolygon2d(int a_cellIdx, VecPt3d &a_polygon) const
Get a plan view polygon of a specified 2D cell.
Definition: XmUGrid.cpp:2349
void GetEdgeAdjacentCells(const XmEdge &a_edge, VecInt &a_adjacentCellIdxs) const
Get the indices of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:3479
VecInt m_pointIdxToPointsToCells
Definition: XmUGrid.cpp:222
XmUGridFaceOrientation ConnectedTopOrBottom(int a_cellIdx, int a_faceIdx) const
Determine face orientation by using cell index of connected face. Top face is connected to lower inde...
Definition: XmUGrid.cpp:2773
XmUGridFaceOrientation GetCell3dFaceOrientation(int a_cellIdx, int a_faceIdx) const
Get the orientation of the face of a vertically prismatic cell.
Definition: XmUGrid.cpp:3623
int GetCellPointCount(int a_cellIdx) const
Get the number of cell points (including polyhedron).
Definition: XmUGrid.cpp:864
void testGetCellDimension()
Test getting dimension of single cells and all cells.
Definition: XmUGrid.cpp:4211
void GetPointAdjacentLocations(int a_pointIdx, VecPt3d &a_edgePoints) const
Given a point gets point locations attached to the point by an edge.
Definition: XmUGrid.cpp:3529
void testGetCell3dFaceOrientationConcaveCell()
Test face orientation for concave cell where a triangle from the first two points in the top face to ...
Definition: XmUGrid.cpp:5553
void testPointFunctions()
[snip_test_PointFunctions]
Definition: XmUGrid.cpp:5254
void testLargeUGridLinkSpeed()
Tests creating a large UGrid and checks the time spent.
Definition: XmUGrid.cpp:5668
void testCellEdgeAdjacentCellFunctions()
Test all get adjacent cell functions.
Definition: XmUGrid.cpp:5375
std::vector< edgerecord > VecEdge
Vector of edgerecord.
void SetUnmodified()
Resets the modified flag to false.
Definition: XmUGrid.cpp:621
XmUGridFaceOrientation FaceOrientationWithFail(int a_cellIdx, int a_faceIdx) const
Find the orientation of a given 3D cell face. Check first for side face, then top or bottom based on ...
Definition: XmUGrid.cpp:2678
VecInt2d GetCell3dFacesPoints(int a_cellIdx) const
Get the faces of a cell.
Definition: XmUGrid.cpp:3584
XmUGridFaceOrientation GetOrientationFromArea(int a_cellIdx, int a_faceIdx) const
Determine top or bottom face orientation using area. Since faces are ordered CCW looking in...
Definition: XmUGrid.cpp:2790
int GetCell3dFaceAdjacentCell(int a_cellIdx, int a_faceIdx) const
Get the cell face neighbors for given cell and face index.
Definition: XmUGrid.cpp:3595
void testGetPointsAdjacentCells()
Test retrieving common cells from points.
Definition: XmUGrid.cpp:4653
int GetCell3dFaceAdjacentCellNoCache(int a_cellIdx, int a_faceIdx) const
Get the cell face neighbors for given cell and face index.
Definition: XmUGrid.cpp:2546
XmUGridCellType GetCellType(int a_cellIdx) const
Get the number of cells.
Definition: XmUGrid.cpp:3299
int GetPointCount() const
Get the number of points.
Definition: XmUGrid.cpp:3092
void testGetCell3dFacePointCount()
[snip_test_GetNumberOfCellFaces]
Definition: XmUGrid.cpp:4349
static std::shared_ptr< XmUGrid > New()
Create a new XmUGrid.
Definition: XmUGrid.cpp:2874
VecPt3d GetPointsLocations(const VecInt &a_points) const
Convert a vector of point indices into a vector of point 3d.
Definition: XmUGrid.cpp:3151
const VecPt3d & GetLocations() const
Get vector of UGrid points.
Definition: XmUGrid.cpp:654
bool GetNextFaceColumn(const VecInt &a_facePoints, int a_starti, int &a_columnBegin, int &a_columnEnd) const
Get next vertical column of points with equal x/y values for side face.
Definition: XmUGrid.cpp:2588
void GetPointAdjacentPoints(int a_pointIdx, VecInt &a_edgePoints) const
Given a point gets point indices attached to the point by an edge.
Definition: XmUGrid.cpp:3519
bool SetPointLocation(int a_pointIdx, const Pt3d &a_location)
Set the point.
Definition: XmUGrid.cpp:3131
std::vector< XmEdge > GetCellEdges(int a_cellIdx) const
Get the Edges of a cell.
Definition: XmUGrid.cpp:3499
Pt3d gmComputePolygonCentroid(const VecPt3d &pts)
Computes the plan view centroid of a non-self-intersecting polygon.
Definition: geoms.cpp:908
void SetModified()
Sets the modified flag to true.
Definition: XmUGrid.cpp:628
void CalculateCacheValues() const
Calculate cached values for faster lookup.
Definition: XmUGrid.cpp:2482
void GetEdgeAdjacentCells(const XmEdge &a_edge, VecInt &a_adjacentCellIdxs) const
Get the indices of the adjacent cells (that shares the same cell edge)
Definition: XmUGrid.cpp:1503
VecPt3d GetPointsLocations(const VecInt &a_points) const
Convert a vector of point indices into a vector of point 3d.
Definition: XmUGrid.cpp:712
int GetCellCount() const
Get the number of cells.
Definition: XmUGrid.cpp:852
int GetFirst() const
Get the first index.
Definition: XmEdge.cpp:103
void testGetCellEdgeCount()
Test getting edges of single cells.
Definition: XmUGrid.cpp:4286
int GetCell3dFacePointCount(int a_cellIdx, int a_faceIdx) const
Get the number of face points for a given cell and face.
Definition: XmUGrid.cpp:3551
bool GetCellCellstream(int a_cellIdx, VecInt &a_cellstream) const
Get cell stream vector for a single cell.
Definition: XmUGrid.cpp:3369
void testGetCellPlanViewPolygon()
[snip_test_GetPointAdjacentPoints]
Definition: XmUGrid.cpp:5112
std::vector< Pt3d > VecPt3d
void testIsCellValidWithPointChange()
Test validating a cell for a changed point.
Definition: XmUGrid.cpp:5215