xmsgeom  1.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
GmPolyLinePtRedistributer.cpp
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
7 //------------------------------------------------------------------------------
8 
9 //----- Included files ---------------------------------------------------------
10 
11 // 1. Precompiled header
12 
13 // 2. My own header
15 
16 // 3. Standard library headers
17 #include <map>
18 
19 // 4. External library headers
20 
21 // 5. Shared code headers
22 #include <xmscore/math/math.h>
23 #include <xmscore/misc/XmError.h>
24 
25 // 6. Non-shared code headers
26 
27 //----- Forward declarations ---------------------------------------------------
28 
29 //----- External globals -------------------------------------------------------
30 
31 //----- Namespace declaration --------------------------------------------------
32 namespace xms
33 {
34 //----- Constants / Enumerations -----------------------------------------------
35 
36 //----- Classes / Structs ------------------------------------------------------
37 
38 //----- Internal functions -----------------------------------------------------
39 
40 //----- Class / Function definitions -------------------------------------------
43 {
44 public:
46 
47  virtual VecPt3d Redistribute(const VecPt3d& a_input, double a_size) override;
48 
49  double PolyLineLengths(const VecPt3d& a_pts, VecDbl& a_lengths);
51  double a_totalLength,
52  const VecDbl& a_lengths,
53  int a_nSeg);
54 };
55 
56 //------------------------------------------------------------------------------
59 //------------------------------------------------------------------------------
60 BSHP<GmPolyLinePtRedistributer> GmPolyLinePtRedistributer::New()
61 {
62  BSHP<GmPolyLinePtRedistributer> ret(new GmPolyLinePtRedistributerImpl);
63  return ret;
64 } // MePolyRedistributePts::New
65 //------------------------------------------------------------------------------
67 //------------------------------------------------------------------------------
68 GmPolyLinePtRedistributer::GmPolyLinePtRedistributer()
69 {
70 }
71 //------------------------------------------------------------------------------
73 //------------------------------------------------------------------------------
74 GmPolyLinePtRedistributer::~GmPolyLinePtRedistributer()
75 {
76 }
77 
78 //------------------------------------------------------------------------------
84 //------------------------------------------------------------------------------
86 {
87  VecPt3d ret;
88  XM_ENSURE_TRUE(!a_polyLines.empty(), ret);
89 
90  VecDbl lengths;
91  double length = PolyLineLengths(a_polyLines, lengths);
92  int nSeg = (int)((length / a_size) + .5);
93  return RedistPolyLineWithNumSeg(a_polyLines, length, lengths, nSeg);
94 } // GmPolyLinePtRedistributerImpl::Redistribute
95 //------------------------------------------------------------------------------
101 //------------------------------------------------------------------------------
103 {
104  double l(0);
105  a_lengths.resize(a_pts.size());
106  for (size_t i = 1; i < a_pts.size(); ++i)
107  {
108  const Pt3d &p0(a_pts[i - 1]), &p1(a_pts[i]);
109  a_lengths[i] = Mdist(p0.x, p0.y, p1.x, p1.y);
110  l += a_lengths[i];
111  }
112  return l;
113 } // GmPolyLinePtRedistributerImpl::PolyLineLengths
114 //------------------------------------------------------------------------------
122 //------------------------------------------------------------------------------
124  double a_totalLength,
125  const VecDbl& a_lengths,
126  int a_nSeg)
127 {
128  VecPt3d ret;
129  std::map<double, size_t> tVals;
130  double runningLen(0), t;
131  for (size_t i = 0; i < a_lengths.size(); ++i)
132  {
133  runningLen += a_lengths[i];
134  t = runningLen / a_totalLength;
135  tVals.insert(std::make_pair(t, i));
136  }
137  VecDbl targetTvals(a_nSeg);
138  for (size_t i = 0; i < targetTvals.size(); ++i)
139  {
140  targetTvals[i] = (i + 1) * (1.0 / a_nSeg);
141  }
142 
143  ret.reserve(a_nSeg + 1);
144  ret.push_back(a_pts.front());
145  for (size_t i = 0; i < targetTvals.size(); ++i)
146  {
147  auto it = tVals.lower_bound(targetTvals[i]);
148  if (it != tVals.end())
149  {
150  size_t seg1 = it->second, seg0(0);
151  double t1 = it->first, t0(0);
152  if (it != tVals.begin())
153  {
154  it--;
155  t0 = it->first;
156  seg0 = it->second;
157  }
158  // convert polyline tval to segment tval
159  double t = (targetTvals[i] - t0) / (t1 - t0);
160  // calculate the point
161  const Pt3d &p0(a_pts[seg0]), &p1(a_pts[seg1]);
162  Pt3d pt;
163  pt.x = p0.x + t * (p1.x - p0.x);
164  pt.y = p0.y + t * (p1.y - p0.y);
165  ret.push_back(pt);
166  }
167  }
168  if (ret.size() < 2)
169  ret.push_back(a_pts.back());
170  return ret;
171 } // GmPolyLinePtRedistributerImpl::RedistPolyLineWithNumSeg
172 
173 } // namespace xms
174 
175 #ifdef CXX_TEST
176 
179 
181 #include <xmsgeom/geometry/geoms.h>
182 
183 //------------------------------------------------------------------------------
185 //------------------------------------------------------------------------------
187 {
188  BSHP<xms::GmPolyLinePtRedistributer> b = xms::GmPolyLinePtRedistributer::New();
189  TS_ASSERT(b);
190 } // GmPolyLinePtRedistributerUnitTests::testCreateClass
191 //------------------------------------------------------------------------------
193 //------------------------------------------------------------------------------
195 {
196  xms::VecPt3d pts{{0, 0, 0}, {10, 0, 0}};
197  double l(2);
198  xms::VecPt3d basePts{{0, 0, 0}, {2, 0, 0}, {4, 0, 0}, {6, 0, 0}, {8, 0, 0}, {10, 0, 0}};
200  xms::VecPt3d outPts = r.Redistribute(pts, l);
201  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
202 } // GmPolyLinePtRedistributerUnitTests::testRedistribute
203 //------------------------------------------------------------------------------
205 //------------------------------------------------------------------------------
207 {
208  xms::VecPt3d pts{{0, 0, 0}, {10, 0, 0}, {10, 10, 0}};
209  double l(5);
210  xms::VecPt3d basePts = {{0, 0, 0}, {5, 0, 0}, {10, 0, 0}, {10, 5, 0}, {10, 10, 0}};
212  xms::VecPt3d outPts = r.Redistribute(pts, l);
213  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
214  l = 3.0;
215  outPts = r.Redistribute(pts, l);
216  basePts = {{0, 0, 0}, {2.85, 0, 0}, {5.71, 0, 0}, {8.57, 0, 0},
217  {10, 1.43, 0}, {10, 4.29, 0}, {10, 7.14, 0}, {10, 10, 0}};
218  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-2);
219  l = 20.0;
220  outPts = r.Redistribute(pts, l);
221  basePts = {{0, 0, 0}, {10, 10, 0}};
222  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
223  l = 41.0;
224  outPts = r.Redistribute(pts, l);
225  TS_ASSERT_DELTA_VECPT3D(basePts, outPts, 1e-9);
226 } // GmPolyLinePtRedistributerUnitTests::testRedistribute1
227 #endif
void testRedistribute1()
tests redistributing 2 line segments
Implementation of GmPolyLinePtRedistributer.
Redistributes the point locations on a polyline based on a size.
#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.
std::vector< double > VecDbl
#define XM_ENSURE_TRUE(...)
std::vector< Pt3d > VecPt3d
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
double Mdist(_T x1, _U y1, _V x2, _W y2)