UNPKG

11.3 kBJavaScriptView Raw
1import { flow, isFinite, last, map } from "lodash/fp";
2import { START_SEGMENT_DETAILS_MAPS, flipOrientation, sameSide, SmartPath } from "../geom-utils";
3import { distance } from "../spinoffs/Angle";
4import { DEFAULT_STUB_LENGTH } from "./edge";
5/**
6 * getOrientationOfHyperedgeStartPoint
7 *
8 * Get orientation of the start point of an edge that is attached to another
9 * edge.
10 *
11 * @param referencedEdge {PvjsonEdge}
12 * @param startPoint {Point}
13 * @param otherPoint {Point}
14 * @return {Orientation}
15 */
16export function getOrientationOfHyperedgeStartPoint(referencedEdge, startPoint, endPoint) {
17 if (!referencedEdge) {
18 throw new Error("Missing referencedEdge when calculating orientation of point attached to other edge.");
19 }
20 const currentPath = new SmartPath([startPoint, endPoint]);
21 const angleOfCurrentVectorSum = currentPath.sum.angle;
22 const referencedPath = new SmartPath(referencedEdge.points, referencedEdge);
23 // This is the angle of the line tangent to the referenced edge at
24 // startPoint.
25 const angleOfReferencedEdgeAtPointOnEdge = referencedPath.position(startPoint.attachmentDisplay.position[0]).angle;
26 const firstSegmentCalculations = START_SEGMENT_DETAILS_MAPS.map(function (startSegmentDetailsMap) {
27 /*
28 * referenced edge
29 * /
30 * /
31 * /.
32 * / angle (rad)
33 * / .
34 * /--------------
35 * / ^ | --------------
36 * / | | | |
37 * | ------------| |
38 * | | |
39 * firstSegment --------------
40 * (of current edge)
41 *
42 */
43 const { orientation } = startSegmentDetailsMap;
44 const [orientationX, orientationY] = orientation;
45 const firstSegmentEndPoint = {
46 x: startPoint.x + DEFAULT_STUB_LENGTH * orientationX,
47 y: startPoint.y + DEFAULT_STUB_LENGTH * orientationY
48 };
49 return {
50 firstSegmentEndPoint,
51 endPoint,
52 emanationAngle: startSegmentDetailsMap.angle,
53 orientation: orientation
54 };
55 })
56 .map(function ({ firstSegmentEndPoint, endPoint, emanationAngle: emanationAngle, orientation }) {
57 const isSameSide = sameSide(referencedEdge.points[0], last(referencedEdge.points), firstSegmentEndPoint, endPoint);
58 const angleBetweenOrientationVectorAndCurrentEdge = distance(emanationAngle, angleOfCurrentVectorSum);
59 const angleBetweenOrientationVectorAndReferencedEdge = distance(angleOfReferencedEdgeAtPointOnEdge, emanationAngle);
60 return {
61 isSameSide,
62 angleBetweenOrientationVectorAndCurrentEdge,
63 angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge: Math.abs(angleBetweenOrientationVectorAndReferencedEdge - Math.PI / 2),
64 orientation
65 };
66 })
67 .sort(function (a, b) {
68 if (a.isSameSide && !b.isSameSide) {
69 return -1;
70 }
71 else if (!a.isSameSide && b.isSameSide) {
72 return 1;
73 }
74 else {
75 if (a.angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge <
76 b.angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge) {
77 return -1;
78 }
79 else if (a.angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge >
80 b.angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge) {
81 return 1;
82 }
83 else {
84 if (a.angleBetweenOrientationVectorAndCurrentEdge <
85 b.angleBetweenOrientationVectorAndCurrentEdge) {
86 return -1;
87 }
88 else if (a.angleBetweenOrientationVectorAndCurrentEdge >
89 b.angleBetweenOrientationVectorAndCurrentEdge) {
90 return 1;
91 }
92 else {
93 return 0;
94 }
95 }
96 }
97 });
98 const formatted = map(function (firstSegmentCalculation) {
99 const { angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge, angleBetweenOrientationVectorAndCurrentEdge, isSameSide } = firstSegmentCalculation;
100 return {
101 angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge: String(angleBetweenOrientationVectorAndVectorPerpendicularToReferencedEdge /
102 Math.PI) + " * PI",
103 angleBetweenOrientationVectorAndCurrentEdge: String(angleBetweenOrientationVectorAndCurrentEdge / Math.PI) + " * PI",
104 isSameSide
105 };
106 }, firstSegmentCalculations);
107 return firstSegmentCalculations[0].orientation;
108}
109// Uses the same sorting criteria as getOrientationOfHyperedgeStartPoint,
110// except with the obvious changes in direction to account for being the
111// endPoint instead of the startPoint.
112export const getOrientationOfHyperedgeEndPoint = flow(getOrientationOfHyperedgeStartPoint, flipOrientation);
113// Validate orientation of attachment display.
114//
115// When attached to a normal Node, we can calculate the orientation immediately
116// so this will return true right away.
117// When attached to an Edge or Group, we need to do more processing,
118// so this will at least initially return false.
119// TODO: Not sure whether the orientation of a point attached to an Edge or a
120// Group is ever set.
121export function validateOrientation(orientation) {
122 return !!orientation && isFinite(orientation[0]) && isFinite(orientation[1]);
123}
124/*
125 // NOTE: PathVisio-Java appears to try to avoid making an edge
126 // terminate into another edge at an approach angle of anything
127 // less than about 30 deg.
128 if (endPoint.hasOwnProperty("isAttachedTo")) {
129 const referencedEndPath = new SmartPath(endEntity.points, endEntity);
130 const angleOfReferencedEdgeAtPointOnEdge = referencedEndPath.position(
131 startPoint.attachmentDisplay.position[0]
132 ).angle;
133 if (
134 Math.abs(
135 START_SIDE_TO_EMANATION_ANGLE_MAPPINGS[endSide] -
136 angleOfReferencedEdgeAtPointOnEdge
137 ) <
138 30 * (Math.PI / 180)
139 ) {
140 // edge1 is almost parallel with edge2, making it hard to read, so we need to recalculate.
141 endPoint.orientation = getOrientationOfHyperedgeEndPoint(
142 endEntity,
143 endPoint,
144 startPoint
145 );
146 return getAndCompareSides(startPoint, endPoint, endEntity);
147 }
148 }
149//*/
150//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3JpZW50YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvZWRnZS9vcmllbnRhdGlvbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ3RELE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsZUFBZSxFQUNmLFFBQVEsRUFFUixTQUFTLEVBQ1YsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBUTdDLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLFFBQVEsQ0FBQztBQUU3Qzs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSw4Q0FDSixjQUEwQixFQUMxQixVQUF3QyxFQUN4QyxRQUFzQztJQUV0QyxFQUFFLENBQUMsQ0FBQyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUM7UUFDcEIsTUFBTSxJQUFJLEtBQUssQ0FDYixzRkFBc0YsQ0FDdkYsQ0FBQztJQUNKLENBQUM7SUFFRCxNQUFNLFdBQVcsR0FBRyxJQUFJLFNBQVMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDO0lBQzFELE1BQU0sdUJBQXVCLEdBQUcsV0FBVyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUM7SUFDdEQsTUFBTSxjQUFjLEdBQUcsSUFBSSxTQUFTLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQztJQUU1RSxrRUFBa0U7SUFDbEUsY0FBYztJQUNkLE1BQU0sa0NBQWtDLEdBQUcsY0FBYyxDQUFDLFFBQVEsQ0FDaEUsVUFBVSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FDekMsQ0FBQyxLQUFLLENBQUM7SUFFUixNQUFNLHdCQUF3QixHQUFHLDBCQUEwQixDQUFDLEdBQUcsQ0FBQyxVQUM5RCxzQkFBc0I7UUFF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
\No newline at end of file