#region License Information /* HeuristicLab * Copyright (C) 2002-2015 Joseph Helm and Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Diagnostics; using HeuristicLab.Problems.BinPacking.Interfaces; using HeuristicLab.Core; using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; using HeuristicLab.Common; using HeuristicLab.Problems.BinPacking.Dimensions; namespace HeuristicLab.Problems.BinPacking.Shapes { [Item("CuboidPackingShape", "Represents the cuboid measures (width, height, depth) of a three-dimensional cuboidic bin-packing object.")] [StorableClass] public abstract class CuboidPackingShape : PackingShape, IRegularPackingShape, IComparable { #region Properties /// /// Describes the size on the X-axis /// [Storable] public int Width { get; set; } /// /// Describes the size on the Y-axis /// [Storable] public int Height { get; set; } /// /// Describes the size on the Z-axis /// [Storable] public int Depth { get; set; } #endregion #region Helpers public override ThreeDimensionalPacking Origin { get { return new ThreeDimensionalPacking(0, 0, 0, 0); } } public override int MultipliedMeasures { get { return Width * Height * Depth; } } public override bool EnclosesPoint(ThreeDimensionalPacking myPosition, ThreeDimensionalPacking checkedPoint) { return (myPosition.X <= checkedPoint.X && (myPosition.X + (myPosition.Rotated ? Depth : Width) - 1) >= checkedPoint.X && myPosition.Y <= checkedPoint.Y && (myPosition.Y + Height - 1) >= checkedPoint.Y && myPosition.Z <= checkedPoint.Z && (myPosition.Z + (myPosition.Rotated ? Width : Depth) - 1) >= checkedPoint.Z); } public override bool Encloses(ThreeDimensionalPacking checkedPosition, PackingShape checkedShape) { return Encloses(checkedPosition, (CuboidPackingShape)checkedShape); } private bool Encloses(ThreeDimensionalPacking checkedPosition, CuboidPackingShape checkedShape) { return Encloses(new CuboidDiagonal(this), new CuboidDiagonal(checkedPosition, checkedShape)); } private bool Encloses(CuboidDiagonal c1, CuboidDiagonal c2) { return (c1.x1 <= c2.x1 && c1.x2 >= c2.x2 && c1.y1 <= c2.y1 && c1.y2 >= c2.y2 && c1.z1 <= c2.z1 && c1.z2 >= c2.z2); } public override bool Overlaps(ThreeDimensionalPacking myPosition, ThreeDimensionalPacking checkedPosition, PackingShape checkedShape) { return Overlaps(myPosition, checkedPosition, (CuboidPackingShape)checkedShape); } private bool Overlaps(ThreeDimensionalPacking myPosition, ThreeDimensionalPacking checkedPosition, CuboidPackingShape checkedShape) { return Overlaps(new CuboidDiagonal(myPosition, this), new CuboidDiagonal(checkedPosition, checkedShape)); } private bool Overlaps(CuboidDiagonal c1, CuboidDiagonal c2) { return !(c1.x1 > c2.x2 || c1.y1 > c2.y2 || c1.z1 > c2.z2 || c1.x2 < c2.x1 || c1.y2 < c2.y1 || c1.z2 < c2.z1); } public void ApplyHorizontalOrientation() { if (Width > Depth) { var aux = Width; Width = Depth; Depth = aux; } } #endregion protected CuboidPackingShape(int width, int height, int depth) : base() { this.Width = width; this.Height = height; this.Depth = depth; } public override void InitializeFromMeasures(int[] measures) { if (measures.Length != 3) throw new InvalidOperationException("Nr of measures does not fit shape-dimension."); this.Width = measures[0]; this.Height = measures[1]; this.Depth = measures[2]; } public override int[] ToArray() { return new int[] { Width, Height, Depth }; } [StorableConstructor] protected CuboidPackingShape(bool deserializing) : base(deserializing) { } protected CuboidPackingShape(CuboidPackingShape original, Cloner cloner) : base(original, cloner) { this.Width = original.Width; this.Height = original.Height; this.Depth = original.Depth; } protected CuboidPackingShape() : base() { } public override string ToString() { return String.Format("CuboidPackingShape ({0}, {1}, {2})", this.Width, this.Height, this.Depth); } #region IComparable Members public int CompareTo(CuboidPackingShape other) { //Using "Clustered-Area-Height"-comparison as descr int result = (this.Width * this.Depth).CompareTo(other.Width * other.Depth); if (result == 0) result = this.MultipliedMeasures.CompareTo(other.MultipliedMeasures); if (result == 0) result = this.Height.CompareTo(other.Height); return result; } public int CompareTo(object obj) { var other = (CuboidPackingShape)obj; if (other != null) return CompareTo(other); else throw new ArgumentException(string.Format("Cannot compare with object {0}", obj), "obj"); } #endregion private struct CuboidDiagonal { public int x1; public int y1; public int z1; public int x2; public int y2; public int z2; public CuboidDiagonal(CuboidPackingShape myShape) : this(new ThreeDimensionalPacking(0, 0, 0, 0), myShape) { } public CuboidDiagonal(ThreeDimensionalPacking myPosition, CuboidPackingShape myShape) { x1 = myPosition.X; y1 = myPosition.Y; z1 = myPosition.Z; x2 = myPosition.X + (myPosition.Rotated ? myShape.Depth : myShape.Width) - 1; y2 = myPosition.Y + myShape.Height - 1; z2 = myPosition.Z + (myPosition.Rotated ? myShape.Width : myShape.Depth) - 1; } } } }