- Go backend (server/)
- Frontend (web/, server/static/)
- Database and deployment files
- Scripts and docs
Co-Authored-By: 狸花猫/Claude-Qwen3.6-Plus 🐾
625 lines
20 KiB
JavaScript
625 lines
20 KiB
JavaScript
"use strict";
|
||
|
||
Object.defineProperty(exports, "__esModule", {
|
||
value: true
|
||
});
|
||
exports.simplifyPolyline = exports.removeRedundantPoint = exports.removeFrom = exports.reconstructPath = exports.pathFinder = exports.mergeBBox = exports.isSegmentsIntersected = exports.isSegmentCrossingBBox = exports.isPointOutsideBBox = exports.isHorizontalPort = exports.isBending = exports.isBBoxesOverlapping = exports.heuristicCostEstimate = exports.getSimplePolyline = exports.getPolylinePoints = exports.getPointsFromBBox = exports.getPathWithBorderRadiusByPolyline = exports.getNeighborPoints = exports.getExpandedBBoxPoint = exports.getExpandedBBox = exports.getBorderRadiusPoints = exports.getBBoxYCrossPoints = exports.getBBoxXCrossPoints = exports.getBBoxFromPoints = exports.getBBoxFromPoint = exports.getBBoxCrossPointsByPoint = exports.filterConnectPoints = exports.distance = exports._costByPoints = exports.SortedArray = void 0;
|
||
var getBBoxFromPoint = exports.getBBoxFromPoint = function getBBoxFromPoint(point) {
|
||
var x = point.x,
|
||
y = point.y;
|
||
return {
|
||
x: x,
|
||
y: y,
|
||
centerX: x,
|
||
centerY: y,
|
||
minX: x,
|
||
minY: y,
|
||
maxX: x,
|
||
maxY: y,
|
||
height: 0,
|
||
width: 0
|
||
};
|
||
};
|
||
var getBBoxFromPoints = exports.getBBoxFromPoints = function getBBoxFromPoints(points) {
|
||
if (points === void 0) {
|
||
points = [];
|
||
}
|
||
var xs = [];
|
||
var ys = [];
|
||
points.forEach(function (p) {
|
||
xs.push(p.x);
|
||
ys.push(p.y);
|
||
});
|
||
var minX = Math.min.apply(Math, xs);
|
||
var maxX = Math.max.apply(Math, xs);
|
||
var minY = Math.min.apply(Math, ys);
|
||
var maxY = Math.max.apply(Math, ys);
|
||
return {
|
||
centerX: (minX + maxX) / 2,
|
||
centerY: (minY + maxY) / 2,
|
||
maxX: maxX,
|
||
maxY: maxY,
|
||
minX: minX,
|
||
minY: minY,
|
||
height: maxY - minY,
|
||
width: maxX - minX
|
||
};
|
||
};
|
||
var isBBoxesOverlapping = exports.isBBoxesOverlapping = function isBBoxesOverlapping(b1, b2) {
|
||
return Math.abs(b1.centerX - b2.centerX) * 2 < b1.width + b2.width && Math.abs(b1.centerY - b2.centerY) * 2 < b1.height + b2.height;
|
||
};
|
||
var filterConnectPoints = exports.filterConnectPoints = function filterConnectPoints(points) {
|
||
// pre-process: remove duplicated points
|
||
var result = [];
|
||
var map = {};
|
||
var pointsLength = points.length;
|
||
for (var i = pointsLength - 1; i >= 0; i--) {
|
||
var p = points[i];
|
||
p.id = "".concat(p.x, "|||").concat(p.y);
|
||
if (!map[p.id]) {
|
||
map[p.id] = p;
|
||
result.push(p);
|
||
}
|
||
}
|
||
return result;
|
||
};
|
||
var simplifyPolyline = exports.simplifyPolyline = function simplifyPolyline(points) {
|
||
return filterConnectPoints(points);
|
||
};
|
||
var getSimplePolyline = exports.getSimplePolyline = function getSimplePolyline(sPoint, tPoint) {
|
||
return [sPoint, {
|
||
x: sPoint.x,
|
||
y: tPoint.y
|
||
}, tPoint];
|
||
};
|
||
var getExpandedBBox = exports.getExpandedBBox = function getExpandedBBox(bbox, offset) {
|
||
if (bbox.width || bbox.height) {
|
||
return {
|
||
centerX: bbox.centerX,
|
||
centerY: bbox.centerY,
|
||
minX: bbox.minX - offset,
|
||
minY: bbox.minY - offset,
|
||
maxX: bbox.maxX + offset,
|
||
maxY: bbox.maxY + offset,
|
||
height: bbox.height + 2 * offset,
|
||
width: bbox.width + 2 * offset
|
||
};
|
||
}
|
||
// when it is a point
|
||
return bbox;
|
||
};
|
||
var isHorizontalPort = exports.isHorizontalPort = function isHorizontalPort(port, bbox) {
|
||
var dx = Math.abs(port.x - bbox.centerX);
|
||
var dy = Math.abs(port.y - bbox.centerY);
|
||
if (dx === 0 && dy === 0) return 0;
|
||
return dx / bbox.width > dy / bbox.height;
|
||
};
|
||
var getExpandedBBoxPoint = exports.getExpandedBBoxPoint = function getExpandedBBoxPoint(bbox,
|
||
// 将原来节点 bbox 扩展了 offset 后的 bbox,且被 gridSize 格式化
|
||
point,
|
||
// 被 gridSize 格式化后的位置(anchorPoint)
|
||
anotherPoint) {
|
||
var isHorizontal = isHorizontalPort(point, bbox);
|
||
if (isHorizontal === 0) {
|
||
// 说明锚点是节点中心,linkCenter: true。需要根据两个节点的相对关系决定方向
|
||
var x = bbox.centerX;
|
||
var y = bbox.centerY;
|
||
if (anotherPoint.y < point.y) {
|
||
// 另一端在左上/右上方时,总是从上方走
|
||
y = bbox.minY;
|
||
} else if (anotherPoint.x > point.x) {
|
||
// 另一端在右下方,往右边走
|
||
x = bbox.maxX;
|
||
} else if (anotherPoint.x < point.x) {
|
||
// 另一端在左下方,往左边走
|
||
x = bbox.minX;
|
||
} else if (anotherPoint.x === point.x) {
|
||
// 另一段在正下方,往下走
|
||
y = bbox.maxY;
|
||
}
|
||
return {
|
||
x: x,
|
||
y: y
|
||
};
|
||
}
|
||
if (isHorizontal) {
|
||
return {
|
||
x: point.x > bbox.centerX ? bbox.maxX : bbox.minX,
|
||
y: point.y
|
||
};
|
||
}
|
||
return {
|
||
x: point.x,
|
||
y: point.y > bbox.centerY ? bbox.maxY : bbox.minY
|
||
};
|
||
};
|
||
/**
|
||
*
|
||
* @param b1
|
||
* @param b2
|
||
*/
|
||
var mergeBBox = exports.mergeBBox = function mergeBBox(b1, b2) {
|
||
var minX = Math.min(b1.minX, b2.minX);
|
||
var minY = Math.min(b1.minY, b2.minY);
|
||
var maxX = Math.max(b1.maxX, b2.maxX);
|
||
var maxY = Math.max(b1.maxY, b2.maxY);
|
||
return {
|
||
centerX: (minX + maxX) / 2,
|
||
centerY: (minY + maxY) / 2,
|
||
minX: minX,
|
||
minY: minY,
|
||
maxX: maxX,
|
||
maxY: maxY,
|
||
height: maxY - minY,
|
||
width: maxX - minX
|
||
};
|
||
};
|
||
var getPointsFromBBox = exports.getPointsFromBBox = function getPointsFromBBox(bbox) {
|
||
// anticlockwise
|
||
return [{
|
||
x: bbox.minX,
|
||
y: bbox.minY
|
||
}, {
|
||
x: bbox.maxX,
|
||
y: bbox.minY
|
||
}, {
|
||
x: bbox.maxX,
|
||
y: bbox.maxY
|
||
}, {
|
||
x: bbox.minX,
|
||
y: bbox.maxY
|
||
}];
|
||
};
|
||
var isPointOutsideBBox = exports.isPointOutsideBBox = function isPointOutsideBBox(point, bbox) {
|
||
var x = point.x,
|
||
y = point.y;
|
||
return x < bbox.minX || x > bbox.maxX || y < bbox.minY || y > bbox.maxY;
|
||
};
|
||
var getBBoxXCrossPoints = exports.getBBoxXCrossPoints = function getBBoxXCrossPoints(bbox, x) {
|
||
if (x < bbox.minX || x > bbox.maxX) {
|
||
return [];
|
||
}
|
||
return [{
|
||
x: x,
|
||
y: bbox.minY
|
||
}, {
|
||
x: x,
|
||
y: bbox.maxY
|
||
}];
|
||
};
|
||
var getBBoxYCrossPoints = exports.getBBoxYCrossPoints = function getBBoxYCrossPoints(bbox, y) {
|
||
if (y < bbox.minY || y > bbox.maxY) {
|
||
return [];
|
||
}
|
||
return [{
|
||
x: bbox.minX,
|
||
y: y
|
||
}, {
|
||
x: bbox.maxX,
|
||
y: y
|
||
}];
|
||
};
|
||
var getBBoxCrossPointsByPoint = exports.getBBoxCrossPointsByPoint = function getBBoxCrossPointsByPoint(bbox, point) {
|
||
return getBBoxXCrossPoints(bbox, point.x).concat(getBBoxYCrossPoints(bbox, point.y));
|
||
};
|
||
/**
|
||
* 曼哈顿距离
|
||
*/
|
||
var distance = exports.distance = function distance(p1, p2) {
|
||
return Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y);
|
||
};
|
||
/**
|
||
* 如果 points 中的一个节点 x 与 p 相等,则消耗 -2。y 同
|
||
* 即优先选择和 points 在同一水平线 / 垂直线上的点
|
||
*/
|
||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||
var _costByPoints = exports._costByPoints = function _costByPoints(p, points) {
|
||
var offset = -2;
|
||
var result = 0;
|
||
points.forEach(function (point) {
|
||
if (point) {
|
||
if (p.x === point.x) {
|
||
result += offset;
|
||
}
|
||
if (p.y === point.y) {
|
||
result += offset;
|
||
}
|
||
}
|
||
});
|
||
return result;
|
||
};
|
||
/**
|
||
* ps 经过 p 到 pt 的距离,减去其他路过节点造成的消耗
|
||
*/
|
||
var heuristicCostEstimate = exports.heuristicCostEstimate = function heuristicCostEstimate(p, ps, pt, source, target) {
|
||
return distance(p, ps) + distance(p, pt) + _costByPoints(p, [ps, pt, source, target]);
|
||
};
|
||
var _reconstructPath = exports.reconstructPath = function reconstructPath(pathPoints, pointById, cameFrom, currentId, iterator) {
|
||
if (iterator === void 0) {
|
||
iterator = 0;
|
||
}
|
||
pathPoints.unshift(pointById[currentId]);
|
||
if (cameFrom[currentId] && cameFrom[currentId] !== currentId && iterator <= 100) {
|
||
_reconstructPath(pathPoints, pointById, cameFrom, cameFrom[currentId], iterator + 1);
|
||
}
|
||
};
|
||
/**
|
||
* 从 arr 中删去 item
|
||
*/
|
||
var removeFrom = exports.removeFrom = function removeFrom(arr, item) {
|
||
var index = arr.indexOf(item);
|
||
if (index > -1) {
|
||
arr.splice(index, 1);
|
||
}
|
||
};
|
||
var isSegmentsIntersected = exports.isSegmentsIntersected = function isSegmentsIntersected(p0, p1, p2, p3) {
|
||
var v1x = p2.x - p0.x;
|
||
var v1y = p2.y - p0.y;
|
||
var v2x = p3.x - p0.x;
|
||
var v2y = p3.y - p0.y;
|
||
var v3x = p2.x - p1.x;
|
||
var v3y = p2.y - p1.y;
|
||
var v4x = p3.x - p1.x;
|
||
var v4y = p3.y - p1.y;
|
||
var pd1 = v1x * v2y - v1y * v2x;
|
||
var pd2 = v3x * v4y - v3y * v4x;
|
||
var pd3 = v1x * v3y - v1y * v3x;
|
||
var pd4 = v2x * v4y - v2y * v4x;
|
||
return pd1 * pd2 <= 0 && pd3 * pd4 <= 0;
|
||
};
|
||
var isSegmentCrossingBBox = exports.isSegmentCrossingBBox = function isSegmentCrossingBBox(p1, p2, bbox) {
|
||
if (bbox.width || bbox.height) {
|
||
var _a = getPointsFromBBox(bbox),
|
||
pa = _a[0],
|
||
pb = _a[1],
|
||
pc = _a[2],
|
||
pd = _a[3];
|
||
return isSegmentsIntersected(p1, p2, pa, pb) || isSegmentsIntersected(p1, p2, pa, pd) || isSegmentsIntersected(p1, p2, pb, pc) || isSegmentsIntersected(p1, p2, pc, pd);
|
||
}
|
||
return false;
|
||
};
|
||
/**
|
||
* 在 points 中找到满足 x 或 y 和 point 的 x 或 y 相等,且与 point 连线不经过 bbox1 与 bbox2 的点
|
||
*/
|
||
var getNeighborPoints = exports.getNeighborPoints = function getNeighborPoints(points, point, bbox1, bbox2) {
|
||
var neighbors = [];
|
||
points.forEach(function (p) {
|
||
if (p === point) return;
|
||
if (p.x === point.x || p.y === point.y) {
|
||
if (isSegmentCrossingBBox(p, point, bbox1) || isSegmentCrossingBBox(p, point, bbox2)) return;
|
||
neighbors.push(p);
|
||
}
|
||
});
|
||
return filterConnectPoints(neighbors);
|
||
};
|
||
/**
|
||
* sorted array ascendly
|
||
* add new item to proper index when calling add
|
||
*/
|
||
var SortedArray = exports.SortedArray = /** @class */function () {
|
||
function SortedArray() {
|
||
this.arr = [];
|
||
this.map = {};
|
||
this.arr = [];
|
||
this.map = {};
|
||
}
|
||
SortedArray.prototype._innerAdd = function (item, length) {
|
||
var idxRange = [0, length - 1];
|
||
while (idxRange[1] - idxRange[0] > 1) {
|
||
var midIdx = Math.floor((idxRange[0] + idxRange[1]) / 2);
|
||
if (this.arr[midIdx].value > item.value) {
|
||
idxRange[1] = midIdx;
|
||
} else if (this.arr[midIdx].value < item.value) {
|
||
idxRange[0] = midIdx;
|
||
} else {
|
||
this.arr.splice(midIdx, 0, item);
|
||
this.map[item.id] = true;
|
||
return;
|
||
}
|
||
}
|
||
this.arr.splice(idxRange[1], 0, item);
|
||
this.map[item.id] = true;
|
||
};
|
||
SortedArray.prototype.add = function (item) {
|
||
// 已经存在,先移除
|
||
delete this.map[item.id];
|
||
var length = this.arr.length;
|
||
if (!length) {
|
||
this.arr.push(item);
|
||
this.map[item.id] = true;
|
||
return;
|
||
}
|
||
// 比最后一个大,加入尾部
|
||
if (this.arr[length - 1].value < item.value) {
|
||
this.arr.push(item);
|
||
this.map[item.id] = true;
|
||
return;
|
||
}
|
||
this._innerAdd(item, length);
|
||
};
|
||
// only remove from the map to avoid cost
|
||
// clear the invalid (not in the map) item when calling minId(true)
|
||
SortedArray.prototype.remove = function (id) {
|
||
if (!this.map[id]) return;
|
||
delete this.map[id];
|
||
};
|
||
SortedArray.prototype._clearAndGetMinId = function () {
|
||
var res;
|
||
for (var i = this.arr.length - 1; i >= 0; i--) {
|
||
if (this.map[this.arr[i].id]) res = this.arr[i].id;else this.arr.splice(i, 1);
|
||
}
|
||
return res;
|
||
};
|
||
SortedArray.prototype._findFirstId = function () {
|
||
while (this.arr.length) {
|
||
var first = this.arr.shift();
|
||
if (this.map[first.id]) return first.id;
|
||
}
|
||
};
|
||
SortedArray.prototype.minId = function (clear) {
|
||
if (clear) {
|
||
return this._clearAndGetMinId();
|
||
} else {
|
||
return this._findFirstId();
|
||
}
|
||
};
|
||
return SortedArray;
|
||
}();
|
||
var pathFinder = exports.pathFinder = function pathFinder(points, start, goal, sBBox, tBBox, os, ot) {
|
||
var _a;
|
||
// A-Star Algorithm
|
||
var closedSet = [];
|
||
var openSet = (_a = {}, _a[start.id] = start, _a);
|
||
var cameFrom = {};
|
||
var gScore = {}; // all default values are Infinity
|
||
var fScore = {}; // all default values are Infinity
|
||
gScore[start.id] = 0;
|
||
fScore[start.id] = heuristicCostEstimate(start, goal, start);
|
||
var sortedOpenSet = new SortedArray();
|
||
sortedOpenSet.add({
|
||
id: start.id,
|
||
value: fScore[start.id]
|
||
});
|
||
var pointById = {};
|
||
points.forEach(function (p) {
|
||
pointById[p.id] = p;
|
||
});
|
||
var current;
|
||
while (Object.keys(openSet).length) {
|
||
var minId = sortedOpenSet.minId(false);
|
||
if (minId) {
|
||
current = openSet[minId];
|
||
} else {
|
||
break;
|
||
}
|
||
// 若 openSet 中 fScore 最小的点就是终点
|
||
if (current === goal) {
|
||
// ending condition
|
||
var pathPoints = [];
|
||
_reconstructPath(pathPoints, pointById, cameFrom, goal.id);
|
||
return pathPoints;
|
||
}
|
||
delete openSet[current.id];
|
||
sortedOpenSet.remove(current.id);
|
||
closedSet.push(current);
|
||
var neighborPoints = getNeighborPoints(points, current, sBBox, tBBox);
|
||
var iterateNeighbors = function iterateNeighbors(items) {
|
||
items.forEach(function (neighbor) {
|
||
if (closedSet.indexOf(neighbor) !== -1) {
|
||
return;
|
||
}
|
||
var neighborId = neighbor.id;
|
||
if (!openSet[neighborId]) {
|
||
openSet[neighborId] = neighbor;
|
||
}
|
||
var tentativeGScore = fScore[current.id] + distance(current, neighbor); // + distance(neighbor, goal);
|
||
if (gScore[neighborId] && tentativeGScore >= gScore[neighborId]) {
|
||
sortedOpenSet.add({
|
||
id: neighborId,
|
||
value: fScore[neighborId]
|
||
});
|
||
return;
|
||
}
|
||
cameFrom[neighborId] = current.id;
|
||
gScore[neighborId] = tentativeGScore;
|
||
fScore[neighborId] = gScore[neighborId] + heuristicCostEstimate(neighbor, goal, start, os, ot);
|
||
sortedOpenSet.add({
|
||
id: neighborId,
|
||
value: fScore[neighborId]
|
||
});
|
||
});
|
||
};
|
||
iterateNeighbors(neighborPoints);
|
||
}
|
||
// throw new Error('Cannot find path');
|
||
return [start, goal];
|
||
};
|
||
var isBending = exports.isBending = function isBending(p0, p1, p2) {
|
||
return !(p0.x === p1.x && p1.x === p2.x || p0.y === p1.y && p1.y === p2.y);
|
||
};
|
||
var getBorderRadiusPoints = exports.getBorderRadiusPoints = function getBorderRadiusPoints(p0, p1, p2, r) {
|
||
var d0 = distance(p0, p1);
|
||
var d1 = distance(p2, p1);
|
||
if (d0 < r) {
|
||
r = d0;
|
||
}
|
||
if (d1 < r) {
|
||
r = d1;
|
||
}
|
||
var ps = {
|
||
x: p1.x - r / d0 * (p1.x - p0.x),
|
||
y: p1.y - r / d0 * (p1.y - p0.y)
|
||
};
|
||
var pt = {
|
||
x: p1.x - r / d1 * (p1.x - p2.x),
|
||
y: p1.y - r / d1 * (p1.y - p2.y)
|
||
};
|
||
return [ps, pt];
|
||
};
|
||
var getPathWithBorderRadiusByPolyline = exports.getPathWithBorderRadiusByPolyline = function getPathWithBorderRadiusByPolyline(points, borderRadius) {
|
||
var pathSegments = [];
|
||
var startPoint = points[0];
|
||
pathSegments.push("M".concat(startPoint.x, " ").concat(startPoint.y));
|
||
points.forEach(function (p, i) {
|
||
var p1 = points[i + 1];
|
||
var p2 = points[i + 2];
|
||
if (p1 && p2) {
|
||
if (isBending(p, p1, p2)) {
|
||
var _a = getBorderRadiusPoints(p, p1, p2, borderRadius),
|
||
ps = _a[0],
|
||
pt = _a[1];
|
||
pathSegments.push("L".concat(ps.x, " ").concat(ps.y));
|
||
pathSegments.push("Q".concat(p1.x, " ").concat(p1.y, " ").concat(pt.x, " ").concat(pt.y));
|
||
pathSegments.push("L".concat(pt.x, " ").concat(pt.y));
|
||
} else {
|
||
pathSegments.push("L".concat(p1.x, " ").concat(p1.y));
|
||
}
|
||
} else if (p1) {
|
||
pathSegments.push("L".concat(p1.x, " ").concat(p1.y));
|
||
}
|
||
});
|
||
return pathSegments.join('');
|
||
};
|
||
var getPolylinePoints = exports.getPolylinePoints = function getPolylinePoints(start, end, sNode, tNode, offset) {
|
||
var sBBox, tBBox;
|
||
if (!sNode || !sNode.getType()) {
|
||
sBBox = getBBoxFromPoint(start);
|
||
} else if (sNode.getType() === 'combo') {
|
||
var sKeyShapeBBox = sNode.getKeyShape().getBBox();
|
||
if (sKeyShapeBBox) {
|
||
var _a = sNode.getModel(),
|
||
sx = _a.x,
|
||
sy = _a.y;
|
||
sBBox = {
|
||
x: sx,
|
||
y: sy,
|
||
width: sKeyShapeBBox.width,
|
||
height: sKeyShapeBBox.height,
|
||
minX: sKeyShapeBBox.minX + sx,
|
||
maxX: sKeyShapeBBox.maxX + sx,
|
||
minY: sKeyShapeBBox.minY + sy,
|
||
maxY: sKeyShapeBBox.maxY + sy
|
||
};
|
||
sBBox.centerX = (sBBox.minX + sBBox.maxX) / 2;
|
||
sBBox.centerY = (sBBox.minY + sBBox.maxY) / 2;
|
||
} else {
|
||
sBBox = getBBoxFromPoint(start);
|
||
}
|
||
} else {
|
||
sBBox = sNode && sNode.getBBox();
|
||
}
|
||
if (!tNode || !tNode.getType()) {
|
||
tBBox = getBBoxFromPoint(end);
|
||
} else if (tNode.getType() === 'combo') {
|
||
var tKeyShapeBBox = tNode.getKeyShape().getBBox();
|
||
if (tKeyShapeBBox) {
|
||
var _b = tNode.getModel(),
|
||
tx = _b.x,
|
||
ty = _b.y;
|
||
tBBox = {
|
||
x: tx,
|
||
y: ty,
|
||
width: tKeyShapeBBox.width,
|
||
height: tKeyShapeBBox.height,
|
||
minX: tKeyShapeBBox.minX + tx,
|
||
maxX: tKeyShapeBBox.maxX + tx,
|
||
minY: tKeyShapeBBox.minY + ty,
|
||
maxY: tKeyShapeBBox.maxY + ty
|
||
};
|
||
tBBox.centerX = (tBBox.minX + tBBox.maxX) / 2;
|
||
tBBox.centerY = (tBBox.minY + tBBox.maxY) / 2;
|
||
} else {
|
||
tBBox = getBBoxFromPoint(end);
|
||
}
|
||
} else {
|
||
tBBox = tNode && tNode.getBBox();
|
||
}
|
||
// if (isBBoxesOverlapping(sBBox, tBBox)) {
|
||
// // source and target nodes are overlapping
|
||
// return simplifyPolyline(getSimplePolyline(start, end));
|
||
// }
|
||
var sxBBox = getExpandedBBox(sBBox, offset);
|
||
var txBBox = getExpandedBBox(tBBox, offset);
|
||
// if (isBBoxesOverlapping(sxBBox, txBBox)) {
|
||
// // the expanded bounding boxes of source and target nodes are overlapping
|
||
// return simplifyPolyline(getSimplePolyline(start, end));
|
||
// }
|
||
var sPoint = getExpandedBBoxPoint(sxBBox, start, end);
|
||
var tPoint = getExpandedBBoxPoint(txBBox, end, start);
|
||
var lineBBox = getBBoxFromPoints([sPoint, tPoint]);
|
||
var sMixBBox = mergeBBox(sxBBox, lineBBox);
|
||
var tMixBBox = mergeBBox(txBBox, lineBBox);
|
||
var connectPoints = [];
|
||
connectPoints = connectPoints.concat(getPointsFromBBox(sMixBBox)).concat(getPointsFromBBox(tMixBBox));
|
||
var centerPoint = {
|
||
x: (start.x + end.x) / 2,
|
||
y: (start.y + end.y) / 2
|
||
};
|
||
[lineBBox, sMixBBox, tMixBBox].forEach(function (bbox) {
|
||
connectPoints = connectPoints.concat(getBBoxCrossPointsByPoint(bbox, centerPoint).filter(function (p) {
|
||
return isPointOutsideBBox(p, sxBBox) && isPointOutsideBBox(p, txBBox);
|
||
}));
|
||
});
|
||
[{
|
||
x: sPoint.x,
|
||
y: tPoint.y
|
||
}, {
|
||
x: tPoint.x,
|
||
y: sPoint.y
|
||
}].forEach(function (p) {
|
||
// impossible!!
|
||
if (isPointOutsideBBox(p, sxBBox) && isPointOutsideBBox(p, txBBox) // &&
|
||
// isPointInsideBBox(p, sMixBBox) && isPointInsideBBox(p, tMixBBox)
|
||
) {
|
||
connectPoints.push(p);
|
||
}
|
||
});
|
||
connectPoints.unshift(sPoint);
|
||
connectPoints.push(tPoint);
|
||
// filter out dulplicated points in connectPoints
|
||
connectPoints = filterConnectPoints(connectPoints); // , sxBBox, txBBox, outerBBox
|
||
var pathPoints = pathFinder(connectPoints, sPoint, tPoint, sBBox, tBBox, start, end);
|
||
pathPoints.unshift(start);
|
||
pathPoints.push(end);
|
||
return simplifyPolyline(pathPoints);
|
||
};
|
||
/**
|
||
* 去除连续同 x 不同 y 的中间点;去除连续同 y 不同 x 的中间点
|
||
* @param points 坐标集合 { x: number, y: number, id: string }[]
|
||
* @returns
|
||
*/
|
||
var removeRedundantPoint = exports.removeRedundantPoint = function removeRedundantPoint(points) {
|
||
if (!(points === null || points === void 0 ? void 0 : points.length)) return points;
|
||
var beginPoint = points[points.length - 1];
|
||
var current = {
|
||
x: beginPoint.x,
|
||
y: beginPoint.y
|
||
};
|
||
var continueSameX = [beginPoint];
|
||
var continueSameY = [beginPoint];
|
||
for (var i = points.length - 2; i >= 0; i--) {
|
||
var point = points[i];
|
||
if (point.x === current.x) {
|
||
continueSameX.push(point);
|
||
} else {
|
||
continueSameX = [point];
|
||
current.x = point.x;
|
||
}
|
||
if (point.y === current.y) {
|
||
continueSameY.push(point);
|
||
} else {
|
||
continueSameY = [point];
|
||
current.y = point.y;
|
||
}
|
||
if (continueSameX.length > 2) {
|
||
var removeIdx = points.indexOf(continueSameX[1]);
|
||
if (removeIdx > -1) points.splice(removeIdx, 1);
|
||
continue;
|
||
}
|
||
if (continueSameY.length > 2) {
|
||
var removeIdx = points.indexOf(continueSameY[1]);
|
||
if (removeIdx > -1) points.splice(removeIdx, 1);
|
||
}
|
||
}
|
||
return points;
|
||
}; |