private bool BerechnenMittelbehaelterNoetig(List <TDreieck> _Dreiecke) { double B1Winkel = 0.0, B2Winkel = 0.0; List <TDreieck> DreieckeWinkeltest = _Dreiecke.ToList(); while (DreieckeWinkeltest.Count > 0) { TDreieck D = DreieckeWinkeltest[DreieckeWinkeltest.Count - 1]; if (B1Winkel < 180.0) { B1Winkel += D.WA; if (B1Winkel < 180.0) { DreieckeWinkeltest.RemoveAt(DreieckeWinkeltest.Count - 1); } } else if (B2Winkel < 180.0) { B2Winkel += D.WA; if (B2Winkel < 180.0) { DreieckeWinkeltest.RemoveAt(DreieckeWinkeltest.Count - 1); } } else { return(true); } } return(false); }
public void DreieckHinzufügen(TDreieck D) { if (BehaelterTyp == TBehaelterTyp.Mittelbehaelter) { DreieckHinzufügenMittelbehaelter(D); return; } D.Verschieben(TempPos - new Point(D.A.X, D.A.Y)); Dreiecke.Add(D); }
public void DreieckHinzufügenMittelbehaelter(TDreieck D) { D.Verschieben(TempPos - new Point(D.A.X, D.A.Y)); if (AnordnungsFlag) { Dreiecke.Insert(0, D); } else { Dreiecke.Add(D); } AnordnungsFlag = !AnordnungsFlag; }
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++pai+ private void DateiEinlesen(string Datei) { string[] Zeilen = Datei.Split('\n'); string[] StartpunktStrings = Zeilen[Zeilen.Length - 1].Split(' '); int DreieckAnzahl; TDreieck[] _Dreiecke; try { DreieckAnzahl = int.Parse(Zeilen[0]); _Dreiecke = new TDreieck[DreieckAnzahl]; for (int I = 0; I < DreieckAnzahl; I++) { string[] HindernisString = Zeilen[I + 1].Split(' '); int PunktAnzahl = int.Parse(HindernisString[0]); Point[] Punkte = new Point[PunktAnzahl]; for (int J = 0; J < PunktAnzahl; J++) { double X = double.Parse(HindernisString[J * 2 + 1]); double Y = double.Parse(HindernisString[J * 2 + 2]); Punkte[J] = new Point(X, Y); } if (Punkte.Length > 3) { throw new Exception("Mehr Punkte als erwartet!"); } _Dreiecke[I] = new TDreieck(Punkte[0], Punkte[1], Punkte[2]); } } catch (Exception Ex) { MessageBox.Show("Die Datei konnte nicht korrekt eingelesen werden!" + Environment.NewLine + Ex.Message); return; } Dreiecke = _Dreiecke.ToArray(); MenuItemSaveAs.IsEnabled = true; Berechnen(); }
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 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(); }