chore: restructure LabelLayoutUtil
This commit is contained in:
parent
82c117b982
commit
9c357f4cbd
|
@ -1,95 +1,7 @@
|
||||||
import {
|
import { findNewLineStartIndex, getAnchorPointAdjustment } from './LayoutUtil';
|
||||||
getDistancePointPoint,
|
|
||||||
rotateVector,
|
|
||||||
getAngle
|
|
||||||
} from './GeometricUtil';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getAttachment
|
|
||||||
} from './LineAttachmentUtil';
|
|
||||||
|
|
||||||
import {
|
|
||||||
roundPoint
|
|
||||||
} from 'diagram-js/lib/layout/LayoutUtil';
|
|
||||||
|
|
||||||
|
|
||||||
export function findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints) {
|
export function findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints) {
|
||||||
|
return findNewLineStartIndex(oldWaypoints, newWaypoints, attachment, hints);
|
||||||
var index = attachment.segmentIndex;
|
|
||||||
|
|
||||||
var offset = newWaypoints.length - oldWaypoints.length;
|
|
||||||
|
|
||||||
// segmentMove happened
|
|
||||||
if (hints.segmentMove) {
|
|
||||||
|
|
||||||
var oldSegmentStartIndex = hints.segmentMove.segmentStartIndex,
|
|
||||||
newSegmentStartIndex = hints.segmentMove.newSegmentStartIndex;
|
|
||||||
|
|
||||||
// if label was on moved segment return new segment index
|
|
||||||
if (index === oldSegmentStartIndex) {
|
|
||||||
return newSegmentStartIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// label is after new segment index
|
|
||||||
if (index >= newSegmentStartIndex) {
|
|
||||||
return (index+offset < newSegmentStartIndex) ? newSegmentStartIndex : index+offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if label is before new segment index
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// bendpointMove happened
|
|
||||||
if (hints.bendpointMove) {
|
|
||||||
|
|
||||||
var insert = hints.bendpointMove.insert,
|
|
||||||
bendpointIndex = hints.bendpointMove.bendpointIndex,
|
|
||||||
newIndex;
|
|
||||||
|
|
||||||
// waypoints length didnt change
|
|
||||||
if (offset === 0) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
// label behind new/removed bendpoint
|
|
||||||
if (index >= bendpointIndex) {
|
|
||||||
newIndex = insert ? index + 1 : index - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// label before new/removed bendpoint
|
|
||||||
if (index < bendpointIndex) {
|
|
||||||
|
|
||||||
newIndex = index;
|
|
||||||
|
|
||||||
// decide label should take right or left segment
|
|
||||||
if (insert && attachment.type !== 'bendpoint' && bendpointIndex-1 === index) {
|
|
||||||
|
|
||||||
var rel = relativePositionMidWaypoint(newWaypoints, bendpointIndex);
|
|
||||||
|
|
||||||
if (rel < attachment.relativeLocation) {
|
|
||||||
newIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
// start/end changed
|
|
||||||
if (offset === 0) {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hints.connectionStart) {
|
|
||||||
return (index === 0) ? 0 : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hints.connectionEnd) {
|
|
||||||
return (index === oldWaypoints.length - 2) ? newWaypoints.length - 2 : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if nothing fits, return null
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,118 +17,17 @@ export function findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachmen
|
||||||
* @return {Point} delta
|
* @return {Point} delta
|
||||||
*/
|
*/
|
||||||
export function getLabelAdjustment(label, newWaypoints, oldWaypoints, hints) {
|
export function getLabelAdjustment(label, newWaypoints, oldWaypoints, hints) {
|
||||||
|
|
||||||
var x = 0,
|
|
||||||
y = 0;
|
|
||||||
|
|
||||||
var labelPosition = getLabelMid(label);
|
var labelPosition = getLabelMid(label);
|
||||||
|
|
||||||
// get closest attachment
|
return getAnchorPointAdjustment(labelPosition, newWaypoints, oldWaypoints, hints).delta;
|
||||||
var attachment = getAttachment(labelPosition, oldWaypoints),
|
|
||||||
oldLabelLineIndex = attachment.segmentIndex,
|
|
||||||
newLabelLineIndex = findNewLabelLineStartIndex(oldWaypoints, newWaypoints, attachment, hints);
|
|
||||||
|
|
||||||
if (newLabelLineIndex === null) {
|
|
||||||
return { x: x, y: y };
|
|
||||||
}
|
|
||||||
|
|
||||||
// should never happen
|
|
||||||
// TODO(@janstuemmel): throw an error here when connectionSegmentMove is refactored
|
|
||||||
if (newLabelLineIndex < 0 ||
|
|
||||||
newLabelLineIndex > newWaypoints.length - 2) {
|
|
||||||
return { x: x, y: y };
|
|
||||||
}
|
|
||||||
|
|
||||||
var oldLabelLine = getLine(oldWaypoints, oldLabelLineIndex),
|
|
||||||
newLabelLine = getLine(newWaypoints, newLabelLineIndex),
|
|
||||||
oldFoot = attachment.position;
|
|
||||||
|
|
||||||
var relativeFootPosition = getRelativeFootPosition(oldLabelLine, oldFoot),
|
|
||||||
angleDelta = getAngleDelta(oldLabelLine, newLabelLine);
|
|
||||||
|
|
||||||
// special rule if label on bendpoint
|
|
||||||
if (attachment.type === 'bendpoint') {
|
|
||||||
|
|
||||||
var offset = newWaypoints.length - oldWaypoints.length,
|
|
||||||
oldBendpointIndex = attachment.bendpointIndex,
|
|
||||||
oldBendpoint = oldWaypoints[oldBendpointIndex];
|
|
||||||
|
|
||||||
// bendpoint position hasn't changed, return same position
|
|
||||||
if (newWaypoints.indexOf(oldBendpoint) !== -1) {
|
|
||||||
return { x: x, y: y };
|
|
||||||
}
|
|
||||||
|
|
||||||
// new bendpoint and old bendpoint have same index, then just return the offset
|
|
||||||
if (offset === 0) {
|
|
||||||
var newBendpoint = newWaypoints[oldBendpointIndex];
|
|
||||||
|
|
||||||
return {
|
|
||||||
x: newBendpoint.x - attachment.position.x,
|
|
||||||
y: newBendpoint.y - attachment.position.y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// if bendpoints get removed
|
|
||||||
if (offset < 0 && oldBendpointIndex !== 0 && oldBendpointIndex < oldWaypoints.length - 1) {
|
|
||||||
relativeFootPosition = relativePositionMidWaypoint(oldWaypoints, oldBendpointIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newFoot = {
|
|
||||||
x: (newLabelLine[1].x - newLabelLine[0].x) * relativeFootPosition + newLabelLine[0].x,
|
|
||||||
y: (newLabelLine[1].y - newLabelLine[0].y) * relativeFootPosition + newLabelLine[0].y
|
|
||||||
};
|
|
||||||
|
|
||||||
// the rotated vector to label
|
|
||||||
var newLabelVector = rotateVector({
|
|
||||||
x: labelPosition.x - oldFoot.x,
|
|
||||||
y: labelPosition.y - oldFoot.y
|
|
||||||
}, angleDelta);
|
|
||||||
|
|
||||||
// the new relative position
|
|
||||||
x = newFoot.x + newLabelVector.x - labelPosition.x;
|
|
||||||
y = newFoot.y + newLabelVector.y - labelPosition.y;
|
|
||||||
|
|
||||||
return roundPoint({
|
|
||||||
x: x,
|
|
||||||
y: y
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// HELPERS //////////////////////
|
// HELPERS //////////////////////
|
||||||
|
|
||||||
function relativePositionMidWaypoint(waypoints, idx) {
|
|
||||||
|
|
||||||
var distanceSegment1 = getDistancePointPoint(waypoints[idx-1], waypoints[idx]),
|
|
||||||
distanceSegment2 = getDistancePointPoint(waypoints[idx], waypoints[idx+1]);
|
|
||||||
|
|
||||||
var relativePosition = distanceSegment1 / (distanceSegment1 + distanceSegment2);
|
|
||||||
|
|
||||||
return relativePosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLabelMid(label) {
|
function getLabelMid(label) {
|
||||||
return {
|
return {
|
||||||
x: label.x + label.width / 2,
|
x: label.x + label.width / 2,
|
||||||
y: label.y + label.height / 2
|
y: label.y + label.height / 2
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAngleDelta(l1, l2) {
|
|
||||||
var a1 = getAngle(l1),
|
|
||||||
a2 = getAngle(l2);
|
|
||||||
return a2 - a1;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getLine(waypoints, idx) {
|
|
||||||
return [ waypoints[idx], waypoints[idx+1] ];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getRelativeFootPosition(line, foot) {
|
|
||||||
|
|
||||||
var length = getDistancePointPoint(line[0], line[1]),
|
|
||||||
lengthToFoot = getDistancePointPoint(line[0], foot);
|
|
||||||
|
|
||||||
return length === 0 ? 0 : lengthToFoot / length;
|
|
||||||
}
|
|
||||||
|
|
|
@ -0,0 +1,233 @@
|
||||||
|
import {
|
||||||
|
getDistancePointPoint,
|
||||||
|
rotateVector,
|
||||||
|
getAngle
|
||||||
|
} from './GeometricUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getAttachment
|
||||||
|
} from './LineAttachmentUtil';
|
||||||
|
|
||||||
|
import {
|
||||||
|
roundPoint
|
||||||
|
} from 'diagram-js/lib/layout/LayoutUtil';
|
||||||
|
|
||||||
|
|
||||||
|
export function findNewLineStartIndex(oldWaypoints, newWaypoints, attachment, hints) {
|
||||||
|
|
||||||
|
var index = attachment.segmentIndex;
|
||||||
|
|
||||||
|
var offset = newWaypoints.length - oldWaypoints.length;
|
||||||
|
|
||||||
|
// segmentMove happened
|
||||||
|
if (hints.segmentMove) {
|
||||||
|
|
||||||
|
var oldSegmentStartIndex = hints.segmentMove.segmentStartIndex,
|
||||||
|
newSegmentStartIndex = hints.segmentMove.newSegmentStartIndex;
|
||||||
|
|
||||||
|
// if point was on moved segment return new segment index
|
||||||
|
if (index === oldSegmentStartIndex) {
|
||||||
|
return newSegmentStartIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// point is after new segment index
|
||||||
|
if (index >= newSegmentStartIndex) {
|
||||||
|
return (index+offset < newSegmentStartIndex) ? newSegmentStartIndex : index+offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if point is before new segment index
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// bendpointMove happened
|
||||||
|
if (hints.bendpointMove) {
|
||||||
|
|
||||||
|
var insert = hints.bendpointMove.insert,
|
||||||
|
bendpointIndex = hints.bendpointMove.bendpointIndex,
|
||||||
|
newIndex;
|
||||||
|
|
||||||
|
// waypoints length didnt change
|
||||||
|
if (offset === 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
// point behind new/removed bendpoint
|
||||||
|
if (index >= bendpointIndex) {
|
||||||
|
newIndex = insert ? index + 1 : index - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// point before new/removed bendpoint
|
||||||
|
if (index < bendpointIndex) {
|
||||||
|
|
||||||
|
newIndex = index;
|
||||||
|
|
||||||
|
// decide point should take right or left segment
|
||||||
|
if (insert && attachment.type !== 'bendpoint' && bendpointIndex-1 === index) {
|
||||||
|
|
||||||
|
var rel = relativePositionMidWaypoint(newWaypoints, bendpointIndex);
|
||||||
|
|
||||||
|
if (rel < attachment.relativeLocation) {
|
||||||
|
newIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// start/end changed
|
||||||
|
if (offset === 0) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hints.connectionStart) {
|
||||||
|
return (index === 0) ? 0 : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hints.connectionEnd) {
|
||||||
|
return (index === oldWaypoints.length - 2) ? newWaypoints.length - 2 : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if nothing fits, return null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the required adjustment (move delta) for the given point
|
||||||
|
* after the connection waypoints got updated.
|
||||||
|
*
|
||||||
|
* @param {Point} position
|
||||||
|
* @param {Array<Point>} newWaypoints
|
||||||
|
* @param {Array<Point>} oldWaypoints
|
||||||
|
* @param {Object} hints
|
||||||
|
*
|
||||||
|
* @return {Object} result
|
||||||
|
* @return {Point} result.point
|
||||||
|
* @return {Point} result.delta
|
||||||
|
*/
|
||||||
|
export function getAnchorPointAdjustment(position, newWaypoints, oldWaypoints, hints) {
|
||||||
|
|
||||||
|
var dx = 0,
|
||||||
|
dy = 0;
|
||||||
|
|
||||||
|
var oldPosition = {
|
||||||
|
point: position,
|
||||||
|
delta: { x: 0, y: 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// get closest attachment
|
||||||
|
var attachment = getAttachment(position, oldWaypoints),
|
||||||
|
oldLabelLineIndex = attachment.segmentIndex,
|
||||||
|
newLabelLineIndex = findNewLineStartIndex(oldWaypoints, newWaypoints, attachment, hints);
|
||||||
|
|
||||||
|
if (newLabelLineIndex === null) {
|
||||||
|
return oldPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// should never happen
|
||||||
|
// TODO(@janstuemmel): throw an error here when connectionSegmentMove is refactored
|
||||||
|
if (newLabelLineIndex < 0 ||
|
||||||
|
newLabelLineIndex > newWaypoints.length - 2) {
|
||||||
|
|
||||||
|
return oldPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
var oldLabelLine = getLine(oldWaypoints, oldLabelLineIndex),
|
||||||
|
newLabelLine = getLine(newWaypoints, newLabelLineIndex),
|
||||||
|
oldFoot = attachment.position;
|
||||||
|
|
||||||
|
var relativeFootPosition = getRelativeFootPosition(oldLabelLine, oldFoot),
|
||||||
|
angleDelta = getAngleDelta(oldLabelLine, newLabelLine);
|
||||||
|
|
||||||
|
// special rule if label on bendpoint
|
||||||
|
if (attachment.type === 'bendpoint') {
|
||||||
|
|
||||||
|
var offset = newWaypoints.length - oldWaypoints.length,
|
||||||
|
oldBendpointIndex = attachment.bendpointIndex,
|
||||||
|
oldBendpoint = oldWaypoints[oldBendpointIndex];
|
||||||
|
|
||||||
|
// bendpoint position hasn't changed, return same position
|
||||||
|
if (newWaypoints.indexOf(oldBendpoint) !== -1) {
|
||||||
|
return oldPosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new bendpoint and old bendpoint have same index, then just return the offset
|
||||||
|
if (offset === 0) {
|
||||||
|
var newBendpoint = newWaypoints[oldBendpointIndex];
|
||||||
|
|
||||||
|
dx = newBendpoint.x - attachment.position.x,
|
||||||
|
dy = newBendpoint.y - attachment.position.y;
|
||||||
|
|
||||||
|
return {
|
||||||
|
delta: {
|
||||||
|
x: dx,
|
||||||
|
y: dy
|
||||||
|
},
|
||||||
|
point: {
|
||||||
|
x: position.x + dx,
|
||||||
|
y: position.y + dy
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// if bendpoints get removed
|
||||||
|
if (offset < 0 && oldBendpointIndex !== 0 && oldBendpointIndex < oldWaypoints.length - 1) {
|
||||||
|
relativeFootPosition = relativePositionMidWaypoint(oldWaypoints, oldBendpointIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var newFoot = {
|
||||||
|
x: (newLabelLine[1].x - newLabelLine[0].x) * relativeFootPosition + newLabelLine[0].x,
|
||||||
|
y: (newLabelLine[1].y - newLabelLine[0].y) * relativeFootPosition + newLabelLine[0].y
|
||||||
|
};
|
||||||
|
|
||||||
|
// the rotated vector to label
|
||||||
|
var newLabelVector = rotateVector({
|
||||||
|
x: position.x - oldFoot.x,
|
||||||
|
y: position.y - oldFoot.y
|
||||||
|
}, angleDelta);
|
||||||
|
|
||||||
|
// the new relative position
|
||||||
|
dx = newFoot.x + newLabelVector.x - position.x;
|
||||||
|
dy = newFoot.y + newLabelVector.y - position.y;
|
||||||
|
|
||||||
|
return {
|
||||||
|
point: roundPoint(newFoot),
|
||||||
|
delta: roundPoint({
|
||||||
|
x: dx,
|
||||||
|
y: dy
|
||||||
|
})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// HELPERS //////////////////////
|
||||||
|
|
||||||
|
function relativePositionMidWaypoint(waypoints, idx) {
|
||||||
|
|
||||||
|
var distanceSegment1 = getDistancePointPoint(waypoints[idx-1], waypoints[idx]),
|
||||||
|
distanceSegment2 = getDistancePointPoint(waypoints[idx], waypoints[idx+1]);
|
||||||
|
|
||||||
|
var relativePosition = distanceSegment1 / (distanceSegment1 + distanceSegment2);
|
||||||
|
|
||||||
|
return relativePosition;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAngleDelta(l1, l2) {
|
||||||
|
var a1 = getAngle(l1),
|
||||||
|
a2 = getAngle(l2);
|
||||||
|
return a2 - a1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLine(waypoints, idx) {
|
||||||
|
return [ waypoints[idx], waypoints[idx+1] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRelativeFootPosition(line, foot) {
|
||||||
|
|
||||||
|
var length = getDistancePointPoint(line[0], line[1]),
|
||||||
|
lengthToFoot = getDistancePointPoint(line[0], foot);
|
||||||
|
|
||||||
|
return length === 0 ? 0 : lengthToFoot / length;
|
||||||
|
}
|
Loading…
Reference in New Issue