NuclearDispersionSystem/ant-design-vue-jeecg/node_modules/@antv/component/lib/label/utils/simulate-anneal.js

188 lines
6.2 KiB
JavaScript
Raw Normal View History

2023-09-14 14:47:11 +08:00
function _createSuper(Derived) { return function () { var Super = _getPrototypeOf(Derived), result; if (_isNativeReflectConstruct()) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (typeof call === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
var Base = require('../../base');
var SimulateAnneal = /*#__PURE__*/function (_Base) {
_inheritsLoose(SimulateAnneal, _Base);
var _super = _createSuper(SimulateAnneal);
function SimulateAnneal() {
return _Base.apply(this, arguments) || this;
}
var _proto = SimulateAnneal.prototype;
_proto.getDefaultCfg = function getDefaultCfg() {
return {
// 最大移动距离
maxMove: 5,
// 线长的权重
lineLength: 0.2,
// 线碰撞权重
intersect: 1,
// 标签与标签碰撞权重
labelToLabel: 30,
// 标签与别的shape碰撞权重
labelToShape: 30,
// 标签偏移
orient: 3,
// 迭代次数
iteration: 200,
// 退火阈值
threshold: 0.1
};
} // 简单的图形碰撞检测
;
_proto._intersect = function _intersect(x1, x2, x3, x4, y1, y2, y3, y4) {
var denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
var numera = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
var numerb = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
var mua = numera / denom;
var mub = numerb / denom;
if (!(mua < 0 || mua > 1 || mub < 0 || mub > 1)) {
return true;
}
return false;
} // 计算重排一个label后的能量值
;
_proto.energy = function energy(index) {
var self = this;
var labels = self.get('labels');
var shapes = self.get('shapes');
var labelLen = labels.length;
var label = labels[index];
var shape = shapes[index];
var bbox = label.getBBox();
var energy = 0;
var dx = labels[index].attr('x') - shapes[index].attr('x');
var dy = labels[index].attr('y') - shapes[index].attr('y');
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
energy += dist * self.get('lineLength');
}
dx /= dist;
dy /= dist;
if (dx > 0 && dy > 0) {
energy += 0;
} else if (dx < 0 && dy > 0) {
energy += self.get('orient');
} else if (dx < 0 && dy < 0) {
energy += self.get('orient') * 2;
} else {
energy += self.get('orient') * 3;
}
var overlap, overlapX, overlapY, temp, tempBBox, tempShape, tempShapeBBox;
for (var i = 0; i < labelLen; i++) {
temp = labels[i];
tempBBox = temp.getBBox();
tempShape = shapes[i];
tempShapeBBox = tempShape.getBBox(); // 标签与标签碰撞增加能量
if (i !== index) {
overlap = self._intersect(shape.attr('x'), label.attr('x'), tempShape.attr('x'), temp.attr('x'), shape.attr('y'), label.attr('y'), tempShape.attr('y'), temp.attr('y'));
if (overlap) {
energy += self.get('intersect');
}
overlapX = Math.max(0, Math.min(tempBBox.maxX, bbox.maxX) - Math.max(tempBBox.minX, bbox.minX));
overlapY = Math.max(0, Math.min(tempBBox.maxY, bbox.maxY) - Math.max(tempBBox.minY, bbox.minY));
energy += overlapX * overlapY * self.get('labelToLabel');
} // 标签与shape碰撞能量
overlapX = Math.max(0, Math.min(tempShapeBBox.maxX, bbox.maxX) - Math.max(tempShapeBBox.minX, bbox.minX));
overlapY = Math.max(0, Math.min(tempShapeBBox.maxY, bbox.maxY) - Math.max(tempShapeBBox.minY, bbox.minY));
energy += overlapX * overlapY * self.get('labelToShape');
}
return energy;
} // 蒙特卡罗模拟位移
;
_proto.move = function move(current) {
var self = this;
var labels = this.get('labels');
var random = Math.floor(Math.random() * labels.length);
var label = labels[random];
var origin = {
x: labels[random].attr('x'),
y: labels[random].attr('y')
};
var originEnergy = self.energy(random);
var moveX = label.attr('x') + (Math.random() - 0.5) * self.get('maxMove');
if (moveX < 0) {
moveX = origin.x;
}
var moveY = label.attr('y') + (Math.random() - 0.5) * self.get('maxMove');
if (moveY < 0) {
moveY = origin.y;
}
label.attr({
x: moveX,
y: moveY
});
var newEnergy = self.energy(random);
var d = newEnergy - originEnergy;
if (Math.random() > Math.exp(-d / current)) {
label.attr({
x: origin.x,
y: origin.y
});
}
};
_proto.cooling = function cooling(current, init, iterate) {
return current - init / iterate;
};
_proto.adjust = function adjust(labels, shapes) {
var self = this;
var iteration = self.get('iteration');
self.set('labels', labels);
self.set('shapes', shapes);
var initTime = 1;
var currentTime = 1;
for (var i = 0; i < iteration; i++) {
for (var j = 0; j < labels.length; j++) {
self.move(currentTime);
}
currentTime = self.cooling(currentTime, initTime, iteration);
if (currentTime < self.get('threshold')) {
break;
}
}
};
return SimulateAnneal;
}(Base);
module.exports = SimulateAnneal;