diff --git a/src/main/java/schule/ngb/zm/Color.java b/src/main/java/schule/ngb/zm/Color.java index 33c2033..578433f 100644 --- a/src/main/java/schule/ngb/zm/Color.java +++ b/src/main/java/schule/ngb/zm/Color.java @@ -3,17 +3,15 @@ package schule.ngb.zm; /** * Repräsentiert eine Farbe in der Zeichenmaschine. *
- * Farben bestehen entweder aus einem Grauwert (zwischen 0 und - * 255) oder einem Rot-, Grün- und Blauanteil (jeweils zwischen - * 0 und 255). + * Farben bestehen entweder aus einem Grauwert (zwischen 0 und 255) oder einem + * Rot-, Grün- und Blauanteil (jeweils zwischen 0 und 255). *
- * Eine Farbe hat außerdem einen Transparenzwert zwischen 0 - * (unsichtbar) und 255 (deckend). + * Eine Farbe hat außerdem einen Transparenzwert zwischen 0 (unsichtbar) und 255 + * (deckend). */ public class Color { - //@formatter:off /** * Die Farbe Schwarz (Grauwert 0). @@ -124,12 +122,12 @@ public class Color { /** * Erstellt eine Farbe. Die Parameter red, green und - * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte - * liegen zwischen 0 und 255. + * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die + * Werte liegen zwischen 0 und 255. * - * @param red Rotwert zwischen 0 und 255. + * @param red Rotwert zwischen 0 und 255. * @param green Grünwert zwischen 0 und 255. - * @param blue Blauwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. */ public Color( int red, int green, int blue ) { this(red, green, blue, 255); @@ -137,16 +135,14 @@ public class Color { /** * Erstellt eine Farbe. Die Parameter red, green und - * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte - * liegen zwischen 0 und 255. + * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die + * Werte liegen zwischen 0 und 255. * alpha gibt den den Transparentwert an (auch zwischen - * 0 und 255), wobei - * 0 komplett durchsichtig ist und 255 komplett - * deckend. + * 0 und 255), wobei 0 komplett durchsichtig ist und 255 komplett deckend. * - * @param red Rotwert zwischen 0 und 255. + * @param red Rotwert zwischen 0 und 255. * @param green Grünwert zwischen 0 und 255. - * @param blue Blauwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. * @param alpha Transparentwert zwischen 0 und 255. */ public Color( int red, int green, int blue, int alpha ) { @@ -184,10 +180,11 @@ public class Color { /** * Interner Konstruktor für die Initialisierung einer Farbe mit einem * RGBA-Wert. - * + *
* Da der Konstruktor {@link #Color(int)} schon besetzt ist, muss hier der - * Parameter {@code isRGBA} auf {@code true} gesetzt werden, damit {@code rgba} - * korrekt interpretiert wird. + * Parameter {@code isRGBA} auf {@code true} gesetzt werden, damit + * {@code rgba} korrekt interpretiert wird. + * * @param rgba RGBA-wert der Farbe. * @param isRGBA Sollte immer {@code true} sein. */ @@ -210,12 +207,12 @@ public class Color { return c; } - public static Color getHSBColor(double h, double s, double b) { - return new Color(java.awt.Color.getHSBColor((float)h, (float)s, (float)b)); + public static Color getHSBColor( double h, double s, double b ) { + return new Color(java.awt.Color.getHSBColor((float) h, (float) s, (float) b)); } - public static Color getHSLColor(double h, double s, double l) { - int rgb = Color.HSLtoRGB(new float[]{(float)h, (float)s, (float)l}); + public static Color getHSLColor( double h, double s, double l ) { + int rgb = Color.HSLtoRGB(new float[]{(float) h, (float) s, (float) l}); return Color.getRGBColor(rgb); } @@ -235,9 +232,9 @@ public class Color { } /** - * Erzeugt eine Farbe aus einem hexadezimalen Code. Der Hexcode kann - * sechs- oder achtstellig sein (wenn ein Transparentwert vorhanden ist). - * Dem Code kann ein {@code #} Zeichen vorangestellt sein. + * Erzeugt eine Farbe aus einem hexadezimalen Code. Der Hexcode kann sechs- + * oder achtstellig sein (wenn ein Transparentwert vorhanden ist). Dem Code + * kann ein {@code #} Zeichen vorangestellt sein. * * @param hexcode * @return @@ -336,10 +333,11 @@ public class Color { /** * Konvertiert eine Farbe mit Komponenten im HSL-Farbraum in den * RGB-Farbraum. - * + *
* Die Farbkomponenten werden als Float-Array übergeben. Im Index 0 steht * der h-Wert im Bereich 0 bis 360, Index 1 und 2 enthalten den s- und * l-Wert im Bereich von 0 bis 1. + * * @param hsl Die Farbkomponenten im HSL-Farbraum. * @param alpha Ein Transparenzwert im Bereich 0 bis 255. * @return Der RGBA-Wert der Farbe. @@ -392,6 +390,7 @@ public class Color { /** * Erzeugt eine Kopie dieser Farbe. + * * @return Ein neues Farbobjekt. */ public Color copy() { @@ -400,10 +399,11 @@ public class Color { /** * Gibt den RGBA-Wert dieser Farbe zurück. - * - * Eine Farbe wird als 32-Bit Integer gespeichert. Bits 24-31 enthalten - * den Transparenzwert, 16-23 den Rotwert, 8-15 den Grünwert und 0-7 den + *
+ * Eine Farbe wird als 32-Bit Integer gespeichert. Bits 24-31 enthalten den + * Transparenzwert, 16-23 den Rotwert, 8-15 den Grünwert und 0-7 den * Blauwert der Farbe. + * * @return Der RGBA-Wert der Farbe. * @see #getRed() * @see #getGreen() @@ -416,6 +416,7 @@ public class Color { /** * Gibt den Rotwert dieser Farbe zurück. + * * @return Der Rotwert der Farbe zwischen 0 und 255. */ public int getRed() { @@ -424,6 +425,7 @@ public class Color { /** * Gibt den Grünwert dieser Farbe zurück. + * * @return Der Grünwert der Farbe zwischen 0 und 255. */ public int getGreen() { @@ -432,6 +434,7 @@ public class Color { /** * Gibt den Blauwert dieser Farbe zurück. + * * @return Der Blauwert der Farbe zwischen 0 und 255. */ public int getBlue() { @@ -440,6 +443,7 @@ public class Color { /** * Gibt den Transparenzwert dieser Farbe zurück. + * * @return Der Transparenzwert der Farbe zwischen 0 und 255. */ public int getAlpha() { @@ -448,9 +452,10 @@ public class Color { /** * Erzeugt ein {@link java.awt.Color}-Objekt aus dieser Farbe. + *
+ * Das erzeugte Farbobjekt hat dieselben Rot-, Grün-, Blau- und + * Transparenzwerte wie diese Farbe. * - * Das erzeugte Farbobjekt hat dieselben Rot-, Grün-, Blau- - * und Transparenzwerte wie diese Farbe. * @return Ein Java-Farbobjekt. */ public java.awt.Color getJavaColor() { @@ -468,11 +473,12 @@ public class Color { * @return {@code true}, wenn die Objekte gleich sind, sonst {@code false}. */ public boolean equals( Object obj ) { - return obj instanceof Color && ((Color)obj).getRGBA() == this.rgba; + return obj instanceof Color && ((Color) obj).getRGBA() == this.rgba; } /** * Erzeugt einen Text-String, der diese Farbe beschreibt. + * * @return Eine Textversion der Farbe. */ @Override @@ -482,6 +488,7 @@ public class Color { /** * Berechnet einen Hashcode für dieses Farbobjekt. + * * @return Ein Hashcode für diese Rabe. */ @Override @@ -490,7 +497,8 @@ public class Color { } /** - * Erzeugt eine um 30% hellere Version dieser Farbe. + * Erzeugt eine um 30% hellere Version dieser Farbe. + * * @return Ein Farbobjekt mit einer helleren Farbe. */ public Color brighter() { @@ -499,6 +507,7 @@ public class Color { /** * Erzeugt eine um {@code percent} hellere Version dieser Farbe. + * * @param percent Eine Prozentzahl zwischen 0 und 100. * @return Ein Farbobjekt mit einer helleren Farbe. */ @@ -510,6 +519,7 @@ public class Color { /** * Erzeugt eine um 30% dunklere Version dieser Farbe. + * * @return Ein Farbobjekt mit einer dunkleren Farbe. */ public Color darker() { @@ -518,6 +528,7 @@ public class Color { /** * Erzeugt eine um {@code percent} dunklere Version dieser Farbe. + * * @param percent Eine Prozentzahl zwischen 0 und 100. * @return Ein Farbobjekt mit einer dunkleren Farbe. */ @@ -528,11 +539,12 @@ public class Color { } public Color greyscale() { - return new Color((int)(getRed()*.299 + getGreen()*.587 + getBlue()*0.114)); + return new Color((int) (getRed() * .299 + getGreen() * .587 + getBlue() * 0.114)); } /** * Erzeugt eine zu dieser invertierte Farbe. + * * @return Ein Farbobjekt mit der invertierten Farbe. */ public Color inverted() { @@ -542,6 +554,7 @@ public class Color { /** * Erzeugt die Komplementärfarbe zu dieser. + * * @return Ein Farbobjekt mit der Komplementärfarbe. */ public Color complement() { @@ -554,11 +567,12 @@ public class Color { * Wählt entweder {@link #WHITE weiß} oder {@link #BLACK schwarz} aus, je * nachdem, welche der Farben besser als Textfarbe mit dieser Farbe als * Hintergrund funktioniert (besser lesbar ist). + * * @return Schwarz oder weiß. */ public Color textcolor() { // Basiert auf https://stackoverflow.com/questions/946544/good-text-foreground-color-for-a-given-background-color - if( (getRed()*.299 + getGreen()*.587 + getBlue()*0.114) < 186 ) { + if( (getRed() * .299 + getGreen() * .587 + getBlue() * 0.114) < 186 ) { return WHITE; } else { return BLACK; diff --git a/src/main/java/schule/ngb/zm/Constants.java b/src/main/java/schule/ngb/zm/Constants.java index 561b3aa..a22bb6a 100644 --- a/src/main/java/schule/ngb/zm/Constants.java +++ b/src/main/java/schule/ngb/zm/Constants.java @@ -1,6 +1,7 @@ package schule.ngb.zm; import schule.ngb.zm.util.ImageLoader; +import schule.ngb.zm.util.Noise; import java.awt.Cursor; import java.awt.event.KeyEvent; @@ -8,6 +9,7 @@ import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.Random; +@SuppressWarnings( "unused" ) public class Constants { /** @@ -76,162 +78,287 @@ public class Constants { */ public static final int STD_BUFFER = 10; + /** + * Option für durchgezogene Konturen und Linien. + */ public static final Options.StrokeType SOLID = Options.StrokeType.SOLID; + /** + * Option für gestrichelte Konturen und Linien. + */ public static final Options.StrokeType DASHED = Options.StrokeType.DASHED; + /** + * Option für gepunktete Konturen und Linien. + */ public static final Options.StrokeType DOTTED = Options.StrokeType.DOTTED; + /** + * Option für Pfeile mit Strichen als Kopf. + */ public static final Options.ArrowHead LINES = Options.ArrowHead.LINES; + /** + * Option für Pfeile mit gefüllten Köpfen. + */ public static final Options.ArrowHead FILLED = Options.ArrowHead.FILLED; + /** + * Option für den Abschluss eines Pfades oder Bogens, ohne die Enden zu + * verbinden. + */ public static final Options.PathType OPEN = Options.PathType.OPEN; + /** + * Option für den Abschluss eines Pfades oder Bogens durch Verbindung der + * Enden des Bogens mit einer Linie. + */ public static final Options.PathType CLOSED = Options.PathType.CLOSED; + /** + * Option für den Abschluss eines Bogens durch Verbindung der Enden des + * Bogens mit dem Mittelpunkt der zugrundeliegenden Ellipse. Dadurch + * entsteht ein Kreisausschnitt. + */ public static final Options.PathType PIE = Options.PathType.PIE; + /** + * Richtung: Mitte (bzw. keine Richtung) + */ public static final Options.Direction CENTER = Options.Direction.CENTER; + /** + * Richtung: Norden + * + * @see #UP + */ public static final Options.Direction NORTH = Options.Direction.NORTH; + /** + * Richtung: Osten + * + * @see #RIGHT + */ public static final Options.Direction EAST = Options.Direction.EAST; + /** + * Richtung: Süden + * + * @see #DOWN + */ public static final Options.Direction SOUTH = Options.Direction.SOUTH; + /** + * Richtung: Westen + * + * @see #LEFT + */ public static final Options.Direction WEST = Options.Direction.WEST; + /** + * Richtung: Nordosten + * + * @see #UPLEFT + */ public static final Options.Direction NORTHEAST = Options.Direction.NORTHEAST; + /** + * Richtung: Südosten + * + * @see #DOWNLEFT + */ public static final Options.Direction SOUTHEAST = Options.Direction.SOUTHEAST; + /** + * Richtung: Nordwesten + * + * @see #UPRIGHT + */ public static final Options.Direction NORTHWEST = Options.Direction.NORTHWEST; + /** + * Richtung: Südwesten + * + * @see #DOWNRIGHT + */ public static final Options.Direction SOUTHWEST = Options.Direction.SOUTHWEST; + /** + * Richtung: Mitte + * + * @see #CENTER + */ public static final Options.Direction MIDDLE = Options.Direction.MIDDLE; + /** + * Richtung: Oben + * + * @see #NORTH + */ public static final Options.Direction UP = Options.Direction.UP; + /** + * Richtung: Rechts + * + * @see #EAST + */ public static final Options.Direction RIGHT = Options.Direction.RIGHT; + /** + * Richtung: Unten + * + * @see #SOUTH + */ public static final Options.Direction DOWN = Options.Direction.DOWN; + /** + * Richtung: Links + * + * @see #WEST + */ public static final Options.Direction LEFT = Options.Direction.LEFT; /** - * Schwarz + * Richtung: Oben links + * + * @see #NORTHWEST + */ + public static final Options.Direction UPLEFT = Options.Direction.UPLEFT; + + /** + * Richtung: Unten links + * + * @see #SOUTHWEST + */ + public static final Options.Direction DOWNLEFT = Options.Direction.DOWNLEFT; + + /** + * Richtung: Oben rechts + * + * @see #UPRIGHT + */ + public static final Options.Direction UPRIGHT = Options.Direction.UPRIGHT; + + /** + * Richtung: Unten rechts + * + * @see #SOUTHEAST + */ + public static final Options.Direction DOWNRIGHT = Options.Direction.DOWNRIGHT; + + + /** + * Farbe: Schwarz */ public static final Color BLACK = Color.BLACK; /** - * Weiß + * Farbe: Weiß */ public static final Color WHITE = Color.WHITE; /** - * Grau + * Farbe: Grau */ public static final Color GRAY = Color.GRAY; /** - * Dunkelgrau + * Farbe: Dunkelgrau */ public static final Color DARKGRAY = Color.DARKGRAY; /** - * Hellgrau + * Farbe: Hellgrau */ public static final Color LIGHTGRAY = Color.LIGHTGRAY; /** - * Rot + * Farbe: Rot */ public static final Color RED = Color.RED; /** - * Blau + * Farbe: Blau */ public static final Color BLUE = Color.BLUE; /** - * Grün + * Farbe: Grün */ public static final Color GREEN = Color.GREEN; /** - * Gelb + * Farbe: Gelb */ public static final Color YELLOW = Color.YELLOW; /** - * Orange + * Farbe: Orange */ public static final Color ORANGE = Color.ORANGE; /** - * Türkis + * Farbe: Türkis */ public static final Color CYAN = Color.CYAN; /** - * Magenta + * Farbe: Magenta */ public static final Color MAGENTA = Color.MAGENTA; /** - * Pink + * Farbe: Pink */ public static final Color PINK = Color.PINK; /** - * Lila + * Farbe: Lila */ public static final Color PURPLE = Color.PURPLE; /** - * Braun + * Farbe: Braun */ public static final Color BROWN = Color.BROWN; /** * Standardfarbe für den Hintergrund. */ - public static final Color STD_BACKGROUND = new Color(200, 200, 200); + public static Color DEFAULT_BACKGROUND = new Color(200, 200, 200); /** - * Konstante zur Prüfung, ob ein Mausknopf gedrückt wurde. + * Konstante zur Prüfung, ob kein Mausknopf gedrückt wurde. */ - public static final int NOBUTTON = MouseEvent.NOBUTTON; + public static final int NOMOUSE = MouseEvent.NOBUTTON; /** * Konstante zur Prüfung, ob Mausknopf 1 (links) gedrückt wurde. */ - public static final int BUTTON1 = MouseEvent.BUTTON1; + public static final int MOUSE1 = MouseEvent.BUTTON1; /** * Konstante zur Prüfung, ob Mausknopf 2 (rechts) gedrückt wurde. */ - public static final int BUTTON2 = MouseEvent.BUTTON2; + public static final int MOUSE2 = MouseEvent.BUTTON2; /** * Konstante zur Prüfung, ob Mausknopf 3 (mittig) gedrückt wurde. */ - public static final int BUTTON3 = MouseEvent.BUTTON3; + public static final int MOUSE3 = MouseEvent.BUTTON3; /** - * Konstante für die Kreiszahl Pi. + * Konstante für die Kreiszahl Pi (entspricht 180 Grad). */ public static final double PI = Math.PI; /** - * Konstante für die Hälfte der Kreiszahl Pi. + * Konstante für die Hälfte der Kreiszahl Pi (entspricht 90 Grad). */ public static final double HALF_PI = Math.PI / 2.0; /** - * Konstante für ein Viertel der Kreiszahl Pi. + * Konstante für ein Viertel der Kreiszahl Pi (entspricht 45 Grad). */ public static final double QUARTER_PI = Math.PI / 4.0; @@ -240,8 +367,7 @@ public class Constants { */ public static final double TWO_PI = Math.PI * 2.0; - - /** + /* * Globale Variablen, die von allen Klassen genutzt werden dürfen. Änderungen * wirken sich auf die aktuelle Zeichenmaschine aus und sollten nur von der * Zeichenmaschine selbst vorgenommen werden. @@ -268,70 +394,86 @@ public class Constants { public static double delta = 0.0; /** - * Die aktuelle {@code x}-Koordinate der Maus. + * Die aktuelle {@code x}-Koordinate der Maus. (Wird einmal pro Frame + * aktualisiert.) */ public static double mouseX = 0.0; /** - * Die aktuelle {@code y}-Koordinate der Maus. + * Die aktuelle {@code y}-Koordinate der Maus. (Wird einmal pro Frame + * aktualisiert.) */ public static double mouseY = 0.0; /** - * Die letzte {@code x}-Koordinate der Maus (wird einmal pro Frame + * Die letzte {@code x}-Koordinate der Maus. (Wird einmal pro Frame * aktualisiert). */ public static double pmouseX = 0.0; /** - * Die letzte {@code y}-Koordinate der Maus (wird einmal pro Frame - * aktualisiert). + * Die letzte {@code y}-Koordinate der Maus. (Wird einmal pro Frame + * aktualisiert.) */ public static double pmouseY = 0.0; /** - * Die aktuelle (current) {@code x}-Koordinate der Maus - * (wird bei jeder Mausbewegung aktualisiert). + * Die aktuelle (current) {@code x}-Koordinate der Maus. (Wird bei + * jeder Mausbewegung aktualisiert). */ public static double cmouseX = 0.0; /** - * Die aktuelle (current) {@code y}-Koordinate der Maus - * (wird bei jeder Mausbewegung aktualisiert). + * Die aktuelle (current) {@code y}-Koordinate der Maus. (Wird bei + * jeder Mausbewegung aktualisiert). */ public static double cmouseY = 0.0; /** - * Gibt an, ob ein Mausknopf derzeit gedrückt ist. + * Gibt an, ob derzeit ein Mausknopf gedrückt ist. */ public static boolean mousePressed = false; /** * Der aktuell gedrückte Mausknopf. Die Mausknöpfe werden durch die - * Konstanten {@link #NOBUTTON}, {@link #BUTTON1}, {@link #BUTTON2} und - * {@link #BUTTON3} angegeben. (Sie stimmen mit den Konstanten in - * {@link MouseEvent} überein. - * - * @see MouseEvent + * Konstanten {@link #NOMOUSE}, {@link #MOUSE1}, {@link #MOUSE2} und + * {@link #MOUSE3} angegeben. */ - public static int mouseButton = NOBUTTON; + public static int mouseButton = NOMOUSE; /** * Das zuletzt ausgelöste {@code MouseEvent}. */ public static MouseEvent mouseEvent; - // Mauszeiger + /** + * Mauszeiger: Pfeil + */ public static final int ARROW = Cursor.DEFAULT_CURSOR; + /** + * Mauszeiger: Fadenkreuz + */ public static final int CROSS = Cursor.CROSSHAIR_CURSOR; + /** + * Mauszeiger: Hand + */ public static final int HAND = Cursor.HAND_CURSOR; + /** + * Mauszeiger: Bewegungspfeile + */ public static final int MOVE = Cursor.MOVE_CURSOR; + /** + * Mauszeiger: Textzeiger + */ public static final int TEXT = Cursor.TEXT_CURSOR; + /** + * Mauszeiger: Ladezeiger + */ public static final int WAIT = Cursor.WAIT_CURSOR; /** @@ -340,14 +482,16 @@ public class Constants { public static boolean keyPressed = false; /** - * Das Zeichen der zuletzt gedrückten Taste. + * Das Text-Zeichen der zuletzt gedrückten Taste. Für Tasten ohne + * zugeordnetes Zeichen ist das Zeichen leer. */ public static char key = ' '; /** * Der Tastencode der zuletzt gedrückten Taste. Die Keycodes können in der - * Klasse {@link KeyEvent} nachgesehen werden. (Zum Beispiel - * {@link KeyEvent#VK_ENTER}.) + * Klasse {@link KeyEvent} nachgesehen werden. Die Keycodes für die + * wichtigsten Tasten sind als Konstanten mit dem Prefix {@code KEY_} + * vorhanden. (Zum Beispiel {@link #KEY_A}.) */ public static int keyCode = 0; @@ -359,12 +503,12 @@ public class Constants { /** * Die Höhe der Zeichenleinwand. */ - public static int width; + public static int canvasWidth; /** * Die Breite der Zeichenleinwand. */ - public static int height; + public static int canvasHeight; /** * Die Breite des Bildschirms, auf dem das Zeichenfenster geöffnet wurde. @@ -387,8 +531,11 @@ public class Constants { /** * Erstellt eine graue Farbe. Der Parameter {@code gray} gibt einen Grauwert - * zwischen 0 und 255 an, wobei - * 0 schwarz und 255 weiß ist. + * zwischen 0 und 255 an, wobei 0 schwarz und 255 weiß ist. + * + *
+ * Color iron_grey = color(94);
+ *
*
* @param gray Grauwert zwischen 0 und 255.
* @return Ein passendes Farbobjekt.
@@ -399,16 +546,16 @@ public class Constants {
/**
* Erstellt eine graue Farbe. Der Parameter {@code gray} gibt einen Grauwert
- * zwischen 0 und 255 an, wobei
- * 0 schwarz und 255 weiß ist.
- * {@code alpha} gibt den den Transparentwert an (auch zwischen
- * 0 und 255), wobei
- * 0 komplett durchsichtig ist und 255 komplett
- * deckend.
+ * zwischen 0 und 255 an, wobei 0 schwarz und 255 weiß ist. {@code alpha}
+ * gibt den Transparenzwert an (auch zwischen 0 und 255), wobei 0 komplett
+ * durchsichtig ist und 255 komplett deckend.
+ *
+ *
+ * Color iron_grey_50 = color(94, 50);
+ *
*
* @param gray Grauwert zwischen 0 und 255.
- * @param alpha Transparentwert zwischen 0 und
- * 255.
+ * @param alpha Transparenzwert zwischen 0 und 255.
* @return Ein passendes Farbobjekt.
*/
public static final Color color( int gray, int alpha ) {
@@ -420,6 +567,10 @@ public class Constants {
* {@code blue} geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte
* liegen zwischen 0 und 255.
*
+ *
+ * Color arctic_blue = color(149, 214, 220);
+ *
+ *
* @param red Rotwert zwischen 0 und 255.
* @param green Grünwert zwischen 0 und 255.
* @param blue Blauwert zwischen 0 und 255.
@@ -432,17 +583,18 @@ public class Constants {
/**
* Erstellt eine Farbe. Die Parameter {@code red}, {@code green} und
* {@code blue} geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte
- * liegen zwischen 0 und 255. {@code alpha} gibt
- * den den Transparentwert an (auch zwischen 0 und
- * 255), wobei
- * 0 komplett durchsichtig ist und 255 komplett
- * deckend.
+ * liegen zwischen 0 und 255. {@code alpha} gibt den Transparenzwert an
+ * (auch zwischen 0 und 255), wobei 0 komplett durchsichtig ist und 255
+ * komplett deckend.
+ *
+ *
+ * Color arctic_blue_50 = color(149, 214, 220, 50);
+ *
*
* @param red Rotwert zwischen 0 und 255.
* @param green Grünwert zwischen 0 und 255.
* @param blue Blauwert zwischen 0 und 255.
- * @param alpha Transparenzwert zwischen 0 und
- * 255.
+ * @param alpha Transparenzwert zwischen 0 und 255.
* @return Ein passendes Farbobjekt.
*/
public static final Color color( int red, int green, int blue, int alpha ) {
@@ -455,6 +607,10 @@ public class Constants {
* Alle Farbkomponenten (Rot, Grün und Blau) werden zufällig im Bereich 0
* bis 255 gewählt.
*
+ *
+ * Color fillColor = randomColor();
+ *
+ *
* @return Ein zufälliges Farbobjekt.
*/
public static final Color randomColor() {
@@ -465,6 +621,10 @@ public class Constants {
* Erzeugt eine "hübsche" zufällige Farbe. Die Farbe wird so gewählt, dass
* die Farben nicht zu verwaschen oder dunkel wirken.
*
+ *
+ * Color fillColor = randomNiceColor();
+ *
+ *
* @return Ein zufälliges Farbobjekt.
*/
public static final Color randomNiceColor() {
@@ -480,6 +640,10 @@ public class Constants {
* und die Sättigung (saturation) und Hellwert (brightness) im Bereich 0 bis
* 100.
*
+ *
+ * Color arctic_blue = colorHsl(185, 32, 86);
+ *
+ *
* @param h Farbton im Bereich 0 bis 360.
* @param s Sättigung im Bereich 0 bis 100.
* @param b Hellwert im Bereich 0 bis 100.
@@ -498,6 +662,10 @@ public class Constants {
* und die Sättigung (saturation) und Helligkeit (lightness) im Bereich 0
* bis 100.
*
+ *
+ * Color arctic_blue = colorHsl(185, 50, 72);
+ *
+ *
* @param h Farbton im Bereich 0 bis 360.
* @param s Sättigung im Bereich 0 bis 100.
* @param l Helligkeit im Bereich 0 bis 100.
@@ -509,14 +677,27 @@ public class Constants {
return Color.getHSLColor(h % 360.0, s / 100.0, l / 100.0);
}
- public static final BufferedImage loadImage( String name ) {
- return ImageLoader.loadImage(name);
+ // Ressourcen
+
+ /**
+ * Lädt ein Bild aus einer Datei oder von einer Webadresse.
+ *
+ * @param source Ein Dateipfad oder eine Webadresse.
+ * @return Das geladene Bild.
+ * @see ImageLoader#loadImage(String)
+ */
+ public static final BufferedImage loadImage( String source ) {
+ return ImageLoader.loadImage(source);
}
// Mathematische Funktionen
/**
- * Berechnet das Minimum aller übergebenen Werte.
+ * Berechnet das Minimum aller angegebenen Werte.
+ *
+ *
+ * double minimum = min(1.0, 5.1, 3.2); // 1.0
+ *
*
* @param numbers Die Werte, aus denen das Minimum ermittelt werden soll.
* @return Das Minimum der Werte.
@@ -536,7 +717,11 @@ public class Constants {
}
/**
- * Berechnet das Maximum aller übergebenen Werte.
+ * Berechnet das Maximum aller angegebenen Werte.
+ *
+ *
+ * double maximum = max(1.0, 5.1, 3.2); // 5.1
+ *
*
* @param numbers Die Werte, aus denen das Maximum ermittelt werden soll.
* @return Das Maximum der Werte.
@@ -555,18 +740,39 @@ public class Constants {
return max;
}
+ /**
+ * Berechnet die Summe alle angegebenen Werte.
+ *
+ *
+ * double summe = sum(1.0, 2.0, 3.2); // 6.2
+ *
+ *
+ * @param numbers Die Werte, aus denen die Summe berechnet werden soll.
+ * @return Die Summe der Werte.
+ */
public static final double sum( double... numbers ) {
if( numbers == null ) {
throw new IllegalArgumentException("Array may not be
+ * double summe = sum(1.0, 2.2, 3.1); // 2.1
+ *
+ *
+ * @param numbers Die Werte, aus denen der MIttelwert berechnet werden
+ * soll.
+ * @return Der Mittelwert der Werte.
+ */
public static final double avg( double... numbers ) {
if( numbers == null || numbers.length == 0 ) {
throw new IllegalArgumentException("Array may not be
+ * double positiv = abs(-3.2); // 3.2
+ *
*
* @param x Eine Zahl.
* @return Der Absolutbetrag.
@@ -586,7 +796,11 @@ public class Constants {
}
/**
- * Ermittelt das Vorzeichen der Zahl {@code x}.
+ * Ermittelt das Vorzeichen der angegebenen Zahl.
+ *
+ *
+ * double vorzeichen = sign(-3.2); // -1.0
+ *
*
* @param x Eine Zahl.
* @return -1, 1 oder 0.
@@ -596,7 +810,11 @@ public class Constants {
}
/**
- * Rundet die Zahl {@code x}.
+ * Rundet die angegebene Zahl auf die nächste ganze Zahl.
+ *
+ *
+ * double gerundet = sign(3.2); // 3.0
+ *
*
* @param x Eine Zahl.
* @return Die gerundete Zahl.
@@ -606,7 +824,11 @@ public class Constants {
}
/**
- * Rundet die Zahl {@code x} ab.
+ * Rundet die angegebene Zahl ab.
+ *
+ *
+ * double abgerundet = sign(3.2); // 3.0
+ *
*
* @param x Eine Zahl.
* @return Die abgerundete Zahl.
@@ -616,7 +838,11 @@ public class Constants {
}
/**
- * Rundet die Zahl {@code x} auf.
+ * Rundet die angegebene Zahl auf.
+ *
+ *
+ * double aufgerundet = sign(3.2); // 4.0
+ *
*
* @param x Eine Zahl.
* @return Die aufgerundete Zahl.
@@ -626,7 +852,11 @@ public class Constants {
}
/**
- * Ermittelt die Quadratwurzel der Zahl {@code x}.
+ * Ermittelt die Quadratwurzel der angegebenen Zahl.
+ *
+ *
+ * double wurzel = sqrt(16); // 4.0
+ *
*
* @param x Eine Zahl.
* @return Die Quadratwurzel.
@@ -636,19 +866,27 @@ public class Constants {
}
/**
- * Ermittelt die Potenz der Zahl {@code x} zum Exponenten {@code p}.
+ * Ermittelt die Potenz der angegebenen Zahl zum angegebenen Exponenten.
+ *
+ *
+ * double hoch4 = sqrt(8, 4); // 4096.0
+ *
*
* @param x Eine Zahl.
- * @param p Der Exponent.
- * @return {@code x} hoch {@code p}.
+ * @param e Der Exponent.
+ * @return {@code x} hoch {@code e}.
*/
- public static final double pow( double x, double p ) {
- return Math.pow(x, p);
+ public static final double pow( double x, double e ) {
+ return Math.pow(x, e);
}
/**
* Rechnet von Grad in Radian um.
*
+ *
+ * double radian = radians(360); // 6.28318530717959
+ *
+ *
* @param angle Ein Winkel in Grad.
* @return Der Winkel in Radian.
*/
@@ -657,7 +895,11 @@ public class Constants {
}
/**
- * Rechent von Radian in Grad um.
+ * Rechnet von Radian in Grad um.
+ *
+ *
+ * double grad = radians(HALF_PI); // 90.0
+ *
*
* @param radians Der Winkel in Radian.
* @return Der Winkel in Grad.
@@ -667,7 +909,11 @@ public class Constants {
}
/**
- * Ermittelt den Sinus der Zahl {@code x}.
+ * Ermittelt den Sinus der angegebenen Zahl.
+ *
+ *
+ * double sinus = sin(0.0); // 0.0
+ *
*
* @param x Eine Zahl.
* @return {@code sin(x)}.
@@ -677,7 +923,11 @@ public class Constants {
}
/**
- * Ermittelt den Kosinus der Zahl {@code x}.
+ * Ermittelt den Kosinus der angegebenen Zahl.
+ *
+ *
+ * double kosinus = cos(0.0); // 1.0
+ *
*
* @param x Eine Zahl.
* @return {@code cos(x)}.
@@ -687,7 +937,11 @@ public class Constants {
}
/**
- * Ermittelt den Tangens der Zahl {@code x}.
+ * Ermittelt den Tangens der angegebenen Zahl.
+ *
+ *
+ * double sinus = tan(1.0); // 1.5574077246549
+ *
*
* @param x Eine Zahl.
* @return {@code tan(x)}.
@@ -697,7 +951,7 @@ public class Constants {
}
/**
- * Ermittelt den Arkussinus der Zahl {@code x}.
+ * Ermittelt den Arkussinus der angegebenen Zahl.
*
* @param x Eine Zahl.
* @return {@code asin(x)}.
@@ -707,7 +961,7 @@ public class Constants {
}
/**
- * Ermittelt den Arkuskosinus der Zahl {@code x}.
+ * Ermittelt den Arkuskosinus der angegebenen Zahl.
*
* @param x Eine Zahl.
* @return {@code acos(x)}.
@@ -717,7 +971,7 @@ public class Constants {
}
/**
- * Ermittelt den Arkusktangens der Zahl {@code x}.
+ * Ermittelt den Arkusktangens der angegebenen Zahl.
*
* @param x Eine Zahl.
* @return {@code atan(x)}.
@@ -727,11 +981,17 @@ public class Constants {
}
/**
- * Beschränkt die Zahl {@code x} auf das Intervall {@code [min, max]}.
+ * Beschränkt die angegebene Zahl auf das Intervall {@code [min, max]}.
* Liegt {@code x} außerhalb des Intervalls, wird eine der Grenzen
* zurückgegeben.
*
+ *
+ * double beschraenkt1 = limit(2.1, 0.0, 3.0); // 2.1
+ * double beschraenkt2 = limit(4.1, 0.0, 3.0); // 1.0
+ *
+ *
* @param x Eine Zahl.
+ * @param min Das Minimum des Intervalls.
* @param max Das Maximum des Intervalls.
* @return Eine Zahl im Intervall {@code [min, max]}.
*/
@@ -746,22 +1006,28 @@ public class Constants {
}
/**
- * Beschränkt die Zahl {@code x} auf das Intervall {@code [min, max]}.
- * Liegt {@code x} außerhalb des Intervalls, wird eine der Grenzen
+ * Beschränkt die angegebene Zahl auf das Intervall {@code [min, max]}.
+ * Liegt {@code i} außerhalb des Intervalls, wird eine der Grenzen
* zurückgegeben.
*
- * @param x Eine Zahl.
+ *
+ * double beschraenkt1 = limit(2, 0, 3); // 2
+ * double beschraenkt2 = limit(4, 0, 3); // 3
+ *
+ *
+ * @param i Eine Zahl.
+ * @param min Das Minimum des Intervalls.
* @param max Das Maximum des Intervalls.
* @return Eine Zahl im Intervall {@code [min, max]}.
*/
- public static final int limit( int x, int min, int max ) {
- if( x > max ) {
+ public static final int limit( int i, int min, int max ) {
+ if( i > max ) {
return max;
}
- if( x < min ) {
+ if( i < min ) {
return min;
}
- return x;
+ return i;
}
/**
@@ -771,30 +1037,91 @@ public class Constants {
* * from - t * (from + to) *+ *
+ * In der Regel liegt {@code t} im Intervall {@code [0, 1]}. Für + * {@code t = 0} ist das Ergebnis {@code from} und für {@code t = 1} ist das + * Ergebnis {@code to}. {@code t} kann aber auch Werte außerhalb des + * Intervalls annehmen. Für {@code t = 2} ist das Ergebnis beispielsweise + * {@code 2*to}; + * + *
+ * double interpoliert = interpolate(100.0, 500.0, 0.5); // 300.0
+ * double interpoliert = interpolate(100.0, 500.0, 1.0); // 500.0
+ * double interpoliert = interpolate(100.0, 500.0, 1.5); // 750.0
+ *
*
* @param from Startwert
* @param to Zielwert
- * @param t Wert zwischen 0 und 1.
+ * @param t Anteil des Ergebnisses auf der Strecke zwischen {@code from}
+ * und {@code to}.
* @return Das Ergebnis der linearen Interpolation.
*/
public static final double interpolate( double from, double to, double t ) {
return from + t * (to - from);
}
+ /**
+ * Interpoliert einen Wert zwischen {@code from} und {@code to}, aber
+ * beschränkt {@code t} auf das Intervall {@code [0, 1]}.
+ *
+ *
+ * double interpoliert = interpolate(100.0, 500.0, 0.5); // 300.0
+ * double interpoliert = interpolate(100.0, 500.0, 1.0); // 500.0
+ * double interpoliert = interpolate(100.0, 500.0, 1.5); // 500.0
+ *
+ *
+ * @param from Startwert
+ * @param to Zielwert
+ * @param t Wert zwischen 0 und 1.
+ * @return
+ * @see #interpolate(double, double, double)
+ */
public static final double morph( double from, double to, double t ) {
return interpolate(from, to, limit(t, 0.0, 1.0));
}
+ /**
+ * Bestimmt für den angegebenen Wert aus dem Intervall
+ * {@code [fromMin, fromMax]} einen zugehörigen Wert aus dem Intervall
+ * {@code [toMin, toMax]}.
+ * + * Für {@code value = fromMin} wird {@code toMin} zurückgegeben. Für + * {@code value = fromMax} ist das Ergebnis {@code toMax}. Befindet sich + * {@code value} genau mittig zwischen {@code fromMin} und {@code fromMax}, + * dann ist das Ergebnis genau {@code interpolate(toMin, toMax, 0.5)}. + *
+ * Mit {@code map()} lassen sich Werte eines Originalintervalls auf ein + * Zielintervalls transponieren. Dies ist beispielsweise hilfreich, um aus + * der Mausbewegung die relative Position auf der Zeichenfläche zu + * bestimmen: + * + *
+ * double relativeMouseX = map(mouseX, 0.0, canvasWidth, 0.0, 1.0);
+ *
+ *
+ * @param value Der Wert aus dem original Intervall.
+ * @param fromMin Untere Grenze des original Intervalls.
+ * @param fromMax Obere Grenze des original Intervalls.
+ * @param toMin Untere Grenze des Zielintervalls.
+ * @param toMax Obere Grenze des Zielintervalls.
+ * @return Der zugehörige Wert aus dem Zielintervall.
+ * @see #interpolate(double, double, double)
+ */
public static final double map( double value, double fromMin, double fromMax, double toMin, double toMax ) {
return interpolate(toMin, toMax, (value - fromMin) / (fromMax - fromMin));
}
/**
- * Shared Random instance
+ * Geteilte {@code Random}-Instanz für einheitliche Zufallszahlen.
*/
private static Random random = null;
- private static final Random getRandom() {
+ /**
+ * Gibt die geteilte {@code Random}-Instanz zurück.
+ *
+ * @return Die {@code Random}-Instanz.
+ */
+ private static Random getRandom() {
if( random == null ) {
random = new Random();
}
@@ -885,8 +1212,7 @@ public class Constants {
* Erzeugt einen zufälligen Wahrheitswert. {@code true} wird mit der
* Wahrscheinlichkeit {@code percent} Prozent erzeugt.
*
- * @param percent Eine Prozentzahl zwischen 0 und
- * 100.
+ * @param percent Eine Prozentzahl zwischen 0 und 100.
* @return Ein Wahrheitswert.
*/
public static final boolean randomBool( int percent ) {
@@ -897,6 +1223,7 @@ public class Constants {
* Erzeugt einen zufälligen Wahrheitswert. {@code true} wird mit der
* Wahrscheinlichkeit {@code weight} erzeugt.
*
+ * @param weight Wahrscheinlichkeit für {@code true}.
* @return Ein Wahrheitswert.
*/
public static final boolean randomBool( double weight ) {
@@ -917,6 +1244,7 @@ public class Constants {
* Wählt ein zufälliges Element aus dem Array aus.
*
* @param values Ein Array mit Werten, die zur Auswahl stehen.
+ * @param
+ * int bin = binary(10); // "1010"
+ *
+ *
+ * @param i Eine Zahl.
+ * @return Die binäre Darstellung der Zahl als Text.
+ */
+ public static final String binary( int i ) {
+ return Integer.toBinaryString(i);
+ }
+
+ /**
+ * Formt die angegebene Binärzahl in eine Dezimalzahl um.
+ *
+ *
+ * int dezimal = romBinary("1010"); // 10
+ *
+ *
+ * @param binary Ein Text nur aus "0" und "1".
+ * @return Der Wert der Binärzahl.
+ */
+ public static final int fromBinary( String binary ) {
+ return Integer.valueOf(binary, 2);
+ }
+
+ /**
+ * Formt die angegebene Zahl in ihre hexadezimal Darstellung um.
+ *
+ *
+ * int hexa = hex(255); // "FF"
+ *
+ *
+ * @param i Eine Zahl.
+ * @return Die hexadezimal Darstellung der Zahl als Text.
+ */
+ public static final String hex( int i ) {
+ return Integer.toHexString(i);
+ }
+
+ /**
+ * Formt die angegebene Binärzahl in eine Dezimalzahl um.
+ *
+ *
+ * int dezimal = romHex("FF"); // 255
+ *
+ *
+ * @param binary Ein Text nur aus den Zeichen "0" bis "9" und "A" bis "F".
+ * @return Der Wert der Binärzahl.
+ */
+ public static final int fromHex( String binary ) {
+ return Integer.valueOf(binary, 16);
+ }
+
+ // Konstants für Key events (Copied from KeyEvent)
/**
* Constant for the ENTER virtual key.
@@ -1248,7 +1743,7 @@ public class Constants {
*/
public static final int KEY_EQUALS = KeyEvent.VK_EQUALS;
- /** VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
+ /* VK_A thru VK_Z are the same as ASCII 'A' thru 'Z' (0x41 - 0x5A) */
/**
* Constant for the "A" key.
diff --git a/src/main/java/schule/ngb/zm/Options.java b/src/main/java/schule/ngb/zm/Options.java
index 70cf071..0997336 100644
--- a/src/main/java/schule/ngb/zm/Options.java
+++ b/src/main/java/schule/ngb/zm/Options.java
@@ -56,7 +56,12 @@ public final class Options {
UP(NORTH),
DOWN(SOUTH),
LEFT(WEST),
- RIGHT(EAST);
+ RIGHT(EAST),
+
+ UPLEFT(NORTHWEST),
+ DOWNLEFT(SOUTHWEST),
+ UPRIGHT(NORTHEAST),
+ DOWNRIGHT(SOUTHEAST);
public final byte x, y;
diff --git a/src/main/java/schule/ngb/zm/Zeichenleinwand.java b/src/main/java/schule/ngb/zm/Zeichenleinwand.java
index 232b688..d59fdaf 100644
--- a/src/main/java/schule/ngb/zm/Zeichenleinwand.java
+++ b/src/main/java/schule/ngb/zm/Zeichenleinwand.java
@@ -1,7 +1,5 @@
package schule.ngb.zm;
-import schule.ngb.zm.shapes.ShapesLayer;
-
import java.awt.Canvas;
import java.awt.Graphics;
import java.awt.Graphics2D;
@@ -37,12 +35,12 @@ public class Zeichenleinwand extends Canvas {
super.setSize(width, height);
this.setPreferredSize(this.getSize());
this.setMinimumSize(this.getSize());
- this.setBackground(Constants.STD_BACKGROUND.getJavaColor());
+ this.setBackground(Constants.DEFAULT_BACKGROUND.getJavaColor());
// Liste der Ebenen initialisieren und die Standardebenen einfügen
layers = new LinkedList<>();
synchronized( layers ) {
- layers.add(new ColorLayer(width, height, Constants.STD_BACKGROUND));
+ layers.add(new ColorLayer(width, height, Constants.DEFAULT_BACKGROUND));
}
}
diff --git a/src/main/java/schule/ngb/zm/Zeichenmaschine.java b/src/main/java/schule/ngb/zm/Zeichenmaschine.java
index f5849cb..e7581da 100644
--- a/src/main/java/schule/ngb/zm/Zeichenmaschine.java
+++ b/src/main/java/schule/ngb/zm/Zeichenmaschine.java
@@ -277,8 +277,8 @@ public class Zeichenmaschine extends Constants {
}
// Wir kennen nun den Bildschirm und können die Breite / Höhe abrufen.
- this.width = width;
- this.height = height;
+ this.canvasWidth = width;
+ this.canvasHeight = height;
java.awt.Rectangle displayBounds = displayDevice.getDefaultConfiguration().getBounds();
this.screenWidth = (int) displayBounds.getWidth();
this.screenHeight = (int) displayBounds.getHeight();
@@ -408,8 +408,8 @@ public class Zeichenmaschine extends Constants {
frame.setResizable(false); // Should be set anyway
displayDevice.setFullScreenWindow(frame);
// Update width / height
- initialWidth = width;
- initialHeight = height;
+ initialWidth = canvasWidth;
+ initialHeight = canvasHeight;
changeSize(screenWidth, screenHeight);
// Register ESC as exit fullscreen
canvas.addKeyListener(fullscreenExitListener);
@@ -595,11 +595,11 @@ public class Zeichenmaschine extends Constants {
* @see #setFullscreen(boolean)
*/
private void changeSize( int newWidth, int newHeight ) {
- width = Math.min(Math.max(newWidth, 100), screenWidth);
- height = Math.min(Math.max(newHeight, 100), screenHeight);
+ canvasWidth = Math.min(Math.max(newWidth, 100), screenWidth);
+ canvasHeight = Math.min(Math.max(newHeight, 100), screenHeight);
if( canvas != null ) {
- canvas.setSize(width, height);
+ canvas.setSize(canvasWidth, canvasHeight);
}
}
@@ -629,7 +629,7 @@ public class Zeichenmaschine extends Constants {
* @return Die Breite der {@link Zeichenleinwand}.
*/
public final int getWidth() {
- return width;
+ return canvasWidth;
}
/**
@@ -638,7 +638,7 @@ public class Zeichenmaschine extends Constants {
* @return Die Höhe der {@link Zeichenleinwand}.
*/
public final int getHeight() {
- return height;
+ return canvasHeight;
}
/**
@@ -718,7 +718,7 @@ public class Zeichenmaschine extends Constants {
public final ColorLayer getBackgroundLayer() {
ColorLayer layer = canvas.getLayer(ColorLayer.class);
if( layer == null ) {
- layer = new ColorLayer(STD_BACKGROUND);
+ layer = new ColorLayer(DEFAULT_BACKGROUND);
canvas.addLayer(0, layer);
}
return layer;
@@ -812,7 +812,7 @@ public class Zeichenmaschine extends Constants {
BufferedImage img = ImageLoader.createImage(canvas.getWidth(), canvas.getHeight());
Graphics2D g = img.createGraphics();
- g.setColor(STD_BACKGROUND.getJavaColor());
+ g.setColor(DEFAULT_BACKGROUND.getJavaColor());
g.fillRect(0, 0, img.getWidth(), img.getHeight());
canvas.draw(g);
g.dispose();
@@ -836,7 +836,7 @@ public class Zeichenmaschine extends Constants {
BufferedImage img = ImageLoader.createImage(canvas.getWidth(), canvas.getHeight());
Graphics2D g = img.createGraphics();
- g.setColor(STD_BACKGROUND.getJavaColor());
+ g.setColor(DEFAULT_BACKGROUND.getJavaColor());
g.fillRect(0, 0, img.getWidth(), img.getHeight());
canvas.draw(g);
g.dispose();
@@ -1166,7 +1166,7 @@ public class Zeichenmaschine extends Constants {
break;
case MouseEvent.MOUSE_RELEASED:
mousePressed = false;
- mouseButton = NOBUTTON;
+ mouseButton = NOMOUSE;
mousePressed(evt);
break;
case MouseEvent.MOUSE_DRAGGED:
diff --git a/src/main/java/schule/ngb/zm/shapes/Shape.java b/src/main/java/schule/ngb/zm/shapes/Shape.java
index 6e3866b..630f5cf 100644
--- a/src/main/java/schule/ngb/zm/shapes/Shape.java
+++ b/src/main/java/schule/ngb/zm/shapes/Shape.java
@@ -243,7 +243,7 @@ public abstract class Shape extends FilledShape {
}
public void alignTo( Options.Direction dir, double buff ) {
- Point2D anchorShape = Shape.getAnchorPoint(width, height, dir);
+ Point2D anchorShape = Shape.getAnchorPoint(canvasWidth, canvasHeight, dir);
Point2D anchorThis = this.getAbsAnchorPoint(dir);
this.x += Math.abs(dir.x) * (anchorShape.getX() - anchorThis.getX()) + dir.x * buff;
diff --git a/src/main/java/schule/ngb/zm/util/Noise.java b/src/main/java/schule/ngb/zm/util/Noise.java
new file mode 100644
index 0000000..a20168f
--- /dev/null
+++ b/src/main/java/schule/ngb/zm/util/Noise.java
@@ -0,0 +1,308 @@
+package schule.ngb.zm.util;
+
+import java.util.Random;
+
+/**
+ * Zufallsgenerator für Perlin-Noise.
+ * + * Die Implementierung basiert auf dem von Ken perlin entwickelten Algorithmus + * und wurde von Matthew A. Johnston für Java implementiert. + *
+ * Original KOmmentar: + *
+ * This is Ken Perlin's implementation of Perlin Noise but modified to be more + * OOP. + *+ * + * @author Ken Perlin, Matthew A. Johnston (WarmWaffles) + */ +public class Noise { + + private Random rand; + + private static final int P = 8; + + private static final int B = 1 << P; + + private static final int M = B - 1; + + private static final int NP = 8; + + private static final int N = 1 << NP; + + private int[] p; + + private double[][] g2; + + private double[] g1; + + private static double[][] points; + + + public Noise() { + this(System.nanoTime()); + } + + public Noise( long seed ) { + this(new Random(seed)); + } + + public Noise( Random rand ) { + p = new int[B + B + 2]; + g2 = new double[B + B + 2][2]; + g1 = new double[B + B + 2]; + + points = new double[32][3]; + + this.rand = rand; + init(); + } + + /** + * A stub function that calls {@link #init()} + * + * @param seed + */ + public void setSeed( int seed ) { + this.rand = new Random(seed); + init(); + } + + public void setRandom( Random rand ) { + this.rand = rand; + init(); + } + + public double noise( double x, double y, double z ) { + int bx, by, bz, b0, b1, b00, b10, b01, b11; + double rx0, rx1, ry0, ry1, rz, sx, sy, sz, a, b, c, d, u, v, q[]; + + bx = (int) Math.IEEEremainder(Math.floor(x), B); + if( bx < 0 ) + bx += B; + + rx0 = x - Math.floor(x); + rx1 = rx0 - 1; + + by = (int) Math.IEEEremainder(Math.floor(y), B); + if( by < 0 ) + by += B; + + ry0 = y - Math.floor(y); + ry1 = ry0 - 1; + + bz = (int) Math.IEEEremainder(Math.floor(z), B); + if( bz < 0 ) + bz += B; + + rz = z - Math.floor(z); + + /* + if (bx < 0 || bx >= B + B + 2) + System.out.println(bx); + */ + b0 = p[bx]; + + bx++; + + b1 = p[bx]; + + b00 = p[b0 + by]; + b10 = p[b1 + by]; + + by++; + + b01 = p[b0 + by]; + b11 = p[b1 + by]; + + sx = s_curve(rx0); + sy = s_curve(ry0); + sz = s_curve(rz); + + q = G(b00 + bz); + u = rx0 * q[0] + ry0 * q[1] + rz * q[2]; + q = G(b10 + bz); + v = rx1 * q[0] + ry0 * q[1] + rz * q[2]; + a = lerp(sx, u, v); + q = G(b01 + bz); + u = rx0 * q[0] + ry1 * q[1] + rz * q[2]; + q = G(b11 + bz); + v = rx1 * q[0] + ry1 * q[1] + rz * q[2]; + b = lerp(sx, u, v); + c = lerp(sy, a, b); + + bz++; + rz--; + + q = G(b00 + bz); + u = rx0 * q[0] + ry0 * q[1] + rz * q[2]; + q = G(b10 + bz); + v = rx1 * q[0] + ry0 * q[1] + rz * q[2]; + a = lerp(sx, u, v); + q = G(b01 + bz); + u = rx0 * q[0] + ry1 * q[1] + rz * q[2]; + q = G(b11 + bz); + v = rx1 * q[0] + ry1 * q[1] + rz * q[2]; + b = lerp(sx, u, v); + d = lerp(sy, a, b); + + return lerp(sz, c, d); + } + + public double noise( double x, double y ) { + int bx0, bx1, by0, by1, b00, b10, b01, b11; + double rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v, q[]; + int i, j; + + t = x + N; + bx0 = ((int) t) & M; + bx1 = (bx0 + 1) & M; + rx0 = t - (int) t; + rx1 = rx0 - 1; + + t = y + N; + by0 = ((int) t) & M; + by1 = (by0 + 1) & M; + ry0 = t - (int) t; + ry1 = ry0 - 1; + + i = p[bx0]; + j = p[bx1]; + + b00 = p[i + by0]; + b10 = p[j + by0]; + b01 = p[i + by1]; + b11 = p[j + by1]; + + sx = s_curve(rx0); + sy = s_curve(ry0); + + q = g2[b00]; + u = rx0 * q[0] + ry0 * q[1]; + q = g2[b10]; + v = rx1 * q[0] + ry0 * q[1]; + a = lerp(sx, u, v); + + q = g2[b01]; + u = rx0 * q[0] + ry1 * q[1]; + q = g2[b11]; + v = rx1 * q[0] + ry1 * q[1]; + b = lerp(sx, u, v); + + return lerp(sy, a, b); + } + + public double noise( double x ) { + + int bx0, bx1; + double rx0, rx1, sx, t, u, v; + t = x + N; + bx0 = ((int) t) & M; + bx1 = (bx0 + 1) & M; + rx0 = t - (int) t; + rx1 = rx0 - 1; + + sx = s_curve(rx0); + u = rx0 * g1[p[bx0]]; + v = rx1 * g1[p[bx1]]; + + return lerp(sx, u, v); + } + + // ======================================================================== + // PRIVATE + // ======================================================================== + private void normalize2( double v[] ) { + double s; + s = Math.sqrt(v[0] * v[0] + v[1] * v[1]); + v[0] = v[0] / s; + v[1] = v[1] / s; + } + + private double[] G( int i ) { + return points[i % 32]; + } + + private double s_curve( double t ) { + return t * t * (3 - t - t); + } + + private double lerp( double t, double a, double b ) { + return a + t * (b - a); + } + + private final void init() { + int i, j, k; + double u, v, w, U, V, W, Hi, Lo; + + for( i = 0; i < B; i++ ) { + p[i] = i; + g1[i] = 2 * rand.nextDouble() - 1; + + do { + u = 2 * rand.nextDouble() - 1; + v = 2 * rand.nextDouble() - 1; + } while( u * u + v * v > 1 || + Math.abs(u) > 2.5 * Math.abs(v) || + Math.abs(v) > 2.5 * Math.abs(u) || + Math.abs(Math.abs(u) - Math.abs(v)) < .4 ); + + g2[i][0] = u; + g2[i][1] = v; + + normalize2(g2[i]); + + do { + u = 2 * rand.nextDouble() - 1; + v = 2 * rand.nextDouble() - 1; + w = 2 * rand.nextDouble() - 1; + U = Math.abs(u); + V = Math.abs(v); + W = Math.abs(w); + Lo = Math.min(U, Math.min(V, W)); + Hi = Math.max(U, Math.max(V, W)); + } while( u * u + v * v + w * w > 1 + || Hi > 4 * Lo + || Math.min(Math.abs(U - V), + Math.min(Math.abs(U - W), Math.abs(V - W))) < .2 ); + } + + while( --i > 0 ) { + k = p[i]; + j = (int) (rand.nextLong() & M); + p[i] = p[j]; + p[j] = k; + } + for( i = 0; i < B + 2; i++ ) { + p[B + i] = p[i]; + g1[B + i] = g1[i]; + for( j = 0; j < 2; j++ ) + g2[B + i][j] = g2[i][j]; + } + + points[3][0] = points[3][1] = points[3][2] = Math.sqrt(1. / 3); + double r2 = Math.sqrt(1. / 2); + double s = Math.sqrt(2 + r2 + r2); + + for( i = 0; i < 3; i++ ) + for( j = 0; j < 3; j++ ) + points[i][j] = (i == j ? 1 + r2 + r2 : r2) / s; + + + for( i = 0; i <= 1; i++ ) { + for( j = 0; j <= 1; j++ ) { + for( k = 0; k <= 1; k++ ) { + int n = i + j * 2 + k * 4; + if( n > 0 ) { + for( int m = 0; m < 4; m++ ) { + points[4 * n + m][0] = (i == 0 ? 1 : -1) * points[m][0]; + points[4 * n + m][1] = (j == 0 ? 1 : -1) * points[m][1]; + points[4 * n + m][2] = (k == 0 ? 1 : -1) * points[m][2]; + } + } + } + } + } + } + +} diff --git a/src/main/java/schule/ngb/zm/util/Validator.java b/src/main/java/schule/ngb/zm/util/Validator.java index 50067b9..cb28143 100644 --- a/src/main/java/schule/ngb/zm/util/Validator.java +++ b/src/main/java/schule/ngb/zm/util/Validator.java @@ -136,8 +136,27 @@ public class Validator { } */ + + public static final