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

Last change on this file since 15554 was 15554, checked in by rhanghof, 21 months ago

#2817:

  • Unittests
  • Bugfixes on the line projection based extreme point creation method
File size: 24.1 KB
Line 
1using HeuristicLab.Common;
2using HeuristicLab.Problems.BinPacking3D.Geometry;
3using HeuristicLab.Problems.BinPacking3D.ResidualSpaceCalculation;
4using System;
5using System.Collections.Generic;
6using System.Linq;
7using System.Text;
8using System.Threading.Tasks;
9
10namespace HeuristicLab.Problems.BinPacking3D.ExtremePointCreation {
11  /// <summary>
12  /// This extreme point creation class uses the line projection based method for creating extreme points.
13  /// This projection method enhances the point based projection method by creating extra extreme points on the intersection points of two items.
14  /// </summary>
15  public class LineProjectionBasedEPCreator : ExtremePointCreator {
16
17    protected override void UpdateExtremePoints(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
18      binPacking.ExtremePoints.Clear();
19
20      foreach (var i in binPacking.Items) {
21        PackingItem it = i.Value;
22        PackingPosition p = binPacking.Positions[i.Key];
23        GenerateNewExtremePointsForItem(binPacking, it, p);
24      }
25    }
26
27    /// <summary>
28    /// Adds a new extreme point an the related residual spaces to a given bin packing.
29    /// - The given position has to be valid.
30    /// - The extreme point does not exist in the bin packing.
31    /// - There must be at minimum one valid residual space. A residual space is invalid if the space is zero.
32    /// </summary>
33    /// <param name="binPacking"></param>
34    /// <param name="position"></param>
35    /// <returns>True = the given point and its related residual spaces were successfully added to the bin packing</returns>
36    protected override bool AddExtremePoint(BinPacking3D binPacking, PackingPosition position) {
37      if (position == null) {
38        return false;
39      }
40
41      if (PointIsInAnyItem(binPacking, new Vector3D(position))) {
42        return false;
43      }
44
45      if (binPacking.ExtremePoints.ContainsKey(position)) {
46        return false;
47      }
48
49      var rs = CalculateResidualSpace(binPacking, new Vector3D(position));
50
51      if (rs.Count() <= 0) {
52        return false;
53      }
54
55      // todo
56      /*
57       ist der extrempunkt im residual space eines anderen muss ueberprueft werden:
58          - ist der andere ep in der luft, kann auch dieser hinzugefuegt werden.
59          - hat der andere ep ein item unterhalb, darf dieser nicht hinzugefuegt werden.
60       -> neu methode basierend auf IsWithinResidualSpaceOfAnotherExtremePoint, die den ep oder rs zurueck gibt, der einen anderen rs einschließt.
61          eventuell gehoert diese logik in den ResidualSpaceCreator.
62      if (LiesOnAnyItem(binPacking, position)) {
63        return false;
64      }*/
65
66      binPacking.ExtremePoints.Add(position, rs);
67      return true;
68    }
69
70    private bool LiesOnAnyItem(BinPacking3D binPacking, PackingPosition position) {
71      if (position.Y == 0) {
72        return true;
73      }
74
75      var items = binPacking.Items.Where(x => {
76        var itemPosition = binPacking.Positions[x.Key];
77        var item = x.Value;
78        int width = itemPosition.Rotated ? item.Depth : item.Width;
79        int depth = itemPosition.Rotated ? item.Width : item.Depth;
80
81        return itemPosition.Y + item.Height == position.Y &&
82               itemPosition.X <= position.X && position.X < itemPosition.X + width &&
83               itemPosition.Z <= position.Z && position.Z < itemPosition.Z + depth;
84      });
85
86      return items.Count() > 0;
87    }
88
89    /// <summary>
90    /// Getnerates the extreme points for a given item.
91    /// It creates extreme points by using a point projection based method and
92    /// creates points by using an edge projection based method.
93    /// </summary>
94    /// <param name="binPacking"></param>
95    /// <param name="newItem"></param>
96    /// <param name="position"></param>
97    protected override void GenerateNewExtremePointsForItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
98      PointProjectionForNewItem(binPacking, newItem, position);
99      EdgeProjectionForNewItem(binPacking, newItem, position);
100    }
101
102    #region Extreme point creation by using a point projection based method
103
104    /// <summary>
105    /// This method creates extreme points by using a point projection based method.
106    /// For each item there will be created three points and each of the points will be projected twice.
107    /// The direction of the projection depends on position of the point.
108    /// </summary>
109    /// <param name="binPacking"></param>
110    /// <param name="newItem"></param>
111    /// <param name="position"></param>
112    private void PointProjectionForNewItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
113      int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
114      int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
115      var binShape = binPacking.BinShape;
116      var sourcePoint = new PackingPosition(position.AssignedBin, position.X + newWidth, position.Y, position.Z);
117      PointProjection(binPacking, sourcePoint, ProjectDown);
118      PointProjection(binPacking, sourcePoint, ProjectBackward);
119
120      sourcePoint = new PackingPosition(position.AssignedBin, position.X, position.Y + newItem.Height, position.Z);
121      PointProjection(binPacking, sourcePoint, ProjectLeft);
122      PointProjection(binPacking, sourcePoint, ProjectBackward);
123
124      sourcePoint = new PackingPosition(position.AssignedBin, position.X, position.Y, position.Z + newDepth);
125      PointProjection(binPacking, sourcePoint, ProjectDown);
126      PointProjection(binPacking, sourcePoint, ProjectLeft);
127    }
128
129
130    /// <summary>
131    /// Projects a given point by using the given projection method to the neares item.
132    /// The given projection method returns a point which lies on a side of the nearest item in the direction.
133    /// </summary>
134    /// <param name="binPacking"></param>
135    /// <param name="position"></param>
136    /// <param name="projectionMethod"></param>
137    private void PointProjection(BinPacking3D binPacking, PackingPosition position, Func<BinPacking3D, Vector3D, Vector3D> projectionMethod) {
138      Vector3D sourcePoint = new Vector3D(position);
139      if (sourcePoint.X < binPacking.BinShape.Width && sourcePoint.Y < binPacking.BinShape.Height && sourcePoint.Z < binPacking.BinShape.Depth) {
140        Vector3D point = projectionMethod?.Invoke(binPacking, sourcePoint);
141        if (point != null) {
142          AddExtremePoint(binPacking, new PackingPosition(position.AssignedBin, point.X, point.Y, point.Z));
143        }
144      }
145    }
146    #endregion
147
148    #region Extreme point creation by using an edge projection based method
149
150    /// <summary>
151    /// This method creates extreme points be projecting the edges of a given item
152    ///   - left
153    ///   - back
154    ///   - down.
155    /// A extreme point will be created, if an edge instersects with an edge of another item.
156    /// </summary>
157    /// <param name="binPacking"></param>
158    /// <param name="newItem"></param>
159    /// <param name="position"></param>
160    private void EdgeProjectionForNewItem(BinPacking3D binPacking, PackingItem newItem, PackingPosition position) {
161      int newWidth = position.Rotated ? newItem.Depth : newItem.Width;
162      int newDepth = position.Rotated ? newItem.Width : newItem.Depth;
163      var binShape = binPacking.BinShape;
164
165      foreach (var ep in GetEpsOnLeft(binPacking, newItem, position)) {
166        AddExtremePoint(binPacking, ep.Key);
167      }
168
169      foreach (var ep in GetEpsBelow(binPacking, newItem, position)) {
170        AddExtremePoint(binPacking, ep.Key);
171      }
172
173      foreach (var ep in GetEpsBehind(binPacking, newItem, position)) {
174        AddExtremePoint(binPacking, ep.Key);
175      }
176    }
177    #endregion
178
179    /// <summary>
180    /// Updates the residual spaces.
181    /// It removes not needed ones.
182    /// A residual space will be removed if the space is a subspace of another one and
183    /// the current one has no item below or both have an item below.
184    /// </summary>
185    /// <param name="binPacking"></param>
186    /// <param name="item"></param>
187    /// <param name="position"></param>
188    protected override void UpdateResidualSpace(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
189    }
190
191    /// <summary>
192    /// Returns true if any item in the bin packing encapsulates the given point
193    /// </summary>
194    /// <param name="binPacking"></param>
195    /// <param name="point"></param>
196    /// <returns></returns>
197    private bool PointIsInAnyItem(BinPacking3D binPacking, Vector3D point) {
198      foreach (var item in binPacking.Items) {
199        PackingPosition position = binPacking.Positions[item.Key];
200        var depth = position.Rotated ? item.Value.Width : item.Value.Depth;
201        var width = position.Rotated ? item.Value.Depth : item.Value.Width;
202        if (position.X <= point.X && point.X < position.X + width &&
203            position.Y <= point.Y && point.Y < position.Y + item.Value.Height &&
204            position.Z <= point.Z && point.Z < position.Z + depth) {
205          return true;
206        }
207      }
208      return false;
209    }
210
211    /// <summary>
212    /// Returns true if an item is in the residual space of a given extrem point
213    /// </summary>
214    /// <param name="rs">KeyValuePair with the position of the extreme point and the size of the residual space</param>
215    /// <param name="item">Given Item</param>
216    /// <param name="position">Given position</param>
217    /// <returns></returns>
218    private bool ItemIsInRs(KeyValuePair<PackingPosition, ResidualSpace> rs, PackingItem item, PackingPosition position) {
219      return GetVertices(item, position).Where(pos => pos.IsInside(rs.Key, rs.Value)).Any();
220    }
221
222    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsBelow(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
223      return binPacking.Items.Select(x => new {
224        Item = x.Value,
225        Position = binPacking.Positions[x.Key]
226      }).Where(x => x.Position.Y < position.Y)
227          .Select(x => Tuple.Create(x.Position, x.Item));
228    }
229
230    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsBehind(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
231      return binPacking.Items.Select(x => new {
232        Item = x.Value,
233        Position = binPacking.Positions[x.Key]
234      }).Where(x => x.Position.Z < position.Z)
235          .Select(x => Tuple.Create(x.Position, x.Item));
236    }
237
238    protected IEnumerable<Tuple<PackingPosition, PackingItem>> GetItemsOnLeft(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
239      return binPacking.Items.Select(x => new {
240        Item = x.Value,
241        Position = binPacking.Positions[x.Key]
242      }).Where(x => x.Position.X < position.X)
243          .Select(x => Tuple.Create(x.Position, x.Item));
244    }
245
246    /// <summary>
247    /// Returns the extreme points and its related residual spaces on the left side of an given item.
248    /// This extreme points are being created by intersecting two edges on the left side of the given item
249    /// (left - in front, left - on top) with all edges on the right side of all other items int the bin packing.
250    /// </summary>
251    /// <param name="item"></param>
252    /// <param name="position"></param>
253    /// <returns></returns>
254    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsOnLeft(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
255      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
256      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsOnLeft(binPacking, item, position);
257      var edges = GetProjectionEdgesOnLeft(item, position);
258
259      foreach (var otherItem in items) {
260        if (position.Equals(otherItem.Item1)) {
261          continue;
262        }
263
264        var otherItemEdges = GetEdgesOnRight(otherItem.Item2, otherItem.Item1);
265        // left - in front
266        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(1, 0, 0))) {
267          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
268            // As this edge has a vertical direction, every point of intersection won't have an item below.
269            // So finally it is being projected down.
270            var point = ProjectDown(binPacking, ProjectLeft(binPacking, ep));
271            var residualSpaces = CalculateResidualSpace(binPacking, point);
272            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
273            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
274              eps.Add(newExtremePoint, residualSpaces);
275            }
276          }
277        }
278
279        // left - on top
280        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(1, 0, 0))) {
281          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
282            var point = ProjectLeft(binPacking, ep);
283            var residualSpaces = CalculateResidualSpace(binPacking, point);
284            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
285            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
286              eps.Add(newExtremePoint, residualSpaces);
287            }
288          }
289        }
290      }
291      return eps;
292    }
293
294
295    /// <summary>
296    /// Returns the extreme points and its related residual spaces below of an given item.
297    /// This extreme points are being created by intersecting two edges below of the given item
298    /// (below - in front, below - right) with all edges on top side of all other items int the bin packing.
299    /// </summary>
300    /// <param name="item"></param>
301    /// <param name="position"></param>
302    /// <returns></returns>
303    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsBelow(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
304      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
305      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsBelow(binPacking, position);
306      var edges = GetProjectionEdgesBelow(item, position);
307
308      foreach (var otherItem in items) {
309        if (position.Equals(otherItem.Item1)) {
310          continue;
311        }
312
313        var otherItemEdges = GetEdgesOnTop(otherItem.Item2, otherItem.Item1);
314        // below - in front
315        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(0, 1, 0))) {
316          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
317            var point = ProjectDown(binPacking, ep);
318            var residualSpaces = CalculateResidualSpace(binPacking, point);
319            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
320            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
321              eps.Add(newExtremePoint, residualSpaces);
322            }
323          }
324        }
325
326        // below - right
327        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(0, 1, 0))) {
328          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
329            var point = ProjectDown(binPacking, ep);
330            var residualSpaces = CalculateResidualSpace(binPacking, point);
331            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
332            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
333              eps.Add(newExtremePoint, residualSpaces);
334            }
335          }
336        }
337      }
338      return eps;
339    }
340
341    /// <summary>
342    /// Returns the extreme points and its related residual spaces below of an given item.
343    /// This extreme points are being created by intersecting two edges below of the given item
344    /// (right - behind, on top - behind) with all edges on top side of all other items int the bin packing.
345    /// </summary>
346    /// <param name="item"></param>
347    /// <param name="position"></param>
348    /// <returns></returns>
349    private IDictionary<PackingPosition, IEnumerable<ResidualSpace>> GetEpsBehind(BinPacking3D binPacking, PackingItem item, PackingPosition position) {
350      var eps = new SortedList<PackingPosition, IEnumerable<ResidualSpace>>();
351      IEnumerable<Tuple<PackingPosition, PackingItem>> items = GetItemsBehind(binPacking, position);
352      var edges = GetProjectionEdgesBehind(item, position);
353
354      foreach (var otherItem in items) {
355        if (position.Equals(otherItem.Item1)) {
356          continue;
357        }
358
359        var otherItemEdges = GetEdgesInFront(otherItem.Item2, otherItem.Item1);
360        // right - behind
361        foreach (var ep in IntersectionsForItem(edges[0], otherItemEdges, new Vector3D(0, 0, 1))) {
362          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
363            // As this edge has a vertical direction, every point of intersection won't have an item below.
364            // So finally it is being projected down.
365            var point = ProjectDown(binPacking, ProjectBackward(binPacking, ep));
366            var residualSpaces = CalculateResidualSpace(binPacking, point);
367            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
368            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
369              eps.Add(newExtremePoint, residualSpaces);
370            }
371          }
372        }
373
374        // on top - behind
375        foreach (var ep in IntersectionsForItem(edges[1], otherItemEdges, new Vector3D(0, 0, 1))) {
376          if (ep.X < binPacking.BinShape.Width && ep.Y < binPacking.BinShape.Height && ep.Z < binPacking.BinShape.Depth) {
377            var point = ProjectBackward(binPacking, ep);
378            var residualSpaces = CalculateResidualSpace(binPacking, point);
379            var newExtremePoint = point.ToPackingPosition(position.AssignedBin);
380            if (residualSpaces.Count() > 0 && !eps.ContainsKey(newExtremePoint)) {
381              eps.Add(newExtremePoint, residualSpaces);
382            }
383          }
384        }
385      }
386      return eps;
387    }
388
389    #region Methods for getting the edges for items
390
391    /// <summary>
392    /// Returns an array of packing position which represents the vertices of an item.
393    /// The position of a vertex in the array is mapped to an item as followed:
394    ///      4----------5
395    ///     /|         /|
396    ///    / |        / |
397    ///   /  0-------/--1
398    ///  6--/-------7  /
399    ///  | /        | /
400    ///  |/         |/
401    ///  2----------3
402    /// 
403    ///  0 = (0,0,0)
404    /// </summary>
405    /// <param name="item"></param>
406    /// <param name="position"></param>
407    /// <returns></returns>
408    private Vector3D[] GetVertices(PackingItem item, PackingPosition position) {
409      int width = position.Rotated ? item.Depth : item.Width;
410      int depth = position.Rotated ? item.Width : item.Depth;
411      return new Vector3D[] {
412        new Vector3D(position.X + 0,     position.Y + 0,           position.Z + 0), // (0,0,0)
413        new Vector3D(position.X + width, position.Y + 0,           position.Z + 0), // (x,0,0)
414        new Vector3D(position.X + 0,     position.Y + 0,           position.Z + depth), // (0,0,z)
415        new Vector3D(position.X + width, position.Y + 0,           position.Z + depth), // (x,0,z)
416
417        new Vector3D(position.X + 0,     position.Y + item.Height, position.Z + 0), // (0,y,0)
418        new Vector3D(position.X + width, position.Y + item.Height, position.Z + 0), // (x,y,0)
419        new Vector3D(position.X + 0,     position.Y + item.Height, position.Z + depth), // (0,y,z)
420        new Vector3D(position.X + width, position.Y + item.Height, position.Z + depth), //(x,y,z)
421      };
422    }
423
424    private Edge3D[] GetProjectionEdgesOnLeft(PackingItem item, PackingPosition position) {
425      Vector3D[] points = GetVertices(item, position);
426
427      return new Edge3D[] {
428        new Edge3D(points[2], points[6]),
429        new Edge3D(points[6], points[4])
430      };
431    }
432
433    private Edge3D[] GetProjectionEdgesBelow(PackingItem item, PackingPosition position) {
434      Vector3D[] points = GetVertices(item, position);
435
436      return new Edge3D[] {
437        new Edge3D(points[2], points[3]),
438        new Edge3D(points[3], points[1])
439      };
440    }
441
442    private Edge3D[] GetProjectionEdgesBehind(PackingItem item, PackingPosition position) {
443      Vector3D[] points = GetVertices(item, position);
444
445      return new Edge3D[] {
446        new Edge3D(points[1], points[5]),
447        new Edge3D(points[5], points[4])
448      };
449    }
450
451    /// <summary>
452    /// Returns an array of edges which contains all edges of the rigth side of an given item.
453    /// </summary>
454    /// <param name="item"></param>
455    /// <param name="position"></param>
456    /// <returns></returns>
457    private Edge3D[] GetEdgesOnRight(PackingItem item, PackingPosition position) {
458      Vector3D[] points = GetVertices(item, position);
459
460      return new Edge3D[] {
461        new Edge3D(points[1], points[5]),
462        new Edge3D(points[5], points[7]),
463        new Edge3D(points[7], points[3]),
464        new Edge3D(points[3], points[1])
465      };
466    }
467
468    /// <summary>
469    /// Returns an array of edges which contains all edges on the top of an given item.
470    /// </summary>
471    /// <param name="item"></param>
472    /// <param name="position"></param>
473    /// <returns></returns>
474    private Edge3D[] GetEdgesOnTop(PackingItem item, PackingPosition position) {
475      Vector3D[] points = GetVertices(item, position);
476
477      return new Edge3D[] {
478        new Edge3D(points[4], points[5]),
479        new Edge3D(points[5], points[7]),
480        new Edge3D(points[7], points[6]),
481        new Edge3D(points[6], points[4])
482      };
483    }
484
485    /// <summary>
486    /// Returns an array of edges which contains all edges in front of an given item.
487    /// </summary>
488    /// <param name="item"></param>
489    /// <param name="position"></param>
490    /// <returns></returns>
491    private Edge3D[] GetEdgesInFront(PackingItem item, PackingPosition position) {
492      Vector3D[] points = GetVertices(item, position);
493
494      return new Edge3D[] {
495        new Edge3D(points[2], points[3]),
496        new Edge3D(points[3], points[7]),
497        new Edge3D(points[7], points[6]),
498        new Edge3D(points[6], points[2])
499      };
500    }
501
502    #endregion
503
504
505    #region Intersections
506
507    /// <summary>
508    /// Returns a collection of points where a given edge (projectedEdge) intersects with other edges.
509    /// The given edge (projectedEdge) will be projected by using the given vector direction
510    /// and a edge of the given edge collection.
511    /// The returned collecten can be empty.
512    /// </summary>
513    /// <param name="projectedEdge"></param>
514    /// <param name="edges"></param>
515    /// <param name="direction"></param>
516    /// <returns></returns>
517    private IEnumerable<Vector3D> IntersectionsForItem(Edge3D projectedEdge, Edge3D[] edges, Vector3D direction = null) {
518      IList<Vector3D> eps = new List<Vector3D>();
519      foreach (var edge in edges) {
520        Edge3D e = projectedEdge;
521        if (direction != null) {
522          if (direction.X != 0) {
523            e.Start.X = edge.Start.X;
524            e.End.X = edge.End.X;
525          } else if (direction.Y != 0) {
526            e.Start.Y = edge.Start.Y;
527            e.End.Y = edge.End.Y;
528          } else if (direction.Z != 0) {
529            e.Start.Z = edge.Start.Z;
530            e.End.Z = edge.End.Z;
531          }
532        }
533
534        var ep = edge.Intersects(e);
535        if (ep != null) {
536          eps.Add(ep);
537        }
538      }
539      return eps as IEnumerable<Vector3D>;
540    }
541
542
543
544    #endregion
545
546    /// <summary>
547    /// Calculates the residual spaces for an extreme point.
548    /// </summary>
549    /// <param name="binPacking"></param>
550    /// <param name="pos"></param>
551    /// <returns></returns>
552    protected override IEnumerable<ResidualSpace> CalculateResidualSpace(BinPacking3D binPacking, Vector3D pos) {
553      return ResidualSpaceCalculatorFactory.CreateCalculator().CalculateResidualSpaces(binPacking, pos);
554    }
555  }
556
557
558}
Note: See TracBrowser for help on using the repository browser.