UNPKG

2.88 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.getPropertiesAtPoint = void 0;
4var parse_path_string_1 = require("../parser/parse-path-string");
5var normalize_path_1 = require("../process/normalize-path");
6var get_point_at_length_1 = require("./get-point-at-length");
7var get_properties_at_length_1 = require("./get-properties-at-length");
8var get_total_length_1 = require("./get-total-length");
9/**
10 * Returns the point and segment in path closest to a given point as well as
11 * the distance to the path stroke.
12 * @see https://bl.ocks.org/mbostock/8027637
13 */
14function getPropertiesAtPoint(pathInput, point) {
15 var path = (0, parse_path_string_1.parsePathString)(pathInput);
16 var normalPath = (0, normalize_path_1.normalizePath)(path);
17 var pathLength = (0, get_total_length_1.getTotalLength)(path);
18 var distanceTo = function (p) {
19 var dx = p.x - point.x;
20 var dy = p.y - point.y;
21 return dx * dx + dy * dy;
22 };
23 var precision = 8;
24 var scan;
25 var scanDistance = 0;
26 var closest;
27 var bestLength = 0;
28 var bestDistance = Infinity;
29 // linear scan for coarse approximation
30 for (var scanLength = 0; scanLength <= pathLength; scanLength += precision) {
31 scan = (0, get_point_at_length_1.getPointAtLength)(normalPath, scanLength);
32 scanDistance = distanceTo(scan);
33 if (scanDistance < bestDistance) {
34 closest = scan;
35 bestLength = scanLength;
36 bestDistance = scanDistance;
37 }
38 }
39 // binary search for precise estimate
40 precision /= 2;
41 var before;
42 var after;
43 var beforeLength = 0;
44 var afterLength = 0;
45 var beforeDistance = 0;
46 var afterDistance = 0;
47 while (precision > 0.5) {
48 beforeLength = bestLength - precision;
49 before = (0, get_point_at_length_1.getPointAtLength)(normalPath, beforeLength);
50 beforeDistance = distanceTo(before);
51 afterLength = bestLength + precision;
52 after = (0, get_point_at_length_1.getPointAtLength)(normalPath, afterLength);
53 afterDistance = distanceTo(after);
54 if (beforeLength >= 0 && beforeDistance < bestDistance) {
55 closest = before;
56 bestLength = beforeLength;
57 bestDistance = beforeDistance;
58 }
59 else if (afterLength <= pathLength && afterDistance < bestDistance) {
60 closest = after;
61 bestLength = afterLength;
62 bestDistance = afterDistance;
63 }
64 else {
65 precision /= 2;
66 }
67 }
68 var segment = (0, get_properties_at_length_1.getPropertiesAtLength)(path, bestLength);
69 var distance = Math.sqrt(bestDistance);
70 return { closest: closest, distance: distance, segment: segment };
71}
72exports.getPropertiesAtPoint = getPropertiesAtPoint;
73//# sourceMappingURL=get-properties-at-point.js.map
\No newline at end of file