|
|
|
@ -11,8 +11,16 @@ function screen_to_canvas(state, p) {
@@ -11,8 +11,16 @@ function screen_to_canvas(state, p) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function rdp_find_max(state, zoom, stroke, start, end) { |
|
|
|
|
// Finds a point from the range [start, end) with the maximum distance from the line (start--end)
|
|
|
|
|
const EPS = 1.0 / zoom; |
|
|
|
|
// const EPS = 10.0;
|
|
|
|
|
let cache_key = null; |
|
|
|
|
|
|
|
|
|
if (end - start > config.rdp_cache_threshold) { |
|
|
|
|
cache_key = stroke.index + '-' + zoom + '-' + start + '-' + end; |
|
|
|
|
if (cache_key in state.rdp_cache) { |
|
|
|
|
return state.rdp_cache[cache_key]; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
let result = -1; |
|
|
|
|
let max_dist = 0; |
|
|
|
@ -26,23 +34,17 @@ function rdp_find_max(state, zoom, stroke, start, end) {
@@ -26,23 +34,17 @@ function rdp_find_max(state, zoom, stroke, start, end) {
|
|
|
|
|
const dy = by - ay; |
|
|
|
|
|
|
|
|
|
const dist_ab = Math.sqrt(dx * dx + dy * dy); |
|
|
|
|
const sin_theta = dy / dist_ab; |
|
|
|
|
const cos_theta = dx / dist_ab; |
|
|
|
|
const dir_nx = dy / dist_ab; |
|
|
|
|
const dir_ny = -dx / dist_ab; |
|
|
|
|
|
|
|
|
|
for (let i = start; i < end; ++i) { |
|
|
|
|
for (let i = start + 1; i < end; ++i) { |
|
|
|
|
const px = state.coordinates.data[stroke.coords_from + i * 2 + 0]; |
|
|
|
|
const py = state.coordinates.data[stroke.coords_from + i * 2 + 1]; |
|
|
|
|
|
|
|
|
|
const ox = px - ax; |
|
|
|
|
const oy = py - ay; |
|
|
|
|
|
|
|
|
|
const rx = cos_theta * ox + sin_theta * oy; |
|
|
|
|
const ry = -sin_theta * ox + cos_theta * oy; |
|
|
|
|
const apx = px - ax; |
|
|
|
|
const apy = py - ay; |
|
|
|
|
|
|
|
|
|
const x = rx + ax; |
|
|
|
|
const y = ry + ay; |
|
|
|
|
|
|
|
|
|
const dist = Math.abs(y - ay); |
|
|
|
|
const dist = Math.abs(apx * dir_nx + apy * dir_ny); |
|
|
|
|
|
|
|
|
|
if (dist > EPS && dist > max_dist) { |
|
|
|
|
result = i; |
|
|
|
@ -50,19 +52,36 @@ function rdp_find_max(state, zoom, stroke, start, end) {
@@ -50,19 +52,36 @@ function rdp_find_max(state, zoom, stroke, start, end) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
state.stats.rdp_max_count++; |
|
|
|
|
state.stats.rdp_segments += end - start - 1; |
|
|
|
|
|
|
|
|
|
if (end - start > config.rdp_cache_threshold) { |
|
|
|
|
state.rdp_cache[cache_key] = result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function process_rdp_indices_r(state, zoom, mask, stroke, start, end) { |
|
|
|
|
// Looks like the recursive implementation spends most of its time in the function call overhead
|
|
|
|
|
// Let's try to use an explicit stack instead to give the js engine more room to play with
|
|
|
|
|
// Update: it's not faster. But it gives more sensible source-line samples in chrome profiler, so I'll leave it
|
|
|
|
|
|
|
|
|
|
let result = 0; |
|
|
|
|
const stack = []; |
|
|
|
|
|
|
|
|
|
stack.push({'start': start, 'end': end}); |
|
|
|
|
|
|
|
|
|
const max = rdp_find_max(state, zoom, stroke, start, end); |
|
|
|
|
while (stack.length > 0) { |
|
|
|
|
const region = stack.pop(); |
|
|
|
|
const max = rdp_find_max(state, zoom, stroke, region.start, region.end); |
|
|
|
|
|
|
|
|
|
if (max !== -1) { |
|
|
|
|
mask[max] = 1; |
|
|
|
|
result += 1; |
|
|
|
|
result += process_rdp_indices_r(state, zoom, mask, stroke, start, max); |
|
|
|
|
result += process_rdp_indices_r(state, zoom, mask, stroke, max, end); |
|
|
|
|
if (max !== -1) { |
|
|
|
|
mask[max] = 1; |
|
|
|
|
result += 1; |
|
|
|
|
stack.push({'start': region.start, 'end': max}); |
|
|
|
|
stack.push({'start': max, 'end': region.end}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result; |
|
|
|
@ -103,8 +122,18 @@ function process_ewmv(points, round = false) {
@@ -103,8 +122,18 @@ function process_ewmv(points, round = false) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function process_stroke(state, zoom, stroke) { |
|
|
|
|
// Try caching the highest zoom level that only returns the endpoints
|
|
|
|
|
if (zoom <= stroke.turns_into_straight_line_zoom) { |
|
|
|
|
return 2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// const result0 = process_ewmv(points);
|
|
|
|
|
const result1 = process_rdp_indices(state, zoom, stroke, true); |
|
|
|
|
|
|
|
|
|
if (result1 === 2 && zoom > stroke.turns_into_straight_line_zoom) { |
|
|
|
|
stroke.turns_into_straight_line_zoom = zoom; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return result1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|