/// <summary> /// metodo per stabilire se è possibile /// trovare una posizione in cui nestare /// un nuovo item /// </summary> /// <param name="temporaryBin"></param> /// <param name="temporaryItem"></param> /// <returns></returns> public bool IsBestPositionFound(Bin <Tuple> temporaryBin, Item temporaryItem) { SetFeasiblePoints(temporaryBin, temporaryItem); //se il bin non contiene punti if (temporaryBin.Points.Count == 0) { return(false); } else if (temporaryBin.Points.Count == 1 && //se il bin contiene 1 solo punto e quel punto è (0,0) temporaryBin.Points.ElementAt(0).Pposition == 0 && temporaryBin.Points.ElementAt(0).Qposition == 0) { var nestedItem = new NestedItem(temporaryItem) { BLpPosition = 0, BLqPosition = 0, BRpPosition = temporaryItem.Width, BRqPosition = 0, TLpPosition = 0, TLqPosition = temporaryItem.Height }; temporaryBin.NestedItems = new List <NestedItem>(); temporaryBin.NestedItems.Add(nestedItem); HandleOperationsPostNestedItem(temporaryBin, temporaryItem, temporaryBin.Points.ElementAt(0), nestedItem); return(true); } else if (temporaryBin.Points.Count > 1)//se il bin contiene n punti { foreach (var feasiblePoint in temporaryBin.Points) { if (!feasiblePoint.IsUsed) { //assegno le coordinate di partenza al nuovo item da nestare, poi inzio a muoverlo NestedItem newNestedItem = new NestedItem(temporaryItem) { BLpPosition = feasiblePoint.Pposition, BLqPosition = feasiblePoint.Qposition, BRpPosition = feasiblePoint.Pposition + temporaryItem.Width, BRqPosition = feasiblePoint.Qposition, TLpPosition = feasiblePoint.Pposition, TLqPosition = feasiblePoint.Qposition + temporaryItem.Height }; feasiblePoint.HatchedArea = GetHatchedArea(feasiblePoint, newNestedItem, temporaryBin, temporaryItem); } } //trovo la tupla con lo scarto minore tra quelle ancora disponibili //(Where(x => x.HatchedArea >= 0) filtra solo le tuple con hatched area = 0) Tuple minHatchedAreaTuple = temporaryBin.Points.Where(x => x.IsUsed == false && x.HatchedArea >= 0) .OrderBy(x => x.HatchedArea) .FirstOrDefault(); //se non riesco a trovare la tupla, vuol dire che le tuple sono finite if (minHatchedAreaTuple == null) { return(false); } //controllo se ho più tuple che hanno lo stesso scarto (il minore) IList <Tuple> minHatchedAreaPoints = new List <Tuple>(); foreach (var point in temporaryBin.Points) { if (point.HatchedArea == minHatchedAreaTuple.HatchedArea && !point.IsUsed) { minHatchedAreaPoints.Add(point); } } if (minHatchedAreaPoints.Count == 1) { var minHatchedAreaPoint = minHatchedAreaPoints.ElementAt(0); var nestedItem = new NestedItem(temporaryItem) { BLpPosition = minHatchedAreaPoint.PfinalPosition, BLqPosition = minHatchedAreaPoint.QfinalPosition, BRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryItem.Width, BRqPosition = minHatchedAreaPoint.QfinalPosition, TLpPosition = minHatchedAreaPoint.PfinalPosition, TLqPosition = minHatchedAreaPoint.QfinalPosition + temporaryItem.Height }; temporaryBin.NestedItems.Add(nestedItem); HandleOperationsPostNestedItem(temporaryBin, temporaryItem, minHatchedAreaPoint, nestedItem); return(true); } else if (minHatchedAreaPoints.Count > 1) { Tuple minCoordinatePoint = ApplyRule(minHatchedAreaPoints); var nestedItem = new NestedItem(temporaryItem) { BLpPosition = minCoordinatePoint.PfinalPosition, BLqPosition = minCoordinatePoint.QfinalPosition, BRpPosition = minCoordinatePoint.PfinalPosition + temporaryItem.Width, BRqPosition = minCoordinatePoint.QfinalPosition, TLpPosition = minCoordinatePoint.PfinalPosition, TLqPosition = minCoordinatePoint.QfinalPosition + temporaryItem.Height }; temporaryBin.NestedItems.Add(nestedItem); HandleOperationsPostNestedItem(temporaryBin, temporaryItem, minCoordinatePoint, nestedItem); return(true); } } return(false); }
/// <summary> /// metodo per gestire le operazioni post item nestato /// </summary> /// <param name="temporaryBin"></param> /// <param name="temporaryItem"></param> /// <param name="point"></param> private void HandleOperationsPostNestedItem(Bin <Tuple> temporaryBin, Item temporaryItem, Tuple point, NestedItem nestedItem) { //setto il punto ad usato, per recuparare il punto dalla lista uso l'id var matchingPoint = temporaryBin.Points.Where(x => x.Pposition == point.Pposition && x.Qposition == point.Qposition) .First(); matchingPoint.IsUsed = true; //controllo se non è più possibile usare dei punti in quanto sono stati "coperti" dal nuovo item nestato foreach (var p in temporaryBin.Points) { if (p.Pposition >= nestedItem.BLpPosition && p.Pposition < nestedItem.BRpPosition && p.Qposition >= nestedItem.BLqPosition && p.Qposition < nestedItem.TLqPosition) { p.IsUsed = true; } } //controllo se il primo nuovo punto (TL) da aggiungere è già presente nella lista temporaryBin.Points Tuple pointFound = temporaryBin.Points.Where(x => x.Pposition == point.PfinalPosition && x.Qposition == point.QfinalPosition + temporaryItem.Height && x.IsUsed == false).FirstOrDefault(); //definisco il primo nuovo punto var firstPoint = new Tuple() { Pposition = point.PfinalPosition, Qposition = point.QfinalPosition + temporaryItem.Height, IsUsed = false }; //controllo se il primo nuovo punto è idoneo ad essere aggiunto perché //potrebbe essere erroneaemente creato sul lato di un item già esistente bool isPointLyingOnItemSide = false; foreach (var ni in temporaryBin.NestedItems) { if (firstPoint.Qposition == ni.BLqPosition && firstPoint.Pposition >= ni.BLpPosition && firstPoint.Pposition <= ni.BRpPosition) { isPointLyingOnItemSide = true; break; } } //aggiungo il primo nuovo punto if (pointFound == null && !isPointLyingOnItemSide) { temporaryBin.Points.Add(firstPoint); } else { pointFound = null; } isPointLyingOnItemSide = false; //controllo se il secondo nuovo punto (BR) da aggiungere è già presente nella lista temporaryBin.Points pointFound = temporaryBin.Points.Where(x => x.Pposition == point.PfinalPosition + temporaryItem.Width && x.Qposition == point.QfinalPosition).FirstOrDefault(); //definisco il secondo nuovo punto var secondPoint = new Tuple() { Pposition = point.PfinalPosition + temporaryItem.Width, Qposition = point.QfinalPosition, IsUsed = false }; //controllo se il secondo nuovo punto è idoneo ad essere aggiunto perché //potrebbe essere erroneaemente creato sul lato di un item già esistente foreach (var ni in temporaryBin.NestedItems) { if (secondPoint.Pposition == ni.BLpPosition && secondPoint.Qposition >= ni.BLqPosition && secondPoint.Qposition <= ni.TLqPosition) { isPointLyingOnItemSide = true; break; } } //aggiungo il secondo nuovo punto if (pointFound == null && !isPointLyingOnItemSide) { temporaryBin.Points.Add(secondPoint); } //setto item a nestato temporaryItem.IsRemoved = true; }