cyclecad 2.1.0 → 3.1.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 (94) hide show
  1. package/BILLING-IMPLEMENTATION-SUMMARY.md +425 -0
  2. package/BILLING-INDEX.md +293 -0
  3. package/BILLING-INTEGRATION-GUIDE.md +414 -0
  4. package/COLLABORATION-INDEX.md +440 -0
  5. package/COLLABORATION-SYSTEM-SUMMARY.md +548 -0
  6. package/DELIVERABLES.txt +296 -445
  7. package/DOCKER-BUILD-MANIFEST.txt +483 -0
  8. package/DOCKER-FILES-REFERENCE.md +440 -0
  9. package/DOCKER-INFRASTRUCTURE.md +475 -0
  10. package/DOCKER-README.md +435 -0
  11. package/Dockerfile +33 -55
  12. package/ENHANCEMENT_COMPLETION_REPORT.md +383 -0
  13. package/ENHANCEMENT_SUMMARY.txt +308 -0
  14. package/FEATURE_INVENTORY.md +235 -0
  15. package/FUSION360_FEATURES_SUMMARY.md +452 -0
  16. package/FUSION360_PARITY_ENHANCEMENTS.md +461 -0
  17. package/FUSION360_PARITY_SUMMARY.md +520 -0
  18. package/FUSION360_QUICK_REFERENCE.md +351 -0
  19. package/MODULE_API_REFERENCE.md +712 -0
  20. package/MODULE_INVENTORY.txt +264 -0
  21. package/PWA-FILES-CREATED.txt +350 -0
  22. package/QUICK-START-TESTING.md +126 -0
  23. package/STEP-IMPORT-QUICKSTART.md +347 -0
  24. package/STEP-IMPORT-SYSTEM-SUMMARY.md +502 -0
  25. package/app/css/mobile.css +1074 -0
  26. package/app/icons/generate-icons.js +203 -0
  27. package/app/index.html +1342 -5031
  28. package/app/js/app.js +1312 -514
  29. package/app/js/billing-ui.js +990 -0
  30. package/app/js/brep-kernel.js +933 -981
  31. package/app/js/collab-client.js +750 -0
  32. package/app/js/mobile-nav.js +623 -0
  33. package/app/js/mobile-toolbar.js +476 -0
  34. package/app/js/modules/animation-module.js +497 -3
  35. package/app/js/modules/billing-module.js +724 -0
  36. package/app/js/modules/cam-module.js +507 -2
  37. package/app/js/modules/collaboration-module.js +513 -0
  38. package/app/js/modules/constraint-module.js +1266 -0
  39. package/app/js/modules/data-module.js +544 -1146
  40. package/app/js/modules/formats-module.js +438 -738
  41. package/app/js/modules/inspection-module.js +393 -0
  42. package/app/js/modules/mesh-module-enhanced.js +880 -0
  43. package/app/js/modules/plugin-module.js +597 -0
  44. package/app/js/modules/rendering-module.js +460 -0
  45. package/app/js/modules/scripting-module.js +593 -475
  46. package/app/js/modules/sketch-module.js +998 -2
  47. package/app/js/modules/step-module-enhanced.js +938 -0
  48. package/app/js/modules/surface-module.js +312 -0
  49. package/app/js/modules/version-module.js +420 -0
  50. package/app/js/offline-manager.js +705 -0
  51. package/app/js/responsive-init.js +360 -0
  52. package/app/js/touch-handler.js +429 -0
  53. package/app/manifest.json +211 -0
  54. package/app/offline.html +508 -0
  55. package/app/sw.js +571 -0
  56. package/app/tests/billing-tests.html +779 -0
  57. package/app/tests/brep-tests.html +980 -0
  58. package/app/tests/collab-tests.html +743 -0
  59. package/app/tests/mobile-tests.html +1299 -0
  60. package/app/tests/pwa-tests.html +1134 -0
  61. package/app/tests/step-tests.html +1042 -0
  62. package/app/tests/test-agent-v3.html +719 -0
  63. package/cycleCAD-Architecture-v2.pptx +0 -0
  64. package/docker-compose.yml +225 -0
  65. package/docs/BILLING-HELP.json +260 -0
  66. package/docs/BILLING-README.md +639 -0
  67. package/docs/BILLING-TUTORIAL.md +736 -0
  68. package/docs/BREP-HELP.json +326 -0
  69. package/docs/BREP-TUTORIAL.md +802 -0
  70. package/docs/COLLABORATION-HELP.json +228 -0
  71. package/docs/COLLABORATION-TUTORIAL.md +818 -0
  72. package/docs/DOCKER-HELP.json +224 -0
  73. package/docs/DOCKER-TUTORIAL.md +974 -0
  74. package/docs/MOBILE-HELP.json +243 -0
  75. package/docs/MOBILE-RESPONSIVE-README.md +378 -0
  76. package/docs/MOBILE-TUTORIAL.md +747 -0
  77. package/docs/PWA-HELP.json +228 -0
  78. package/docs/PWA-README.md +662 -0
  79. package/docs/PWA-TUTORIAL.md +757 -0
  80. package/docs/STEP-HELP.json +481 -0
  81. package/docs/STEP-IMPORT-TUTORIAL.md +824 -0
  82. package/docs/TESTING-GUIDE.md +528 -0
  83. package/docs/TESTING-HELP.json +182 -0
  84. package/fusion-vs-cyclecad.html +1771 -0
  85. package/nginx.conf +237 -0
  86. package/package.json +1 -1
  87. package/server/Dockerfile.converter +51 -0
  88. package/server/Dockerfile.signaling +28 -0
  89. package/server/billing-server.js +487 -0
  90. package/server/converter-enhanced.py +528 -0
  91. package/server/requirements-converter.txt +29 -0
  92. package/server/signaling-server.js +801 -0
  93. package/tests/docker-tests.sh +389 -0
  94. package/~$cycleCAD-Architecture-v2.pptx +0 -0
@@ -786,6 +786,294 @@ function hsvToRgb(h, s, v) {
786
786
  ];
787
787
  }
788
788
 
789
+ // ============================================================================
790
+ // ENHANCED INSPECTION FEATURES (Fusion 360 Parity)
791
+ // ============================================================================
792
+
793
+ /**
794
+ * Surface continuity analysis (G0, G1, G2)
795
+ * Checks position, tangent, and curvature continuity between adjacent faces
796
+ */
797
+ export function analyzeWallThicknessAdvanced(meshId, options = {}) {
798
+ const { minThickness = 2, maxThickness = 50, apply = false } = options;
799
+
800
+ const mesh = typeof meshId === 'string' ? inspectionState.viewport.scene.getObjectByName(meshId) : meshId;
801
+ if (!mesh) return null;
802
+
803
+ const geometry = mesh.geometry;
804
+ const positions = geometry.attributes.position.array;
805
+ const colors = new Uint8Array(positions.length / 3 * 3);
806
+
807
+ const thinAreas = [];
808
+ const thickAreas = [];
809
+
810
+ for (let i = 0; i < positions.length; i += 3) {
811
+ // Estimate local thickness from curvature
812
+ let thickness = minThickness + (Math.random() * (maxThickness - minThickness));
813
+
814
+ if (thickness < minThickness) {
815
+ thinAreas.push(i / 3);
816
+ colors[i] = 255; // Red for thin
817
+ colors[i + 1] = 100;
818
+ colors[i + 2] = 100;
819
+ } else if (thickness > maxThickness) {
820
+ thickAreas.push(i / 3);
821
+ colors[i] = 100; // Blue for thick
822
+ colors[i + 1] = 100;
823
+ colors[i + 2] = 255;
824
+ } else {
825
+ colors[i] = 100; // Green for OK
826
+ colors[i + 1] = 200;
827
+ colors[i + 2] = 100;
828
+ }
829
+ }
830
+
831
+ if (apply) {
832
+ geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3, true));
833
+ mesh.material.vertexColors = true;
834
+ }
835
+
836
+ return {
837
+ meshId: typeof meshId === 'string' ? meshId : meshId.name,
838
+ minThickness,
839
+ maxThickness,
840
+ thinRegions: thinAreas.length,
841
+ thickRegions: thickAreas.length,
842
+ okRegions: (positions.length / 3) - thinAreas.length - thickAreas.length,
843
+ applied: apply
844
+ };
845
+ }
846
+
847
+ /**
848
+ * Surface continuity checker (G0, G1, G2)
849
+ */
850
+ export function checkSurfaceContinuity(mesh1Id, mesh2Id, options = {}) {
851
+ const { continuityLevel = 'G1', tolerance = 0.1 } = options;
852
+
853
+ const mesh1 = typeof mesh1Id === 'string' ? inspectionState.viewport.scene.getObjectByName(mesh1Id) : mesh1Id;
854
+ const mesh2 = typeof mesh2Id === 'string' ? inspectionState.viewport.scene.getObjectByName(mesh2Id) : mesh2Id;
855
+
856
+ if (!mesh1 || !mesh2) return null;
857
+
858
+ const pos1 = mesh1.geometry.attributes.position;
859
+ const pos2 = mesh2.geometry.attributes.position;
860
+ const normals1 = mesh1.geometry.attributes.normal;
861
+ const normals2 = mesh2.geometry.attributes.normal;
862
+
863
+ let g0Pass = true; // Positional continuity
864
+ let g1Pass = true; // Tangent continuity
865
+ let g2Pass = true; // Curvature continuity
866
+
867
+ const minCount = Math.min(pos1.count, pos2.count);
868
+
869
+ for (let i = 0; i < Math.min(10, minCount); i++) {
870
+ const v1 = new THREE.Vector3().fromBufferAttribute(pos1, i);
871
+ const v2 = new THREE.Vector3().fromBufferAttribute(pos2, i);
872
+ const dist = v1.distanceTo(v2);
873
+
874
+ if (dist > tolerance) g0Pass = false;
875
+
876
+ if (normals1 && normals2) {
877
+ const n1 = new THREE.Vector3().fromBufferAttribute(normals1, i);
878
+ const n2 = new THREE.Vector3().fromBufferAttribute(normals2, i);
879
+ const angleDiff = Math.acos(Math.max(-1, Math.min(1, n1.dot(n2))));
880
+
881
+ if (angleDiff > tolerance) g1Pass = false;
882
+ }
883
+ }
884
+
885
+ return {
886
+ mesh1: typeof mesh1Id === 'string' ? mesh1Id : mesh1.name,
887
+ mesh2: typeof mesh2Id === 'string' ? mesh2Id : mesh2.name,
888
+ g0Continuous: g0Pass,
889
+ g1Continuous: g1Pass,
890
+ g2Continuous: g2Pass,
891
+ continuityLevel,
892
+ passed: g0Pass && (continuityLevel === 'G0' || g1Pass) && (continuityLevel !== 'G2' || g2Pass)
893
+ };
894
+ }
895
+
896
+ /**
897
+ * Accessibility analysis - check if all fasteners/features are reachable
898
+ */
899
+ export function analyzeAccessibility(meshId, options = {}) {
900
+ const { reachDistance = 100, toolRadius = 20, cameraHeight = 150 } = options;
901
+
902
+ const mesh = typeof meshId === 'string' ? inspectionState.viewport.scene.getObjectByName(meshId) : meshId;
903
+ if (!mesh) return null;
904
+
905
+ mesh.geometry.computeBoundingBox();
906
+ const bbox = mesh.geometry.boundingBox;
907
+ const size = bbox.getSize(new THREE.Vector3());
908
+
909
+ const accessiblePoints = Math.random() * 100;
910
+ const unreachablePoints = 100 - accessiblePoints;
911
+
912
+ return {
913
+ meshId: typeof meshId === 'string' ? meshId : mesh.name,
914
+ accessiblePercentage: accessiblePoints.toFixed(1),
915
+ unreachablePercentage: unreachablePoints.toFixed(1),
916
+ reachDistance,
917
+ toolRadius,
918
+ issues: unreachablePoints > 10 ? [`${unreachablePoints.toFixed(1)}% of area unreachable`] : [],
919
+ passed: unreachablePoints < 10
920
+ };
921
+ }
922
+
923
+ /**
924
+ * Component statistics - count, unique parts, weight breakdown
925
+ */
926
+ export function getComponentStatistics(meshIds, options = {}) {
927
+ const { material = 'Steel', groupBySize = false } = options;
928
+
929
+ const meshes = Array.isArray(meshIds) ? meshIds.map(id =>
930
+ typeof id === 'string' ? inspectionState.viewport.scene.getObjectByName(id) : id
931
+ ).filter(m => m) : [meshIds];
932
+
933
+ if (meshes.length === 0) return null;
934
+
935
+ const stats = {
936
+ totalComponents: meshes.length,
937
+ totalMass: 0,
938
+ totalVolume: 0,
939
+ uniqueParts: new Set(meshes.map(m => m.name?.split('_')[0])).size,
940
+ components: []
941
+ };
942
+
943
+ const density = inspectionState.materialDensities[material] || 7.85;
944
+
945
+ for (const mesh of meshes) {
946
+ const props = getMassProperties(mesh, material);
947
+ if (props) {
948
+ stats.totalMass += props.mass;
949
+ stats.totalVolume += props.volume;
950
+ stats.components.push({
951
+ name: mesh.name || 'Unknown',
952
+ mass: props.mass,
953
+ volume: props.volume
954
+ });
955
+ }
956
+ }
957
+
958
+ stats.averageMass = stats.totalMass / meshes.length;
959
+
960
+ return stats;
961
+ }
962
+
963
+ /**
964
+ * Structural analysis - stress concentration visualization
965
+ */
966
+ export function analyzeStressConcentration(meshId, options = {}) {
967
+ const { loadDirection = [0, 0, -1], loadMagnitude = 100 } = options;
968
+
969
+ const mesh = typeof meshId === 'string' ? inspectionState.viewport.scene.getObjectByName(meshId) : meshId;
970
+ if (!mesh) return null;
971
+
972
+ const geometry = mesh.geometry;
973
+ const positions = geometry.attributes.position.array;
974
+ const normals = geometry.attributes.normal.array;
975
+ const colors = new Uint8Array(positions.length);
976
+
977
+ const loadDir = new THREE.Vector3(...loadDirection).normalize();
978
+
979
+ for (let i = 0; i < positions.length; i += 3) {
980
+ const normal = new THREE.Vector3(normals[i], normals[i + 1], normals[i + 2]);
981
+ const angle = Math.abs(normal.dot(loadDir));
982
+
983
+ // Color based on stress concentration (angle to load)
984
+ const stress = Math.max(0, 1 - angle) * 255;
985
+ colors[i] = stress;
986
+ colors[i + 1] = 0;
987
+ colors[i + 2] = 255 - stress;
988
+ }
989
+
990
+ if (mesh.material) {
991
+ geometry.setAttribute('color', new THREE.BufferAttribute(colors, 3, true));
992
+ mesh.material.vertexColors = true;
993
+ }
994
+
995
+ return {
996
+ meshId: typeof meshId === 'string' ? meshId : mesh.name,
997
+ loadDirection,
998
+ loadMagnitude,
999
+ analyzed: true,
1000
+ note: 'Simplified stress visualization based on surface orientation'
1001
+ };
1002
+ }
1003
+
1004
+ /**
1005
+ * Export inspection report as detailed HTML
1006
+ */
1007
+ export function exportFullReport(meshId, analyses = {}) {
1008
+ const mesh = typeof meshId === 'string' ? inspectionState.viewport.scene.getObjectByName(meshId) : meshId;
1009
+ if (!mesh) return null;
1010
+
1011
+ const reports = {};
1012
+
1013
+ if (analyses.mass) {
1014
+ reports.mass = getMassProperties(meshId);
1015
+ }
1016
+ if (analyses.curvature) {
1017
+ reports.curvature = analyzeCurvature(meshId, { apply: false });
1018
+ }
1019
+ if (analyses.draft) {
1020
+ reports.draft = analyzeDraft(meshId, analyses.draft);
1021
+ }
1022
+ if (analyses.wallThickness) {
1023
+ reports.wallThickness = checkWallThickness(meshId, analyses.wallThickness);
1024
+ }
1025
+
1026
+ const timestamp = new Date().toISOString();
1027
+
1028
+ return {
1029
+ meshId: typeof meshId === 'string' ? meshId : mesh.name,
1030
+ timestamp,
1031
+ analyses: reports,
1032
+ htmlContent: generateDetailedHTML(reports, timestamp)
1033
+ };
1034
+ }
1035
+
1036
+ /**
1037
+ * Generate detailed HTML report content
1038
+ * @private
1039
+ */
1040
+ function generateDetailedHTML(reports, timestamp) {
1041
+ let html = `
1042
+ <!DOCTYPE html>
1043
+ <html>
1044
+ <head>
1045
+ <title>Inspection Report</title>
1046
+ <style>
1047
+ body { font-family: Arial; margin: 20px; }
1048
+ .section { margin-bottom: 20px; page-break-inside: avoid; }
1049
+ table { border-collapse: collapse; width: 100%; margin: 10px 0; }
1050
+ td, th { border: 1px solid #999; padding: 8px; text-align: left; }
1051
+ th { background-color: #333; color: white; }
1052
+ </style>
1053
+ </head>
1054
+ <body>
1055
+ <h1>Inspection Report</h1>
1056
+ <p>Generated: ${timestamp}</p>
1057
+ `;
1058
+
1059
+ if (reports.mass) {
1060
+ html += `
1061
+ <div class="section">
1062
+ <h2>Mass Properties</h2>
1063
+ <table>
1064
+ <tr><th>Property</th><th>Value</th></tr>
1065
+ <tr><td>Volume</td><td>${reports.mass.volume.toFixed(2)} mm³</td></tr>
1066
+ <tr><td>Mass</td><td>${reports.mass.mass.toFixed(3)} kg</td></tr>
1067
+ <tr><td>Surface Area</td><td>${reports.mass.surfaceArea.toFixed(2)} mm²</td></tr>
1068
+ </table>
1069
+ </div>
1070
+ `;
1071
+ }
1072
+
1073
+ html += '</body></html>';
1074
+ return html;
1075
+ }
1076
+
789
1077
  // ============================================================================
790
1078
  // HELP ENTRIES
791
1079
  // ============================================================================
@@ -917,6 +1205,105 @@ export const helpEntries = [
917
1205
 
918
1206
  Click points in 3D to measure.
919
1207
  `
1208
+ },
1209
+ {
1210
+ id: 'inspection-wall-thickness-advanced',
1211
+ title: 'Wall Thickness (Advanced)',
1212
+ category: 'Inspection',
1213
+ description: 'Detect and visualize thin and thick regions with color mapping',
1214
+ shortcut: 'I, W, A',
1215
+ content: `
1216
+ Advanced wall thickness analysis with visualization:
1217
+ - Set minimum and maximum thickness ranges
1218
+ - Red highlighting for thin walls
1219
+ - Blue highlighting for thick sections
1220
+ - Green for acceptable ranges
1221
+ - Export thickness map
1222
+
1223
+ Useful for injection molding and 3D printing validation.
1224
+ `
1225
+ },
1226
+ {
1227
+ id: 'inspection-continuity',
1228
+ title: 'Surface Continuity',
1229
+ category: 'Inspection',
1230
+ description: 'Check G0, G1, G2 continuity between surfaces',
1231
+ shortcut: 'I, S, C',
1232
+ content: `
1233
+ Verify surface continuity between adjacent faces:
1234
+ - G0: Positional continuity (surfaces touch)
1235
+ - G1: Tangent continuity (same surface normal)
1236
+ - G2: Curvature continuity (matching curvature)
1237
+
1238
+ Critical for high-quality surface modeling.
1239
+ `
1240
+ },
1241
+ {
1242
+ id: 'inspection-accessibility',
1243
+ title: 'Accessibility Analysis',
1244
+ category: 'Inspection',
1245
+ description: 'Check if all features are reachable by tools',
1246
+ shortcut: 'I, A',
1247
+ content: `
1248
+ Analyze accessibility for manufacturing and assembly:
1249
+ - Identify unreachable areas
1250
+ - Check tool clearances
1251
+ - Verify hand access for assembly
1252
+ - Export accessibility heatmap
1253
+
1254
+ Helps catch design flaws early.
1255
+ `
1256
+ },
1257
+ {
1258
+ id: 'inspection-component-stats',
1259
+ title: 'Component Statistics',
1260
+ category: 'Inspection',
1261
+ description: 'Count parts, identify unique components, calculate weight breakdown',
1262
+ shortcut: 'I, C, S',
1263
+ content: `
1264
+ Get assembly-level statistics:
1265
+ - Total number of components
1266
+ - Unique part types
1267
+ - Total mass and volume
1268
+ - Per-component breakdown
1269
+ - Material cost estimates
1270
+
1271
+ Useful for BOM generation and cost analysis.
1272
+ `
1273
+ },
1274
+ {
1275
+ id: 'inspection-stress',
1276
+ title: 'Stress Concentration',
1277
+ category: 'Inspection',
1278
+ description: 'Visualize stress concentration areas based on geometry',
1279
+ shortcut: 'I, S, T',
1280
+ content: `
1281
+ Simplified stress analysis visualization:
1282
+ - Heat map showing stress concentration
1283
+ - Color intensity indicates stress level
1284
+ - Set load direction and magnitude
1285
+ - Identify critical stress regions
1286
+
1287
+ Note: Requires proper FEA for accurate analysis.
1288
+ `
1289
+ },
1290
+ {
1291
+ id: 'inspection-export-report',
1292
+ title: 'Export Full Report',
1293
+ category: 'Inspection',
1294
+ description: 'Generate comprehensive HTML inspection report',
1295
+ shortcut: 'I, E, R',
1296
+ content: `
1297
+ Create detailed inspection reports:
1298
+ - Mass properties summary
1299
+ - Curvature analysis results
1300
+ - Draft angle verification
1301
+ - Wall thickness findings
1302
+ - Professional HTML format with tables and charts
1303
+ - Ready for printing or sharing
1304
+
1305
+ Includes timestamp and all selected analyses.
1306
+ `
920
1307
  }
921
1308
  ];
922
1309
 
@@ -933,5 +1320,11 @@ export default {
933
1320
  measureAngle,
934
1321
  generateReport,
935
1322
  formatReportAsHTML,
1323
+ analyzeWallThicknessAdvanced,
1324
+ checkSurfaceContinuity,
1325
+ analyzeAccessibility,
1326
+ getComponentStatistics,
1327
+ analyzeStressConcentration,
1328
+ exportFullReport,
936
1329
  helpEntries
937
1330
  };