geometrix 0.5.10 → 0.5.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +505 -0
- package/dist/index.js +3848 -0
- package/package.json +7 -1
- package/.eslintignore +0 -17
- package/.eslintrc.cjs +0 -24
- package/.prettierignore +0 -15
- package/.prettierrc +0 -8
- package/src/aaExportContent.ts +0 -213
- package/src/aaExportFile.ts +0 -141
- package/src/aaParamGeom.ts +0 -62
- package/src/angle_utils.test.ts +0 -83
- package/src/angle_utils.ts +0 -98
- package/src/arc_to_stroke.ts +0 -73
- package/src/canvas_utils.test.ts +0 -28
- package/src/canvas_utils.ts +0 -159
- package/src/contour.test.ts +0 -37
- package/src/contour.ts +0 -806
- package/src/designParams.ts +0 -178
- package/src/figure.test.ts +0 -21
- package/src/figure.ts +0 -400
- package/src/index.ts +0 -16
- package/src/line.test.ts +0 -78
- package/src/line.ts +0 -359
- package/src/paramFile.ts +0 -52
- package/src/point.test.ts +0 -36
- package/src/point.ts +0 -246
- package/src/prepare_pax.ts +0 -102
- package/src/segment.test.ts +0 -26
- package/src/segment.ts +0 -701
- package/src/sub_design.ts +0 -16
- package/src/triangle_utils.test.ts +0 -38
- package/src/triangle_utils.ts +0 -112
- package/src/vector.test.ts +0 -28
- package/src/vector.ts +0 -122
- package/src/volume.ts +0 -50
- package/src/write_dxf.ts +0 -100
- package/src/write_openjscad.ts +0 -284
- package/src/write_openscad.ts +0 -305
- package/src/write_pax.ts +0 -73
- package/src/write_svg.ts +0 -101
- package/svg/any_triangle.svg +0 -156
- package/svg/arc_definition.svg +0 -506
- package/svg/construct_corner_rounded_ext_arc_ext_arc.svg +0 -378
- package/svg/construct_corner_rounded_int_arc_ext_arc.svg +0 -359
- package/svg/construct_corner_rounded_int_arc_int_arc.svg +0 -356
- package/svg/construct_corner_rounded_stroke_ext_arc.svg +0 -374
- package/svg/construct_corner_rounded_stroke_ext_arc_obtuse.svg +0 -370
- package/svg/construct_corner_rounded_stroke_ext_arc_obtuse_method2.svg +0 -311
- package/svg/construct_corner_rounded_stroke_int_arc.svg +0 -364
- package/svg/construct_corner_rounded_stroke_int_arc_obtuse.svg +0 -358
- package/svg/construct_corner_rounded_stroke_int_arc_obtuse_method2.svg +0 -237
- package/svg/construct_corner_rounded_stroke_stroke.svg +0 -280
- package/svg/construct_corner_wideacc.svg +0 -286
- package/svg/construct_corner_widened.svg +0 -278
- package/svg/construction_of_line_intersection_1.svg +0 -187
- package/svg/construction_of_line_intersection_2.svg +0 -189
- package/svg/contour_arc_definition_options.svg +0 -324
- package/svg/contour_point_absolute_relative.svg +0 -258
- package/svg/contour_tangential_two_arcs.svg +0 -531
- package/svg/contour_tangential_two_arcs_impossible_case.svg +0 -175
- package/svg/contour_tangential_two_arcs_requirements.svg +0 -364
- package/svg/corner_rounded_ext_arc_ext_arc.svg +0 -281
- package/svg/corner_rounded_int_arc_ext_arc.svg +0 -281
- package/svg/corner_rounded_int_arc_int_arc.svg +0 -279
- package/svg/corner_rounded_stroke_ext_arc.svg +0 -218
- package/svg/corner_rounded_stroke_int_arc.svg +0 -225
- package/svg/corner_rounded_stroke_stroke.svg +0 -174
- package/svg/geom_dev.svg +0 -14708
- package/svg/geom_modules.svg +0 -246
- package/svg/geom_user.svg +0 -58
- package/svg/line_axis_x_cases.svg +0 -1408
- package/svg/line_axis_y_cases.svg +0 -1369
- package/svg/line_distanceOrig.svg +0 -318
- package/svg/line_getAxisXIntersection.svg +0 -262
- package/svg/line_getAxisXIntersection_2.svg +0 -244
- package/svg/line_getAxisYIntersection.svg +0 -304
- package/svg/line_getAxisYIntersection_2.svg +0 -285
- package/svg/line_getAxisYIntersection_3.svg +0 -277
- package/svg/line_intersection.svg +0 -346
- package/svg/line_projectPoint.svg +0 -311
- package/svg/point_1.svg +0 -243
- package/svg/point_2.svg +0 -409
- package/svg/point_3.svg +0 -298
- package/svg/point_4.svg +0 -272
- package/svg/point_5.svg +0 -356
- package/svg/right_triangle.svg +0 -194
- package/svg/vector_definition.svg +0 -130
- package/tsconfig.json +0 -13
- package/vitest.config.ts +0 -7
package/src/line.ts
DELETED
|
@@ -1,359 +0,0 @@
|
|
|
1
|
-
// line.ts
|
|
2
|
-
// line.ts deals with lines
|
|
3
|
-
// line.ts depends on angle_utils.ts, triangle_utils.ts and point.ts
|
|
4
|
-
|
|
5
|
-
import type { tCanvasAdjust } from './canvas_utils';
|
|
6
|
-
//import type { tPolar } from './point';
|
|
7
|
-
//import { colorCanvasPoint } from '$lib/style/colors.scss';
|
|
8
|
-
import { colors, point2canvas } from './canvas_utils';
|
|
9
|
-
import {
|
|
10
|
-
//degToRad,
|
|
11
|
-
//radToDeg,
|
|
12
|
-
roundZero,
|
|
13
|
-
//withinZero2Pi,
|
|
14
|
-
withinPiPi,
|
|
15
|
-
withinZeroPi,
|
|
16
|
-
withinHPiHPi
|
|
17
|
-
} from './angle_utils';
|
|
18
|
-
import {
|
|
19
|
-
//rightTriLaFromLbLc,
|
|
20
|
-
//rightTriLbFromLaLc,
|
|
21
|
-
//lcFromLaLbAc,
|
|
22
|
-
//aCFromLaLbLc,
|
|
23
|
-
//aCFromAaAb
|
|
24
|
-
lbFromLaAaAb
|
|
25
|
-
//aBFromLaLbAa
|
|
26
|
-
} from './triangle_utils';
|
|
27
|
-
import { point, Point } from './point';
|
|
28
|
-
|
|
29
|
-
interface tAffine {
|
|
30
|
-
quasiVertical: boolean;
|
|
31
|
-
ha: number;
|
|
32
|
-
hb: number;
|
|
33
|
-
va: number;
|
|
34
|
-
vb: number;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/* Base classes */
|
|
38
|
-
|
|
39
|
-
class Line {
|
|
40
|
-
cx: number;
|
|
41
|
-
cy: number;
|
|
42
|
-
ca: number;
|
|
43
|
-
constructor(ix: number, iy: number, ia: number) {
|
|
44
|
-
this.cx = ix;
|
|
45
|
-
this.cy = iy;
|
|
46
|
-
this.ca = ia;
|
|
47
|
-
}
|
|
48
|
-
draw(ctx: CanvasRenderingContext2D, cAdjust: tCanvasAdjust, color: string = colors.line) {
|
|
49
|
-
const display_length = ctx.canvas.width * 2;
|
|
50
|
-
const [cx1, cy1] = point2canvas(
|
|
51
|
-
this.cx - display_length * Math.cos(this.ca),
|
|
52
|
-
this.cy - display_length * Math.sin(this.ca),
|
|
53
|
-
cAdjust
|
|
54
|
-
);
|
|
55
|
-
const [cx2, cy2] = point2canvas(
|
|
56
|
-
this.cx + 2 * display_length * Math.cos(this.ca),
|
|
57
|
-
this.cy + 2 * display_length * Math.sin(this.ca),
|
|
58
|
-
cAdjust
|
|
59
|
-
);
|
|
60
|
-
ctx.beginPath();
|
|
61
|
-
ctx.moveTo(cx1, cy1);
|
|
62
|
-
ctx.lineTo(cx2, cy2);
|
|
63
|
-
ctx.strokeStyle = color;
|
|
64
|
-
ctx.stroke();
|
|
65
|
-
}
|
|
66
|
-
setFromPoints(p1: Point, p2: Point) {
|
|
67
|
-
this.cx = p1.cx;
|
|
68
|
-
this.cy = p1.cy;
|
|
69
|
-
this.ca = p1.angleToPoint(p2);
|
|
70
|
-
return this;
|
|
71
|
-
}
|
|
72
|
-
getAffine(): tAffine {
|
|
73
|
-
const rAffine: tAffine = { quasiVertical: false, ha: 0, hb: 0, va: 0, vb: 0 };
|
|
74
|
-
const angleZeroHPi = Math.abs(withinHPiHPi(this.ca));
|
|
75
|
-
if (angleZeroHPi > Math.PI / 4) {
|
|
76
|
-
// x = va * y + vb
|
|
77
|
-
rAffine.quasiVertical = true;
|
|
78
|
-
rAffine.va = -1 * Math.tan(withinHPiHPi(this.ca - Math.PI / 2));
|
|
79
|
-
rAffine.vb = this.cx - rAffine.va * this.cy;
|
|
80
|
-
} else {
|
|
81
|
-
// y = ha * x + hb
|
|
82
|
-
rAffine.ha = Math.tan(withinHPiHPi(this.ca));
|
|
83
|
-
rAffine.hb = this.cy - rAffine.ha * this.cx;
|
|
84
|
-
}
|
|
85
|
-
return rAffine;
|
|
86
|
-
}
|
|
87
|
-
setAffine(iAffine: tAffine): Line {
|
|
88
|
-
const rLine = new Line(0, 0, 0);
|
|
89
|
-
if (iAffine.quasiVertical) {
|
|
90
|
-
rLine.ca = Math.PI / 2 - Math.atan(iAffine.va);
|
|
91
|
-
rLine.cx = iAffine.vb;
|
|
92
|
-
rLine.cy = 0;
|
|
93
|
-
} else {
|
|
94
|
-
rLine.ca = Math.atan(iAffine.ha);
|
|
95
|
-
rLine.cx = 0;
|
|
96
|
-
rLine.cy = iAffine.hb;
|
|
97
|
-
}
|
|
98
|
-
return rLine;
|
|
99
|
-
}
|
|
100
|
-
// intersection
|
|
101
|
-
intersection(il: Line): Point {
|
|
102
|
-
if (this.isParallel(il)) {
|
|
103
|
-
throw `err902: no intersection, lines are parallel ca1: ${this.ca} ca2: ${il.ca}`;
|
|
104
|
-
}
|
|
105
|
-
let rx = 0;
|
|
106
|
-
let ry = 0;
|
|
107
|
-
const affin1 = this.getAffine();
|
|
108
|
-
const affin2 = il.getAffine();
|
|
109
|
-
if (affin1.quasiVertical) {
|
|
110
|
-
if (affin2.quasiVertical) {
|
|
111
|
-
// x = va1 * y + vb1; x = va2 * y + vb2
|
|
112
|
-
// y = (vb1 - vb2) / (va2 - va1)
|
|
113
|
-
ry = (affin1.vb - affin2.vb) / (affin2.va - affin1.va);
|
|
114
|
-
rx = affin1.va * ry + affin1.vb;
|
|
115
|
-
} else {
|
|
116
|
-
// x = va1 * y + vb1; y = ha2 * x + hb2
|
|
117
|
-
// x = va1 * (ha2 * x + hb2) + vb1; x = ((va1 * hb2) + vb1) / (1 - va1 * ha2)
|
|
118
|
-
rx = (affin1.va * affin2.hb + affin1.vb) / (1 - affin1.va * affin2.ha);
|
|
119
|
-
ry = affin2.ha * rx + affin2.hb;
|
|
120
|
-
}
|
|
121
|
-
} else {
|
|
122
|
-
if (affin2.quasiVertical) {
|
|
123
|
-
// y = ha1 * x + hb1; x = va2 * y + vb2
|
|
124
|
-
// y = ha1 * (va2 * y + vb2) + hb1; y = ((ha1 * vb2) + hb1) / (1 - ha1 * va2)
|
|
125
|
-
ry = (affin1.ha * affin2.vb + affin1.hb) / (1 - affin1.ha * affin2.va);
|
|
126
|
-
rx = affin2.va * ry + affin2.vb;
|
|
127
|
-
} else {
|
|
128
|
-
// y = ha1 * x + hb1; y = ha2 * x + hb2
|
|
129
|
-
// y = (hb1 - hb2) / (ha2 - ha1)
|
|
130
|
-
rx = (affin1.hb - affin2.hb) / (affin2.ha - affin1.ha);
|
|
131
|
-
ry = affin1.ha * rx + affin1.hb;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
const rp = point(rx, ry);
|
|
135
|
-
return rp;
|
|
136
|
-
}
|
|
137
|
-
getAxisXIntersection(): number {
|
|
138
|
-
const c_axisX = new Line(0, 0, 0);
|
|
139
|
-
const rp = this.intersection(c_axisX);
|
|
140
|
-
return rp.cx;
|
|
141
|
-
}
|
|
142
|
-
getAxisYIntersection(): number {
|
|
143
|
-
const c_axisY = new Line(0, 0, Math.PI / 2);
|
|
144
|
-
const rp = this.intersection(c_axisY);
|
|
145
|
-
return rp.cy;
|
|
146
|
-
}
|
|
147
|
-
getAxisXIntersecTri(): number {
|
|
148
|
-
let rX = Infinity;
|
|
149
|
-
if (roundZero(withinHPiHPi(this.ca)) !== 0) {
|
|
150
|
-
const p1 = new Point(this.cx, this.cy);
|
|
151
|
-
const l1ca = withinZeroPi(this.ca);
|
|
152
|
-
const aC = p1.angleOrig();
|
|
153
|
-
const la = p1.distanceOrig();
|
|
154
|
-
if (roundZero(la) === 0) {
|
|
155
|
-
rX = 0;
|
|
156
|
-
} else if (roundZero(withinHPiHPi(l1ca - aC)) === 0) {
|
|
157
|
-
rX = 0;
|
|
158
|
-
} else {
|
|
159
|
-
const aA = Math.min(l1ca, Math.PI - l1ca);
|
|
160
|
-
const aB = withinPiPi(l1ca - aC);
|
|
161
|
-
const aB2 = Math.min(Math.abs(aB), Math.PI - Math.abs(aB));
|
|
162
|
-
rX = Math.sign(aB) * lbFromLaAaAb(la, aA, aB2);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
return rX;
|
|
166
|
-
}
|
|
167
|
-
getAxisYIntersecTri(): number {
|
|
168
|
-
let rY = Infinity;
|
|
169
|
-
if (roundZero(withinHPiHPi(this.ca - Math.PI / 2)) !== 0) {
|
|
170
|
-
const p1 = new Point(this.cx, this.cy);
|
|
171
|
-
const l1ca = withinHPiHPi(this.ca);
|
|
172
|
-
const aC = p1.angleOrig();
|
|
173
|
-
const la = p1.distanceOrig();
|
|
174
|
-
const angleDiff = withinHPiHPi(l1ca - aC);
|
|
175
|
-
if (roundZero(la) === 0) {
|
|
176
|
-
rY = 0;
|
|
177
|
-
} else if (roundZero(angleDiff) === 0) {
|
|
178
|
-
rY = 0;
|
|
179
|
-
} else {
|
|
180
|
-
const aA = withinZeroPi(l1ca - Math.PI / 2);
|
|
181
|
-
const aB = -1 * withinPiPi(l1ca - aC);
|
|
182
|
-
const aA2 = Math.min(aA, Math.PI - aA);
|
|
183
|
-
const aB2 = Math.min(Math.abs(aB), Math.PI - Math.abs(aB));
|
|
184
|
-
rY = Math.sign(aB) * lbFromLaAaAb(la, aA2, aB2);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return rY;
|
|
188
|
-
}
|
|
189
|
-
angleOrig(): number {
|
|
190
|
-
// compute direction, i.e. top-side or bottom-side
|
|
191
|
-
const p1 = new Point(this.cx, this.cy);
|
|
192
|
-
const aC = p1.angleOrig();
|
|
193
|
-
const l1ca = withinHPiHPi(this.ca);
|
|
194
|
-
const aB = -1 * withinPiPi(l1ca - aC);
|
|
195
|
-
let direction = 0;
|
|
196
|
-
if (aB < 0) {
|
|
197
|
-
direction = -Math.PI;
|
|
198
|
-
}
|
|
199
|
-
// end of direction calculation
|
|
200
|
-
const ra = withinZeroPi(Math.PI / 2 + this.ca) + direction;
|
|
201
|
-
return ra;
|
|
202
|
-
}
|
|
203
|
-
distanceOrig(): number {
|
|
204
|
-
const a1 = this.angleOrig();
|
|
205
|
-
const p1 = new Point(this.cx, this.cy);
|
|
206
|
-
const a2 = p1.angleOrig();
|
|
207
|
-
const la = p1.distanceOrig();
|
|
208
|
-
const a12 = withinHPiHPi(a2 - a1);
|
|
209
|
-
const rd = la * Math.cos(a12);
|
|
210
|
-
return rd;
|
|
211
|
-
}
|
|
212
|
-
projectOrig(): Point {
|
|
213
|
-
const pa = this.angleOrig();
|
|
214
|
-
const pl = this.distanceOrig();
|
|
215
|
-
return point(0, 0).setPolar(pa, pl);
|
|
216
|
-
}
|
|
217
|
-
// methods inherited from point
|
|
218
|
-
translate(ix: number, iy: number): Line {
|
|
219
|
-
return new Line(this.cx + ix, this.cy + iy, this.ca);
|
|
220
|
-
}
|
|
221
|
-
rotateOrig(ia: number): Line {
|
|
222
|
-
// rotation with the origin as center
|
|
223
|
-
const lPoint2 = new Point(this.cx, this.cy).rotateOrig(ia);
|
|
224
|
-
return new Line(lPoint2.cx, lPoint2.cy, withinPiPi(this.ca + ia));
|
|
225
|
-
}
|
|
226
|
-
scaleOrig(ir: number): Line {
|
|
227
|
-
const lPoint2 = new Point(this.cx, this.cy).scaleOrig(ir);
|
|
228
|
-
return new Line(lPoint2.cx, lPoint2.cy, this.ca);
|
|
229
|
-
}
|
|
230
|
-
rotate(ic: Point, ia: number): Line {
|
|
231
|
-
const lPoint2 = new Point(this.cx, this.cy).rotate(ic, ia);
|
|
232
|
-
return new Line(lPoint2.cx, lPoint2.cy, withinPiPi(this.ca + ia));
|
|
233
|
-
}
|
|
234
|
-
scale(ic: Point, ir: number): Line {
|
|
235
|
-
const lPoint2 = new Point(this.cx, this.cy).scale(ic, ir);
|
|
236
|
-
return new Line(lPoint2.cx, lPoint2.cy, this.ca);
|
|
237
|
-
}
|
|
238
|
-
clone(): Line {
|
|
239
|
-
const lPoint2 = new Point(this.cx, this.cy);
|
|
240
|
-
return new Line(lPoint2.cx, lPoint2.cy, this.ca);
|
|
241
|
-
}
|
|
242
|
-
// end of methods from point
|
|
243
|
-
// line creation
|
|
244
|
-
lineOrthogonal(ic: Point): Line {
|
|
245
|
-
return new Line(ic.cx, ic.cy, this.ca + Math.PI / 2);
|
|
246
|
-
}
|
|
247
|
-
lineParallel(ic: Point): Line {
|
|
248
|
-
return new Line(ic.cx, ic.cy, this.ca);
|
|
249
|
-
}
|
|
250
|
-
// orthogonal projection
|
|
251
|
-
distanceToPoint(ic: Point): number {
|
|
252
|
-
let rd = 0;
|
|
253
|
-
const p1 = new Point(this.cx, this.cy);
|
|
254
|
-
const lp1ic = p1.distanceToPoint(ic);
|
|
255
|
-
if (roundZero(lp1ic) !== 0) {
|
|
256
|
-
const aC = p1.angleToPoint(ic);
|
|
257
|
-
const aB = withinHPiHPi(aC - this.ca);
|
|
258
|
-
rd = lp1ic * Math.abs(Math.sin(aB));
|
|
259
|
-
}
|
|
260
|
-
return rd;
|
|
261
|
-
}
|
|
262
|
-
projectPoint(ic: Point): Point {
|
|
263
|
-
let rd = 0;
|
|
264
|
-
const p1 = new Point(this.cx, this.cy);
|
|
265
|
-
const lp1ic = p1.distanceToPoint(ic);
|
|
266
|
-
if (roundZero(lp1ic) !== 0) {
|
|
267
|
-
const aC = p1.angleToPoint(ic);
|
|
268
|
-
const aB = withinPiPi(aC - this.ca);
|
|
269
|
-
rd = lp1ic * Math.cos(aB);
|
|
270
|
-
}
|
|
271
|
-
const rp = p1.translatePolar(this.ca, rd);
|
|
272
|
-
return rp;
|
|
273
|
-
}
|
|
274
|
-
// line comparison
|
|
275
|
-
isParallel(il: Line): boolean {
|
|
276
|
-
const rb = roundZero(withinHPiHPi(this.ca - il.ca)) === 0;
|
|
277
|
-
return rb;
|
|
278
|
-
}
|
|
279
|
-
isOrthogonal(il: Line): boolean {
|
|
280
|
-
const rb = roundZero(withinHPiHPi(Math.PI / 2 + this.ca - il.ca)) === 0;
|
|
281
|
-
return rb;
|
|
282
|
-
}
|
|
283
|
-
isEqual(il: Line): boolean {
|
|
284
|
-
const p2 = point(il.cx, il.cy);
|
|
285
|
-
const dist = this.distanceToPoint(p2);
|
|
286
|
-
const rb = roundZero(dist) === 0 && this.isParallel(il);
|
|
287
|
-
return rb;
|
|
288
|
-
}
|
|
289
|
-
// bisector
|
|
290
|
-
bisector(il: Line, ip: Point): Line {
|
|
291
|
-
const pInter = this.intersection(il);
|
|
292
|
-
const a1t = withinZeroPi(this.ca);
|
|
293
|
-
const a2t = withinZeroPi(il.ca);
|
|
294
|
-
const a1 = Math.min(a1t, a2t);
|
|
295
|
-
const a2 = Math.max(a1t, a2t);
|
|
296
|
-
const aList = [a1, a2, a1 + Math.PI, a2 + Math.PI, a1];
|
|
297
|
-
const aRef = pInter.angleToPoint(ip);
|
|
298
|
-
let idx = 0;
|
|
299
|
-
for (let i = 0; i < 4; i++) {
|
|
300
|
-
const aDiff1 = withinPiPi(aList[i] - aRef);
|
|
301
|
-
const aDiff2 = withinPiPi(aList[i + 1] - aRef);
|
|
302
|
-
if (aDiff1 === 0 || aDiff2 === 0) {
|
|
303
|
-
throw `err419: bad reference point for bisecor ${ip.cx} ${ip.cy}`;
|
|
304
|
-
}
|
|
305
|
-
if (aDiff1 < 0 && aDiff2 > 0) {
|
|
306
|
-
idx = i;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
const a0 = withinZeroPi((a1 + a2) / 2);
|
|
310
|
-
const ca = a0 + (idx * Math.PI) / 2;
|
|
311
|
-
return new Line(pInter.cx, pInter.cy, ca);
|
|
312
|
-
}
|
|
313
|
-
// parallel distance
|
|
314
|
-
lineParallelDistance(iDist: number, ipMagnet: Point, ipMagnet2: Point): Line {
|
|
315
|
-
const p1 = point(this.cx, this.cy);
|
|
316
|
-
const p2a = p1.translatePolar(this.ca + Math.PI / 2, iDist);
|
|
317
|
-
const p2b = p1.translatePolar(this.ca - Math.PI / 2, iDist);
|
|
318
|
-
let p2 = p2b;
|
|
319
|
-
let pMagnet = ipMagnet;
|
|
320
|
-
if (roundZero(this.distanceToPoint(pMagnet)) === 0) {
|
|
321
|
-
pMagnet = ipMagnet2;
|
|
322
|
-
}
|
|
323
|
-
if (pMagnet.distanceToPoint(p2a) < pMagnet.distanceToPoint(p2b)) {
|
|
324
|
-
p2 = p2a;
|
|
325
|
-
}
|
|
326
|
-
return new Line(p2.cx, p2.cy, this.ca);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
function line(ix: number, iy: number, ia: number): Line {
|
|
331
|
-
return new Line(ix, iy, ia);
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
function linePP(ip1: Point, ip2: Point): Line {
|
|
335
|
-
const rline = line(0, 0, 0).setFromPoints(ip1, ip2);
|
|
336
|
-
return rline;
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
function bisector(ip1: Point, ip2: Point): Line {
|
|
340
|
-
if (ip1.isEqual(ip2)) {
|
|
341
|
-
throw `err546: no bisector with two same points cx: ${ip1.cx} cy: ${ip1.cy}`;
|
|
342
|
-
}
|
|
343
|
-
const pbi = ip1.middlePoint(ip2);
|
|
344
|
-
const abi = withinZeroPi(ip1.angleToPoint(ip2) + Math.PI / 2);
|
|
345
|
-
return line(pbi.cx, pbi.cy, abi);
|
|
346
|
-
}
|
|
347
|
-
function circleCenter(ip1: Point, ip2: Point, ip3: Point): Point {
|
|
348
|
-
if (ip1.isEqual(ip2) || ip2.isEqual(ip3) || ip1.isEqual(ip3)) {
|
|
349
|
-
throw `err833: no bisector with two same points cx: ${ip1.cx} cy: ${ip1.cy}`;
|
|
350
|
-
}
|
|
351
|
-
const bisec1 = bisector(ip1, ip2);
|
|
352
|
-
const bisec2 = bisector(ip2, ip3);
|
|
353
|
-
const rp = bisec1.intersection(bisec2);
|
|
354
|
-
return rp;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
/* export */
|
|
358
|
-
|
|
359
|
-
export { Line, line, linePP, bisector, circleCenter };
|
package/src/paramFile.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
// paramFile.ts
|
|
2
|
-
|
|
3
|
-
import type { tParamVal } from './designParams';
|
|
4
|
-
|
|
5
|
-
interface tParamValInFile {
|
|
6
|
-
lastModif: string;
|
|
7
|
-
pVal: tParamVal;
|
|
8
|
-
comment: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function createParamFile(lastModif: string, idparams: tParamVal, comment: string): string {
|
|
12
|
-
const allVal: tParamValInFile = {
|
|
13
|
-
lastModif: lastModif,
|
|
14
|
-
pVal: idparams,
|
|
15
|
-
comment: comment
|
|
16
|
-
};
|
|
17
|
-
const fContentStr = JSON.stringify(allVal, null, ' ');
|
|
18
|
-
return fContentStr;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
function parseParamFile(fContentStr: string): [tParamValInFile, string] {
|
|
22
|
-
const wholeJson = JSON.parse(fContentStr) as tParamValInFile;
|
|
23
|
-
const lastModifKey = 'lastModif';
|
|
24
|
-
const pValKey = 'pVal';
|
|
25
|
-
const commentKey = 'comment';
|
|
26
|
-
let rlog = '';
|
|
27
|
-
const rObj: tParamValInFile = { lastModif: '', pVal: {}, comment: '' };
|
|
28
|
-
if (Object.hasOwn(wholeJson, lastModifKey)) {
|
|
29
|
-
rObj[lastModifKey] = wholeJson[lastModifKey];
|
|
30
|
-
}
|
|
31
|
-
if (Object.hasOwn(wholeJson, pValKey)) {
|
|
32
|
-
const paNaVa = wholeJson[pValKey];
|
|
33
|
-
for (const paNa of Object.keys(paNaVa)) {
|
|
34
|
-
const paVa = paNaVa[paNa];
|
|
35
|
-
//const paVa = parseFloat(paVaStr);
|
|
36
|
-
if (isNaN(paVa)) {
|
|
37
|
-
throw `err905: ${paVa} is not a number!`;
|
|
38
|
-
}
|
|
39
|
-
rObj[pValKey][paNa] = paVa;
|
|
40
|
-
}
|
|
41
|
-
rlog += `info398: parsing file has found ${Object.keys(rObj[pValKey]).length} parameters\n`;
|
|
42
|
-
} else {
|
|
43
|
-
throw `err489: parameter-json-file has no key ${pValKey}\n`;
|
|
44
|
-
}
|
|
45
|
-
if (Object.hasOwn(wholeJson, commentKey)) {
|
|
46
|
-
rObj[commentKey] = wholeJson[commentKey];
|
|
47
|
-
}
|
|
48
|
-
return [rObj, rlog];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export type { tParamValInFile };
|
|
52
|
-
export { createParamFile, parseParamFile };
|
package/src/point.test.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from 'vitest';
|
|
2
|
-
//import type { tPolar } from './point';
|
|
3
|
-
import { Point, point } from './point';
|
|
4
|
-
|
|
5
|
-
describe('point module', () => {
|
|
6
|
-
const p1 = new Point(5, 5);
|
|
7
|
-
const p2 = point(8, 9);
|
|
8
|
-
const p3 = point(25, 25);
|
|
9
|
-
it('Point class basic', () => {
|
|
10
|
-
expect(p1.distanceOrig()).toBeCloseTo(5 * Math.sqrt(2), 5);
|
|
11
|
-
expect(p1.isEqual(p1)).toBe(true);
|
|
12
|
-
expect(p1.isEqual(p3)).toBeFalsy();
|
|
13
|
-
});
|
|
14
|
-
it('Point translate', () => {
|
|
15
|
-
expect(p1.translate(1, 2).isEqual(point(6, 7))).toBeTruthy();
|
|
16
|
-
expect(p1.translatePolar(Math.PI / 2, 10).isEqual(point(5, 15))).toBeTruthy();
|
|
17
|
-
});
|
|
18
|
-
it('distanceToPoint function', () => {
|
|
19
|
-
expect(p1.distanceToPoint(p2)).toBeCloseTo(5);
|
|
20
|
-
});
|
|
21
|
-
it('angleToPoint function', () => {
|
|
22
|
-
expect(p1.angleToPoint(p3)).toBeCloseTo(Math.PI / 4, 5);
|
|
23
|
-
});
|
|
24
|
-
const p4 = point(5, -1);
|
|
25
|
-
const p5 = point(15, 5);
|
|
26
|
-
it('point creation middle', () => {
|
|
27
|
-
expect(p1.middlePoint(p4).isEqual(point(5, 2))).toBeTruthy();
|
|
28
|
-
});
|
|
29
|
-
it('point creation equidistance', () => {
|
|
30
|
-
expect(() => p1.equidistantPoint(p4, 2, p2)).toThrowError(/err392/);
|
|
31
|
-
expect(p1.equidistantPoint(p4, 5, p2).isEqual(point(9, 2))).toBeTruthy();
|
|
32
|
-
expect(p1.equidistantPoint(p4, 10, p2).isEqual(point(9, 3))).toBeFalsy();
|
|
33
|
-
expect(() => p1.equidistantPoint(p1, 10, p2)).toThrowError(/err633/);
|
|
34
|
-
expect(p1.equidistantPoint(p5, 5, p2).isEqual(point(10, 5))).toBeTruthy();
|
|
35
|
-
});
|
|
36
|
-
});
|
package/src/point.ts
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
// point.ts
|
|
2
|
-
// point.ts deals with points
|
|
3
|
-
// point.ts depends on canvas_utils.ts
|
|
4
|
-
|
|
5
|
-
import type { tCanvasAdjust } from './canvas_utils';
|
|
6
|
-
//import { colorCanvasPoint } from '$lib/style/colors.scss';
|
|
7
|
-
import { colors, point2canvas } from './canvas_utils';
|
|
8
|
-
import { roundZero, withinPiPi } from './angle_utils';
|
|
9
|
-
|
|
10
|
-
type tPolar = [number, number]; // angle, distance
|
|
11
|
-
enum ShapePoint {
|
|
12
|
-
eDefault,
|
|
13
|
-
eCircle,
|
|
14
|
-
eCross,
|
|
15
|
-
eSquare,
|
|
16
|
-
eBigSquare,
|
|
17
|
-
eTwoTri,
|
|
18
|
-
eTri1,
|
|
19
|
-
eTri2,
|
|
20
|
-
eTri3,
|
|
21
|
-
eTri4
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/* Base classes */
|
|
25
|
-
class Point {
|
|
26
|
-
cx: number;
|
|
27
|
-
cy: number;
|
|
28
|
-
shape: ShapePoint;
|
|
29
|
-
constructor(ix: number, iy: number, ishape = ShapePoint.eDefault) {
|
|
30
|
-
this.cx = ix;
|
|
31
|
-
this.cy = iy;
|
|
32
|
-
this.shape = ishape;
|
|
33
|
-
}
|
|
34
|
-
draw(
|
|
35
|
-
ctx: CanvasRenderingContext2D,
|
|
36
|
-
cAdjust: tCanvasAdjust,
|
|
37
|
-
color: string = colors.point,
|
|
38
|
-
ishape = ShapePoint.eDefault
|
|
39
|
-
) {
|
|
40
|
-
if (isFinite(this.cx) && isFinite(this.cy)) {
|
|
41
|
-
const radius = ctx.canvas.width * (0.7 / 100);
|
|
42
|
-
const radius2 = 2 * radius;
|
|
43
|
-
const [cx2, cy2] = point2canvas(this.cx, this.cy, cAdjust);
|
|
44
|
-
//console.log(`dbg493: ${cx2} ${cy2}`);
|
|
45
|
-
let shape = ishape;
|
|
46
|
-
if (shape === ShapePoint.eDefault) {
|
|
47
|
-
shape = this.shape;
|
|
48
|
-
}
|
|
49
|
-
ctx.beginPath();
|
|
50
|
-
switch (shape) {
|
|
51
|
-
case ShapePoint.eCross:
|
|
52
|
-
ctx.moveTo(cx2 - radius2, cy2);
|
|
53
|
-
ctx.lineTo(cx2 + radius2, cy2);
|
|
54
|
-
ctx.moveTo(cx2, cy2 - radius2);
|
|
55
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
56
|
-
break;
|
|
57
|
-
case ShapePoint.eSquare:
|
|
58
|
-
ctx.rect(cx2 - radius, cy2 - radius, 2 * radius, 2 * radius);
|
|
59
|
-
break;
|
|
60
|
-
case ShapePoint.eBigSquare:
|
|
61
|
-
ctx.rect(cx2 - 2 * radius, cy2 - 2 * radius, 4 * radius, 4 * radius);
|
|
62
|
-
break;
|
|
63
|
-
case ShapePoint.eTwoTri:
|
|
64
|
-
ctx.moveTo(cx2 - radius2, cy2);
|
|
65
|
-
ctx.lineTo(cx2 + radius2, cy2);
|
|
66
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
67
|
-
ctx.lineTo(cx2, cy2 - radius2);
|
|
68
|
-
ctx.lineTo(cx2 - radius2, cy2);
|
|
69
|
-
break;
|
|
70
|
-
case ShapePoint.eTri1:
|
|
71
|
-
ctx.moveTo(cx2 - radius2, cy2);
|
|
72
|
-
ctx.lineTo(cx2 + radius2, cy2);
|
|
73
|
-
ctx.lineTo(cx2, cy2 - radius2);
|
|
74
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
75
|
-
break;
|
|
76
|
-
case ShapePoint.eTri2:
|
|
77
|
-
ctx.moveTo(cx2 + radius2, cy2);
|
|
78
|
-
ctx.lineTo(cx2 - radius2, cy2);
|
|
79
|
-
ctx.lineTo(cx2, cy2 - radius2);
|
|
80
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
81
|
-
break;
|
|
82
|
-
case ShapePoint.eTri3:
|
|
83
|
-
ctx.moveTo(cx2 + radius2, cy2);
|
|
84
|
-
ctx.lineTo(cx2 - radius2, cy2);
|
|
85
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
86
|
-
ctx.lineTo(cx2, cy2 - radius2);
|
|
87
|
-
break;
|
|
88
|
-
case ShapePoint.eTri4:
|
|
89
|
-
ctx.moveTo(cx2 - radius2, cy2);
|
|
90
|
-
ctx.lineTo(cx2 + radius2, cy2);
|
|
91
|
-
ctx.lineTo(cx2, cy2 + radius2);
|
|
92
|
-
ctx.lineTo(cx2, cy2 - radius2);
|
|
93
|
-
break;
|
|
94
|
-
case ShapePoint.eCircle:
|
|
95
|
-
default:
|
|
96
|
-
ctx.arc(cx2, cy2, radius, 0, 2 * Math.PI);
|
|
97
|
-
}
|
|
98
|
-
ctx.strokeStyle = color;
|
|
99
|
-
ctx.stroke();
|
|
100
|
-
} else {
|
|
101
|
-
console.log(`INFO489: point not draw because of infinity ${this.cx} ${this.cy}`);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
distanceOrig(): number {
|
|
105
|
-
return Math.sqrt(this.cx ** 2 + this.cy ** 2);
|
|
106
|
-
}
|
|
107
|
-
angleOrig(): number {
|
|
108
|
-
return Math.atan2(this.cy, this.cx);
|
|
109
|
-
}
|
|
110
|
-
getPolar(): tPolar {
|
|
111
|
-
return [this.angleOrig(), this.distanceOrig()];
|
|
112
|
-
}
|
|
113
|
-
setPolar(ia: number, il: number): Point {
|
|
114
|
-
return new Point(il * Math.cos(ia), il * Math.sin(ia));
|
|
115
|
-
}
|
|
116
|
-
translate(ix: number, iy: number): Point {
|
|
117
|
-
return new Point(this.cx + ix, this.cy + iy);
|
|
118
|
-
}
|
|
119
|
-
translatePolar(ia: number, il: number): Point {
|
|
120
|
-
return new Point(this.cx + il * Math.cos(ia), this.cy + il * Math.sin(ia));
|
|
121
|
-
}
|
|
122
|
-
clone(ishape = ShapePoint.eDefault): Point {
|
|
123
|
-
return new Point(this.cx, this.cy, ishape);
|
|
124
|
-
}
|
|
125
|
-
rotateOrig(ia: number): Point {
|
|
126
|
-
// rotation with the origin as center
|
|
127
|
-
const polar = this.getPolar();
|
|
128
|
-
return this.setPolar(polar[0] + ia, polar[1]);
|
|
129
|
-
}
|
|
130
|
-
scaleOrig(ir: number): Point {
|
|
131
|
-
const polar = this.getPolar();
|
|
132
|
-
return this.setPolar(polar[0], polar[1] * ir);
|
|
133
|
-
}
|
|
134
|
-
rotate(ic: Point, ia: number): Point {
|
|
135
|
-
const p1 = this.translate(-1 * ic.cx, -1 * ic.cy);
|
|
136
|
-
const polar = p1.getPolar();
|
|
137
|
-
const p2 = this.setPolar(polar[0] + ia, polar[1]);
|
|
138
|
-
return p2.translate(ic.cx, ic.cy);
|
|
139
|
-
}
|
|
140
|
-
scale(ic: Point, ir: number): Point {
|
|
141
|
-
const p1 = this.translate(-1 * ic.cx, -1 * ic.cy);
|
|
142
|
-
const polar = p1.getPolar();
|
|
143
|
-
const p2 = this.setPolar(polar[0], polar[1] * ir);
|
|
144
|
-
return p2.translate(ic.cx, ic.cy);
|
|
145
|
-
}
|
|
146
|
-
// point comparison
|
|
147
|
-
isEqual(ic: Point): boolean {
|
|
148
|
-
const rb = roundZero(this.cx - ic.cx) === 0 && roundZero(this.cy - ic.cy) === 0;
|
|
149
|
-
return rb;
|
|
150
|
-
}
|
|
151
|
-
// measurement
|
|
152
|
-
distanceToPoint(p2: Point): number {
|
|
153
|
-
const rd = Math.sqrt((p2.cx - this.cx) ** 2 + (p2.cy - this.cy) ** 2);
|
|
154
|
-
return rd;
|
|
155
|
-
}
|
|
156
|
-
angleToPoint(p2: Point): number {
|
|
157
|
-
if (roundZero(this.distanceToPoint(p2)) === 0) {
|
|
158
|
-
throw `err434: no angle because points identical ${this.cx} ${p2.cx} ${this.cy} ${p2.cy}`;
|
|
159
|
-
}
|
|
160
|
-
const ra = Math.atan2(p2.cy - this.cy, p2.cx - this.cx);
|
|
161
|
-
return ra;
|
|
162
|
-
}
|
|
163
|
-
angleFromToPoints(p2: Point, p3: Point): number {
|
|
164
|
-
const ap2 = this.angleToPoint(p2);
|
|
165
|
-
const ap3 = this.angleToPoint(p3);
|
|
166
|
-
const ra = withinPiPi(ap3 - ap2);
|
|
167
|
-
return ra;
|
|
168
|
-
}
|
|
169
|
-
// from 2 points create a new point
|
|
170
|
-
middlePoint(p2: Point): Point {
|
|
171
|
-
const rx = (this.cx + p2.cx) / 2;
|
|
172
|
-
const ry = (this.cy + p2.cy) / 2;
|
|
173
|
-
return new Point(rx, ry);
|
|
174
|
-
}
|
|
175
|
-
equidistantPoint(p2: Point, dist: number, p3: Point): Point {
|
|
176
|
-
const lp1p2h = this.distanceToPoint(p2) / 2;
|
|
177
|
-
if (this.isEqual(p2)) {
|
|
178
|
-
throw `err633: no equidistance because identical point ${this.cx} ${this.cy}`;
|
|
179
|
-
}
|
|
180
|
-
if (dist < lp1p2h) {
|
|
181
|
-
throw `err392: equidistance ${dist} smaller than lp1p2h ${lp1p2h}`;
|
|
182
|
-
}
|
|
183
|
-
const pbi = this.middlePoint(p2);
|
|
184
|
-
const abi = this.angleToPoint(p2) + Math.PI / 2;
|
|
185
|
-
const oppos = Math.sqrt(dist ** 2 - lp1p2h ** 2);
|
|
186
|
-
const rp1 = pbi.translatePolar(abi, oppos);
|
|
187
|
-
const rp2 = pbi.translatePolar(abi + Math.PI, oppos);
|
|
188
|
-
const dp1 = p3.distanceToPoint(rp1);
|
|
189
|
-
const dp2 = p3.distanceToPoint(rp2);
|
|
190
|
-
if (oppos !== 0 && dp1 === dp2) {
|
|
191
|
-
throw `err284: magnet point p3 is on line p1p2. cx ${p3.cx} cy: ${p3.cy}`;
|
|
192
|
-
}
|
|
193
|
-
let rp = rp1;
|
|
194
|
-
if (dp2 < dp1) {
|
|
195
|
-
rp = rp2;
|
|
196
|
-
}
|
|
197
|
-
return rp;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function point(ix: number, iy: number, ishape = ShapePoint.eDefault) {
|
|
202
|
-
return new Point(ix, iy, ishape);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
function pointMinMax(aPoint: Point[]): [number, number, number, number] {
|
|
206
|
-
let xMin = 0;
|
|
207
|
-
let xMax = 0;
|
|
208
|
-
let yMin = 0;
|
|
209
|
-
let yMax = 0;
|
|
210
|
-
if (aPoint.length > 0) {
|
|
211
|
-
// the first point of the list should not contain infinity
|
|
212
|
-
const p0 = aPoint[0];
|
|
213
|
-
if (
|
|
214
|
-
p0.cx === Number.NEGATIVE_INFINITY ||
|
|
215
|
-
p0.cx === Number.POSITIVE_INFINITY ||
|
|
216
|
-
p0.cy === Number.NEGATIVE_INFINITY ||
|
|
217
|
-
p0.cy === Number.POSITIVE_INFINITY
|
|
218
|
-
) {
|
|
219
|
-
throw `err292: pointMinMax first point with infinity: ${p0.cx} ${p0.cy}`;
|
|
220
|
-
}
|
|
221
|
-
xMin = aPoint[0].cx;
|
|
222
|
-
xMax = aPoint[0].cx;
|
|
223
|
-
yMin = aPoint[0].cy;
|
|
224
|
-
yMax = aPoint[0].cy;
|
|
225
|
-
for (const p of aPoint) {
|
|
226
|
-
if (p.cx !== Number.NEGATIVE_INFINITY) {
|
|
227
|
-
xMin = Math.min(xMin, p.cx);
|
|
228
|
-
}
|
|
229
|
-
if (p.cx !== Number.POSITIVE_INFINITY) {
|
|
230
|
-
xMax = Math.max(xMax, p.cx);
|
|
231
|
-
}
|
|
232
|
-
if (p.cy !== Number.NEGATIVE_INFINITY) {
|
|
233
|
-
yMin = Math.min(yMin, p.cy);
|
|
234
|
-
}
|
|
235
|
-
if (p.cy !== Number.POSITIVE_INFINITY) {
|
|
236
|
-
yMax = Math.max(yMax, p.cy);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
return [xMin, xMax, yMin, yMax];
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* export */
|
|
244
|
-
|
|
245
|
-
export type { tPolar };
|
|
246
|
-
export { ShapePoint, Point, point, pointMinMax };
|