UNPKG

26.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var fp_1 = require("lodash/fp");
4var geom_utils_1 = require("../geom-utils");
5var edge_1 = require("./edge");
6var orientation_1 = require("./orientation");
7var INDEX_TO_DIMENSION = ["x", "y"];
8function getActiveOrientationIndexAndDimension(orientation) {
9 var activeOrientationIndex = fp_1.findIndex(function (orientationScalar) { return orientationScalar !== 0; }, orientation);
10 var activeOrientationDimension = INDEX_TO_DIMENSION[activeOrientationIndex];
11 var otherOrientationDimension = activeOrientationDimension === "x"
12 ? "y"
13 : "x";
14 return {
15 activeOrientationIndex: activeOrientationIndex,
16 activeOrientationDimension: activeOrientationDimension,
17 otherOrientationDimension: otherOrientationDimension
18 };
19}
20/**
21 * calculateAllPoints for edges of type Elbow and Curved
22 *
23 * PathVisio-Java does not always specify all the points needed to draw edges
24 * of type Elbow and Curved. Unless the user drags one or more of the
25 * waypoints, PathVisio-Java will only specify the first and last points,
26 * leaving implicit one or more additional points that are required to draw
27 * the edge.
28 *
29 * Kaavio requires that a PvjsonEdge specifies ALL the points required for
30 * drawing the edge, so this function calculates any implicit points required
31 * to unambiguously specify an edge and returns the full set of points
32 * (implicit points are made explicit).
33 *
34 * @param explicitPoints {Array}
35 * @param [sourceEntity] {Object} entity from which the EDGE emanates
36 * (never an Anchor)
37 * @param [targetEntity] {Object} entity into which the EDGE terminates
38 * (never an Anchor)
39 * @return {Array} Full set of points required to render the edge
40 */
41function calculateAllPoints(explicitPoints, sourceEntity, targetEntity) {
42 var firstPoint = explicitPoints[0];
43 var lastPoint = explicitPoints[explicitPoints.length - 1];
44 // NOTE: we need at least one of the first point or the last point to have a
45 // valid orientation. If that's not the case already, we try setting it here,
46 // based on other information available to us.
47 if (!orientation_1.validateOrientation(firstPoint.orientation)) {
48 if (firstPoint.hasOwnProperty("isAttachedTo")) {
49 // It is correct to specify <PvjsonEdge> as the type for
50 // sourceEntity/targetEntity when calculating the orientation of a point
51 // attached to another edge below, because we get into there if neither
52 // the first nor last point have a valid orientation. If a point is
53 // attached to a SingleFreeNode, a Group or a GPML State, it would already
54 // have a valid orientation calculated by this point, so the point must
55 // be either attached to nothing or else attached to an edge.
56 firstPoint.orientation = orientation_1.getOrientationOfHyperedgeStartPoint(sourceEntity, firstPoint, lastPoint);
57 }
58 else {
59 firstPoint.orientation = [-1, 0];
60 }
61 }
62 if (!orientation_1.validateOrientation(lastPoint.orientation)) {
63 if (lastPoint.hasOwnProperty("isAttachedTo")) {
64 // It is correct to specify <PvjsonEdge> as the type for
65 // sourceEntity/targetEntity when calculating the orientation of a point
66 // attached to another edge below, because we get into there if neither
67 // the first nor last point have a valid orientation. If a point is
68 // attached to a SingleFreeNode, a Group or a GPML State, it would already
69 // have a valid orientation calculated by this point, so the point must
70 // be either attached to nothing or else attached to an edge.
71 lastPoint.orientation = orientation_1.getOrientationOfHyperedgeEndPoint(targetEntity, lastPoint, firstPoint);
72 }
73 else {
74 var x0 = firstPoint.x, y0 = firstPoint.y;
75 var x1 = lastPoint.x, y1 = lastPoint.y;
76 var firstSide = geom_utils_1.getStartSideByOrientation(firstPoint.orientation);
77 if (firstSide === "left") {
78 if (x0 >= x1 && x0 < x1 + edge_1.DEFAULT_STUB_LENGTH) {
79 lastPoint.orientation = [1, 0];
80 }
81 else {
82 lastPoint.orientation = [-1, 0];
83 }
84 }
85 else if (firstSide === "right") {
86 if (x0 + edge_1.DEFAULT_STUB_LENGTH <= x1) {
87 lastPoint.orientation = [1, 0];
88 }
89 else {
90 lastPoint.orientation = [-1, 0];
91 }
92 }
93 else {
94 lastPoint.orientation = [-1, 0];
95 }
96 }
97 }
98 if (explicitPoints.length > 2) {
99 return explicitPoints;
100 }
101 var startPoint;
102 var endPoint;
103 var endEntity;
104 var pointOrderReversed;
105 if (orientation_1.validateOrientation(firstPoint.orientation)) {
106 pointOrderReversed = false;
107 startPoint = firstPoint;
108 endPoint = lastPoint;
109 endEntity = targetEntity;
110 }
111 else if (orientation_1.validateOrientation(lastPoint.orientation)) {
112 pointOrderReversed = true;
113 startPoint = lastPoint;
114 endPoint = firstPoint;
115 endEntity = sourceEntity;
116 }
117 else {
118 throw new Error("Either first or last point (or both) should have a valid\n\t\t\torientation by now in\n\t\t\tcalculateAllPoints(\n\t\t\t\t" + JSON.stringify(explicitPoints) + ",\n\t\t\t\t" + JSON.stringify(sourceEntity) + ",\n\t\t\t\t" + JSON.stringify(targetEntity) + "\n\t\t\t)");
119 }
120 var startOrientation = startPoint.orientation;
121 var endOrientation = endPoint.orientation;
122 var vectorSumOrientation = [
123 Math.sign(endPoint.x - startPoint.x),
124 Math.sign(endPoint.y - startPoint.y)
125 ];
126 var _a = getActiveOrientationIndexAndDimension(startOrientation), activeStartOrientationIndex = _a.activeOrientationIndex, activeStartOrientationDimension = _a.activeOrientationDimension, otherStartOrientationDimension = _a.otherOrientationDimension;
127 var _b = getActiveOrientationIndexAndDimension(endOrientation), activeEndOrientationIndex = _b.activeOrientationIndex, activeEndOrientationDimension = _b.activeOrientationDimension, otherEndOrientationDimension = _b.otherOrientationDimension;
128 var pvjsonPoints = [];
129 pvjsonPoints.push(startPoint);
130 // Calculate intermediate data points, which are implicit.
131 // Remember that this refers to the minimum number of points required to
132 // define the path, so 3 points could mean this:
133 //
134 // -------------------*-------------------
135 // | |
136 // | |
137 // * *
138 //
139 // or this:
140 // *
141 // |
142 // |
143 // -------------------*-------------------
144 // |
145 // |
146 // *
147 //
148 // or several other possible configurations
149 // NOTE: when an edge is connected to a SingleFreeNode or a Group (how about a State?),
150 // PathVisio-Java will route the edge around the side from which the edge
151 // emanates, if needed.
152 // But when an edge is connected to another edge, PathVisio-Java
153 // does not do any special re-routing for that connection.
154 if (activeStartOrientationIndex === activeEndOrientationIndex) {
155 // Start and end orientations are parallel, e.g.,
156 // starts at right and ends on either right or left side, or
157 // starts on top and ends on either top or bottom side.
158 var activeOrientationIndex = activeStartOrientationIndex;
159 var activeOrientationDimension = activeStartOrientationDimension;
160 var otherOrientationDimension = otherStartOrientationDimension;
161 var otherOrientationDimensionDisplacement = endPoint[otherOrientationDimension] -
162 startPoint[otherOrientationDimension];
163 if (startOrientation[activeOrientationIndex] ===
164 vectorSumOrientation[activeOrientationIndex]) {
165 // we don't have to avoid the start side
166 pvjsonPoints[1] = {};
167 pvjsonPoints[1][otherOrientationDimension] =
168 startPoint[otherOrientationDimension] +
169 otherOrientationDimensionDisplacement / 2;
170 if (startOrientation[activeOrientationIndex] ===
171 endOrientation[activeOrientationIndex]) {
172 // *---
173 // |
174 // |
175 // *
176 // |
177 // |
178 // ---------------------*
179 pvjsonPoints[1][activeOrientationDimension] =
180 startPoint[activeOrientationDimension] +
181 startOrientation[activeOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
182 }
183 else {
184 // *-------------------------
185 // |
186 // |
187 // *
188 // |
189 // |
190 // *---
191 pvjsonPoints[1][activeOrientationDimension] =
192 endPoint[activeOrientationDimension] -
193 endOrientation[activeOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
194 }
195 }
196 else {
197 // must initially route around start side
198 if (startOrientation[activeOrientationIndex] ===
199 endOrientation[activeOrientationIndex]) {
200 // *---
201 // |
202 // |
203 // *
204 // |
205 // |
206 // -----------*-----------
207 // |
208 // |
209 // *
210 // |
211 // |
212 // ---*
213 pvjsonPoints[1] = {};
214 pvjsonPoints[1][activeOrientationDimension] =
215 startPoint[activeOrientationDimension] +
216 startOrientation[activeOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
217 pvjsonPoints[1][otherOrientationDimension] =
218 startPoint[otherOrientationDimension] +
219 otherOrientationDimensionDisplacement / 4;
220 pvjsonPoints[2] = {};
221 pvjsonPoints[2][activeOrientationDimension] =
222 (startPoint[activeOrientationDimension] +
223 endPoint[activeOrientationDimension]) /
224 2;
225 pvjsonPoints[2][otherOrientationDimension] =
226 startPoint[otherOrientationDimension] +
227 otherOrientationDimensionDisplacement / 2;
228 pvjsonPoints[3] = {};
229 pvjsonPoints[3][activeOrientationDimension] =
230 endPoint[activeOrientationDimension] -
231 endOrientation[activeOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
232 pvjsonPoints[3][otherOrientationDimension] =
233 startPoint[otherOrientationDimension] +
234 3 * otherOrientationDimensionDisplacement / 4;
235 }
236 else {
237 // *---
238 // |
239 // |
240 // *
241 // |
242 // |
243 // *---------------------
244 pvjsonPoints[1] = {};
245 pvjsonPoints[1][activeOrientationDimension] =
246 startPoint[activeOrientationDimension] +
247 startOrientation[activeOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
248 pvjsonPoints[1][otherOrientationDimension] =
249 startPoint[otherOrientationDimension] +
250 otherOrientationDimensionDisplacement / 2;
251 }
252 }
253 }
254 else {
255 // Start and end orientations are perpendicular
256 if (startOrientation[activeStartOrientationIndex] ===
257 vectorSumOrientation[activeStartOrientationIndex] &&
258 endOrientation[activeEndOrientationIndex] ===
259 vectorSumOrientation[activeEndOrientationIndex]) {
260 // *
261 // |
262 // |
263 // |
264 // |
265 // |
266 // ---------------------*
267 //
268 // Do nothing.
269 }
270 else {
271 // ---*
272 // |
273 // |
274 // |
275 // *
276 // * |
277 // | |
278 // | |
279 // --------*--------
280 //
281 // or *---
282 // |
283 // |
284 // |
285 // *
286 // * |
287 // | |
288 // | |
289 // --------*--------
290 //
291 // or
292 //
293 // ----*
294 // |
295 // |
296 // *
297 // |
298 // |
299 // ---*---
300 // |
301 // |
302 // *
303 var otherStartOrientationDimensionDisplacement = endPoint[otherStartOrientationDimension] -
304 endOrientation[activeEndOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH -
305 startPoint[otherStartOrientationDimension];
306 pvjsonPoints[1] = {};
307 pvjsonPoints[1][activeStartOrientationDimension] =
308 startPoint[activeStartOrientationDimension] +
309 startOrientation[activeStartOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
310 pvjsonPoints[1][otherStartOrientationDimension] =
311 startPoint[otherStartOrientationDimension] +
312 otherStartOrientationDimensionDisplacement / 2;
313 pvjsonPoints[2] = {};
314 pvjsonPoints[2][activeEndOrientationDimension] =
315 endPoint[activeEndOrientationDimension] -
316 endOrientation[activeEndOrientationIndex] * edge_1.DEFAULT_STUB_LENGTH;
317 pvjsonPoints[2][otherEndOrientationDimension] =
318 (pvjsonPoints[1][otherEndOrientationDimension] +
319 endPoint[otherEndOrientationDimension]) /
320 2;
321 }
322 }
323 pvjsonPoints.push(endPoint);
324 return pointOrderReversed ? pvjsonPoints.reverse() : pvjsonPoints;
325}
326exports.calculateAllPoints = calculateAllPoints;
327//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsY3VsYXRlQWxsUG9pbnRzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2VkZ2UvY2FsY3VsYXRlQWxsUG9pbnRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsZ0NBQXNFO0FBQ3RFLDRDQVV1QjtBQUd2QiwrQkFBNkM7QUFDN0MsNkNBSXVCO0FBRXZCLElBQU0sa0JBQWtCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLENBQUM7QUFFdEMsK0NBQStDLFdBQTZCO0lBQzFFLElBQU0sc0JBQXNCLEdBQUcsY0FBUyxDQUN0QyxVQUFDLGlCQUF5QixJQUFLLE9BQUEsaUJBQWlCLEtBQUssQ0FBQyxFQUF2QixDQUF1QixFQUN0RCxXQUFXLENBQ1osQ0FBQztJQUNGLElBQU0sMEJBQTBCLEdBQUcsa0JBQWtCLENBQUMsc0JBQXNCLENBQUMsQ0FBQztJQUM5RSxJQUFNLHlCQUF5QixHQUFHLDBCQUEwQixLQUFLLEdBQUc7UUFDbEUsQ0FBQyxDQUFDLEdBQUc7UUFDTCxDQUFDLENBQUMsR0FBRyxDQUFDO0lBQ1IsTUFBTSxDQUFDO1FBQ0wsc0JBQXNCLHdCQUFBO1FBQ3RCLDBCQUEwQiw0QkFBQTtRQUMxQix5QkFBeUIsMkJBQUE7S0FDMUIsQ0FBQztBQUNKLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FvQkc7QUFDSCw0QkFDRSxjQUFzQyxFQUN0QyxZQUFzQyxFQUN0QyxZQUFzQztJQUV0QyxJQUFJLFVBQVUsR0FBRyxjQUFjLENBQUMsQ0FBQyxDQUFpQyxDQUFDO0lBQ25FLElBQUksU0FBUyxHQUFHLGNBQWMsQ0FBQyxjQUFjLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FDNUMsQ0FBQztJQUViLDRFQUE0RTtJQUM1RSw2RUFBNkU7SUFDN0UsOENBQThDO0lBQzlDLEVBQUUsQ0FBQyxDQUFDLENBQUMsaUNBQW1CLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqRCxFQUFF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
\No newline at end of file