schizo Posted February 12, 2004 Share Posted February 12, 2004 This is what is included with the UPS XML contribution (which works great for the most part). What i need to do is put some constraints on it. I ship odd size packages, and it is putting some "Oversized" products into smaller boxes because it is based on volume. Can anyone let me know how to add a variable of "max_width". ex. a product that is 108x1x2 is being placed into a box 12x12x12 Any help would be great. -Shawn // A very simple box packing algorithm. Given a list of packages, returns // an array of boxes. function packProducts($productsArray) { // This algorithm is trivial. It works on the premise that you have selected // boxes that fit your products, and that their volumes are resonable multiples // of the products they store. For example, if you sell CDs and these CDs are // 5x5x0.5", your boxes should be 5x5x0.5 (1 CD mailer), 5x5x2.5 (5 CD mailer) // and 5x5x5 (10 CD mailer). No matter how many CDs a customer buys, this // routine will always find the optimal packing. // // Your milage may differ, depending on what variety of products you sell, and // how they're boxed. I just made up this algorithm in a hurry to fill a small // niche. You are encouraged to find better algorithms. Better algorithms mean // better packaging, resulting in higher quoting accuracy and less loss due to // inaccurate quoting. // // The algorithm proceeds as follows: // Get the first, smallest box, and try to put everything into it. If not all // of it fits, try fitting it all into the next largest box. Keep increasing // the size of the box until no larger box can be obtained, then spill over // into a second, smallest box. Once again, increase the box size until // everything fits, or spill over again. Repeat until everything is boxed. // // The cost of a box determines the order in which it is tried. There will definitely // be cases where it is cheaper to send two small packages rather than one larger one. // In that case, you'll need a better algorithm. // Get the available packages and "prepare" empty boxes with weight and remaining volume // counters. (Take existing box and add 'remaining_volume' and 'current_weight'; $definedPackages = $this->getPackages(); $emptyBoxesArray = array(); for ($i = 0; $i < count($definedPackages); $i++) { $definedBox = $definedPackages[$i]; $definedBox['remaining_volume'] = $definedBox['length'] * $definedBox['width'] * $definedBox['height']; $definedBox['max_width'] = $definedBox['width']; $definedBox['current_weight'] = $definedBox['empty_weight']; $emptyBoxesArray[] = $definedBox; } $packedBoxesArray = array(); $currentBox = NULL; // Get the product array and expand multiple qty items. $productsRemaining = array(); for ($i = 0; $i < count($productsArray); $i++) { $product = $productsArray[$i]; for ($j = 0; $j < $productsArray[$i]['quantity']; $j++) { $productsRemaining[] = $product; } } // Worst case, you'll need as many boxes as products ordered. while (count($productsRemaining)) { // Immediately set aside products that are already packed and ready. if ($productsRemaining[0]['ready_to_ship'] == '1') { $packedBoxesArray[] = array ( 'length' => $productsRemaining[0]['length'], 'width' => $productsRemaining[0]['width'], 'height' => $productsRemaining[0]['height'], 'current_weight' => $productsRemaining[0]['weight'] ); $productsRemaining = array_slice($productsRemaining, 1); continue; } //Cylcle through boxes, increasing box size if all doesn't fit. if (count($emptyBoxesArray) == 0) { print_r("ERROR: No boxes to ship unpackaged product<br>"); break; } for ($b = 0; $b < count($emptyBoxesArray); $b++) { $currentBox = $emptyBoxesArray[$b]; //Try to fit each product in box for ($p = 0; $p < count($productsRemaining); $p++) { if ($this->fitsInBox($productsRemaining[$p], $currentBox)) { //It fits. Put it in the box. $currentBox = $this->putProductInBox($productsRemaining[$p], $currentBox); if ($p == count($productsRemaining) - 1) { $packedBoxesArray[] = $currentBox; $productsRemaining = array_slice($productsRemaining, $p + 1); break 2; } } else { if ($b == count($emptyBoxesArray) - 1) { //We're at the largest box already, and it's full. //Keep what we've packed so far and get another box. $packedBoxesArray[] = $currentBox; $productsRemaining = array_slice($productsRemaining, $p + 1); break 2; } // Not all of them fit. Stop packing remaining products and try // next box. break; } } } } return $packedBoxesArray; } function fitsInBox($product, $box) { $productVolume = $product['length'] * $product['width'] * $product['height']; if ($productVolume <= $box['remaining_volume']) { if ($productWidth <= $box['max_width']) { if ($box['max_weight'] == 0 || ($box['current_weight'] + $product['weight'] <= $box['max_weight'])) { return true; } } return false; } function putProductInBox($product, $box) { $productVolume = $product['length'] * $product['width'] * $product['height']; $box['max_width'] <= $product['width'] $box['remaining_volume'] -= $productVolume; $box['products'][] = $product; $box['current_weight'] += $product['weight']; return $box; } Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.