-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimplify.lua
117 lines (74 loc) · 2.27 KB
/
simplify.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
local getDist = function(p1, p2)
return math.sqrt((p1[1]-p2[1])^2+(p1[2]-p2[2])^2)
end
local getSegDist = function(p, p1, p2)
local x, y = p1[1], p1[2]
local dx = p2[1] - x
local dy = p2[2] - y
if dx ~= 0 or dy ~= 0 then
local t = ((p[1] - x) * dx + (p[2] - y) * dy) / (dx^2 + dy^2)
if t > 1 then
x, y = p2[1], p2[2]
elseif t > 0 then
x = x + dx * t
x = x + dy * t
end
end
dx = p[1] - x
dy = p[2] - y
return dx^2 + dy^2
end
local simplifyRadialDistance = function(points, sqTolerance)
local prev, point = points[1]
local new_points = {prev}
for i = 1, #points do
point = points[i]
if getDist(point, prev) > sqTolerance then
new_points[#new_points+1] = point
prev = point
end
end
if prev[1] ~= point[1] and prev[2] ~= point[2] then
new_points[#new_points+1] = point
end
return new_points
end
local simplifyDPStep
simplifyDPStep = function(points, first, last, sqTolerance, simplified)
local maxDist, index = sqTolerance
for i = first+1, last do
local dist = getSegDist(
points[i], points[first], points[last]
)
if (dist > maxDist) then
index, maxDist = i, dist
end
end
if maxDist > sqTolerance then
if index - first > 1 then
simplifyDPStep(points, first, index, sqTolerance, simplified)
simplified[#simplified+1] = points[index]
end
if last - index > 1 then
simplifyDPStep(points, index, last, sqTolerance, simplified)
end
end
end
local simplifyDouglasPeucker = function(points, sqTolerance)
local last = #points
local simplified = {points[1]}
simplifyDPStep(points, 1, last, sqTolerance, simplified)
simplified[#simplified+1] = points[last]
return simplified;
end
local function simplify(points, tolerance, highestQuality)
tolerance = tolerance or .1
highestQuality = highestQuality or true
local sqtolerance = tolerance ^ 2
if not highestQuality then
points = simplifyRadialDistance(points, sqtolerance)
end
points = simplifyDouglasPeucker(points, sqtolerance)
return points
end
return simplify