74std::optional<rectpack2D::rect_wh>
spreadRectangles( std::vector<RECT_T>& vecSubRects,
int areaSizeX,
int areaSizeY )
79 std::optional<rectpack2D::rect_wh>
result;
81 int max_side = std::max( areaSizeX, areaSizeY );
83 for(
int i = 0; i < 2000; i++ )
85 bool anyUnsuccessful =
false;
86 const int discard_step = 1;
88 auto report_successful =
91 return rectpack2D::callback_result::CONTINUE_PACKING;
94 auto report_unsuccessful =
97 anyUnsuccessful =
true;
98 return rectpack2D::callback_result::ABORT_PACKING;
101 result = rectpack2D::find_best_packing<SPACES_T>( vecSubRects,
102 make_finder_input( max_side, discard_step,
103 report_successful, report_unsuccessful,
104 rectpack2D::flipping_option::DISABLED ) );
106 if( !
result || anyUnsuccessful )
108 max_side = (int) ( max_side * 1.2 );
120 int aComponentGap,
int aGroupGap )
122 using FpBBoxToFootprintsPair = std::pair<BOX2I, std::vector<FOOTPRINT*>>;
123 using SheetBBoxToFootprintsMapPair = std::pair<BOX2I, std::map<VECTOR2I, FpBBoxToFootprintsPair>>;
125 std::map<wxString, SheetBBoxToFootprintsMapPair> sheetsMap;
128 for(
FOOTPRINT* footprint : *aFootprints )
130 wxString
path = aGroupBySheet ? footprint->GetPath().AsString().BeforeLast(
'/' ) : wxString( wxS(
"" ) );
132 VECTOR2I size = footprint->GetBoundingBox(
false ).GetSize();
133 size.
x += aComponentGap;
134 size.
y += aComponentGap;
136 sheetsMap[
path].second[size].second.push_back( footprint );
139 for(
auto& [sheetPath, sheetPair] : sheetsMap )
141 auto& [sheet_bbox, sizeToFpMap] = sheetPair;
143 for(
auto& [fpSize, fpPair] : sizeToFpMap )
145 auto& [block_bbox, footprints] = fpPair;
149 double blockEstimateArea = (double) fpSize.x * fpSize.y * footprints.size();
150 double initialSide = std::sqrt( blockEstimateArea );
151 bool vertical = fpSize.x >= fpSize.y;
153 int initialCountPerLine = footprints.size();
155 const int singleLineRatio = 5;
160 if( ( fpSize.y * footprints.size() / fpSize.x ) > singleLineRatio )
161 initialCountPerLine = initialSide / fpSize.y;
165 if( ( fpSize.x * footprints.size() / fpSize.y ) > singleLineRatio )
166 initialCountPerLine = initialSide / fpSize.x;
169 int optimalCountPerLine = initialCountPerLine;
170 int optimalRemainder = footprints.size() % optimalCountPerLine;
172 if( optimalRemainder != 0 )
174 for(
int i = std::max( 2, initialCountPerLine - 2 );
175 i <= std::min( (
int) footprints.size() - 2, initialCountPerLine + 2 ); i++ )
177 int r = footprints.size() % i;
179 if( r == 0 || r >= optimalRemainder )
181 optimalCountPerLine = i;
182 optimalRemainder = r;
190 for(
unsigned i = 0; i < footprints.size(); i++ )
198 position.
x += fpSize.x * ( i / optimalCountPerLine );
199 position.
y += fpSize.y * ( i % optimalCountPerLine );
203 position.
x += fpSize.x * ( i % optimalCountPerLine );
204 position.
y += fpSize.y * ( i / optimalCountPerLine );
211 new_fp_bbox.
Inflate( aComponentGap / 2 );
212 block_bbox.
Merge( new_fp_bbox );
216 std::vector<RECT_T> vecSubRects;
217 long long blocksArea = 0;
220 for(
auto& [fpSize, fpPair] : sizeToFpMap )
222 auto& [block_bbox, footprints] = fpPair;
224 vecSubRects.emplace_back( 0, 0, block_bbox.GetWidth() /
scale, block_bbox.GetHeight() /
scale,
false );
226 blocksArea += block_bbox.GetArea();
230 int areaSide =
KiROUND( std::sqrt( blocksArea ) );
233 unsigned block_i = 0;
236 for(
auto& [fpSize, pair] : sizeToFpMap )
238 auto& [src_bbox, footprints] = pair;
240 RECT_T srect = vecSubRects[block_i];
247 if( (uint64_t) target_pos.
x + (uint64_t) target_size.
x > INT_MAX / 2 )
248 target_pos.
x -= INT_MAX / 2;
250 if( (uint64_t) target_pos.
y + (uint64_t) target_size.
y > INT_MAX / 2 )
251 target_pos.
y -= INT_MAX / 2;
255 footprint->Move( target_pos - src_bbox.GetPosition() );
256 sheet_bbox.Merge( footprint->GetBoundingBox(
false ) );
263 std::vector<RECT_T> vecSubRects;
264 long long sheetsArea = 0;
267 for(
auto& [sheetPath, sheetPair] : sheetsMap )
269 auto& [sheet_bbox, sizeToFpMap] = sheetPair;
270 BOX2I rect = sheet_bbox;
277 sheetsArea += sheet_bbox.GetArea();
281 int areaSide = std::sqrt( sheetsArea );
284 unsigned srect_i = 0;
287 for(
auto& [sheetPath, sheetPair] : sheetsMap )
289 auto& [src_bbox, sizeToFpMap] = sheetPair;
291 RECT_T srect = vecSubRects[srect_i];
293 VECTOR2I target_pos( srect.x *
scale + aTargetBoxPosition.
x, srect.y *
scale + aTargetBoxPosition.
y );
298 if( (int64_t) target_pos.
x + (int64_t) target_size.
x > INT_MAX / 2 )
299 target_pos.
x -= INT_MAX / 2;
301 if( (int64_t) target_pos.
y + (int64_t) target_size.
y > INT_MAX / 2 )
302 target_pos.
y -= INT_MAX / 2;
304 for(
auto& [fpSize, fpPair] : sizeToFpMap )
306 auto& [block_bbox, footprints] = fpPair;
309 footprint->Move( target_pos - src_bbox.GetPosition() );
wxString result
Test unit parsing edge cases and error handling.