1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.segmentArcFactory = void 0;
|
4 | var segment_line_factory_1 = require("./segment-line-factory");
|
5 | var distance_square_root_1 = require("./distance-square-root");
|
6 | function angleBetween(v0, v1) {
|
7 | var v0x = v0.x, v0y = v0.y;
|
8 | var v1x = v1.x, v1y = v1.y;
|
9 | var p = v0x * v1x + v0y * v1y;
|
10 | var n = Math.sqrt((Math.pow(v0x, 2) + Math.pow(v0y, 2)) * (Math.pow(v1x, 2) + Math.pow(v1y, 2)));
|
11 | var sign = v0x * v1y - v0y * v1x < 0 ? -1 : 1;
|
12 | var angle = sign * Math.acos(p / n);
|
13 | return angle;
|
14 | }
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | function getPointAtArcSegmentLength(x1, y1, RX, RY, angle, LAF, SF, x, y, t) {
|
21 | var abs = Math.abs, sin = Math.sin, cos = Math.cos, sqrt = Math.sqrt, PI = Math.PI;
|
22 | var rx = abs(RX);
|
23 | var ry = abs(RY);
|
24 | var xRot = ((angle % 360) + 360) % 360;
|
25 | var xRotRad = xRot * (PI / 180);
|
26 | if (x1 === x && y1 === y) {
|
27 | return { x: x1, y: y1 };
|
28 | }
|
29 | if (rx === 0 || ry === 0) {
|
30 | return (0, segment_line_factory_1.segmentLineFactory)(x1, y1, x, y, t).point;
|
31 | }
|
32 | var dx = (x1 - x) / 2;
|
33 | var dy = (y1 - y) / 2;
|
34 | var transformedPoint = {
|
35 | x: cos(xRotRad) * dx + sin(xRotRad) * dy,
|
36 | y: -sin(xRotRad) * dx + cos(xRotRad) * dy,
|
37 | };
|
38 | var radiiCheck = Math.pow(transformedPoint.x, 2) / Math.pow(rx, 2) + Math.pow(transformedPoint.y, 2) / Math.pow(ry, 2);
|
39 | if (radiiCheck > 1) {
|
40 | rx *= sqrt(radiiCheck);
|
41 | ry *= sqrt(radiiCheck);
|
42 | }
|
43 | var cSquareNumerator = Math.pow(rx, 2) * Math.pow(ry, 2) - Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) - Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
|
44 | var cSquareRootDenom = Math.pow(rx, 2) * Math.pow(transformedPoint.y, 2) + Math.pow(ry, 2) * Math.pow(transformedPoint.x, 2);
|
45 | var cRadicand = cSquareNumerator / cSquareRootDenom;
|
46 | cRadicand = cRadicand < 0 ? 0 : cRadicand;
|
47 | var cCoef = (LAF !== SF ? 1 : -1) * sqrt(cRadicand);
|
48 | var transformedCenter = {
|
49 | x: cCoef * ((rx * transformedPoint.y) / ry),
|
50 | y: cCoef * (-(ry * transformedPoint.x) / rx),
|
51 | };
|
52 | var center = {
|
53 | x: cos(xRotRad) * transformedCenter.x - sin(xRotRad) * transformedCenter.y + (x1 + x) / 2,
|
54 | y: sin(xRotRad) * transformedCenter.x + cos(xRotRad) * transformedCenter.y + (y1 + y) / 2,
|
55 | };
|
56 | var startVector = {
|
57 | x: (transformedPoint.x - transformedCenter.x) / rx,
|
58 | y: (transformedPoint.y - transformedCenter.y) / ry,
|
59 | };
|
60 | var startAngle = angleBetween({ x: 1, y: 0 }, startVector);
|
61 | var endVector = {
|
62 | x: (-transformedPoint.x - transformedCenter.x) / rx,
|
63 | y: (-transformedPoint.y - transformedCenter.y) / ry,
|
64 | };
|
65 | var sweepAngle = angleBetween(startVector, endVector);
|
66 | if (!SF && sweepAngle > 0) {
|
67 | sweepAngle -= 2 * PI;
|
68 | }
|
69 | else if (SF && sweepAngle < 0) {
|
70 | sweepAngle += 2 * PI;
|
71 | }
|
72 | sweepAngle %= 2 * PI;
|
73 | var alpha = startAngle + sweepAngle * t;
|
74 | var ellipseComponentX = rx * cos(alpha);
|
75 | var ellipseComponentY = ry * sin(alpha);
|
76 | var point = {
|
77 | x: cos(xRotRad) * ellipseComponentX - sin(xRotRad) * ellipseComponentY + center.x,
|
78 | y: sin(xRotRad) * ellipseComponentX + cos(xRotRad) * ellipseComponentY + center.y,
|
79 | };
|
80 |
|
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 | return point;
|
88 | }
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 | function segmentArcFactory(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, distance, options) {
|
96 | var _a;
|
97 | var _b = options.bbox, bbox = _b === void 0 ? true : _b, _c = options.length, length = _c === void 0 ? true : _c, _d = options.sampleSize, sampleSize = _d === void 0 ? 30 : _d;
|
98 | var distanceIsNumber = typeof distance === 'number';
|
99 | var x = X1;
|
100 | var y = Y1;
|
101 | var LENGTH = 0;
|
102 | var prev = [x, y, LENGTH];
|
103 | var cur = [x, y];
|
104 | var t = 0;
|
105 | var POINT = { x: 0, y: 0 };
|
106 | var POINTS = [{ x: x, y: y }];
|
107 | if (distanceIsNumber && distance <= 0) {
|
108 | POINT = { x: x, y: y };
|
109 | }
|
110 |
|
111 | for (var j = 0; j <= sampleSize; j += 1) {
|
112 | t = j / sampleSize;
|
113 | (_a = getPointAtArcSegmentLength(X1, Y1, RX, RY, angle, LAF, SF, X2, Y2, t), x = _a.x, y = _a.y);
|
114 | if (bbox) {
|
115 | POINTS.push({ x: x, y: y });
|
116 | }
|
117 | if (length) {
|
118 | LENGTH += (0, distance_square_root_1.distanceSquareRoot)(cur, [x, y]);
|
119 | }
|
120 | cur = [x, y];
|
121 | if (distanceIsNumber && LENGTH >= distance && distance > prev[2]) {
|
122 | var dv = (LENGTH - distance) / (LENGTH - prev[2]);
|
123 | POINT = {
|
124 | x: cur[0] * (1 - dv) + prev[0] * dv,
|
125 | y: cur[1] * (1 - dv) + prev[1] * dv,
|
126 | };
|
127 | }
|
128 | prev = [x, y, LENGTH];
|
129 | }
|
130 | if (distanceIsNumber && distance >= LENGTH) {
|
131 | POINT = { x: X2, y: Y2 };
|
132 | }
|
133 | return {
|
134 | length: LENGTH,
|
135 | point: POINT,
|
136 | min: {
|
137 | x: Math.min.apply(null, POINTS.map(function (n) { return n.x; })),
|
138 | y: Math.min.apply(null, POINTS.map(function (n) { return n.y; })),
|
139 | },
|
140 | max: {
|
141 | x: Math.max.apply(null, POINTS.map(function (n) { return n.x; })),
|
142 | y: Math.max.apply(null, POINTS.map(function (n) { return n.y; })),
|
143 | },
|
144 | };
|
145 | }
|
146 | exports.segmentArcFactory = segmentArcFactory;
|
147 |
|
\ | No newline at end of file |