1 | "use strict";
|
---|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
---|
3 | exports.Path = void 0;
|
---|
4 | const Factory_1 = require("../Factory");
|
---|
5 | const Shape_1 = require("../Shape");
|
---|
6 | const Global_1 = require("../Global");
|
---|
7 | const BezierFunctions_1 = require("../BezierFunctions");
|
---|
8 | class Path extends Shape_1.Shape {
|
---|
9 | constructor(config) {
|
---|
10 | super(config);
|
---|
11 | this.dataArray = [];
|
---|
12 | this.pathLength = 0;
|
---|
13 | this._readDataAttribute();
|
---|
14 | this.on('dataChange.konva', function () {
|
---|
15 | this._readDataAttribute();
|
---|
16 | });
|
---|
17 | }
|
---|
18 | _readDataAttribute() {
|
---|
19 | this.dataArray = Path.parsePathData(this.data());
|
---|
20 | this.pathLength = Path.getPathLength(this.dataArray);
|
---|
21 | }
|
---|
22 | _sceneFunc(context) {
|
---|
23 | var ca = this.dataArray;
|
---|
24 | context.beginPath();
|
---|
25 | var isClosed = false;
|
---|
26 | for (var n = 0; n < ca.length; n++) {
|
---|
27 | var c = ca[n].command;
|
---|
28 | var p = ca[n].points;
|
---|
29 | switch (c) {
|
---|
30 | case 'L':
|
---|
31 | context.lineTo(p[0], p[1]);
|
---|
32 | break;
|
---|
33 | case 'M':
|
---|
34 | context.moveTo(p[0], p[1]);
|
---|
35 | break;
|
---|
36 | case 'C':
|
---|
37 | context.bezierCurveTo(p[0], p[1], p[2], p[3], p[4], p[5]);
|
---|
38 | break;
|
---|
39 | case 'Q':
|
---|
40 | context.quadraticCurveTo(p[0], p[1], p[2], p[3]);
|
---|
41 | break;
|
---|
42 | case 'A':
|
---|
43 | var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6], fs = p[7];
|
---|
44 | var r = rx > ry ? rx : ry;
|
---|
45 | var scaleX = rx > ry ? 1 : rx / ry;
|
---|
46 | var scaleY = rx > ry ? ry / rx : 1;
|
---|
47 | context.translate(cx, cy);
|
---|
48 | context.rotate(psi);
|
---|
49 | context.scale(scaleX, scaleY);
|
---|
50 | context.arc(0, 0, r, theta, theta + dTheta, 1 - fs);
|
---|
51 | context.scale(1 / scaleX, 1 / scaleY);
|
---|
52 | context.rotate(-psi);
|
---|
53 | context.translate(-cx, -cy);
|
---|
54 | break;
|
---|
55 | case 'z':
|
---|
56 | isClosed = true;
|
---|
57 | context.closePath();
|
---|
58 | break;
|
---|
59 | }
|
---|
60 | }
|
---|
61 | if (!isClosed && !this.hasFill()) {
|
---|
62 | context.strokeShape(this);
|
---|
63 | }
|
---|
64 | else {
|
---|
65 | context.fillStrokeShape(this);
|
---|
66 | }
|
---|
67 | }
|
---|
68 | getSelfRect() {
|
---|
69 | var points = [];
|
---|
70 | this.dataArray.forEach(function (data) {
|
---|
71 | if (data.command === 'A') {
|
---|
72 | var start = data.points[4];
|
---|
73 | var dTheta = data.points[5];
|
---|
74 | var end = data.points[4] + dTheta;
|
---|
75 | var inc = Math.PI / 180.0;
|
---|
76 | if (Math.abs(start - end) < inc) {
|
---|
77 | inc = Math.abs(start - end);
|
---|
78 | }
|
---|
79 | if (dTheta < 0) {
|
---|
80 | for (let t = start - inc; t > end; t -= inc) {
|
---|
81 | const point = Path.getPointOnEllipticalArc(data.points[0], data.points[1], data.points[2], data.points[3], t, 0);
|
---|
82 | points.push(point.x, point.y);
|
---|
83 | }
|
---|
84 | }
|
---|
85 | else {
|
---|
86 | for (let t = start + inc; t < end; t += inc) {
|
---|
87 | const point = Path.getPointOnEllipticalArc(data.points[0], data.points[1], data.points[2], data.points[3], t, 0);
|
---|
88 | points.push(point.x, point.y);
|
---|
89 | }
|
---|
90 | }
|
---|
91 | }
|
---|
92 | else if (data.command === 'C') {
|
---|
93 | for (let t = 0.0; t <= 1; t += 0.01) {
|
---|
94 | const point = Path.getPointOnCubicBezier(t, data.start.x, data.start.y, data.points[0], data.points[1], data.points[2], data.points[3], data.points[4], data.points[5]);
|
---|
95 | points.push(point.x, point.y);
|
---|
96 | }
|
---|
97 | }
|
---|
98 | else {
|
---|
99 | points = points.concat(data.points);
|
---|
100 | }
|
---|
101 | });
|
---|
102 | var minX = points[0];
|
---|
103 | var maxX = points[0];
|
---|
104 | var minY = points[1];
|
---|
105 | var maxY = points[1];
|
---|
106 | var x, y;
|
---|
107 | for (var i = 0; i < points.length / 2; i++) {
|
---|
108 | x = points[i * 2];
|
---|
109 | y = points[i * 2 + 1];
|
---|
110 | if (!isNaN(x)) {
|
---|
111 | minX = Math.min(minX, x);
|
---|
112 | maxX = Math.max(maxX, x);
|
---|
113 | }
|
---|
114 | if (!isNaN(y)) {
|
---|
115 | minY = Math.min(minY, y);
|
---|
116 | maxY = Math.max(maxY, y);
|
---|
117 | }
|
---|
118 | }
|
---|
119 | return {
|
---|
120 | x: minX,
|
---|
121 | y: minY,
|
---|
122 | width: maxX - minX,
|
---|
123 | height: maxY - minY,
|
---|
124 | };
|
---|
125 | }
|
---|
126 | getLength() {
|
---|
127 | return this.pathLength;
|
---|
128 | }
|
---|
129 | getPointAtLength(length) {
|
---|
130 | return Path.getPointAtLengthOfDataArray(length, this.dataArray);
|
---|
131 | }
|
---|
132 | static getLineLength(x1, y1, x2, y2) {
|
---|
133 | return Math.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
|
---|
134 | }
|
---|
135 | static getPathLength(dataArray) {
|
---|
136 | let pathLength = 0;
|
---|
137 | for (var i = 0; i < dataArray.length; ++i) {
|
---|
138 | pathLength += dataArray[i].pathLength;
|
---|
139 | }
|
---|
140 | return pathLength;
|
---|
141 | }
|
---|
142 | static getPointAtLengthOfDataArray(length, dataArray) {
|
---|
143 | var point, i = 0, ii = dataArray.length;
|
---|
144 | if (!ii) {
|
---|
145 | return null;
|
---|
146 | }
|
---|
147 | while (i < ii && length > dataArray[i].pathLength) {
|
---|
148 | length -= dataArray[i].pathLength;
|
---|
149 | ++i;
|
---|
150 | }
|
---|
151 | if (i === ii) {
|
---|
152 | point = dataArray[i - 1].points.slice(-2);
|
---|
153 | return {
|
---|
154 | x: point[0],
|
---|
155 | y: point[1],
|
---|
156 | };
|
---|
157 | }
|
---|
158 | if (length < 0.01) {
|
---|
159 | point = dataArray[i].points.slice(0, 2);
|
---|
160 | return {
|
---|
161 | x: point[0],
|
---|
162 | y: point[1],
|
---|
163 | };
|
---|
164 | }
|
---|
165 | var cp = dataArray[i];
|
---|
166 | var p = cp.points;
|
---|
167 | switch (cp.command) {
|
---|
168 | case 'L':
|
---|
169 | return Path.getPointOnLine(length, cp.start.x, cp.start.y, p[0], p[1]);
|
---|
170 | case 'C':
|
---|
171 | return Path.getPointOnCubicBezier((0, BezierFunctions_1.t2length)(length, Path.getPathLength(dataArray), (i) => {
|
---|
172 | return (0, BezierFunctions_1.getCubicArcLength)([cp.start.x, p[0], p[2], p[4]], [cp.start.y, p[1], p[3], p[5]], i);
|
---|
173 | }), cp.start.x, cp.start.y, p[0], p[1], p[2], p[3], p[4], p[5]);
|
---|
174 | case 'Q':
|
---|
175 | return Path.getPointOnQuadraticBezier((0, BezierFunctions_1.t2length)(length, Path.getPathLength(dataArray), (i) => {
|
---|
176 | return (0, BezierFunctions_1.getQuadraticArcLength)([cp.start.x, p[0], p[2]], [cp.start.y, p[1], p[3]], i);
|
---|
177 | }), cp.start.x, cp.start.y, p[0], p[1], p[2], p[3]);
|
---|
178 | case 'A':
|
---|
179 | var cx = p[0], cy = p[1], rx = p[2], ry = p[3], theta = p[4], dTheta = p[5], psi = p[6];
|
---|
180 | theta += (dTheta * length) / cp.pathLength;
|
---|
181 | return Path.getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi);
|
---|
182 | }
|
---|
183 | return null;
|
---|
184 | }
|
---|
185 | static getPointOnLine(dist, P1x, P1y, P2x, P2y, fromX, fromY) {
|
---|
186 | fromX = fromX !== null && fromX !== void 0 ? fromX : P1x;
|
---|
187 | fromY = fromY !== null && fromY !== void 0 ? fromY : P1y;
|
---|
188 | const len = this.getLineLength(P1x, P1y, P2x, P2y);
|
---|
189 | if (len < 1e-10) {
|
---|
190 | return { x: P1x, y: P1y };
|
---|
191 | }
|
---|
192 | if (P2x === P1x) {
|
---|
193 | return { x: fromX, y: fromY + (P2y > P1y ? dist : -dist) };
|
---|
194 | }
|
---|
195 | const m = (P2y - P1y) / (P2x - P1x);
|
---|
196 | const run = Math.sqrt((dist * dist) / (1 + m * m)) * (P2x < P1x ? -1 : 1);
|
---|
197 | const rise = m * run;
|
---|
198 | if (Math.abs(fromY - P1y - m * (fromX - P1x)) < 1e-10) {
|
---|
199 | return { x: fromX + run, y: fromY + rise };
|
---|
200 | }
|
---|
201 | const u = ((fromX - P1x) * (P2x - P1x) + (fromY - P1y) * (P2y - P1y)) / (len * len);
|
---|
202 | const ix = P1x + u * (P2x - P1x);
|
---|
203 | const iy = P1y + u * (P2y - P1y);
|
---|
204 | const pRise = this.getLineLength(fromX, fromY, ix, iy);
|
---|
205 | const pRun = Math.sqrt(dist * dist - pRise * pRise);
|
---|
206 | const adjustedRun = Math.sqrt((pRun * pRun) / (1 + m * m)) * (P2x < P1x ? -1 : 1);
|
---|
207 | const adjustedRise = m * adjustedRun;
|
---|
208 | return { x: ix + adjustedRun, y: iy + adjustedRise };
|
---|
209 | }
|
---|
210 | static getPointOnCubicBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y, P4x, P4y) {
|
---|
211 | function CB1(t) {
|
---|
212 | return t * t * t;
|
---|
213 | }
|
---|
214 | function CB2(t) {
|
---|
215 | return 3 * t * t * (1 - t);
|
---|
216 | }
|
---|
217 | function CB3(t) {
|
---|
218 | return 3 * t * (1 - t) * (1 - t);
|
---|
219 | }
|
---|
220 | function CB4(t) {
|
---|
221 | return (1 - t) * (1 - t) * (1 - t);
|
---|
222 | }
|
---|
223 | var x = P4x * CB1(pct) + P3x * CB2(pct) + P2x * CB3(pct) + P1x * CB4(pct);
|
---|
224 | var y = P4y * CB1(pct) + P3y * CB2(pct) + P2y * CB3(pct) + P1y * CB4(pct);
|
---|
225 | return {
|
---|
226 | x: x,
|
---|
227 | y: y,
|
---|
228 | };
|
---|
229 | }
|
---|
230 | static getPointOnQuadraticBezier(pct, P1x, P1y, P2x, P2y, P3x, P3y) {
|
---|
231 | function QB1(t) {
|
---|
232 | return t * t;
|
---|
233 | }
|
---|
234 | function QB2(t) {
|
---|
235 | return 2 * t * (1 - t);
|
---|
236 | }
|
---|
237 | function QB3(t) {
|
---|
238 | return (1 - t) * (1 - t);
|
---|
239 | }
|
---|
240 | var x = P3x * QB1(pct) + P2x * QB2(pct) + P1x * QB3(pct);
|
---|
241 | var y = P3y * QB1(pct) + P2y * QB2(pct) + P1y * QB3(pct);
|
---|
242 | return {
|
---|
243 | x: x,
|
---|
244 | y: y,
|
---|
245 | };
|
---|
246 | }
|
---|
247 | static getPointOnEllipticalArc(cx, cy, rx, ry, theta, psi) {
|
---|
248 | var cosPsi = Math.cos(psi), sinPsi = Math.sin(psi);
|
---|
249 | var pt = {
|
---|
250 | x: rx * Math.cos(theta),
|
---|
251 | y: ry * Math.sin(theta),
|
---|
252 | };
|
---|
253 | return {
|
---|
254 | x: cx + (pt.x * cosPsi - pt.y * sinPsi),
|
---|
255 | y: cy + (pt.x * sinPsi + pt.y * cosPsi),
|
---|
256 | };
|
---|
257 | }
|
---|
258 | static parsePathData(data) {
|
---|
259 | if (!data) {
|
---|
260 | return [];
|
---|
261 | }
|
---|
262 | var cs = data;
|
---|
263 | var cc = [
|
---|
264 | 'm',
|
---|
265 | 'M',
|
---|
266 | 'l',
|
---|
267 | 'L',
|
---|
268 | 'v',
|
---|
269 | 'V',
|
---|
270 | 'h',
|
---|
271 | 'H',
|
---|
272 | 'z',
|
---|
273 | 'Z',
|
---|
274 | 'c',
|
---|
275 | 'C',
|
---|
276 | 'q',
|
---|
277 | 'Q',
|
---|
278 | 't',
|
---|
279 | 'T',
|
---|
280 | 's',
|
---|
281 | 'S',
|
---|
282 | 'a',
|
---|
283 | 'A',
|
---|
284 | ];
|
---|
285 | cs = cs.replace(new RegExp(' ', 'g'), ',');
|
---|
286 | for (var n = 0; n < cc.length; n++) {
|
---|
287 | cs = cs.replace(new RegExp(cc[n], 'g'), '|' + cc[n]);
|
---|
288 | }
|
---|
289 | var arr = cs.split('|');
|
---|
290 | var ca = [];
|
---|
291 | var coords = [];
|
---|
292 | var cpx = 0;
|
---|
293 | var cpy = 0;
|
---|
294 | var re = /([-+]?((\d+\.\d+)|((\d+)|(\.\d+)))(?:e[-+]?\d+)?)/gi;
|
---|
295 | var match;
|
---|
296 | for (n = 1; n < arr.length; n++) {
|
---|
297 | var str = arr[n];
|
---|
298 | var c = str.charAt(0);
|
---|
299 | str = str.slice(1);
|
---|
300 | coords.length = 0;
|
---|
301 | while ((match = re.exec(str))) {
|
---|
302 | coords.push(match[0]);
|
---|
303 | }
|
---|
304 | var p = [];
|
---|
305 | for (var j = 0, jlen = coords.length; j < jlen; j++) {
|
---|
306 | if (coords[j] === '00') {
|
---|
307 | p.push(0, 0);
|
---|
308 | continue;
|
---|
309 | }
|
---|
310 | var parsed = parseFloat(coords[j]);
|
---|
311 | if (!isNaN(parsed)) {
|
---|
312 | p.push(parsed);
|
---|
313 | }
|
---|
314 | else {
|
---|
315 | p.push(0);
|
---|
316 | }
|
---|
317 | }
|
---|
318 | while (p.length > 0) {
|
---|
319 | if (isNaN(p[0])) {
|
---|
320 | break;
|
---|
321 | }
|
---|
322 | var cmd = '';
|
---|
323 | var points = [];
|
---|
324 | var startX = cpx, startY = cpy;
|
---|
325 | var prevCmd, ctlPtx, ctlPty;
|
---|
326 | var rx, ry, psi, fa, fs, x1, y1;
|
---|
327 | switch (c) {
|
---|
328 | case 'l':
|
---|
329 | cpx += p.shift();
|
---|
330 | cpy += p.shift();
|
---|
331 | cmd = 'L';
|
---|
332 | points.push(cpx, cpy);
|
---|
333 | break;
|
---|
334 | case 'L':
|
---|
335 | cpx = p.shift();
|
---|
336 | cpy = p.shift();
|
---|
337 | points.push(cpx, cpy);
|
---|
338 | break;
|
---|
339 | case 'm':
|
---|
340 | var dx = p.shift();
|
---|
341 | var dy = p.shift();
|
---|
342 | cpx += dx;
|
---|
343 | cpy += dy;
|
---|
344 | cmd = 'M';
|
---|
345 | if (ca.length > 2 && ca[ca.length - 1].command === 'z') {
|
---|
346 | for (var idx = ca.length - 2; idx >= 0; idx--) {
|
---|
347 | if (ca[idx].command === 'M') {
|
---|
348 | cpx = ca[idx].points[0] + dx;
|
---|
349 | cpy = ca[idx].points[1] + dy;
|
---|
350 | break;
|
---|
351 | }
|
---|
352 | }
|
---|
353 | }
|
---|
354 | points.push(cpx, cpy);
|
---|
355 | c = 'l';
|
---|
356 | break;
|
---|
357 | case 'M':
|
---|
358 | cpx = p.shift();
|
---|
359 | cpy = p.shift();
|
---|
360 | cmd = 'M';
|
---|
361 | points.push(cpx, cpy);
|
---|
362 | c = 'L';
|
---|
363 | break;
|
---|
364 | case 'h':
|
---|
365 | cpx += p.shift();
|
---|
366 | cmd = 'L';
|
---|
367 | points.push(cpx, cpy);
|
---|
368 | break;
|
---|
369 | case 'H':
|
---|
370 | cpx = p.shift();
|
---|
371 | cmd = 'L';
|
---|
372 | points.push(cpx, cpy);
|
---|
373 | break;
|
---|
374 | case 'v':
|
---|
375 | cpy += p.shift();
|
---|
376 | cmd = 'L';
|
---|
377 | points.push(cpx, cpy);
|
---|
378 | break;
|
---|
379 | case 'V':
|
---|
380 | cpy = p.shift();
|
---|
381 | cmd = 'L';
|
---|
382 | points.push(cpx, cpy);
|
---|
383 | break;
|
---|
384 | case 'C':
|
---|
385 | points.push(p.shift(), p.shift(), p.shift(), p.shift());
|
---|
386 | cpx = p.shift();
|
---|
387 | cpy = p.shift();
|
---|
388 | points.push(cpx, cpy);
|
---|
389 | break;
|
---|
390 | case 'c':
|
---|
391 | points.push(cpx + p.shift(), cpy + p.shift(), cpx + p.shift(), cpy + p.shift());
|
---|
392 | cpx += p.shift();
|
---|
393 | cpy += p.shift();
|
---|
394 | cmd = 'C';
|
---|
395 | points.push(cpx, cpy);
|
---|
396 | break;
|
---|
397 | case 'S':
|
---|
398 | ctlPtx = cpx;
|
---|
399 | ctlPty = cpy;
|
---|
400 | prevCmd = ca[ca.length - 1];
|
---|
401 | if (prevCmd.command === 'C') {
|
---|
402 | ctlPtx = cpx + (cpx - prevCmd.points[2]);
|
---|
403 | ctlPty = cpy + (cpy - prevCmd.points[3]);
|
---|
404 | }
|
---|
405 | points.push(ctlPtx, ctlPty, p.shift(), p.shift());
|
---|
406 | cpx = p.shift();
|
---|
407 | cpy = p.shift();
|
---|
408 | cmd = 'C';
|
---|
409 | points.push(cpx, cpy);
|
---|
410 | break;
|
---|
411 | case 's':
|
---|
412 | ctlPtx = cpx;
|
---|
413 | ctlPty = cpy;
|
---|
414 | prevCmd = ca[ca.length - 1];
|
---|
415 | if (prevCmd.command === 'C') {
|
---|
416 | ctlPtx = cpx + (cpx - prevCmd.points[2]);
|
---|
417 | ctlPty = cpy + (cpy - prevCmd.points[3]);
|
---|
418 | }
|
---|
419 | points.push(ctlPtx, ctlPty, cpx + p.shift(), cpy + p.shift());
|
---|
420 | cpx += p.shift();
|
---|
421 | cpy += p.shift();
|
---|
422 | cmd = 'C';
|
---|
423 | points.push(cpx, cpy);
|
---|
424 | break;
|
---|
425 | case 'Q':
|
---|
426 | points.push(p.shift(), p.shift());
|
---|
427 | cpx = p.shift();
|
---|
428 | cpy = p.shift();
|
---|
429 | points.push(cpx, cpy);
|
---|
430 | break;
|
---|
431 | case 'q':
|
---|
432 | points.push(cpx + p.shift(), cpy + p.shift());
|
---|
433 | cpx += p.shift();
|
---|
434 | cpy += p.shift();
|
---|
435 | cmd = 'Q';
|
---|
436 | points.push(cpx, cpy);
|
---|
437 | break;
|
---|
438 | case 'T':
|
---|
439 | ctlPtx = cpx;
|
---|
440 | ctlPty = cpy;
|
---|
441 | prevCmd = ca[ca.length - 1];
|
---|
442 | if (prevCmd.command === 'Q') {
|
---|
443 | ctlPtx = cpx + (cpx - prevCmd.points[0]);
|
---|
444 | ctlPty = cpy + (cpy - prevCmd.points[1]);
|
---|
445 | }
|
---|
446 | cpx = p.shift();
|
---|
447 | cpy = p.shift();
|
---|
448 | cmd = 'Q';
|
---|
449 | points.push(ctlPtx, ctlPty, cpx, cpy);
|
---|
450 | break;
|
---|
451 | case 't':
|
---|
452 | ctlPtx = cpx;
|
---|
453 | ctlPty = cpy;
|
---|
454 | prevCmd = ca[ca.length - 1];
|
---|
455 | if (prevCmd.command === 'Q') {
|
---|
456 | ctlPtx = cpx + (cpx - prevCmd.points[0]);
|
---|
457 | ctlPty = cpy + (cpy - prevCmd.points[1]);
|
---|
458 | }
|
---|
459 | cpx += p.shift();
|
---|
460 | cpy += p.shift();
|
---|
461 | cmd = 'Q';
|
---|
462 | points.push(ctlPtx, ctlPty, cpx, cpy);
|
---|
463 | break;
|
---|
464 | case 'A':
|
---|
465 | rx = p.shift();
|
---|
466 | ry = p.shift();
|
---|
467 | psi = p.shift();
|
---|
468 | fa = p.shift();
|
---|
469 | fs = p.shift();
|
---|
470 | x1 = cpx;
|
---|
471 | y1 = cpy;
|
---|
472 | cpx = p.shift();
|
---|
473 | cpy = p.shift();
|
---|
474 | cmd = 'A';
|
---|
475 | points = this.convertEndpointToCenterParameterization(x1, y1, cpx, cpy, fa, fs, rx, ry, psi);
|
---|
476 | break;
|
---|
477 | case 'a':
|
---|
478 | rx = p.shift();
|
---|
479 | ry = p.shift();
|
---|
480 | psi = p.shift();
|
---|
481 | fa = p.shift();
|
---|
482 | fs = p.shift();
|
---|
483 | x1 = cpx;
|
---|
484 | y1 = cpy;
|
---|
485 | cpx += p.shift();
|
---|
486 | cpy += p.shift();
|
---|
487 | cmd = 'A';
|
---|
488 | points = this.convertEndpointToCenterParameterization(x1, y1, cpx, cpy, fa, fs, rx, ry, psi);
|
---|
489 | break;
|
---|
490 | }
|
---|
491 | ca.push({
|
---|
492 | command: cmd || c,
|
---|
493 | points: points,
|
---|
494 | start: {
|
---|
495 | x: startX,
|
---|
496 | y: startY,
|
---|
497 | },
|
---|
498 | pathLength: this.calcLength(startX, startY, cmd || c, points),
|
---|
499 | });
|
---|
500 | }
|
---|
501 | if (c === 'z' || c === 'Z') {
|
---|
502 | ca.push({
|
---|
503 | command: 'z',
|
---|
504 | points: [],
|
---|
505 | start: undefined,
|
---|
506 | pathLength: 0,
|
---|
507 | });
|
---|
508 | }
|
---|
509 | }
|
---|
510 | return ca;
|
---|
511 | }
|
---|
512 | static calcLength(x, y, cmd, points) {
|
---|
513 | var len, p1, p2, t;
|
---|
514 | var path = Path;
|
---|
515 | switch (cmd) {
|
---|
516 | case 'L':
|
---|
517 | return path.getLineLength(x, y, points[0], points[1]);
|
---|
518 | case 'C':
|
---|
519 | return (0, BezierFunctions_1.getCubicArcLength)([x, points[0], points[2], points[4]], [y, points[1], points[3], points[5]], 1);
|
---|
520 | case 'Q':
|
---|
521 | return (0, BezierFunctions_1.getQuadraticArcLength)([x, points[0], points[2]], [y, points[1], points[3]], 1);
|
---|
522 | case 'A':
|
---|
523 | len = 0.0;
|
---|
524 | var start = points[4];
|
---|
525 | var dTheta = points[5];
|
---|
526 | var end = points[4] + dTheta;
|
---|
527 | var inc = Math.PI / 180.0;
|
---|
528 | if (Math.abs(start - end) < inc) {
|
---|
529 | inc = Math.abs(start - end);
|
---|
530 | }
|
---|
531 | p1 = path.getPointOnEllipticalArc(points[0], points[1], points[2], points[3], start, 0);
|
---|
532 | if (dTheta < 0) {
|
---|
533 | for (t = start - inc; t > end; t -= inc) {
|
---|
534 | p2 = path.getPointOnEllipticalArc(points[0], points[1], points[2], points[3], t, 0);
|
---|
535 | len += path.getLineLength(p1.x, p1.y, p2.x, p2.y);
|
---|
536 | p1 = p2;
|
---|
537 | }
|
---|
538 | }
|
---|
539 | else {
|
---|
540 | for (t = start + inc; t < end; t += inc) {
|
---|
541 | p2 = path.getPointOnEllipticalArc(points[0], points[1], points[2], points[3], t, 0);
|
---|
542 | len += path.getLineLength(p1.x, p1.y, p2.x, p2.y);
|
---|
543 | p1 = p2;
|
---|
544 | }
|
---|
545 | }
|
---|
546 | p2 = path.getPointOnEllipticalArc(points[0], points[1], points[2], points[3], end, 0);
|
---|
547 | len += path.getLineLength(p1.x, p1.y, p2.x, p2.y);
|
---|
548 | return len;
|
---|
549 | }
|
---|
550 | return 0;
|
---|
551 | }
|
---|
552 | static convertEndpointToCenterParameterization(x1, y1, x2, y2, fa, fs, rx, ry, psiDeg) {
|
---|
553 | var psi = psiDeg * (Math.PI / 180.0);
|
---|
554 | var xp = (Math.cos(psi) * (x1 - x2)) / 2.0 + (Math.sin(psi) * (y1 - y2)) / 2.0;
|
---|
555 | var yp = (-1 * Math.sin(psi) * (x1 - x2)) / 2.0 +
|
---|
556 | (Math.cos(psi) * (y1 - y2)) / 2.0;
|
---|
557 | var lambda = (xp * xp) / (rx * rx) + (yp * yp) / (ry * ry);
|
---|
558 | if (lambda > 1) {
|
---|
559 | rx *= Math.sqrt(lambda);
|
---|
560 | ry *= Math.sqrt(lambda);
|
---|
561 | }
|
---|
562 | var f = Math.sqrt((rx * rx * (ry * ry) - rx * rx * (yp * yp) - ry * ry * (xp * xp)) /
|
---|
563 | (rx * rx * (yp * yp) + ry * ry * (xp * xp)));
|
---|
564 | if (fa === fs) {
|
---|
565 | f *= -1;
|
---|
566 | }
|
---|
567 | if (isNaN(f)) {
|
---|
568 | f = 0;
|
---|
569 | }
|
---|
570 | var cxp = (f * rx * yp) / ry;
|
---|
571 | var cyp = (f * -ry * xp) / rx;
|
---|
572 | var cx = (x1 + x2) / 2.0 + Math.cos(psi) * cxp - Math.sin(psi) * cyp;
|
---|
573 | var cy = (y1 + y2) / 2.0 + Math.sin(psi) * cxp + Math.cos(psi) * cyp;
|
---|
574 | var vMag = function (v) {
|
---|
575 | return Math.sqrt(v[0] * v[0] + v[1] * v[1]);
|
---|
576 | };
|
---|
577 | var vRatio = function (u, v) {
|
---|
578 | return (u[0] * v[0] + u[1] * v[1]) / (vMag(u) * vMag(v));
|
---|
579 | };
|
---|
580 | var vAngle = function (u, v) {
|
---|
581 | return (u[0] * v[1] < u[1] * v[0] ? -1 : 1) * Math.acos(vRatio(u, v));
|
---|
582 | };
|
---|
583 | var theta = vAngle([1, 0], [(xp - cxp) / rx, (yp - cyp) / ry]);
|
---|
584 | var u = [(xp - cxp) / rx, (yp - cyp) / ry];
|
---|
585 | var v = [(-1 * xp - cxp) / rx, (-1 * yp - cyp) / ry];
|
---|
586 | var dTheta = vAngle(u, v);
|
---|
587 | if (vRatio(u, v) <= -1) {
|
---|
588 | dTheta = Math.PI;
|
---|
589 | }
|
---|
590 | if (vRatio(u, v) >= 1) {
|
---|
591 | dTheta = 0;
|
---|
592 | }
|
---|
593 | if (fs === 0 && dTheta > 0) {
|
---|
594 | dTheta = dTheta - 2 * Math.PI;
|
---|
595 | }
|
---|
596 | if (fs === 1 && dTheta < 0) {
|
---|
597 | dTheta = dTheta + 2 * Math.PI;
|
---|
598 | }
|
---|
599 | return [cx, cy, rx, ry, theta, dTheta, psi, fs];
|
---|
600 | }
|
---|
601 | }
|
---|
602 | exports.Path = Path;
|
---|
603 | Path.prototype.className = 'Path';
|
---|
604 | Path.prototype._attrsAffectingSize = ['data'];
|
---|
605 | (0, Global_1._registerNode)(Path);
|
---|
606 | Factory_1.Factory.addGetterSetter(Path, 'data');
|
---|