@@ -914,6 +914,259 @@ describe("OCCT operations unit tests", () => {
914914 res . delete ( ) ;
915915 } ) ;
916916
917+ describe ( "Bounding box operations" , ( ) => {
918+ it ( "should get bounding box properties of a box shape" , ( ) => {
919+ const box = occHelper . entitiesService . bRepPrimAPIMakeBox ( 2 , 3 , 4 , [ 0 , 0 , 0 ] ) ;
920+ const bbox = operations . boundingBoxOfShape ( { shape : box } ) ;
921+
922+ expect ( bbox . min [ 0 ] ) . toBeCloseTo ( - 1 , 5 ) ;
923+ expect ( bbox . min [ 1 ] ) . toBeCloseTo ( - 2 , 5 ) ;
924+ expect ( bbox . min [ 2 ] ) . toBeCloseTo ( - 1.5 , 5 ) ;
925+ expect ( bbox . max [ 0 ] ) . toBeCloseTo ( 1 , 5 ) ;
926+ expect ( bbox . max [ 1 ] ) . toBeCloseTo ( 2 , 5 ) ;
927+ expect ( bbox . max [ 2 ] ) . toBeCloseTo ( 1.5 , 5 ) ;
928+ expect ( bbox . center [ 0 ] ) . toBeCloseTo ( 0 , 5 ) ;
929+ expect ( bbox . center [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
930+ expect ( bbox . center [ 2 ] ) . toBeCloseTo ( 0 , 5 ) ;
931+ expect ( bbox . size [ 0 ] ) . toBeCloseTo ( 2 , 5 ) ;
932+ expect ( bbox . size [ 1 ] ) . toBeCloseTo ( 4 , 5 ) ;
933+ expect ( bbox . size [ 2 ] ) . toBeCloseTo ( 3 , 5 ) ;
934+
935+ box . delete ( ) ;
936+ } ) ;
937+
938+ it ( "should get bounding box min point of a sphere" , ( ) => {
939+ const sphere = occHelper . entitiesService . bRepPrimAPIMakeSphere ( [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , 2 ) ;
940+ const min = operations . boundingBoxMinOfShape ( { shape : sphere } ) ;
941+
942+ expect ( min [ 0 ] ) . toBeCloseTo ( - 2 , 5 ) ;
943+ expect ( min [ 1 ] ) . toBeCloseTo ( - 2 , 5 ) ;
944+ expect ( min [ 2 ] ) . toBeCloseTo ( - 2 , 5 ) ;
945+
946+ sphere . delete ( ) ;
947+ } ) ;
948+
949+ it ( "should get bounding box max point of a sphere" , ( ) => {
950+ const sphere = occHelper . entitiesService . bRepPrimAPIMakeSphere ( [ 5 , 10 , - 3 ] , [ 0 , 1 , 0 ] , 1.5 ) ;
951+ const max = operations . boundingBoxMaxOfShape ( { shape : sphere } ) ;
952+
953+ expect ( max [ 0 ] ) . toBeCloseTo ( 6.5 , 5 ) ;
954+ expect ( max [ 1 ] ) . toBeCloseTo ( 11.5 , 5 ) ;
955+ expect ( max [ 2 ] ) . toBeCloseTo ( - 1.5 , 5 ) ;
956+
957+ sphere . delete ( ) ;
958+ } ) ;
959+
960+ it ( "should get bounding box center of a cylinder" , ( ) => {
961+ const cyl = occHelper . entitiesService . bRepPrimAPIMakeCylinder ( [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , 2 , 10 , 360 ) ;
962+ const center = operations . boundingBoxCenterOfShape ( { shape : cyl } ) ;
963+
964+ expect ( center [ 0 ] ) . toBeCloseTo ( 0 , 5 ) ;
965+ expect ( center [ 1 ] ) . toBeCloseTo ( 5 , 5 ) ;
966+ expect ( center [ 2 ] ) . toBeCloseTo ( 0 , 5 ) ;
967+
968+ cyl . delete ( ) ;
969+ } ) ;
970+
971+ it ( "should get bounding box size of a cube" , ( ) => {
972+ const box = occHelper . entitiesService . bRepPrimAPIMakeBox ( 5 , 5 , 5 , [ 0 , 0 , 0 ] ) ;
973+ const size = operations . boundingBoxSizeOfShape ( { shape : box } ) ;
974+
975+ expect ( size [ 0 ] ) . toBeCloseTo ( 5 , 5 ) ;
976+ expect ( size [ 1 ] ) . toBeCloseTo ( 5 , 5 ) ;
977+ expect ( size [ 2 ] ) . toBeCloseTo ( 5 , 5 ) ;
978+
979+ box . delete ( ) ;
980+ } ) ;
981+
982+ it ( "should create a bounding box shape from a complex wire" , ( ) => {
983+ const points = [
984+ [ 0 , 0 , 0 ] ,
985+ [ 5 , 10 , 3 ] ,
986+ [ - 2 , 5 , 8 ] ,
987+ [ 3 , - 1 , 2 ]
988+ ] as Inputs . Base . Point3 [ ] ;
989+ const polyWire = wire . createPolylineWire ( { points } ) ;
990+
991+ const bboxShape = operations . boundingBoxShapeOfShape ( { shape : polyWire } ) ;
992+ const volume = solid . getSolidVolume ( { shape : bboxShape } ) ;
993+ const bbox = operations . boundingBoxOfShape ( { shape : polyWire } ) ;
994+
995+ // Volume should be width * height * depth
996+ const expectedVolume = bbox . size [ 0 ] * bbox . size [ 1 ] * bbox . size [ 2 ] ;
997+ expect ( volume ) . toBeCloseTo ( expectedVolume , 5 ) ;
998+
999+ polyWire . delete ( ) ;
1000+ bboxShape . delete ( ) ;
1001+ } ) ;
1002+
1003+ it ( "should get bounding box of compound shape with multiple solids" , ( ) => {
1004+ const box1 = occHelper . entitiesService . bRepPrimAPIMakeBox ( 1 , 1 , 1 , [ 0 , 0 , 0 ] ) ;
1005+ const box2 = occHelper . entitiesService . bRepPrimAPIMakeBox ( 1 , 1 , 1 , [ 5 , 5 , 5 ] ) ;
1006+ const compound = occHelper . converterService . makeCompound ( { shapes : [ box1 , box2 ] } ) ;
1007+
1008+ const bbox = operations . boundingBoxOfShape ( { shape : compound } ) ;
1009+
1010+ expect ( bbox . min [ 0 ] ) . toBeCloseTo ( - 0.5 , 4 ) ;
1011+ expect ( bbox . min [ 1 ] ) . toBeCloseTo ( - 0.5 , 4 ) ;
1012+ expect ( bbox . min [ 2 ] ) . toBeCloseTo ( - 0.5 , 4 ) ;
1013+ expect ( bbox . max [ 0 ] ) . toBeCloseTo ( 5.5 , 4 ) ;
1014+ expect ( bbox . max [ 1 ] ) . toBeCloseTo ( 5.5 , 4 ) ;
1015+ expect ( bbox . max [ 2 ] ) . toBeCloseTo ( 5.5 , 4 ) ;
1016+ expect ( bbox . size [ 0 ] ) . toBeCloseTo ( 6 , 4 ) ;
1017+ expect ( bbox . size [ 1 ] ) . toBeCloseTo ( 6 , 4 ) ;
1018+ expect ( bbox . size [ 2 ] ) . toBeCloseTo ( 6 , 4 ) ;
1019+
1020+ box1 . delete ( ) ;
1021+ box2 . delete ( ) ;
1022+ compound . delete ( ) ;
1023+ } ) ;
1024+
1025+ it ( "should get bounding box of extruded wire" , ( ) => {
1026+ const circleWire = wire . createCircleWire ( { center : [ 3 , 0 , 0 ] , radius : 1 , direction : [ 0 , 1 , 0 ] } ) ;
1027+ const extruded = operations . extrude ( { shape : circleWire , direction : [ 0 , 5 , 0 ] } ) ;
1028+
1029+ const bbox = operations . boundingBoxOfShape ( { shape : extruded } ) ;
1030+
1031+ expect ( bbox . min [ 0 ] ) . toBeCloseTo ( 2 , 5 ) ;
1032+ expect ( bbox . min [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
1033+ expect ( bbox . min [ 2 ] ) . toBeCloseTo ( - 1 , 5 ) ;
1034+ expect ( bbox . max [ 0 ] ) . toBeCloseTo ( 4 , 5 ) ;
1035+ expect ( bbox . max [ 1 ] ) . toBeCloseTo ( 5 , 5 ) ;
1036+ expect ( bbox . max [ 2 ] ) . toBeCloseTo ( 1 , 5 ) ;
1037+
1038+ circleWire . delete ( ) ;
1039+ extruded . delete ( ) ;
1040+ } ) ;
1041+
1042+ it ( "should get bounding box of revolved shape" , ( ) => {
1043+ const squareFace = face . createSquareFace ( { center : [ 5 , 0 , 0 ] , size : 2 , direction : [ 0 , 1 , 0 ] } ) ;
1044+ const revolved = operations . revolve ( { shape : squareFace , direction : [ 0 , 1 , 0 ] , angle : 180 , copy : false } ) ;
1045+
1046+ const bbox = operations . boundingBoxOfShape ( { shape : revolved } ) ;
1047+
1048+ expect ( bbox . min [ 0 ] ) . toBeCloseTo ( - 6 , 0 ) ;
1049+ expect ( bbox . min [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
1050+ expect ( bbox . min [ 2 ] ) . toBeCloseTo ( - 6 , 0 ) ;
1051+ expect ( bbox . max [ 0 ] ) . toBeCloseTo ( 6 , 0 ) ;
1052+ expect ( bbox . max [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
1053+ expect ( bbox . max [ 2 ] ) . toBeCloseTo ( 1 , 0 ) ;
1054+
1055+ squareFace . delete ( ) ;
1056+ revolved . delete ( ) ;
1057+ } ) ;
1058+ } ) ;
1059+
1060+ describe ( "Bounding sphere operations" , ( ) => {
1061+ it ( "should get bounding sphere properties of a box" , ( ) => {
1062+ const box = occHelper . entitiesService . bRepPrimAPIMakeBox ( 2 , 2 , 2 , [ 0 , 0 , 0 ] ) ;
1063+ const bsphere = operations . boundingSphereOfShape ( { shape : box } ) ;
1064+
1065+ // Box is centered at [0,0,0], bounding sphere center is at bbox center
1066+ expect ( bsphere . center [ 0 ] ) . toBeCloseTo ( 0 , 5 ) ;
1067+ expect ( bsphere . center [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
1068+ expect ( bsphere . center [ 2 ] ) . toBeCloseTo ( 0 , 5 ) ;
1069+ expect ( bsphere . radius ) . toBeCloseTo ( Math . sqrt ( 3 ) , 5 ) ;
1070+
1071+ box . delete ( ) ;
1072+ } ) ;
1073+
1074+ it ( "should get bounding sphere center of a sphere" , ( ) => {
1075+ const sphere = occHelper . entitiesService . bRepPrimAPIMakeSphere ( [ 3 , 4 , 5 ] , [ 0 , 1 , 0 ] , 2 ) ;
1076+ const center = operations . boundingSphereCenterOfShape ( { shape : sphere } ) ;
1077+
1078+ expect ( center [ 0 ] ) . toBeCloseTo ( 3 , 5 ) ;
1079+ expect ( center [ 1 ] ) . toBeCloseTo ( 4 , 5 ) ;
1080+ expect ( center [ 2 ] ) . toBeCloseTo ( 5 , 5 ) ;
1081+
1082+ sphere . delete ( ) ;
1083+ } ) ;
1084+
1085+ it ( "should get bounding sphere radius of a cylinder" , ( ) => {
1086+ const cyl = occHelper . entitiesService . bRepPrimAPIMakeCylinder ( [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , 3 , 8 , 360 ) ;
1087+ const radius = operations . boundingSphereRadiusOfShape ( { shape : cyl } ) ;
1088+
1089+ // For a cylinder with radius 3 and height 8, the bounding sphere radius is
1090+ // the distance from center (0, 4, 0) to corner (3, 8, 0) or (3, 0, 0)
1091+ // = sqrt(3^2 + 4^2 + 3^2) = sqrt(34) ≈ 5.83
1092+ expect ( radius ) . toBeCloseTo ( Math . sqrt ( 34 ) , 2 ) ;
1093+
1094+ cyl . delete ( ) ;
1095+ } ) ;
1096+
1097+ it ( "should create a bounding sphere shape from a torus-like shape" , ( ) => {
1098+ const circle = face . createCircleFace ( { center : [ 5 , 0 , 0 ] , radius : 1 , direction : [ 0 , 1 , 0 ] } ) ;
1099+ const torus = operations . revolve ( { shape : circle , direction : [ 0 , 1 , 0 ] , angle : 360 , copy : false } ) ;
1100+
1101+ const bsphereShape = operations . boundingSphereShapeOfShape ( { shape : torus } ) ;
1102+ const bsphere = operations . boundingSphereOfShape ( { shape : torus } ) ;
1103+
1104+ // Get the volume of the bounding sphere
1105+ const volume = solid . getSolidVolume ( { shape : bsphereShape } ) ;
1106+ const expectedVolume = ( 4 / 3 ) * Math . PI * Math . pow ( bsphere . radius , 3 ) ;
1107+
1108+ expect ( volume ) . toBeCloseTo ( expectedVolume , 2 ) ;
1109+
1110+ circle . delete ( ) ;
1111+ torus . delete ( ) ;
1112+ bsphereShape . delete ( ) ;
1113+ } ) ;
1114+
1115+ it ( "should get bounding sphere of compound with multiple shapes" , ( ) => {
1116+ const sphere1 = occHelper . entitiesService . bRepPrimAPIMakeSphere ( [ 0 , 0 , 0 ] , [ 0 , 1 , 0 ] , 1 ) ;
1117+ const sphere2 = occHelper . entitiesService . bRepPrimAPIMakeSphere ( [ 10 , 0 , 0 ] , [ 0 , 1 , 0 ] , 1 ) ;
1118+ const compound = occHelper . converterService . makeCompound ( { shapes : [ sphere1 , sphere2 ] } ) ;
1119+
1120+ const bsphere = operations . boundingSphereOfShape ( { shape : compound } ) ;
1121+
1122+ // Center should be at midpoint of bounding box
1123+ expect ( bsphere . center [ 0 ] ) . toBeCloseTo ( 5 , 5 ) ;
1124+ expect ( bsphere . center [ 1 ] ) . toBeCloseTo ( 0 , 5 ) ;
1125+ expect ( bsphere . center [ 2 ] ) . toBeCloseTo ( 0 , 5 ) ;
1126+
1127+ expect ( bsphere . radius ) . toBeCloseTo ( Math . sqrt ( 38 ) , 2 ) ;
1128+
1129+ sphere1 . delete ( ) ;
1130+ sphere2 . delete ( ) ;
1131+ compound . delete ( ) ;
1132+ } ) ;
1133+
1134+ it ( "should get bounding sphere for a wire" , ( ) => {
1135+ const points = [
1136+ [ 0 , 0 , 0 ] ,
1137+ [ 10 , 0 , 0 ] ,
1138+ [ 10 , 10 , 0 ] ,
1139+ [ 0 , 10 , 0 ]
1140+ ] as Inputs . Base . Point3 [ ] ;
1141+ const squareWire = wire . createPolylineWire ( { points } ) ;
1142+
1143+ const bsphere = operations . boundingSphereOfShape ( { shape : squareWire } ) ;
1144+
1145+ expect ( bsphere . center ) . toEqual ( [ 5 , 5 , 0 ] ) ;
1146+ expect ( bsphere . radius ) . toBeCloseTo ( Math . sqrt ( 50 ) , 5 ) ;
1147+
1148+ squareWire . delete ( ) ;
1149+ } ) ;
1150+
1151+ it ( "should compare bounding box and bounding sphere volumes" , ( ) => {
1152+ const box = occHelper . entitiesService . bRepPrimAPIMakeBox ( 4 , 4 , 4 , [ - 2 , - 2 , - 2 ] ) ;
1153+
1154+ const bboxShape = operations . boundingBoxShapeOfShape ( { shape : box } ) ;
1155+ const bsphereShape = operations . boundingSphereShapeOfShape ( { shape : box } ) ;
1156+
1157+ const bboxVolume = solid . getSolidVolume ( { shape : bboxShape } ) ;
1158+ const bsphereVolume = solid . getSolidVolume ( { shape : bsphereShape } ) ;
1159+
1160+ // Bounding sphere should always have larger volume than bounding box for a cube
1161+ expect ( bsphereVolume ) . toBeGreaterThan ( bboxVolume ) ;
1162+ expect ( bboxVolume ) . toBeCloseTo ( 64 , 4 ) ;
1163+
1164+ box . delete ( ) ;
1165+ bboxShape . delete ( ) ;
1166+ bsphereShape . delete ( ) ;
1167+ } ) ;
1168+ } ) ;
1169+
9171170
9181171} ) ;
9191172
0 commit comments