Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2817-BinPackingSpeedup/HeuristicLab.Problems.BinPacking/3.3/3D/ExtremePointCreation/LineProjectionBasedEPCreator.cs

Last change on this file was 15731, checked in by rhanghof, 6 years ago

#2817:

  • Added a new packer.
  • Enhanced the material types.
  • Added extreme point pruning for layer support in the extrem point creators.
  • BinPacking3D: Added a graph for calculating weigth distribution of the items.
File size: 18.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using HeuristicLab.Common;
23using HeuristicLab.Problems.BinPacking3D.Geometry;
24using HeuristicLab.Problems.BinPacking3D.ResidualSpaceCalculation;
25using System;
26using System.Collections.Generic;
27using System.Linq;
28using System.Text;
29using System.Threading.Tasks;
30using System.Collections.Concurrent;
31
32namespace HeuristicLab.Problems.BinPacking3D.ExtremePointCreation {
33  /// <summary>
34  /// This extreme point creation class uses the line projection based method for creating extreme points.
35  /// This projection method enhances the point based projection method by creating extra extreme points on the intersection points of two items.
36  /// </summary>
37  public class LineProjectionBasedEPCreator : PointProjectionBasedEPCreator {
38   
39
40
41    /// <summary>
42    /// Getnerates the extreme points for a given item.
43    /// It creates extreme points by using a point projection based method and
44    /// creates points by using an edge projection based method.
45    /// </summary>
46    /// <param name="binPacking"></param>
47    /// <param name="newItem"></param>
48    /// <param name="position"></param>
49    protected override void GenerateNewExtremePointsForItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
50      PointProjectionForNewItem(binPacking, newItem, position);
51      EdgeProjectionForNewItem(binPacking, newItem, position);
52    }
53   
54
55    #region Extreme point creation by using an edge projection based method
56
57    /// <summary>
58    /// This method creates extreme points be projecting the edges of a given item
59    ///   - left
60    ///   - back
61    ///   - down.
62    /// A extreme point will be created, if an edge instersects with an edge of another item.
63    /// </summary>
64    /// <param name="binPacking"></param>
65    /// <param name="newItem"></param>
66    /// <param name="position"></param>
67    private void EdgeProjectionForNewItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
68      int newWidth = newItem.Width;
69      int newDepth = newItem.Depth;
70      var binShape = binPacking.BinShape;
71
72      foreach (var ep in GetEpsOnLeft(binPacking, newItem, position)) {
73        AddExtremePoint(binPacking, ep.Key);
74      }
75
76      foreach (var ep in GetEpsBelow(binPacking, newItem, position)) {
77        AddExtremePoint(binPacking, ep.Key);
78      }
79
80      foreach (var ep in GetEpsBehind(binPacking, newItem, position)) {
81        AddExtremePoint(binPacking, ep.Key);
82      }
83    }
84    #endregion
85   
86
87    /// <summary>
88    /// Returns true if any item in the bin packing encapsulates the given point
89    /// </summary>
90    /// <param name="binPacking"></param>
91    /// <param name="point"></param>
92    /// <returns></returns>
93    private bool PointIsInAnyItem(BinPacking3D binPacking, Vector3D point) {
94      foreach (var item in binPacking.Items) {
95        PackingPosition position = binPacking.Positions[item.Key];
96        var depth = item.Value.Depth;
97        var width = item.Value.Width;
98        if (position.X <= point.X && point.X < position.X + width &&
99            position.Y <= point.Y && point.Y < position.Y + item.Value.Height &&
100            position.Z <= point.Z && point.Z < position.Z + depth) {
101          return true;
102        }
103      }
104      return false;
105    }
106
107    /// <summary>
108    /// Returns true if an item is in the residual space of a given extrem point
109    /// </summary>
110    /// <param name="rs">KeyValuePair with the position of the extreme point and the size of the residual space</param>
111    /// <param name="item">Given Item</param>
112    /// <param name="position">Given position</param>
113    /// <returns></returns>
114    private bool ItemIsInRs(KeyValuePair<PackingPosition, ResidualSpace> rs, PackingItem item, PackingPosition position) {
115      return GetVertices(item, position).Where(pos => pos.IsInside(rs.Key, rs.Value)).Any();
116    }
117
118    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsBelow(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
119      return binPacking.Items.Select(x => new {
120        Item = x.Value,
121        Position = binPacking.Positions[x.Key]
122      }).Where(x => x.Position.Y < position.Y)
123          .Select(x => Tuple.Create(x.Position, x.Item));
124    }
125
126    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsBehind(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
127      return binPacking.Items.Select(x => new {
128        Item = x.Value,
129        Position = binPacking.Positions[x.Key]
130      }).Where(x => x.Position.Z < position.Z)
131          .Select(x => Tuple.Create(x.Position, x.Item));
132    }
133
134    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsOnLeft(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
135      return binPacking.Items.Select(x => new {
136        Item = x.Value,
137        Position = binPacking.Positions[x.Key]
138      }).Where(x => x.Position.X < position.X)
139          .Select(x => Tuple.Create(x.Position, x.Item));
140    }
141
142    /// <summary>
143    /// Returns the extreme points and its related residual spaces on the left side of an given item.
144    /// This extreme points are being created by intersecting two edges on the left side of the given item
145    /// (left - in front, left - on top) with all edges on the right side of all other items int the bin packing.
146    /// </summary>
147    /// <param name="item"></param>
148    /// <param name="position"></param>
149    /// <returns></returns>
150    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsOnLeft(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
151      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
152      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsOnLeft(binPacking, item, position);
153      var edges = GetProjectionEdgesOnLeft(item, position);
154
155      foreach (var otherItem in items) {
156        if (position.Equals(otherItem.Item1)) {
157          continue;
158        }
159
160        var otherItemEdges = GetEdgesOnRight(otherItem.Item2, otherItem.Item1);
161        // left - in front
162        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(1, 0, 0))) {
163          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
164            // As this edge has a vertical direction, every point of intersection won't have an item below.
165            // So finally it is being projected down.
166            var point = ProjectDown(binPacking, ProjectLeft(binPacking, ep));
167            var residualSpaces = CalculateResidualSpace(binPacking, point);
168            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
169            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
170              eps.Add(newExtremePoint, residualSpaces);
171            }
172          }
173        }
174
175        // left - on top
176        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(1, 0, 0))) {
177          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
178            var point = ProjectLeft(binPacking, ep);
179            var residualSpaces = CalculateResidualSpace(binPacking, point);
180            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
181            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
182              eps.Add(newExtremePoint, residualSpaces);
183            }
184          }
185        }
186      }
187      return eps;
188    }
189
190
191    /// <summary>
192    /// Returns the extreme points and its related residual spaces below of an given item.
193    /// This extreme points are being created by intersecting two edges below of the given item
194    /// (below - in front, below - right) with all edges on top side of all other items int the bin packing.
195    /// </summary>
196    /// <param name="item"></param>
197    /// <param name="position"></param>
198    /// <returns></returns>
199    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsBelow(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
200      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
201      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsBelow(binPacking, position);
202      var edges = GetProjectionEdgesBelow(item, position);
203
204      foreach (var otherItem in items) {
205        if (position.Equals(otherItem.Item1)) {
206          continue;
207        }
208
209        var otherItemEdges = GetEdgesOnTop(otherItem.Item2, otherItem.Item1);
210        // below - in front
211        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(0, 1, 0))) {
212          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
213            var point = ProjectDown(binPacking, ep);
214            var residualSpaces = CalculateResidualSpace(binPacking, point);
215            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
216            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
217              eps.Add(newExtremePoint, residualSpaces);
218            }
219          }
220        }
221
222        // below - right
223        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(0, 1, 0))) {
224          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
225            var point = ProjectDown(binPacking, ep);
226            var residualSpaces = CalculateResidualSpace(binPacking, point);
227            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
228            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
229              eps.Add(newExtremePoint, residualSpaces);
230            }
231          }
232        }
233      }
234      return eps;
235    }
236
237    /// <summary>
238    /// Returns the extreme points and its related residual spaces below of an given item.
239    /// This extreme points are being created by intersecting two edges below of the given item
240    /// (right - behind, on top - behind) with all edges on top side of all other items int the bin packing.
241    /// </summary>
242    /// <param name="item"></param>
243    /// <param name="position"></param>
244    /// <returns></returns>
245    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsBehind(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
246      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
247      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsBehind(binPacking, position);
248      var edges = GetProjectionEdgesBehind(item, position);
249
250      foreach (var otherItem in items) {
251        if (position.Equals(otherItem.Item1)) {
252          continue;
253        }
254
255        var otherItemEdges = GetEdgesInFront(otherItem.Item2, otherItem.Item1);
256        // right - behind
257        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(0, 0, 1))) {
258          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
259            // As this edge has a vertical direction, every point of intersection won't have an item below.
260            // So finally it is being projected down.
261            var point = ProjectDown(binPacking, ProjectBackward(binPacking, ep));
262            var residualSpaces = CalculateResidualSpace(binPacking, point);
263            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
264            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
265              eps.Add(newExtremePoint, residualSpaces);
266            }
267          }
268        }
269
270        // on top - behind
271        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(0, 0, 1))) {
272          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
273            var point = ProjectBackward(binPacking, ep);
274            var residualSpaces = CalculateResidualSpace(binPacking, point);
275            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
276            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
277              eps.Add(newExtremePoint, residualSpaces);
278            }
279          }
280        }
281      }
282      return eps;
283    }
284
285    #region Methods for getting the edges for items
286
287    /// <summary>
288    /// Returns an array of packing position which represents the vertices of an item.
289    /// The position of a vertex in the array is mapped to an item as followed:
290    ///      4----------5
291    ///     /|         /|
292    ///    / |        / |
293    ///   /  0-------/--1
294    ///  6--/-------7  /
295    ///  | /        | /
296    ///  |/         |/
297    ///  2----------3
298    /// 
299    ///  0 = (0,0,0)
300    /// </summary>
301    /// <param name="item"></param>
302    /// <param name="position"></param>
303    /// <returns></returns>
304    private Vector3D[] GetVertices(PackingItem item, PackingPosition position) {
305      int width = item.Width;
306      int depth = item.Depth;
307      return new Vector3D[] {
308        new Vector3D(position.X + 0,     position.Y + 0,           position.Z + 0), // (0,0,0)
309        new Vector3D(position.X + width, position.Y + 0,           position.Z + 0), // (x,0,0)
310        new Vector3D(position.X + 0,     position.Y + 0,           position.Z + depth), // (0,0,z)
311        new Vector3D(position.X + width, position.Y + 0,           position.Z + depth), // (x,0,z)
312
313        new Vector3D(position.X + 0,     position.Y + item.Height, position.Z + 0), // (0,y,0)
314        new Vector3D(position.X + width, position.Y + item.Height, position.Z + 0), // (x,y,0)
315        new Vector3D(position.X + 0,     position.Y + item.Height, position.Z + depth), // (0,y,z)
316        new Vector3D(position.X + width, position.Y + item.Height, position.Z + depth), //(x,y,z)
317      };
318    }
319
320    private Edge3D[] GetProjectionEdgesOnLeft(PackingItem item, PackingPosition position) {
321      Vector3D[] points = GetVertices(item, position);
322
323      return new Edge3D[] {
324        new Edge3D(points[2], points[6]),
325        new Edge3D(points[6], points[4])
326      };
327    }
328
329    private Edge3D[] GetProjectionEdgesBelow(PackingItem item, PackingPosition position) {
330      Vector3D[] points = GetVertices(item, position);
331
332      return new Edge3D[] {
333        new Edge3D(points[2], points[3]),
334        new Edge3D(points[3], points[1])
335      };
336    }
337
338    private Edge3D[] GetProjectionEdgesBehind(PackingItem item, PackingPosition position) {
339      Vector3D[] points = GetVertices(item, position);
340
341      return new Edge3D[] {
342        new Edge3D(points[1], points[5]),
343        new Edge3D(points[5], points[4])
344      };
345    }
346
347    /// <summary>
348    /// Returns an array of edges which contains all edges of the rigth side of an given item.
349    /// </summary>
350    /// <param name="item"></param>
351    /// <param name="position"></param>
352    /// <returns></returns>
353    private Edge3D[] GetEdgesOnRight(PackingItem item, PackingPosition position) {
354      Vector3D[] points = GetVertices(item, position);
355
356      return new Edge3D[] {
357        new Edge3D(points[1], points[5]),
358        new Edge3D(points[5], points[7]),
359        new Edge3D(points[7], points[3]),
360        new Edge3D(points[3], points[1])
361      };
362    }
363
364    /// <summary>
365    /// Returns an array of edges which contains all edges on the top of an given item.
366    /// </summary>
367    /// <param name="item"></param>
368    /// <param name="position"></param>
369    /// <returns></returns>
370    private Edge3D[] GetEdgesOnTop(PackingItem item, PackingPosition position) {
371      Vector3D[] points = GetVertices(item, position);
372
373      return new Edge3D[] {
374        new Edge3D(points[4], points[5]),
375        new Edge3D(points[5], points[7]),
376        new Edge3D(points[7], points[6]),
377        new Edge3D(points[6], points[4])
378      };
379    }
380
381    /// <summary>
382    /// Returns an array of edges which contains all edges in front of an given item.
383    /// </summary>
384    /// <param name="item"></param>
385    /// <param name="position"></param>
386    /// <returns></returns>
387    private Edge3D[] GetEdgesInFront(PackingItem item, PackingPosition position) {
388      Vector3D[] points = GetVertices(item, position);
389
390      return new Edge3D[] {
391        new Edge3D(points[2], points[3]),
392        new Edge3D(points[3], points[7]),
393        new Edge3D(points[7], points[6]),
394        new Edge3D(points[6], points[2])
395      };
396    }
397
398    #endregion
399
400
401    #region Intersections
402
403    /// <summary>
404    /// Returns a collection of points where a given edge (projectedEdge) intersects with other edges.
405    /// The given edge (projectedEdge) will be projected by using the given vector direction
406    /// and a edge of the given edge collection.
407    /// The returned collecten can be empty.
408    /// </summary>
409    /// <param name="projectedEdge"></param>
410    /// <param name="edges"></param>
411    /// <param name="direction"></param>
412    /// <returns></returns>
413    private IEnumerable<Vector3D> IntersectionsForItem(Edge3D projectedEdge, Edge3D[] edges, Vector3D direction = null) {
414      IList<Vector3D> eps = new List<Vector3D>();
415      foreach (var edge in edges) {
416        Edge3D e = projectedEdge;
417        if (direction != null) {
418          if (direction.X != 0) {
419            e.Start.X = edge.Start.X;
420            e.End.X = edge.End.X;
421          } else if (direction.Y != 0) {
422            e.Start.Y = edge.Start.Y;
423            e.End.Y = edge.End.Y;
424          } else if (direction.Z != 0) {
425            e.Start.Z = edge.Start.Z;
426            e.End.Z = edge.End.Z;
427          }
428        }
429
430        var ep = edge.Intersects(e);
431        if (ep != null) {
432          eps.Add(ep);
433        }
434      }
435
436      return eps as IEnumerable<Vector3D>;
437    }
438    #endregion
439   
440  }
441}
Note: See TracBrowser for help on using the repository browser.