NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/component/lib/label/utils/visual-center.js
2023-09-14 14:47:11 +08:00

165 lines
3.4 KiB
JavaScript

var SQRT = Math.SQRT2;
function getCell(x, y, h, points) {
var d = _calcDist(x, y, points);
return {
x: x,
y: y,
h: h,
d: d,
max: d + h * SQRT
};
}
function getCentroidCell(polygon) {
var area = 0;
var x = 0;
var y = 0;
var a, b, f;
var points = polygon[0];
for (var i = 0, len = points.length, j = len - 1; i < len; j = i++) {
a = points[i];
b = points[j];
f = a[0] * b[1] - b[0] * a[1];
x += (a[0] + b[0]) * f;
y += (a[1] + b[1]) * f;
area += f * 3;
}
if (area === 0) return getCell(points[0][0], points[0][1], 0, polygon);
return getCell(x / area, y / area, 0, polygon);
}
function _segmentDist(px, py, a, b) {
var x = a[0],
y = a[1],
dx = b[0] - x,
dy = b[1] - y,
t;
if (dx !== 0 || dy !== 0) {
t = ((px - x) * dx + (py - y) * dy) / (dx * dx + dy * dy);
if (t > 1) {
x = b[0];
y = b[1];
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}
dx = px - x;
dy = py - y;
return dx * dx + dy * dy;
}
function _calcDist(x, y, points) {
var inside = false;
var minDist = Infinity;
var polygon, a, b, length;
for (var k = 0; k < points.length; k++) {
polygon = points[k];
length = polygon.length;
for (var i = 0, j = length - 1; i < length; j = i++) {
a = polygon[i];
b = polygon[j];
if (a[1] > y !== b[1] > y && x < (b[0] - a[0]) * (y - a[1]) / (b[1] - a[1]) + a[0]) {
inside = !inside;
}
minDist = Math.min(minDist, _segmentDist(x, y, a, b));
}
}
return (inside ? 1 : -1) * Math.sqrt(minDist);
}
/**
* 计算polygon视觉中心
* @param {Array} points polygon点数组
* @param {Object} bbox polygon的bbox
* @return {{x: *, y: *}} 返回视觉中心坐标
*/
module.exports = function visualCenter(points, bbox) {
if (!bbox) {
var minX = Infinity,
minY = Infinity,
maxX = -Infinity,
maxY = -Infinity,
p;
for (var i = 0; i < points[0].length; i++) {
p = points[0][i];
if (!i || p[0] < minX) minX = p[0];
if (!i || p[1] < minY) minY = p[1];
if (!i || p[0] > maxX) maxX = p[0];
if (!i || p[1] > maxY) maxY = p[1];
}
bbox = {
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY,
width: maxX - minX,
height: maxY - minY
};
}
var cellSize = Math.min(bbox.width, bbox.height);
var h = cellSize / 2;
var cellQueue = [];
var boxCenter = {
x: bbox.minX + bbox.width / 2,
y: bbox.minY + bbox.height / 2
};
if (cellSize === 0) {
return boxCenter;
}
for (var _i = bbox.minX; _i < bbox.maxX; _i += cellSize) {
for (var j = bbox.minY; j < bbox.maxY; j += cellSize) {
cellQueue.push(getCell(_i + h, j + h, h, points));
}
}
var best = getCentroidCell(points);
var boxCell = getCell(boxCenter.x, boxCenter.y, 0, points);
if (boxCell > best.d) {
best = boxCell;
}
var cell;
while (cellQueue.length) {
cell = cellQueue.pop();
if (cell.d > best.d) {
best = cell;
}
if (cell.max - best.d <= 1) {
continue;
}
h = cell.h / 2;
cellQueue.push(getCell(cell.x - h, cell.y - h, h, points));
cellQueue.push(getCell(cell.x + h, cell.y - h, h, points));
cellQueue.push(getCell(cell.x - h, cell.y + h, h, points));
cellQueue.push(getCell(cell.x + h, cell.y + h, h, points));
}
return {
x: best.x,
y: best.y
};
};