Example #1
0
 /// <summary>
 /// metodo per controllare se nestare un nuovo item in un certo punto
 /// comporta delle sovrapposizioni tra nuovo item e item già in soluzione
 /// </summary>
 /// <param name="newPricedItem"></param>
 /// <param name="temporaryBin"></param>
 /// <returns></returns>
 bool IsOverlappingOk(PricedItem newPricedItem, Bin <Tuple> temporaryBin)
 {
     foreach (var pricedItem in temporaryBin.PricedItems)
     {
         //se c'è overlap
         if (pricedItem.BLpPosition < newPricedItem.BRpPosition && pricedItem.BRpPosition > newPricedItem.BLpPosition &&
             pricedItem.BLqPosition < newPricedItem.TLqPosition && pricedItem.TLqPosition > newPricedItem.BLqPosition)
         {
             return(false);
         }
     }
     return(true);
 }
Example #2
0
        /// <summary>
        /// metodo che spinge il più in basso possibile
        /// il nuovo item da nestare
        /// </summary>
        /// <param name="feasiblePoint"></param>
        /// <param name="temporaryBin"></param>
        /// <param name="temporaryItem"></param>
        /// <param name="newNestedItem"></param>
        /// <returns></returns>
        private IList <PricedItem> PushItemDown(Bin <Tuple> temporaryBin, PricedItem newPricedItem, Tuple feasiblePoint)
        {
            //lista delle intersezioni tra item nuovo e item già in soluzione
            IList <PricedItem> intersectedPricedItems = new List <PricedItem>();

            foreach (var pricedItem in temporaryBin.PricedItems)
            {
                //cerco intersezioni verticali tra nuovo item e item già in soluzione (HO TOLTO UGUALE DESTRA -> CHECK)
                if (((newPricedItem.BLpPosition >= pricedItem.BLpPosition && newPricedItem.BLpPosition < pricedItem.BRpPosition) ||
                     (newPricedItem.BRpPosition > pricedItem.BLpPosition && newPricedItem.BRpPosition <= pricedItem.BRpPosition) ||
                     (newPricedItem.BLpPosition <= pricedItem.TLpPosition && newPricedItem.BRpPosition >= pricedItem.TRpPosition) || //le p di OI cadono dentro le p di NI o le p di OI sono uguali alle p di NI
                     (newPricedItem.BLpPosition > pricedItem.TLpPosition && newPricedItem.BRpPosition < pricedItem.TRpPosition)      //le p di NI cadono dentro le p di OI
                     ) &&
                    newPricedItem.BLqPosition >= pricedItem.TLqPosition)
                {
                    intersectedPricedItems.Add(pricedItem);
                }
            }

            //3 possibili risultati
            if (intersectedPricedItems.Count == 0) //non ho intersezioni
            {
                newPricedItem.BLqPosition = 0;
                newPricedItem.TLqPosition = newPricedItem.Height;
                newPricedItem.BRqPosition = 0;
                newPricedItem.TRqPosition = newPricedItem.Height;
            }
            else
            {
                if (intersectedPricedItems.Count == 1) //1 sola intersezione
                {
                    float delta = feasiblePoint.Qposition - intersectedPricedItems.ElementAt(0).Height;
                    newPricedItem.BLqPosition -= delta;
                    newPricedItem.TLqPosition -= delta;
                    newPricedItem.BRqPosition -= delta;
                    newPricedItem.TRqPosition -= delta;
                }
                else if (intersectedPricedItems.Count > 1) //N intersezioni
                {
                    float heightSum = intersectedPricedItems.OrderBy(x => x.TLqPosition).Last().TLqPosition;
                    float delta     = feasiblePoint.Qposition - heightSum;
                    newPricedItem.BLqPosition -= delta;
                    newPricedItem.TLqPosition -= delta;
                    newPricedItem.BRqPosition -= delta;
                    newPricedItem.TRqPosition -= delta;
                }
            }

            feasiblePoint.QfinalPosition = newPricedItem.BLqPosition;
            return(intersectedPricedItems);
        }
Example #3
0
        /// <summary>
        /// il metodo che spinge il più a sinistra possibile
        /// il nuovo item da nestare
        /// </summary>
        /// <param name="feasiblePoint"></param>
        /// <param name="temporaryBin"></param>
        /// <param name="temporaryItem"></param>
        /// <param name="newNestedItem"></param>
        /// <returns></returns>
        private IList <PricedItem> PushItemLeft(Bin <Tuple> temporaryBin, PricedItem newPricedItem, Tuple feasiblePoint)
        {
            //lista delle intersezioni tra item nuovo e item già in soluzione
            IList <PricedItem> intersectedPricedItems = new List <PricedItem>();

            foreach (var pricedItem in temporaryBin.PricedItems)
            {
                //cerco interesezioni orizzontali tra nuovo item e item già in soluzione (HO TOLTO UGUALE DESTRA -> CHECK)
                if (((newPricedItem.BLqPosition >= pricedItem.BLqPosition && newPricedItem.BLqPosition < pricedItem.TLqPosition) ||
                     (newPricedItem.TLqPosition > pricedItem.BLqPosition && newPricedItem.TLqPosition <= pricedItem.TLqPosition) ||
                     (newPricedItem.BLqPosition <= pricedItem.BRqPosition && newPricedItem.TLqPosition >= pricedItem.TRqPosition) || //le coord q di OI cadono entrambe dentro a NI o sono uguali
                     (newPricedItem.BLqPosition > pricedItem.BRqPosition && newPricedItem.TLqPosition < pricedItem.TRqPosition)      //le coord q di NI cadono entrambe dentro OI
                     ) &&
                    newPricedItem.BLpPosition >= pricedItem.BRpPosition)
                {
                    intersectedPricedItems.Add(pricedItem);
                }
            }

            //3 possibili risultati
            if (intersectedPricedItems.Count == 0) //non ho intersezioni
            {
                newPricedItem.BLpPosition = 0;
                newPricedItem.TLpPosition = 0;
                newPricedItem.BRpPosition = newPricedItem.Width;
                newPricedItem.TRpPosition = newPricedItem.Width;
            }
            else
            {
                if (intersectedPricedItems.Count == 1) //1 sola intersezione
                {
                    float delta = feasiblePoint.Pposition - intersectedPricedItems.ElementAt(0).Width;
                    newPricedItem.BLpPosition -= delta;
                    newPricedItem.TLpPosition -= delta;
                    newPricedItem.BRpPosition -= delta;
                    newPricedItem.TRpPosition -= delta;
                }
                else if (intersectedPricedItems.Count > 1) //N intersezioni
                {
                    float widthSum = intersectedPricedItems.OrderBy(x => x.BRpPosition).Last().BRpPosition;
                    float delta    = feasiblePoint.Pposition - widthSum;
                    newPricedItem.BLpPosition -= delta;
                    newPricedItem.TLpPosition -= delta;
                    newPricedItem.BRpPosition -= delta;
                    newPricedItem.TRpPosition -= delta;
                }
            }

            feasiblePoint.PfinalPosition = newPricedItem.BLpPosition;
            return(intersectedPricedItems);
        }
Example #4
0
        /// <summary>
        /// metodo che calcola l'hatched area totale relativa
        /// al posizionamento di un nuovo item e la ritorna.
        /// il metodo ritorna -1 se l'item, per come è posizionato (cioè dopo averlo spinto
        /// in basso a sinistra), eccede le dimensioni del bin
        /// </summary>
        /// <param name="feasiblePoint"></param>
        /// <param name="newNestedItem"></param>
        /// <param name="temporaryBin"></param>
        /// <param name="temporaryItem"></param>
        /// <returns></returns>
        private float GetHatchedArea(Bin <Tuple> temporaryBin, PricedItem newPricedItem, Tuple feasiblePoint)
        {
            PushItemDown(temporaryBin, newPricedItem, feasiblePoint);
            IList <PricedItem> leftIntersectedPricedItems = PushItemLeft(temporaryBin, newPricedItem, feasiblePoint);
            //conto il numero di intersezioni che ho da sotto, perché potrebbero cambiare (da quelle inzialemnte trovate con
            //la prima invocazione di PushItemDown) dopo aver spinto l'item tutto a sinistra
            IList <PricedItem> downIntersectedPricedItems = CheckDownInsersectionNumber(temporaryBin, newPricedItem, feasiblePoint);

            //controllo se l'oggetto, anche essendo stato spostato in basso a sintra, sborderebbe e
            //se la posizione in cui deve essere nestato il nuovo item comporterebbe delle sovrapposizioni con item già in soluzione
            if (IsBorderObserved(newPricedItem, temporaryBin.Height, temporaryBin.Width) && IsOverlappingOk(newPricedItem, temporaryBin))
            {
                ComputeHatchedArea(feasiblePoint, newPricedItem, downIntersectedPricedItems, leftIntersectedPricedItems);
                //Console.WriteLine("(" + feasiblePoint.Pposition + ", " + feasiblePoint.Qposition + "), HR = " + feasiblePoint.HatchedArea +
                //", new coord(" + feasiblePoint.PfinalPosition + ", " + feasiblePoint.QfinalPosition + ")");
                return(feasiblePoint.HatchedArea);
            }
            else
            {
                return(-1);
            }
        }
Example #5
0
        /// <summary>
        /// metodo che computa l'euristica di hsolve
        /// </summary>
        public IList <Sequence> ComputeHeuristic()
        {
            IUtilities utilities = new Utilities();

            //================ STEP 1 - INITIALIZATION ================

            //inizializzo il prezzo v associato ad ogni item j
            IList <PricedItem> pricedItems = new List <PricedItem>();
            int counter = 0;

            foreach (var dimension in Configuration.Dimensions)
            {
                var pricedItem = new PricedItem()
                {
                    Height = dimension.Height,
                    Width  = dimension.Width,
                    Id     = counter,
                    Price  = dimension.Height * dimension.Width,
                };
                pricedItems.Add(pricedItem);
                counter += 1;
            }

            IList <Bin <Tuple> > bins = new List <Bin <Tuple> >();

            counter = 0;

            //inserisco ogni item prezzato e i nuovi punti disponibili
            //in un bin diverso
            foreach (var pricedItem in pricedItems)
            {
                var bin = new Bin <Tuple>()
                {
                    Id          = counter,
                    Height      = Configuration.BinHeight,
                    Width       = Configuration.BinWidth,
                    PricedItems = new List <PricedItem>()
                    {
                        pricedItems.ElementAt(counter)
                    },
                    Points = new List <Tuple>()
                    {
                        new Tuple()
                        {
                            Pposition = 0,
                            Qposition = pricedItem.Height,
                            IsUsed    = false
                        },
                        new Tuple()
                        {
                            Pposition = pricedItem.Width,
                            Qposition = 0,
                            IsUsed    = false
                        }
                    }
                };

                bins.Add(bin);
                counter += 1;
            }

            int itemNumber = counter + 1;

            counter = 0;
            //inizializzo il costo della soluzione con il numero degli elementi
            int zStar = itemNumber;

            //inizializzo il numero di iterazioni
            int iter = 0;

            //calcolo il lower bound ed il relativo intervallo
            float lowerBound    = utilities.ComputeLowerBound(pricedItems, Configuration.BinWidth, Configuration.BinHeight);
            float lowerBoundMin = lowerBound - Configuration.LowerBoundDelta;
            float lowerBoundMax = lowerBound + Configuration.LowerBoundDelta;
            int   maxIter       = Configuration.MaxIter;

            //================ STEP 2 - ERASE THE CURRENT SOLUTION ================

l3:

            /*Sequence sequence = new Sequence()
             * {
             *  Bins = new List<Bin<Tuple>>()
             * };*/

            //creo una lista temporanea J' di item
            IList <PricedItem> temporaryPricedItems = new List <PricedItem>();

            //assegno la lista di item J a J'
            temporaryPricedItems = pricedItems;

            //setto il bin che considero al momento
            int i = 0;

            //creo tanti bin temporanei quanti sono gli item
            IList <Bin <Tuple> > temporaryBins = new List <Bin <Tuple> >();

            foreach (var pricedItem in pricedItems)
            {
                var temporaryBin = new Bin <Tuple>()
                {
                    Id          = counter,
                    Height      = Configuration.BinHeight,
                    Width       = Configuration.BinWidth,
                    PricedItems = null,
                    Points      = new List <Tuple>()
                    {
                        new Tuple()
                        {
                            Pposition = 0,
                            Qposition = 0,
                            IsUsed    = false
                        }
                    }
                };
                temporaryBins.Add(temporaryBin);
                counter += 1;
            }

            //1) ogni volta che inizio una nuova iterazione iter devo riordinare gli item per price decrescente
            //dato che i price sono stati aggiornati;
            //2) riattribuisco gli id agli item, così l'item col prezzo maggiore è quello che ha l'id 0 e così via
            var sortedTemporaryPricedItems = new List <PricedItem>();

            counter = 0;
            foreach (var temporaryPricedItem in temporaryPricedItems.OrderByDescending(x => x.Price))
            {
                sortedTemporaryPricedItems.Add(temporaryPricedItem);
                temporaryPricedItem.Id = counter;
                counter += 1;
            }



            //================ STEP 3 - FILLING UP BIN i ================
l1:         //cerco la posizione migliore per ogni item j'
            foreach (var sortedTemporaryPricedItem in sortedTemporaryPricedItems)
            {
                if (!sortedTemporaryPricedItem.IsRemoved)
                {
                    utilities.IsBestPositionFound(temporaryBins.ElementAt(i), sortedTemporaryPricedItem);
                    //salvo un bin nuovo ogni volta che  viene aggiunto un elemento

                    /*var tempItem = temporaryBins[i];
                     * Bin<Tuple> b;
                     *
                     * if (tempItem.PricedItems != null)
                     * {
                     *
                     *  b = new Bin<Tuple>
                     *  {
                     *      Id = tempItem.Id,
                     *      Height = tempItem.Height,
                     *      Width = tempItem.Width,
                     *      Points = new List<Tuple>(tempItem.Points),
                     *      PricedItems = new List<PricedItem>(tempItem.PricedItems)
                     *  };
                     * }
                     * else
                     * {
                     *  b = new Bin<Tuple>
                     *  {
                     *      Id = tempItem.Id,
                     *      Height = tempItem.Height,
                     *      Width = tempItem.Width,
                     *      Points = new List<Tuple>(tempItem.Points),
                     *      PricedItems = new List<PricedItem>()
                     *  };
                     * }
                     *
                     * sequence.Bins.Add(b);*/
                }
            }

            //================ STEP 4 - CHECK IF ALL ITEMS HAVE BEEN ALLOCATED ================
            int  z = i;
            bool isSortedTemporaryPricedItemsEmpty = true;

            //controllo se tutta la lista è stata svuotata
            foreach (var sortedTemporaryPricedItem in sortedTemporaryPricedItems)
            {
                if (sortedTemporaryPricedItem.IsRemoved == false)
                {
                    isSortedTemporaryPricedItemsEmpty = false;
                    break;
                }
            }

            if (isSortedTemporaryPricedItemsEmpty)
            {
                //Sequences.Add(sequence);
                goto l0;
            }
            if (!isSortedTemporaryPricedItemsEmpty && (i < (zStar)))
            {
                i += 1;
                goto l1;
            }
            goto l2;

            //================ STEP 5 - UPDATE THE BEST SOLUTION ================

            l0 : zStar = z;
            bins       = temporaryBins;

            Sequence sequence1 = new Sequence()
            {
                Bins = new List <Bin <Tuple> >()
            };

            sequence1.Bins = bins;
            Sequences.Add(sequence1);
            //================ STEP 6 - CHECK OPTIMALITY ================
            //guardo se il costo della soluzione è compreso nell'intervallo del lower bound
            if (zStar > lowerBoundMin && zStar < lowerBoundMax)
            {
                goto end;
            }

            //================ STEP 7 - UPDATE THE ITEM PRICES ================

            l2 : if (iter == maxIter)
            {
                goto end;
            }
            else
            {
                utilities.UpdatePrice(z, pricedItems, bins);
                iter += 1;
                //rimetto tutti gli item come isRemoved = false perché cominicio una nuova iterazione
                foreach (var pricedItem in pricedItems)
                {
                    pricedItem.IsRemoved = false;
                }
                goto l3;
            }

end:
            Sequence sequence2 = new Sequence()
            {
                Bins = new List <Bin <Tuple> >()
            };

            sequence2.Bins = bins;
            Sequences.Add(sequence2);

            Sequence firstSequence = Sequences.FirstOrDefault();
            Sequence lastSequence  = Sequences.LastOrDefault();

            Sequences.Clear();
            Sequences.Add(firstSequence);
            Sequences.Add(lastSequence);

            return(Sequences);
        }
Example #6
0
 /// <summary>
 /// metodo che controlla se, a fronte del posizione del nuovo item da nestare,
 /// le dimensioni di tale item sforano rispetto alle dimensioni del bin
 /// </summary>
 /// <param name="newNestedItem"></param>
 /// <param name="temporaryBinHeight"></param>
 /// <param name="temporaryBinWidth"></param>
 /// <returns></returns>
 bool IsBorderObserved(PricedItem newPricedItem, float temporaryBinHeight, float temporaryBinWidth)
 {
     return(newPricedItem.TLqPosition <= temporaryBinHeight && newPricedItem.BRpPosition <= temporaryBinWidth);
 }
Example #7
0
        private IList <PricedItem> CheckDownInsersectionNumber(Bin <Tuple> temporaryBin, PricedItem newPricedItem, Tuple feasiblePoint)
        {
            //lista delle intersezioni tra item nuovo e item già in soluzione
            IList <PricedItem> intersectedPricedItems = new List <PricedItem>();

            foreach (var pricedItem in temporaryBin.PricedItems)
            {
                //cerco intersezioni verticali tra nuovo item e item già in soluzione (HO TOLTO UGUALE DESTRA -> CHECK)
                if (((newPricedItem.BLpPosition >= pricedItem.BLpPosition && newPricedItem.BLpPosition < pricedItem.BRpPosition) ||
                     (newPricedItem.BRpPosition > pricedItem.BLpPosition && newPricedItem.BRpPosition <= pricedItem.BRpPosition) ||
                     (newPricedItem.BLpPosition <= pricedItem.TLpPosition && newPricedItem.BRpPosition >= pricedItem.TRpPosition) || //le p di OI cadono dentro le p di NI o le p di OI sono uguali alle p di NI
                     (newPricedItem.BLpPosition > pricedItem.TLpPosition && newPricedItem.BRpPosition < pricedItem.TRpPosition)      //le p di NI cadono dentro le p di OI
                     ) &&
                    newPricedItem.BLqPosition >= pricedItem.TLqPosition)
                {
                    intersectedPricedItems.Add(pricedItem);
                }
            }

            return(intersectedPricedItems);
        }
Example #8
0
        /// <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 Bin <Tuple> IsBestPositionFound(Bin <Tuple> temporaryBin, PricedItem temporaryPricedItem)
        {
            //se l'item non è nestabile (ovvero le sue dimensioni eccedano quelle del bin)
            //setto comunque l'item come removed, altrimenti la lista di item non sarà mai empty e hsolve non va avanti
            if (temporaryPricedItem.Height > temporaryBin.Height || temporaryPricedItem.Width > temporaryBin.Width)
            {
                temporaryPricedItem.IsRemoved = true;
                return(temporaryBin);
            }

            //item nestabile, procedo
            SetFeasiblePoints(temporaryBin);

            //se il bin non contiene punti
            if (temporaryBin.Points.Count == 0)
            {
                return(temporaryBin);
            }
            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)
            {
                temporaryBin.PricedItems = new List <PricedItem>()
                {
                    new PricedItem()
                    {
                        Height      = temporaryPricedItem.Height,
                        Width       = temporaryPricedItem.Width,
                        Id          = temporaryPricedItem.Id,
                        Price       = temporaryPricedItem.Price,
                        TLqPosition = temporaryPricedItem.Height,
                        BRpPosition = temporaryPricedItem.Width,
                        TRpPosition = temporaryPricedItem.Width,
                        TRqPosition = temporaryPricedItem.Height
                    }
                };
                HandleOperationsPostNestedItem(temporaryBin, temporaryPricedItem, temporaryBin.Points.ElementAt(0));
                return(temporaryBin);
            }
            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
                        PricedItem newPricedItem = new PricedItem()
                        {
                            Height      = temporaryPricedItem.Height,
                            Width       = temporaryPricedItem.Width,
                            Id          = temporaryPricedItem.Id,
                            Price       = temporaryPricedItem.Price,
                            BLpPosition = feasiblePoint.Pposition,
                            BLqPosition = feasiblePoint.Qposition,
                            BRpPosition = feasiblePoint.Pposition + temporaryPricedItem.Width,
                            BRqPosition = feasiblePoint.Qposition,
                            TLpPosition = feasiblePoint.Pposition,
                            TLqPosition = feasiblePoint.Qposition + temporaryPricedItem.Height,
                            TRpPosition = feasiblePoint.Pposition + temporaryPricedItem.Width,
                            TRqPosition = feasiblePoint.Qposition + temporaryPricedItem.Height
                        };
                        feasiblePoint.HatchedArea = GetHatchedArea(temporaryBin, newPricedItem, feasiblePoint);
                    }
                }

                //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(temporaryBin);
                }

                //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 pricedItem = new PricedItem()
                    {
                        Height      = temporaryPricedItem.Height,
                        Width       = temporaryPricedItem.Width,
                        Id          = temporaryPricedItem.Id,
                        Price       = temporaryPricedItem.Price,
                        BLpPosition = minHatchedAreaPoint.PfinalPosition,
                        BLqPosition = minHatchedAreaPoint.QfinalPosition,
                        BRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryPricedItem.Width,
                        BRqPosition = minHatchedAreaPoint.QfinalPosition,
                        TLpPosition = minHatchedAreaPoint.PfinalPosition,
                        TLqPosition = minHatchedAreaPoint.QfinalPosition + temporaryPricedItem.Height,
                        TRpPosition = minHatchedAreaPoint.PfinalPosition + temporaryPricedItem.Width,
                        TRqPosition = minHatchedAreaPoint.QfinalPosition + temporaryPricedItem.Height
                    };

                    temporaryBin.PricedItems.Add(pricedItem);
                    HandleOperationsPostNestedItem(temporaryBin, temporaryPricedItem, minHatchedAreaPoint);
                    return(temporaryBin);
                }
                else if (minHatchedAreaPoints.Count > 1)
                {
                    Tuple minCoordinatePoint = ApplyRule(minHatchedAreaPoints);

                    var pricedItem = new PricedItem()
                    {
                        Height      = temporaryPricedItem.Height,
                        Width       = temporaryPricedItem.Width,
                        Id          = temporaryPricedItem.Id,
                        Price       = temporaryPricedItem.Price,
                        BLpPosition = minCoordinatePoint.PfinalPosition,
                        BLqPosition = minCoordinatePoint.QfinalPosition,
                        BRpPosition = minCoordinatePoint.PfinalPosition + temporaryPricedItem.Width,
                        BRqPosition = minCoordinatePoint.QfinalPosition,
                        TLpPosition = minCoordinatePoint.PfinalPosition,
                        TLqPosition = minCoordinatePoint.QfinalPosition + temporaryPricedItem.Height,
                        TRpPosition = minCoordinatePoint.PfinalPosition + temporaryPricedItem.Width,
                        TRqPosition = minCoordinatePoint.QfinalPosition + temporaryPricedItem.Height
                    };

                    temporaryBin.PricedItems.Add(pricedItem);
                    HandleOperationsPostNestedItem(temporaryBin, temporaryPricedItem, minCoordinatePoint);



                    return(temporaryBin);
                }
            }
            return(temporaryBin);
        }
Example #9
0
        /// <summary>
        /// metodo che calcola l'hatched area prima sotto
        /// e poi a sinistra del nuovo item
        /// </summary>
        /// <param name="downIntersectedNestedItems"></param>
        /// <param name="leftIntersectedNestedItems"></param>
        /// <returns></returns>
        ///
        private void ComputeHatchedArea(Tuple feasiblePoint, PricedItem newPricedItem, IList <PricedItem> downIntersectedNestedItems, IList <PricedItem> leftIntersectedNestedItems)
        {
            float totalHatchedArea = 0;
            //variabile per l'hatched area che eventualmente rimane sotto e a sinitra
            float partialHatchedArea;

            if (downIntersectedNestedItems.Count > 0)
            {
                //definiso la green area sotto il nuovo item
                AdjacentItem adjacentItem = new AdjacentItem()
                {
                    BRpPosition = feasiblePoint.PfinalPosition + newPricedItem.Width,
                    BRqPosition = 0,
                    TRpPosition = feasiblePoint.PfinalPosition + newPricedItem.Width,
                    TRqPosition = feasiblePoint.QfinalPosition,
                    BLpPosition = feasiblePoint.PfinalPosition,
                    BLqPosition = 0,
                    TLpPosition = feasiblePoint.PfinalPosition,
                    TLqPosition = feasiblePoint.QfinalPosition,
                    Height      = newPricedItem.BRqPosition,
                    Width       = newPricedItem.Width,
                    Area        = newPricedItem.BRqPosition * newPricedItem.Width
                };

                //per ogni item già in posizione, che è stato intersecato,
                //calcolo quanta parte di area di esso rientra nella green area e
                //infine sommo tale area all'area totale degli item intersecati
                float itemsInSolutionArea = 0;
                float intersectedWidth;

                foreach (var intersectedItem in downIntersectedNestedItems)
                {
                    //if else per scegliere la width dell'item in soluzione
                    //di cui devo calcolare l'area
                    //per fare valore assoluto Math.Abs( ... );
                    if (newPricedItem.BLpPosition < intersectedItem.BLpPosition && //new item + a sx di interesect item
                        newPricedItem.BRpPosition < intersectedItem.BRpPosition)
                    {
                        intersectedWidth = newPricedItem.BRpPosition - intersectedItem.BLpPosition;
                    }
                    else if (intersectedItem.BLpPosition < newPricedItem.BLpPosition && //new item è + a  dx di intersected item
                             intersectedItem.BRpPosition < newPricedItem.BRpPosition)
                    {
                        intersectedWidth = intersectedItem.BRpPosition - newPricedItem.BLpPosition;
                    }
                    else if ((newPricedItem.BLpPosition == intersectedItem.BLpPosition && //new item inizia come insertected item ma termina prima
                              newPricedItem.BRpPosition < intersectedItem.BRpPosition) ||
                             (intersectedItem.BLpPosition < newPricedItem.BLpPosition &&  // new item inizia dopo di insertected item ma terminano uguali
                              intersectedItem.BRpPosition == newPricedItem.BRpPosition) ||
                             (intersectedItem.BLpPosition < newPricedItem.BLpPosition &&  //le coordinate p del new item cadono dentro quelle p dell'intersected item
                              intersectedItem.BRpPosition > newPricedItem.BRpPosition))
                    {
                        intersectedWidth = adjacentItem.Width;
                    }
                    else
                    {
                        intersectedWidth = intersectedItem.Width;
                    }

                    itemsInSolutionArea += (intersectedItem.Height * intersectedWidth);
                }

                partialHatchedArea = adjacentItem.Area - itemsInSolutionArea;
                totalHatchedArea  += partialHatchedArea;
            }

            if (leftIntersectedNestedItems.Count > 0)
            {
                //definiso la green area a sintra del nuovo item
                AdjacentItem adjacentItem = new AdjacentItem()
                {
                    BRpPosition = feasiblePoint.PfinalPosition,
                    BRqPosition = feasiblePoint.QfinalPosition,
                    TRpPosition = feasiblePoint.PfinalPosition,
                    TRqPosition = feasiblePoint.QfinalPosition + newPricedItem.Height,
                    BLpPosition = 0,
                    BLqPosition = feasiblePoint.QfinalPosition,
                    TLpPosition = 0,
                    TLqPosition = feasiblePoint.QfinalPosition + newPricedItem.Height,
                    Height      = newPricedItem.Height,
                    Width       = newPricedItem.BLpPosition,
                    Area        = newPricedItem.Height * newPricedItem.BLpPosition
                };

                //per ogni item già in posizione, che è stato intersecato,
                //calcolo quanta parte di area di esso rientra nella green area e
                //infine sommo tale area all'area totale degli item intersecati
                float itemsInSolutionArea = 0;
                float intersectedHeight;
                foreach (var intersectedItem in leftIntersectedNestedItems)
                {
                    //if else per scegliere la height dell'item in soluzione
                    //di cui devo calcolare l'area
                    //per fare valore assoluto Math.Abs( ... );
                    if (intersectedItem.BLqPosition < newPricedItem.BLqPosition && //new item + in alto di intersected item
                        intersectedItem.TLqPosition < newPricedItem.TLqPosition)
                    {
                        intersectedHeight = intersectedItem.TLqPosition - newPricedItem.BLqPosition;
                    }
                    else if (newPricedItem.BLqPosition < intersectedItem.BLqPosition && //new item + in basso di interesect item
                             newPricedItem.TLqPosition < intersectedItem.TLqPosition)
                    {
                        intersectedHeight = newPricedItem.TLqPosition - intersectedItem.BLqPosition;
                    }
                    else if ((newPricedItem.BLqPosition == intersectedItem.BLqPosition && //new item inizia come insertected item ma termina prima
                              newPricedItem.TLqPosition < intersectedItem.TLqPosition) ||
                             (intersectedItem.BLqPosition < newPricedItem.BLqPosition &&  // new item inizia dopo di insertected item ma terminano uguali
                              intersectedItem.TLqPosition == newPricedItem.TLqPosition) ||
                             (intersectedItem.BLqPosition < newPricedItem.BLqPosition &&  //le coordinate q del new item cadono dentro quelle dell'intersected item
                              intersectedItem.TLqPosition > newPricedItem.TLqPosition))
                    {
                        intersectedHeight = adjacentItem.Height;
                    }
                    else
                    {
                        intersectedHeight = intersectedItem.Height;
                    }

                    itemsInSolutionArea += (intersectedHeight * intersectedItem.Width);
                }

                partialHatchedArea = adjacentItem.Area - itemsInSolutionArea;
                totalHatchedArea  += partialHatchedArea;
            }

            feasiblePoint.HatchedArea = totalHatchedArea;
        }
Example #10
0
        /// <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, PricedItem sortedTemporaryPricedItem, Tuple point)
        {
            //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
            foreach (var p in temporaryBin.Points)
            {
                //cerco punti "coperti" dal nuovo item nestato
                if ((p.Pposition >= sortedTemporaryPricedItem.BLpPosition && p.Pposition < sortedTemporaryPricedItem.BRpPosition &&
                     p.Qposition >= sortedTemporaryPricedItem.BLqPosition && p.Qposition < sortedTemporaryPricedItem.TLqPosition) ||

                    (p.PfinalPosition == matchingPoint.PfinalPosition && //cerco punti che, dopo push down and left portavano alle stesse coordinate finali
                     p.QfinalPosition == matchingPoint.QfinalPosition &&
                     sortedTemporaryPricedItem.BRpPosition >= p.Pposition &&
                     sortedTemporaryPricedItem.TLqPosition >= p.Qposition))

                {
                    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 + sortedTemporaryPricedItem.Height &&
                                                         x.IsUsed == false).FirstOrDefault();

            //definisco il primo nuovo punto
            var firstPoint = new Tuple()
            {
                Pposition = point.PfinalPosition,
                Qposition = point.QfinalPosition + sortedTemporaryPricedItem.Height,
                IsUsed    = false
            };

            //controllo se il primo nuovo punto è idoneo ad essere aggiunto perché
            //potrebbe essere erroneaemente creato sul lato di un item già in soluzione
            bool isPointLyingOnItemSide = false;

            foreach (var ni in temporaryBin.PricedItems)
            {
                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 + sortedTemporaryPricedItem.Width &&
                                                   x.Qposition == point.QfinalPosition).FirstOrDefault();

            //definisco il secondo nuovo punto
            var secondPoint = new Tuple()
            {
                Pposition = point.PfinalPosition + sortedTemporaryPricedItem.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.PricedItems)
            {
                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
            sortedTemporaryPricedItem.IsRemoved = true;
        }