Use iterators for DouglasPeucker
This commit is contained in:
parent
651c07c724
commit
7d425aa76f
@ -106,37 +106,38 @@ DouglasPeucker::DouglasPeucker()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level)
|
void DouglasPeucker::Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level)
|
||||||
{
|
{
|
||||||
// check if input data is invalid
|
// check if input data is invalid
|
||||||
BOOST_ASSERT_MSG(!input_geometry.empty(), "geometry invalid");
|
BOOST_ASSERT_MSG(begin != end, "geometry invalid");
|
||||||
|
|
||||||
if (input_geometry.size() < 2)
|
unsigned size = std::distance(begin, end);
|
||||||
|
if (size < 2)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
input_geometry.front().necessary = true;
|
begin->necessary = true;
|
||||||
input_geometry.back().necessary = true;
|
std::prev(end)->necessary = true;
|
||||||
|
|
||||||
{
|
{
|
||||||
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
BOOST_ASSERT_MSG(zoom_level < 19, "unsupported zoom level");
|
||||||
unsigned left_border = 0;
|
RandomAccessIt left_border = begin;
|
||||||
unsigned right_border = 1;
|
RandomAccessIt right_border = std::next(begin);
|
||||||
// Sweep over array and identify those ranges that need to be checked
|
// Sweep over array and identify those ranges that need to be checked
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// traverse list until new border element found
|
// traverse list until new border element found
|
||||||
if (input_geometry[right_border].necessary)
|
if (right_border->necessary)
|
||||||
{
|
{
|
||||||
// sanity checks
|
// sanity checks
|
||||||
BOOST_ASSERT(input_geometry[left_border].necessary);
|
BOOST_ASSERT(left_border->necessary);
|
||||||
BOOST_ASSERT(input_geometry[right_border].necessary);
|
BOOST_ASSERT(right_border->necessary);
|
||||||
recursion_stack.emplace(left_border, right_border);
|
recursion_stack.emplace(left_border, right_border);
|
||||||
left_border = right_border;
|
left_border = right_border;
|
||||||
}
|
}
|
||||||
++right_border;
|
++right_border;
|
||||||
} while (right_border < input_geometry.size());
|
} while (right_border != end);
|
||||||
}
|
}
|
||||||
|
|
||||||
// mark locations as 'necessary' by divide-and-conquer
|
// mark locations as 'necessary' by divide-and-conquer
|
||||||
@ -146,24 +147,23 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
|
|||||||
const GeometryRange pair = recursion_stack.top();
|
const GeometryRange pair = recursion_stack.top();
|
||||||
recursion_stack.pop();
|
recursion_stack.pop();
|
||||||
// sanity checks
|
// sanity checks
|
||||||
BOOST_ASSERT_MSG(input_geometry[pair.first].necessary, "left border mus be necessary");
|
BOOST_ASSERT_MSG(pair.first->necessary, "left border mus be necessary");
|
||||||
BOOST_ASSERT_MSG(input_geometry[pair.second].necessary, "right border must be necessary");
|
BOOST_ASSERT_MSG(pair.second->necessary, "right border must be necessary");
|
||||||
BOOST_ASSERT_MSG(pair.second < input_geometry.size(), "right border outside of geometry");
|
BOOST_ASSERT_MSG(std::distance(pair.second, end) > 0, "right border outside of geometry");
|
||||||
BOOST_ASSERT_MSG(pair.first < pair.second, "left border on the wrong side");
|
BOOST_ASSERT_MSG(std::distance(pair.first, pair.second) >= 0, "left border on the wrong side");
|
||||||
|
|
||||||
int max_int_distance = 0;
|
int max_int_distance = 0;
|
||||||
unsigned farthest_entry_index = pair.second;
|
auto farthest_entry_it = pair.second;
|
||||||
const CoordinatePairCalculator dist_calc(input_geometry[pair.first].location,
|
const CoordinatePairCalculator dist_calc(pair.first->location, pair.second->location);
|
||||||
input_geometry[pair.second].location);
|
|
||||||
|
|
||||||
// sweep over range to find the maximum
|
// sweep over range to find the maximum
|
||||||
for (const auto i : osrm::irange(pair.first + 1, pair.second))
|
for (auto it = std::next(pair.first); it != pair.second; ++it)
|
||||||
{
|
{
|
||||||
const int distance = dist_calc(input_geometry[i].location);
|
const int distance = dist_calc(it->location);
|
||||||
// found new feasible maximum?
|
// found new feasible maximum?
|
||||||
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
|
if (distance > max_int_distance && distance > douglas_peucker_thresholds[zoom_level])
|
||||||
{
|
{
|
||||||
farthest_entry_index = i;
|
farthest_entry_it = it;
|
||||||
max_int_distance = distance;
|
max_int_distance = distance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -172,14 +172,14 @@ void DouglasPeucker::Run(std::vector<SegmentInformation> &input_geometry, const
|
|||||||
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
|
if (max_int_distance > douglas_peucker_thresholds[zoom_level])
|
||||||
{
|
{
|
||||||
// mark idx as necessary
|
// mark idx as necessary
|
||||||
input_geometry[farthest_entry_index].necessary = true;
|
farthest_entry_it->necessary = true;
|
||||||
if (1 < (farthest_entry_index - pair.first))
|
if (1 < std::distance(pair.first, farthest_entry_it))
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(pair.first, farthest_entry_index);
|
recursion_stack.emplace(pair.first, farthest_entry_it);
|
||||||
}
|
}
|
||||||
if (1 < (pair.second - farthest_entry_index))
|
if (1 < std::distance(pair.second, farthest_entry_it))
|
||||||
{
|
{
|
||||||
recursion_stack.emplace(farthest_entry_index, pair.second);
|
recursion_stack.emplace(farthest_entry_it, pair.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,16 +43,18 @@ struct SegmentInformation;
|
|||||||
|
|
||||||
class DouglasPeucker
|
class DouglasPeucker
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
using RandomAccessIt = std::vector<SegmentInformation>::iterator;
|
||||||
private:
|
private:
|
||||||
std::vector<int> douglas_peucker_thresholds;
|
std::vector<int> douglas_peucker_thresholds;
|
||||||
|
|
||||||
using GeometryRange = std::pair<unsigned, unsigned>;
|
using GeometryRange = std::pair<RandomAccessIt, RandomAccessIt>;
|
||||||
// Stack to simulate the recursion
|
// Stack to simulate the recursion
|
||||||
std::stack<GeometryRange> recursion_stack;
|
std::stack<GeometryRange> recursion_stack;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DouglasPeucker();
|
DouglasPeucker();
|
||||||
void Run(std::vector<SegmentInformation> &input_geometry, const unsigned zoom_level);
|
void Run(RandomAccessIt begin, RandomAccessIt end, const unsigned zoom_level);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* DOUGLASPEUCKER_H_ */
|
#endif /* DOUGLASPEUCKER_H_ */
|
||||||
|
@ -190,7 +190,7 @@ class DescriptionFactory
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generalize poly line
|
// Generalize poly line
|
||||||
polyline_generalizer.Run(path_description, zoomLevel);
|
polyline_generalizer.Run(path_description.begin(), path_description.end(), zoomLevel);
|
||||||
|
|
||||||
// fix what needs to be fixed else
|
// fix what needs to be fixed else
|
||||||
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
|
unsigned necessary_pieces = 0; // a running index that counts the necessary pieces
|
||||||
|
Loading…
Reference in New Issue
Block a user