var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => {
  __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
  return value;
};

// packages/shared/src/index.ts
import {
  Box3,
  Raycaster,
  Vector2 as Vector22,
  Vector3
} from "three";

// packages/shared/src/aStar/aStar.ts
import { Vector2 } from "three";

// packages/shared/src/aStar/utils.ts
function standardKeyPointsChanger(path) {
  const keyPoints = [];
  const map = {};
  for (const item of path) {
    const node1 = map[JSON.stringify(item.begin)];
    const node2 = map[JSON.stringify(item.end)];
    if (!node1) {
      map[JSON.stringify(item.begin)] = {
        id: JSON.stringify(item.begin),
        x: item.begin[0],
        y: item.begin[1],
        neighbours: [
          {
            id: JSON.stringify(item.end),
            d: item.distance
          }
        ]
      };
    } else {
      node1.neighbours.push({
        id: JSON.stringify(item.end),
        d: item.distance
      });
    }
    if (!node2) {
      map[JSON.stringify(item.end)] = {
        id: JSON.stringify(item.end),
        x: item.end[0],
        y: item.end[1],
        neighbours: [
          {
            id: JSON.stringify(item.begin),
            d: item.distance
          }
        ]
      };
    } else {
      node2.neighbours.push({
        id: JSON.stringify(item.begin),
        d: item.distance
      });
    }
  }
  for (const key of Object.keys(map)) {
    keyPoints.push(map[key]);
  }
  return keyPoints;
}
function myTruncate(point, precision = 3) {
  const [x, y] = point;
  if (isNaN(+x) || isNaN(+y)) {
    return [];
  }
  return [
    parseFloat((+x).toFixed(precision)),
    parseFloat((+y).toFixed(precision))
  ];
}
function getDistance(p1, p2) {
  return Math.abs(
    Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
  );
}
function parsePath(path) {
  const _parseArr = (arr) => {
    return [parseFloat(arr[0]), parseFloat(arr[1])];
  };
  for (const item of path) {
    Object.assign(item, {
      begin: _parseArr(item.begin),
      end: _parseArr(item.end),
      distance: parseFloat(item.distance)
    });
  }
  return path;
}

// packages/shared/src/aStar/aStar.ts
var AStar = class {
  constructor(path) {
    this.path = path;
    __publicField(this, "sc");
    __publicField(this, "keyPoints");
    __publicField(this, "keyPointMap");
    __publicField(this, "openList");
    __publicField(this, "closeList");
    __publicField(this, "invalidList");
    __publicField(this, "searchCount");
    __publicField(this, "beginTime");
    __publicField(this, "endTime");
    __publicField(this, "beginNode");
    __publicField(this, "endNode");
    __publicField(this, "beginVertical");
    __publicField(this, "endVertical");
    this.path = parsePath(this.path);
    this.sc = 1;
    this.keyPoints = standardKeyPointsChanger(this.path);
    this.keyPointMap = {};
    for (let i = 0; i < this.keyPoints.length; i++) {
      const p = this.keyPoints[i];
      this.keyPointMap[p.id] = p;
    }
    this.openList = [];
    this.closeList = [];
    this.invalidList = [];
    this.searchCount = 0;
    this.beginTime = new Date();
    this.endTime = new Date();
  }
  shortestPath(beginNode, endNode) {
    const result = [];
    this.openList = [];
    this.closeList = [];
    this.invalidList = [];
    this.searchCount = 0;
    this.beginTime = new Date();
    beginNode.parent = null;
    beginNode.d = 0;
    this.beginNode = beginNode;
    this.endNode = endNode;
    this.closeList.push(this.beginNode);
    while (true) {
      if (this.closeList.length === 0) {
        break;
      }
      this.searchCount++;
      let currNode = this.closeList[this.closeList.length - 1];
      if (currNode.id === endNode.id) {
        while (currNode && currNode !== null) {
          result.unshift(currNode);
          currNode = currNode.parent;
        }
        break;
      }
      if (currNode.neighbours && currNode.neighbours.length > 0) {
        for (let i = 0; i < currNode.neighbours.length; i++) {
          const nb = currNode.neighbours[i];
          const tmpNode = this.keyPointMap[nb.id];
          if (!tmpNode || this.contain(this.invalidList, tmpNode)) {
            continue;
          }
          if (this.contain(this.closeList, tmpNode)) {
            continue;
          }
          if (this.contain(this.openList, tmpNode)) {
            continue;
          }
          tmpNode.d = nb.d;
          tmpNode.parent = currNode;
          tmpNode.cost = this.f(tmpNode);
          this.openList.push(tmpNode);
        }
      }
      if (this.openList.length > 0) {
        let minNode = null;
        for (let i = 0; i < this.openList.length; i++) {
          const tmp = this.openList[i];
          if (minNode === null || minNode.cost > tmp.cost) {
            minNode = tmp;
          }
        }
        this.remove(this.openList, minNode);
        this.closeList.push(minNode);
      } else {
        this.invalidList.push(currNode);
        this.remove(this.closeList, currNode);
      }
      if (this.searchCount > 5e5) {
        break;
      }
    }
    this.endTime = new Date();
    return result;
  }
  contain(nodes, node) {
    let result = false;
    nodes.forEach(function(item) {
      if (item.id === node.id) {
        result = true;
      }
    });
    return result;
  }
  remove(nodes, node) {
    let move = false;
    for (let i = 0; i < nodes.length; i++) {
      if (move) {
        nodes[i - 1] = nodes[i];
      }
      if (node.id === nodes[i].id) {
        move = true;
      }
    }
    if (move) {
      nodes.length -= 1;
    }
  }
  f(n) {
    return this.g(n) + this.h(n);
  }
  g(n) {
    let result = 0;
    let currNode = n;
    while (currNode && currNode !== null) {
      result += currNode.d;
      currNode = currNode.parent;
    }
    return result;
  }
  h(n) {
    return this.euclidianCost(n, this.endNode);
  }
  euclidianCost(begin, end) {
    const dx = begin.x - end.x;
    const dy = begin.y - end.y;
    return Math.sqrt(dx * dx + dy * dy) * this.sc;
  }
  getNearest(point, isBegin = true) {
    let nearItem;
    let tempItem;
    let nearPoint;
    let vertical;
    let dist = Infinity;
    for (let i = 0; i < this.path.length; i++) {
      tempItem = this.path[i];
      const {
        dist: tempDist,
        point: tempPoint,
        vertical: tempVertical
      } = this.nearestPointOnLine(tempItem.begin, tempItem.end, point);
      if (tempDist < dist) {
        dist = tempDist;
        nearPoint = tempPoint;
        nearItem = tempItem;
        vertical = tempVertical;
      }
    }
    return { point: nearPoint, vertical };
  }
  calcShortestPath(begin, end) {
    const { point: beginPoint, vertical: beginVertical } = this.getNearest(
      begin,
      true
    );
    const { point: endPoint, vertical: endVertical } = this.getNearest(
      end,
      false
    );
    this.beginVertical = beginVertical;
    this.endVertical = endVertical;
    const standardBeginPoint = this.keyPoints.find(
      (_) => _.id === JSON.stringify(beginPoint)
    );
    const standardEndPoint = this.keyPoints.find(
      (_) => _.id === JSON.stringify(endPoint)
    );
    let result = this.shortestPath(standardBeginPoint, standardEndPoint);
    result = this.trackOptimize(result);
    return result;
  }
  trackOptimize(trackPoints) {
    if (trackPoints.length >= 2) {
      if (this.beginVertical) {
        const beginV = new Vector2(
          this.beginVertical[0],
          this.beginVertical[1]
        );
        if (this.isInLine(trackPoints[0], trackPoints[1], beginV, 2)) {
          console.log(
            "\u8D77\u70B9\u5782\u70B9\u5728\u5BFC\u822A\u7EBF\u4E0A\uFF0Cshift \u53BB\u9664\u8FDE\u63A5\u8D77\u70B9\uFF0C\u540E\u7EED unshift \u8D77\u70B9\u5782\u70B9"
          );
          trackPoints.shift();
        }
        trackPoints.unshift(beginV);
      }
      if (this.endVertical) {
        const endV = new Vector2(this.endVertical[0], this.endVertical[1]);
        if (this.isInLine(
          trackPoints[trackPoints.length - 1],
          trackPoints[trackPoints.length - 2],
          endV,
          2
        )) {
          console.log(
            "\u7EC8\u70B9\u5782\u70B9\u5728\u5BFC\u822A\u7EBF\u4E0A\uFF0Cpop \u53BB\u9664\u8FDE\u63A5\u7EC8\u70B9\uFF0C\u540E\u7EED push \u7EC8\u70B9\u5782\u70B9"
          );
          trackPoints.pop();
        }
        trackPoints.push(endV);
      }
    }
    return trackPoints;
  }
  nearestPointOnLine(begin, end, p) {
    const _getNearPointByLineBeginEnd = () => {
      const arr = [
        {
          point: begin,
          dist: getDistance(
            new Vector2(begin[0], begin[1]),
            new Vector2(p[0], p[1])
          )
        },
        {
          point: end,
          dist: getDistance(
            new Vector2(end[0], end[1]),
            new Vector2(p[0], p[1])
          )
        }
      ];
      arr.sort((a, b) => a.dist - b.dist);
      return arr[0];
    };
    let point = [0, 0];
    let vertical = null;
    let dist = 0;
    const { x, y } = this.getVerticalPoint(
      new Vector2(begin[0], begin[1]),
      new Vector2(end[0], end[1]),
      new Vector2(p[0], p[1])
    );
    const isInline = this.isInLine(
      new Vector2(begin[0], begin[1]),
      new Vector2(end[0], end[1]),
      new Vector2(x, y),
      2
    );
    const { point: _point, dist: _dist } = _getNearPointByLineBeginEnd();
    point = _point;
    if (isInline) {
      vertical = [x, y];
      dist = getDistance(new Vector2(p[0], p[1]), new Vector2(x, y));
    } else {
      vertical = null;
      point = _point;
      dist = _dist;
    }
    return {
      vertical,
      point,
      dist
    };
  }
  getVerticalPoint(p1, p2, p) {
    const A = p2.y - p1.y;
    const B = p1.x - p2.x;
    const C = p2.x * p1.y - p1.x * p2.y;
    const tmp = A * A + B * B;
    let x = (B * B * p.x - A * B * p.y - A * C) / tmp;
    let y = (A * A * p.y - A * B * p.x - B * C) / tmp;
    const [x1, y1] = myTruncate([x, y]);
    x = x1;
    y = y1;
    return { x, y };
  }
  getAngle(p1, p2) {
    const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x);
    const angle = radian * (180 / Math.PI);
    return {
      radian,
      angle
    };
  }
  isInLine(p1, p2, p, offsetAngle = 0) {
    if (!p1 || !p2 || !p) {
      return false;
    }
    const diffAngle = Math.floor(this.getAngle(p1, p).angle) - Math.floor(this.getAngle(p, p2).angle);
    if (offsetAngle === 0) {
      return diffAngle === 0;
    } else {
      return diffAngle >= -offsetAngle && diffAngle <= offsetAngle;
    }
  }
};

// packages/shared/src/GLTFLoader.promise.ts
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js";
var GLTFLoaderPromise = (url, onProgress) => {
  const loader = new GLTFLoader();
  return new Promise((resolve, reject) => {
    loader.load(
      url,
      ({ scene }) => resolve(scene),
      onProgress,
      reject
    );
  });
};

// packages/shared/src/warning.ts
var warn = (msg, ...args) => {
  console.warn(`[KTMap warn] ${msg}`, ...args);
};

// packages/shared/src/index.ts
import { throttle, debounce, merge } from "lodash-es";
var getIntersects = ({
  event,
  $map,
  scene,
  camera,
  objects
}) => {
  const { top, left } = $map.getBoundingClientRect();
  const raycaster = new Raycaster();
  const mouse = new Vector22();
  mouse.x = (event.clientX - left) / $map.clientWidth * 2 - 1;
  mouse.y = -((event.clientY - top) / $map.clientHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  const intersects = raycaster.intersectObjects(
    objects || scene.children,
    true
  );
  return intersects;
};
var getWorldPosition = ({
  event,
  $map,
  scene,
  camera,
  objects
}) => {
  const intersects = getIntersects({ event, $map, scene, camera, objects });
  const points = intersects.map((item) => item.point);
  const worldPosition = new Vector3();
  if (points.length > 0) {
    worldPosition.set(points[0].x, points[0].y, points[0].z);
    return { worldPosition, intersects };
  }
  return {};
};
var getScreenPostion = ({
  worldPosition,
  $map,
  scene,
  camera
}) => {
  const { top, left, width, height } = $map.getBoundingClientRect();
  const standardVector = new Vector3().copy(worldPosition).project(camera);
  const halfWidth = width / 2;
  const halfHeight = height / 2;
  const x = Math.round(standardVector.x * halfWidth + halfWidth);
  const y = Math.round(-standardVector.y * halfHeight + halfHeight);
  return {
    x: x + left,
    y: y + top
  };
};
var getObjectsByName = (name, parent) => {
  const arr = [];
  parent.traverse((item) => {
    if (item.name === name)
      arr.push(item);
  });
  return arr;
};
var getObjectByName = (name, parent) => {
  return getObjectsByName(name, parent)[0];
};
var getPointBetweenPoints = ({
  p1,
  p2,
  segment = Math.abs(
    Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
  ) + 1,
  i = 0
}) => {
  return {
    point: new Vector22(
      (p2.x - p1.x) / segment * i + p1.x,
      (p2.y - p1.y) / segment * i + p1.y
    ),
    segment
  };
};
var getAngle = (p1, p2) => {
  const radian = Math.atan2(p2.y - p1.y, p2.x - p1.x);
  const angle = radian * (180 / Math.PI);
  return {
    radian,
    angle
  };
};
var CLS_PREFIX = "ktmap";
var truncateBase = (n, precision = 3) => {
  if (isNaN(+n))
    return n;
  return parseFloat((+n).toFixed(precision));
};
var truncateNumber = (data, precision = 3) => {
  return Array.isArray(data) ? data.map((_) => truncateBase(_, precision)) : truncateBase(data, precision);
};
var truncateVector2 = (data, precision = 3) => {
  return Array.isArray(data) ? data.map(
    (_) => new Vector22(
      truncateBase(_.x, precision),
      truncateBase(_.y, precision)
    )
  ) : new Vector22(
    truncateBase(data.x, precision),
    truncateBase(data.y, precision)
  );
};
var truncateVector3 = (data, precision = 3) => {
  return Array.isArray(data) ? data.map(
    (_) => new Vector3(
      truncateBase(_.x, precision),
      truncateBase(_.y, precision),
      truncateBase(_.z, precision)
    )
  ) : new Vector3(
    truncateBase(data.x, precision),
    truncateBase(data.y, precision),
    truncateBase(data.z, precision)
  );
};
var getDistance2 = (p1, p2) => {
  return Math.abs(
    Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2))
  );
};
var getBox3Center = (mesh) => {
  return new Box3().setFromObject(mesh).getCenter(new Vector3());
};
var sleep = (delay = 1e3) => new Promise((_) => setTimeout(_, delay));
var getDollys = (targetMesh, controls, offset = 5) => {
  if (!targetMesh) {
    return { fitDistance: 0, dollys: [0] };
  }
  const bb = new Box3().setFromObject(targetMesh);
  const fitDistance = controls.getDistanceToFitBox(
    bb.max.x - bb.min.x,
    bb.max.y - bb.min.y,
    bb.max.z - bb.min.z
  );
  const minDollys = [...new Array(offset)].map((_, i) => fitDistance / (i + 2)).reverse();
  const maxDollys = [...new Array(offset)].map((_, i) => fitDistance * (i + 2));
  const dollys = [...minDollys, fitDistance, ...maxDollys];
  return { fitDistance, dollys };
};
var NOOP = () => {
};
var extend = Object.assign;
var objectToString = Object.prototype.toString;
var toTypeString = (value) => objectToString.call(value);
var isArray = Array.isArray;
var isMap = (val) => toTypeString(val) === "[object Map]";
var isSet = (val) => toTypeString(val) === "[object Set]";
var isDate = (val) => toTypeString(val) === "[object Date]";
var isFunction = (val) => typeof val === "function";
var isString = (val) => typeof val === "string";
var isSymbol = (val) => typeof val === "symbol";
var isObject = (val) => val !== null && typeof val === "object";
var isPromise = (val) => {
  return isObject(val) && isFunction(val.then) && isFunction(val.catch);
};
export {
  AStar,
  CLS_PREFIX,
  GLTFLoaderPromise,
  NOOP,
  debounce,
  extend,
  getAngle,
  getBox3Center,
  getDistance2 as getDistance,
  getDollys,
  getIntersects,
  getObjectByName,
  getObjectsByName,
  getPointBetweenPoints,
  getScreenPostion,
  getWorldPosition,
  isArray,
  isDate,
  isFunction,
  isMap,
  isObject,
  isPromise,
  isSet,
  isString,
  isSymbol,
  merge,
  objectToString,
  sleep,
  throttle,
  toTypeString,
  truncateNumber,
  truncateVector2,
  truncateVector3,
  warn
};
//# sourceMappingURL=shared.esm-bundler.js.map
