brep-io-kernel 1.0.0 → 1.0.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.
Files changed (134) hide show
  1. package/README.md +16 -3
  2. package/package.json +5 -1
  3. package/dist-kernel/help/CONTRIBUTING.html +0 -248
  4. package/dist-kernel/help/LICENSE.html +0 -248
  5. package/dist-kernel/help/MODELING.png +0 -0
  6. package/dist-kernel/help/PMI.png +0 -0
  7. package/dist-kernel/help/SKETCH.png +0 -0
  8. package/dist-kernel/help/assembly-constraints__Coincident_Constraint_dialog.png +0 -0
  9. package/dist-kernel/help/assembly-constraints___Angle_Constraint_dialog.png +0 -0
  10. package/dist-kernel/help/assembly-constraints___Distance_Constraint_dialog.png +0 -0
  11. package/dist-kernel/help/assembly-constraints___Fixed_Constraint_dialog.png +0 -0
  12. package/dist-kernel/help/assembly-constraints___Parallel_Constraint_dialog.png +0 -0
  13. package/dist-kernel/help/assembly-constraints___Touch_Align_Constraint_dialog.png +0 -0
  14. package/dist-kernel/help/assembly-constraints__angle-constraint.html +0 -248
  15. package/dist-kernel/help/assembly-constraints__coincident-constraint.html +0 -248
  16. package/dist-kernel/help/assembly-constraints__distance-constraint.html +0 -248
  17. package/dist-kernel/help/assembly-constraints__fixed-constraint.html +0 -248
  18. package/dist-kernel/help/assembly-constraints__parallel-constraint.html +0 -248
  19. package/dist-kernel/help/assembly-constraints__solver.html +0 -248
  20. package/dist-kernel/help/assembly-constraints__touch-align-constraint.html +0 -248
  21. package/dist-kernel/help/brep-api.html +0 -263
  22. package/dist-kernel/help/brep-kernel.html +0 -258
  23. package/dist-kernel/help/brep-model.html +0 -248
  24. package/dist-kernel/help/cylindrical-face-radius-embedding.html +0 -290
  25. package/dist-kernel/help/dialog-screenshots.html +0 -248
  26. package/dist-kernel/help/extruded-sketch-radius-embedding.html +0 -336
  27. package/dist-kernel/help/features__Assembly_Component_dialog.png +0 -0
  28. package/dist-kernel/help/features__Boolean_dialog.png +0 -0
  29. package/dist-kernel/help/features__Chamfer_dialog.png +0 -0
  30. package/dist-kernel/help/features__Datium_dialog.png +0 -0
  31. package/dist-kernel/help/features__Extrude_dialog.png +0 -0
  32. package/dist-kernel/help/features__Fillet_dialog.png +0 -0
  33. package/dist-kernel/help/features__Helix_dialog.png +0 -0
  34. package/dist-kernel/help/features__Hole_dialog.png +0 -0
  35. package/dist-kernel/help/features__Image_Heightmap_Solid_dialog.png +0 -0
  36. package/dist-kernel/help/features__Image_to_Face_dialog.png +0 -0
  37. package/dist-kernel/help/features__Import_3D_Model_dialog.png +0 -0
  38. package/dist-kernel/help/features__Loft_dialog.png +0 -0
  39. package/dist-kernel/help/features__Mirror_dialog.png +0 -0
  40. package/dist-kernel/help/features__Offset_Shell_dialog.png +0 -0
  41. package/dist-kernel/help/features__Overlap_Cleanup_dialog.png +0 -0
  42. package/dist-kernel/help/features__Pattern_Linear_dialog.png +0 -0
  43. package/dist-kernel/help/features__Pattern_Radial_dialog.png +0 -0
  44. package/dist-kernel/help/features__Pattern_dialog.png +0 -0
  45. package/dist-kernel/help/features__Plane_dialog.png +0 -0
  46. package/dist-kernel/help/features__Primitive_Cone_dialog.png +0 -0
  47. package/dist-kernel/help/features__Primitive_Cube_dialog.png +0 -0
  48. package/dist-kernel/help/features__Primitive_Cylinder_dialog.png +0 -0
  49. package/dist-kernel/help/features__Primitive_Pyramid_dialog.png +0 -0
  50. package/dist-kernel/help/features__Primitive_Sphere_dialog.png +0 -0
  51. package/dist-kernel/help/features__Primitive_Torus_dialog.png +0 -0
  52. package/dist-kernel/help/features__Remesh_dialog.png +0 -0
  53. package/dist-kernel/help/features__Revolve_dialog.png +0 -0
  54. package/dist-kernel/help/features__Sheet_Metal_Contour_Flange_dialog.png +0 -0
  55. package/dist-kernel/help/features__Sheet_Metal_Cutout_dialog.png +0 -0
  56. package/dist-kernel/help/features__Sheet_Metal_Flange_dialog.png +0 -0
  57. package/dist-kernel/help/features__Sheet_Metal_Tab_dialog.png +0 -0
  58. package/dist-kernel/help/features__Sketch_dialog.png +0 -0
  59. package/dist-kernel/help/features__Spline_dialog.png +0 -0
  60. package/dist-kernel/help/features__Sweep_dialog.png +0 -0
  61. package/dist-kernel/help/features__Transform_dialog.png +0 -0
  62. package/dist-kernel/help/features__Tube_dialog.png +0 -0
  63. package/dist-kernel/help/features__assembly-component.html +0 -248
  64. package/dist-kernel/help/features__boolean.html +0 -248
  65. package/dist-kernel/help/features__chamfer.html +0 -248
  66. package/dist-kernel/help/features__datium.html +0 -248
  67. package/dist-kernel/help/features__datum.html +0 -248
  68. package/dist-kernel/help/features__extrude.html +0 -248
  69. package/dist-kernel/help/features__fillet.html +0 -248
  70. package/dist-kernel/help/features__helix.html +0 -248
  71. package/dist-kernel/help/features__hole.html +0 -248
  72. package/dist-kernel/help/features__image-heightmap-solid.html +0 -248
  73. package/dist-kernel/help/features__image-to-face-2D_dialog.png +0 -0
  74. package/dist-kernel/help/features__image-to-face-3D_dialog.png +0 -0
  75. package/dist-kernel/help/features__image-to-face.html +0 -248
  76. package/dist-kernel/help/features__import-3d-model.html +0 -248
  77. package/dist-kernel/help/features__index.html +0 -248
  78. package/dist-kernel/help/features__loft.html +0 -248
  79. package/dist-kernel/help/features__mirror.html +0 -248
  80. package/dist-kernel/help/features__offset-shell.html +0 -248
  81. package/dist-kernel/help/features__pattern-linear.html +0 -248
  82. package/dist-kernel/help/features__pattern-radial.html +0 -248
  83. package/dist-kernel/help/features__pattern.html +0 -248
  84. package/dist-kernel/help/features__plane.html +0 -248
  85. package/dist-kernel/help/features__primitive-cone.html +0 -248
  86. package/dist-kernel/help/features__primitive-cube.html +0 -248
  87. package/dist-kernel/help/features__primitive-cylinder.html +0 -248
  88. package/dist-kernel/help/features__primitive-pyramid.html +0 -248
  89. package/dist-kernel/help/features__primitive-sphere.html +0 -248
  90. package/dist-kernel/help/features__primitive-torus.html +0 -248
  91. package/dist-kernel/help/features__remesh.html +0 -248
  92. package/dist-kernel/help/features__revolve.html +0 -248
  93. package/dist-kernel/help/features__sheet-metal-contour-flange.html +0 -248
  94. package/dist-kernel/help/features__sheet-metal-flange.html +0 -248
  95. package/dist-kernel/help/features__sheet-metal-tab.html +0 -248
  96. package/dist-kernel/help/features__sketch.html +0 -248
  97. package/dist-kernel/help/features__spline.html +0 -248
  98. package/dist-kernel/help/features__sweep.html +0 -248
  99. package/dist-kernel/help/features__transform.html +0 -248
  100. package/dist-kernel/help/features__tube.html +0 -248
  101. package/dist-kernel/help/file-formats.html +0 -248
  102. package/dist-kernel/help/getting-started.html +0 -248
  103. package/dist-kernel/help/highlights.html +0 -248
  104. package/dist-kernel/help/history-systems.html +0 -248
  105. package/dist-kernel/help/how-it-works.html +0 -248
  106. package/dist-kernel/help/index.html +0 -862
  107. package/dist-kernel/help/input-params-schema.html +0 -363
  108. package/dist-kernel/help/inspector-improvements.html +0 -248
  109. package/dist-kernel/help/inspector.html +0 -248
  110. package/dist-kernel/help/modes__modeling.html +0 -248
  111. package/dist-kernel/help/modes__pmi.html +0 -248
  112. package/dist-kernel/help/modes__sketch.html +0 -248
  113. package/dist-kernel/help/plugins.html +0 -248
  114. package/dist-kernel/help/pmi-annotations__Angle_Dimension_dialog.png +0 -0
  115. package/dist-kernel/help/pmi-annotations__Explode_Body_dialog.png +0 -0
  116. package/dist-kernel/help/pmi-annotations__Hole_Callout_dialog.png +0 -0
  117. package/dist-kernel/help/pmi-annotations__Leader_dialog.png +0 -0
  118. package/dist-kernel/help/pmi-annotations__Linear_Dimension_dialog.png +0 -0
  119. package/dist-kernel/help/pmi-annotations__Note_dialog.png +0 -0
  120. package/dist-kernel/help/pmi-annotations__Radial_Dimension_dialog.png +0 -0
  121. package/dist-kernel/help/pmi-annotations__angle-dimension.html +0 -248
  122. package/dist-kernel/help/pmi-annotations__explode-body.html +0 -248
  123. package/dist-kernel/help/pmi-annotations__hole-callout.html +0 -248
  124. package/dist-kernel/help/pmi-annotations__index.html +0 -248
  125. package/dist-kernel/help/pmi-annotations__leader.html +0 -248
  126. package/dist-kernel/help/pmi-annotations__linear-dimension.html +0 -248
  127. package/dist-kernel/help/pmi-annotations__note.html +0 -248
  128. package/dist-kernel/help/pmi-annotations__radial-dimension.html +0 -248
  129. package/dist-kernel/help/search-index.json +0 -464
  130. package/dist-kernel/help/simplified-radial-dimensions.html +0 -298
  131. package/dist-kernel/help/solid-methods.html +0 -359
  132. package/dist-kernel/help/table-of-contents.html +0 -330
  133. package/dist-kernel/help/ui-overview.html +0 -248
  134. package/dist-kernel/help/whats-new.html +0 -248
@@ -1,336 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width,initial-scale=1" />
6
- <title>Radius Metadata for Extruded Sketches - BREP</title>
7
- <style>
8
- :root{
9
- --bg:#0b0f14; --panel:#0f141b; --text:#d7dde6; --muted:#9aa7b2;
10
- --border:#1b2430; --accent:#5cc8ff; --chip:#121823;
11
- }
12
- *{box-sizing:border-box}
13
- html,body{margin:0;background:var(--bg);color:var(--text);font:14px/1.5 ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace}
14
- main{max-width:1100px;margin:0 auto;padding:28px}
15
- h1{margin:0 0 18px;font-size:22px;color:var(--accent);font-weight:700}
16
- .summary{color:var(--muted);margin-bottom:22px}
17
- .card{background:var(--panel);border:1px solid var(--border);border-radius:14px;padding:18px;margin:0 0 18px}
18
- .readme{padding:0}
19
- .readme .header{padding:16px 18px;border-bottom:1px solid var(--border)}
20
- .readme .content{padding:18px}
21
- .doc-card{padding:18px}
22
- .doc-nav{margin:0 0 18px;display:flex;gap:12px;flex-wrap:wrap;align-items:center;color:var(--muted)}
23
- .doc-nav-links{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
24
- .doc-nav a{color:var(--accent);font-weight:600}
25
- .doc-list{list-style:none;margin:18px 0;padding:0}
26
- .doc-list li{margin:6px 0}
27
- .doc-list a{color:var(--accent)}
28
- .nav-search{margin-left:auto;position:relative;display:flex;align-items:center;gap:8px;flex-wrap:wrap;justify-content:flex-end;min-width:240px;max-width:520px}
29
- .search-title{font-weight:700;font-size:14px;margin-bottom:4px}
30
- .search-hint{color:var(--muted);font-size:12px;margin:0}
31
- .search-input-row{display:flex;gap:8px;align-items:center;width:100%}
32
- .search-input{flex:1;border:1px solid var(--border);border-radius:10px;background:var(--chip);color:var(--text);padding:10px 12px}
33
- .search-input:focus{outline:1px solid var(--accent);box-shadow:0 0 0 3px rgba(92,200,255,0.15)}
34
- .search-clear{border:1px solid var(--border);background:var(--panel);color:var(--muted);border-radius:10px;padding:9px 12px;cursor:pointer;font-weight:600}
35
- .search-clear:hover{border-color:var(--accent);color:var(--accent)}
36
- .search-status{color:var(--muted);font-size:12px;margin-top:4px;width:100%;text-align:right}
37
- .search-results{position:absolute;top:100%;right:0;margin-top:10px;border:1px solid var(--border);border-radius:12px;background:var(--panel);max-height:360px;overflow:auto;min-width:320px;max-width:520px;box-shadow:0 12px 30px rgba(0,0,0,0.35);z-index:25}
38
- .search-results ul{list-style:none;margin:0;padding:0}
39
- .search-item{padding:10px 12px;border-bottom:1px solid var(--border)}
40
- .search-item:last-child{border-bottom:none}
41
- .search-item a{display:block;color:var(--accent);font-weight:600}
42
- .search-snippet{color:var(--muted);font-size:13px;margin-top:4px}
43
- .search-results mark{background:rgba(92,200,255,0.2);color:var(--text);border-radius:4px;padding:0 2px}
44
- .prose h1{font-size:24px;margin:0 0 12px}
45
- .prose h2{font-size:18px;margin:18px 0 8px}
46
- .prose h3{font-size:16px;margin:14px 0 6px}
47
- .prose p{margin:0 0 10px}
48
- .prose ul,.prose ol{margin:0 0 10px 18px}
49
- .prose li{margin:4px 0}
50
- .prose code{background:#0d1520;border:1px solid var(--border);padding:1px 5px;border-radius:6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,'Liberation Mono','Courier New',monospace;font-size:12px}
51
- .prose pre{background:#0d1520;border:1px solid var(--border);padding:12px;border-radius:12px;overflow:auto}
52
- .prose a{color:var(--accent)}
53
- .prose img{max-width:100%;height:auto;}
54
- .prose table{border-collapse:collapse;width:100%;margin:16px 0;background:var(--panel);border:1px solid var(--border);border-radius:8px;overflow:hidden}
55
- .prose th,.prose td{padding:8px 12px;text-align:left;border-bottom:1px solid var(--border)}
56
- .prose th{background:var(--chip);color:var(--text);font-weight:600;font-size:13px}
57
- .prose tr:last-child td{border-bottom:none}
58
- .prose tbody tr:hover{background:rgba(92,200,255,0.05)}
59
- .license{
60
- background:var(--panel);border:1px solid var(--border);border-radius:14px;
61
- padding:16px 16px 8px;margin:0 0 18px;
62
- }
63
- .license > h2{margin:0 0 10px;font-size:16px;font-weight:700}
64
- .pkg{
65
- border-top:1px solid var(--border);padding:10px 0;
66
- display:grid;grid-template-columns:1fr auto;gap:10px;align-items:center;
67
- }
68
- .pkg:first-of-type{border-top:none}
69
- .pkg .meta{display:flex;gap:10px;flex-wrap:wrap}
70
- .pkg .name{font-weight:600}
71
- .pkg .desc{color:var(--muted);margin-top:2px}
72
- a{color:var(--accent);text-decoration:none} a:hover{text-decoration:underline}
73
- .chip{background:var(--chip);border:1px solid var(--border);border-radius:999px;padding:2px 8px;font-size:12px;color:var(--muted)}
74
- .footer{margin-top:26px;color:var(--muted);font-size:12px}
75
- </style>
76
- </head>
77
- <body>
78
- <main>
79
- <nav class="doc-nav">
80
- <div class="doc-nav-links">
81
- <a href="index.html">Help Home</a><span>&middot;</span><a href="/help/table-of-contents.html">Table of Contents</a><span>&middot;</span><a href="https://github.com/mmiscool/BREP" target="_blank" rel="noopener noreferrer">GitHub</a>
82
- </div>
83
- <div class="nav-search">
84
- <div class="search-input-row">
85
- <input type="search" id="doc-search" class="search-input" placeholder="Search docs... Type at least 2 characters to search" autocomplete="off" spellcheck="false" />
86
- <button type="button" class="search-clear" id="doc-search-clear">Clear</button>
87
- </div>
88
- <div class="search-status" id="doc-search-status"></div>
89
- <div class="search-results" id="doc-search-results" hidden>
90
- <ul id="doc-search-list"></ul>
91
- </div>
92
- </div>
93
- </nav>
94
- <section class="card doc-card">
95
-
96
- <div class="prose">
97
- <h1>Radius Metadata for Extruded Sketches</h1><p>This document details how radius metadata is automatically embedded when extruding circular or arc-based sketch elements.</p><h2>How It Works</h2><h3>Automatic Detection</h3><p>When extruding a sketch face, the system automatically scans all edges in the sketch for circular geometry:</p><ol><li><strong>Circle Detection</strong>: Edges with <code>sketchGeomType: &#39;circle&#39;</code> and radius/center data</li><li><strong>Arc Detection</strong>: Edges with <code>sketchGeomType: &#39;arc&#39;</code> and radius/center data (any arc angle)</li><li><strong>Metadata Application</strong>: Cylindrical face metadata is applied to the resulting side walls</li></ol><h3>Edge Data Requirements</h3><p>For automatic detection, sketch edges need this <code>userData</code> structure:</p><h4>Circles</h4><p><pre><code>javascript
98
- edge.userData = {
99
- sketchGeomType: &#39;circle&#39;,
100
- circleCenter: [x, y, z], // Center point in local coordinates
101
- circleRadius: number // Radius value
102
- }</code></pre></p><h4>Arcs</h4><p><pre><code>javascript
103
- edge.userData = {
104
- sketchGeomType: &#39;arc&#39;,
105
- arcCenter: [x, y, z], // Center point in local coordinates
106
- arcRadius: number, // Radius value
107
- arcAngle: number // Arc angle in radians (any value)
108
- }</code></pre></p><h2>Generated Metadata</h2><h3>Cylindrical Face Metadata Structure</h3><p><pre><code>javascript
109
- {
110
- type: &#39;cylindrical&#39;,
111
- radius: 6.5, // Original radius from sketch
112
- height: 12.0, // Extrusion distance
113
- axis: [0, 1, 0], // Extrusion direction (normalized)
114
- center: [0, 6.0, 0] // Center point along cylinder axis
115
- }</code></pre></p><h3>Face Naming Convention</h3><p>Side walls are named using the pattern: <code>${featureName}:${edgeName}_SW</code></p><p>Examples:</p><ul><li><code>ExtrudedPart:CircleEdge1_SW</code></li><li><code>HousingExtrude:OuterCircle_SW</code></li><li><code>EXTRUDE_001:ArcEdge_SW</code></li></ul><h2>Coordinate Transformations</h2><h3>Local to World Conversion</h3><p>The system properly handles coordinate transformations:</p><ol><li><strong>Edge Transforms</strong>: If the edge has a <code>matrixWorld</code>, center points are transformed</li><li><strong>Extrusion Direction</strong>: Direction vectors are transformed through the edge matrix</li><li><strong>Final Positioning</strong>: Center points are positioned along the extrusion axis</li></ol><h3>Example Transformation</h3><p><pre><code>javascript
116
- // Original sketch data (local coordinates)
117
- circleCenter: [5, 0, 3]
118
- circleRadius: 2.5
119
-
120
- // After transformation and extrusion
121
- metadata: {
122
- center: [5, 6.0, 3], // Moved to mid-height of extrusion
123
- radius: 2.5, // Preserved original radius
124
- height: 12.0, // Total extrusion distance
125
- axis: [0, 1, 0] // Normalized extrusion direction
126
- }</code></pre></p><h2>Supported Sketch Configurations</h2><h3>Single Circle</h3><p><pre><code>javascript
127
- // Sketch with one circular edge
128
- edges: [
129
- {
130
- userData: {
131
- sketchGeomType: &#39;circle&#39;,
132
- circleCenter: [0, 0, 0],
133
- circleRadius: 5.0
134
- }
135
- }
136
- ]
137
- // Results in one cylindrical face with radius 5.0</code></pre></p><h3>Multiple Circles (Ring/Tube)</h3><p><pre><code>javascript
138
- // Sketch with outer and inner circles
139
- edges: [
140
- { userData: { sketchGeomType: &#39;circle&#39;, circleRadius: 10.0 } }, // Outer
141
- { userData: { sketchGeomType: &#39;circle&#39;, circleRadius: 6.0 } } // Inner
142
- ]
143
- // Results in two cylindrical faces with different radii</code></pre></p><h3>Arc Segments</h3><p><pre><code>javascript
144
- // Sketch with arc edges
145
- edges: [
146
- { userData: { sketchGeomType: &#39;arc&#39;, arcRadius: 8.0, arcAngle: Math.PI } }
147
- ]
148
- // Results in cylindrical face with radius 8.0 (angle doesn&#39;t matter for extrusion)</code></pre></p><h3>Mixed Geometry</h3><p><pre><code>javascript
149
- // Sketch with circles, arcs, and lines
150
- edges: [
151
- { userData: { sketchGeomType: &#39;circle&#39;, circleRadius: 4.0 } },
152
- { userData: { sketchGeomType: &#39;arc&#39;, arcRadius: 7.0 } },
153
- { userData: { sketchGeomType: &#39;line&#39; } } // Ignored - not circular
154
- ]
155
- // Results in two cylindrical faces (4.0 and 7.0 radius)</code></pre></p><h2>Integration with PMI Dimensions</h2><h3>Automatic Radius Detection</h3><p>When creating radial dimensions:</p><ol><li><strong>Face Selection</strong>: User selects any extruded cylindrical face</li><li><strong>Metadata Lookup</strong>: System finds embedded radius from original sketch</li><li><strong>Precise Measurement</strong>: Uses exact radius value instead of geometric approximation</li></ol><h3>Example Usage</h3><p><pre><code>javascript
156
- // Create radial dimension
157
- const radialDim = RadialDimension.create(pmiMode);
158
- radialDim.cylindricalFaceRef = &#39;ExtrudedCircle:OuterRing_SW&#39;;
159
-
160
- // System automatically uses radius: 7.5 from original sketch geometry
161
- // No need to specify center points or edge references</code></pre></p><h2>Error Handling</h2><h3>Missing or Invalid Data</h3><ul><li><strong>No sketch geometry</strong>: Falls back to geometric calculation from mesh</li><li><strong>Invalid radius values</strong>: Skips metadata embedding for that edge</li><li><strong>Transform errors</strong>: Uses identity transform as fallback</li><li><strong>Duplicate edges</strong>: Each edge gets its own metadata entry</li></ul><h3>Graceful Degradation</h3><p><pre><code>javascript
162
- try {
163
- // Attempt metadata embedding
164
- this.setFaceMetadata(faceName, metadata);
165
- } catch (err) {
166
- // Silently continue - dimension system will fall back to geometric calculation
167
- }</code></pre></p><h2>Performance Benefits</h2><h3>Computational Efficiency</h3><ul><li><strong>Direct Lookup</strong>: O(1) metadata retrieval vs O(n) mesh analysis</li><li><strong>No Approximation</strong>: Exact values from design intent</li><li><strong>Cached Results</strong>: Metadata persists through boolean operations</li></ul><h3>Memory Usage</h3><ul><li><strong>Minimal Overhead</strong>: Small metadata objects per cylindrical face</li><li><strong>Selective Storage</strong>: Only circular/arc edges generate metadata</li><li><strong>Automatic Cleanup</strong>: Metadata removed when faces are deleted</li></ul><h2>Future Enhancements</h2><h3>Additional Geometry Types</h3><ul><li><strong>Elliptical Arcs</strong>: Store major/minor axis information</li><li><strong>Spline Curves</strong>: Store control point and knot data</li><li><strong>Complex Profiles</strong>: Multi-radius and transitional curves</li></ul><h3>Enhanced Metadata</h3><p><pre><code>javascript
168
- // Future expanded metadata structure
169
- {
170
- type: &#39;cylindrical&#39;,
171
- radius: 5.0,
172
- height: 10.0,
173
- axis: [0, 1, 0],
174
- center: [0, 5.0, 0],
175
-
176
- // Enhanced information
177
- sourceSketch: &#39;Sketch001&#39;,
178
- sourceEdge: &#39;Circle1&#39;,
179
- tolerance: {
180
- radius: ±0.1,
181
- position: ±0.05
182
- },
183
- materialThickness: 2.0,
184
- surfaceFinish: &#39;machined&#39;
185
- }</code></pre></p><p>This system provides exact radius information for dimensioning while maintaining backward compatibility with existing geometric calculation methods.</p>
186
- </div>
187
- </section>
188
- </main>
189
- <script>
190
- (() => {
191
- const searchInput = document.getElementById("doc-search");
192
- const resultsBox = document.getElementById("doc-search-results");
193
- const resultsList = document.getElementById("doc-search-list");
194
- const statusEl = document.getElementById("doc-search-status");
195
- const clearBtn = document.getElementById("doc-search-clear");
196
- if (!searchInput || !resultsBox || !resultsList || !statusEl || !clearBtn) return;
197
- const indexUrl = "./search-index.json";
198
- let indexPromise = null;
199
- let cachedEntries = null;
200
-
201
- const escapeHtml = (text = "") =>
202
- text
203
- .replace(/&/g, "&amp;")
204
- .replace(/</g, "&lt;")
205
- .replace(/>/g, "&gt;");
206
-
207
- const escapeRegExp = (text = "") => text.replace(/[.*+?^{}()|[]\$]/g, "\$&");
208
-
209
- const highlight = (text, terms) => {
210
- if (!terms.length) return escapeHtml(text);
211
- const pattern = terms.map(escapeRegExp).join("|");
212
- const regex = new RegExp(`(${pattern})`, "gi");
213
- return escapeHtml(text).replace(regex, "<mark>$1</mark>");
214
- };
215
-
216
- const buildSnippet = (entry, terms) => {
217
- const source = entry.content || entry.summary || "";
218
- if (!source) return { plain: "", highlighted: "" };
219
- let hit = source.length;
220
- for (const term of terms) {
221
- const idx = entry.contentLower.indexOf(term);
222
- if (idx !== -1 && idx < hit) hit = idx;
223
- }
224
- if (!Number.isFinite(hit) || hit === source.length) hit = 0;
225
- const start = Math.max(0, hit - 60);
226
- const end = Math.min(source.length, hit + 140);
227
- const snippet = source.slice(start, end);
228
- return { plain: snippet, highlighted: highlight(snippet, terms) };
229
- };
230
-
231
- const updateStatus = (message) => {
232
- statusEl.textContent = message;
233
- };
234
-
235
- const loadIndex = async () => {
236
- if (cachedEntries) return cachedEntries;
237
- if (!indexPromise) {
238
- indexPromise = fetch(indexUrl, { cache: "no-store" })
239
- .then((res) => {
240
- if (!res.ok) throw new Error("Failed to load search index");
241
- return res.json();
242
- })
243
- .then((json) => {
244
- cachedEntries = Array.isArray(json)
245
- ? json.map((entry) => ({
246
- ...entry,
247
- contentLower: (entry.content || "").toLowerCase(),
248
- titleLower: (entry.title || "").toLowerCase(),
249
- }))
250
- : [];
251
- return cachedEntries;
252
- })
253
- .catch((err) => {
254
- console.error("Search index load failed", err);
255
- cachedEntries = [];
256
- throw err;
257
- });
258
- }
259
- return indexPromise;
260
- };
261
-
262
- const renderResults = (entries, terms) => {
263
- if (!terms.length) {
264
- resultsBox.hidden = true;
265
- return;
266
- }
267
- if (!entries.length) {
268
- resultsList.innerHTML = '<li class="search-item"><div class="search-snippet">No matches found.</div></li>';
269
- resultsBox.hidden = false;
270
- return;
271
- }
272
- const rendered = entries
273
- .slice(0, 30)
274
- .map((entry) => {
275
- const snippet = buildSnippet(entry, terms);
276
- const title = highlight(entry.title || entry.href, terms);
277
- const hasFragment = snippet.plain && snippet.plain.trim().length > 0;
278
- const fragment = hasFragment ? `#:~:text=${encodeURIComponent(snippet.plain.trim())}` : "";
279
- const hrefWithFragment = hasFragment
280
- ? (entry.href.includes("#") ? `${entry.href}&:~:text=${encodeURIComponent(snippet.plain.trim())}` : `${entry.href}${fragment}`)
281
- : entry.href;
282
- const snippetHtml = snippet.highlighted ? `<div class="search-snippet">${snippet.highlighted}</div>` : "";
283
- return `<li class="search-item"><a href="${hrefWithFragment}">${title}</a>${snippetHtml}</li>`;
284
- })
285
- .join("");
286
- resultsList.innerHTML = rendered;
287
- resultsBox.hidden = false;
288
- };
289
-
290
- const performSearch = async () => {
291
- const rawQuery = searchInput.value.trim();
292
- if (rawQuery.length < 2) {
293
- updateStatus("Type at least 2 characters to search.");
294
- resultsBox.hidden = true;
295
- return;
296
- }
297
- const terms = rawQuery.toLowerCase().split(/\s+/).filter(Boolean);
298
- updateStatus("Searching...");
299
- try {
300
- const entries = await loadIndex();
301
- const matches = entries.filter((entry) =>
302
- terms.every((term) => entry.contentLower.includes(term) || entry.titleLower.includes(term))
303
- );
304
- renderResults(matches, terms);
305
- updateStatus(matches.length ? `${matches.length} result${matches.length === 1 ? "" : "s"} for "${rawQuery}"` : "No matches found.");
306
- } catch (err) {
307
- updateStatus("Search unavailable (could not load index).");
308
- }
309
- };
310
-
311
- searchInput.addEventListener("input", performSearch);
312
-
313
- searchInput.addEventListener("focus", () => {
314
- if (!cachedEntries) {
315
- loadIndex().catch(() => updateStatus("Search unavailable (could not load index)."));
316
- }
317
- });
318
-
319
- clearBtn.addEventListener("click", () => {
320
- searchInput.value = "";
321
- resultsBox.hidden = true;
322
- updateStatus("Type at least 2 characters to search.");
323
- searchInput.focus();
324
- });
325
-
326
- document.addEventListener("keydown", (evt) => {
327
- if (evt.key === "Escape" && document.activeElement === searchInput) {
328
- searchInput.value = "";
329
- resultsBox.hidden = true;
330
- updateStatus("Type at least 2 characters to search.");
331
- }
332
- });
333
- })();
334
- </script>
335
- </body>
336
- </html>