xmsgrid  1.0
GmPolyLinePtRedistributer.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
14 
15 // 3. Standard library headers
16 #include <map>
17 
18 // 4. External library headers
19 
20 // 5. Shared code headers
21 #include <xmscore/math/math.h>
22 #include <xmscore/misc/XmError.h>
23 
24 // 6. Non-shared code headers
25 
26 //----- Forward declarations ---------------------------------------------------
27 
28 //----- External globals -------------------------------------------------------
29 
30 //----- Namespace declaration --------------------------------------------------
31 namespace xms
32 {
33 //----- Constants / Enumerations -----------------------------------------------
34 
35 //----- Classes / Structs ------------------------------------------------------
36 
37 //----- Internal functions -----------------------------------------------------
38 
39 //----- Class / Function definitions -------------------------------------------
42 {
43 public:
45 
46  virtual VecPt3d Redistribute(const VecPt3d& a_input, double a_size) override;
47 
48  double PolyLineLengths(const VecPt3d& a_pts, VecDbl& a_lengths);
50  double a_totalLength,
51  const VecDbl& a_lengths,
52  int a_nSeg);
53 };
54 
55 //------------------------------------------------------------------------------
58 //------------------------------------------------------------------------------
59 BSHP<GmPolyLinePtRedistributer> GmPolyLinePtRedistributer::New()
60 {
61  BSHP<GmPolyLinePtRedistributer> ret(new GmPolyLinePtRedistributerImpl);
62  return ret;
63 } // MePolyRedistributePts::New
64 //------------------------------------------------------------------------------
66 //------------------------------------------------------------------------------
67 GmPolyLinePtRedistributer::GmPolyLinePtRedistributer()
68 {
69 }
70 //------------------------------------------------------------------------------
72 //------------------------------------------------------------------------------
73 GmPolyLinePtRedistributer::~GmPolyLinePtRedistributer()
74 {
75 }
76 
77 //------------------------------------------------------------------------------
83 //------------------------------------------------------------------------------
85 {
86  VecPt3d ret;
87  XM_ENSURE_TRUE(!a_polyLines.empty(), ret);
88 
89  VecDbl lengths;
90  double length = PolyLineLengths(a_polyLines, lengths);
91  int nSeg = (int)((length / a_size) + .5);
92  return RedistPolyLineWithNumSeg(a_polyLines, length, lengths, nSeg);
93 } // GmPolyLinePtRedistributerImpl::Redistribute
94 //------------------------------------------------------------------------------
100 //------------------------------------------------------------------------------
102 {
103  double l(0);
104  a_lengths.resize(a_pts.size());
105  for (size_t i = 1; i < a_pts.size(); ++i)
106  {
107  const Pt3d &p0(a_pts[i - 1]), &p1(a_pts[i]);
108  a_lengths[i] = Mdist(p0.x, p0.y, p1.x, p1.y);
109  l += a_lengths[i];
110  }
111  return l;
112 } // GmPolyLinePtRedistributerImpl::PolyLineLengths
113 //------------------------------------------------------------------------------
121 //------------------------------------------------------------------------------
123  double a_totalLength,
124  const VecDbl& a_lengths,
125  int a_nSeg)
126 {
127  VecPt3d ret;
128  std::map<double, size_t> tVals;
129  double runningLen(0), t;
130  for (size_t i = 0; i < a_lengths.size(); ++i)
131  {
132  runningLen += a_lengths[i];
133  t = runningLen / a_totalLength;
134  tVals.insert(std::make_pair(t, i));
135  }
136  VecDbl targetTvals(a_nSeg);
137  for (size_t i = 0; i < targetTvals.size(); ++i)
138  {
139  targetTvals[i] = (i + 1) * (1.0 / a_nSeg);
140  }
141 
142  ret.reserve(a_nSeg + 1);
143  ret.push_back(a_pts.front());
144  for (size_t i = 0; i < targetTvals.size(); ++i)
145  {
146  auto it = tVals.lower_bound(targetTvals[i]);
147  if (it != tVals.end())
148  {
149  size_t seg1 = it->second, seg0(0);
150  double t1 = it->first, t0(0);
151  if (it != tVals.begin())
152  {
153  it--;
154  t0 = it->first;
155  seg0 = it->second;
156  }
157  // convert polyline tval to segment tval
158  double t = (targetTvals[i] - t0) / (t1 - t0);
159  // calculate the point
160  const Pt3d &p0(a_pts[seg0]), &p1(a_pts[seg1]);
161  Pt3d pt;
162  pt.x = p0.x + t * (p1.x - p0.x);
163  pt.y = p0.y + t * (p1.y - p0.y);
164  ret.push_back(pt);
165  }
166  }
167  if (ret.size() < 2)
168  ret.push_back(a_pts.back());
169  return ret;
170 } // GmPolyLinePtRedistributerImpl::RedistPolyLineWithNumSeg
171 
172 } // namespace xms
173 
174 #ifdef CXX_TEST
175 
178 
180 #include <xmsgrid/geometry/geoms.h>
181 
182 //------------------------------------------------------------------------------
184 //------------------------------------------------------------------------------
186 {
187  BSHP<xms::GmPolyLinePtRedistributer> b = xms::GmPolyLinePtRedistributer::New();
188  TS_ASSERT(b);
189 } // GmPolyLinePtRedistributerUnitTests::testCreateClass
190 //------------------------------------------------------------------------------
192 //------------------------------------------------------------------------------
194 {
195  xms::VecPt3d pts{{0, 0, 0}, {10, 0, 0}};
196  double l(2);
197  xms::VecPt3d basePts{{0, 0, 0}, {2, 0, 0}, {4, 0, 0}, {6, 0, 0}, {8, 0, 0}, {10, 0, 0}};
199  xms::VecPt3d outPts = r.Redistribute(pts, l);
200  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
201 } // GmPolyLinePtRedistributerUnitTests::testRedistribute
202 //------------------------------------------------------------------------------
204 //------------------------------------------------------------------------------
206 {
207  xms::VecPt3d pts{{0, 0, 0}, {10, 0, 0}, {10, 10, 0}};
208  double l(5);
209  xms::VecPt3d basePts = {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {10, 5, 0}, {10, 10, 0}};
211  xms::VecPt3d outPts = r.Redistribute(pts, l);
212  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
213  l = 3.0;
214  outPts = r.Redistribute(pts, l);
215  basePts = {{0, 0, 0}, {2.85, 0, 0}, {5.71, 0, 0}, {8.57, 0, 0},
216  {10, 1.43, 0}, {10, 4.29, 0}, {10, 7.14, 0}, {10, 10, 0}};
217  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-2);
218  l = 20.0;
219  outPts = r.Redistribute(pts, l);
220  basePts = {{0, 0, 0}, {10, 10, 0}};
221  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
222  l = 41.0;
223  outPts = r.Redistribute(pts, l);
224  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
225 } // GmPolyLinePtRedistributerUnitTests::testRedistribute1
226 #endif
void testRedistribute1()
tests redistributing 2 line segments
Implementation of GmPolyLinePtRedistributer.
Redistributes the point locations on a polyline based on a size.
std::vector< double > VecDbl
#define TS_ASSERT_DELTA_VECPT3D(a, b, delta)
double PolyLineLengths(const VecPt3d &a_pts, VecDbl &a_lengths)
Calculates the total length (xy) of a polyline as well as the length of each segment.
static BSHP< GmPolyLinePtRedistributer > New()
Creates an instance of this class.
void testCreateClass()
tests creating the class
virtual VecPt3d Redistribute(const VecPt3d &a_input, double a_size) override
Redistributes the distance between points on a polyline based on the a_size value provided to the met...
Functions dealing with geometry.
#define XM_ENSURE_TRUE(...)
VecPt3d RedistPolyLineWithNumSeg(const VecPt3d &a_pts, double a_totalLength, const VecDbl &a_lengths, int a_nSeg)
Calculates the total length (xy) of a polyline as well as the length of each segment.
void testRedistribute()
tests redistributing 1 line segment
XMS Namespace.
Definition: geoms.cpp:34
double Mdist(_T x1, _U y1, _V x2, _W y2)
std::vector< Pt3d > VecPt3d