@@ -921,6 +921,8 @@ function placeParts(sheets, parts, config, nestindex) {
921921
922922 var allbounds ;
923923 var partbounds ;
924+ var hull = null ;
925+
924926 if ( config . placementType == 'gravity' || config . placementType == 'box' ) {
925927 allbounds = GeometryUtil . getPolygonBounds ( allpoints ) ;
926928
@@ -930,14 +932,15 @@ function placeParts(sheets, parts, config, nestindex) {
930932 }
931933 partbounds = GeometryUtil . getPolygonBounds ( partpoints ) ;
932934 }
933- else {
934- allpoints = getHull ( allpoints ) ;
935+ else if ( config . placementType == 'convexhull' && allpoints . length > 0 ) {
936+ // Calculate the hull of all already placed parts once
937+ hull = getHull ( allpoints ) ;
935938 }
939+
936940 for ( let j = 0 ; j < finalNfp . length ; j ++ ) {
937941 nf = finalNfp [ j ] ;
938- //console.log('evalnf',nf.length);
942+
939943 for ( let k = 0 ; k < nf . length ; k ++ ) {
940-
941944 shiftvector = {
942945 x : nf [ k ] . x - part [ 0 ] . x ,
943946 y : nf [ k ] . y - part [ 0 ] . y ,
@@ -947,8 +950,7 @@ function placeParts(sheets, parts, config, nestindex) {
947950 filename : part . filename
948951 } ;
949952
950- // ENHANCEMENT: Add a more rigorous overlap check before considering this position
951- // First, create a theoretical placement of the part at this position
953+ // ENHANCEMENT: Add a more rigorous overlap check before considering this position
952954 const theoreticPlacement = [ ] ;
953955 for ( let m = 0 ; m < part . length ; m ++ ) {
954956 theoreticPlacement . push ( {
@@ -957,7 +959,6 @@ function placeParts(sheets, parts, config, nestindex) {
957959 } ) ;
958960 }
959961
960- // Then check for overlaps with all previously placed parts
961962 let hasOverlap = false ;
962963 for ( let m = 0 ; m < placed . length ; m ++ ) {
963964 const placedPart = [ ] ;
@@ -968,21 +969,16 @@ function placeParts(sheets, parts, config, nestindex) {
968969 } ) ;
969970 }
970971
971- // Use our enhanced overlap detector with additional safety margin
972972 if ( checkPlacementOverlap ( theoreticPlacement , placedPart , config . overlapTolerance || 0.0001 ) ) {
973973 hasOverlap = true ;
974974 break ;
975975 }
976976 }
977977
978- // Skip this position if any overlap was detected
979978 if ( hasOverlap ) {
980979 continue ;
981980 }
982981
983- /*for(m=0; m<part.length; m++){
984- localpoints.push({x: part[m].x+shiftvector.x, y:part[m].y+shiftvector.y});
985- }*/
986982 //console.time('evalbounds');
987983
988984 if ( config . placementType == 'gravity' || config . placementType == 'box' ) {
@@ -1008,22 +1004,40 @@ function placeParts(sheets, parts, config, nestindex) {
10081004 area = rectbounds . width * rectbounds . height ;
10091005 }
10101006 }
1011- else {
1012- // must be convex hull
1013- var localpoints = clone ( allpoints ) ;
1014-
1007+ else if ( config . placementType == 'convexhull' ) {
1008+ // Create points for the part at this candidate position
1009+ var partPoints = [ ] ;
10151010 for ( let m = 0 ; m < part . length ; m ++ ) {
1016- localpoints . push ( { x : part [ m ] . x + shiftvector . x , y : part [ m ] . y + shiftvector . y } ) ;
1011+ partPoints . push ( {
1012+ x : part [ m ] . x + shiftvector . x ,
1013+ y : part [ m ] . y + shiftvector . y
1014+ } ) ;
10171015 }
1018-
1019- area = Math . abs ( GeometryUtil . polygonArea ( getHull ( localpoints ) ) ) ;
1020- shiftvector . hull = getHull ( localpoints ) ;
1021- shiftvector . hullsheet = getHull ( sheet ) ;
1016+
1017+ var combinedHull ;
1018+
1019+ // If this is the first part, the hull is just the part itself
1020+ if ( allpoints . length === 0 ) {
1021+ combinedHull = getHull ( partPoints ) ;
1022+ } else {
1023+ // Merge the points of the part with the points of the hull
1024+ // and recalculate the combined hull (more efficient than using all points)
1025+ var hullPoints = hull . concat ( partPoints ) ;
1026+ combinedHull = getHull ( hullPoints ) ;
1027+ }
1028+
1029+ if ( ! combinedHull ) {
1030+ console . warn ( "Failed to calculate convex hull" ) ;
1031+ continue ;
1032+ }
1033+
1034+ // Calculate area of the convex hull
1035+ area = Math . abs ( GeometryUtil . polygonArea ( combinedHull ) ) ;
1036+
1037+ // Store for later use
1038+ shiftvector . hull = combinedHull ;
10221039 }
10231040
1024- //console.timeEnd('evalbounds');
1025- //console.time('evalmerge');
1026-
10271041 if ( config . mergeLines ) {
10281042 // if lines can be merged, subtract savings from area calculation
10291043 var shiftedpart = shiftPolygon ( part , shiftvector ) ;
@@ -1039,8 +1053,6 @@ function placeParts(sheets, parts, config, nestindex) {
10391053 area -= merged . totalLength * config . timeRatio ;
10401054 }
10411055
1042- //console.timeEnd('evalmerge');
1043-
10441056 if (
10451057 minarea === null ||
10461058 ( config . placementType == 'gravity' && (
@@ -1053,7 +1065,9 @@ function placeParts(sheets, parts, config, nestindex) {
10531065 // ENHANCEMENT: Add final verification before accepting position
10541066 if ( ! hasOverlap ) {
10551067 minarea = area ;
1056- minwidth = rectbounds . width ;
1068+ if ( config . placementType == 'gravity' || config . placementType == 'box' ) {
1069+ minwidth = rectbounds . width ;
1070+ }
10571071 position = shiftvector ;
10581072 minx = shiftvector . x ;
10591073 miny = shiftvector . y ;
0 commit comments