fix(modeling): correct label line attachments not being recognized
* remove rounding where it does not matter * work around some precision errors in logic * adjust test cases (to higher precision) Closes #669
This commit is contained in:
parent
84dc3b50e7
commit
7d896855a9
|
@ -2,7 +2,8 @@
|
|||
|
||||
var sqrt = Math.sqrt,
|
||||
min = Math.min,
|
||||
max = Math.max;
|
||||
max = Math.max,
|
||||
abs = Math.abs;
|
||||
|
||||
/**
|
||||
* Calculate the square (power to two) of a number.
|
||||
|
@ -136,12 +137,6 @@ module.exports.getAttachment = getAttachment;
|
|||
*/
|
||||
function getCircleSegmentIntersections(s1, s2, cc, cr) {
|
||||
|
||||
// silently round values
|
||||
s1 = roundPoint(s1);
|
||||
s2 = roundPoint(s2);
|
||||
cc = roundPoint(cc);
|
||||
cr = min(getDistance(s1, cc), getDistance(s2, cc));
|
||||
|
||||
var baX = s2.x - s1.x;
|
||||
var baY = s2.y - s1.y;
|
||||
var caX = cc.x - s1.x;
|
||||
|
@ -155,6 +150,12 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
|
|||
var q = c / a;
|
||||
|
||||
var disc = pBy2 * pBy2 - q;
|
||||
|
||||
// round disc to 10 digits to work around
|
||||
// negative, very close to zero results (-4e-15)
|
||||
// being produced in some environments
|
||||
disc = round(disc, 10);
|
||||
|
||||
if (disc < 0) {
|
||||
return [];
|
||||
}
|
||||
|
@ -165,8 +166,8 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
|
|||
var abScalingFactor2 = -pBy2 - tmpSqrt;
|
||||
|
||||
var i1 = {
|
||||
x: round(s1.x - baX * abScalingFactor1),
|
||||
y: round(s1.y - baY * abScalingFactor1)
|
||||
x: s1.x - baX * abScalingFactor1,
|
||||
y: s1.y - baY * abScalingFactor1
|
||||
};
|
||||
|
||||
if (disc === 0) { // abScalingFactor1 == abScalingFactor2
|
||||
|
@ -174,10 +175,11 @@ function getCircleSegmentIntersections(s1, s2, cc, cr) {
|
|||
}
|
||||
|
||||
var i2 = {
|
||||
x: round(s1.x - baX * abScalingFactor2),
|
||||
y: round(s1.y - baY * abScalingFactor2)
|
||||
x: s1.x - baX * abScalingFactor2,
|
||||
y: s1.y - baY * abScalingFactor2
|
||||
};
|
||||
|
||||
// return only points on line segment
|
||||
return [ i1, i2 ].filter(function(p) {
|
||||
return isPointInSegment(p, s1, s2);
|
||||
});
|
||||
|
@ -192,7 +194,14 @@ function isPointInSegment(p, segmentStart, segmentEnd) {
|
|||
}
|
||||
|
||||
function fenced(n, rangeStart, rangeEnd) {
|
||||
return min(rangeStart, rangeEnd) <= n && n <= max(rangeStart, rangeEnd);
|
||||
|
||||
// use matching threshold to work around
|
||||
// precisison errors in intersection computation
|
||||
|
||||
return (
|
||||
n >= min(rangeStart, rangeEnd) - EQUAL_THRESHOLD &&
|
||||
n <= max(rangeStart, rangeEnd) + EQUAL_THRESHOLD
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -211,23 +220,32 @@ function mid(p1, p2) {
|
|||
};
|
||||
}
|
||||
|
||||
function round(n) {
|
||||
return Math.round(n * 1000) / 1000;
|
||||
/**
|
||||
* Round number to precision
|
||||
*
|
||||
* @param {Number} number
|
||||
* @param {Integer} [precision=1]
|
||||
*
|
||||
* @return {Number}
|
||||
*/
|
||||
function round(number, precision) {
|
||||
|
||||
if (typeof precision === 'undefined') {
|
||||
return Math.round(number);
|
||||
}
|
||||
|
||||
var factor = Math.pow(10, precision);
|
||||
var tempNumber = number * factor;
|
||||
var roundedTempNumber = Math.round(tempNumber);
|
||||
return roundedTempNumber / factor;
|
||||
}
|
||||
|
||||
function roundPoint(p) {
|
||||
return {
|
||||
x: round(p.x),
|
||||
y: round(p.y)
|
||||
};
|
||||
}
|
||||
|
||||
var EQUAL_THRESHOLD = 0.2;
|
||||
var EQUAL_THRESHOLD = 0.1;
|
||||
|
||||
function pointsEqual(p1, p2) {
|
||||
|
||||
return (
|
||||
Math.abs(p1.x - p2.x) <= EQUAL_THRESHOLD &&
|
||||
Math.abs(p1.y - p2.y) <= EQUAL_THRESHOLD
|
||||
abs(p1.x - p2.x) <= EQUAL_THRESHOLD &&
|
||||
abs(p1.y - p2.y) <= EQUAL_THRESHOLD
|
||||
);
|
||||
}
|
||||
|
|
|
@ -232,14 +232,13 @@ describe('modeling/behavior/util - LineAttachmentUtil#getAttachment', function()
|
|||
var attachment = getAttachment({ x: 35.197169, y: 5.399375 }, floatingPointLine);
|
||||
|
||||
// then
|
||||
// expext values to be rounded to 3 decimal places
|
||||
expect(attachment).to.eql({
|
||||
type: 'bendpoint',
|
||||
position: { x: 30.793, y: 10.463 },
|
||||
bendpointIndex: 1,
|
||||
segmentIndex: 0
|
||||
});
|
||||
expect(attachment.type).to.equal('bendpoint');
|
||||
expect(attachment.segmentIndex).to.equal(1);
|
||||
expect(attachment.bendpointIndex).to.equal(1);
|
||||
|
||||
// expect values to be roughly equal
|
||||
expect(attachment.position.x).to.be.within(30.793 - EPSILON, 30.793 + EPSILON);
|
||||
expect(attachment.position.y).to.be.within(10.463 - EPSILON, 10.463 + EPSILON);
|
||||
});
|
||||
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue