Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ResidualSpaceCalculation/ResidualSpaceCalculator.cs @ 15585

Last change on this file since 15585 was 15585, checked in by rhanghof, 7 years ago

#2817:

  • Bugfixes for the line projection based extreme point creation
  • Bugfixes for the tests
File size: 9.5 KB
Line 
1using HeuristicLab.Problems.BinPacking3D.Geometry;
2using System;
3using System.Collections.Generic;
4using System.Linq;
5using System.Text;
6using System.Threading.Tasks;
7
8namespace HeuristicLab.Problems.BinPacking3D.ResidualSpaceCalculation {
9  internal class ResidualSpaceCalculator : IResidualSpaceCalculator {
10
11    internal ResidualSpaceCalculator() {}
12   
13    public IEnumerable<ResidualSpace> CalculateResidualSpaces(BinPacking3D binPacking, Vector3D point) {
14      IList<ResidualSpace> residualSpaces = new List<ResidualSpace>();
15      var rs1 = CalculateXZY(binPacking, point);
16      var rs2 = CalculateZYX(binPacking, point);
17      var rs3 = CalculateYXZ(binPacking, point);
18
19      if (!rs1.IsZero()) {
20        residualSpaces.Add(rs1);
21      }
22
23      if (!rs2.IsZero() && !residualSpaces.Any(rs => rs.Equals(rs2))) {
24        residualSpaces.Add(rs2);
25      }
26      if (!rs3.IsZero() && !residualSpaces.Any(rs => rs.Equals(rs3))) {
27        residualSpaces.Add(rs3);
28      }
29      return residualSpaces;
30    }
31
32    /// <summary>
33    /// Calculates a resiual space by expanding to the limits of the axis in the following order:
34    /// 1. x
35    /// 2. z
36    /// 3. y
37    /// </summary>
38    /// <param name="binPacking"></param>
39    /// <param name="point"></param>
40    /// <returns></returns>
41    private ResidualSpace CalculateXZY(BinPacking3D binPacking, Vector3D point) {
42      ResidualSpace rs = new ResidualSpace(binPacking, point);
43
44      LimitResidualSpaceOnRight(binPacking, point, rs);
45      LimitResidualSpaceInFront(binPacking, point, rs);
46      LimitResidualSpaceAbove(binPacking, point, rs);
47      return rs;
48    }
49
50    /// <summary>
51    /// Calculates a resiual space by expanding to the limits of the axis in the following order:
52    /// 1. z
53    /// 2. y
54    /// 3. x
55    /// </summary>
56    /// <param name="binPacking"></param>
57    /// <param name="point"></param>
58    /// <returns></returns>
59    private ResidualSpace CalculateZYX(BinPacking3D binPacking, Vector3D point) {
60      ResidualSpace rs = new ResidualSpace(binPacking, point);
61
62      LimitResidualSpaceInFront(binPacking, point, rs);
63      LimitResidualSpaceAbove(binPacking, point, rs);
64      LimitResidualSpaceOnRight(binPacking, point, rs);
65      return rs;
66    }
67
68    /// <summary>
69    /// Calculates a resiual space by expanding to the limits of the axis in the following order:
70    /// 1. y
71    /// 2. x
72    /// 3. z
73    /// </summary>
74    /// <param name="binPacking"></param>
75    /// <param name="point"></param>
76    /// <returns></returns>
77    private ResidualSpace CalculateYXZ(BinPacking3D binPacking, Vector3D point) {
78      ResidualSpace rs = new ResidualSpace(binPacking, point);
79
80      LimitResidualSpaceAbove(binPacking, point, rs);
81      LimitResidualSpaceOnRight(binPacking, point, rs);
82      LimitResidualSpaceInFront(binPacking, point, rs);
83      return rs;
84    }
85   
86    /// <summary>
87    /// Returnst true if a given residual space and item overlaps at the x-axis
88    /// </summary>
89    /// <param name="point"></param>
90    /// <param name="residualSpace"></param>
91    /// <param name="position"></param>
92    /// <param name="item"></param>
93    /// <returns></returns>
94    private bool OverlapsX(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item) {
95      if (point.X > position.X && point.X >= position.X + item.Width) {
96        return false;
97      }
98
99      if (point.X <= position.X && position.X >= point.X + residualSpace.Width) {
100        return false;
101      }
102      return true;
103    }
104
105    /// <summary>
106    /// Returnst true if a given residual space and item overlaps at the y-axis
107    /// </summary>
108    /// <param name="point"></param>
109    /// <param name="residualSpace"></param>
110    /// <param name="position"></param>
111    /// <param name="item"></param>
112    private bool OverlapsY(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item) {
113      if (point.Y > position.Y && point.Y >= position.Y + item.Height) {
114        return false;
115      }
116
117      if (point.Y <= position.Y && position.Y >= point.Y + residualSpace.Height) {
118        return false;
119      }
120      return true;
121    }
122
123    /// <summary>
124    /// Returnst true if a given residual space and item overlaps at the z-axis
125    /// </summary>
126    /// <param name="point"></param>
127    /// <param name="residualSpace"></param>
128    /// <param name="position"></param>
129    /// <param name="item"></param>
130    private bool OverlapsZ(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item) {
131      if (point.Z > position.Z && point.Z >= position.Z + item.Depth) {
132        return false;
133      }
134
135      if (point.Z <= position.Z && position.Z >= point.Z + residualSpace.Depth) {
136        return false;
137      }
138      return true;
139    }
140
141    private bool OverlapsOnRight(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item) {
142      // if point.x >= position.x => the residual space is being located on the left side!
143      if (point.X >= position.X) {
144        return false;
145      }
146      var y = OverlapsY(point, residualSpace, position, item);
147      var z = OverlapsZ(point, residualSpace, position, item);
148      return y && z;
149    }
150
151    private bool OverlapsInFront(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item) {
152      if (point.Z >= position.Z) {
153        return false;
154      }
155      var x = OverlapsX(point, residualSpace, position, item);
156      var y = OverlapsY(point, residualSpace, position, item);
157
158      return x && y;
159    }
160
161
162    private bool OverlapsAbove(Vector3D point, ResidualSpace residualSpace, PackingPosition position, PackingItem item ) {
163      if (point.Y >= position.Y) {
164        return false;
165      }
166      var x = OverlapsX(point, residualSpace, position, item);
167      var z = OverlapsZ(point, residualSpace, position, item);
168
169      return x && z;
170    }
171
172    /// <summary>
173    /// Recalculates the width of a given residual space.
174    /// The new width is being limited by any item right of the residual space or the dimension of the bin shape.
175    /// If the new width is zero, the whole residual space is being set to zero.
176    /// </summary>
177    /// <param name="binPacking"></param>
178    /// <param name="point"></param>
179    /// <param name="residualSpace"></param>
180    private void LimitResidualSpaceOnRight(BinPacking3D binPacking, Vector3D point, ResidualSpace residualSpace) {
181      if (residualSpace.IsZero()) {
182        return;
183      }
184     
185      var items = binPacking.Items.Select(item => new { Dimension = item.Value, Position = binPacking.Positions[item.Key] })
186                                  .Where(item => OverlapsOnRight(point, residualSpace, item.Position, item.Dimension));
187      if (items.Count() > 0) {
188        foreach (var item in items) {
189          int newWidth = item.Position.X - point.X;
190          if (newWidth <= 0) {
191            residualSpace.SetZero();
192            return;
193          } else if (residualSpace.Width > newWidth) {
194            residualSpace.Width = newWidth;
195          }
196        }
197      }     
198    }
199
200    /// <summary>
201    /// Recalculates the depth of a given residual space.
202    /// The new depth is being limited by any item in front of the residual space or the dimension of the bin shape.
203    /// If the new depth is zero, the whole residual space is being set to zero.
204    /// </summary>
205    /// <param name="binPacking"></param>
206    /// <param name="point"></param>
207    /// <param name="residualSpace"></param>
208    private void LimitResidualSpaceInFront(BinPacking3D binPacking, Vector3D point, ResidualSpace residualSpace) {
209      if (residualSpace.IsZero()) {
210        return;
211      }
212
213      var items = binPacking.Items.Select(item => new { Dimension = item.Value, Position = binPacking.Positions[item.Key] })
214                                  .Where(item => OverlapsInFront(point, residualSpace, item.Position, item.Dimension));
215      if (items.Count() > 0) {
216        foreach (var item in items) {
217          int newDepth = item.Position.Z - point.Z;
218          if (newDepth <= 0) {
219            residualSpace.SetZero();
220            return;
221          } else if (residualSpace.Depth > newDepth) {
222            residualSpace.Depth = newDepth;
223          }
224        }
225      }
226    }
227
228    /// <summary>
229    /// Recalculates the height of a given residual space.
230    /// The new height is being limited by any item above the residual space or the dimension of the bin shape.
231    /// If the new height is zero, the whole residual space is being set to zero.
232    /// </summary>
233    /// <param name="binPacking"></param>
234    /// <param name="point"></param>
235    /// <param name="residualSpace"></param>
236    private void LimitResidualSpaceAbove(BinPacking3D binPacking, Vector3D point, ResidualSpace residualSpace) {
237      if (residualSpace.IsZero()) {
238        return;
239      }
240
241      var items = binPacking.Items.Select(item => new { Dimension = item.Value, Position = binPacking.Positions[item.Key] })
242                                  .Where(item => OverlapsAbove(point, residualSpace, item.Position, item.Dimension));
243      if (items.Count() > 0) {
244        foreach (var item in items) {
245          int newHeight = item.Position.Y - point.Y;
246          if (newHeight <= 0) {
247            residualSpace.SetZero();
248            return;
249          } else if (residualSpace.Height > newHeight) {
250            residualSpace.Height = newHeight;
251          }
252        }
253      }
254    }
255  }
256}
Note: See TracBrowser for help on using the repository browser.