Previous Posts
Original Douglas-Peucker Algorithm
The Douglas-Peucker algorithm uses a point-to-edge distance tolerance. The algorithm starts with a crude simplification that is the single edge joining the first and last vertices of the original polyline. It then computes the distance of all intermediate vertices to that edge. The vertex that is furthest away from that edge, and that has a computed distance that is larger than a specified tolerance, will be marked as a key and added to the simplification. This process will recurse for each edge in the current simplification, until all vertices of the original polyline are within tolerance of the simplification results. This process is illustrated below:
Initially, the simplification consists of a single edge. During the first step, the fourth vertex is marked as a key and the simplification is adjusted accordingly. During the second step, the first edge of the current simplification is processed. The maximum vertex distance to that edge falls below the tolerance threshold, and no new key is added. During the third step, a key is found for the second edge of the current simplification. This edge is split at the key and the simplification is updated. This process continues until no more keys can be found. Note that at each step, only one edge of the current simplification is processed.
This algorithm has a worst case running time of O(nm), and O(n log m) on average, where m is the size of the simplified polyline. As such, this is an output dependent algorithm, and will be very fast when m is small. To make it even faster, the Distance between points routine is applied as a pre-processing step.
MATLAB Implementation
function out_points = points_simplify_2d(points,
epsilon)
id_end = size(points,1);
id_start = 1;
% Indeces of points are not removed by
Douglas-Peucker algorithm
remaining_ids = true(id_end,1);
% Call douglas_peucker_iteration
(recursive function)
[points remaining_ids] = douglas_peucker_iteration( ...
points,epsilon,id_start,id_end, remaining_ids);
points,epsilon,id_start,id_end, remaining_ids);
out_points =
points(remaining_ids,:);
end
function [points remaining_ids] = douglas_peucker_iteration(points, epsilon, id_start, id_end, remaining_ids)
% For the points (start + 1) to (end)
-> next_points_relative is
% relative coordinates from start point
next_points_relative = bsxfun(@minus,
points(id_start+1:id_end,:),
points(id_start,:));
end_point_relative = next_points_relative(end,:)';
% Efficient Method to get
distances_from_start_end_line
beta = (end_point_relative' *
next_points_relative')./(end_point_relative'*end_point_relative);
b =
next_points_relative-bsxfun(@times,beta,end_point_relative)';
distances_from_start_end_line =
hypot(b(:,1),b(:,2));
% Identify maximum distance and get
its index
[dmax dmax_id] = max(distances_from_start_end_line);
dmax_id =
id_start + dmax_id; %ID of the edge point
if dmax <= epsilon;
remaining_ids(id_start+1:id_end-1) = false;
else
remaining_ids(id_start+1:id_end-1) = false;
else
[points
remaining_ids] = douglas_peucker_iteration( ...
points,epsilon,id_start,dmax_id, remaining_ids);
points,epsilon,id_start,dmax_id, remaining_ids);
[points
remaining_ids] = douglas_peucker_iteration( ...
points,epsilon,dmax_id,id_end,
remaining_ids);
end
end
______________________________________________________________________
References:
[1] http://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm
[2] Polyline Simplification
No comments:
Post a Comment