bin-packing icon indicating copy to clipboard operation
bin-packing copied to clipboard

Bug with simple packer

Open eemmy opened this issue 3 years ago • 1 comments

Hello, I am facing a problem when trying to use the simplest version of the lib, the packer.js (even though the filename refers to the other one)

It turns out that the following code:

     /**
     * Handle main data generation. This method generate only raw data, used by another API (INSERT LATE) to generate real used data.
     * @param {*} req
     * @param {*} res
     * @return {void}
     */
    getOffsets: (req, res) => {
        // Necessary data
        const mdfData = {
            height: 1000,
            width: 800
        }

        // Import optimizer library and instantiate it
        const growingPacker = require('../vendor/packer.growing.js');
        const packer        = new growingPacker(800, 1000);

        // This will take data to generate offsets
        let pieces = [
            { h: 21100, w: 2220},
            { h: 1000, w: 22000 },
            { h: 1000, w: 22000 },
            { h: 1000, w: 22000 },
            { h: 1000, w: 22000 },
            { h: 1000, w: 22000 },
            { h: 1000, w: 22000 },
            { h: 2000, w: 22000 },
            { h: 1000, w: 22000 },
        ];

        // Sort pieces by height
        pieces.sort((a, b) => { return(b.h < a.h) });
        
        // Generate offsets
        packer.fit(pieces);
        console.log(pieces); 
        

        res.send(pieces)
    }

It is generating this output:

[
    { "h": 21100, "w": 2220 },
    { "h": 1000, "w": 22000 },
    { "h": 1000, "w": 22000 },
    { "h": 1000, "w": 22000 },
    { "h": 1000, "w": 22000 },
    { "h": 1000, "w": 22000 },
    { "h": 1000, "w": 22000 },
    { "h": 2000, "w": 22000 },
    { "h": 1000, "w": 22000 }
]

My packer.growing.js looks like this:

Packer = function(w, h) {
  this.init(w, h);
};

Packer.prototype = {

  init: function(w, h) {
    this.root = { x: 0, y: 0, w: w, h: h };
  },

  fit: function(blocks) {
    var n, node, block;
    for (n = 0; n < blocks.length; n++) {
      block = blocks[n];
      if (node = this.findNode(this.root, block.w, block.h))
        block.fit = this.splitNode(node, block.w, block.h);
    }
  },

  findNode: function(root, w, h) {
    if (root.used)
      return this.findNode(root.right, w, h) || this.findNode(root.down, w, h);
    else if ((w <= root.w) && (h <= root.h))
      return root;
    else
      return null;
  },

  splitNode: function(node, w, h) {
    node.used = true;
    node.down  = { x: node.x,     y: node.y + h, w: node.w,     h: node.h - h };
    node.right = { x: node.x + w, y: node.y,     w: node.w - w, h: h          };
    return node;
  }

}

module.exports = Packer;

I am using Node + ExpressJS for development.

I was using Growing at first, which was generating the expected data output, but the feature I am developing requires me to enter a width/height limit.

If you can help me, I would be very grateful. Thanks in advance, and sorry for the bad English

eemmy avatar Sep 02 '21 20:09 eemmy

Try pieces.sort((a, b) => { return(b.h - a.h) }); instead.

lantto avatar Mar 06 '22 16:03 lantto