71 virtual bool MeshIt(
int a_polyId,
73 const VecInt& a_polyCorners,
80 const Pt3d& a_topLeft);
162 const VecInt& a_polyCorners,
169 size_t nCorner = a_polyCorners.size();
172 for (
size_t i = 1; same && i < a_polyCorners.size(); ++i)
174 if (a_polyCorners[i] != a_polyCorners[0])
180 if (2 == nCorner || 3 == nCorner)
184 std::string msg =
"Polygon corners incorrectly specified. Aborting patch mesh generation.";
203 const Pt3d& a_topLeft)
205 int polyCornerIdx(0);
206 double dist =
MdistSq(a_oPoly[0].x, a_oPoly[0].y, a_topLeft.
x, a_topLeft.
y);
207 for (
size_t i = 0; i < a_idx.size(); ++i)
210 double d1 =
MdistSq(a_oPoly[q].x, a_oPoly[q].y, a_topLeft.
x, a_topLeft.
y);
214 polyCornerIdx = (int)i;
217 return polyCornerIdx;
247 idx.insert(idx.end(), a_polyCorners.begin(), a_polyCorners.end());
254 idx.push_back((
int)pts.size());
255 pts.push_back(pts.front());
257 tmpPts.assign(idx.size() - 1,
VecPt3d());
258 for (
size_t i = 1; i < idx.size(); ++i)
260 for (
int j = idx[i - 1]; j <= idx[i]; ++j)
262 tmpPts[i - 1].push_back(pts[j]);
266 int ix[4][4] = {{3, 2, 1, 0}, {0, 3, 2, 1}, {1, 0, 3, 2}, {2, 1, 0, 3}};
268 m_pts[0].swap(tmpPts[
ix[polyCornerIdx][0]]);
269 m_pts[1].swap(tmpPts[
ix[polyCornerIdx][1]]);
270 m_pts[2].swap(tmpPts[
ix[polyCornerIdx][2]]);
271 m_pts[3].swap(tmpPts[
ix[polyCornerIdx][3]]);
272 std::reverse(
m_pts[0].begin(),
m_pts[0].end());
273 std::reverse(
m_pts[1].begin(),
m_pts[1].end());
306 for (
size_t i = 0; i <
m_pts.size(); ++i)
307 np[i] = (
int)
m_pts[i].size();
311 if ((np[2] - np[0] == 0) && (np[3] - np[1] != 0))
331 std::reverse(
m_pts[1].begin(),
m_pts[1].end());
332 std::reverse(
m_pts[3].begin(),
m_pts[3].end());
342 std::reverse(
m_pts[0].begin(),
m_pts[0].end());
343 std::reverse(
m_pts[2].begin(),
m_pts[2].end());
346 if ((np[1] - np[3]) > (np[2] - np[0]))
373 c.reserve(a_polyCorners.size() + 1);
375 for (
size_t i = 0; i < a_polyCorners.size(); ++i)
376 c.push_back(a_polyCorners[i]);
379 p0 = a_outPoly.back();
380 p1 = a_outPoly.front();
385 for (
size_t i = 1; i < c.size() && !err; ++i)
387 if (c[i] == c[i - 1])
391 std::string msg =
"Invalid corner detected in polygon. Aborting patch.";
396 p0 = a_outPoly[c[i] - 1];
397 p1 = a_outPoly[c[i]];
398 if (c[i] + 1 < (
int)a_outPoly.size())
399 p2 = a_outPoly[c[i] + 1];
409 std::string msg =
"Non-convex corner detected in polygon. Aborting patch.";
493 int changes = a_nodesincol.back() - a_nodesincol[0];
499 for (
size_t i = 1; i < a_nodesincol.size() - 1; ++i)
501 if (a_nodesincol[i] > a_nodesincol[i - 1])
503 if (a_nodesincol[i] & 1)
505 if (!(a_nodesincol[i - 1] & 1))
513 if (a_nodesincol[0] % 2 && a_nodesincol.back() % 2)
515 for (
size_t i = 1; i < a_nodesincol.size() - 1; ++i)
517 if (a_nodesincol[i] < a_nodesincol.back() && a_nodesincol[i] % 2 == 0)
522 else if (changes < -1)
524 std::string msg =
"Error in polygon to patch algorithm.";
531 for (
size_t i = 1; i < a_nodesincol.size() - 1; ++i)
532 a_nodesincol[i] =
Mmax(a_nodesincol[i], 2);
544 XM_ENSURE_TRUE(a_np <= (
int)a_pts.size() && a_np <= (int)a_pcnts.size());
545 double len(0), delta(0);
548 for (
int i = 1; i < a_np; ++i)
549 len +=
Mdist(a_pts[i].x, a_pts[i].y, a_pts[i - 1].x, a_pts[i - 1].y);
551 a_pcnts[a_np - 1] = 1.0;
553 for (
int i = 1; i < a_np - 1; ++i)
555 delta +=
Mdist(a_pts[i].x, a_pts[i].y, a_pts[i - 1].x, a_pts[i - 1].y);
558 a_pcnts[i] = (double)i / (
double)(a_pts.size() - 1);
560 a_pcnts[i] = delta / len;
578 VecDbl pcnt_new(a_np_new, 0);
580 if (1 == a_pts.size())
582 for (
size_t i = 0; i < pcnt_new.size() && i < a_ptsNew.size(); ++i)
584 a_ptsNew[i] = a_pts[0];
591 for (
size_t i = 0, j = 0; i < pcnt_new.size(); i++)
593 while (j < (a_pts.size() - 1) && a_pcnt[j + 1] <= pcnt_new[i])
596 if (j == (a_pts.size() - 1))
597 a_ptsNew[i] = a_pts[j];
600 a_ptsNew[i].x = a_pts[j].x + (pcnt_new[i] - a_pcnt[j]) * (a_pts[j + 1].x - a_pts[j].x) /
601 (a_pcnt[j + 1] - a_pcnt[j]);
602 a_ptsNew[i].y = a_pts[j].y + (pcnt_new[i] - a_pcnt[j]) * (a_pts[j + 1].y - a_pts[j].y) /
603 (a_pcnt[j + 1] - a_pcnt[j]);
604 a_ptsNew[i].z = a_pts[j].z + (pcnt_new[i] - a_pcnt[j]) * (a_pts[j + 1].z - a_pts[j].z) /
605 (a_pcnt[j + 1] - a_pcnt[j]);
635 VecDbl x_in(a_pcnt_in.size(), 0);
636 for (
size_t i = 1; i < x_in.size() - 1; ++i)
638 x_in[i] = (double)i / (x_in.size() - 1);
642 VecDbl x_out(a_pcnt_out.size(), 0);
643 for (
size_t i = 1; i < x_out.size() - 1; ++i)
645 x_out[i] = (double)i / (x_out.size() - 1);
652 a_pcnt_out.front() = x_out.front();
653 a_pcnt_out.back() = x_out.back();
655 for (
size_t i = 1, j = 0; i < a_pcnt_out.size() - 1; ++i)
657 while (j < a_pcnt_in.size() - 1 && x_in[j + 1] <= x_out[i])
660 a_pcnt_out[i] = a_pcnt_in[j] + (x_out[i] - x_in[j]) * (a_pcnt_in[j + 1] - a_pcnt_in[j]) /
661 (x_in[j + 1] - x_in[j]);
733 size_t m0(
m_pts[3].size());
739 newcol[0] =
m_pts[3][(int)((
double)j / (
m_np_side - 1) * (m0 - 1) + 0.5)];
747 if (idx1 > 0 && idx1 < (
int)
m_meshPts->size())
750 if (idx2 > 0 && idx2 < (
int)
m_meshPts->size())
759 Mdist(newcol[i].x, newcol[i].y, newcol[i - 1].x, newcol[i - 1].y) <
XM_ZERO_TOL)
796 for (
int i = 1; i < np - 1; ++i)
798 double u_pcnt = (double)a_j / (np_side - 1);
799 int row = (int)((
double)i / (np - 1) * (
m_np_end - 1) + 0.5);
800 int col = (int)(u_pcnt * (
m_nodesinrow[row] - 1) + 0.5);
802 for (
int i_test = i; row > 0 && i_test == i;)
804 i_test = (int)((
double)(row - 1) / (
m_np_end - 1) * (np - 1) + 0.5);
814 a_newcol[i].x = a_newcol[i].y = a_newcol[i].z = -1234.5;
826 int j_test, col_test;
827 for (j_test = a_j, col_test = col; j_test > 1 && col_test == col;)
851 u_pcnt = (double)j_min / (
double)(
m_nodesinrow[i_test] - 1);
852 double v_pcnt = (double)i_test / (
double)(
m_nodesincol[j_test] - 1);
856 double u2 = 1.0 - u1;
859 double v2 = 1.0 - v1;
862 v2 * a_newcol[0].x + v1 * a_newcol[np - 1].x -
863 u2 * (v2 * c[0].
x + v1 * c[1].
x) - u1 * (v2 * c[2].x + v1 * c[3].x);
865 v2 * a_newcol[0].y + v1 * a_newcol[np - 1].y -
866 u2 * (v2 * c[0].
y + v1 * c[1].
y) - u1 * (v2 * c[2].y + v1 * c[3].y);
868 v2 * a_newcol[0].z + v1 * a_newcol[np - 1].z -
869 u2 * (v2 * c[0].
z + v1 * c[1].
z) - u1 * (v2 * c[2].z + v1 * c[3].z);
881 const int VTK_QUAD(9);
882 const int VTK_TRI(5);
897 int i(0), index1(0), index2(0);
906 index2 = (int)(fval * (
m_nodesincol[j - 1] - 1) + 0.51);
908 index2 = (int)(fval * (
m_nodesincol[j - 1] - 1) + 0.49);
910 index2 =
Mmin(index2, index1 + 1);
917 if ((node1a == node1b && node2a == node2b) || (node1a == node2a && node1b == node2b) ||
918 (node1a == node1b && node1a == node2a) || (node1b == node1a && node1b == node2b) ||
919 (node2b == node1b && node2b == node2a) || (node2a == node1a && node2a == node2b))
924 int x[4] = {node1a, node1b, node2b, node2a};
925 VecInt n_ccw(&x[0], &x[4]);
928 for (
int i = 0; i < 4; ++i)
931 pts[i] = (*m_meshPts)[n_ccw[i]];
934 node1a = n_ccw[idxs[0]];
935 node1b = n_ccw[idxs[1]];
936 node2b = n_ccw[idxs[2]];
937 node2a = n_ccw[idxs[3]];
939 if (node1a != node1b && node2a != node2b && node1a != node2a && node1b != node2b)
952 if (node1a == node1b)
957 else if (node2a == node2b)
962 else if (node1a == node2a)
974 for (
int i = 0; i < 3; ++i)
1002 cellFlags.resize(nCell,
false);
1004 for (
int i = 0; !err && i < nCell; ++i)
1023 VecInt cellPtIdx, adjCellIdx;
1028 for (
size_t i = 0; i < cellPtIdx.size(); ++i)
1030 cellPoints.push_back(mp[cellPtIdx[i]]);
1031 cellCenter += cellPoints.back();
1033 cellCenter /= cellPoints.size();
1037 cellPtIdx.push_back(cellPtIdx.front());
1039 for (
size_t i = 1; i < cellPtIdx.size(); ++i)
1041 int i0(cellPtIdx[i - 1]), i1(cellPtIdx[i]);
1042 const Pt3d &p0(mp[i0]), &p1(mp[i1]);
1044 for (
auto v : adjPtIdx)
1047 if (a_cellFlags[adjCellIdx[cnt]])
1051 for (
size_t j = 0; j < v.size(); ++j)
1053 adjacentPoints.push_back(mp[v[j]]);
1054 adjCellCenter += adjacentPoints.back();
1056 adjCellCenter /= adjacentPoints.size();
1058 bool overlap(
false);
1062 std::string msg =
"Invalid patch. Centroid of base cell inside of adjacent cell.";
1071 std::string msg =
"Invalid patch. Centroid of adjacent cell inside of base cell.";
1079 v.push_back(v.front());
1080 for (
size_t j = 1; !overlap && j < v.size(); ++j)
1082 int j0(v[j - 1]), j1(v[j]);
1084 if (i0 == j0 || i0 == j1 || i1 == j0 || i1 == j1)
1087 const Pt3d &p2(mp[j0]), &p3(mp[j1]);
1090 std::string msg =
"Invalid patch. Edges of adjacent cells overlap.";
1098 a_cellFlags[a_cellIdx] =
true;
1111 m_cellIdx.push_back(static_cast<int>(i));
1128 for (
size_t i = 0, c = 0; i <
m_meshCells.size(); ++i, ++c)
1161 std::set<int> adjCells;
1162 adjCells.insert(a_cellIdx);
1164 a_adjCellIdx.resize(0);
1165 for (
size_t i = 0; i < a_ptIdxs.size(); ++i)
1167 const int& px = a_ptIdxs[i];
1173 if (adjCells.find(cx1) != adjCells.end())
1175 adjCells.insert(cx1);
1176 a_adjPts.push_back(
VecInt());
1177 a_adjCellIdx.push_back(cx1);
1182 a_adjPts.back().push_back(pt);
1216 using namespace xms;
1217 pts = {{0, 0, 0}, {0, 10, 0}, {0, 20, 0}, {0, 30, 0}, {10, 30, 0}, {20, 30, 0},
1218 {30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 0, 0}, {20, 0, 0}, {10, 0, 0}};
1220 xms::VecInt corner = {3, 6, 9};
1223 TS_ASSERT_EQUALS(4, p.
m_pts.size());
1224 if (4 != p.
m_pts.size())
1226 xms::VecPt3d2d basePts(4);
1228 using namespace xms;
1229 basePts[0] = {{0, 30, 0}, {0, 20, 0}, {0, 10, 0}, {0, 0, 0}};
1230 basePts[1] = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {30, 0, 0}};
1231 basePts[2] = {{30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 0, 0}};
1232 basePts[3] = {{0, 30, 0}, {10, 30, 0}, {20, 30, 0}, {30, 30, 0}};
1241 using namespace xms;
1242 pts = {{0, 30, 0}, {10, 30, 0}, {20, 30, 0}, {30, 30, 0}, {30, 20, 0}, {30, 10, 0},
1243 {30, 0, 0}, {20, 0, 0}, {10, 0, 0}, {0, 0, 0}, {0, 10, 0}, {0, 20, 0}};
1246 TS_ASSERT_EQUALS(4, p.
m_pts.size());
1247 if (4 != p.
m_pts.size())
1250 using namespace xms;
1251 basePts[0] = {{0, 30, 0}, {0, 20, 0}, {0, 10, 0}, {0, 0, 0}};
1252 basePts[1] = {{0, 0, 0}, {10, 0, 0}, {20, 0, 0}, {30, 0, 0}};
1253 basePts[2] = {{30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 00, 0}};
1254 basePts[3] = {{0, 30, 0}, {10, 30, 0}, {20, 30, 0}, {30, 30, 0}};
1268 using namespace xms;
1269 pts = {{0, 0, 0}, {0, 70, 0}, {0, 100, 0}, {35, 100, 0}, {100, 100, 0},
1270 {100, 70, 0}, {100, 35, 0}, {100, 0, 0}, {70, 0, 0}, {35, 0, 0}};
1272 xms::VecInt corner = {2, 4, 7};
1275 TS_ASSERT_EQUALS(4, p.
m_pts.size());
1276 if (4 != p.
m_pts.size())
1278 xms::VecPt3d2d basePts(4);
1280 using namespace xms;
1281 basePts[0] = {{0, 100, 0}, {0, 70, 0}, {0, 0, 0}};
1282 basePts[1] = {{0, 0, 0}, {35, 0, 0}, {70, 0, 0}, {100, 0, 0}};
1283 basePts[2] = {{100, 100, 0}, {100, 70, 0}, {100, 35, 0}, {100, 0, 0}};
1284 basePts[3] = {{0, 100, 0}, {35, 100, 0}, {100, 100, 0}};
1298 using namespace xms;
1299 pts = {{0, 0, 0}, {0, 10, 0}, {0, 20, 0}, {0, 30, 0}, {10, 30, 0}, {20, 30, 0},
1300 {30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 0, 0}, {20, 0, 0}, {10, 0, 0}};
1302 xms::VecInt corner = {3, 6, 9};
1306 p.
MeshIt(-1, pts, corner, 1e-9, mPts, mCells);
1315 using namespace xms;
1316 pts = {{1, 1, 0}, {0, 1, 0}, {0, 10, 0}, {0, 20, 0}, {0, 30, 0}, {10, 30, 0}, {20, 30, 0},
1317 {30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 0, 0}, {20, 0, 0}, {10, 0, 0}, {1, 0, 0}};
1319 xms::VecInt corner = {4, 7, 10};
1327 using namespace xms;
1328 pts = {{0, 0, 0}, {0, 10, 0}, {0, 20, 0}, {0, 29, 0}, {0, 30, 0}, {10, 30, 0}, {20, 30, 0},
1329 {30, 30, 0}, {30, 20, 0}, {30, 10, 0}, {30, 0, 0}, {20, 0, 0}, {10, 0, 0}};
1331 corner = {3, 7, 10};
1342 xms::VecPt3d pts = {{-15, 38}, {17, 47}, {52, 50}, {95, 40},
1343 {92, 27}, {51, 35}, {18, 33}, {-12, 26}};
1344 xms::VecInt corner = {3, 4, 7};
1348 TS_ASSERT_EQUALS(
true, p.
MeshIt(-1, pts, corner, 1e-9, mpts, mcells));
1349 xms::VecPt3d basePts = {{-15, 38}, {-12, 26}, {95, 40}, {92, 27},
1350 {17, 47}, {18, 33}, {52, 50}, {51, 35}};
1352 xms::VecInt baseCells = {9, 4, 0, 1, 5, 4, 9, 4, 4, 5, 7, 6, 9, 4, 6, 7, 3, 2};
int m_polyId
id of the polygon
int m_np_side
variable refactored out of patch code
void GenerateMeshCells()
Creates the mesh cells and puts the mesh pts into 1 vector.
std::vector< int > VecInt
VecInt m_nodesincol
number of nodes in a column
void gmEnvelopeOfPts(const VecPt3d &a_pts, Pt3d &a_min, Pt3d &a_max)
int m_m1
variable refactored out of patch code
VecInt m_meshCells
generated mesh cells
Utilities related to a VTK unstructured grid (from shared1\UGridUtils.cpp)
virtual bool MeshIt(int a_polyId, const VecPt3d &a_outPoly, const VecInt &a_polyCorners, double a_xytol, VecPt3d &a_points, VecInt &a_cells) override
Perform MESH_PATCH meshing on a polygon. Return the mesh points through a_points and a_cells (mix of ...
friend MePolyPatcherUnitTests
tests the class
bool QuadPatchErrors(const VecPt3d &a_outPoly, const VecInt &a_polyCorners)
Checks the polygon to make sure that each side of the polygon has the same number of segments...
static BSHP< MePolyPatcher > New()
Creates a new instance of this class.
std::vector< double > VecDbl
int m_dm
variable refactored out of patch code
double gmAngleBetweenEdges(const Pt3d &p1, const Pt3d &p2, const Pt3d &p3)
VecInt m_nodesinrow
number of nodes in a row
bool AdjustNodesInCol3a(VecInt &a_nodesincol, int flag)
performs adjustments to the nodes to make the correct desired transitions from column to column...
VecPt3d2d m_end2pts
1 side of polygon points
VecDbl2d m_newend1pcnt
percentage of node location along side
VecPt3d2d m_side1pts
1 side of polygon points
BSHP< VecPt3d > m_meshPts
generated mesh nodes
void testQuadPatchErrors()
tests error detection in polygon for quad patch
VecDbl m_side1pcnt
percentage of node location along side
void testCreateClass()
test creating the class
VecDbl2d m_newside1pcnt
percentage of node location along side
void testPolyPtsToSides1()
tests converting the polygon definition into the "side" definition
void testPatch00()
test patch generation of a square with equal side spacing
int gmPointInPolygon2D(const T *a_verts, const size_t a_num, const double a_x, const double a_y, const double a_tol)
VecPt3d2d m_pts
polygon points divided into 4 sides
VecInt2d m_nodeIdx
index to m_meshPts identifying mesh nodes
double m_xytol
tolerance for geometry comparison
VecDbl m_end1pcnt
percentage of node location along side
VecDbl m_end2pcnt
percentage of node location along side
boost::dynamic_bitset< size_t > DynBitset
std::vector< VecInt > VecInt2d
void QuadPatch(const VecPt3d &a_outPoly, const VecInt &a_polyCorners)
Creates mesh cells using the patch algorithm for triangles.
void meModifyMessageWithPolygonId(int a_polyId, std::string &a_msg)
Prepends the polygon id as part of an error messge.
bool gmLinesIntersect(const Pt3d &one1, const Pt3d &one2, const Pt3d &two1, const Pt3d &two2)
bool SetupSideInfo()
Set up some variables based on the points being setup.
VecInt m_ptCellCnt
number of cells connected to each point
void CalcPointPercentages()
Calculates percentages that are used to determine the locations of the mesh points.
void ValidateMeshCells()
Ensures that the generated mesh cells are valid (no ill formed cells)
void PolyPtsToSides(const VecPt3d &a_outPoly, const VecInt &a_polyCorners)
puts the polygon points in the
VecPt3d2d m_side2pts
1 side of polygon points
int m_np_end
variable refactored out of patch code
double MdistSq(_T x1, _U y1, _V x2, _W y2)
int m_n0
variable refactored out of patch code
VecInt m_ptCellIdx
index into cell adjacency array for each point
#define XM_ENSURE_TRUE(...)
int m_n1
variable refactored out of patch code
void InterpolatePercentages(const VecDbl &a_pcnt_in, VecDbl &a_pcnt_out)
gets the new percentages, interpolated from old percentages
VecDbl2d m_newend2pcnt
percentage of node location along side
BSHP< GmPtSearch > m_ptSearch
spatial index for searching points
void testPolyPtsToSides()
tests converting the polygon definition into the "side" definition
void CreateCellAdjacencyInfo()
Creates arrays with cell adjacency information.
std::vector< VecPt3d > VecPt3d2d
Generates a mesh with triangle/quad cells using the patch method.
VecDbl m_side2pcnt
percentage of node location along side
void gmOrderPointsCounterclockwise(const VecPt3d &a_pts, VecInt &a_ccwOrder, int a_startindex)
std::vector< VecDbl > VecDbl2d
VecInt m_cellIdx
location of each cell in m_meshCells
void OrderPoints()
checks that the points are ordered in the expected order
double Mdist(_T x1, _U y1, _V x2, _W y2)
VecInt m_ptAdjCells
adjacent cells for each point
void testBug9226()
tests for bug report 9226
VecDbl2d m_newside2pcnt
percentage of node location along side
Generates an adaptive patch mesh from a polygon.
int m_m0
variable refactored out of patch code
int m_dn
variable refactored out of patch code
void GetCellPtInfo(int a_cellIdx, VecInt &a_ptIdxs, VecInt &a_adjCellIdx, VecInt2d &a_adjPts)
Gets the points that make up the cell and points from adjacent cells.
VecPt3d2d m_end1pts
1 side of polygon points
void PointsFromPercentages(const VecPt3d &a_pts, const VecDbl &a_pcnts, int a_np_new, VecPt3d &a_ptsNew)
reinterpolates the array of points a_pts to a new array of points a_ptsNew. The interpolation is perf...
void SetUpColumnForRectPatch3a(int a_j, VecPt3d &a_newcol)
initialize an array of nodes for a column of patch nodes
void GetPercentages(int a_np, const VecPt3d &a_pts, VecDbl &pcnts)
returns the real percentage for each point across the line.
void GenerateMeshPts()
Creates the mesh pts.
VecInt m_ptIdxToRemove
mesh nodes that will be removed
bool CellOverlapsAdj(int a_cellIdx, DynBitset &a_cellFlags)
Checks to see if the cells overlaps with any adjacent cells.
std::vector< Pt3d > VecPt3d
size_t PolyCornerClosestToTopLeft(const VecPt3d &a_oPoly, const VecInt &a_idx, const Pt3d &a_topLeft)
puts the polygon points in the