private void BehaelterAnnaehern(TBehaelter B1, TBehaelter B2)
        {
            const double Distanz      = 1000;
            const double StrahlLaenge = 10 * Distanz;

            Vector B2Verschub = new Vector((B1.TempPos.X + Distanz) - B2.TempPos.X, 0 - B2.TempPos.Y);

            B2.Verschieben(B2Verschub);

            List <Vector> Results1 = new List <Vector>();

            foreach (TDreieck D1 in B1.Dreiecke)
            {
                Point[] Eckpunkte = new Point[] { D1.A, D1.B, D1.C };
                foreach (Point Eckpunkt in Eckpunkte)
                {
                    foreach (TDreieck D2 in B2.Dreiecke)
                    {
                        Point B = Eckpunkt + new Vector(StrahlLaenge, 0);
                        DreieckKollision(Eckpunkt, B, D2.A, D2.B, ref Results1);
                        DreieckKollision(Eckpunkt, B, D2.B, D2.C, ref Results1);
                        DreieckKollision(Eckpunkt, B, D2.C, D2.A, ref Results1);
                    }
                }
            }

            List <Vector> Results2 = new List <Vector>();

            foreach (TDreieck D2 in B2.Dreiecke)
            {
                Point[] Eckpunkte = new Point[] { D2.A, D2.B, D2.C };
                foreach (Point Eckpunkt in Eckpunkte)
                {
                    foreach (TDreieck D1 in B1.Dreiecke)
                    {
                        Point B = Eckpunkt + new Vector(-StrahlLaenge, 0);
                        DreieckKollision(Eckpunkt, B, D1.A, D1.B, ref Results2);
                        DreieckKollision(Eckpunkt, B, D1.B, D1.C, ref Results2);
                        DreieckKollision(Eckpunkt, B, D1.C, D1.A, ref Results2);
                    }
                }
            }

            List <double> Distanzen1 = new List <double>();

            foreach (Vector V in Results1)
            {
                Distanzen1.Add(V.Y * StrahlLaenge);
            }

            foreach (Vector V in Results2)
            {
                Distanzen1.Add(V.Y * StrahlLaenge);
            }

            double KleinsteDistanz = double.PositiveInfinity;

            foreach (double D in Distanzen1)
            {
                if (D < KleinsteDistanz)
                {
                    KleinsteDistanz = D;
                }
            }

            B2.Verschieben(new Vector(-KleinsteDistanz, 0));
        }
Example #2
0
        // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

        private void Berechnen()
        {
            // Alle Dreiecke in Liste zuordnen & Behaelterliste erstellen
            List <TDreieck>   DreieckeUnzugeteilt = Dreiecke.ToList();
            List <TBehaelter> _Behaelter          = new List <TBehaelter>();

            // Dreiecke nach KLEINSTER Kante ordnen | Worst Case: O(N)=N² Operation
            DreieckeUnzugeteilt = OrdneNachKleinsterStrecke(DreieckeUnzugeteilt);

            // Gesamtwinkel bestimmen
            double GesamtWinkel = 0.0;

            foreach (TDreieck D in DreieckeUnzugeteilt)
            {
                GesamtWinkel += D.WA;
            }

            // Handeln nach Gesamtwinkel
            if (GesamtWinkel < 180.0)
            {
                // 1 Behaelter ausreichend
                TBehaelter B = new TBehaelter();
                B.BehaelterTyp = TBehaelter.TBehaelterTyp.Startbehaelter;

                _Behaelter.Add(B);

                while (DreieckeUnzugeteilt.Count > 0)
                {
                    TDreieck D = DreieckeUnzugeteilt[DreieckeUnzugeteilt.Count - 1];
                    _Behaelter[0].DreieckHinzufügen(D);
                    DreieckeUnzugeteilt.RemoveAt(DreieckeUnzugeteilt.Count - 1);
                }
            }
            else
            {
                // 2 oder mehr Behaelter notwendig?
                if (BerechnenMittelbehaelterNoetig(Dreiecke.ToList()))
                {
                    // Start-, Mittel- und Endbehälter
                    TBehaelter BStart = new TBehaelter();
                    TBehaelter BEnde  = new TBehaelter();
                    BStart.BehaelterTyp = TBehaelter.TBehaelterTyp.Startbehaelter;
                    BEnde.BehaelterTyp  = TBehaelter.TBehaelterTyp.Endbehaelter;

                    _Behaelter.Add(BStart);
                    _Behaelter.Add(BEnde);

                    // Mittelbehälterzahl (ungefähr - im worst case sind es mehr)
                    int BehaelterZahlMindestens       = (int)Math.Ceiling(GesamtWinkel / 180.0);
                    int MittelbehaelterZahlMindestens = BehaelterZahlMindestens - 2;

                    if (MittelbehaelterZahlMindestens > 0)
                    {
                        for (int I = 0; I < MittelbehaelterZahlMindestens; I++)
                        {
                            TBehaelter BMittel = new TBehaelter();
                            BMittel.BehaelterTyp = TBehaelter.TBehaelterTyp.Mittelbehaelter;

                            _Behaelter.Insert(1, BMittel);
                        }
                    }

                    // Abwechselnd Start- und Endbehälter auf 90° auffüllen (Dreiecke mit größter Strecke zuerst)
                    bool   InStartcontainer = true;
                    double WinkelStart      = 0.0;
                    double WinkelEnd        = 0.0;
                    while ((WinkelStart < 90.0) && (WinkelEnd < 90.0) && DreieckeUnzugeteilt.Count > 0)
                    {
                        TDreieck D = DreieckeUnzugeteilt[DreieckeUnzugeteilt.Count - 1];

                        if (InStartcontainer)
                        {
                            WinkelStart += D.WA;

                            if (WinkelStart > 90.0)
                            {
                                continue;
                            }

                            BStart.DreieckHinzufügen(D);
                        }
                        else
                        {
                            WinkelEnd += D.WA;

                            if (WinkelEnd > 90.0)
                            {
                                continue;
                            }

                            BEnde.DreieckHinzufügen(D);
                        }

                        DreieckeUnzugeteilt.RemoveAt(DreieckeUnzugeteilt.Count - 1);

                        // Flag umkehren
                        InStartcontainer = !InStartcontainer;
                    }

                    // Temporären Winkel setzen
                    foreach (TBehaelter B in _Behaelter)
                    {
                        B.TempWinkel = 0.0;
                    }

                    // Start- und Endbehälter sind bereits teilweise gefüllt
                    BStart.TempWinkel = BStart.GefuellterWinkel();
                    BEnde.TempWinkel  = BEnde.GefuellterWinkel();

                    // Restliche Dreiecke auch unter Mittelbehältern zuteilen
                    int Index       = 0;
                    int Fehlzaehler = 0;
                    while (DreieckeUnzugeteilt.Count > 0)
                    {
                        TBehaelter B = _Behaelter[Index];
                        TDreieck   D = DreieckeUnzugeteilt[DreieckeUnzugeteilt.Count - 1];

                        // Dreieck hinzufügen wenn noch Platz ist
                        B.TempWinkel += D.WA;

                        if (B.TempWinkel < 180.0)
                        {
                            // Dreieck hinzufügen
                            B.DreieckHinzufügen(D);

                            DreieckeUnzugeteilt.RemoveAt(DreieckeUnzugeteilt.Count - 1);

                            Fehlzaehler = 0;
                        }
                        else
                        {
                            Fehlzaehler++;
                        }

                        // Falls die Behälter nicht ausreichen wird ein neuer hinzugefügt
                        if (Fehlzaehler >= _Behaelter.Count)
                        {
                            TBehaelter BNeu = new TBehaelter();
                            BNeu.BehaelterTyp = TBehaelter.TBehaelterTyp.Mittelbehaelter;
                            BNeu.TempWinkel   = 0;

                            _Behaelter.Insert(1, BNeu);
                        }

                        // Nächste Iteration
                        Index++;
                        if (Index >= _Behaelter.Count)
                        {
                            Index = 0;
                        }
                    }
                }
                else
                {
                    // Start- und Endbehälter
                    TBehaelter BStart = new TBehaelter();
                    TBehaelter BEnde  = new TBehaelter();
                    BStart.BehaelterTyp = TBehaelter.TBehaelterTyp.Startbehaelter;
                    BEnde.BehaelterTyp  = TBehaelter.TBehaelterTyp.Endbehaelter;

                    _Behaelter.Add(BStart);
                    _Behaelter.Add(BEnde);

                    // Abwechselnd Dreiecke zu Start- und Endbehälter hinzufügen (Dreiecke mit größter Strecke zuerst)
                    bool InStartcontainer = true;
                    while (DreieckeUnzugeteilt.Count > 0)
                    {
                        TDreieck D = DreieckeUnzugeteilt[DreieckeUnzugeteilt.Count - 1];

                        if (InStartcontainer)
                        {
                            BStart.DreieckHinzufügen(D);
                        }
                        else
                        {
                            BEnde.DreieckHinzufügen(D);
                        }

                        DreieckeUnzugeteilt.RemoveAt(DreieckeUnzugeteilt.Count - 1);

                        // Flag umkehren
                        InStartcontainer = !InStartcontainer;
                    }
                }
            }

            // Dreiecke in allen Behältern korrekt orientieren
            foreach (TBehaelter B in _Behaelter)
            {
                B.DreieckeAnordnen();
            }

            TBehaelter[] BesteAnordnung;
            double       BesteStrecke;

            if (_Behaelter.Count > 3) // Ab 3 sind Permuatation möglich (2 Behälter werden abgezogen)
            {
                // Permuatationen ohne Start- und Endbehälter
                List <TBehaelter> PermuatationsBehaelter = new List <TBehaelter>(_Behaelter);
                PermuatationsBehaelter.RemoveAt(0);
                PermuatationsBehaelter.RemoveAt(PermuatationsBehaelter.Count - 1);

                // Alle möglichen Kombinationen bestimmen
                var PermutationenRoh = BehaelterPermutationen(PermuatationsBehaelter, PermuatationsBehaelter.Count).ToArray();

                List <TBehaelter[]> Permutationen = new List <TBehaelter[]>();

                double[] Ergebnisse = new double[PermutationenRoh.Length];
                for (int I = 0; I < PermutationenRoh.Length; I++)
                {
                    List <TBehaelter> PermutationenUnvollstaendig = PermutationenRoh[I].ToList();
                    PermutationenUnvollstaendig.Insert(0, _Behaelter[0]);
                    PermutationenUnvollstaendig.Add(_Behaelter[_Behaelter.Count - 1]);

                    TBehaelter[] PermutationenVollstaendig = PermutationenUnvollstaendig.ToArray();

                    Permutationen.Add(PermutationenVollstaendig);

                    TBerechnung Berechnung = new TBerechnung(PermutationenVollstaendig);
                    Ergebnisse[I] = Berechnung.Berechnen();
                }

                int BestePermuatationIndex = -1;
                for (int I = 0; I < Ergebnisse.Length; I++)
                {
                    if (BestePermuatationIndex == -1 || Ergebnisse[I] < Ergebnisse[BestePermuatationIndex])
                    {
                        BestePermuatationIndex = I;
                    }
                }

                // Beste Permutation anzeigen
                TBehaelter[] BestePermutation = Permutationen[BestePermuatationIndex].ToArray();
                BestePermutation[0].Verschieben(new Vector(-(BestePermutation[0].TempPos.X - 200), 0));

                TBerechnung BerechnungBeste = new TBerechnung(BestePermutation);
                BerechnungBeste.Berechnen();

                BesteAnordnung = BestePermutation;
                BesteStrecke   = Ergebnisse[BestePermuatationIndex];
            }
            else
            {
                TBerechnung Berechnung = new TBerechnung(_Behaelter.ToArray());
                BesteStrecke   = Berechnung.Berechnen();
                BesteAnordnung = _Behaelter.ToArray();
            }

            // Ausgabe
            StatusBarItemInfo.Content = "Distanz: " + (int)Math.Round(BesteStrecke) + "m";

            // Behälter setzen & Zeichnen
            Behaelter = _Behaelter;
            Zeichne();
        }