private HPGLElemente.Linie ErsteLinie(UInt16 Stift) { double KleinsterAbstand = Double.MaxValue; double AktuellerAbstand = 0D; bool ErsteLinieRückwärts = false; HPGLElemente.Linie ersteLinie = null; if (_Linien == null || _Linien.Count == 0) { PlotterCom.StaticLogger.Log("Kann keine erste Linie ermitteln, Linien sind leer oder null!", 4); return(null); } // Irgendwas sollte drin stehen, auch wenn aufgrund des Stiftes keine passende Linie gefunden wird. ersteLinie = _Linien[0]; foreach (HPGLElemente.Linie aktuelleLinie in _Linien) { if (aktuelleLinie.Pen != Stift) { continue; } AktuellerAbstand = (aktuelleLinie.StartX * aktuelleLinie.StartX) + (aktuelleLinie.StartY + aktuelleLinie.StartY); if (AktuellerAbstand < KleinsterAbstand) { KleinsterAbstand = AktuellerAbstand; ErsteLinieRückwärts = false; ersteLinie = aktuelleLinie; } AktuellerAbstand = (aktuelleLinie.EndX * aktuelleLinie.EndX) + (aktuelleLinie.EndY + aktuelleLinie.EndY); if (AktuellerAbstand < KleinsterAbstand) { KleinsterAbstand = AktuellerAbstand; ErsteLinieRückwärts = true; ersteLinie = aktuelleLinie; } } if (ErsteLinieRückwärts) { ersteLinie.DreheUm(); } return(ersteLinie); }
// Findet alle Dubletten zu einer Linie. private void FindeDublette(HPGLElemente.Linie dublette) { foreach (HPGLElemente.Linie TestLinie in _Linien) { if (!dublette.Equals(TestLinie)) { if ((dublette.StartX == TestLinie.StartX) && (dublette.StartY == TestLinie.StartY) && (dublette.EndX == TestLinie.EndX) && (dublette.EndY == TestLinie.EndY)) { TestLinie.Dublette = true; } } } }
public void Optimiere(ToolStripProgressBar progressBar, ToolStripLabel label) { List <HPGLElemente.Linie> optimierteListe = null; // Die neue, optimierte Liste. List <UInt16> StiftListe = null; // Die Liste aller verwendeten Stifte. double kleinsterAbstand; // Der kleinste Abstand, der bisher gefunden wurde. double aktuellerAbstandV = 0D; // Temporäre Variable zum halten des aktuellen Abstands vorwärts. double aktuellerAbstandR = 0D; // Temporäre Variable zum halten des aktuellen Abstands rückwärts. bool LinieRückwärts = false; // Ist true, wenn die aktuelle Linie umgedreht werden muss. bool LinieGefunden = true; // Habe ich eine Line gefunden? HPGLElemente.Linie besteLinie = null; // Die aktuell beste Linie. HPGLElemente.Linie zuletztOptimierteLinie = null; // Die Linie, ab deren Ende gesucht wird. if ((_Linien == null) || (_Linien.Count == 0)) { PlotterCom.StaticLogger.Log("Keine Linien zum Optimieren. Ende", 4); return; } // Erstelle Liste mit allen verwendeten Stiften. StiftListe = StiftListeErstellen(); // Fals die letzte Optimierung abgebrochen wurde, setzte OptimierenAbbrechen wieder auf false. OptimierenAbbrechen = false; // Erstelle eine neue, leere Liste in der die optimierte Liste aufgebaut wird. optimierteListe = new List <HPGLElemente.Linie>(_Linien.Count); // Zuerst das optimiert-Kennzeichen zurück setzen! foreach (HPGLElemente.Linie aktuelleLinie in _Linien) { aktuelleLinie.Optimiert = false; } // Das erste Element suchen und einfügen; optimierteListe.Add(ErsteLinie(StiftListe[0])); optimierteListe[0].Optimiert = true; zuletztOptimierteLinie = optimierteListe[0]; foreach (UInt16 AktuellerStift in StiftListe) { // Zum hereinspringen in die Schleife LinieGefunden erstmal auf true setzen. LinieGefunden = true; // Solange noch neue Linien gefunden werden... while (LinieGefunden) { kleinsterAbstand = System.Double.MaxValue; LinieRückwärts = false; LinieGefunden = false; // Wird true gesetzt, wenn eine Linie gefunden wurde. // Es wird keine Linie gefunden wenn alle Linien optimiert wurden, die mit dem // aktuellen Stift gezeichnet werden. if (OptimierenAbbrechen) { break; } // ... suche eine Nachfolgerlinie. foreach (HPGLElemente.Linie aktuelleLinie in _Linien) { // Wenn die Linie einen Stiftwechsel erfordern würde, ignoriere sie. if (aktuelleLinie.Pen != AktuellerStift) { continue; } // Bereits optimierte Linien auch ignorieren. if (aktuelleLinie.Optimiert) { // Ev. wäre es sinnvoll, die bereits optimierten aus der Liste zu entfernen, um die // Geschwindigkeit zu erhöhen. Müssste man mal drüber nachdenken was das für Folgen hätte. // --> Abbrechen nicht mehr möglich. // --> Progress-Bar-Wert wird falsch berechnet. continue; } // Berechne den Abstand zum aktuellen Kandidaten. aktuellerAbstandV = ( (zuletztOptimierteLinie.EndX - aktuelleLinie.StartX) * (zuletztOptimierteLinie.EndX - aktuelleLinie.StartX) + (zuletztOptimierteLinie.EndY - aktuelleLinie.StartY) * (zuletztOptimierteLinie.EndY - aktuelleLinie.StartY) ); // Berechne den Abstand zum Ende des aktuellen Kandidaten. aktuellerAbstandR = ( (zuletztOptimierteLinie.EndX - aktuelleLinie.EndX) * (zuletztOptimierteLinie.EndX - aktuelleLinie.EndX) + (zuletztOptimierteLinie.EndY - aktuelleLinie.EndY) * (zuletztOptimierteLinie.EndY - aktuelleLinie.EndY) ); if (aktuellerAbstandV < kleinsterAbstand) { kleinsterAbstand = aktuellerAbstandV; besteLinie = aktuelleLinie; LinieRückwärts = false; LinieGefunden = true; } if (aktuellerAbstandR < kleinsterAbstand) { kleinsterAbstand = aktuellerAbstandV; besteLinie = aktuelleLinie; LinieRückwärts = true; LinieGefunden = true; } // Wenn ich eine direkt anschließende Linie gefunden habe, kann ich die Suche stoppen. if (aktuellerAbstandV == 0D) { break; } } // Habe ich etwas gefunden, nimm es in die optimierte Liste auf. if (LinieGefunden) { zuletztOptimierteLinie = besteLinie; // Umdrehen, wenn das Ende näher war. if (LinieRückwärts) { besteLinie.DreheUm(); } besteLinie.Optimiert = true; optimierteListe.Add(besteLinie); } if (optimierteListe.Count % 128 == 0) { if ((progressBar != null) && (label != null)) { int Prozent = (int)(((float)optimierteListe.Count / (float)_Linien.Count) * 100F); progressBar.Value = Prozent; label.Text = Prozent.ToString() + "%"; System.Windows.Forms.Application.DoEvents(); } } } } if (!OptimierenAbbrechen) { _Linien = optimierteListe; } }