@ifc-lite/drawing-2d 1.4.0

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.
Files changed (158) hide show
  1. package/LICENSE +373 -0
  2. package/dist/drawing-generator.d.ts +80 -0
  3. package/dist/drawing-generator.d.ts.map +1 -0
  4. package/dist/drawing-generator.js +281 -0
  5. package/dist/drawing-generator.js.map +1 -0
  6. package/dist/edge-extractor.d.ts +47 -0
  7. package/dist/edge-extractor.d.ts.map +1 -0
  8. package/dist/edge-extractor.js +204 -0
  9. package/dist/edge-extractor.js.map +1 -0
  10. package/dist/gpu-section-cutter.d.ts +42 -0
  11. package/dist/gpu-section-cutter.d.ts.map +1 -0
  12. package/dist/gpu-section-cutter.js +405 -0
  13. package/dist/gpu-section-cutter.js.map +1 -0
  14. package/dist/graphic-overrides/index.d.ts +10 -0
  15. package/dist/graphic-overrides/index.d.ts.map +1 -0
  16. package/dist/graphic-overrides/index.js +8 -0
  17. package/dist/graphic-overrides/index.js.map +1 -0
  18. package/dist/graphic-overrides/presets.d.ts +22 -0
  19. package/dist/graphic-overrides/presets.d.ts.map +1 -0
  20. package/dist/graphic-overrides/presets.js +283 -0
  21. package/dist/graphic-overrides/presets.js.map +1 -0
  22. package/dist/graphic-overrides/rule-engine.d.ts +64 -0
  23. package/dist/graphic-overrides/rule-engine.d.ts.map +1 -0
  24. package/dist/graphic-overrides/rule-engine.js +438 -0
  25. package/dist/graphic-overrides/rule-engine.js.map +1 -0
  26. package/dist/graphic-overrides/types.d.ts +200 -0
  27. package/dist/graphic-overrides/types.d.ts.map +1 -0
  28. package/dist/graphic-overrides/types.js +5 -0
  29. package/dist/graphic-overrides/types.js.map +1 -0
  30. package/dist/hatch-generator.d.ts +76 -0
  31. package/dist/hatch-generator.d.ts.map +1 -0
  32. package/dist/hatch-generator.js +282 -0
  33. package/dist/hatch-generator.js.map +1 -0
  34. package/dist/hidden-line.d.ts +64 -0
  35. package/dist/hidden-line.d.ts.map +1 -0
  36. package/dist/hidden-line.js +318 -0
  37. package/dist/hidden-line.js.map +1 -0
  38. package/dist/index.d.ts +44 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +109 -0
  41. package/dist/index.js.map +1 -0
  42. package/dist/line-merger.d.ts +35 -0
  43. package/dist/line-merger.d.ts.map +1 -0
  44. package/dist/line-merger.js +265 -0
  45. package/dist/line-merger.js.map +1 -0
  46. package/dist/math.d.ts +90 -0
  47. package/dist/math.d.ts.map +1 -0
  48. package/dist/math.js +284 -0
  49. package/dist/math.js.map +1 -0
  50. package/dist/openings/index.d.ts +7 -0
  51. package/dist/openings/index.d.ts.map +1 -0
  52. package/dist/openings/index.js +10 -0
  53. package/dist/openings/index.js.map +1 -0
  54. package/dist/openings/opening-filter.d.ts +61 -0
  55. package/dist/openings/opening-filter.d.ts.map +1 -0
  56. package/dist/openings/opening-filter.js +244 -0
  57. package/dist/openings/opening-filter.js.map +1 -0
  58. package/dist/openings/opening-relationship-builder.d.ts +35 -0
  59. package/dist/openings/opening-relationship-builder.d.ts.map +1 -0
  60. package/dist/openings/opening-relationship-builder.js +121 -0
  61. package/dist/openings/opening-relationship-builder.js.map +1 -0
  62. package/dist/openings/opening-utils.d.ts +55 -0
  63. package/dist/openings/opening-utils.d.ts.map +1 -0
  64. package/dist/openings/opening-utils.js +128 -0
  65. package/dist/openings/opening-utils.js.map +1 -0
  66. package/dist/polygon-builder.d.ts +62 -0
  67. package/dist/polygon-builder.d.ts.map +1 -0
  68. package/dist/polygon-builder.js +261 -0
  69. package/dist/polygon-builder.js.map +1 -0
  70. package/dist/section-cutter.d.ts +49 -0
  71. package/dist/section-cutter.d.ts.map +1 -0
  72. package/dist/section-cutter.js +220 -0
  73. package/dist/section-cutter.js.map +1 -0
  74. package/dist/sheet/frame-renderer.d.ts +28 -0
  75. package/dist/sheet/frame-renderer.d.ts.map +1 -0
  76. package/dist/sheet/frame-renderer.js +199 -0
  77. package/dist/sheet/frame-renderer.js.map +1 -0
  78. package/dist/sheet/frame-types.d.ts +57 -0
  79. package/dist/sheet/frame-types.d.ts.map +1 -0
  80. package/dist/sheet/frame-types.js +88 -0
  81. package/dist/sheet/frame-types.js.map +1 -0
  82. package/dist/sheet/index.d.ts +26 -0
  83. package/dist/sheet/index.d.ts.map +1 -0
  84. package/dist/sheet/index.js +12 -0
  85. package/dist/sheet/index.js.map +1 -0
  86. package/dist/sheet/paper-sizes.d.ts +36 -0
  87. package/dist/sheet/paper-sizes.d.ts.map +1 -0
  88. package/dist/sheet/paper-sizes.js +252 -0
  89. package/dist/sheet/paper-sizes.js.map +1 -0
  90. package/dist/sheet/scale-bar-renderer.d.ts +29 -0
  91. package/dist/sheet/scale-bar-renderer.d.ts.map +1 -0
  92. package/dist/sheet/scale-bar-renderer.js +287 -0
  93. package/dist/sheet/scale-bar-renderer.js.map +1 -0
  94. package/dist/sheet/scale-bar-types.d.ts +82 -0
  95. package/dist/sheet/scale-bar-types.d.ts.map +1 -0
  96. package/dist/sheet/scale-bar-types.js +66 -0
  97. package/dist/sheet/scale-bar-types.js.map +1 -0
  98. package/dist/sheet/sheet-types.d.ts +84 -0
  99. package/dist/sheet/sheet-types.d.ts.map +1 -0
  100. package/dist/sheet/sheet-types.js +77 -0
  101. package/dist/sheet/sheet-types.js.map +1 -0
  102. package/dist/sheet/title-block-renderer.d.ts +44 -0
  103. package/dist/sheet/title-block-renderer.d.ts.map +1 -0
  104. package/dist/sheet/title-block-renderer.js +335 -0
  105. package/dist/sheet/title-block-renderer.js.map +1 -0
  106. package/dist/sheet/title-block-types.d.ts +100 -0
  107. package/dist/sheet/title-block-types.d.ts.map +1 -0
  108. package/dist/sheet/title-block-types.js +174 -0
  109. package/dist/sheet/title-block-types.js.map +1 -0
  110. package/dist/styles.d.ts +77 -0
  111. package/dist/styles.d.ts.map +1 -0
  112. package/dist/styles.js +347 -0
  113. package/dist/styles.js.map +1 -0
  114. package/dist/styling/index.d.ts +7 -0
  115. package/dist/styling/index.d.ts.map +1 -0
  116. package/dist/styling/index.js +10 -0
  117. package/dist/styling/index.js.map +1 -0
  118. package/dist/styling/layer-mapping.d.ts +57 -0
  119. package/dist/styling/layer-mapping.d.ts.map +1 -0
  120. package/dist/styling/layer-mapping.js +303 -0
  121. package/dist/styling/layer-mapping.js.map +1 -0
  122. package/dist/styling/line-styles.d.ts +49 -0
  123. package/dist/styling/line-styles.d.ts.map +1 -0
  124. package/dist/styling/line-styles.js +123 -0
  125. package/dist/styling/line-styles.js.map +1 -0
  126. package/dist/styling/line-weights.d.ts +61 -0
  127. package/dist/styling/line-weights.d.ts.map +1 -0
  128. package/dist/styling/line-weights.js +183 -0
  129. package/dist/styling/line-weights.js.map +1 -0
  130. package/dist/svg-exporter.d.ts +63 -0
  131. package/dist/svg-exporter.d.ts.map +1 -0
  132. package/dist/svg-exporter.js +278 -0
  133. package/dist/svg-exporter.js.map +1 -0
  134. package/dist/symbols/door-symbol.d.ts +82 -0
  135. package/dist/symbols/door-symbol.d.ts.map +1 -0
  136. package/dist/symbols/door-symbol.js +390 -0
  137. package/dist/symbols/door-symbol.js.map +1 -0
  138. package/dist/symbols/index.d.ts +8 -0
  139. package/dist/symbols/index.d.ts.map +1 -0
  140. package/dist/symbols/index.js +11 -0
  141. package/dist/symbols/index.js.map +1 -0
  142. package/dist/symbols/symbol-renderer.d.ts +29 -0
  143. package/dist/symbols/symbol-renderer.d.ts.map +1 -0
  144. package/dist/symbols/symbol-renderer.js +173 -0
  145. package/dist/symbols/symbol-renderer.js.map +1 -0
  146. package/dist/symbols/symbol-utils.d.ts +48 -0
  147. package/dist/symbols/symbol-utils.d.ts.map +1 -0
  148. package/dist/symbols/symbol-utils.js +129 -0
  149. package/dist/symbols/symbol-utils.js.map +1 -0
  150. package/dist/symbols/window-symbol.d.ts +57 -0
  151. package/dist/symbols/window-symbol.d.ts.map +1 -0
  152. package/dist/symbols/window-symbol.js +209 -0
  153. package/dist/symbols/window-symbol.js.map +1 -0
  154. package/dist/types.d.ts +443 -0
  155. package/dist/types.d.ts.map +1 -0
  156. package/dist/types.js +31 -0
  157. package/dist/types.js.map +1 -0
  158. package/package.json +53 -0
@@ -0,0 +1,265 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ import { EPSILON, point2DDistance, point2DSub, point2DDot, point2DCross, lineDirection, } from './math';
5
+ const DEFAULT_OPTIONS = {
6
+ angleTolerance: 0.01, // ~0.5 degrees
7
+ distanceTolerance: 0.001,
8
+ gapTolerance: 0.01,
9
+ };
10
+ /**
11
+ * Merge collinear line segments within the same entity
12
+ */
13
+ export function mergeDrawingLines(lines, options = {}) {
14
+ const opts = { ...DEFAULT_OPTIONS, ...options };
15
+ // Group lines by entity and category
16
+ const groups = new Map();
17
+ for (const line of lines) {
18
+ const key = `${line.modelIndex}:${line.entityId}:${line.category}:${line.visibility}`;
19
+ if (!groups.has(key)) {
20
+ groups.set(key, []);
21
+ }
22
+ groups.get(key).push(line);
23
+ }
24
+ // Merge within each group
25
+ const result = [];
26
+ for (const groupLines of groups.values()) {
27
+ const merged = mergeLineGroup(groupLines, opts);
28
+ result.push(...merged);
29
+ }
30
+ return result;
31
+ }
32
+ /**
33
+ * Merge lines within a single group (same entity, category, visibility)
34
+ */
35
+ function mergeLineGroup(lines, opts) {
36
+ if (lines.length <= 1)
37
+ return lines;
38
+ // Extract just the Line2D parts for merging
39
+ const line2Ds = lines.map((l) => l.line);
40
+ const mergedLine2Ds = mergeCollinearLines(line2Ds, opts);
41
+ // Map merged lines back to DrawingLines
42
+ // Use properties from first line in group (they're all the same)
43
+ const template = lines[0];
44
+ return mergedLine2Ds.map((line) => ({
45
+ ...template,
46
+ line,
47
+ }));
48
+ }
49
+ /**
50
+ * Core algorithm: merge collinear Line2D segments
51
+ */
52
+ export function mergeCollinearLines(lines, options = {}) {
53
+ const opts = { ...DEFAULT_OPTIONS, ...options };
54
+ if (lines.length <= 1)
55
+ return lines;
56
+ // Group lines by direction (using angle buckets)
57
+ const buckets = groupByDirection(lines, opts.angleTolerance);
58
+ const result = [];
59
+ // Process each direction bucket
60
+ for (const bucket of buckets.values()) {
61
+ // Further group by actual line (same direction, same line equation)
62
+ const lineGroups = groupByLine(bucket, opts.distanceTolerance);
63
+ for (const group of lineGroups) {
64
+ // Merge segments on the same line
65
+ const merged = mergeSegmentsOnLine(group, opts.gapTolerance);
66
+ result.push(...merged);
67
+ }
68
+ }
69
+ return result;
70
+ }
71
+ /**
72
+ * Group lines by their direction (angle bucket)
73
+ */
74
+ function groupByDirection(lines, angleTolerance) {
75
+ const buckets = new Map();
76
+ const bucketSize = angleTolerance * 2;
77
+ for (const line of lines) {
78
+ const dir = lineDirection(line);
79
+ // Normalize angle to [0, π) since direction is symmetric
80
+ let angle = Math.atan2(dir.y, dir.x);
81
+ if (angle < 0)
82
+ angle += Math.PI;
83
+ if (angle >= Math.PI)
84
+ angle -= Math.PI;
85
+ // Find bucket
86
+ const bucketIdx = Math.floor(angle / bucketSize);
87
+ if (!buckets.has(bucketIdx)) {
88
+ buckets.set(bucketIdx, []);
89
+ }
90
+ buckets.get(bucketIdx).push(line);
91
+ }
92
+ return buckets;
93
+ }
94
+ /**
95
+ * Group lines that lie on the same infinite line
96
+ */
97
+ function groupByLine(lines, distanceTolerance) {
98
+ const groups = [];
99
+ const assigned = new Set();
100
+ for (let i = 0; i < lines.length; i++) {
101
+ if (assigned.has(i))
102
+ continue;
103
+ const group = [lines[i]];
104
+ assigned.add(i);
105
+ // Find all other lines on the same line
106
+ for (let j = i + 1; j < lines.length; j++) {
107
+ if (assigned.has(j))
108
+ continue;
109
+ if (linesOnSameLine(lines[i], lines[j], distanceTolerance)) {
110
+ group.push(lines[j]);
111
+ assigned.add(j);
112
+ }
113
+ }
114
+ groups.push(group);
115
+ }
116
+ return groups;
117
+ }
118
+ /**
119
+ * Check if two lines lie on the same infinite line
120
+ */
121
+ function linesOnSameLine(a, b, tolerance) {
122
+ const dirA = lineDirection(a);
123
+ // Distance from b.start to line a
124
+ const toB = point2DSub(b.start, a.start);
125
+ const distStart = Math.abs(point2DCross(dirA, toB));
126
+ if (distStart > tolerance)
127
+ return false;
128
+ // Distance from b.end to line a
129
+ const toBEnd = point2DSub(b.end, a.start);
130
+ const distEnd = Math.abs(point2DCross(dirA, toBEnd));
131
+ return distEnd <= tolerance;
132
+ }
133
+ /**
134
+ * Merge segments that lie on the same line
135
+ * Uses 1D projection along the line
136
+ */
137
+ function mergeSegmentsOnLine(lines, gapTolerance) {
138
+ if (lines.length <= 1)
139
+ return lines;
140
+ // Project all segments to 1D parameter space along the line
141
+ const baseLine = lines[0];
142
+ const dir = lineDirection(baseLine);
143
+ const origin = baseLine.start;
144
+ const intervals = lines.map((line) => {
145
+ const t0 = projectPoint1D(line.start, origin, dir);
146
+ const t1 = projectPoint1D(line.end, origin, dir);
147
+ return { t0: Math.min(t0, t1), t1: Math.max(t0, t1) };
148
+ });
149
+ // Sort by start parameter
150
+ intervals.sort((a, b) => a.t0 - b.t0);
151
+ // Merge overlapping/adjacent intervals
152
+ const merged = [];
153
+ let current = intervals[0];
154
+ for (let i = 1; i < intervals.length; i++) {
155
+ const next = intervals[i];
156
+ // Check if intervals overlap or are adjacent (within gap tolerance)
157
+ if (next.t0 <= current.t1 + gapTolerance) {
158
+ // Merge
159
+ current = {
160
+ t0: current.t0,
161
+ t1: Math.max(current.t1, next.t1),
162
+ };
163
+ }
164
+ else {
165
+ // Gap too large, start new interval
166
+ merged.push(current);
167
+ current = next;
168
+ }
169
+ }
170
+ merged.push(current);
171
+ // Convert back to Line2D
172
+ return merged.map((interval) => ({
173
+ start: {
174
+ x: origin.x + dir.x * interval.t0,
175
+ y: origin.y + dir.y * interval.t0,
176
+ },
177
+ end: {
178
+ x: origin.x + dir.x * interval.t1,
179
+ y: origin.y + dir.y * interval.t1,
180
+ },
181
+ }));
182
+ }
183
+ /**
184
+ * Project point to 1D parameter along direction from origin
185
+ */
186
+ function projectPoint1D(point, origin, dir) {
187
+ const toPoint = point2DSub(point, origin);
188
+ return point2DDot(toPoint, dir);
189
+ }
190
+ // ═══════════════════════════════════════════════════════════════════════════
191
+ // SEGMENT DEDUPLICATION
192
+ // ═══════════════════════════════════════════════════════════════════════════
193
+ /**
194
+ * Remove duplicate line segments
195
+ */
196
+ export function deduplicateLines(lines, tolerance = 0.001) {
197
+ const result = [];
198
+ for (const line of lines) {
199
+ let isDuplicate = false;
200
+ for (const existing of result) {
201
+ if (linesEqual(line, existing, tolerance)) {
202
+ isDuplicate = true;
203
+ break;
204
+ }
205
+ }
206
+ if (!isDuplicate) {
207
+ result.push(line);
208
+ }
209
+ }
210
+ return result;
211
+ }
212
+ /**
213
+ * Check if two lines are equal (considering both directions)
214
+ */
215
+ function linesEqual(a, b, tolerance) {
216
+ // Forward match
217
+ if (point2DDistance(a.start, b.start) < tolerance &&
218
+ point2DDistance(a.end, b.end) < tolerance) {
219
+ return true;
220
+ }
221
+ // Reverse match
222
+ if (point2DDistance(a.start, b.end) < tolerance &&
223
+ point2DDistance(a.end, b.start) < tolerance) {
224
+ return true;
225
+ }
226
+ return false;
227
+ }
228
+ // ═══════════════════════════════════════════════════════════════════════════
229
+ // LINE SPLITTING (for hidden line removal)
230
+ // ═══════════════════════════════════════════════════════════════════════════
231
+ /**
232
+ * Split a line at given parameters
233
+ * @param line The line to split
234
+ * @param params Array of t values (0-1) where to split
235
+ * @returns Array of line segments
236
+ */
237
+ export function splitLineAtParams(line, params) {
238
+ // Add endpoints and sort
239
+ const allParams = [0, ...params.filter((t) => t > 0 && t < 1), 1].sort((a, b) => a - b);
240
+ // Remove duplicates
241
+ const uniqueParams = [];
242
+ for (const p of allParams) {
243
+ if (uniqueParams.length === 0 || p - uniqueParams[uniqueParams.length - 1] > EPSILON) {
244
+ uniqueParams.push(p);
245
+ }
246
+ }
247
+ // Create segments
248
+ const segments = [];
249
+ for (let i = 0; i < uniqueParams.length - 1; i++) {
250
+ const t0 = uniqueParams[i];
251
+ const t1 = uniqueParams[i + 1];
252
+ segments.push({
253
+ start: {
254
+ x: line.start.x + t0 * (line.end.x - line.start.x),
255
+ y: line.start.y + t0 * (line.end.y - line.start.y),
256
+ },
257
+ end: {
258
+ x: line.start.x + t1 * (line.end.x - line.start.x),
259
+ y: line.start.y + t1 * (line.end.y - line.start.y),
260
+ },
261
+ });
262
+ }
263
+ return segments;
264
+ }
265
+ //# sourceMappingURL=line-merger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-merger.js","sourceRoot":"","sources":["../src/line-merger.ts"],"names":[],"mappings":"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"}
package/dist/math.d.ts ADDED
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Vector math utilities for 2D drawing generation
3
+ */
4
+ import type { Vec3, Point2D, Line2D, Bounds2D } from './types';
5
+ export declare const EPSILON = 1e-7;
6
+ export declare function vec3(x: number, y: number, z: number): Vec3;
7
+ export declare function vec3Add(a: Vec3, b: Vec3): Vec3;
8
+ export declare function vec3Sub(a: Vec3, b: Vec3): Vec3;
9
+ export declare function vec3Scale(v: Vec3, s: number): Vec3;
10
+ export declare function vec3Dot(a: Vec3, b: Vec3): number;
11
+ export declare function vec3Cross(a: Vec3, b: Vec3): Vec3;
12
+ export declare function vec3Length(v: Vec3): number;
13
+ export declare function vec3Normalize(v: Vec3): Vec3;
14
+ export declare function vec3Lerp(a: Vec3, b: Vec3, t: number): Vec3;
15
+ export declare function vec3Equals(a: Vec3, b: Vec3, tolerance?: number): boolean;
16
+ export declare function vec3Distance(a: Vec3, b: Vec3): number;
17
+ export declare function point2D(x: number, y: number): Point2D;
18
+ export declare function point2DAdd(a: Point2D, b: Point2D): Point2D;
19
+ export declare function point2DSub(a: Point2D, b: Point2D): Point2D;
20
+ export declare function point2DScale(p: Point2D, s: number): Point2D;
21
+ export declare function point2DDot(a: Point2D, b: Point2D): number;
22
+ export declare function point2DLength(p: Point2D): number;
23
+ export declare function point2DDistance(a: Point2D, b: Point2D): number;
24
+ export declare function point2DLerp(a: Point2D, b: Point2D, t: number): Point2D;
25
+ export declare function point2DEquals(a: Point2D, b: Point2D, tolerance?: number): boolean;
26
+ export declare function point2DNormalize(p: Point2D): Point2D;
27
+ /**
28
+ * 2D cross product (returns scalar z-component)
29
+ */
30
+ export declare function point2DCross(a: Point2D, b: Point2D): number;
31
+ export declare function lineLength(line: Line2D): number;
32
+ export declare function lineMidpoint(line: Line2D): Point2D;
33
+ export declare function lineDirection(line: Line2D): Point2D;
34
+ /**
35
+ * Check if two lines are collinear (same direction and overlapping)
36
+ */
37
+ export declare function linesCollinear(a: Line2D, b: Line2D, angleTolerance?: number, distanceTolerance?: number): boolean;
38
+ /**
39
+ * Project a point onto a line, returning the parameter t
40
+ * t=0 at start, t=1 at end
41
+ */
42
+ export declare function projectPointOnLine(point: Point2D, line: Line2D): number;
43
+ export declare function boundsEmpty(): Bounds2D;
44
+ export declare function boundsExtendPoint(bounds: Bounds2D, point: Point2D): Bounds2D;
45
+ export declare function boundsExtendLine(bounds: Bounds2D, line: Line2D): Bounds2D;
46
+ export declare function boundsCenter(bounds: Bounds2D): Point2D;
47
+ export declare function boundsSize(bounds: Bounds2D): Point2D;
48
+ export declare function boundsValid(bounds: Bounds2D): boolean;
49
+ /**
50
+ * Compute signed distance from point to plane
51
+ * Positive = in front of plane (in normal direction)
52
+ * Negative = behind plane
53
+ */
54
+ export declare function signedDistanceToPlane(point: Vec3, normal: Vec3, distance: number): number;
55
+ /**
56
+ * Get the normal vector for a section axis
57
+ */
58
+ export declare function getAxisNormal(axis: 'x' | 'y' | 'z', flipped: boolean): Vec3;
59
+ /**
60
+ * Get the two axes perpendicular to the section axis (for 2D projection)
61
+ */
62
+ export declare function getProjectionAxes(axis: 'x' | 'y' | 'z'): {
63
+ u: 'x' | 'y' | 'z';
64
+ v: 'x' | 'y' | 'z';
65
+ };
66
+ /**
67
+ * Project a 3D point to 2D based on section axis
68
+ */
69
+ export declare function projectTo2D(point: Vec3, axis: 'x' | 'y' | 'z', flipped: boolean): Point2D;
70
+ /**
71
+ * Compute signed area of polygon (positive = CCW, negative = CW)
72
+ */
73
+ export declare function polygonSignedArea(points: Point2D[]): number;
74
+ /**
75
+ * Check if polygon winding is counter-clockwise
76
+ */
77
+ export declare function isCounterClockwise(points: Point2D[]): boolean;
78
+ /**
79
+ * Reverse polygon winding
80
+ */
81
+ export declare function reversePolygon(points: Point2D[]): Point2D[];
82
+ /**
83
+ * Ensure polygon has counter-clockwise winding
84
+ */
85
+ export declare function ensureCCW(points: Point2D[]): Point2D[];
86
+ /**
87
+ * Ensure polygon has clockwise winding
88
+ */
89
+ export declare function ensureCW(points: Point2D[]): Point2D[];
90
+ //# sourceMappingURL=math.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"math.d.ts","sourceRoot":"","sources":["../src/math.ts"],"names":[],"mappings":"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"}
package/dist/math.js ADDED
@@ -0,0 +1,284 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ // ═══════════════════════════════════════════════════════════════════════════
5
+ // CONSTANTS
6
+ // ═══════════════════════════════════════════════════════════════════════════
7
+ export const EPSILON = 1e-7;
8
+ // ═══════════════════════════════════════════════════════════════════════════
9
+ // VEC3 OPERATIONS
10
+ // ═══════════════════════════════════════════════════════════════════════════
11
+ export function vec3(x, y, z) {
12
+ return { x, y, z };
13
+ }
14
+ export function vec3Add(a, b) {
15
+ return { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z };
16
+ }
17
+ export function vec3Sub(a, b) {
18
+ return { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
19
+ }
20
+ export function vec3Scale(v, s) {
21
+ return { x: v.x * s, y: v.y * s, z: v.z * s };
22
+ }
23
+ export function vec3Dot(a, b) {
24
+ return a.x * b.x + a.y * b.y + a.z * b.z;
25
+ }
26
+ export function vec3Cross(a, b) {
27
+ return {
28
+ x: a.y * b.z - a.z * b.y,
29
+ y: a.z * b.x - a.x * b.z,
30
+ z: a.x * b.y - a.y * b.x,
31
+ };
32
+ }
33
+ export function vec3Length(v) {
34
+ return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
35
+ }
36
+ export function vec3Normalize(v) {
37
+ const len = vec3Length(v);
38
+ if (len < EPSILON)
39
+ return { x: 0, y: 0, z: 0 };
40
+ return { x: v.x / len, y: v.y / len, z: v.z / len };
41
+ }
42
+ export function vec3Lerp(a, b, t) {
43
+ return {
44
+ x: a.x + t * (b.x - a.x),
45
+ y: a.y + t * (b.y - a.y),
46
+ z: a.z + t * (b.z - a.z),
47
+ };
48
+ }
49
+ export function vec3Equals(a, b, tolerance = EPSILON) {
50
+ return (Math.abs(a.x - b.x) < tolerance &&
51
+ Math.abs(a.y - b.y) < tolerance &&
52
+ Math.abs(a.z - b.z) < tolerance);
53
+ }
54
+ export function vec3Distance(a, b) {
55
+ const dx = b.x - a.x;
56
+ const dy = b.y - a.y;
57
+ const dz = b.z - a.z;
58
+ return Math.sqrt(dx * dx + dy * dy + dz * dz);
59
+ }
60
+ // ═══════════════════════════════════════════════════════════════════════════
61
+ // VEC2 / POINT2D OPERATIONS
62
+ // ═══════════════════════════════════════════════════════════════════════════
63
+ export function point2D(x, y) {
64
+ return { x, y };
65
+ }
66
+ export function point2DAdd(a, b) {
67
+ return { x: a.x + b.x, y: a.y + b.y };
68
+ }
69
+ export function point2DSub(a, b) {
70
+ return { x: a.x - b.x, y: a.y - b.y };
71
+ }
72
+ export function point2DScale(p, s) {
73
+ return { x: p.x * s, y: p.y * s };
74
+ }
75
+ export function point2DDot(a, b) {
76
+ return a.x * b.x + a.y * b.y;
77
+ }
78
+ export function point2DLength(p) {
79
+ return Math.sqrt(p.x * p.x + p.y * p.y);
80
+ }
81
+ export function point2DDistance(a, b) {
82
+ const dx = b.x - a.x;
83
+ const dy = b.y - a.y;
84
+ return Math.sqrt(dx * dx + dy * dy);
85
+ }
86
+ export function point2DLerp(a, b, t) {
87
+ return {
88
+ x: a.x + t * (b.x - a.x),
89
+ y: a.y + t * (b.y - a.y),
90
+ };
91
+ }
92
+ export function point2DEquals(a, b, tolerance = EPSILON) {
93
+ return Math.abs(a.x - b.x) < tolerance && Math.abs(a.y - b.y) < tolerance;
94
+ }
95
+ export function point2DNormalize(p) {
96
+ const len = point2DLength(p);
97
+ if (len < EPSILON)
98
+ return { x: 0, y: 0 };
99
+ return { x: p.x / len, y: p.y / len };
100
+ }
101
+ /**
102
+ * 2D cross product (returns scalar z-component)
103
+ */
104
+ export function point2DCross(a, b) {
105
+ return a.x * b.y - a.y * b.x;
106
+ }
107
+ // ═══════════════════════════════════════════════════════════════════════════
108
+ // LINE OPERATIONS
109
+ // ═══════════════════════════════════════════════════════════════════════════
110
+ export function lineLength(line) {
111
+ return point2DDistance(line.start, line.end);
112
+ }
113
+ export function lineMidpoint(line) {
114
+ return {
115
+ x: (line.start.x + line.end.x) / 2,
116
+ y: (line.start.y + line.end.y) / 2,
117
+ };
118
+ }
119
+ export function lineDirection(line) {
120
+ return point2DNormalize(point2DSub(line.end, line.start));
121
+ }
122
+ /**
123
+ * Check if two lines are collinear (same direction and overlapping)
124
+ */
125
+ export function linesCollinear(a, b, angleTolerance = 0.01, distanceTolerance = 0.001) {
126
+ const dirA = lineDirection(a);
127
+ const dirB = lineDirection(b);
128
+ // Check if directions are parallel (or anti-parallel)
129
+ const cross = Math.abs(point2DCross(dirA, dirB));
130
+ if (cross > angleTolerance)
131
+ return false;
132
+ // Check if lines are on the same line (distance from point to line)
133
+ const toB = point2DSub(b.start, a.start);
134
+ const dist = Math.abs(point2DCross(dirA, toB));
135
+ return dist < distanceTolerance;
136
+ }
137
+ /**
138
+ * Project a point onto a line, returning the parameter t
139
+ * t=0 at start, t=1 at end
140
+ */
141
+ export function projectPointOnLine(point, line) {
142
+ const lineVec = point2DSub(line.end, line.start);
143
+ const pointVec = point2DSub(point, line.start);
144
+ const lenSq = point2DDot(lineVec, lineVec);
145
+ if (lenSq < EPSILON)
146
+ return 0;
147
+ return point2DDot(pointVec, lineVec) / lenSq;
148
+ }
149
+ // ═══════════════════════════════════════════════════════════════════════════
150
+ // BOUNDS OPERATIONS
151
+ // ═══════════════════════════════════════════════════════════════════════════
152
+ export function boundsEmpty() {
153
+ return {
154
+ min: { x: Infinity, y: Infinity },
155
+ max: { x: -Infinity, y: -Infinity },
156
+ };
157
+ }
158
+ export function boundsExtendPoint(bounds, point) {
159
+ return {
160
+ min: {
161
+ x: Math.min(bounds.min.x, point.x),
162
+ y: Math.min(bounds.min.y, point.y),
163
+ },
164
+ max: {
165
+ x: Math.max(bounds.max.x, point.x),
166
+ y: Math.max(bounds.max.y, point.y),
167
+ },
168
+ };
169
+ }
170
+ export function boundsExtendLine(bounds, line) {
171
+ let result = boundsExtendPoint(bounds, line.start);
172
+ result = boundsExtendPoint(result, line.end);
173
+ return result;
174
+ }
175
+ export function boundsCenter(bounds) {
176
+ return {
177
+ x: (bounds.min.x + bounds.max.x) / 2,
178
+ y: (bounds.min.y + bounds.max.y) / 2,
179
+ };
180
+ }
181
+ export function boundsSize(bounds) {
182
+ return {
183
+ x: bounds.max.x - bounds.min.x,
184
+ y: bounds.max.y - bounds.min.y,
185
+ };
186
+ }
187
+ export function boundsValid(bounds) {
188
+ return (bounds.min.x <= bounds.max.x &&
189
+ bounds.min.y <= bounds.max.y &&
190
+ isFinite(bounds.min.x) &&
191
+ isFinite(bounds.max.x) &&
192
+ isFinite(bounds.min.y) &&
193
+ isFinite(bounds.max.y));
194
+ }
195
+ // ═══════════════════════════════════════════════════════════════════════════
196
+ // PLANE OPERATIONS
197
+ // ═══════════════════════════════════════════════════════════════════════════
198
+ /**
199
+ * Compute signed distance from point to plane
200
+ * Positive = in front of plane (in normal direction)
201
+ * Negative = behind plane
202
+ */
203
+ export function signedDistanceToPlane(point, normal, distance) {
204
+ return vec3Dot(point, normal) - distance;
205
+ }
206
+ /**
207
+ * Get the normal vector for a section axis
208
+ */
209
+ export function getAxisNormal(axis, flipped) {
210
+ const sign = flipped ? -1 : 1;
211
+ switch (axis) {
212
+ case 'x':
213
+ return { x: sign, y: 0, z: 0 };
214
+ case 'y':
215
+ return { x: 0, y: sign, z: 0 };
216
+ case 'z':
217
+ return { x: 0, y: 0, z: sign };
218
+ }
219
+ }
220
+ /**
221
+ * Get the two axes perpendicular to the section axis (for 2D projection)
222
+ */
223
+ export function getProjectionAxes(axis) {
224
+ switch (axis) {
225
+ case 'x':
226
+ return { u: 'z', v: 'y' }; // Looking along X, project to ZY
227
+ case 'y':
228
+ return { u: 'x', v: 'z' }; // Looking along Y (down), project to XZ
229
+ case 'z':
230
+ return { u: 'x', v: 'y' }; // Looking along Z, project to XY
231
+ }
232
+ }
233
+ /**
234
+ * Project a 3D point to 2D based on section axis
235
+ */
236
+ export function projectTo2D(point, axis, flipped) {
237
+ const axes = getProjectionAxes(axis);
238
+ const u = point[axes.u];
239
+ const v = point[axes.v];
240
+ // Flip U axis when section is flipped to maintain consistent orientation
241
+ return { x: flipped ? -u : u, y: v };
242
+ }
243
+ // ═══════════════════════════════════════════════════════════════════════════
244
+ // POLYGON OPERATIONS
245
+ // ═══════════════════════════════════════════════════════════════════════════
246
+ /**
247
+ * Compute signed area of polygon (positive = CCW, negative = CW)
248
+ */
249
+ export function polygonSignedArea(points) {
250
+ if (points.length < 3)
251
+ return 0;
252
+ let area = 0;
253
+ for (let i = 0; i < points.length; i++) {
254
+ const j = (i + 1) % points.length;
255
+ area += points[i].x * points[j].y;
256
+ area -= points[j].x * points[i].y;
257
+ }
258
+ return area / 2;
259
+ }
260
+ /**
261
+ * Check if polygon winding is counter-clockwise
262
+ */
263
+ export function isCounterClockwise(points) {
264
+ return polygonSignedArea(points) > 0;
265
+ }
266
+ /**
267
+ * Reverse polygon winding
268
+ */
269
+ export function reversePolygon(points) {
270
+ return [...points].reverse();
271
+ }
272
+ /**
273
+ * Ensure polygon has counter-clockwise winding
274
+ */
275
+ export function ensureCCW(points) {
276
+ return isCounterClockwise(points) ? points : reversePolygon(points);
277
+ }
278
+ /**
279
+ * Ensure polygon has clockwise winding
280
+ */
281
+ export function ensureCW(points) {
282
+ return isCounterClockwise(points) ? reversePolygon(points) : points;
283
+ }
284
+ //# sourceMappingURL=math.js.map