// Path: CutletLib/src/main/java/com/cutlet/lib/model/Dimension.java
// @ToString
// public class Dimension implements Serializable{
// 
//     private double length;
//     private double width;
// 
//     public Dimension(final double length, final double width) {
//         this.length = length;
//         this.width = width;
//     }
// 
//     public double getLength() {
//         return length;
//     }
// 
//     public void setLength(final double length) {
//         this.length = length;
//     }
// 
//     public double getWidth() {
//         return width;
//     }
// 
//     public void setWidth(final double width) {
//         this.width = width;
//     }
// 
//     public double getArea() {
//         return getLength() * getWidth();
//     }
// 
//     public boolean canHold(@NonNull final Dimension other) {
//         return other.getLength() <= this.getLength() && other.getWidth() <= this.getWidth();
//     }    
//     
//     public Dimension rotated() {
//         return new Dimension(width, length);
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/Position.java
// @ToString
// public class Position implements Serializable {
// 
//     private double x, y;
// 
//     public Position(final double x, final double y) {
//         this.x = x;
//         this.y = y;
//     }
// 
//     public double getX() {
//         return x;
//     }
// 
//     public void setX(final double x) {
//         this.x = x;
//     }
// 
//     public double getY() {
//         return y;
//     }
// 
//     public void setY(final double y) {
//         this.y = y;
//     }
// 
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/StockSheet.java
// @ToString
// public class StockSheet implements Serializable {
// 
//     private final Material material;
//     private final double thickness;
//     private final String title;
//     private final Dimension dimension;
//     
// 
// 
//     public StockSheet(@NonNull final String title, 
//             @NonNull final Material material, 
//             @NonNull final Dimension dimension, 
//             final double thickness) {
//         
//         this.material = material;
//         this.dimension = dimension;
//         this.thickness = thickness;
//         this.title = title;
//     }
// 
//     public Dimension getDimension() {
//         return dimension;
//     }
// 
//     public double getThickness() {
//         return thickness;
//     }
// }


import com.cutlet.lib.model.Dimension;
import com.cutlet.lib.model.Position;
import com.cutlet.lib.model.StockSheet;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import lombok.NonNull;

        double boundingBoxMinY = Double.MAX_VALUE;
        double boundingBoxMaxY = Double.MIN_VALUE;

        for (CutTreeNode node : this) {
            if (node instanceof FreeNode) {
            } else if (node instanceof PanelNode) {
                final PanelNode pn = (PanelNode) node;
                usedArea += pn.getDimension().getArea();

                // this is only partly correct...
                // we should also take cuts into consideration!
                Dimension dim = pn.getDimension();
                Position pos = pn.getPosition();
                boundingBoxMinX = Math.min(pos.getX(), boundingBoxMinX);
                boundingBoxMaxX = Math.max(pos.getX() + dim.getLength(), boundingBoxMaxX);
                boundingBoxMinY = Math.min(pos.getY(), boundingBoxMinY);
                boundingBoxMaxY = Math.max(pos.getY() + dim.getWidth(), boundingBoxMaxY);

            } else if (node instanceof CutNode) {
                final CutNode cn = (CutNode) node;
                numberOfCuts++;
                totalCutLength += cn.getCutLength();
            }
        }
        double boundingBoxArea = (boundingBoxMaxX - boundingBoxMinX) * (boundingBoxMaxY - boundingBoxMinY);

        CutTreeStats stats = new CutTreeStats(numberOfCuts,
                totalCutLength,
                sheetArea,
                usedArea,

// Path: CutletLib/src/main/java/com/cutlet/lib/model/Dimension.java
// @ToString
// public class Dimension implements Serializable{
// 
//     private double length;
//     private double width;
// 
//     public Dimension(final double length, final double width) {
//         this.length = length;
//         this.width = width;
//     }
// 
//     public double getLength() {
//         return length;
//     }
// 
//     public void setLength(final double length) {
//         this.length = length;
//     }
// 
//     public double getWidth() {
//         return width;
//     }
// 
//     public void setWidth(final double width) {
//         this.width = width;
//     }
// 
//     public double getArea() {
//         return getLength() * getWidth();
//     }
// 
//     public boolean canHold(@NonNull final Dimension other) {
//         return other.getLength() <= this.getLength() && other.getWidth() <= this.getWidth();
//     }    
//     
//     public Dimension rotated() {
//         return new Dimension(width, length);
//     }
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/Position.java
// @ToString
// public class Position implements Serializable {
// 
//     private double x, y;
// 
//     public Position(final double x, final double y) {
//         this.x = x;
//         this.y = y;
//     }
// 
//     public double getX() {
//         return x;
//     }
// 
//     public void setX(final double x) {
//         this.x = x;
//     }
// 
//     public double getY() {
//         return y;
//     }
// 
//     public void setY(final double y) {
//         this.y = y;
//     }
// 
// }
// 
// Path: CutletLib/src/main/java/com/cutlet/lib/model/StockSheet.java
// @ToString
// public class StockSheet implements Serializable {
// 
//     private final Material material;
//     private final double thickness;
//     private final String title;
//     private final Dimension dimension;
//     
// 
// 
//     public StockSheet(@NonNull final String title, 
//             @NonNull final Material material, 
//             @NonNull final Dimension dimension, 
//             final double thickness) {
//         
//         this.material = material;
//         this.dimension = dimension;
//         this.thickness = thickness;
//         this.title = title;
//     }
// 
//     public Dimension getDimension() {
//         return dimension;
//     }
// 
//     public double getThickness() {
//         return thickness;
//     }
// }


// Path: CutletLib/src/main/java/com/cutlet/lib/data/cuttree/CutTree.java
import com.cutlet.lib.model.Dimension;
import com.cutlet.lib.model.Position;
import com.cutlet.lib.model.StockSheet;
import java.io.Serializable;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import lombok.NonNull;

        double boundingBoxMinY = Double.MAX_VALUE;
        double boundingBoxMaxY = Double.MIN_VALUE;

        for (CutTreeNode node : this) {
            if (node instanceof FreeNode) {
            } else if (node instanceof PanelNode) {
                final PanelNode pn = (PanelNode) node;
                usedArea += pn.getDimension().getArea();

                // this is only partly correct...
                // we should also take cuts into consideration!
                Dimension dim = pn.getDimension();
                Position pos = pn.getPosition();
                boundingBoxMinX = Math.min(pos.getX(), boundingBoxMinX);
                boundingBoxMaxX = Math.max(pos.getX() + dim.getLength(), boundingBoxMaxX);
                boundingBoxMinY = Math.min(pos.getY(), boundingBoxMinY);
                boundingBoxMaxY = Math.max(pos.getY() + dim.getWidth(), boundingBoxMaxY);

            } else if (node instanceof CutNode) {
                final CutNode cn = (CutNode) node;
                numberOfCuts++;
                totalCutLength += cn.getCutLength();
            }
        }
        double boundingBoxArea = (boundingBoxMaxX - boundingBoxMinX) * (boundingBoxMaxY - boundingBoxMinY);

        CutTreeStats stats = new CutTreeStats(numberOfCuts,
                totalCutLength,
                sheetArea,
                usedArea,

                boundingBoxArea);
