fluidcad 0.0.33 → 0.0.34

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 (237) hide show
  1. package/README.md +3 -2
  2. package/bin/commands/init.js +55 -0
  3. package/bin/commands/mcp.js +33 -0
  4. package/bin/commands/serve.js +77 -0
  5. package/bin/fluidcad.js +15 -107
  6. package/lib/dist/common/scene-object.d.ts +2 -1
  7. package/lib/dist/common/scene-object.js +3 -2
  8. package/lib/dist/core/2d/tarc.d.ts +20 -2
  9. package/lib/dist/core/2d/tarc.js +24 -0
  10. package/lib/dist/core/interfaces.d.ts +31 -2
  11. package/lib/dist/core/repeat.js +62 -46
  12. package/lib/dist/features/2d/arc.d.ts +8 -2
  13. package/lib/dist/features/2d/arc.js +94 -17
  14. package/lib/dist/features/2d/back.js +3 -2
  15. package/lib/dist/features/2d/sketch.d.ts +4 -0
  16. package/lib/dist/features/2d/sketch.js +21 -0
  17. package/lib/dist/features/2d/tarc-constrained.d.ts +2 -0
  18. package/lib/dist/features/2d/tarc-constrained.js +8 -0
  19. package/lib/dist/features/2d/tarc-radius-to-object.d.ts +16 -0
  20. package/lib/dist/features/2d/tarc-radius-to-object.js +58 -0
  21. package/lib/dist/features/2d/tarc-to-object.d.ts +18 -0
  22. package/lib/dist/features/2d/tarc-to-object.js +66 -0
  23. package/lib/dist/features/2d/tarc-to-point-tangent.d.ts +2 -0
  24. package/lib/dist/features/2d/tarc-to-point-tangent.js +3 -0
  25. package/lib/dist/features/2d/tarc-to-point.d.ts +2 -0
  26. package/lib/dist/features/2d/tarc-to-point.js +3 -0
  27. package/lib/dist/features/2d/tarc-with-tangent.d.ts +2 -0
  28. package/lib/dist/features/2d/tarc-with-tangent.js +3 -0
  29. package/lib/dist/features/2d/tarc.d.ts +2 -0
  30. package/lib/dist/features/2d/tarc.js +3 -0
  31. package/lib/dist/features/extrude-base.d.ts +9 -0
  32. package/lib/dist/features/extrude-base.js +22 -0
  33. package/lib/dist/features/extrude-to-face.js +1 -5
  34. package/lib/dist/features/extrude-two-distances.js +1 -2
  35. package/lib/dist/features/extrude.js +1 -2
  36. package/lib/dist/features/mirror-feature.d.ts +3 -2
  37. package/lib/dist/features/mirror-feature.js +1 -1
  38. package/lib/dist/features/repeat-circular.d.ts +3 -3
  39. package/lib/dist/features/repeat-circular.js +8 -1
  40. package/lib/dist/features/repeat-linear.d.ts +4 -2
  41. package/lib/dist/features/repeat-linear.js +10 -1
  42. package/lib/dist/features/repeat-matrix.d.ts +3 -1
  43. package/lib/dist/features/repeat-matrix.js +7 -2
  44. package/lib/dist/features/shell.d.ts +4 -1
  45. package/lib/dist/features/shell.js +14 -3
  46. package/lib/dist/helpers/clone-transform.d.ts +2 -1
  47. package/lib/dist/index.d.ts +7 -1
  48. package/lib/dist/index.js +3 -3
  49. package/lib/dist/math/lazy-matrix.d.ts +31 -0
  50. package/lib/dist/math/lazy-matrix.js +66 -0
  51. package/lib/dist/oc/constraints/constraint-solver-adaptor.d.ts +5 -0
  52. package/lib/dist/oc/constraints/constraint-solver-adaptor.js +16 -0
  53. package/lib/dist/oc/constraints/constraint-solver.d.ts +4 -0
  54. package/lib/dist/oc/constraints/curve/curve-constraint-solver.d.ts +4 -0
  55. package/lib/dist/oc/constraints/curve/curve-constraint-solver.js +3 -0
  56. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.d.ts +6 -1
  57. package/lib/dist/oc/constraints/geometric/geometric-constraint-solver.js +4 -0
  58. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.d.ts +8 -0
  59. package/lib/dist/oc/constraints/geometric/tangent-arc-from-point-tangent.js +111 -0
  60. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.d.ts +8 -0
  61. package/lib/dist/oc/constraints/geometric/tangent-arc-radius-to-object.js +161 -0
  62. package/lib/dist/oc/mesh.d.ts +9 -4
  63. package/lib/dist/oc/mesh.js +14 -13
  64. package/lib/dist/oc/shell-ops.d.ts +2 -1
  65. package/lib/dist/oc/shell-ops.js +5 -2
  66. package/lib/dist/rendering/mesh-builder.d.ts +3 -0
  67. package/lib/dist/rendering/mesh-builder.js +8 -4
  68. package/lib/dist/rendering/render-edge.d.ts +2 -1
  69. package/lib/dist/rendering/render-edge.js +2 -2
  70. package/lib/dist/rendering/render-face.d.ts +2 -1
  71. package/lib/dist/rendering/render-face.js +2 -2
  72. package/lib/dist/rendering/render-solid.d.ts +2 -1
  73. package/lib/dist/rendering/render-solid.js +2 -2
  74. package/lib/dist/rendering/render-wire.d.ts +2 -1
  75. package/lib/dist/rendering/render-wire.js +2 -2
  76. package/lib/dist/rendering/render.d.ts +3 -0
  77. package/lib/dist/rendering/render.js +7 -2
  78. package/lib/dist/scene-manager.d.ts +4 -2
  79. package/lib/dist/scene-manager.js +12 -4
  80. package/lib/dist/tests/features/2d/arc.test.js +64 -0
  81. package/lib/dist/tests/features/2d/back.test.js +17 -1
  82. package/lib/dist/tests/features/2d/tarc.test.js +157 -0
  83. package/lib/dist/tests/features/repeat-user-repro.test.d.ts +1 -0
  84. package/lib/dist/tests/features/repeat-user-repro.test.js +60 -0
  85. package/lib/dist/tests/features/shell.test.js +36 -0
  86. package/lib/dist/tests/global-setup.js +2 -1
  87. package/lib/dist/tests/helpers/extract-blocks.d.ts +9 -0
  88. package/lib/dist/tests/helpers/extract-blocks.js +56 -0
  89. package/lib/dist/tests/llm-docs-examples.test.d.ts +1 -0
  90. package/lib/dist/tests/llm-docs-examples.test.js +62 -0
  91. package/lib/dist/tests/setup.js +2 -1
  92. package/lib/dist/tsconfig.tsbuildinfo +1 -1
  93. package/llm-docs/.coverage-allowlist.txt +9 -0
  94. package/llm-docs/api/arc.md +48 -0
  95. package/llm-docs/api/axis.md +42 -0
  96. package/llm-docs/api/bezier.md +42 -0
  97. package/llm-docs/api/booleans.md +44 -0
  98. package/llm-docs/api/chamfer.md +40 -0
  99. package/llm-docs/api/circle.md +36 -0
  100. package/llm-docs/api/color.md +34 -0
  101. package/llm-docs/api/connect.md +41 -0
  102. package/llm-docs/api/constraint-qualifiers.md +48 -0
  103. package/llm-docs/api/copy.md +63 -0
  104. package/llm-docs/api/cursor-lines.md +50 -0
  105. package/llm-docs/api/cursor-move.md +61 -0
  106. package/llm-docs/api/cut.md +55 -0
  107. package/llm-docs/api/draft.md +36 -0
  108. package/llm-docs/api/edge-filter.md +57 -0
  109. package/llm-docs/api/ellipse.md +34 -0
  110. package/llm-docs/api/extrude.md +74 -0
  111. package/llm-docs/api/face-filter.md +61 -0
  112. package/llm-docs/api/fillet.md +51 -0
  113. package/llm-docs/api/index.json +139 -0
  114. package/llm-docs/api/line.md +42 -0
  115. package/llm-docs/api/load.md +37 -0
  116. package/llm-docs/api/local.md +38 -0
  117. package/llm-docs/api/loft.md +37 -0
  118. package/llm-docs/api/mirror.md +44 -0
  119. package/llm-docs/api/offset.md +36 -0
  120. package/llm-docs/api/part.md +40 -0
  121. package/llm-docs/api/plane.md +44 -0
  122. package/llm-docs/api/polygon.md +37 -0
  123. package/llm-docs/api/primitive-solids.md +39 -0
  124. package/llm-docs/api/project-intersect.md +48 -0
  125. package/llm-docs/api/rect.md +48 -0
  126. package/llm-docs/api/remove.md +32 -0
  127. package/llm-docs/api/repeat.md +79 -0
  128. package/llm-docs/api/revolve.md +38 -0
  129. package/llm-docs/api/rib.md +40 -0
  130. package/llm-docs/api/rotate.md +37 -0
  131. package/llm-docs/api/select.md +41 -0
  132. package/llm-docs/api/shell.md +41 -0
  133. package/llm-docs/api/sketch.md +76 -0
  134. package/llm-docs/api/slot.md +36 -0
  135. package/llm-docs/api/split-trim.md +42 -0
  136. package/llm-docs/api/sweep.md +43 -0
  137. package/llm-docs/api/tarc.md +45 -0
  138. package/llm-docs/api/tcircle.md +38 -0
  139. package/llm-docs/api/tline.md +42 -0
  140. package/llm-docs/api/translate.md +40 -0
  141. package/llm-docs/api/types/aline.md +35 -0
  142. package/llm-docs/api/types/arc-angles.md +29 -0
  143. package/llm-docs/api/types/arc-points.md +48 -0
  144. package/llm-docs/api/types/axis-like.md +38 -0
  145. package/llm-docs/api/types/axis.md +21 -0
  146. package/llm-docs/api/types/boolean-operation.md +50 -0
  147. package/llm-docs/api/types/circular-repeat-options.md +31 -0
  148. package/llm-docs/api/types/common.md +32 -0
  149. package/llm-docs/api/types/cut.md +125 -0
  150. package/llm-docs/api/types/draft.md +21 -0
  151. package/llm-docs/api/types/extrudable-geometry.md +23 -0
  152. package/llm-docs/api/types/extrude.md +194 -0
  153. package/llm-docs/api/types/geometry.md +51 -0
  154. package/llm-docs/api/types/hline.md +35 -0
  155. package/llm-docs/api/types/linear-repeat-options.md +31 -0
  156. package/llm-docs/api/types/loft.md +154 -0
  157. package/llm-docs/api/types/mirror.md +35 -0
  158. package/llm-docs/api/types/offset.md +31 -0
  159. package/llm-docs/api/types/plane-like.md +35 -0
  160. package/llm-docs/api/types/plane-transform-options.md +29 -0
  161. package/llm-docs/api/types/plane.md +21 -0
  162. package/llm-docs/api/types/point-like.md +22 -0
  163. package/llm-docs/api/types/point2dlike.md +26 -0
  164. package/llm-docs/api/types/polygon.md +46 -0
  165. package/llm-docs/api/types/rect.md +128 -0
  166. package/llm-docs/api/types/revolve.md +102 -0
  167. package/llm-docs/api/types/rib.md +133 -0
  168. package/llm-docs/api/types/scene-object.md +33 -0
  169. package/llm-docs/api/types/select.md +21 -0
  170. package/llm-docs/api/types/shell.md +54 -0
  171. package/llm-docs/api/types/slot.md +43 -0
  172. package/llm-docs/api/types/sweep.md +189 -0
  173. package/llm-docs/api/types/tangent-arc-two-objects.md +46 -0
  174. package/llm-docs/api/types/transformable.md +93 -0
  175. package/llm-docs/api/types/trim.md +27 -0
  176. package/llm-docs/api/types/two-objects-tangent-line.md +46 -0
  177. package/llm-docs/api/types/vertex.md +17 -0
  178. package/llm-docs/api/types/vline.md +35 -0
  179. package/llm-docs/concepts/coordinate-system.md +45 -0
  180. package/llm-docs/concepts/history-and-rollback.md +40 -0
  181. package/llm-docs/concepts/last-selection.md +49 -0
  182. package/llm-docs/concepts/scene-graph.md +37 -0
  183. package/llm-docs/index.json +1750 -0
  184. package/mcp/dist/client.d.ts +64 -0
  185. package/mcp/dist/client.js +248 -0
  186. package/mcp/dist/discovery.d.ts +11 -0
  187. package/mcp/dist/discovery.js +78 -0
  188. package/mcp/dist/docs-index.d.ts +81 -0
  189. package/mcp/dist/docs-index.js +261 -0
  190. package/mcp/dist/resources.d.ts +4 -0
  191. package/mcp/dist/resources.js +115 -0
  192. package/mcp/dist/server.d.ts +12 -0
  193. package/mcp/dist/server.js +489 -0
  194. package/mcp/dist/tools/coordination.d.ts +9 -0
  195. package/mcp/dist/tools/coordination.js +46 -0
  196. package/mcp/dist/tools/docs.d.ts +66 -0
  197. package/mcp/dist/tools/docs.js +122 -0
  198. package/mcp/dist/tools/engine.d.ts +56 -0
  199. package/mcp/dist/tools/engine.js +145 -0
  200. package/mcp/dist/tools/inspection.d.ts +75 -0
  201. package/mcp/dist/tools/inspection.js +121 -0
  202. package/mcp/dist/tools/screenshot.d.ts +63 -0
  203. package/mcp/dist/tools/screenshot.js +263 -0
  204. package/mcp/dist/tools/source.d.ts +84 -0
  205. package/mcp/dist/tools/source.js +434 -0
  206. package/mcp/dist/tools/workspaces.d.ts +13 -0
  207. package/mcp/dist/tools/workspaces.js +33 -0
  208. package/mcp/dist/types.d.ts +18 -0
  209. package/mcp/dist/types.js +11 -0
  210. package/package.json +19 -5
  211. package/server/dist/code-editor.d.ts +36 -0
  212. package/server/dist/code-editor.js +8 -0
  213. package/server/dist/fluidcad-server.d.ts +50 -0
  214. package/server/dist/fluidcad-server.js +153 -1
  215. package/server/dist/global-registry.d.ts +30 -0
  216. package/server/dist/global-registry.js +126 -0
  217. package/server/dist/index.js +171 -26
  218. package/server/dist/instance-file.d.ts +31 -0
  219. package/server/dist/instance-file.js +73 -0
  220. package/server/dist/lint-fluid-js.d.ts +15 -0
  221. package/server/dist/lint-fluid-js.js +271 -0
  222. package/server/dist/routes/editor.d.ts +24 -0
  223. package/server/dist/routes/editor.js +44 -0
  224. package/server/dist/routes/export.d.ts +1 -1
  225. package/server/dist/routes/export.js +45 -8
  226. package/server/dist/routes/health.d.ts +7 -0
  227. package/server/dist/routes/health.js +14 -0
  228. package/server/dist/routes/lint.d.ts +10 -0
  229. package/server/dist/routes/lint.js +28 -0
  230. package/server/dist/routes/render.d.ts +33 -0
  231. package/server/dist/routes/render.js +34 -0
  232. package/server/dist/routes/scene.d.ts +5 -0
  233. package/server/dist/routes/scene.js +48 -0
  234. package/server/dist/routes/screenshot.js +68 -1
  235. package/server/dist/ws-protocol.d.ts +56 -2
  236. package/ui/dist/assets/{index-CFi9p7wR.js → index-BdqrMDRu.js} +21 -21
  237. package/ui/dist/index.html +1 -1
@@ -1,15 +1,36 @@
1
1
  import { registerBuilder } from "../index.js";
2
- import { normalizeAxis, normalizePlane } from "../helpers/normalize.js";
2
+ import { Axis } from "../math/axis.js";
3
+ import { SceneObject } from "../common/scene-object.js";
3
4
  import { Matrix4 } from "../math/matrix4.js";
5
+ import { LazyMatrix } from "../math/lazy-matrix.js";
4
6
  import { rad } from "../helpers/math-helpers.js";
5
7
  import { RepeatLinear } from "../features/repeat-linear.js";
6
8
  import { RepeatCircular } from "../features/repeat-circular.js";
7
9
  import { cloneWithTransform } from "../helpers/clone-transform.js";
8
- import { PlaneObjectBase } from "../features/plane-renderable-base.js";
9
- import { PlaneObject } from "../features/plane.js";
10
10
  import { MirrorFeature } from "../features/mirror-feature.js";
11
11
  import { RepeatMatrix } from "../features/repeat-matrix.js";
12
+ import { resolveAxis, resolvePlane } from "../helpers/resolve.js";
13
+ import { normalizeAxis } from "../helpers/normalize.js";
12
14
  import { AxisObjectBase } from "../features/axis-renderable-base.js";
15
+ /**
16
+ * Resolve a repeat axis argument to a value usable by LazyMatrix. Scene-
17
+ * resident sources (AxisObjectBase or an edge SceneObject) go through
18
+ * resolveAxis so they end up in the scene and get built before consumers.
19
+ * Primitive inputs (world-axis string, raw Axis) stay as concrete Axis
20
+ * values — no extra scene object, no rendered world-axis line.
21
+ */
22
+ function resolveRepeatAxis(arg, context) {
23
+ if (arg instanceof AxisObjectBase) {
24
+ return arg;
25
+ }
26
+ if (arg instanceof SceneObject) {
27
+ return resolveAxis(arg, context);
28
+ }
29
+ if (arg instanceof Axis) {
30
+ return arg;
31
+ }
32
+ return normalizeAxis(arg);
33
+ }
13
34
  function build(context) {
14
35
  return (function repeat() {
15
36
  const args = Array.from(arguments);
@@ -23,8 +44,9 @@ function build(context) {
23
44
  const objects = restObjects.length > 0
24
45
  ? restObjects
25
46
  : [context.getSceneObjects().at(-1)];
26
- const feature = new RepeatMatrix(matrix, objects);
27
- const cloned = cloneWithTransform(objects, matrix, feature);
47
+ const lazy = LazyMatrix.of(matrix);
48
+ const feature = new RepeatMatrix(lazy, objects);
49
+ const cloned = cloneWithTransform(objects, lazy, feature);
28
50
  context.addSceneObject(feature);
29
51
  context.addSceneObjects(cloned);
30
52
  return feature;
@@ -35,9 +57,9 @@ function build(context) {
35
57
  const type = args[0];
36
58
  if (type === 'linear' || type === 'circular') {
37
59
  const axisArg = args[1];
38
- const axes = Array.isArray(axisArg)
39
- ? axisArg.map(a => normalizeAxis(a))
40
- : [normalizeAxis(axisArg)];
60
+ const axisSources = Array.isArray(axisArg)
61
+ ? axisArg.map(a => resolveRepeatAxis(a, context))
62
+ : [resolveRepeatAxis(axisArg, context)];
41
63
  const options = args[2];
42
64
  const restObjects = args.slice(3);
43
65
  const objects = restObjects.length > 0
@@ -51,9 +73,9 @@ function build(context) {
51
73
  const lengths = 'length' in options && options.length != null
52
74
  ? (Array.isArray(options.length) ? options.length : [options.length])
53
75
  : null;
54
- const repeat = new RepeatLinear(axes, options, objects);
76
+ const repeat = new RepeatLinear(axisSources, options, objects);
55
77
  const transformedObjects = [];
56
- const axisOffsets = axes.map((axis, i) => {
78
+ const axisOffsets = axisSources.map((axis, i) => {
57
79
  const count = counts[i] ?? counts[0];
58
80
  const offset = offsets != null
59
81
  ? (offsets[i] ?? offsets[0])
@@ -88,19 +110,26 @@ function build(context) {
88
110
  if (options.skip?.some(s => s.length === indices.length && s.every((v, i) => v === indices[i]))) {
89
111
  continue;
90
112
  }
91
- // Compose translation from all axes
92
- let dx = 0, dy = 0, dz = 0;
93
- for (let a = 0; a < axisOffsets.length; a++) {
94
- const { axis, offset } = axisOffsets[a];
113
+ // Capture per-axis offset + signed index for this instance; the
114
+ // axis direction is read lazily at build time so an AxisObjectBase
115
+ // can still be unbuilt at parse time.
116
+ const perAxis = axisOffsets.map((entry, a) => {
95
117
  const idx = options.centered
96
- ? indices[a] - Math.floor(axisOffsets[a].count / 2)
118
+ ? indices[a] - Math.floor(entry.count / 2)
97
119
  : indices[a];
98
- dx += axis.direction.x * offset * idx;
99
- dy += axis.direction.y * offset * idx;
100
- dz += axis.direction.z * offset * idx;
101
- }
102
- const transform = Matrix4.fromTranslation(dx, dy, dz);
103
- const cloned = cloneWithTransform(objects, transform, repeat);
120
+ return { axis: entry.axis, offset: entry.offset, idx };
121
+ });
122
+ const lazy = LazyMatrix.from(() => {
123
+ let dx = 0, dy = 0, dz = 0;
124
+ for (const { axis, offset, idx } of perAxis) {
125
+ const dir = (axis instanceof AxisObjectBase ? axis.getAxis() : axis).direction;
126
+ dx += dir.x * offset * idx;
127
+ dy += dir.y * offset * idx;
128
+ dz += dir.z * offset * idx;
129
+ }
130
+ return Matrix4.fromTranslation(dx, dy, dz);
131
+ });
132
+ const cloned = cloneWithTransform(objects, lazy, repeat);
104
133
  transformedObjects.push(...cloned);
105
134
  }
106
135
  context.addSceneObject(repeat);
@@ -108,7 +137,7 @@ function build(context) {
108
137
  return repeat;
109
138
  }
110
139
  if (type === 'circular') {
111
- const axis = axes[0];
140
+ const axis = axisSources[0];
112
141
  const circularOptions = options;
113
142
  const { count, centered, skip } = circularOptions;
114
143
  const repeat = new RepeatCircular(axis, circularOptions, objects);
@@ -127,8 +156,8 @@ function build(context) {
127
156
  continue;
128
157
  }
129
158
  const angle = startOffset + offset * i;
130
- const matrix = Matrix4.fromRotationAroundAxis(axis.origin, axis.direction, rad(angle));
131
- const cloned = cloneWithTransform(objects, matrix, repeat);
159
+ const lazy = LazyMatrix.rotation(axis, rad(angle));
160
+ const cloned = cloneWithTransform(objects, lazy, repeat);
132
161
  transformedObjects.push(...cloned);
133
162
  }
134
163
  context.addSceneObject(repeat);
@@ -142,31 +171,16 @@ function build(context) {
142
171
  const targetObjects = restObjects.length > 0
143
172
  ? restObjects
144
173
  : [context.getSceneObjects().at(-1)];
145
- let planeObj;
146
- let normalizedPlane;
147
- if (planeArg instanceof PlaneObjectBase) {
148
- planeObj = planeArg;
149
- planeObj.build();
150
- normalizedPlane = planeObj.getPlane();
151
- }
152
- else {
153
- normalizedPlane = normalizePlane(planeArg);
154
- planeObj = new PlaneObject(normalizedPlane);
155
- planeObj.build();
156
- context.addSceneObject(planeObj);
157
- }
158
- const matrix = Matrix4.mirrorPlane(normalizedPlane.normal, normalizedPlane.origin);
159
- const mirrorFeature = new MirrorFeature(planeObj, matrix);
160
- const mirrorTree = cloneWithTransform(targetObjects, matrix, mirrorFeature);
174
+ const planeObj = resolvePlane(planeArg, context);
175
+ const lazy = LazyMatrix.mirror(planeObj);
176
+ const mirrorFeature = new MirrorFeature(planeObj, lazy);
177
+ const mirrorTree = cloneWithTransform(targetObjects, lazy, mirrorFeature);
161
178
  context.addSceneObject(mirrorFeature);
162
179
  context.addSceneObjects(mirrorTree);
163
180
  return mirrorFeature;
164
181
  }
165
182
  if (type === 'rotate') {
166
183
  const axisArg = args[1];
167
- const axis = axisArg instanceof AxisObjectBase
168
- ? axisArg.getAxis()
169
- : normalizeAxis(axisArg);
170
184
  let angle = 90;
171
185
  let restStart = 2;
172
186
  if (typeof args[2] === 'number') {
@@ -177,9 +191,11 @@ function build(context) {
177
191
  const objects = restObjects.length > 0
178
192
  ? restObjects
179
193
  : [context.getSceneObjects().at(-1)];
180
- const matrix = Matrix4.fromRotationAroundAxis(axis.origin, axis.direction, rad(angle));
181
- const feature = new RepeatMatrix(matrix, objects);
182
- const cloned = cloneWithTransform(objects, matrix, feature);
194
+ const axis = resolveRepeatAxis(axisArg, context);
195
+ const lazy = LazyMatrix.rotation(axis, rad(angle));
196
+ const sources = axis instanceof AxisObjectBase ? [axis] : [];
197
+ const feature = new RepeatMatrix(lazy, objects, sources);
198
+ const cloned = cloneWithTransform(objects, lazy, feature);
183
199
  context.addSceneObject(feature);
184
200
  context.addSceneObjects(cloned);
185
201
  return feature;
@@ -2,9 +2,9 @@ import { Point2DLike } from "../../math/point.js";
2
2
  import { PlaneObjectBase } from "../plane-renderable-base.js";
3
3
  import { GeometrySceneObject } from "./geometry.js";
4
4
  import { LazyVertex } from "../lazy-vertex.js";
5
- import { IArcPoints, IArcAngles } from "../../core/interfaces.js";
5
+ import { IArcPoints, IArcRadius, IArcCenter, IArcAngles } from "../../core/interfaces.js";
6
6
  import { SceneObject } from "../../common/scene-object.js";
7
- export declare class Arc extends GeometrySceneObject implements IArcPoints, IArcAngles {
7
+ export declare class Arc extends GeometrySceneObject implements IArcPoints, IArcRadius, IArcCenter, IArcAngles {
8
8
  private _startPoint;
9
9
  private _endPoint;
10
10
  private _arcRadius;
@@ -13,18 +13,24 @@ export declare class Arc extends GeometrySceneObject implements IArcPoints, IArc
13
13
  private _bulgeRadius;
14
14
  private _centerPoint;
15
15
  private _centered;
16
+ private _clockwise;
17
+ private _major;
16
18
  private _targetPlane;
17
19
  constructor(targetPlane?: PlaneObjectBase | null);
18
20
  static toPoint(endPoint: LazyVertex, targetPlane?: PlaneObjectBase | null): Arc;
19
21
  static twoPoints(startPoint: LazyVertex, endPoint: LazyVertex, targetPlane?: PlaneObjectBase | null): Arc;
20
22
  static fromAngles(arcRadius: number, startAngle: number, endAngle: number, targetPlane?: PlaneObjectBase | null): Arc;
23
+ private static circumcenter;
21
24
  radius(value: number): this;
22
25
  center(value: Point2DLike): this;
23
26
  centered(): this;
27
+ cw(): this;
28
+ major(): this;
24
29
  build(): void;
25
30
  private buildTwoPointsCenter;
26
31
  private buildTwoPointsBulge;
27
32
  private buildToPoint;
33
+ private makeMajorArc;
28
34
  private buildWithCenter;
29
35
  private buildFromAngles;
30
36
  getType(): string;
@@ -16,6 +16,8 @@ export class Arc extends GeometrySceneObject {
16
16
  _bulgeRadius = 0;
17
17
  _centerPoint = null;
18
18
  _centered = false;
19
+ _clockwise = false;
20
+ _major = false;
19
21
  _targetPlane;
20
22
  constructor(targetPlane = null) {
21
23
  super();
@@ -39,6 +41,13 @@ export class Arc extends GeometrySceneObject {
39
41
  arc._endAngle = endAngle;
40
42
  return arc;
41
43
  }
44
+ static circumcenter(a, b, c) {
45
+ const D = 2 * (a.x * (b.y - c.y) + b.x * (c.y - a.y) + c.x * (a.y - b.y));
46
+ const aa = a.x * a.x + a.y * a.y;
47
+ const bb = b.x * b.x + b.y * b.y;
48
+ const cc = c.x * c.x + c.y * c.y;
49
+ return new Point2D((aa * (b.y - c.y) + bb * (c.y - a.y) + cc * (a.y - b.y)) / D, (aa * (c.x - b.x) + bb * (a.x - c.x) + cc * (b.x - a.x)) / D);
50
+ }
42
51
  // Chainable methods (IArc)
43
52
  radius(value) {
44
53
  this._bulgeRadius = value;
@@ -52,6 +61,14 @@ export class Arc extends GeometrySceneObject {
52
61
  this._centered = true;
53
62
  return this;
54
63
  }
64
+ cw() {
65
+ this._clockwise = true;
66
+ return this;
67
+ }
68
+ major() {
69
+ this._major = true;
70
+ return this;
71
+ }
55
72
  build() {
56
73
  if (this._startPoint && this._endPoint) {
57
74
  // Two explicit points: default center = current position
@@ -81,21 +98,26 @@ export class Arc extends GeometrySceneObject {
81
98
  const endPt = this._endPoint.asPoint2D();
82
99
  const centerPt = this._centerPoint
83
100
  ? this._centerPoint.asPoint2D()
84
- : this.getCurrentPosition();
101
+ : new Point2D((startPt.x + endPt.x) / 2, (startPt.y + endPt.y) / 2);
85
102
  const dx = startPt.x - centerPt.x;
86
103
  const dy = startPt.y - centerPt.y;
87
104
  const radius = Math.sqrt(dx * dx + dy * dy);
88
105
  const endAngle = Math.atan2(endPt.y - centerPt.y, endPt.x - centerPt.x);
106
+ const normal = this._clockwise ? plane.normal.negate() : plane.normal;
89
107
  const center = plane.localToWorld(centerPt);
90
108
  const start = plane.localToWorld(startPt);
91
109
  const end = plane.localToWorld(endPt);
92
- const arc = Geometry.makeArc(center, radius, plane.normal, start, end);
110
+ const arc = Geometry.makeArc(center, radius, normal, start, end);
93
111
  const edge = Geometry.makeEdgeFromCurve(arc);
94
- const tx = -Math.sin(endAngle);
95
- const ty = Math.cos(endAngle);
112
+ const sign = this._clockwise ? -1 : 1;
113
+ const tx = sign * (-Math.sin(endAngle));
114
+ const ty = sign * Math.cos(endAngle);
96
115
  this.setTangent(new Point2D(tx, ty));
97
116
  this.setState('start', Vertex.fromPoint2D(startPt));
98
117
  this.setState('end', Vertex.fromPoint2D(endPt));
118
+ const centerVertex = Vertex.fromPoint2D(centerPt);
119
+ centerVertex.markAsMetaShape();
120
+ this.addShape(centerVertex);
99
121
  this.addShape(edge);
100
122
  if (this.sketch) {
101
123
  this.setCurrentPosition(endPt);
@@ -129,14 +151,19 @@ export class Arc extends GeometrySceneObject {
129
151
  const center = plane.localToWorld(centerPoint);
130
152
  const start = plane.localToWorld(startPoint);
131
153
  const end = plane.localToWorld(targetPoint);
132
- const arc = Geometry.makeArc(center, r, normal, start, end);
154
+ const arc = this._major
155
+ ? this.makeMajorArc(startPoint, targetPoint, centerPoint, cw, plane)
156
+ : Geometry.makeArc(center, r, normal, start, end);
133
157
  const edge = Geometry.makeEdgeFromCurve(arc);
134
- const signT = cw ? -1 : 1;
158
+ const signT = (cw ? -1 : 1) * (this._major ? -1 : 1);
135
159
  const endTx = signT * (-Math.sin(endAngle));
136
160
  const endTy = signT * Math.cos(endAngle);
137
161
  this.setTangent(new Point2D(endTx, endTy));
138
162
  this.setState('start', Vertex.fromPoint2D(startPoint));
139
163
  this.setState('end', Vertex.fromPoint2D(targetPoint));
164
+ const centerVertex = Vertex.fromPoint2D(centerPoint);
165
+ centerVertex.markAsMetaShape();
166
+ this.addShape(centerVertex);
140
167
  this.addShape(edge);
141
168
  if (this.sketch) {
142
169
  this.setCurrentPosition(targetPoint);
@@ -172,14 +199,19 @@ export class Arc extends GeometrySceneObject {
172
199
  const center = plane.localToWorld(centerPoint);
173
200
  const start = plane.localToWorld(startPoint);
174
201
  const end = plane.localToWorld(targetPoint);
175
- const arc = Geometry.makeArc(center, r, normal, start, end);
202
+ const arc = this._major
203
+ ? this.makeMajorArc(startPoint, targetPoint, centerPoint, cw, plane)
204
+ : Geometry.makeArc(center, r, normal, start, end);
176
205
  const edge = Geometry.makeEdgeFromCurve(arc);
177
- const signT = cw ? -1 : 1;
206
+ const signT = (cw ? -1 : 1) * (this._major ? -1 : 1);
178
207
  const endTx = signT * (-Math.sin(endAngle));
179
208
  const endTy = signT * Math.cos(endAngle);
180
209
  this.setTangent(new Point2D(endTx, endTy));
181
210
  this.setState('start', Vertex.fromPoint2D(startPoint));
182
211
  this.setState('end', Vertex.fromPoint2D(targetPoint));
212
+ const centerVertex = Vertex.fromPoint2D(centerPoint);
213
+ centerVertex.markAsMetaShape();
214
+ this.addShape(centerVertex);
183
215
  this.addShape(edge);
184
216
  if (this.sketch) {
185
217
  this.setCurrentPosition(targetPoint);
@@ -188,6 +220,24 @@ export class Arc extends GeometrySceneObject {
188
220
  this._targetPlane.removeShapes(this);
189
221
  }
190
222
  }
223
+ makeMajorArc(startPoint2D, endPoint2D, centerPoint2D, cw, plane) {
224
+ const startAngleRad = Math.atan2(startPoint2D.y - centerPoint2D.y, startPoint2D.x - centerPoint2D.x);
225
+ const endAngleRad = Math.atan2(endPoint2D.y - centerPoint2D.y, endPoint2D.x - centerPoint2D.x);
226
+ let minorSweep = cw ? startAngleRad - endAngleRad : endAngleRad - startAngleRad;
227
+ if (minorSweep <= 0) {
228
+ minorSweep += 2 * Math.PI;
229
+ }
230
+ const midAngle = cw
231
+ ? startAngleRad + (2 * Math.PI - minorSweep) / 2
232
+ : startAngleRad - (2 * Math.PI - minorSweep) / 2;
233
+ const r = Math.sqrt((startPoint2D.x - centerPoint2D.x) ** 2 +
234
+ (startPoint2D.y - centerPoint2D.y) ** 2);
235
+ const midPoint2D = new Point2D(centerPoint2D.x + r * Math.cos(midAngle), centerPoint2D.y + r * Math.sin(midAngle));
236
+ const start = plane.localToWorld(startPoint2D);
237
+ const mid = plane.localToWorld(midPoint2D);
238
+ const end = plane.localToWorld(endPoint2D);
239
+ return Geometry.makeArcThreePoints(start, mid, end);
240
+ }
191
241
  buildWithCenter() {
192
242
  const plane = this._targetPlane?.getPlane() || this.sketch.getPlane();
193
243
  const startPt = this._targetPlane
@@ -195,20 +245,33 @@ export class Arc extends GeometrySceneObject {
195
245
  : this.getCurrentPosition();
196
246
  const endPt = this._endPoint.asPoint2D();
197
247
  const centerPt = this._centerPoint.asPoint2D();
198
- const dx = startPt.x - centerPt.x;
199
- const dy = startPt.y - centerPt.y;
200
- const radius = Math.sqrt(dx * dx + dy * dy);
201
- const endAngle = Math.atan2(endPt.y - centerPt.y, endPt.x - centerPt.x);
202
- const center = plane.localToWorld(centerPt);
248
+ const aStart = Math.atan2(startPt.y - centerPt.y, startPt.x - centerPt.x);
249
+ const aEnd = Math.atan2(endPt.y - centerPt.y, endPt.x - centerPt.x);
250
+ let sweep = this._clockwise ? aStart - aEnd : aEnd - aStart;
251
+ if (sweep <= 0) {
252
+ sweep += 2 * Math.PI;
253
+ }
254
+ const midAngle = this._clockwise ? aStart - sweep / 2 : aStart + sweep / 2;
255
+ const rStart = Math.sqrt((startPt.x - centerPt.x) ** 2 + (startPt.y - centerPt.y) ** 2);
256
+ const rEnd = Math.sqrt((endPt.x - centerPt.x) ** 2 + (endPt.y - centerPt.y) ** 2);
257
+ const rMid = (rStart + rEnd) / 2;
258
+ const midPt = new Point2D(centerPt.x + rMid * Math.cos(midAngle), centerPt.y + rMid * Math.sin(midAngle));
259
+ const actualCenter = Arc.circumcenter(startPt, midPt, endPt);
260
+ const endAngle = Math.atan2(endPt.y - actualCenter.y, endPt.x - actualCenter.x);
203
261
  const start = plane.localToWorld(startPt);
204
262
  const end = plane.localToWorld(endPt);
205
- const arc = Geometry.makeArc(center, radius, plane.normal, start, end);
263
+ const mid = plane.localToWorld(midPt);
264
+ const arc = Geometry.makeArcThreePoints(start, mid, end);
206
265
  const edge = Geometry.makeEdgeFromCurve(arc);
207
- const tx = -Math.sin(endAngle);
208
- const ty = Math.cos(endAngle);
266
+ const sign = this._clockwise ? -1 : 1;
267
+ const tx = sign * (-Math.sin(endAngle));
268
+ const ty = sign * Math.cos(endAngle);
209
269
  this.setTangent(new Point2D(tx, ty));
210
270
  this.setState('start', Vertex.fromPoint2D(startPt));
211
271
  this.setState('end', Vertex.fromPoint2D(endPt));
272
+ const centerVertex = Vertex.fromPoint2D(actualCenter);
273
+ centerVertex.markAsMetaShape();
274
+ this.addShape(centerVertex);
212
275
  this.addShape(edge);
213
276
  if (this.sketch) {
214
277
  this.setCurrentPosition(endPt);
@@ -254,6 +317,9 @@ export class Arc extends GeometrySceneObject {
254
317
  const edge = Geometry.makeEdgeFromCurve(arc);
255
318
  this.setState('start', Vertex.fromPoint2D(startPoint));
256
319
  this.setState('end', Vertex.fromPoint2D(endPoint));
320
+ const centerVertex = Vertex.fromPoint2D(centerPoint);
321
+ centerVertex.markAsMetaShape();
322
+ this.addShape(centerVertex);
257
323
  const sign = cw ? -1 : 1;
258
324
  const tx = sign * (-Math.sin(endAngleRad));
259
325
  const ty = sign * Math.cos(endAngleRad);
@@ -286,6 +352,8 @@ export class Arc extends GeometrySceneObject {
286
352
  copy._bulgeRadius = this._bulgeRadius;
287
353
  copy._centerPoint = this._centerPoint;
288
354
  copy._centered = this._centered;
355
+ copy._clockwise = this._clockwise;
356
+ copy._major = this._major;
289
357
  return copy;
290
358
  }
291
359
  compareTo(other) {
@@ -301,6 +369,9 @@ export class Arc extends GeometrySceneObject {
301
369
  if (this._targetPlane && other._targetPlane && !this._targetPlane.compareTo(other._targetPlane)) {
302
370
  return false;
303
371
  }
372
+ if (this._clockwise !== other._clockwise) {
373
+ return false;
374
+ }
304
375
  if (this._endPoint && other._endPoint) {
305
376
  if (!this._endPoint.compareTo(other._endPoint)) {
306
377
  return false;
@@ -316,7 +387,7 @@ export class Arc extends GeometrySceneObject {
316
387
  if (this._centerPoint && other._centerPoint) {
317
388
  return this._centerPoint.compareTo(other._centerPoint);
318
389
  }
319
- return this._bulgeRadius === other._bulgeRadius;
390
+ return this._bulgeRadius === other._bulgeRadius && this._major === other._major;
320
391
  }
321
392
  if (!this._endPoint && !other._endPoint) {
322
393
  return this._arcRadius === other._arcRadius &&
@@ -340,6 +411,12 @@ export class Arc extends GeometrySceneObject {
340
411
  if (this._bulgeRadius !== 0) {
341
412
  base.radius = this._bulgeRadius;
342
413
  }
414
+ if (this._clockwise) {
415
+ base.clockwise = true;
416
+ }
417
+ if (this._major) {
418
+ base.major = true;
419
+ }
343
420
  return base;
344
421
  }
345
422
  return {
@@ -9,8 +9,9 @@ export class Back extends GeometrySceneObject {
9
9
  return 'back';
10
10
  }
11
11
  build() {
12
- const target = this.sketch.getPreviousPosition(this, this.count);
13
- this.setCurrentPosition(target);
12
+ const { position, tangent } = this.sketch.getPreviousState(this, this.count);
13
+ this.setCurrentPosition(position);
14
+ this.setTangent(tangent);
14
15
  }
15
16
  getDependencies() {
16
17
  return [];
@@ -15,6 +15,10 @@ export declare class Sketch extends SceneObject implements Extrudable {
15
15
  getTangentAt(currentObj: GeometrySceneObject): Point2D;
16
16
  getPositionAt(currentObj: GeometrySceneObject): Point2D;
17
17
  getPreviousPosition(currentObj: GeometrySceneObject, count?: number): Point2D;
18
+ getPreviousState(currentObj: GeometrySceneObject, count?: number): {
19
+ position: Point2D;
20
+ tangent: Point2D;
21
+ };
18
22
  getLastPosition(scope?: Set<SceneObject>): Point2D;
19
23
  build(context?: BuildSceneObjectContext): void;
20
24
  getEdges(): Edge[];
@@ -78,6 +78,27 @@ export class Sketch extends SceneObject {
78
78
  }
79
79
  return this.getStartPoint();
80
80
  }
81
+ getPreviousState(currentObj, count = 1) {
82
+ const children = this.getChildren();
83
+ const previous = children.slice(0, children.indexOf(currentObj));
84
+ let remaining = count;
85
+ for (let i = previous.length - 1; i >= 0; i--) {
86
+ const pos = previous[i].getState('current-position');
87
+ if (pos) {
88
+ if (remaining === 0) {
89
+ for (let j = i; j >= 0; j--) {
90
+ const t = previous[j].getTangent();
91
+ if (t) {
92
+ return { position: pos, tangent: t };
93
+ }
94
+ }
95
+ return { position: pos, tangent: new Point2D(1, 0) };
96
+ }
97
+ remaining--;
98
+ }
99
+ }
100
+ return { position: this.getStartPoint(), tangent: new Point2D(1, 0) };
101
+ }
81
102
  getLastPosition(scope) {
82
103
  let children = this.getChildren().slice();
83
104
  if (scope) {
@@ -1,4 +1,5 @@
1
1
  import { GeometrySceneObject } from "./geometry.js";
2
+ import { SceneObject } from "../../common/scene-object.js";
2
3
  import { LazyVertex } from "../lazy-vertex.js";
3
4
  import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
5
  import { ITangentArcTwoObjects } from "../../core/interfaces.js";
@@ -11,6 +12,7 @@ export declare class TangentArcTwoObjects extends GeometrySceneObject implements
11
12
  build(): void;
12
13
  start(index?: number): LazyVertex;
13
14
  end(index?: number): LazyVertex;
15
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
14
16
  compareTo(other: TangentArcTwoObjects): boolean;
15
17
  getType(): string;
16
18
  getUniqueType(): string;
@@ -1,6 +1,7 @@
1
1
  import { GeometrySceneObject } from "./geometry.js";
2
2
  import { LazyVertex } from "../lazy-vertex.js";
3
3
  import { Vertex } from "../../common/vertex.js";
4
+ import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
5
  import { createConstraintSolver } from "../../oc/constraints/create-solver.js";
5
6
  export class TangentArcTwoObjects extends GeometrySceneObject {
6
7
  c1;
@@ -41,6 +42,13 @@ export class TangentArcTwoObjects extends GeometrySceneObject {
41
42
  end(index = 0) {
42
43
  return new LazyVertex(this.generateUniqueName(`end-vertex-${index}`), () => [this.getState('end')]);
43
44
  }
45
+ createCopy(remap) {
46
+ const remappedC1Object = remap.get(this.c1.object) || this.c1.object;
47
+ const remappedC2Object = remap.get(this.c2.object) || this.c2.object;
48
+ const c1 = new QualifiedSceneObject(remappedC1Object, this.c1.qualifier);
49
+ const c2 = new QualifiedSceneObject(remappedC2Object, this.c2.qualifier);
50
+ return new TangentArcTwoObjects(c1, c2, this.radius, this.mustTouch);
51
+ }
44
52
  compareTo(other) {
45
53
  if (!(other instanceof TangentArcTwoObjects)) {
46
54
  return false;
@@ -0,0 +1,16 @@
1
+ import { GeometrySceneObject } from "./geometry.js";
2
+ import { SceneObject } from "../../common/scene-object.js";
3
+ import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
+ export declare class TangentArcRadiusToObject extends GeometrySceneObject {
5
+ radius: number;
6
+ target: QualifiedSceneObject;
7
+ constructor(radius: number, target: QualifiedSceneObject);
8
+ build(): void;
9
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
10
+ compareTo(other: TangentArcRadiusToObject): boolean;
11
+ getType(): string;
12
+ getUniqueType(): string;
13
+ serialize(): {
14
+ radius: number;
15
+ };
16
+ }
@@ -0,0 +1,58 @@
1
+ import { GeometrySceneObject } from "./geometry.js";
2
+ import { Vertex } from "../../common/vertex.js";
3
+ import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
+ import { solveTangentArcRadiusToObject } from "../../oc/constraints/geometric/tangent-arc-radius-to-object.js";
5
+ export class TangentArcRadiusToObject extends GeometrySceneObject {
6
+ radius;
7
+ target;
8
+ constructor(radius, target) {
9
+ super();
10
+ this.radius = radius;
11
+ this.target = target;
12
+ }
13
+ build() {
14
+ const plane = this.sketch.getPlane();
15
+ const startPoint = this.getCurrentPosition();
16
+ const startTangent = this.sketch.getTangentAt(this);
17
+ const targetShape = this.target.toQualifiedShape();
18
+ const result = solveTangentArcRadiusToObject(plane, startPoint, startTangent, this.radius, targetShape);
19
+ for (let i = 0; i < result.edges.length; i++) {
20
+ this.setState(`edge-${i}`, result.edges[i]);
21
+ }
22
+ if (result.edges.length > 0) {
23
+ const lastEdge = result.edges[result.edges.length - 1];
24
+ const localStart = plane.worldToLocal(lastEdge.getFirstVertex().toPoint());
25
+ const localEnd = plane.worldToLocal(lastEdge.getLastVertex().toPoint());
26
+ this.setState('start', Vertex.fromPoint2D(localStart));
27
+ this.setState('end', Vertex.fromPoint2D(localEnd));
28
+ if (result.endTangent) {
29
+ this.setTangent(result.endTangent);
30
+ }
31
+ this.setCurrentPosition(localEnd);
32
+ }
33
+ this.addShapes(result.edges);
34
+ }
35
+ createCopy(remap) {
36
+ const remappedObject = remap.get(this.target.object) || this.target.object;
37
+ const target = new QualifiedSceneObject(remappedObject, this.target.qualifier);
38
+ return new TangentArcRadiusToObject(this.radius, target);
39
+ }
40
+ compareTo(other) {
41
+ if (!(other instanceof TangentArcRadiusToObject)) {
42
+ return false;
43
+ }
44
+ if (!super.compareTo(other)) {
45
+ return false;
46
+ }
47
+ return this.radius === other.radius && this.target.compareTo(other.target);
48
+ }
49
+ getType() {
50
+ return 'tarc';
51
+ }
52
+ getUniqueType() {
53
+ return 'tarc-radius-to-object';
54
+ }
55
+ serialize() {
56
+ return { radius: this.radius };
57
+ }
58
+ }
@@ -0,0 +1,18 @@
1
+ import { GeometrySceneObject } from "./geometry.js";
2
+ import { SceneObject } from "../../common/scene-object.js";
3
+ import { QualifiedSceneObject } from "./constraints/qualified-geometry.js";
4
+ import { ITangentArcToObject } from "../../core/interfaces.js";
5
+ export declare class TangentArcToObject extends GeometrySceneObject implements ITangentArcToObject {
6
+ target: QualifiedSceneObject;
7
+ private flipped;
8
+ constructor(target: QualifiedSceneObject);
9
+ flip(): this;
10
+ build(): void;
11
+ createCopy(remap: Map<SceneObject, SceneObject>): SceneObject;
12
+ compareTo(other: TangentArcToObject): boolean;
13
+ getType(): string;
14
+ getUniqueType(): string;
15
+ serialize(): {
16
+ flipped: boolean;
17
+ };
18
+ }