20 #include <boost/utility.hpp>    26 #include <xmsgrid/ugrid/XmEdge.h>    54   explicit CellData(
int a_num3EdgePoints = -999, 
int a_pointIdx = -1)
    68 typedef std::vector<CellData> VecCellData; 
    73   MeBadQuadRemoverImpl(BSHP<XmUGrid> a_ugrid);
    75   virtual BSHP<XmUGrid> RemoveBadQuads(
double a_maxAspect = 0.7) 
override;
    78   bool ReplacePoint(
int a_ptIdx, 
int a_newPtIdx);
    79   void MovePoint(
int a_ptIdx, 
const Pt3d& a_newPoint);
    80   void DeleteCell(
int a_cellIdx);
    81   BSHP<XmUGrid> BuildUGridFromReplacedPoints();
    82   void CollapseFromPoint(
int a_cellIdx, 
int a_pointIdx_w3, 
const VecInt& a_adjCells);
    83   void ComputeCellData(
int a_cellIdx, 
double max_aspect);
    84   bool CanCollapse(
int a_cellIdx, 
int pointIdx_w3, 
VecInt& a_adjCells);
    87   typedef std::pair<int, Pt3d> MovedPoint;       
    88   typedef std::vector<MovedPoint> MovedPointVec; 
   111 BSHP<XmUGrid> BuildUGrid(
const VecPt3d& a_points, 
const VecInt2d& a_faces)
   114   for (
auto& face : a_faces)
   116     if (face.size() == 4)
   118       cells.push_back(XMU_QUAD);
   120       cells.insert(cells.end(), face.begin(), face.end());
   122     else if (face.size() == 3)
   124       cells.push_back(XMU_TRIANGLE);
   126       cells.insert(cells.end(), face.begin(), face.end());
   142 void GetPointIdxsAttachedByEdge(BSHP<XmUGrid> a_ugrid, 
int a_pointIdx, 
VecInt& a_edgePoints)
   145   a_edgePoints.clear();
   146   VecInt associatedCells = a_ugrid->GetPointAdjacentCells(a_pointIdx);
   147   if (associatedCells.size() == 0)
   151   for (
int i = 0; i < associatedCells.size(); ++i)
   153     for (
int j = 0; j < a_ugrid->GetCellEdgeCount(associatedCells[i]); ++j)
   155       XmEdge temp = a_ugrid->GetCellEdge(associatedCells[i], j);
   158         a_edgePoints.push_back(temp.
GetSecond());
   162         a_edgePoints.push_back(temp.
GetFirst());
   166   std::sort(a_edgePoints.begin(), a_edgePoints.end());
   167   auto it = std::unique(a_edgePoints.begin(), a_edgePoints.end());
   168   a_edgePoints.erase(it, a_edgePoints.end());
   178 int GetAdjacentPointCount(BSHP<XmUGrid> a_ugrid, 
int a_pointIdx)
   181   GetPointIdxsAttachedByEdge(a_ugrid, a_pointIdx, adjacentPoints);
   182   bool isBoundary = 
false;
   184   for (
auto adjacentPtIdx : adjacentPoints)
   186     a_ugrid->GetPointsAdjacentCells(a_pointIdx, adjacentPtIdx, adjacentCells);
   187     if (adjacentCells.size() == 1)
   194   int count = (int)adjacentPoints.size();
   195   return isBoundary ? -count : count;
   203 VecInt GetAdjacentPointCounts(BSHP<XmUGrid> a_ugrid)
   205   VecInt counts(a_ugrid->GetPointCount());
   206   int numPoints = a_ugrid->GetPointCount();
   207   for (
int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
   209     counts[pointIdx] = GetAdjacentPointCount(a_ugrid, pointIdx);
   228 MeBadQuadRemoverImpl::MeBadQuadRemoverImpl(BSHP<XmUGrid> a_ugrid)
   233   int cellCount = a_ugrid->GetCellCount();
   242 BSHP<XmUGrid> MeBadQuadRemoverImpl::RemoveBadQuads(
double a_maxAspect)
   244   if (a_maxAspect != 0.0)
   246     a_maxAspect *= a_maxAspect;
   249   int cellCnt = 
m_ugrid->GetCellCount();
   251   for (
int a_cellIdx = 0; a_cellIdx < cellCnt; ++a_cellIdx)
   254     if (cellData.m_num3EdgePoints == -999)
   256       ComputeCellData(a_cellIdx, a_maxAspect);
   263     for (
int a_cellIdx = 0; a_cellIdx < cellCnt; ++a_cellIdx)
   268         if (data.m_num3EdgePoints == 1)
   270           int collapsablePtIdx = data.m_pointIdx;
   272           if (collapsablePtIdx != -1 && CanCollapse(a_cellIdx, collapsablePtIdx, adjCells))
   275             CollapseFromPoint(a_cellIdx, collapsablePtIdx, adjCells);
   281     if (collapseCnt == 0)
   287   BSHP<XmUGrid> newUgrid = BuildUGridFromReplacedPoints();
   297 bool MeBadQuadRemoverImpl::ReplacePoint(
int a_ptIdx, 
int a_newPtIdx)
   301   if (oldIndex == -1 && newIndex == -1)
   313 void MeBadQuadRemoverImpl::MovePoint(
int a_ptIdx, 
const Pt3d& a_newPoint)
   322 void MeBadQuadRemoverImpl::DeleteCell(
int a_cellIdx)
   331 BSHP<XmUGrid> MeBadQuadRemoverImpl::BuildUGridFromReplacedPoints()
   336     oldPoints[movedPoint.first] = movedPoint.second;
   340   int numPoints = (int)
m_ugrid->GetPointCount();
   341   newPoints.reserve(numPoints);
   343   VecInt newPointIdxLookupTable(numPoints, -1);
   346   for (
int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
   350       newPoints.push_back(oldPoints[pointIdx]);
   351       newPointIdxLookupTable[pointIdx] = currPtIdx;
   357   for (
int pointIdx = 0; pointIdx < numPoints; ++pointIdx)
   362       newPointIdxLookupTable[pointIdx] = newPointIdxLookupTable[idx];
   368   int numCells = 
m_ugrid->GetCellCount();
   369   cells.reserve(6 * numCells);
   370   for (
int cellIdx = 0; cellIdx < numCells; ++cellIdx)
   374       int cellType = 
m_ugrid->GetCellType(cellIdx);
   376       cells.push_back(cellType);
   377       cells.push_back(
m_ugrid->GetCellEdgeCount(cellIdx));
   379       for (
auto pointIdx : cellPoints)
   381         cells.push_back(newPointIdxLookupTable[pointIdx]);
   385   BSHP<XmUGrid> newUGrid = XmUGrid::New(newPoints, cells);
   395 void MeBadQuadRemoverImpl::CollapseFromPoint(
int a_cellIdx,
   400   auto it = std::find(pointIdxs.begin(), pointIdxs.end(), a_pointIdx_w3);
   402   int position = int(it - pointIdxs.begin());
   403   int diagonalPtIdx = pointIdxs[(position + 2) % (
int)pointIdxs.size()];
   404   if (ReplacePoint(a_pointIdx_w3, diagonalPtIdx))
   412       double sumWt = (double)(diagonalCnt + vCnt);
   413       double ptWt = double(vCnt) / sumWt;
   414       double diagonalPtWt = double(diagonalCnt) / sumWt;
   415       Pt3d movedPos = diagonalPtWt * points[diagonalPtIdx] + ptWt * points[a_pointIdx_w3];
   416       MovePoint(diagonalPtIdx, movedPos);
   418     DeleteCell(a_cellIdx);
   419     for (
auto adjCell : a_adjCells)
   437 void MeBadQuadRemoverImpl::ComputeCellData(
int a_cellIdx, 
double max_aspect)
   441   int adjPointCnt = (int)points.size();
   443   if (adjPointCnt != 4)
   445     CellData data(-adjPointCnt, -1);
   451   VecBool aspectOk = {
true, 
true, 
true, 
true};
   453   if (max_aspect > 0.0)
   459     bool even = d0 / d1 <= max_aspect;
   460     bool odd = d1 / d0 <= max_aspect;
   461     aspectOk = {even, odd, even, odd};
   467   for (
int i = 0; i < 4; ++i)
   469     int pointIdx = pointIdxs[i];
   471     bool on_boundary = adjPointCnt < 0;
   472     adjPointCnt = abs(adjPointCnt);
   473     if (adjPointCnt == 2 && !on_boundary)
   475       int opposingIdx = pointIdxs[(i + 2) % 4];
   476       Pt3d opposingPt = 
m_ugrid->GetPointLocation(opposingIdx);
   477       int adjCellIdx = 
m_ugrid->GetCell2dEdgeAdjacentCell(a_cellIdx, i);
   479       if (adjPointIdxs.size() == 3)
   489         if (ReplacePoint(opposingIdx, pointIdxs[i]))
   491           MovePoint(pointIdxs[i], opposingPt);
   492           DeleteCell(a_cellIdx);
   498       else if (adjPointIdxs.size() == 4)
   509         auto it = std::find(adjPointIdxs.begin(), adjPointIdxs.end(), pointIdx);
   510         int position = int(it - adjPointIdxs.begin());
   511         int adjOpposingIdx = adjPointIdxs[(position + 2) % (
int)adjPointIdxs.size()];
   513         Pt3d adjOpposingPt = 
m_ugrid->GetPointLocation(adjOpposingIdx);
   516         double d1 = diagonals[(i + 1) & 0x1];
   519           if (ReplacePoint(pointIdxs[i], opposingIdx))
   521             DeleteCell(a_cellIdx);
   530     if (adjPointCnt == 2 && on_boundary)
   539     if (adjPointCnt == 3 && !on_boundary)
   545         pointIdx_w3 = pointIdx;
   554   if (pointIdx_w3 != XM_NONE && threes == 2 &&
   555       (bits == BOOST_BINARY(0101) || bits == BOOST_BINARY(1010)))
   557     VecInt adjCells = 
m_ugrid->GetPointAdjacentCells(pointIdx_w3);
   558     CollapseFromPoint(a_cellIdx, pointIdx_w3, adjCells);
   562   m_cellsData[a_cellIdx] = CellData(threes, pointIdx_w3);
   570 bool MeBadQuadRemoverImpl::CanCollapse(
int a_cellIdx, 
int pointIdx_w3, 
VecInt& a_adjCells)
   573   bool on_boundary = adjPointCnt < 0;
   579   adjPointCnt = std::abs(adjPointCnt);
   580   XM_ASSERT(adjPointCnt == 3 && !on_boundary);
   582   a_adjCells = 
m_ugrid->GetPointAdjacentCells(pointIdx_w3);
   583   for (
auto adjCell : a_adjCells)
   585     if (adjCell != a_cellIdx)
   588       int fd0 = fd.m_num3EdgePoints;
   589       if (fd0 < 0 || fd0 > 1)
   610 BSHP<MeBadQuadRemover> MeBadQuadRemover::New(BSHP<XmUGrid> a_ugrid)
   612   BSHP<MeBadQuadRemover> badQuadRemover(
new MeBadQuadRemoverImpl(a_ugrid));
   613   return badQuadRemover;
   659   VecInt counts = GetAdjacentPointCounts(grid);
   660   VecInt expectedCounts = {-2, -3, -2, -3, 4, -3, -2, -3, -2};
   677       {0, 0, 0},   {10, 0, 0},  {20, 0, 0},  {30, 0, 0}, {30, 20, 0}, {0, 10, 0},  {10, 10, 0},
   678       {15, 10, 0}, {25, 10, 0}, {30, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}, {5, 3, 0},
   680     VecInt cells = {XMU_QUAD, 4, 0, 1, 6,  13, XMU_QUAD, 4, 0, 13, 6,  5,
   681                     XMU_QUAD, 4, 1, 2, 7,  6,  XMU_QUAD, 4, 2, 3,  9,  8,
   682                     XMU_QUAD, 4, 5, 6, 11, 10, XMU_QUAD, 4, 6, 7,  12, 11,
   683                     XMU_QUAD, 4, 2, 8, 12, 7,  XMU_QUAD, 4, 8, 9,  4,  12};
   686     MeBadQuadRemoverImpl replacer(ugrid);
   688     replacer.MovePoint(8, {20, 10, 0});
   690     TS_ASSERT(replacer.ReplacePoint(7, 8));
   691     replacer.DeleteCell(6);
   692     TS_ASSERT(replacer.ReplacePoint(13, 1));
   693     replacer.DeleteCell(0);
   695     VecPt3d expectPoints = {{0, 0, 0},   {10, 0, 0}, {20, 0, 0},  {30, 0, 0},
   696                             {30, 20, 0}, {0, 10, 0}, {10, 10, 0}, {20, 10, 0},
   697                             {30, 10, 0}, {0, 20, 0}, {10, 20, 0}, {20, 20, 0}};
   699     BSHP<XmUGrid> newUGrid = replacer.BuildUGridFromReplacedPoints();
   706                           XMU_QUAD, 4, 0, 1, 6, 5, XMU_QUAD, 4, 1, 2, 7, 6, XMU_QUAD, 4, 2, 3, 8, 7,
   707                           XMU_QUAD, 4, 5, 6, 10, 9, XMU_QUAD, 4, 6, 7, 11, 10,
   709                           XMU_QUAD, 4, 7, 8, 4, 11};
   726     TS_ASSERT_EQUALS(expectCells, newUGrid->GetCellstream());
   776   VecInt2d faces = {{10, 20, 30, 0},  {30, 11, 1, 0},   {35, 12, 2, 1},   {11, 12, 35, 1},
   777                     {12, 13, 3, 2},   {31, 14, 4, 3},   {14, 15, 5, 4},   {15, 16, 6, 5},
   778                     {16, 17, 7, 6},   {17, 18, 8, 7},   {32, 33, 9, 8},   {20, 21, 11, 30},
   779                     {36, 22, 12, 11}, {21, 22, 36, 11}, {22, 23, 13, 12}, {13, 23, 31, 3},
   780                     {23, 24, 14, 31}, {24, 25, 15, 14}, {25, 26, 16, 15}, {26, 27, 17, 16},
   781                     {27, 28, 18, 17}, {18, 28, 32, 8},  {28, 29, 34, 32}, {34, 19, 33, 32},
   782                     {33, 19, 37, 9},  {34, 29, 37, 19}, {40, 41, 28, 27}, {41, 42, 39, 28},
   783                     {42, 43, 38, 39}, {38, 43, 40, 27}, {43, 42, 41, 40}};
   834   BSHP<XmUGrid> ugridIn = BuildUGrid(points, faces);
   836   BSHP<XmUGrid> collapsedUGrid = remover->RemoveBadQuads(0.7);
   882   VecPt3d actualPoints = collapsedUGrid->GetLocations();
   886     9, 4, 10, 11, 1,  0,  9, 4, 32, 12, 2,  1,  9, 4, 11, 12, 32, 1,  9, 4, 12, 13, 3,  2,
   887     9, 4, 13, 14, 4,  3,  9, 4, 14, 15, 5,  4,  9, 4, 15, 16, 6,  5,  9, 4, 16, 17, 7,  6,
   888     9, 4, 17, 29, 8,  7,  9, 4, 29, 30, 9,  8,  9, 4, 19, 20, 11, 10, 9, 4, 20, 21, 12, 11,
   889     9, 4, 21, 22, 13, 12, 9, 4, 22, 23, 14, 13, 9, 4, 23, 24, 15, 14, 9, 4, 24, 25, 16, 15,
   890     9, 4, 25, 26, 17, 16, 9, 4, 26, 27, 29, 17, 9, 4, 27, 28, 31, 29, 9, 4, 31, 18, 30, 29,
   891     9, 4, 30, 18, 33, 9,  9, 4, 31, 28, 33, 18, 9, 4, 36, 37, 27, 26, 9, 4, 37, 38, 35, 27,
   892     9, 4, 38, 39, 34, 35, 9, 4, 34, 39, 36, 26, 9, 4, 39, 38, 37, 36};
   893   VecInt actualCells = collapsedUGrid->GetCellstream();
   894   TS_ASSERT_EQUALS(expectedCells, actualCells);
   902   VecInt2d faces = {{0, 2, 1, 3}, {0, 1, 2}};
   911   BSHP<XmUGrid> ugridIn = BuildUGrid(points, faces);
   913   BSHP<XmUGrid> collapsedUGrid = remover->RemoveBadQuads(0.7);
   914   VecPt3d expectedPoints = {{-10, 0, 0}, {10, 0, 0}, {0, 20, 0}};
   916   VecPt3d actualPoints = collapsedUGrid->GetLocations();
   919   VecInt expectedCells = {XMU_TRIANGLE, 3, 0, 1, 2};
   921   VecInt actualCells = collapsedUGrid->GetCellstream();
   922   TS_ASSERT_EQUALS(expectedCells, actualCells);
 DynBitset m_cellsToDelete
True if a cell is to be deleted. 
 
void testCollapseQuadTri()
Test simple mesh with one quad and one triangle that share two adjacent edges. Expected to result in ...
 
std::vector< int > VecInt
 
std::vector< bool > VecBool
 
std::vector< double > VecDbl
 
BSHP< XmUGrid > m_ugrid
The input UGrid containing the bad quads. 
 
double gmXyDistanceSquared(const Pt3d &pt1, const Pt3d &pt2)
 
VecCellData m_cellsData
Vector of potentially collapsable quads. 
 
static BSHP< XmUGrid > New()
 
static BSHP< MeBadQuadRemover > New(BSHP< XmUGrid > a_ugrid)
Create new MeBadQuadRemover. 
 
BSHP< XmUGrid > TEST_XmUGridSimpleQuad()
 
boost::dynamic_bitset< size_t > DynBitset
 
std::vector< VecInt > VecInt2d
 
void testReplacePoints()
Test ReplacePoint and BuildUGridFromReplacedPoints. 
 
const VecInt m_adjPointCnts
 
MeBadQuadRemover()
Constructor. 
 
MovedPointVec m_movedPoints
List of points moved with new location. 
 
VecInt m_pointIdxMap
A mapping of original index to new point index. 
 
void testGetAdjacentPointCounts()
Test GetAdjacentPointCounts. 
 
void testCollapse()
Testing quad removal on a more complex quad UGrid. The original mesh has two rows of quads with some ...
 
virtual ~MeBadQuadRemover()
Destructor. 
 
std::vector< Pt3d > VecPt3d