56   enum RelaxTypeEnum { RELAXTYPE_AREA, RELAXTYPE_ANGLE, RELAXTYPE_SPRING };
    67                      const VecInt& a_fixedPoints,
    68                      BSHP<TrTin> a_tin) 
override;
   105 MeRelaxerImpl::MeRelaxerImpl()
   108 , m_fixedPoints(nullptr)
   112 , m_relaxType(RELAXTYPE_AREA)
   121 MeRelaxerImpl::~MeRelaxerImpl()
   135                           const VecInt& a_fixedPoints,
   149   for (
size_t i = 0; i < a_fixedPoints.size(); ++i)
   161   int numiterations(3); 
   163   if (relaxtype == RELAXTYPE_SPRING)
   168         "No size function specified with spring relaxation "   169         "method. Relaxation method has been set to AREA "   172       relaxtype = RELAXTYPE_AREA;
   190   for (
int i = 0; i < numiterations; ++i)
   197       m_tin->Triangles().clear();
   198       m_tin->TrisAdjToPts().clear();
   204         pts[idx] = pts.back();
   206         szs[idx] = szs.back();
   214     bool trianglesChanged(
false);
   215     trianglesChanged = 
m_tin->OptimizeTriangulation();
   217     if (trianglesChanged && RELAXTYPE_SPRING == relaxtype)
   234   if (type == 
"spring_relaxation")
   246   size_t numTri = 
m_tin->NumTriangles();
   248   for (
size_t t = 0; t < numTri; ++t)
   263   XM_ASSERT(a_iteration > 0 && a_numiterations > 0 && a_iteration <= a_numiterations);
   267   size_t nPoints = points.size();
   268   Pt3d origlocation, newlocation;
   269   for (
size_t p = 0; p < nPoints; ++p)
   273       origlocation = points[p];
   280       case RELAXTYPE_ANGLE:
   283       case RELAXTYPE_SPRING:
   291       newlocation.
z = origlocation.
z;
   296         points[p] = newlocation;
   304       else if (RELAXTYPE_SPRING == a_relaxType)
   321   double sumx(0.0), sumy(0.0), area, sumarea(0.0);
   322   const VecInt& adjTris = 
m_tin->TrisAdjToPts()[a_point];
   323   for (
size_t i = 0; i < adjTris.size(); ++i)
   325     area = 
m_tin->TriangleArea(adjTris[i]);
   331   a_newLocation.
x = sumx / sumarea;
   332   a_newLocation.
y = sumy / sumarea;
   343   double targetangle, mag, a, c, d;
   344   double da, db, dx, dy, sx, sy, radius;
   345   Pt2d sum, pt, p1, p2, p3, centroid;
   349   const VecInt& adjTris = 
m_tin->TrisAdjToPts()[a_point];
   351   size_t num = adjTris.size();
   354   targetangle = 2.0 * 
XM_PI / (double)num;
   359   for (
size_t i = 0; i < adjTris.size(); ++i)
   361     int tri = adjTris[i];
   362     id = 
m_tin->LocalIndex(tri, a_point);
   366     pt.
x = points[a_point].x;
   367     pt.
y = points[a_point].y;
   368     p1.
x = points[point1].x;
   369     p1.
y = points[point1].y;
   370     p2.
x = points[point2].x;
   371     p2.
y = points[point2].y;
   375     c = sqrt(
sqr(dx) + 
sqr(dy));
   376     sx = p1.
x + dx / 2.0;
   377     sy = p1.
y + dy / 2.0;
   379     a = (c / 2.0) / sin(targetangle / 2.0);
   380     d = a * cos(targetangle / 2.0);
   381     radius = (a * a) / (2.0 * d);
   393       centroid.
x = sx + (d - radius) * dy;
   394       centroid.
y = sy - (d - radius) * dx;
   398       centroid.
x = sx - (d - radius) * dy;
   399       centroid.
y = sy + (d - radius) * dx;
   402     dx = pt.
x - centroid.
x;
   403     dy = pt.
y - centroid.
y;
   404     mag = sqrt(dx * dx + dy * dy);
   408     p3.
x = centroid.
x + radius * dx;
   409     p3.
y = centroid.
y + radius * dy;
   414   a_newLocation.
x = (sum.
x / (double)num);
   415   a_newLocation.
y = (sum.
y / (double)num);
   428   double springStiffness(1.0);
   431   double numPtsFactor(1.7 / (
double)neighbors.size());
   432   Pt3d& p0(points[a_point]);
   434   for (
size_t i = 0; i < neighbors.size(); ++i)
   436     int neighborIdx = neighbors[i];
   437     Pt3d& p1(points[neighborIdx]);
   440     double dist = 
Mdist(p0.x, p0.y, p1.
x, p1.
y);
   441     double targetDist = 0.5 * (size0 + size1); 
   442     double force(springStiffness * (dist - targetDist));
   443     double _fx = force * vec.
x / dist;
   444     double _fy = force * vec.
y / dist;
   450   a_newLocation.
x = p0.x + fx;
   451   a_newLocation.
y = p0.y + fy;
   461   size_t nPts(points.size());
   464     m_flags.assign(nPts, RELAX_RELAX);
   469   for (
size_t i = 0; i < points.size(); ++i)
   475     const VecInt& adjTris = adjTris2d[i];
   476     size_t numTri = adjTris.size();
   478     std::set<int> setPoints;
   479     for (
size_t j = 0; j < numTri; ++j)
   481       int idx = adjTris[j] * 3;
   482       for (
int t = 0; t < 3; ++t)
   485         int ptIdx = tris[idx + t];
   488         setPoints.insert(tris[idx + t]);
   491     setPoints.erase(static_cast<int>(i));
   503   size_t nPts(points.size());
   505   for (
size_t i = 0; i < points.size(); ++i)
   520   Pt3d originalLocation = 
m_tin->Points()[a_idx];
   521   m_tin->Points()[a_idx] = a_newLocation;
   522   const VecInt& adjTris = 
m_tin->TrisAdjToPts()[a_idx];
   524   for (
size_t i = 0; rval && i < adjTris.size(); ++i)
   527     if (!
GT_EPS(
m_tin->TriangleArea(adjTris[i]), 0.0, FLT_EPSILON))
   532   m_tin->Points()[a_idx] = originalLocation;
   542   for (
size_t i = 0; i < a_tin->NumTriangles(); ++i)
   544     if (a_tin->TriangleArea(static_cast<int>(i)) < 0.0)
   641   VecInt2d& trisAdjToPts = tin->TrisAdjToPts();
   644   tin->Points().reserve(5 * 5);
   645   for (
size_t i = 0; i < 5; ++i)
   647     for (
size_t j = 0; j < 5; ++j)
   649       tin->Points().push_back(
Pt3d(j * 10.0, i * 10.0, static_cast<double>(j)));
   658   int outPolyA[] = {0, 1, 2, 3, 4, 9, 14, 19, 24, 23, 22, 21, 20, 15, 10, 5};
   662   relaxer->Relax(outPoly, tin);
   663   const double kDelta = 1e-2;
   664   VecPt3d& tinPts = tin->Points();
   666     {0.00, 0.00, 0.00},   {10.00, 0.00, 1.00},  {20.00, 0.00, 2.00},  {30.00, 0.00, 3.00},
   667     {40.00, 0.00, 4.00},  {0.00, 10.00, 0.00},  {11.10, 8.88, 1.00},  {20.02, 10.20, 2.00},
   668     {29.94, 9.92, 3.00},  {40.00, 10.00, 4.00}, {0.00, 20.00, 0.00},  {9.33, 19.09, 1.00},
   669     {20.68, 20.86, 2.00}, {31.15, 18.86, 3.00}, {40.00, 20.00, 4.00}, {0.00, 30.00, 0.00},
   670     {9.94, 29.75, 1.00},  {18.83, 31.19, 2.00}, {29.14, 29.13, 3.00}, {40.00, 30.00, 4.00},
   671     {0.00, 40.00, 0.00},  {10.00, 40.00, 1.00}, {20.00, 40.00, 2.00}, {30.00, 40.00, 3.00},
   672     {40.00, 40.00, 4.00}};
   693   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {0, 0, 0},
   694                     {10, 0, 0},    {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}, {-5, 10, 0}};
   695   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 3, 7, 9, 4, 8, 7, 4, 5, 8, 3, 9, 6, 3, 4, 7};
   698   tin->Points() = points;
   699   tin->Triangles() = tris;
   700   tin->BuildTrisAdjToPts();
   703   sizer->SetConstantSizeFunc(3.0);
   711   VecDbl expectedPointSizes(points.size(), 3);
   714     {1, 3, 4}, {0, 2, 4}, {1, 4, 5},    {0, 4, 6, 7, 9}, {0, 1, 2, 3, 5, 7, 8},
   715     {2, 4, 8}, {3, 9},    {3, 4, 8, 9}, {4, 5, 7},       {3, 6, 7}};
   734   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {0, 0, 0},
   735                     {10, 0, 0},    {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}, {-5, 10, 0}};
   736   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 4, 8, 7, 4, 5, 8, 3, 9, 6};
   739   tin->Points() = points;
   740   tin->Triangles() = tris;
   741   tin->BuildTrisAdjToPts();
   744   sizer->SetConstantSizeFunc(3.0);
   752   VecDbl expectedPointSizes(points.size(), 3);
   755     {1, 3, 4}, {0, 2, 4}, {1, 4, 5}, {0, 4, 6, 9}, {0, 1, 2, 3, 5, 7, 8},
   756     {2, 4, 8}, {3, 9},    {4, 8},    {4, 5, 7},    {3, 6}};
   775   VecPt3d points = {{-10, -10, 1}, {0, -10, 2},  {10, -10, 3}, {-10, 0, 4}, {8, 7, 5},
   776                     {10, 0, 6},    {-10, 10, 7}, {0, 10, 8},   {10, 10, 9}};
   777   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 3, 4, 6, 4, 7, 6, 4, 5, 8, 4, 8, 7};
   780   tin->Points() = points;
   781   tin->Triangles() = tris;
   782   tin->BuildTrisAdjToPts();
   785   sizer->SetConstantSizeFunc(10.0);
   793   Pt3d newloc, startPt(8, 7, 0), ptZero;
   794   double startDist(
Mdist(0.0, 0.0, startPt.x, startPt.y));
   796   double newDist(
Mdist(0.0, 0.0, newloc.
x, newloc.
y));
   797   TS_ASSERT(newDist < startDist);
   800   Pt3d expectedNewLoc(0.905, 0.542, 0);
   804   tin->Points()[4] = newloc;
   807   newDist = 
Mdist(0.0, 0.0, newloc.
x, newloc.
y);
   808   TS_ASSERT(newDist < startDist);
   809   expectedNewLoc = 
Pt3d(0.023, 0.016, 0);
   812   tin->Points()[4] = newloc;
   815   newDist = 
Mdist(0.0, 0.0, newloc.
x, newloc.
y);
   816   TS_ASSERT(newDist < startDist);
   817   expectedNewLoc = 
Pt3d(0, 0, 0);
   837   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {8, 7, 0},
   838                     {15, 0, 0},    {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}};
   839   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 3, 4, 6, 4, 7, 6, 4, 5, 8, 4, 8, 7};
   842   tin->Points() = points;
   843   tin->Triangles() = tris;
   844   tin->BuildTrisAdjToPts();
   847   sizer->SetConstantSizeFunc(10.0);
   856   Pt3d newloc, startPt(8, 7, 0), ptZero;
   857   double startDist(
Mdist(0.0, 0.0, startPt.x, startPt.y));
   859   double newDist(
Mdist(0.0, 0.0, newloc.
x, newloc.
y));
   860   TS_ASSERT(newDist < startDist);
   863   Pt3d expectedNewLoc(0.673, 0.377, 0);
   867   tin->Points()[4] = newloc;
   870   newDist = 
Mdist(0.0, 0.0, newloc.
x, newloc.
y);
   871   TS_ASSERT(newDist < startDist);
   872   expectedNewLoc = 
Pt3d(0.547, -0.005, 0);
   876   tin->Points()[4] = newloc;
   879   newDist = 
Mdist(0.0, 0.0, newloc.
x, newloc.
y);
   880   TS_ASSERT(newDist < startDist);
   881   expectedNewLoc = 
Pt3d(0.545, 0, 0);
   905   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {8, 7, 0},
   906                     {10, 0, 0},    {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}};
   907   VecInt tris = {0, 1, 3, 1, 4, 3, 1, 5, 4, 1, 2, 5, 3, 4, 6, 4, 7, 6, 4, 5, 8, 4, 8, 7};
   910   tin->Points() = points;
   911   tin->Triangles() = tris;
   912   tin->BuildTrisAdjToPts();
   915   sizer->SetConstantSizeFunc(100.0);
   923   Pt3d newloc, startPt(8, 7, 0), ptZero;
   944   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {0, 0, 0},
   945                     {5, 0, 0},     {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}};
   946   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 4, 5, 7, 5, 8, 7, 3, 4, 7, 3, 7, 6};
   949   tin->Points() = points;
   950   tin->Triangles() = tris;
   951   tin->BuildTrisAdjToPts();
   954   sizer->SetConstantSizeFunc(3.0);
   962   Pt3d newloc(-2, -2, 0), ptZero;
   965   tin->Points()[4] = ptZero;
   966   newloc = 
Pt3d(-2, 2, 0);
   969   tin->Points()[4] = ptZero;
   970   newloc = 
Pt3d(-7, 7, 0);
   973   tin->Points()[4] = ptZero;
   974   newloc = 
Pt3d(7, 0, 0);
   977   tin->Points()[4] = ptZero;
   978   newloc = 
Pt3d(5, 5, 0);
   981   tin->Points()[4] = ptZero;
   982   newloc = 
Pt3d(-10, 0, 0);
   985   tin->Points()[4] = ptZero;
   986   newloc = 
Pt3d(-11, 0, 0);
   989   tin->Points()[4] = ptZero;
   990   newloc = 
Pt3d(-2, -11, 0);
  1010   VecPt3d points = {{-10, -10, 0}, {0, -10, 0},  {10, -10, 0}, {-10, 0, 0}, {8, 7, 0},
  1011                     {10, 0, 0},    {-10, 10, 0}, {0, 10, 0},   {10, 10, 0}};
  1012   VecInt tris = {0, 4, 3, 0, 1, 4, 1, 2, 4, 2, 5, 4, 3, 4, 6, 4, 7, 6, 4, 5, 8, 4, 8, 7};
  1015   tin->Points() = points;
  1016   tin->Triangles() = tris;
  1017   tin->BuildTrisAdjToPts();
  1024   tin->Triangles() = tris;
 void SetupPointSizes()
Set up point sizes to be used by the spring relax algorithm. 
 
bool AllTrianglesHavePositiveArea(BSHP< TrTin > a_tin)
Checks if all triangles have a positive area. 
 
void testSpringRelaxSinglePoint2()
Tests the spring relax of a point. Uses the TIN below. 
 
std::vector< int > VecInt
 
void SpringRelaxSinglePoint(int a_point, Pt3d &a_newLocation)
Relax a point using spring method. 
 
bool GT_EPS(_T A, _U B, _V epsilon)
 
static BSHP< MePolyRedistributePts > New()
Creates an instance of this class. 
 
double m_slideangle
Used on boundary relaxation. Not sure how to document this one. 
 
void testRelaxWhileMeshing()
Tests the relaxation code as if we were creating a mesh. 
 
int trIncrementIndex(int i)
 
#define XM_ENSURE_TRUE_VOID(...)
 
std::vector< double > VecDbl
 
RelaxTypeEnum
Types of relaxation, or the relaxation algorithms. 
 
std::string stToLowerCopy(const std::string &str)
 
void RelaxMarkedPoints(RelaxTypeEnum a_relaxType, int a_iteration, int a_numiterations)
Relaxes the points marked by m_flags. Compare to rlRelaxMarkedNodes. 
 
void testAllTrianglesHavePositiveArea()
Tests the spring relax of a point. Uses the TIN below. 
 
RelaxTypeEnum m_relaxType
the type of relaxation to perform. See RelaxTypeEnum 
 
void testSpringRelaxSetup2()
Tests the spring relax setup. Uses the TIN below. This tin has missing triangles compared to the prev...
 
static BSHP< MeRelaxer > New()
Creates a new instance of the class. 
 
const VecInt * m_fixedPoints
locations that may not be relaxed 
 
void testSpringRelaxSinglePoint3()
Tests the spring relax of a point. Uses the TIN below. We are relaxing point 4 and it has 3 connectio...
 
VecPt3d m_centroids
The triangle centroids. 
 
BSHP< MePolyRedistributePts > m_sizer
size function used by the spring relax method 
 
void SetupNeighbors()
Set up neighbor point information to be used by the spring relax algorithm. 
 
int trDecrementIndex(int i)
 
virtual bool SetRelaxationMethod(const std::string &a_relaxMethod) override
Sets the relaxation method. 
 
std::vector< VecInt > VecInt2d
 
static BSHP< TrTin > New()
 
virtual ~MeRelaxer()
Destructor. 
 
void ComputeCentroids()
Computes the centroids of each triangle. 
 
#define XM_ENSURE_TRUE_VOID_NO_ASSERT(...)
 
VecDbl m_pointSizes
sizer size at each mesh point 
 
#define XM_DISALLOW_COPY_AND_ASSIGN(TypeName)
 
virtual void Relax(const VecInt &a_fixedPoints, BSHP< TrTin > a_tin) override
Moves interior mesh points to create a better mesh. 
 
bool NewLocationIsValid(size_t a_idx, Pt3d &a_newLocation)
Checks if a new relaxed location results in valid triangle (area is positive) 
 
virtual void SetPointSizer(BSHP< MePolyRedistributePts > a_sizer) override
Sets size function used by the spring relaxation method. 
 
RelaxFlagEnum
Point flags. 
 
void AngleRelax(int a_point, Pt3d &a_newLocation)
Relax a point using angles. Moves point to equalize the angles between the edges touching the point...
 
Pt3d gmCreateVector(const Pt3d &a_p1, const Pt3d &a_p2)
 
#define XM_COUNTOF(array)
 
void testNewLocationIsValid()
Tests that a new location for a point is within one of the triangles adjacent to that point's current...
 
Relaxes mesh points. Moves them around to form a better mesh. 
 
VecInt2d m_pointNeighbors
neighbor points for spring relaxation 
 
double Mdist(_T x1, _U y1, _V x2, _W y2)
 
BSHP< TrTin > m_tin
triangles connecting points (mesh elements) 
 
VecInt m_pointsToDelete
indexes of points that must be removed 
 
void testSpringRelaxSinglePoint()
Tests the spring relax of a point. Uses the TIN below. 
 
VecInt m_flags
Flags for points of type RelaxFlagEnum. 
 
void AreaRelax(int a_point, Pt3d &a_newLocation)
Relax a point using area of surrounding triangles. Trys to move point to the center of the area...
 
std::vector< Pt3d > VecPt3d
 
void testSpringRelaxSetup()
Tests the spring relax setup. Uses the TIN below.