Selaa lähdekoodia

Merge branch 'master' of http://192.168.0.115:3000/bill/traffic-laser

xushiting 2 vuotta sitten
vanhempi
commit
5a2503fa30
1 muutettua tiedostoa jossa 171 lisäystä ja 0 poistoa
  1. 171 0
      src/graphic/Util/bezierUtil.js

+ 171 - 0
src/graphic/Util/bezierUtil.js

@@ -0,0 +1,171 @@
+const sqrt = Math.sqrt,
+  min = Math.min,
+  max = Math.max,
+  sign = Math.sign,
+  abs = Math.abs,
+  pow = Math.pow,
+  acos = Math.acos,
+  cos = Math.cos,
+  sin = Math.sin;
+
+export function transformCoord(rotation, dx, dy) {
+  var cos = Math.cos(rotation);
+  var sin = Math.sin(rotation);
+  return function transformPoint(x, y) {
+    return {
+      x: cos * (x - dx) + sin * (y - dy),
+      y: -sin * (x - dx) + cos * (y - dy),
+    };
+  };
+}
+
+export function createIsRoughHit(fromX, fromY, cpX, cpY, toX, toY) {
+  var _a, _b, _c;
+  var transform = transformCoord(Math.atan2(toX - fromX, toY - fromY), (fromX + toX) / 2, (fromY + toY) / 2);
+  var t_from = transform(fromX, fromY);
+  var t_cp = transform(cpX, cpY);
+  var t_to = transform(toX, toY);
+  var ratio = Math.abs(t_from.x);
+  var _d = [t_cp.y / 2, 0].sort((a, b) => a - b),
+    bottom = _d[0],
+    top = _d[1];
+  var left, right;
+  if (t_cp.x >= t_from.x && t_cp.x <= t_to.y) {
+    (_a = [t_from.x, t_to.x]), (left = _a[0]), (right = _a[1]);
+  } else if (t_cp.x > 0) {
+    (_b = [t_from.x, 0.5 * (t_cp.x + (ratio * ratio) / t_cp.x)]), (left = _b[0]), (right = _b[1]);
+  } else {
+    (_c = [0.5 * (t_cp.x + (ratio * ratio) / t_cp.x), t_to.x]), (left = _c[0]), (right = _c[1]);
+  }
+  return function isRoughtHit(x, y, distance) {
+    var t_point = transform(x, y);
+    if (t_point.x < left - distance || t_point.x > right + distance) return false;
+    if (t_point.y < bottom - distance || t_point.y > top + distance) return false;
+    return true;
+  };
+}
+export function baseMeasureBezier(fromX, fromY, cpX, cpY, toX, toY) {
+  var isRoughHit = createIsRoughHit(fromX, fromY, cpX, cpY, toX, toY);
+  var _a = (0, createCalDistanceToBezier)(fromX, fromY, cpX, cpY, toX, toY),
+    getDistance = _a.getDistance,
+    getInfo = _a.getInfo;
+  function baseIsHit(x, y, hitDistance) {
+    if (typeof hitDistance !== 'number') throw new Error('isHit params "hitDistance" must be a number');
+    // rough hit
+    if (!isRoughHit(x, y, hitDistance)) return false;
+    //  analyical
+    return getDistance(x, y) <= hitDistance;
+  }
+  function isHit(a, b, c) {
+    if (typeof a === 'number') return baseIsHit(a, b, c);
+    if (Array.isArray(a)) return baseIsHit(a[0], a[1], b);
+    return baseIsHit(a.x, a.y, b);
+  }
+  return {
+    isHit: isHit,
+    getInfo: function (a, b) {
+      if (typeof a === 'number') return getInfo(a, b);
+      if (Array.isArray(a)) return getInfo(a[0], a[1]);
+      return getInfo(a.x, a.y);
+    },
+  };
+}
+export function measureBezier(a, b, c, d, e, f) {
+  if (typeof a === 'number') {
+    // @ts-ignore
+    return baseMeasureBezier(a, b, c, d, e, f);
+  }
+  if (Array.isArray(a)) {
+    return baseMeasureBezier(a[0], a[1], b[0], b[1], c[0], c[1]);
+  }
+  // @ts-ignore
+  return baseMeasureBezier(a.x, a.y, b.x, b.y, c.x, c.y);
+}
+
+function clamp(x, min_n, max_n) {
+  return min(max(x, min_n), max_n);
+}
+function dot(x, y) {
+  return x[0] * y[0] + x[1] * y[1];
+}
+function dot2(a, b) {
+  return a * a + b * b;
+}
+export function createCalDistanceToBezier(sX, sY, cpX, cpY, eX, eY) {
+  var a = [cpX - sX, cpY - sY];
+  var b = [sX - 2 * cpX + eX, sY - 2 * cpY + eY];
+  var c = [2 * a[0], 2 * a[1]];
+  var kk = 1 / dot(b, b);
+  var kx = kk * dot(a, b);
+  var kx_2 = kx * kx;
+  var dot_a = dot(a, a);
+  var SQRT_3 = pow(3, 1 / 2);
+  var calBezierTValues =
+    dot(b, b) === 0
+      ? // bezier fallback to line or point
+      function calBezierTValues(d) {
+        return dot_a === 0 ? 0 : clamp(-dot(a, d) / 2 / dot_a, 0, 1);
+      }
+      : function calBezierTValues(d) {
+        var ky = (kk * (2.0 * dot_a + dot(d, b))) / 3.0;
+        var kz = kk * dot(d, a);
+        var p = ky - kx_2;
+        var p3 = p * p * p;
+        var q = kx * (2.0 * kx_2 - 3.0 * ky) + kz;
+        var h = q * q + 4.0 * p3;
+        if (h >= 0.0) {
+          h = sqrt(h);
+          var x_0 = (h - q) / 2.0;
+          var x_1 = (-h - q) / 2.0;
+          var t = clamp(sign(x_0) * pow(abs(x_0), 1 / 3) + sign(x_1) * pow(abs(x_1), 1 / 3) - kx, 0.0, 1.0);
+          return t;
+        } else {
+          var z = sqrt(-p);
+          var v = acos(q / (p * z * 2.0)) / 3.0;
+          var m = cos(v);
+          var n = sin(v) * SQRT_3;
+          return [clamp((m + m) * z - kx, 0, 1), clamp((-n - m) * z - kx, 0, 1)];
+        }
+      };
+  return {
+    getDistance: function (pX, pY) {
+      var d = [sX - pX, sY - pY];
+      var t = calBezierTValues(d);
+      if (typeof t === 'number') return sqrt(dot2((c[0] + b[0] * t) * t + d[0], (c[1] + b[1] * t) * t + d[1]));
+      var _a = t,
+        t_0 = _a[0],
+        t_1 = _a[1];
+      return sqrt(min(dot2(d[0] + (c[0] + b[0] * t_0) * t_0, d[1] + (c[1] + b[1] * t_0) * t_0), dot2(d[0] + (c[0] + b[0] * t_1) * t_1, d[1] + (c[1] + b[1] * t_1) * t_1)));
+    },
+    getInfo: function (pX, pY) {
+      var d = [sX - pX, sY - pY];
+      var t = calBezierTValues(d);
+      if (typeof t === 'number') {
+        var p_x = (c[0] + b[0] * t) * t + d[0];
+        var p_y = (c[1] + b[1] * t) * t + d[1];
+        return {
+          distance: sqrt(dot2(p_x, p_y)),
+          point: [p_x + pX, p_y + pY],
+        };
+      }
+      var _a = t,
+        t_0 = _a[0],
+        t_1 = _a[1];
+      var p_0_x = (c[0] + b[0] * t_0) * t_0 + d[0];
+      var p_0_y = (c[1] + b[1] * t_0) * t_0 + d[1];
+      var p_1_x = (c[0] + b[0] * t_1) * t_1 + d[0];
+      var p_1_y = (c[1] + b[1] * t_1) * t_1 + d[1];
+      var d_0 = dot2(p_0_x, p_0_y);
+      var d_1 = dot2(p_1_x, p_1_y);
+      return d_0 >= d_1
+        ? {
+          distance: sqrt(d_1),
+          point: [p_1_x + pX, p_1_y + pY],
+        }
+        : {
+          distance: sqrt(d_0),
+          point: [p_0_x + pX, p_0_y + pY],
+        };
+    },
+  };
+}