You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

159 lines
3.8 KiB

function rdp_find_max(points, start, end) {
const EPS = 0.5;
let result = -1;
let max_dist = 0;
const a = points[start];
const b = points[end];
const dx = b.x - a.x;
const dy = b.y - a.y;
const dist_ab = Math.sqrt(dx * dx + dy * dy);
const sin_theta = dy / dist_ab;
const cos_theta = dx / dist_ab;
for (let i = start; i < end; ++i) {
const p = points[i];
const ox = p.x - a.x;
const oy = p.y - a.y;
const rx = cos_theta * ox + sin_theta * oy;
const ry = -sin_theta * ox + cos_theta * oy;
const x = rx + a.x;
const y = ry + a.y;
const dist = Math.abs(y - a.y);
if (dist > EPS && dist > max_dist) {
result = i;
max_dist = dist;
}
}
return result;
}
function process_rdp_r(points, start, end) {
let result = [];
const max = rdp_find_max(points, start, end);
if (max !== -1) {
const before = process_rdp_r(points, start, max);
const after = process_rdp_r(points, max, end);
result = [...before, points[max], ...after];
}
return result;
}
function process_rdp(points) {
const result = process_rdp_r(points, 0, points.length - 1);
result.unshift(points[0]);
result.push(points[points.length - 1]);
return result;
}
function process_ewmv(points, round = false) {
const result = [];
const alpha = 0.4;
result.push(points[0]);
for (let i = 1; i < points.length; ++i) {
const p = points[i];
const x = Math.round(alpha * p.x + (1 - alpha) * result[result.length - 1].x);
const y = Math.round(alpha * p.y + (1 - alpha) * result[result.length - 1].y);
result.push({'x': x, 'y': y});
}
return result;
}
function process_stroke(points) {
const result0 = process_ewmv(points);
const result1 = process_rdp(result0, true);
return result1;
}
function stroke_stats(points, width) {
let length = 0;
let xmin = points[0].x, ymin = points[0].y;
let xmax = xmin, ymax = ymin;
for (let i = 0; i < points.length; ++i) {
const point = points[i];
if (point.x < xmin) xmin = point.x;
if (point.y < ymin) ymin = point.y;
if (point.x > xmax) xmax = point.x;
if (point.y > ymax) ymax = point.y;
if (i > 0) {
const last = points[i - 1];
const dx = point.x - last.x;
const dy = point.y - last.y;
length += Math.sqrt(dx * dx + dy * dy);
}
}
xmin -= width;
ymin -= width;
xmax += width * 2;
ymax += width * 2;
const bbox = {
'xmin': Math.floor(xmin),
'ymin': Math.floor(ymin),
'xmax': Math.ceil(xmax),
'ymax': Math.ceil(ymax)
};
return {
'bbox': bbox,
'length': length,
};
}
function rectangles_intersect(a, b) {
const result = (
a.xmin <= b.xmax
&& a.xmax >= b.xmin
&& a.ymin <= b.ymax
&& a.ymax >= b.ymin
);
return result;
}
function stroke_intersects_region(points, bbox) {
const stats = stroke_stats(points, storage.cursor.width);
return rectangles_intersect(stats.bbox, bbox);
}
function color_to_u32(color_str) {
const r = parseInt(color_str.substring(1, 3), 16);
const g = parseInt(color_str.substring(3, 5), 16);
const b = parseInt(color_str.substring(5, 7), 16);
return (r << 16) | (g << 8) | b;
}
function color_from_u32(color_u32) {
const r = (color_u32 >> 16) & 0xFF;
const g = (color_u32 >> 8) & 0xFF;
const b = color_u32 & 0xFF;
let r_str = r.toString(16);
let g_str = g.toString(16);
let b_str = b.toString(16);
if (r <= 0xF) r_str = '0' + r_str;
if (g <= 0xF) g_str = '0' + g_str;
if (b <= 0xF) b_str = '0' + b_str;
return '#' + r_str + g_str + b_str;
}