@@ -283,7 +283,8 @@ describe("OCCT io unit tests", () => {
283283 expect ( pathsWithLayer . layer ) . toBe ( "TestLayer" ) ;
284284 expect ( pathsWithLayer . color ) . toBe ( "#FF0000" ) ;
285285
286- const dxfContent = io . dxfCreate ( { pathsParts : [ pathsWithLayer ] } ) ;
286+ const dxfDto = new Inputs . OCCT . DxfPathsPartsListDto ( [ pathsWithLayer ] ) ;
287+ const dxfContent = io . dxfCreate ( dxfDto ) ;
287288 expect ( dxfContent ) . toContain ( "TestLayer" ) ;
288289 expect ( dxfContent ) . toContain ( "LWPOLYLINE" ) ;
289290 } ) ;
@@ -594,4 +595,140 @@ describe("OCCT io unit tests", () => {
594595 arcWire . delete ( ) ;
595596 arc . delete ( ) ;
596597 } ) ;
598+
599+ it ( "should save cube shape as STL file" , ( ) => {
600+ const cube = solid . createCube ( { size : 10 , center : [ 0 , 0 , 0 ] } ) ;
601+ const dto = new Inputs . OCCT . SaveStlDto ( cube , "cube.stl" , 0.01 , false ) ;
602+ const stl = io . saveShapeStl ( dto ) ;
603+
604+ // STL file should contain proper header and facet definitions
605+ expect ( stl ) . toContain ( "solid" ) ;
606+ expect ( stl ) . toContain ( "facet normal" ) ;
607+ expect ( stl ) . toContain ( "outer loop" ) ;
608+ expect ( stl ) . toContain ( "vertex" ) ;
609+ expect ( stl ) . toContain ( "endloop" ) ;
610+ expect ( stl ) . toContain ( "endfacet" ) ;
611+ expect ( stl ) . toContain ( "endsolid" ) ;
612+
613+ cube . delete ( ) ;
614+ } ) ;
615+
616+ it ( "should save cylinder shape as STL file" , ( ) => {
617+ const cylinder = solid . createCylinder ( { radius : 5 , height : 10 , direction : [ 0 , 1 , 0 ] , center : [ 0 , 0 , 0 ] } ) ;
618+ const dto = new Inputs . OCCT . SaveStlDto ( cylinder , "cylinder.stl" , 0.1 , false ) ;
619+ const stl = io . saveShapeStl ( dto ) ;
620+
621+ expect ( stl ) . toContain ( "solid" ) ;
622+ expect ( stl ) . toContain ( "facet normal" ) ;
623+ expect ( stl ) . toContain ( "endsolid" ) ;
624+
625+ // Count the number of facets (triangles)
626+ const facetCount = ( stl . match ( / f a c e t n o r m a l / g) || [ ] ) . length ;
627+ expect ( facetCount ) . toBeGreaterThan ( 10 ) ;
628+
629+ cylinder . delete ( ) ;
630+ } ) ;
631+
632+ it ( "should save cone shape as STL file with Y to Z adjustment" , ( ) => {
633+ const cone = solid . createCone ( { radius1 : 10 , radius2 : 5 , height : 20 , angle : 360 , direction : [ 0 , 1 , 0 ] , center : [ 0 , 0 , 0 ] } ) ;
634+ const dto = new Inputs . OCCT . SaveStlDto ( cone , "cone.stl" , 0.1 , true ) ;
635+ const stl = io . saveShapeStl ( dto ) ;
636+
637+ expect ( stl ) . toContain ( "solid" ) ;
638+ expect ( stl ) . toContain ( "facet normal" ) ;
639+ expect ( stl ) . toContain ( "endsolid" ) ;
640+
641+ cone . delete ( ) ;
642+ } ) ;
643+
644+ it ( "should save sphere shape as STL file with higher precision" , ( ) => {
645+ const sphere = solid . createSphere ( { radius : 5 , center : [ 0 , 0 , 0 ] } ) ;
646+ const dtoLowRes = new Inputs . OCCT . SaveStlDto ( sphere , "sphere.stl" , 1 , false ) ;
647+ const stlLowRes = io . saveShapeStl ( dtoLowRes ) ;
648+
649+ const dtoHighRes = new Inputs . OCCT . SaveStlDto ( sphere , "sphere.stl" , 0.01 , false ) ;
650+ const stlHighRes = io . saveShapeStl ( dtoHighRes ) ;
651+
652+ // Higher precision should result in more facets
653+ const facetCountLow = ( stlLowRes . match ( / f a c e t n o r m a l / g) || [ ] ) . length ;
654+ const facetCountHigh = ( stlHighRes . match ( / f a c e t n o r m a l / g) || [ ] ) . length ;
655+
656+ expect ( facetCountHigh ) . toBeGreaterThan ( facetCountLow ) ;
657+
658+ sphere . delete ( ) ;
659+ } ) ;
660+
661+ it ( "should save box shape as STL file and contain valid vertex coordinates" , ( ) => {
662+ const box = solid . createBox ( { width : 4 , length : 6 , height : 8 , center : [ 0 , 0 , 0 ] } ) ;
663+ const dto = new Inputs . OCCT . SaveStlDto ( box , "box.stl" , 0.01 , false ) ;
664+ const stl = io . saveShapeStl ( dto ) ;
665+
666+ // A box should have 12 triangular facets (2 per face, 6 faces)
667+ const facetCount = ( stl . match ( / f a c e t n o r m a l / g) || [ ] ) . length ;
668+ expect ( facetCount ) . toBe ( 12 ) ;
669+
670+ // Check that vertex coordinates are present
671+ const vertexMatches = stl . match ( / v e r t e x \s + [ - \d . e + ] + \s + [ - \d . e + ] + \s + [ - \d . e + ] + / g) ;
672+ expect ( vertexMatches ) . not . toBeNull ( ) ;
673+ expect ( vertexMatches ) . toHaveLength ( 36 ) ; // 12 facets * 3 vertices each
674+
675+ box . delete ( ) ;
676+ } ) ;
677+
678+ it ( "should load shape from STEP file with .stp extension" , ( ) => {
679+ const cube = solid . createCube ( { size : 5 , center : [ 0 , 0 , 0 ] } ) ;
680+ const stepText = io . saveShapeSTEP ( { shape : cube , adjustYtoZ : false , fileName : "cube.stp" } ) ;
681+ const loaded = io . loadSTEPorIGES ( { filetext : stepText , fileName : "cube.stp" , adjustZtoY : false } ) ;
682+
683+ const volumeOriginal = solid . getSolidVolume ( { shape : cube } ) ;
684+ const volumeLoaded = solid . getSolidVolume ( { shape : loaded } ) ;
685+ expect ( volumeOriginal ) . toBeCloseTo ( volumeLoaded ) ;
686+
687+ cube . delete ( ) ;
688+ loaded . delete ( ) ;
689+ } ) ;
690+
691+ it ( "should load shape from STEP file with adjustZtoY enabled" , ( ) => {
692+ const cylinder = solid . createCylinder ( { radius : 3 , height : 10 , direction : [ 0 , 1 , 0 ] , center : [ 0 , 0 , 0 ] } ) ;
693+ const stepText = io . saveShapeSTEP ( { shape : cylinder , adjustYtoZ : true , fileName : "cylinder.step" } ) ;
694+ const loaded = io . loadSTEPorIGES ( { filetext : stepText , fileName : "cylinder.step" , adjustZtoY : true } ) ;
695+
696+ const volumeOriginal = solid . getSolidVolume ( { shape : cylinder } ) ;
697+ const volumeLoaded = solid . getSolidVolume ( { shape : loaded } ) ;
698+ expect ( volumeOriginal ) . toBeCloseTo ( volumeLoaded ) ;
699+
700+ cylinder . delete ( ) ;
701+ loaded . delete ( ) ;
702+ } ) ;
703+
704+ it ( "should load sphere shape from STEP file and preserve volume" , ( ) => {
705+ const sphere = solid . createSphere ( { radius : 7 , center : [ 0 , 0 , 0 ] } ) ;
706+ const stepText = io . saveShapeSTEP ( { shape : sphere , adjustYtoZ : false , fileName : "sphere.step" } ) ;
707+ const loaded = io . loadSTEPorIGES ( { filetext : stepText , fileName : "sphere.step" , adjustZtoY : false } ) ;
708+
709+ const volumeOriginal = solid . getSolidVolume ( { shape : sphere } ) ;
710+ const volumeLoaded = solid . getSolidVolume ( { shape : loaded } ) ;
711+ expect ( volumeOriginal ) . toBeCloseTo ( volumeLoaded ) ;
712+
713+ sphere . delete ( ) ;
714+ loaded . delete ( ) ;
715+ } ) ;
716+
717+ it ( "should load box shape from STEP file and preserve volume" , ( ) => {
718+ const box = solid . createBox ( { width : 4 , length : 6 , height : 8 , center : [ 0 , 0 , 0 ] } ) ;
719+ const stepText = io . saveShapeSTEP ( { shape : box , adjustYtoZ : false , fileName : "box.step" } ) ;
720+ const loaded = io . loadSTEPorIGES ( { filetext : stepText , fileName : "box.step" , adjustZtoY : false } ) ;
721+
722+ const volumeOriginal = solid . getSolidVolume ( { shape : box } ) ;
723+ const volumeLoaded = solid . getSolidVolume ( { shape : loaded } ) ;
724+ expect ( volumeOriginal ) . toBeCloseTo ( volumeLoaded ) ;
725+
726+ box . delete ( ) ;
727+ loaded . delete ( ) ;
728+ } ) ;
729+
730+ it ( "should return undefined for unsupported file extension" , ( ) => {
731+ const result = io . loadSTEPorIGES ( { filetext : "some content" , fileName : "file.obj" , adjustZtoY : false } ) ;
732+ expect ( result ) . toBeUndefined ( ) ;
733+ } ) ;
597734} ) ;
0 commit comments