diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2024-05-05 14:36:59 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2024-05-05 14:36:59 +0200 |
| commit | aed3ad2011483d36b1f6f6b772a6f300cb967cc0 (patch) | |
| tree | 7f1543b344bdd783db1d5b079dbd15b3e6a0bf34 /Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java | |
| parent | a91e3342f58a6476e17d9bd172f02b1c7cacf603 (diff) | |
| download | unterricht-aed3ad2011483d36b1f6f6b772a6f300cb967cc0.tar.gz unterricht-aed3ad2011483d36b1f6f6b772a6f300cb967cc0.zip | |
add Baelle project for simple inheritance
Diffstat (limited to 'Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java')
| -rw-r--r-- | Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java | 1866 |
1 files changed, 1866 insertions, 0 deletions
diff --git a/Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java b/Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java new file mode 100644 index 00000000..e17192e3 --- /dev/null +++ b/Info/10/2/Baelle/BlueJ_Projekt/Zeichenfenster.java @@ -0,0 +1,1866 @@ +import java.awt.*; +import java.awt.geom.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; +import javax.swing.event.*; +import java.util.*; +/** + * Die Klasse stellt ein Fenster mit einer Malfläche zur Verfügung, + * auf der Objekte der Klassen Rechteck, Kreis und Dreieck sowie Turtle dargestellt + * werden können. + * Die Zeichenfläche wird beim ersten Anlegen eines Zeichenobjekts automatisch + * nach dem Muster Singleton angelegt. + * + * @author Albert Wiedemann + * @version 1.0 + */ +class Zeichenfenster +{ + /** Interface für die Aktionsausführung. */ + interface AktionsEmpfaenger + { + /** Methode wird vom Taktgeber aufgerufen. */ + void Ausführen(); + void Taste (char taste); + void SonderTaste (int taste); + void Geklickt (int x, int y, int anzahl); + } + + /** Aufzählung der erzeugbaren Objektarten. */ + static enum SymbolArt {kreis, dreieck, rechteck, turtle, figur, text;}; + + /** Einziges Objekt der Zeichenfläche. */ + private static Zeichenfenster zeichenfläche = null; + + /** Fenster für die Zeichenfläche. */ + private JFrame fenster; + /** Die eigentliche Darstellungskomponente. */ + private JComponent malfläche; + /** Stop-Knopf für den Taktgeber. */ + private JButton stop; + /** Start-Knopf für den Taktgeber. */ + private JButton start; + /** Einsteller für die Taktrate*/ + private JSlider slider; + /** Feld aller zu zeichnenden Objekte. */ + private ArrayList<GrafikSymbol> alleSymbole; + /** Feld aller zu zeichnenden Objekte. */ + private ArrayList<AktionsEmpfaenger> aktionsEmpfänger; + /** Timerobjekt für die zentrale Zeitverwaltung */ + private javax.swing.Timer timer; + + /** + * Legt das Fenster und die Malfläche an + */ + private Zeichenfenster () + { + alleSymbole = new ArrayList<GrafikSymbol>(); + aktionsEmpfänger = new ArrayList<AktionsEmpfaenger>(); + fenster = new JFrame("Zeichenfenster"); + fenster.setLocation(50, 50); + fenster.setSize(800, 600); + fenster.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); //Close-Button kann nicht versteckt oder abgestellt werden. + + malfläche = new JComponent() + { + public void paint (Graphics g) + { + g.setColor(new Color (230, 230, 230)); + g.fillRect(0, 0, getWidth() - 1, getHeight() - 1); + synchronized (malfläche) + { + for (GrafikSymbol s: alleSymbole) + { + if (s.sichtbar) + { + s.Zeichnen(g); + } + } + } + } + }; + malfläche.setOpaque(true); + malfläche.addMouseListener(new MouseAdapter () + { + /** + * Gibt den Ort eines Mouseclicks an die eigentliche Aktionsmethode weiter. + * @param e das zugrestellte Ereignis + */ + public void mousePressed(MouseEvent e) + { + malfläche.requestFocus(); + ArrayList<AktionsEmpfaenger> empfänger = new ArrayList<AktionsEmpfaenger>(aktionsEmpfänger); + for (AktionsEmpfaenger em: empfänger) + { + em.Geklickt(e.getX(), e.getY(), e.getClickCount()); + } + } + } + ); + malfläche.addKeyListener(new KeyAdapter () + { + /** + * Gibt die Taste an die eigentliche Aktionsmethode weiter. + * @param e das zugestellte Ereignis + */ + public void keyPressed(KeyEvent e) + { + ArrayList<AktionsEmpfaenger> empfänger = new ArrayList<AktionsEmpfaenger>(aktionsEmpfänger); + if ((int) e.getKeyChar() == KeyEvent.CHAR_UNDEFINED) + { + switch (e.getKeyCode()) + { + case KeyEvent.VK_ENTER: + for (AktionsEmpfaenger em: empfänger) + { + em.Taste((char) KeyEvent.VK_ENTER); + } + break; + default: + for (AktionsEmpfaenger em: empfänger) + { + em.SonderTaste(e.getKeyCode()); + } + } + } + else + { + for (AktionsEmpfaenger em: empfänger) + { + em.Taste(e.getKeyChar()); + } + } + } + } + ); + malfläche.addComponentListener(new ComponentAdapter() + { + /** + * Setzt die Hintegrundbilder aller Turtle auf die neue Größe. + */ + public void componentResized(ComponentEvent e) + { + synchronized (malfläche) + { + for (GrafikSymbol s: alleSymbole) + { + if (s instanceof TurtleIntern) + { + ((TurtleIntern) s).NeueGrößeSetzen(); + } + } + } + } + } + ); + fenster.add(malfläche, BorderLayout.CENTER); + JPanel panel = new JPanel(); + panel.setMinimumSize(new Dimension(200, 60)); + panel.setSize(200,60); + panel.setVisible(true); + panel.setLayout(new GridLayout(1, 2)); + JPanel panel2 = new JPanel(); + panel2.setMinimumSize(new Dimension(100, 60)); + panel2.setSize(100,60); + panel2.setVisible(true); + panel2.setLayout(new GridLayout(1, 1)); + stop = new JButton(); + start = new JButton(); + start.setLocation(10, 10); + start.setSize(80, 30); + start.setText("Start"); + start.setVisible(true); + start.addActionListener(new ActionListener () + { + public void actionPerformed (ActionEvent evt) + { + TaktgeberStartenIntern(); + malfläche.requestFocus(); + } + } + ); + panel2.add(start); + stop.setLocation(100, 10); + stop.setSize(80, 30); + stop.setText("Stop"); + stop.setVisible(true); + stop.setEnabled(false); + stop.addActionListener(new ActionListener () + { + public void actionPerformed (ActionEvent evt) + { + TaktgeberStoppenIntern(); + malfläche.requestFocus(); + } + } + ); + panel2.add(stop); + panel.add(panel2); + slider = new JSlider(0, 1000, 100); + slider.setLocation(190, 10); + slider.setSize(160, 40); + slider.setMinimumSize(new Dimension(160, 40)); + slider.setPreferredSize(new Dimension(160, 40)); + slider.setMajorTickSpacing(100); + slider.setPaintTicks(true); + slider.setPaintLabels(true); + slider.setValue(1000); + slider.addChangeListener(new ChangeListener() + { + public void stateChanged(ChangeEvent e) + { + timer.setDelay(slider.getValue()); + malfläche.requestFocus(); + } + } + ); + panel.add(slider); + + fenster.add(panel, BorderLayout.SOUTH); + fenster.setVisible(true); + malfläche.requestFocus(); + + timer = new javax.swing.Timer (1000, new ActionListener () + { + /** + * Vom Timer aufgerufen. + * Erzeugt den nächsten Taktimpuls + * @param evt der Timerevent + */ + public void actionPerformed (ActionEvent evt) + { + ArrayList<AktionsEmpfaenger> empfänger = new ArrayList<AktionsEmpfaenger>(aktionsEmpfänger); + for (AktionsEmpfaenger e: empfänger) + { + e.Ausführen(); + } + } + } + ); + } + + /** + * Meldet die aktuelle Breite der Malfläche. + * @returns Breite der Malfläche + */ + static int MalflächenBreiteGeben() + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.malfläche.getWidth(); + } + + /** + * Meldet die aktuelle Höhe der Malfläche. + * @returns Höhe der Malfläche + */ + static int MalflächenHöheGeben() + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.malfläche.getHeight(); + } + + /** + * Trägt einen neuen Aktionsempfänger ein. + * @param neu der neue Aktionsempfänger + */ + static void AktionsEmpfängerEintragen(AktionsEmpfaenger neu) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.aktionsEmpfänger.add(neu); + } + + /** + * Löscht einen Aktionsempfänger aus der Liste. + * @param alt der zu löschende Aktionsempfänger + */ + static void AktionsEmpfängerEntfernen(AktionsEmpfaenger alt) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.aktionsEmpfänger.remove(alt); + } + + /** + * Erzeugt ein neues darzustelledes Symbol. + * Die möglichen Symbole sind im Aufzählungstyp SymbolArt beschrieben. + * @param art Art des zu erzeugenden Symbols. + * @return Referenz auf das Delegate-Objekt. + */ + static GrafikSymbol SymbolErzeugen (SymbolArt art) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + return zeichenfläche.SymbolAnlegen(art); + } + + /** + * Startet den Taktgeber. + */ + static void TaktgeberStarten () + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.TaktgeberStartenIntern(); + } + + /** + * Stoppt den Taktgeber. + */ + static void TaktgeberStoppen () + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.TaktgeberStoppenIntern(); + } + + /** + * Ablaufgeschwindigkeit des Zeitgebers einstellen. + * + * @param dauer: Angabe in Millisekunden + */ + static void TaktdauerSetzen (int dauer) + { + if (zeichenfläche == null) + { + zeichenfläche = new Zeichenfenster(); + } + zeichenfläche.slider.setValue(dauer < 0 ? 0 : (dauer > 1000 ? 1000: dauer)); + } + + /** + * Erzeugt das neue Symbol tatsächlich. + * @param art Art des zu erzeugenden Symbols. + * @return Referenz auf das Delegate-Objekt. + */ + private GrafikSymbol SymbolAnlegen (SymbolArt art) + { + GrafikSymbol neu = null; + switch (art) + { + case rechteck: + neu = new RechteckIntern(); + break; + case kreis: + neu = new EllipseIntern(); + break; + case dreieck: + neu = new DreieckIntern(); + break; + case turtle: + neu = new TurtleIntern(); + break; + case figur: + neu = new FigurIntern(); + break; + case text: + neu = new TextIntern(); + break; + } + synchronized (zeichenfläche.malfläche) + { + zeichenfläche.alleSymbole.add(neu); + } + malfläche.repaint(); + return neu; + } + + /** + * Startet den Taktgeber. + */ + private void TaktgeberStartenIntern() + { + start.setEnabled(false); + stop.setEnabled(true); + timer.start(); + } + + /** + * Stoppt den Taktgeber. + */ + private void TaktgeberStoppenIntern() + { + start.setEnabled(true); + stop.setEnabled(false); + timer.stop(); + } + + /** + * Oberklasse für alle verfügbaren Grafiksymbole. + * Alle Grafiksymbole werden über ihr umgebendes Rechteck beschrieben. + */ + abstract class GrafikSymbol + { + /** x-Position der linken oberen Ecke. */ + protected int x; + /** y-Position der linken oberen Ecke. */ + protected int y; + /** Breite des umgebenden Rechtecks. */ + protected int b; + /** Höhe des umgebenden Rechtecks. */ + protected int h; + /** Farbe des Symbols. */ + protected Color c; + /** Sichtbarkeit des Symbols. */ + protected boolean sichtbar; + /** Drehwinkel (mathematisch positiver Drehsinn) des Symbols. */ + protected int winkel; + /** Die Form des Grafiksymbols. */ + protected Area form; + /** Farbe Hellgelb. */ + protected final Color hellgelb = new Color(255,255,128); + /** Farbe Hellgrün. */ + protected final Color hellgrün = new Color(128,255,128); + /** Farbe Orange. */ + protected final Color orange = new Color(255,128,0); + /** Farbe Braun. */ + protected final Color braun = new Color(128,64,0); + + /** + * Der Konstruktor erzeugt ein rotes Symbol in der linken oberen Ecke des Fensters. + */ + GrafikSymbol() + { + x = 10; + y = 10; + b = 100; + h = 100; + c = Color.RED; + sichtbar = true; + winkel = 0; + FormErzeugen(); + } + + /** + * Normiert den Winkel auf Werte im Bereich [0; 360[ + * @param winkel der Eingabewinkel + * @return der normierte Winkel + */ + int WinkelNormieren(int winkel) + { + while (winkel < 0) + { + winkel += 360; + } + return winkel % 360; + } + + /** + * Setzt die Position (der linken oberen Ecke) des Objekts. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + */ + void PositionSetzen (int x, int y) + { + this.x = x; + this.y = y; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Größe des Objekts. + * @param breite (neue) Breite des Objekts + * @param höhe (neue) Höhe des Objekts + */ + void GrößeSetzen (int breite, int höhe) + { + b = breite; + h = höhe; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bestimmt die RGB-Farbe für den gegeben String. + * @param farbe die Farbe als String + * @return die Farbe als RGB-Farbe + */ + Color FarbeCodieren (String farbe) + { + farbe = farbe.toLowerCase(); + switch (farbe) + { + case "weiß": + case "weiss": + return Color.WHITE; + case "rot": + return Color.RED; + case "grün": + case "gruen": + return Color.GREEN; + case "blau": + return Color.BLUE; + case "gelb": + return Color.YELLOW; + case "magenta": + return Color.MAGENTA; + case "cyan": + return Color.CYAN; + case "hellgelb": + return hellgelb; + case "hellgrün": + case "hellgruen": + return hellgrün; + case "orange": + return orange; + case "braun": + return braun; + case "grau": + return Color.GRAY; + case "schwarz": + return Color.BLACK; + default: + return Color.BLACK; + } + } + + /** + * Setzt die Farbe des Objekts. + * @param farbe (neue) Farbe des Objekts + */ + void FarbeSetzen (String farbe) + { + FarbeSetzen(FarbeCodieren(farbe)); + } + + /** + * Setzt die Farbe des Objekts. + * @param c (neue) Farbe des Objekts + */ + void FarbeSetzen (Color c) + { + this.c = c; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Sichtbarkeit des Objekts. + * @param sichtbar (neue) Sichtbarkeit des Objekts + */ + void SichtbarkeitSetzen (boolean sichtbar) + { + this.sichtbar = sichtbar; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt den Drehwinkel des Objekts. + * @param winkel der (neue) Drehwinkel des Objekts + */ + void WinkelSetzen (int winkel) + { + this.winkel = WinkelNormieren(winkel); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Entfernt das Objekt aus dem Zeichenfenster. + */ + void Entfernen () + { + synchronized (zeichenfläche.malfläche) + { + zeichenfläche.alleSymbole.remove(this); + zeichenfläche.malfläche.repaint(); + } + } + + /** + * Bringt das Objekt eine Ebene nach vorn. + */ + void NachVornBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index < zeichenfläche.alleSymbole.size() - 1) + { + zeichenfläche.alleSymbole.set(index, zeichenfläche.alleSymbole.get(index + 1)); + zeichenfläche.alleSymbole.set(index + 1, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt in die vorderste Ebene. + */ + void GanzNachVornBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index < zeichenfläche.alleSymbole.size() - 1) + { + zeichenfläche.alleSymbole.remove(index); + zeichenfläche.alleSymbole.add(this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt eine Ebene nach hinten. + */ + void NachHintenBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index > 0) + { + zeichenfläche.alleSymbole.set(index, zeichenfläche.alleSymbole.get(index - 1)); + zeichenfläche.alleSymbole.set(index - 1, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Bringt das Objekt in die hinterste Ebene. + */ + void GanzNachHintenBringen () + { + synchronized (zeichenfläche.malfläche) + { + int index = zeichenfläche.alleSymbole.indexOf(this); + if (index > 0) + { + zeichenfläche.alleSymbole.remove(index); + zeichenfläche.alleSymbole.add(0, this); + zeichenfläche.malfläche.repaint(); + } + } + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return wahr, wenn der Punkt innerhalb der Figur ist + */ + boolean IstInnerhalb (int x, int y) + { + return form.contains(x, y); + } + + /** + * Testet, ob die beiden Figuren überlappen. + * @param wen die andere Form + * @return wahr, wenn die beiden Formen überlappen. + */ + boolean Schneidet (Area wen) + { + Area area = new Area(form); + area.intersect (wen); + return !area.isEmpty(); + } + + /** + * Zeichnet das Objekt + * @param g das Grafikobjekt zum Zeichnen + */ + void Zeichnen(Graphics g) + { + g.setColor(c); + ((Graphics2D) g).fill(form); + } + + /** + * Berechnet den Drehwinkel gemäß den Konventionen des Graphik-Frameworks. + * Für Java: Winkel in Radians, positive Drehrichtng im Uhrzeiger. + * @param winkel: Der Winkel in Grad, mathematischer Drehsinn + * @return Winkel für Graphik-Framework + */ + double DrehwinkelGeben (int winkel) + { + return - Math.PI * (winkel > 180 ? winkel - 360 : winkel) / 180.0; + } + + /** + * Erstellt die Form des Objekts. + */ + abstract void FormErzeugen(); + } + + /** + * Objekte dieser Klasse verwalten ein Rechteck. + */ + private class RechteckIntern extends GrafikSymbol + { + /** + * Erstellt die Form des Rechtecks. + */ + @Override void FormErzeugen() + { + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (new Rectangle2D.Double(this.x, this.y, b, h), a)); + } + } + + /** + * Objekte dieser Klasse verwalten eine Ellipse. + */ + private class EllipseIntern extends GrafikSymbol + { + /** + * Erstellt die Form der Ellipse. + */ + @Override void FormErzeugen() + { + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (new Ellipse2D.Double(this.x, this.y, b, h), a)); + } + } + + /** + * Objekte dieser Klasse verwalten ein Dreieck. + */ + private class DreieckIntern extends GrafikSymbol + { + /** + * Erstellt die Form des Dreiecks. + */ + @Override void FormErzeugen() + { + Polygon rand = new Polygon (new int [] {x + b / 2, x + b, x, x + b / 2}, + new int [] {y, y + h, y + h, y}, 4); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x + b / 2, this.y + h / 2); + form = new Area(new Path2D.Double (rand, a)); + } + } + + /** + * Objekte dieser Klasse verwalten einen Text. + */ + class TextIntern extends GrafikSymbol + { + /** Der aktuelle Text. */ + private String text; + /** Die aktuelle Textgröße. */ + float size; + + /** + * Belegt text und size mit Defaultwerten. + */ + TextIntern () + { + super(); + text = "Text"; + size = 12; + c = Color.black; + } + + /** + * Erstellt die Form des Textes. + * Dummy, legt ein leeres Area an. + */ + @Override void FormErzeugen() + { + form = new Area(); + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return falsch + */ + @Override boolean IstInnerhalb (int x, int y) + { + return false; + } + + /** + * Setzt den aktuellen Text. + * @param t der neue Text + */ + void TextSetzen (String t) + { + text = t; + zeichenfläche.malfläche.repaint(); + } + + /** + * Setzt die Größe des Textes. + */ + void TextGrößeSetzen (int größe) + { + size = größe; + zeichenfläche.malfläche.repaint(); + } + + /** + * Vergrößert den Text. + */ + void TextVergrößern() + { + if (size <= 10) + { + size += 1; + } + else if (size <= 40) + { + size += 2; + } + else + { + size += 4; + } + zeichenfläche.malfläche.repaint(); + } + + /** + * Verkleinert den Text. + */ + void TextVerkleinern() + { + if (size <= 10) + { + size -= 1; + } + else if (size <= 40) + { + size -= 2; + } + else + { + size -= 4; + } + if (size < 1) + { + size = 1; + } + zeichenfläche.malfläche.repaint(); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + g.setColor(c); + Font f = g.getFont(); + Font f2 = f.deriveFont(size); + g.setFont(f2); + + if (winkel == 0) + { + g.drawString(text, x, y); + } + else + { + Graphics2D g2 = (Graphics2D) g; + AffineTransform alt = g2.getTransform(); + //g2.rotate(DrehwinkelGeben (winkel), x + b / 2, y + h / 2); + //g2.rotate(DrehwinkelGeben (winkel), x + text.length() * size / 4, y + size / 2); + Rectangle2D bounds = f2.getStringBounds(text, g2.getFontRenderContext()); + g2.rotate(DrehwinkelGeben (winkel), x + bounds.getWidth() / 2, y - bounds.getHeight() / 2); + g.drawString(text, x, y); + g2.setTransform(alt); + } + g.setFont(f); + } + } + + /** + * Oberklasse für alle Elemente einer Figur (Figur, Turtle). + */ + private abstract class FigurenElement + { + double xe; + double ye; + double breite; + double höhe; + Color c; + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + abstract void ElementZeichnen(Graphics2D g, double größe, int x, int y); + + /** + * Fügt den Pfadteil deiser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + abstract void ElementZuForm (Path2D.Double p, double größe, int x, int y); + } + + /** + * Ein rechteckiges Figurenelement. + */ + private class FigurenElementRechteck extends FigurenElement + { + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinate der linken oberen Ecke des Rechtecks relativ zum Aufhängepunkt. + * @param y y-Koordinate der linken oberen Ecke des Rechtecks relativ zum Aufhängepunkt. + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param c Farbe des Rechtecks + */ + FigurenElementRechteck (double x, double y, double breite, double höhe, Color c) + { + this.xe = x; + this.ye = y; + this.breite = breite; + this.höhe = höhe; + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + g.fill(new Rectangle2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + p.append(new Rectangle2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0), false); + } + } + + /** + * Ein elliptisches Figurenelement. + */ + private class FigurenElementEllipse extends FigurenElement + { + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinate der linken oberen Ecke des umgebenden Rechtecks relativ zum Aufhängepunkt. + * @param y y-Koordinate der linken oberen Ecke des umgebenden Rechtecks relativ zum Aufhängepunkt. + * @param breite Breite der Ellipse + * @param höhe Höhe der Ellipse + * @param c Farbe der Ellipse + */ + FigurenElementEllipse (double x, double y, double breite, double höhe, Color c) + { + this.xe = x; + this.ye = y; + this.breite = breite; + this.höhe = höhe; + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + g.fill(new Ellipse2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + p.append(new Ellipse2D.Double (x+größe*xe/100.0, y+größe*ye/100.0, größe*breite/100.0, größe*höhe/100.0), false); + } + } + + /** + * Ein Figurenelement begrenzt durch das angegebene Polygon. + */ + private class FigurenElementPolygon extends FigurenElement + { + /** Das Polygonobjekt */ + private Polygon poly; + + /** + * Der Konstruktor speichert die Rahmendaten. + * @param x x-Koordinaten der Stützpunkte des Polygons relativ zum Aufhängepunkt. + * @param y y-Koordinaten der Stützpunkte des Polygons relativ zum Aufhängepunkt. + * @param c Farbe der Polygonfläche + */ + FigurenElementPolygon (int [] x, int[] y, Color c) + { + int anz = x.length <= y.length ? x.length : y.length; + poly = new Polygon (x, y, anz); + Rectangle2D bounds = poly.getBounds2D(); + xe = bounds.getX(); + ye = bounds.getY(); + breite = bounds.getWidth(); + höhe = bounds.getHeight(); + this.c = c; + } + + /** + * Zeichnet das Figurenelement. + * @param g das Grafikobjekt + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZeichnen(Graphics2D g, double größe, int x, int y) + { + g.setColor(c); + AffineTransform at = new AffineTransform(größe/100.0, 0, 0, größe/100.0, x, y); + g.fill(new Path2D.Double (poly, at)); + } + + /** + * Fügt den Pfadteil dieser Komponente zum umgebenden Pfad hinzu. + * @param p der Gesamtpfad + * @param größe die aktuelle Größe der Figur + * @param x die x-Koordinate des Aufhängepunkts der Figur + * @param y die y-Koordinate des Aufhängepunkts der Figur + */ + @Override void ElementZuForm (Path2D.Double p, double größe, int x, int y) + { + AffineTransform at = new AffineTransform(größe/100.0, 0, 0, größe/100.0, x, y); + Path2D.Double p2 = new Path2D.Double (poly, at); + p2.closePath(); + p2.setWindingRule(Path2D.WIND_EVEN_ODD); + p.append(p2, false); + } + } + + /** + * Das Objekt dieser Klasse zeichnet den Weg der Turtle. + */ + class TurtleIntern extends GrafikSymbol + { + private class LinienElement + { + /** x-Koordinate des Startpunktes. */ + private double xStart; + /** y-Koordinate des Startpunktes. */ + private double yStart; + /** x-Koordinate des Endpunktes. */ + private double xEnde; + /** y-Koordinate des Endpunktes. */ + private double yEnde; + /** Farbe des LinienElements. */ + private Color c; + + LinienElement (double xStart, double yStart, double xEnde, double yEnde, Color c) + { + this.xStart = xStart; + this.yStart = yStart; + this.xEnde = xEnde; + this.yEnde = yEnde; + this.c = c; + } + + void Zeichnen (Graphics2D g) + { + g.setColor(c); + g.draw(new Line2D.Double (xStart, yStart, xEnde, yEnde)); + } + } + + /** + * Verwaltet das Hintergrundfenster für die Turtlezeichnung. + */ + private class HintergrundBild + { + /** Das aktuelle Hintergrundbild. */ + private BufferedImage bild; + /** Das zugehörige Zeichenobjekt. */ + private Graphics2D g; + + /** + * Der Konstruktor legt das Bild in der Größe der Zeichenfläche an. + */ + HintergrundBild() + { + bild = new BufferedImage(Zeichenfenster.MalflächenBreiteGeben(), Zeichenfenster.MalflächenBreiteGeben(), BufferedImage.TYPE_INT_ARGB); + g = bild.createGraphics(); + g.setColor(new Color (0, 0, 0, 0)); + g.fillRect(0, 0, bild.getWidth(), bild.getHeight()); + } + + /** + * Zeichent die angegebe Linie in das Bild. + * @param linie das zu zeichnende Linienelement. + */ + void LinieZeichnen(LinienElement linie) + { + linie.Zeichnen(g); + } + + /** + * Zeichnet das Bild in das angegebene Zeichenobjekt. + * @param wohin Zeichenobjekt + */ + void BildZeichnen (Graphics2D wohin) + { + wohin.drawImage(bild, null, 0, 0); + } + } + + /** Genaue x-Koordinate der Turtle. */ + double xD; + /** Genaue y-Koordinate der Turtle. */ + double yD; + /** Startkoordinate der Turtle. */ + private int homeX; + /** Startkoordinate der Turtle. */ + private int homeY; + /** Startwinkel der Turtle. */ + private int homeWinkel; + /** Stiftposition. */ + boolean stiftUnten; + /** Die Sichtbarkeit des Turtle-Symbols. */ + private boolean symbolSichtbar; + /** Linienelemente. */ + private ArrayList<LinienElement> linien; + /** Standardfigur für Turtle. */ + private LinkedList<FigurenElement> standardFigur; + /** Das Hintergrundbild für die Linien. */ + private HintergrundBild hintergrund; + + /** + * Legt die Turtle mit Startpunkt (100|200) in Richtung 0˚ an. + */ + TurtleIntern () + { + super (); + x = 100; + y = 200; + xD = x; + yD = y; + h = 40; + b = 40; + homeX=x; + homeY=y; + homeWinkel=winkel; + c = Color.black; + stiftUnten = true; + symbolSichtbar = true; + linien = new ArrayList<LinienElement>(); + hintergrund = new HintergrundBild(); + standardFigur = new LinkedList<FigurenElement>(); + StandardfigurErzeugen(); + FormErzeugen(); + } + + /** + * Baut die Standardfigur aus den Elementen auf. + */ + private void StandardfigurErzeugen() + { + //Kopf + standardFigur.add(new FigurenElementEllipse(50, -12.5, 25, 25, Color.GREEN)); + //Beine + standardFigur.add(new FigurenElementEllipse(22.5, -32.5, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(40.0, -32.5, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(22.5, 15.0, 12.5, 17.5, Color.GREEN)); + standardFigur.add(new FigurenElementEllipse(40.0, 15.0, 12.5, 17.5, Color.GREEN)); + //Augen + standardFigur.add(new FigurenElementRechteck(67.5, -10.0, 5.0, 7.5, c)); + standardFigur.add(new FigurenElementRechteck(67.5, 2.5, 5.0, 7.5, c)); + //Schwanz + standardFigur.add(new FigurenElementEllipse(0, -3.75, 25, 7.5, c)); + //Rumpf + standardFigur.add(new FigurenElementEllipse(7.5, -23.75, 57.5, 47.5, braun)); + } + + /** + * Passt das Hintergrundbild an eine neue Größe der Zeichenfläche an. + */ + void NeueGrößeSetzen() + { + hintergrund = new HintergrundBild(); + for (LinienElement l: linien) + { + hintergrund.LinieZeichnen(l); + } + } + + /** + * Erstellt die Form der Turtle. + */ + @Override void FormErzeugen() + { + Area area = new Area(); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x, this.y); + double größe = h > b ? b : h; + if (standardFigur != null) + { + synchronized (standardFigur) + { + for (FigurenElement e: standardFigur) + { + Path2D.Double p = new Path2D.Double(); + e.ElementZuForm(p, größe, x, y); + area.add( new Area(new Path2D.Double (p, a))); + } + } + + } + form = area; + } + + /** + * Setzt die Position (der linken oberen Ecke) des Objekts. + * @param x x-Position der linken oberen Ecke + * @param y y-Position der linken oberen Ecke + */ + @Override void PositionSetzen (int x, int y) + { + super.PositionSetzen (x, y); + xD = x; + yD = y; + } + + /** + * Setzt die Turtle wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + x = homeX; + y = homeY; + xD = x; + yD = y; + winkel = homeWinkel; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bewegt die Turtle nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + double neuX = xD + Math.cos(DrehwinkelGeben (winkel)) * länge; + double neuY = yD + Math.sin(DrehwinkelGeben (winkel)) * länge; + if (stiftUnten) + { + synchronized (this) + { + LinienElement l = new LinienElement(xD, yD, neuX, neuY, c); + linien.add (l); + hintergrund.LinieZeichnen (l); + } + } + xD = neuX; + yD = neuY; + x =(int) Math.round(xD); + y =(int) Math.round(yD); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Dreht die Turtle + * @param grad Drehwinkel im Gradmass + */ + void Drehen(int grad) + { + winkel = WinkelNormieren(winkel + grad); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Versetzt Zeichenfläche und Turtle in den Ausgangszustand + */ + void Löschen() + { + linien.clear(); + hintergrund = new HintergrundBild(); + ZumStartpunktGehen(); + } + + /** + * Turtle wechselt in den Modus "nicht zeichnen" + */ + void StiftHeben() + { + stiftUnten = false; + } + + /** + * Turtle wechselt in den Modus "zeichnen" + */ + void StiftSenken() + { + stiftUnten = true; + } + + /** + * Schaltet die Sichtbarkeit des Turtlesymbols ein oder aus. + * Erlaubte Parameterwerte: true, false + * @param sichtbar (neue) Sichtbarkeit des Turtlesymbols + */ + void SichtbarkeitFürSymbolSetzen (boolean sichtbar) + { + symbolSichtbar = sichtbar; + zeichenfläche.malfläche.repaint(); + } + + /** + * Testet, ob der angegebene Punkt innerhalb der Figur ist. + * @param x x-Koordinate des zu testenden Punktes + * @param y y-Koordinate des zu testenden Punktes + * @return wahr, wenn der Punkt innerhalb der Figur ist + */ + + /** + * Testet, ob die Turtle eine (sichtbare) Figur berührt. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur sind + */ + boolean Berührt () + { + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.IstInnerhalb(x, y) && g.sichtbar && (!(g instanceof TurtleIntern) || ((TurtleIntern) g).symbolSichtbar)) + { + return true; + } + } + return false; + } + + /** + * Testet, ob die Turtle eine (sichtbare) Figur in der angegebenen Farbe berührt. + * Bei Überlappungen + * @param farbe die Farbe, die die berührte Figur haben muss. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (String farbe) + { + Color c2 = FarbeCodieren(farbe); + boolean ok = false; + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.IstInnerhalb(x, y) && g.sichtbar) + { + if (g instanceof TurtleIntern) + { + TurtleIntern t = (TurtleIntern) g; + if (t.symbolSichtbar) + { + for (FigurenElement e: t.standardFigur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + p = new Path2D.Double (p, a); + if (p.contains(x, y)) + { + ok = c2.equals(e.c); + } + } + } + } + else if (g instanceof FigurIntern) + { + FigurIntern t = (FigurIntern) g; + LinkedList<FigurenElement> figur = ((t.eigeneFigur == null) || (t.eigeneFigur.size() == 0)) ? t.standardFigur : t.eigeneFigur; + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + p = new Path2D.Double (p, a); + if (p.contains(x, y)) + { + ok = c2.equals(e.c); + } + } + } + else + { + ok = ok || c2.equals(g.c); + } + } + } + return ok; + } + + /** + * Testet, ob die Turtle die (sichtbare, ) angegebene Figur berührt. + * @param object das Objekt, das getestet werden soll. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (Object object) + { + GrafikSymbol s = null; + if (object instanceof Rechteck) + { + s = ((Rechteck) object).symbol; + } + else if (object instanceof Dreieck) + { + s = ((Dreieck) object).symbol; + } + else if (object instanceof Kreis) + { + s = ((Kreis) object).symbol; + } + else if (object instanceof Turtle) + { + s = ((Turtle) object).symbol; + } + else if (object instanceof Figur) + { + s = ((Figur) object).symbol; + } + return (s != null) && (s != this) && s.IstInnerhalb(x, y) && s.sichtbar && (!(s instanceof TurtleIntern) || ((TurtleIntern) s).symbolSichtbar); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + Graphics2D g2 = (Graphics2D) g; + synchronized (this) + { + hintergrund.BildZeichnen(g2); + } + + if (symbolSichtbar) + { + g.setColor(Color.black); + double größe = h > b ? b : h; + AffineTransform alt = g2.getTransform(); + g2.rotate(DrehwinkelGeben (winkel), x, y); + if (standardFigur != null) + { + synchronized (standardFigur) + { + for (FigurenElement e: standardFigur) + { + e.ElementZeichnen(g2, größe, x, y); + } + } + } + g2.setTransform(alt); + } + } + } + + /** + * Das Objekt dieser Klasse ist ein in der Gestalt definierbarer Akteur. + */ + class FigurIntern extends GrafikSymbol + { + + /** Genaue x-Koordinate der Figur. */ + double xD; + /** Genaue y-Koordinate der Figur. */ + double yD; + /** Startkoordinate der Figur. */ + private int homeX; + /** Startkoordinate der Figur. */ + private int homeY; + /** Startwinkel der Figur. */ + private int homeWinkel; + /** Eigene Figur für Figur. */ + private LinkedList<FigurenElement> eigeneFigur; + /** Standardfigur für Figur. */ + private LinkedList<FigurenElement> standardFigur; + + /** + * Legt die Figur mit Startpunkt (100|200) in Richtung 0˚ an. + */ + FigurIntern () + { + super (); + x = 100; + y = 200; + xD = x; + yD = y; + h = 40; + b = 40; + homeX=x; + homeY=y; + homeWinkel=winkel; + c = Color.black; + eigeneFigur = new LinkedList<FigurenElement>(); + standardFigur = new LinkedList<FigurenElement>(); + StandardfigurErzeugen(); + FormErzeugen(); + } + + /** + * Baut die Standardfigur aus den Elementen auf. + */ + private void StandardfigurErzeugen() + { + int[] x = new int [] {-50, 50, -50}; + int[] y = new int [] {-50, 0, 50}; + standardFigur.add (new FigurenElementPolygon (x, y, Color.yellow)); + standardFigur.add(new FigurenElementEllipse(-10, -10, 20, 20, Color.blue)); + } + + /** + * Erstellt die Form der Figur. + */ + @Override void FormErzeugen() + { + Area area = new Area(); + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (winkel), this.x, this.y); + double größe = h > b ? b : h; + if (standardFigur != null) + { + LinkedList<FigurenElement> figur = ((eigeneFigur == null) || (eigeneFigur.size() == 0)) ? standardFigur : eigeneFigur; + synchronized (figur) + { + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + e.ElementZuForm(p, größe, x, y); + area.add(new Area(new Path2D.Double (p, a))); + } + } + + } + form = area; + } + + /** + * Setzt die Position (der Mitte) des Objekts. + * @param x x-Position der Mitte + * @param y y-Position der Mitte + */ + @Override void PositionSetzen (int x, int y) + { + super.PositionSetzen (x, y); + xD = x; + yD = y; + } + + /** + * Setzt die Figur wieder an ihre Ausgangsposition. + */ + void ZumStartpunktGehen() + { + x = homeX; + y = homeY; + xD = x; + yD = y; + winkel = homeWinkel; + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Bewegt die Figur nach vorne. + * @param länge Anzahl der Längeneinheiten + */ + void Gehen(double länge) + { + double neuX = xD + Math.cos(DrehwinkelGeben (winkel)) * länge; + double neuY = yD + Math.sin(DrehwinkelGeben (winkel)) * länge; + xD = neuX; + yD = neuY; + x =(int) Math.round(xD); + y =(int) Math.round(yD); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Dreht die Figur + * @param grad Drehwinkel im Gradmass + */ + void Drehen(int grad) + { + winkel = WinkelNormieren(winkel + grad); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Testet, ob die Figur eine (sichtbare) Grafik-Figur berührt. + * @return true, wenn die Figurkoordinaten innerhalb einer Grafikfigur sind + */ + boolean Berührt () + { + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.Schneidet(form) && g.sichtbar && (!(g instanceof TurtleIntern) || ((TurtleIntern) g).symbolSichtbar)) + { + return true; + } + } + return false; + } + + /** + * Testet, ob die Figur eine (sichtbare) Grafik-Figur in der angegebenen Farbe berührt. + * Bei Überlappungen + * @param farbe die Farbe, die die berührte Figur haben muss. + * @return true, wenn die Figurkoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (String farbe) + { + Color c2 = FarbeCodieren(farbe); + boolean ok = false; + for (GrafikSymbol g: zeichenfläche.alleSymbole) + { + if ((g != this) && g.Schneidet(form) && g.sichtbar) + { + if (g instanceof TurtleIntern) + { + TurtleIntern t = (TurtleIntern) g; + if (t.symbolSichtbar) + { + Area[] areas = new Area [t.standardFigur.size()]; + Color[] colors = new Color [t.standardFigur.size()]; + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + int pos = 0; + for (FigurenElement e: t.standardFigur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + p = new Path2D.Double (p, a); + areas [pos] = new Area(p); + colors[pos] = e.c; + for (int i = pos - 1; i >= 0;i--) + { + areas[i].subtract(areas[pos]); + } + pos += 1; + } + for (int i = 0; i < areas.length; i++) + { + if (Schneidet(areas[i]) && (c2.equals(colors[i]))) + { + ok = true; + } + } + } + } + else if (g instanceof FigurIntern) + { + FigurIntern t = (FigurIntern) g; + LinkedList<FigurenElement> figur = ((t.eigeneFigur == null) || (t.eigeneFigur.size() == 0)) ? t.standardFigur : t.eigeneFigur; + Area[] areas = new Area [figur.size()]; + Color[] colors = new Color [figur.size()]; + AffineTransform a = new AffineTransform(); + a.rotate(DrehwinkelGeben (t.winkel), t.x, t.y); + int pos = 0; + for (FigurenElement e: figur) + { + Path2D.Double p = new Path2D.Double(); + double größe = t.h > t.b ? t.b : t.h; + e.ElementZuForm(p, größe, t.x, t.y); + p = new Path2D.Double (p, a); + areas [pos] = new Area(p); + colors[pos] = e.c; + for (int i = pos - 1; i >= 0;i--) + { + areas[i].subtract(areas[pos]); + } + pos += 1; + } + for (int i = 0; i < areas.length; i++) + { + if (Schneidet(areas[i]) && (c2.equals(colors[i]))) + { + ok = true; + } + } + } + else + { + ok = ok || c2.equals(g.c); + } + } + } + return ok; + } + + /** + * Testet, ob die Figur die (sichtbare, ) angegebene Grafik-Figur berührt. + * @param object das Objekt, das getestet werden soll. + * @return true, wenn die Turtlekoordinaten innerhalb einer Grafikfigur in der angegebenen Farbe sind + */ + boolean Berührt (Object object) + { + GrafikSymbol s = null; + if (object instanceof Rechteck) + { + s = ((Rechteck) object).symbol; + } + else if (object instanceof Dreieck) + { + s = ((Dreieck) object).symbol; + } + else if (object instanceof Kreis) + { + s = ((Kreis) object).symbol; + } + else if (object instanceof Turtle) + { + s = ((Turtle) object).symbol; + } + else if (object instanceof Figur) + { + s = ((Figur) object).symbol; + } + return (s != null) && (s != this) && s.Schneidet(form) && s.sichtbar && (!(s instanceof TurtleIntern) || ((TurtleIntern) s).symbolSichtbar); + } + + /** + * Erzeugt ein neues, rechteckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des Rechtecks + * @param y y-Wert der linken oberen Ecke des Rechtecks + * @param breite Breite des Rechtecks + * @param höhe Höhe des Rechtecks + * @param farbe (Füll)Farbe des Rechtecks + */ + void FigurteilFestlegenRechteck (int x, int y, int breite, int höhe, String farbe) + { + synchronized (eigeneFigur) + { + eigeneFigur.add(new FigurenElementRechteck(x, y, breite, höhe, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Erzeugt ein neues, elliptisches Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x x-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param y y-Wert der linken oberen Ecke des umgebenden Rechtecks der Ellipse + * @param breite Breite des umgebenden Rechtecks der Ellipse + * @param höhe Höhe des umgebenden Rechtecks der Ellipse + * @param farbe (Füll)Farbe der Ellipse + */ + void FigurteilFestlegenEllipse (int x, int y, int breite, int höhe, String farbe) + { + synchronized (eigeneFigur) + { + eigeneFigur.add(new FigurenElementEllipse(x, y, breite, höhe, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Erzeugt ein neues, dreieckiges Element einer eigenen Darstellung der Figur. + * Alle Werte beziehen sich auf eine Figur der Größe 100 und den Koordinaten (0|0) in der Mitte des Quadrats + * @param x1 x-Wert des ersten Punkts des Dreiecks + * @param y1 y-Wert des ersten Punkts des Dreiecks + * @param x2 x-Wert des zweiten Punkts des Dreiecks + * @param y2 y-Wert des zweiten Punkts des Dreiecks + * @param x3 x-Wert des dritten Punkts des Dreiecks + * @param y3 y-Wert des dritten Punkts des Dreiecks + * @param farbe (Füll)Farbe der Ellipse + */ + void FigurteilFestlegenDreieck (int x1, int y1, int x2, int y2, int x3, int y3, String farbe) + { + synchronized (eigeneFigur) + { + int[] x = new int [] {x1, x2, x3}; + int[] y = new int [] {y1, y2, y3}; + eigeneFigur.add(new FigurenElementPolygon(x, y, FarbeCodieren(farbe))); + } + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Löscht die Vereinbarung für die eigene Darstellung Figur. + * Die Figur wird wieder durch die Originalfigur dargestellt. + */ + void EigeneFigurLöschen() + { + eigeneFigur.clear(); + FormErzeugen(); + zeichenfläche.malfläche.repaint(); + } + + /** + * Zeichnet das Objekt als Dreieck in der gegebenen Farbe. + * @param g das Grafikobjekt zum Zeichnen + */ + @Override void Zeichnen(Graphics g) + { + Graphics2D g2 = (Graphics2D) g; + // Outline + g.setColor(Color.black); + Stroke stAlt = g2.getStroke(); + g2.setStroke(new BasicStroke(3.0f)); + g2.draw(form); + g2.setStroke(stAlt); + // Füllung + double größe = h > b ? b : h; + AffineTransform alt = g2.getTransform(); + g2.rotate(DrehwinkelGeben (winkel), x, y); + if (standardFigur != null) + { + LinkedList<FigurenElement> figur = ((eigeneFigur == null) || (eigeneFigur.size() == 0)) ? standardFigur : eigeneFigur; + synchronized (figur) + { + for (FigurenElement e: figur) + { + e.ElementZeichnen(g2, größe, x, y); + } + } + } + g2.setTransform(alt); + } + } +} |
