mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-04-14 06:33:34 +02:00
Changed language to english
After some soulsearching I decided to change the language (back) to English. The documentation and comments will still be in German, but method names and variables are completely in English now. Besides that, a lot of imprvoements have been made in many areas and the framework is coming together niecely.
This commit is contained in:
280
src/schule/ngb/zm/Color.java
Normal file
280
src/schule/ngb/zm/Color.java
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
public class Color {
|
||||||
|
|
||||||
|
public static final Color BLACK = new Color(java.awt.Color.BLACK);
|
||||||
|
|
||||||
|
public static final Color WHITE = new Color(java.awt.Color.WHITE);
|
||||||
|
|
||||||
|
public static final Color GRAY = new Color(java.awt.Color.GRAY);
|
||||||
|
|
||||||
|
public static final Color DARKGRAY = new Color(java.awt.Color.DARK_GRAY);
|
||||||
|
|
||||||
|
public static final Color LIGHTGRAY = new Color(java.awt.Color.LIGHT_GRAY);
|
||||||
|
|
||||||
|
public static final Color RED = new Color(java.awt.Color.RED);
|
||||||
|
|
||||||
|
public static final Color GREEN = new Color(java.awt.Color.GREEN);
|
||||||
|
|
||||||
|
public static final Color BLUE = new Color(java.awt.Color.BLUE);
|
||||||
|
|
||||||
|
public static final Color YELLOW = new Color(java.awt.Color.YELLOW);
|
||||||
|
|
||||||
|
public static final Color ORANGE = new Color(java.awt.Color.ORANGE);
|
||||||
|
|
||||||
|
public static final Color CYAN = new Color(java.awt.Color.CYAN);
|
||||||
|
|
||||||
|
public static final Color MAGENTA = new Color(java.awt.Color.MAGENTA);
|
||||||
|
|
||||||
|
public static final Color PINK = new Color(java.awt.Color.PINK);
|
||||||
|
|
||||||
|
public static final Color HGGREEN = new Color(0, 165, 81);
|
||||||
|
|
||||||
|
public static final Color HGRED = new Color(151, 54, 60);
|
||||||
|
|
||||||
|
|
||||||
|
private int rgba;
|
||||||
|
|
||||||
|
public Color() {
|
||||||
|
rgba = 0xFF000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( int gray ) {
|
||||||
|
this(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( int gray, int alpha ) {
|
||||||
|
this(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( int red, int green, int blue ) {
|
||||||
|
this(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( int red, int green, int blue, int alpha ) {
|
||||||
|
rgba = (alpha << 24) | (red << 16) | (green << 8) | blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( Color color ) {
|
||||||
|
this(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( Color color, int alpha ) {
|
||||||
|
this(color.getRed(), color.getGreen(), color.getBlue(), alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( java.awt.Color color ) {
|
||||||
|
this(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color( java.awt.Color color, int alpha ) {
|
||||||
|
this(color.getRed(), color.getGreen(), color.getBlue(), alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color parseRGB( int rgba ) {
|
||||||
|
Color c = new Color();
|
||||||
|
c.rgba = rgba;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color parseHexcode( String hexcode ) {
|
||||||
|
if( hexcode.startsWith("#") ) {
|
||||||
|
hexcode = hexcode.substring(1);
|
||||||
|
}
|
||||||
|
if( hexcode.length() != 3 && hexcode.length() != 6 && hexcode.length() != 8 ) {
|
||||||
|
throw new IllegalArgumentException("color hexcodes have to be 3, 6 or 8 digits long, got " + hexcode.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
// normalize hexcode to 8 digits
|
||||||
|
int alpha = 255;
|
||||||
|
if( hexcode.length() == 3 ) {
|
||||||
|
hexcode = "" + hexcode.charAt(0) + hexcode.charAt(0) + hexcode.charAt(1) + hexcode.charAt(1) + hexcode.charAt(2) + hexcode.charAt(2);
|
||||||
|
} else if( hexcode.length() == 8 ) {
|
||||||
|
alpha = Integer.valueOf(hexcode.substring(6, 8), 16);
|
||||||
|
hexcode = hexcode.substring(0, 6);
|
||||||
|
} else {
|
||||||
|
hexcode = hexcode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Color c = new Color();
|
||||||
|
c.rgba = (alpha << 24) | Integer.valueOf(hexcode, 16);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color morph( java.awt.Color pFarbe1, java.awt.Color pFarbe2, double pFactor ) {
|
||||||
|
if( pFactor < 0.0 || pFarbe2 == null ) {
|
||||||
|
return new Color(pFarbe1);
|
||||||
|
}
|
||||||
|
if( pFactor > 1.0 || pFarbe1 == null ) return new Color(pFarbe2);
|
||||||
|
double pFactorInv = 1 - pFactor;
|
||||||
|
return new Color((int) (pFactorInv * pFarbe1.getRed() + pFactor * pFarbe2.getRed()), (int) (pFactorInv * pFarbe1.getGreen() + pFactor * pFarbe2.getGreen()), (int) (pFactorInv * pFarbe1.getBlue() + pFactor * pFarbe2.getBlue()), (int) (pFactorInv * pFarbe1.getAlpha() + pFactor * pFarbe2.getAlpha()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static float[] RGBtoHSL( int rgb, float[] hsl ) {
|
||||||
|
float r = ((rgb >> 16) & 255) / 255.0f;
|
||||||
|
float g = ((rgb >> 8) & 255) / 255.0f;
|
||||||
|
float b = (rgb & 255) / 255.0f;
|
||||||
|
float max = Math.max(Math.max(r, g), b);
|
||||||
|
float min = Math.min(Math.min(r, g), b);
|
||||||
|
float c = max - min;
|
||||||
|
|
||||||
|
if( hsl == null ) {
|
||||||
|
hsl = new float[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
float h_ = 0.f;
|
||||||
|
if( c == 0 ) {
|
||||||
|
h_ = 0;
|
||||||
|
} else if( max == r ) {
|
||||||
|
h_ = (float) (g - b) / c;
|
||||||
|
if( h_ < 0 ) h_ += 6.f;
|
||||||
|
} else if( max == g ) {
|
||||||
|
h_ = (float) (b - r) / c + 2.f;
|
||||||
|
} else if( max == b ) {
|
||||||
|
h_ = (float) (r - g) / c + 4.f;
|
||||||
|
}
|
||||||
|
float h = 60.f * h_;
|
||||||
|
|
||||||
|
float l = (max + min) * 0.5f;
|
||||||
|
|
||||||
|
float s;
|
||||||
|
if( c == 0 ) {
|
||||||
|
s = 0.f;
|
||||||
|
} else {
|
||||||
|
s = c / (1 - Math.abs(2.f * l - 1.f));
|
||||||
|
}
|
||||||
|
|
||||||
|
hsl[0] = h;
|
||||||
|
hsl[1] = s;
|
||||||
|
hsl[2] = l;
|
||||||
|
return hsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int HSLtoRGB( float[] hsl ) {
|
||||||
|
return HSLtoRGB(hsl, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int HSLtoRGB( float[] hsl, int alpha ) {
|
||||||
|
float h = hsl[0];
|
||||||
|
float s = hsl[1];
|
||||||
|
float l = hsl[2];
|
||||||
|
|
||||||
|
float c = (1 - Math.abs(2.f * l - 1.f)) * s;
|
||||||
|
float h_ = h / 60.f;
|
||||||
|
float h_mod2 = h_;
|
||||||
|
if( h_mod2 >= 4.f ) h_mod2 -= 4.f;
|
||||||
|
else if( h_mod2 >= 2.f ) h_mod2 -= 2.f;
|
||||||
|
|
||||||
|
float x = c * (1 - Math.abs(h_mod2 - 1));
|
||||||
|
float r_, g_, b_;
|
||||||
|
if( h_ < 1 ) {
|
||||||
|
r_ = c;
|
||||||
|
g_ = x;
|
||||||
|
b_ = 0;
|
||||||
|
} else if( h_ < 2 ) {
|
||||||
|
r_ = x;
|
||||||
|
g_ = c;
|
||||||
|
b_ = 0;
|
||||||
|
} else if( h_ < 3 ) {
|
||||||
|
r_ = 0;
|
||||||
|
g_ = c;
|
||||||
|
b_ = x;
|
||||||
|
} else if( h_ < 4 ) {
|
||||||
|
r_ = 0;
|
||||||
|
g_ = x;
|
||||||
|
b_ = c;
|
||||||
|
} else if( h_ < 5 ) {
|
||||||
|
r_ = x;
|
||||||
|
g_ = 0;
|
||||||
|
b_ = c;
|
||||||
|
} else {
|
||||||
|
r_ = c;
|
||||||
|
g_ = 0;
|
||||||
|
b_ = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
float m = l - (0.5f * c);
|
||||||
|
int r = (int) ((r_ + m) * (255.f) + 0.5f);
|
||||||
|
int g = (int) ((g_ + m) * (255.f) + 0.5f);
|
||||||
|
int b = (int) ((b_ + m) * (255.f) + 0.5f);
|
||||||
|
return (alpha & 255) << 24 | r << 16 | g << 8 | b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void setRed( int red ) {
|
||||||
|
rgba = (red << 16) | (0xFF00FFFF & rgba);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public Color copy() {
|
||||||
|
return new Color(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void setGreen( int green ) {
|
||||||
|
rgba = (green << 8) | (0xFFFF00FF & rgba);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public int getRGBA() {
|
||||||
|
return rgba;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void setBlue( int blue ) {
|
||||||
|
rgba = blue | (0xFFFFFF00 & rgba);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public int getRed() {
|
||||||
|
return (rgba >> 16) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void setAlpha( int alpha ) {
|
||||||
|
rgba = (alpha << 24) | (0x00FFFFFF & rgba);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public int getGreen() {
|
||||||
|
return (rgba >> 8) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBlue() {
|
||||||
|
return rgba & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAlpha() {
|
||||||
|
return (rgba >> 24) & 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.awt.Color getColor() {
|
||||||
|
return new java.awt.Color(rgba, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object po ) {
|
||||||
|
if( this == po ) return true;
|
||||||
|
if( po == null || getClass() != po.getClass() ) return false;
|
||||||
|
Color ppColor = (Color) po;
|
||||||
|
return rgba == ppColor.rgba;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + '[' + "r=" + getRed() + ',' + "g=" + getGreen() + ',' + "b=" + getBlue() + ',' + "a=" + getAlpha() + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color brighter() {
|
||||||
|
return brighter(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color brighter( int percent ) {
|
||||||
|
float[] hsl = RGBtoHSL(rgba, null);
|
||||||
|
hsl[2] = Math.min(Math.max(hsl[2] * (1.0f + percent / 100.0f), 0.0f), 1.0f);
|
||||||
|
return Color.parseRGB(HSLtoRGB(hsl, getAlpha()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color darker() {
|
||||||
|
return darker(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color darker( int percent ) {
|
||||||
|
float[] hsl = RGBtoHSL(rgba, null);
|
||||||
|
hsl[2] = Math.min(Math.max(hsl[2] * (1.0f - percent / 100.0f), 0.0f), 1.0f);
|
||||||
|
return Color.parseRGB(HSLtoRGB(hsl, getAlpha()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
18
src/schule/ngb/zm/ColorLayer.java
Normal file
18
src/schule/ngb/zm/ColorLayer.java
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
public class ColorLayer extends Layer {
|
||||||
|
|
||||||
|
private Color background;
|
||||||
|
|
||||||
|
public ColorLayer( Color color ) {
|
||||||
|
this.background = color;
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
drawing.setColor(background.getColor());
|
||||||
|
drawing.fillRect(0, 0, getWidth(), getHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
208
src/schule/ngb/zm/Constants.java
Normal file
208
src/schule/ngb/zm/Constants.java
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
|
||||||
|
public static final String APP_NAME = "Zeichenmaschine";
|
||||||
|
|
||||||
|
public static final int APP_VERSION_MAJ = 0;
|
||||||
|
|
||||||
|
public static final int APP_VERSION_MIN = 1;
|
||||||
|
|
||||||
|
public static final int APP_VERSION_REV = 5;
|
||||||
|
|
||||||
|
public static final String APP_VERSION = APP_VERSION_MAJ + "." + APP_VERSION_MIN + "." + APP_VERSION_REV;
|
||||||
|
|
||||||
|
public static final int STD_WIDTH = 400;
|
||||||
|
|
||||||
|
public static final int STD_HEIGHT = 400;
|
||||||
|
|
||||||
|
public static final int STD_FPS = 60;
|
||||||
|
|
||||||
|
public static final Color STD_FILLCOLOR = Color.WHITE;
|
||||||
|
|
||||||
|
public static final Color STD_STROKECOLOR = Color.BLACK;
|
||||||
|
|
||||||
|
public static final double STD_STROKEWEIGHT = 1.0;
|
||||||
|
|
||||||
|
public static final int STD_FONTSIZE = 14;
|
||||||
|
|
||||||
|
public static final Options.StrokeType SOLID = Options.StrokeType.SOLID;
|
||||||
|
|
||||||
|
public static final Options.StrokeType DASHED = Options.StrokeType.DASHED;
|
||||||
|
|
||||||
|
public static final Options.StrokeType DOTTED = Options.StrokeType.DOTTED;
|
||||||
|
|
||||||
|
public static final Options.ArrowHead LINES = Options.ArrowHead.LINES;
|
||||||
|
|
||||||
|
public static final Options.ArrowHead FILLED = Options.ArrowHead.FILLED;
|
||||||
|
|
||||||
|
public static final Options.PathType OPEN = Options.PathType.OPEN;
|
||||||
|
|
||||||
|
public static final Options.PathType CLOSED = Options.PathType.CLOSED;
|
||||||
|
|
||||||
|
public static final Options.PathType PIE = Options.PathType.PIE;
|
||||||
|
|
||||||
|
public static final Options.Direction CENTER = Options.Direction.CENTER;
|
||||||
|
|
||||||
|
public static final Options.Direction NORTH = Options.Direction.NORTH;
|
||||||
|
|
||||||
|
public static final Options.Direction EAST = Options.Direction.EAST;
|
||||||
|
|
||||||
|
public static final Options.Direction SOUTH = Options.Direction.SOUTH;
|
||||||
|
|
||||||
|
public static final Options.Direction WEST = Options.Direction.WEST;
|
||||||
|
|
||||||
|
public static final Options.Direction NORTHEAST = Options.Direction.NORTHEAST;
|
||||||
|
|
||||||
|
public static final Options.Direction SOUTHEAST = Options.Direction.SOUTHEAST;
|
||||||
|
|
||||||
|
public static final Options.Direction NORTHWEST = Options.Direction.NORTHWEST;
|
||||||
|
|
||||||
|
public static final Options.Direction SOUTHWEST = Options.Direction.SOUTHWEST;
|
||||||
|
|
||||||
|
public static final Options.Direction MIDDLE = Options.Direction.MIDDLE;
|
||||||
|
|
||||||
|
public static final Options.Direction UP = Options.Direction.UP;
|
||||||
|
|
||||||
|
public static final Options.Direction RIGHT = Options.Direction.RIGHT;
|
||||||
|
|
||||||
|
public static final Options.Direction DOWN = Options.Direction.DOWN;
|
||||||
|
|
||||||
|
public static final Options.Direction LEFT = Options.Direction.LEFT;
|
||||||
|
|
||||||
|
public static final Color BLACK = Color.BLACK;
|
||||||
|
|
||||||
|
public static final Color WHITE = Color.WHITE;
|
||||||
|
|
||||||
|
public static final Color RED = Color.RED;
|
||||||
|
|
||||||
|
public static final Color BLUE = Color.BLUE;
|
||||||
|
|
||||||
|
public static final Color GREEN = Color.GREEN;
|
||||||
|
|
||||||
|
public static final Color YELLOW = Color.YELLOW;
|
||||||
|
|
||||||
|
public static Color STD_BACKGROUND = new Color(200, 200, 200);
|
||||||
|
|
||||||
|
public static Color color( int gray ) {
|
||||||
|
return color(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color color( int gray, int alpha ) {
|
||||||
|
return color(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color color( int red, int green, int blue ) {
|
||||||
|
return color(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color color( int red, int green, int blue, int alpha ) {
|
||||||
|
if( red < 0 || red >= 256 )
|
||||||
|
throw new IllegalArgumentException("red must be between 0 and 255");
|
||||||
|
if( green < 0 || green >= 256 )
|
||||||
|
throw new IllegalArgumentException("green must be between 0 and 255");
|
||||||
|
if( blue < 0 || blue >= 256 )
|
||||||
|
throw new IllegalArgumentException("blue must be between 0 and 255");
|
||||||
|
if( alpha < 0 || alpha >= 256 )
|
||||||
|
throw new IllegalArgumentException("alpha must be between 0 and 255");
|
||||||
|
|
||||||
|
return new Color(red, green, blue, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static double abs( double x ) {
|
||||||
|
return Math.abs(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double sign( double x ) {
|
||||||
|
return Math.signum(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double round( double x ) {
|
||||||
|
return Math.round(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double floor( double x ) {
|
||||||
|
return Math.floor(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double ceil( double x ) {
|
||||||
|
return Math.ceil(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double sin( double x ) {
|
||||||
|
return Math.sin(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double cos( double x ) {
|
||||||
|
return Math.cos(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double tan( double x ) {
|
||||||
|
return Math.tan(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double arcsin( double x ) {
|
||||||
|
return Math.asin(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double arccos( double x ) {
|
||||||
|
return Math.acos(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double arctan( double x ) {
|
||||||
|
return Math.atan(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double limit( double x, double max ) {
|
||||||
|
if( x > max ) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double limit( double x, double min, double max ) {
|
||||||
|
if( x > max ) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
if( x < min ) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double morph( double from, double to, double t ) {
|
||||||
|
return from - t * (from + to);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double random( double min, double max ) {
|
||||||
|
return Math.random() * (max - min) + min;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int random( int min, int max ) {
|
||||||
|
return (int) (Math.random() * (max - min) + min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean randomBool() {
|
||||||
|
return randomBool(.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean randomBool( int percent ) {
|
||||||
|
return randomBool(percent / 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean randomBool( double weight ) {
|
||||||
|
return Math.random() < weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double randomGuassian() {
|
||||||
|
return new Random().nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double noise() {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ import java.awt.*;
|
|||||||
* Zeichenbare Objekte können auf eine Zeichenfläche gezeichnet werden.
|
* Zeichenbare Objekte können auf eine Zeichenfläche gezeichnet werden.
|
||||||
* In der Regel werden sie einmal pro Frame gezeichnet.
|
* In der Regel werden sie einmal pro Frame gezeichnet.
|
||||||
*/
|
*/
|
||||||
public interface Zeichenbar {
|
public interface Drawable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt an, ob das Objekt derzeit sichtbar ist (also gezeichnet werden
|
* Gibt an, ob das Objekt derzeit sichtbar ist (also gezeichnet werden
|
||||||
@@ -14,11 +14,11 @@ public interface Zeichenbar {
|
|||||||
*
|
*
|
||||||
* @return <code>true</code>, wenn das Objekt sichtbar ist.
|
* @return <code>true</code>, wenn das Objekt sichtbar ist.
|
||||||
*/
|
*/
|
||||||
public boolean istSichtbar();
|
boolean isVisible();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wird aufgerufen, um das Objekt auf die Zeichenfläche <var>graphics</var>
|
* Wird aufgerufen, um das Objekt auf die Zeichenfläche <var>graphics</var>
|
||||||
* zu zeichnen.
|
* zu draw.
|
||||||
* <p>
|
* <p>
|
||||||
* Das Objekt muss dafür Sorge tragen, dass der Zustand der Zeichenfläche
|
* Das Objekt muss dafür Sorge tragen, dass der Zustand der Zeichenfläche
|
||||||
* (Transformationsmatrix, Farbe, ...) erhalten bleibt. Das Objekt sollte
|
* (Transformationsmatrix, Farbe, ...) erhalten bleibt. Das Objekt sollte
|
||||||
@@ -26,6 +26,6 @@ public interface Zeichenbar {
|
|||||||
*
|
*
|
||||||
* @param graphics Die Zeichenfläche.
|
* @param graphics Die Zeichenfläche.
|
||||||
*/
|
*/
|
||||||
public void zeichnen( Graphics2D graphics );
|
void draw( Graphics2D graphics );
|
||||||
|
|
||||||
}
|
}
|
||||||
525
src/schule/ngb/zm/DrawingLayer.java
Normal file
525
src/schule/ngb/zm/DrawingLayer.java
Normal file
@@ -0,0 +1,525 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import schule.ngb.zm.util.ImageLoader;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.*;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
|
public class DrawingLayer extends Layer {
|
||||||
|
|
||||||
|
protected Color strokeColor;
|
||||||
|
|
||||||
|
protected Color fillColor;
|
||||||
|
|
||||||
|
protected double strokeWeight;
|
||||||
|
|
||||||
|
protected Options.StrokeType strokeType = SOLID;
|
||||||
|
|
||||||
|
private Options.Direction default_anchor = CENTER;
|
||||||
|
|
||||||
|
protected Line2D.Double line = new Line2D.Double();
|
||||||
|
protected Ellipse2D.Double ellipse = new Ellipse2D.Double();
|
||||||
|
protected Rectangle2D.Double rect = new Rectangle2D.Double();
|
||||||
|
protected Arc2D.Double arc = new Arc2D.Double();
|
||||||
|
|
||||||
|
private Stack<AffineTransform> transformStack = new Stack<>();
|
||||||
|
|
||||||
|
private FontMetrics fontMetrics = null;
|
||||||
|
|
||||||
|
public DrawingLayer() {
|
||||||
|
super();
|
||||||
|
transformStack.push(new AffineTransform());
|
||||||
|
|
||||||
|
strokeColor = Color.BLACK;
|
||||||
|
fillColor = Color.WHITE;
|
||||||
|
strokeWeight = 1.0;
|
||||||
|
|
||||||
|
fontMetrics = drawing.getFontMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DrawingLayer( int width, int height ) {
|
||||||
|
super(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getColor() {
|
||||||
|
return fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor( int gray ) {
|
||||||
|
setColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor( Color color ) {
|
||||||
|
fillColor = color;
|
||||||
|
drawing.setColor(color.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noFill() {
|
||||||
|
fillColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor( int gray, int alpha ) {
|
||||||
|
setColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor( int red, int green, int blue ) {
|
||||||
|
setColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getStrokeColor() {
|
||||||
|
return strokeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray ) {
|
||||||
|
setStrokeColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( Color color ) {
|
||||||
|
strokeColor = color;
|
||||||
|
drawing.setColor(color.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noStroke() {
|
||||||
|
strokeColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray, int alpha ) {
|
||||||
|
setStrokeColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue ) {
|
||||||
|
setStrokeColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setStrokeColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeWeight( double pWeight ) {
|
||||||
|
strokeWeight = pWeight;
|
||||||
|
drawing.setStroke(createStroke());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Stroke createStroke() {
|
||||||
|
switch( strokeType ) {
|
||||||
|
case DOTTED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{1.0f, 5.0f}, 0.0f);
|
||||||
|
case DASHED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{5.0f}, 0.0f);
|
||||||
|
default:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options.StrokeType getStrokeType() {
|
||||||
|
return strokeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeType( Options.StrokeType type ) {
|
||||||
|
switch( type ) {
|
||||||
|
case DASHED:
|
||||||
|
this.strokeType = DASHED;
|
||||||
|
break;
|
||||||
|
case DOTTED:
|
||||||
|
this.strokeType = DOTTED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
this.strokeType = SOLID;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetStroke() {
|
||||||
|
setStrokeColor(STD_STROKECOLOR);
|
||||||
|
setStrokeWeight(STD_STROKEWEIGHT);
|
||||||
|
setStrokeType(SOLID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
default_anchor = anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear( int gray ) {
|
||||||
|
clear(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear( int gray, int alpha ) {
|
||||||
|
clear(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear( int red, int green, int blue ) {
|
||||||
|
clear(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear( int red, int green, int blue, int alpha ) {
|
||||||
|
clear(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear( Color pColor ) {
|
||||||
|
/*graphics.setBackground(pColor);
|
||||||
|
graphics.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());*/
|
||||||
|
java.awt.Color currentColor = drawing.getColor();
|
||||||
|
pushMatrix();
|
||||||
|
resetMatrix();
|
||||||
|
drawing.setColor(pColor.getColor());
|
||||||
|
drawing.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
|
||||||
|
drawing.setColor(currentColor);
|
||||||
|
popMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void line( double x1, double y1, double x2, double y2 ) {
|
||||||
|
//Shape line = new Line2D.Double(x1, y1, x2, y2);
|
||||||
|
line.setLine(x1, y1, x2, y2);
|
||||||
|
drawShape(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pixel( double x, double y ) {
|
||||||
|
square(x, y, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void square( double x, double y, double w ) {
|
||||||
|
rect(x, y, w, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void square( double x, double y, double w, Options.Direction anchor ) {
|
||||||
|
rect(x, y, w, w, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rect( double x, double y, double w, double h ) {
|
||||||
|
rect(x, y, w, h, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rect( double x, double y, double w, double h, Options.Direction anchor ) {
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
||||||
|
// Shape rect = new Rectangle2D.Double(anchorPoint.getX(), anchorPoint.getY(), w, h);
|
||||||
|
rect.setRect(anchorPoint.getX(), anchorPoint.getY(), w, h);
|
||||||
|
fillShape(rect);
|
||||||
|
drawShape(rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void point( double x, double y ) {
|
||||||
|
circle(x - 1, y - 1, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void circle( double x, double y, double d ) {
|
||||||
|
ellipse(x, y, d, d, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void circle( double x, double y, double d, Options.Direction anchor ) {
|
||||||
|
ellipse(x, y, d, d, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ellipse( double x, double y, double w, double h ) {
|
||||||
|
ellipse(x, y, w, h, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ellipse( double x, double y, double w, double h, Options.Direction anchor ) {
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
||||||
|
// Shape ellipse = new Ellipse2D.Double(anchorPoint.x, anchorPoint.y, w, h);
|
||||||
|
ellipse.setFrame(anchorPoint.x, anchorPoint.y, w, h);
|
||||||
|
fillShape(ellipse);
|
||||||
|
drawShape(ellipse);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void arc( double x, double y, double d, double angle1, double angle2 ) {
|
||||||
|
while( angle2 < angle1 ) angle2 += 360.0;
|
||||||
|
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, CENTER);
|
||||||
|
/*Shape arc = new Arc2D.Double(
|
||||||
|
anchorPoint.x,
|
||||||
|
anchorPoint.y,
|
||||||
|
d, d,
|
||||||
|
angle1, angle2 - angle1,
|
||||||
|
Arc2D.OPEN
|
||||||
|
);*/
|
||||||
|
arc.setArc(
|
||||||
|
anchorPoint.x, anchorPoint.y,
|
||||||
|
d, d,
|
||||||
|
angle1, angle2 - angle1,
|
||||||
|
Arc2D.OPEN
|
||||||
|
);
|
||||||
|
|
||||||
|
drawShape(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pie( double x, double y, double d, double angle1, double angle2 ) {
|
||||||
|
while( angle2 < angle1 ) angle2 += 360.0;
|
||||||
|
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, CENTER);
|
||||||
|
/*Shape arc = new Arc2D.Double(
|
||||||
|
anchorPoint.x,
|
||||||
|
anchorPoint.y,
|
||||||
|
d, d,
|
||||||
|
angle1, angle2 - angle1,
|
||||||
|
Arc2D.PIE
|
||||||
|
);*/
|
||||||
|
arc.setArc(
|
||||||
|
anchorPoint.x, anchorPoint.y,
|
||||||
|
d, d,
|
||||||
|
angle1, angle2 - angle1,
|
||||||
|
Arc2D.PIE
|
||||||
|
);
|
||||||
|
|
||||||
|
fillShape(arc);
|
||||||
|
drawShape(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void curve( double x1, double y1, double x2, double y2, double x3, double y3 ) {
|
||||||
|
QuadCurve2D curve = new QuadCurve2D.Double(x1, y1, x2, y2, x3, y3);
|
||||||
|
drawShape(curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void curve( double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4 ) {
|
||||||
|
CubicCurve2D curve = new CubicCurve2D.Double(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||||
|
drawShape(curve);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void triangle( double x1, double y1, double x2, double y2, double x3, double y3 ) {
|
||||||
|
Path2D path = new Path2D.Double();
|
||||||
|
path.moveTo(x1, y1);
|
||||||
|
path.lineTo(x2, y2);
|
||||||
|
path.lineTo(x3, y3);
|
||||||
|
path.lineTo(x1, y1);
|
||||||
|
|
||||||
|
fillShape(path);
|
||||||
|
drawShape(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rhombus( double x, double y, double width, double height ) {
|
||||||
|
rhombus(x, y, width, height, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rhombus( double x, double y, double width, double height, Options.Direction anchor ) {
|
||||||
|
double whalf = width / 2.0, hhalf = height / 2.0;
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, width, height, anchor);
|
||||||
|
polygon(anchorPoint.x + whalf, anchorPoint.y, anchorPoint.x + width, anchorPoint.y + hhalf, anchorPoint.x + whalf, anchorPoint.y + height, anchorPoint.x, anchorPoint.y + hhalf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void polygon( double... coordinates ) {
|
||||||
|
if( coordinates.length < 4 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path2D path = new Path2D.Double();
|
||||||
|
path.moveTo(coordinates[0], coordinates[1]);
|
||||||
|
for( int i = 2; i < coordinates.length; i += 2 ) {
|
||||||
|
if( i + 1 < coordinates.length ) {
|
||||||
|
path.lineTo(coordinates[i], coordinates[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = coordinates.length;
|
||||||
|
if( coordinates[len - 2] != coordinates[0] || coordinates[len - 1] != coordinates[1] ) {
|
||||||
|
path.lineTo(coordinates[0], coordinates[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fillShape(path);
|
||||||
|
drawShape(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void polygon( Point2D... points ) {
|
||||||
|
if( points.length < 2 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Path2D path = new Path2D.Double();
|
||||||
|
path.moveTo(points[0].getX(), points[0].getY());
|
||||||
|
for( int i = 1; i < points.length; i += 1 ) {
|
||||||
|
path.lineTo(points[i].getX(), points[i].getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = points.length;
|
||||||
|
if( points[len - 1].equals(points[0]) ) {
|
||||||
|
path.moveTo(points[0].getX(), points[0].getY());
|
||||||
|
}
|
||||||
|
|
||||||
|
fillShape(path);
|
||||||
|
drawShape(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( String imageSource, double x, double y ) {
|
||||||
|
image(ImageLoader.loadImage(imageSource), x, y, 1.0, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( String imageSource, double x, double y, Options.Direction anchor ) {
|
||||||
|
image(ImageLoader.loadImage(imageSource), x, y, 1.0, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( String imageSource, double x, double y, double scale ) {
|
||||||
|
image(ImageLoader.loadImage(imageSource), x, y, scale, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( String imageSource, double x, double y, double scale, Options.Direction anchor ) {
|
||||||
|
image(ImageLoader.loadImage(imageSource), x, y, scale, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( Image image, double x, double y ) {
|
||||||
|
image(image, x, y, 1.0, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( Image image, double x, double y, double scale ) {
|
||||||
|
image(image, x, y, scale, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void image( Image image, double x, double y, double scale, Options.Direction anchor ) {
|
||||||
|
if( image != null ) {
|
||||||
|
double neww = image.getWidth(null) * scale;
|
||||||
|
double newh = image.getHeight(null) * scale;
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y, neww, newh, anchor);
|
||||||
|
drawing.drawImage(image, (int) anchorPoint.x, (int) anchorPoint.y, (int) neww, (int) newh, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void text( String text, double x, double y ) {
|
||||||
|
text(text, x, y, default_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void text( String text, double x, double y, Options.Direction anchor ) {
|
||||||
|
FontMetrics fm = drawing.getFontMetrics();
|
||||||
|
Point2D.Double anchorPoint = getAnchorPoint(x, y + fm.getAscent(), fm.stringWidth(text), fm.getHeight(), anchor);
|
||||||
|
|
||||||
|
drawing.drawString(text, (float) anchorPoint.x, (float) anchorPoint.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFontSize( int size ) {
|
||||||
|
setFont(drawing.getFont().deriveFont((float)size));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFont( String fontName ) {
|
||||||
|
Font font = new Font(fontName, drawing.getFont().getStyle(), drawing.getFont().getSize());
|
||||||
|
setFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFont( String fontName, int size ) {
|
||||||
|
Font font = new Font(fontName, drawing.getFont().getStyle(), size);
|
||||||
|
setFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFont( String fontName, int size, int style ) {
|
||||||
|
Font font = new Font(fontName, style, size);
|
||||||
|
setFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFont( Font font ) {
|
||||||
|
drawing.setFont(font);
|
||||||
|
fontMetrics = drawing.getFontMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Point2D.Double transformToCanvas( double x, double y ) {
|
||||||
|
return transformToCanvas(new Point2D.Double(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Double transformToCanvas( Point2D.Double pPoint ) {
|
||||||
|
AffineTransform matrix = getMatrix();
|
||||||
|
matrix.transform(pPoint, pPoint);
|
||||||
|
return pPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Double transformToUser( double x, double y ) {
|
||||||
|
return transformToUser(new Point2D.Double(x,y));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Double transformToUser( Point2D.Double pPoint ) {
|
||||||
|
AffineTransform matrix = getMatrix();
|
||||||
|
|
||||||
|
try {
|
||||||
|
matrix.inverseTransform(pPoint, pPoint);
|
||||||
|
} catch( NoninvertibleTransformException e ) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return pPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Double getAnchorPoint( double x, double y, double w, double h, Options.Direction anchor ) {
|
||||||
|
double whalf = w * .5, hhalf = h * .5;
|
||||||
|
|
||||||
|
// anchor == CENTER
|
||||||
|
Point2D.Double anchorPoint = new Point2D.Double(x - whalf, y - hhalf);
|
||||||
|
|
||||||
|
if( NORTH.is(anchor) ) {
|
||||||
|
anchorPoint.y += hhalf;
|
||||||
|
}
|
||||||
|
if( SOUTH.is(anchor) ) {
|
||||||
|
anchorPoint.y -= hhalf;
|
||||||
|
}
|
||||||
|
if( WEST.is(anchor) ) {
|
||||||
|
anchorPoint.x += whalf;
|
||||||
|
}
|
||||||
|
if( EAST.is(anchor) ) {
|
||||||
|
anchorPoint.x -= whalf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return anchorPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fillShape( Shape pShape ) {
|
||||||
|
if( fillColor != null && fillColor.getAlpha() > 0.0 ) {
|
||||||
|
drawing.setColor(fillColor.getColor());
|
||||||
|
drawing.fill(pShape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void drawShape( Shape pShape ) {
|
||||||
|
if( strokeColor != null && strokeColor.getAlpha() > 0.0
|
||||||
|
&& strokeWeight > 0.0 ) {
|
||||||
|
drawing.setColor(strokeColor.getColor());
|
||||||
|
drawing.setStroke(createStroke());
|
||||||
|
drawing.draw(pShape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void translate( double dx, double dy ) {
|
||||||
|
drawing.translate(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale( double factor ) {
|
||||||
|
drawing.scale(factor, factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate( double pAngle ) {
|
||||||
|
drawing.rotate(Math.toRadians(pAngle));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shear( double dx, double dy ) {
|
||||||
|
drawing.shear(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AffineTransform getMatrix() {
|
||||||
|
return drawing.getTransform();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushMatrix() {
|
||||||
|
transformStack.push(drawing.getTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popMatrix() {
|
||||||
|
if( transformStack.isEmpty() ) {
|
||||||
|
resetMatrix();
|
||||||
|
} else {
|
||||||
|
drawing.setTransform(transformStack.pop());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetMatrix() {
|
||||||
|
drawing.setTransform(new AffineTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
|
|
||||||
public abstract class Ebene extends Konstanten implements Zeichenbar, Aktualisierbar {
|
|
||||||
|
|
||||||
protected BufferedImage puffer;
|
|
||||||
|
|
||||||
protected Graphics2D zeichnung;
|
|
||||||
|
|
||||||
protected boolean sichtbar = true;
|
|
||||||
|
|
||||||
protected boolean aktiv = true;
|
|
||||||
|
|
||||||
|
|
||||||
public Ebene() {
|
|
||||||
this(STD_BREITE, STD_HOEHE);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Ebene( int pBreite, int pHoehe ) {
|
|
||||||
zeichnungErstellen(pBreite, pHoehe);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getBreite() {
|
|
||||||
return puffer.getWidth();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getHoehe() {
|
|
||||||
return puffer.getHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setGroesse( int pBreite, int pHoehe ) {
|
|
||||||
if( puffer != null ) {
|
|
||||||
zeichnenWiederherstellen(pBreite, pHoehe);
|
|
||||||
} else {
|
|
||||||
zeichnungErstellen(pBreite, pHoehe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void zeichnungErstellen( int pBreite, int pHoehe ) {
|
|
||||||
puffer = new BufferedImage(pBreite, pHoehe, BufferedImage.TYPE_INT_ARGB);
|
|
||||||
zeichnung = puffer.createGraphics();
|
|
||||||
|
|
||||||
// add antialiasing
|
|
||||||
RenderingHints hints = new RenderingHints(
|
|
||||||
RenderingHints.KEY_ANTIALIASING,
|
|
||||||
RenderingHints.VALUE_ANTIALIAS_ON
|
|
||||||
);
|
|
||||||
hints.put(
|
|
||||||
RenderingHints.KEY_RENDERING,
|
|
||||||
RenderingHints.VALUE_RENDER_QUALITY
|
|
||||||
);
|
|
||||||
zeichnung.addRenderingHints(hints);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void zeichnenWiederherstellen( int pBreite, int pHoehe ) {
|
|
||||||
BufferedImage oldCanvas = puffer;
|
|
||||||
zeichnungErstellen(pBreite, pHoehe);
|
|
||||||
zeichnung.drawImage(oldCanvas, 0, 0, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Leert die Ebene und löscht alles bisher gezeichnete.
|
|
||||||
*/
|
|
||||||
public abstract void leeren();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zeichnet den Puffer auf die Grafik-Instanz.
|
|
||||||
*
|
|
||||||
* @param pGraphics
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void zeichnen( Graphics2D pGraphics ) {
|
|
||||||
if( sichtbar ) {
|
|
||||||
pGraphics.drawImage(puffer, 0, 0, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean istSichtbar() {
|
|
||||||
return sichtbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verstecken() {
|
|
||||||
sichtbar = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zeigen() {
|
|
||||||
sichtbar = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void umschalten() {
|
|
||||||
sichtbar = !sichtbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void aktualisieren( double delta ) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean istAktiv() {
|
|
||||||
return aktiv;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
public class Farbe extends Color {
|
|
||||||
|
|
||||||
public static final Farbe SCHWARZ = new Farbe(Color.BLACK);
|
|
||||||
public static final Farbe WEISS = new Farbe(Color.WHITE);
|
|
||||||
public static final Farbe GRAU = new Farbe(Color.GRAY);
|
|
||||||
public static final Farbe DUNKELGRAU = new Farbe(Color.DARK_GRAY);
|
|
||||||
public static final Farbe HELLGRAU = new Farbe(Color.LIGHT_GRAY);
|
|
||||||
|
|
||||||
public static final Farbe ROT = new Farbe(Color.RED);
|
|
||||||
public static final Farbe GRUEN = new Farbe(Color.GREEN);
|
|
||||||
public static final Farbe BLAU = new Farbe(Color.BLUE);
|
|
||||||
public static final Farbe GELB = new Farbe(Color.YELLOW);
|
|
||||||
public static final Farbe ORANGE = new Farbe(Color.ORANGE);
|
|
||||||
public static final Farbe CYAN = new Farbe(Color.CYAN);
|
|
||||||
public static final Farbe MAGENTA = new Farbe(Color.MAGENTA);
|
|
||||||
public static final Farbe PINK = new Farbe(Color.PINK);
|
|
||||||
|
|
||||||
public static final Farbe HGGRUEN = new Farbe(0, 165, 81);
|
|
||||||
public static final Farbe HGROT = new Farbe(151, 54, 60);
|
|
||||||
|
|
||||||
|
|
||||||
public Farbe( int pGrau ) {
|
|
||||||
super(pGrau, pGrau, pGrau, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe( int pGrau, int pAlpha ) {
|
|
||||||
super(pGrau, pGrau, pGrau, pAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public Farbe( int pRot, int pGruen, int pBlau ) {
|
|
||||||
super(pRot, pGruen, pBlau);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe( int pRot, int pGruen, int pBlau, int pAlpha ) {
|
|
||||||
super(pRot, pGruen, pBlau, pAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe( Color pColor ) {
|
|
||||||
super(pColor.getRed(), pColor.getGreen(), pColor.getBlue(), pColor.getAlpha());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe( Color pColor, int pAlpha ) {
|
|
||||||
super(pColor.getRed(), pColor.getGreen(), pColor.getBlue(), pAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Farbe vonRGB( int pRGB ) {
|
|
||||||
return new Farbe(
|
|
||||||
(pRGB >> 16) & 255,
|
|
||||||
(pRGB >> 8) & 255,
|
|
||||||
pRGB & 255,
|
|
||||||
(pRGB >> 24) & 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Farbe vonHexcode( String pHexcode ) {
|
|
||||||
if( pHexcode.startsWith("#") ) {
|
|
||||||
pHexcode = pHexcode.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int red = Integer.valueOf(pHexcode.substring(0, 2), 16);
|
|
||||||
int green = Integer.valueOf(pHexcode.substring(2, 4), 16);
|
|
||||||
int blue = Integer.valueOf(pHexcode.substring(4, 6), 16);
|
|
||||||
|
|
||||||
int alpha = 255;
|
|
||||||
if( pHexcode.length() == 8 ) {
|
|
||||||
alpha = Integer.valueOf(pHexcode.substring(6, 8), 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Farbe(red, green, blue, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Farbe morphen( Color pFarbe1, Color pFarbe2, double pFactor ) {
|
|
||||||
if( pFactor < 0.0 || pFarbe2 == null ) {
|
|
||||||
return new Farbe(pFarbe1);
|
|
||||||
}
|
|
||||||
if( pFactor > 1.0 || pFarbe1 == null )
|
|
||||||
return new Farbe(pFarbe2);
|
|
||||||
double pFactorInv = 1 - pFactor;
|
|
||||||
return new Farbe(
|
|
||||||
(int) (pFactorInv * pFarbe1.getRed() + pFactor * pFarbe2.getRed()),
|
|
||||||
(int) (pFactorInv * pFarbe1.getGreen() + pFactor * pFarbe2.getGreen()),
|
|
||||||
(int) (pFactorInv * pFarbe1.getBlue() + pFactor * pFarbe2.getBlue()),
|
|
||||||
(int) (pFactorInv * pFarbe1.getAlpha() + pFactor * pFarbe2.getAlpha())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe kopie() {
|
|
||||||
return new Farbe(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
75
src/schule/ngb/zm/ImageLayer.java
Normal file
75
src/schule/ngb/zm/ImageLayer.java
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import schule.ngb.zm.util.ImageLoader;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.image.ImageObserver;
|
||||||
|
|
||||||
|
public class ImageLayer extends Layer {
|
||||||
|
|
||||||
|
protected Image image;
|
||||||
|
|
||||||
|
protected double x = 0;
|
||||||
|
|
||||||
|
protected double y = 0;
|
||||||
|
|
||||||
|
protected boolean redraw = true;
|
||||||
|
|
||||||
|
public ImageLayer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ImageLayer( String source ) {
|
||||||
|
image = ImageLoader.loadImage(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageLayer( Image image ) {
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageLayer( int width, int height, Image image ) {
|
||||||
|
super(width, height);
|
||||||
|
this.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setImage( Image image ) {
|
||||||
|
this.image = image;
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX( double pX ) {
|
||||||
|
this.x = pX;
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY( double pY ) {
|
||||||
|
this.y = pY;
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
super.clear();
|
||||||
|
redraw = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D graphics ) {
|
||||||
|
if( redraw && visible ) {
|
||||||
|
drawing.drawImage(image, (int)x, (int)y, null);
|
||||||
|
redraw = false;
|
||||||
|
}
|
||||||
|
super.draw(graphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,145 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import schule.ngb.zm.formen.Konturform;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Arc2D;
|
|
||||||
|
|
||||||
public class Konstanten {
|
|
||||||
|
|
||||||
public static final String APP_NAME = "Zeichenmaschine";
|
|
||||||
|
|
||||||
public static final int STD_BREITE = 400;
|
|
||||||
public static final int STD_HOEHE = 400;
|
|
||||||
public static final int STD_FPS = 60;
|
|
||||||
|
|
||||||
public static Color STD_HINTERGRUND = new Color(200, 200, 200);
|
|
||||||
|
|
||||||
|
|
||||||
public static final int DURCHGEZOGEN = Konturform.DURCHGEZOGEN;
|
|
||||||
public static final int GESTRICHELT = Konturform.GESTRICHELT;
|
|
||||||
public static final int GEPUNKTET = Konturform.GEPUNKTET;
|
|
||||||
|
|
||||||
public static final int OFFEN = Arc2D.OPEN;
|
|
||||||
public static final int GESCHLOSSEN = Arc2D.CHORD;
|
|
||||||
public static final int KREISTEIL = Arc2D.PIE;
|
|
||||||
|
|
||||||
|
|
||||||
public static final byte ZENTRUM = 0;
|
|
||||||
public static final byte NORDEN = 1 << 0;
|
|
||||||
public static final byte OSTEN = 1 << 2;
|
|
||||||
public static final byte SUEDEN = 1 << 3;
|
|
||||||
public static final byte WESTEN = 1 << 4;
|
|
||||||
|
|
||||||
public static final byte NORDOSTEN = NORDEN | OSTEN;
|
|
||||||
public static final byte SUEDOSTEN = SUEDEN | OSTEN;
|
|
||||||
public static final byte NORDWESTEN = NORDEN | WESTEN;
|
|
||||||
public static final byte SUEDWESTEN = SUEDEN | WESTEN;
|
|
||||||
|
|
||||||
public static final byte MITTE = ZENTRUM;
|
|
||||||
public static final byte OBEN = NORDEN;
|
|
||||||
public static final byte RECHTS = OSTEN;
|
|
||||||
public static final byte UNTEN = SUEDEN;
|
|
||||||
public static final byte LINKS = WESTEN;
|
|
||||||
|
|
||||||
|
|
||||||
public static final Farbe SCHWARZ = Farbe.SCHWARZ;
|
|
||||||
public static final Farbe WEISS = Farbe.WEISS;
|
|
||||||
public static final Farbe ROT = Farbe.ROT;
|
|
||||||
public static final Farbe BLAU = Farbe.BLAU;
|
|
||||||
public static final Farbe GRUEN = Farbe.GRUEN;
|
|
||||||
public static final Farbe GELB = Farbe.GELB;
|
|
||||||
|
|
||||||
public Farbe farbe( int pGrau ) {
|
|
||||||
return farbe(pGrau, pGrau, pGrau, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe farbe( int pGrau, int pAlpha ) {
|
|
||||||
return farbe(pGrau, pGrau, pGrau, pAlpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe farbe(int red, int green, int blue) {
|
|
||||||
return farbe(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Farbe farbe(int red, int green, int blue, int alpha) {
|
|
||||||
if (red < 0 || red >= 256)
|
|
||||||
throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256)
|
|
||||||
throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256)
|
|
||||||
throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
if (alpha < 0 || alpha >= 256)
|
|
||||||
throw new IllegalArgumentException("alpha must be between 0 and 255");
|
|
||||||
|
|
||||||
return new Farbe(red, green, blue, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public double abs( double x ) {
|
|
||||||
return Math.abs(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double vorzeichen( double x ) {
|
|
||||||
return Math.signum(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double runden( double x ) {
|
|
||||||
return Math.round(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double abrunden( double x ) {
|
|
||||||
return Math.floor(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double aufrunden( double x ) {
|
|
||||||
return Math.ceil(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double sin( double x ) {
|
|
||||||
return Math.sin(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double cos( double x ) {
|
|
||||||
return Math.cos(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double tan( double x ) {
|
|
||||||
return Math.tan(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double arcsin( double x ) {
|
|
||||||
return Math.asin(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double arccos( double x ) {
|
|
||||||
return Math.acos(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double arctan( double x ) {
|
|
||||||
return Math.atan(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double beschraenken( double x, double max ) {
|
|
||||||
if( x > max ) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double beschraenken( double x, double min, double max ) {
|
|
||||||
if( x > max ) {
|
|
||||||
return max;
|
|
||||||
}
|
|
||||||
if( x < min ) {
|
|
||||||
return min;
|
|
||||||
}
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double morphen( double pVon, double pNach, double pFaktor ) {
|
|
||||||
return pVon - pFaktor*(pVon+pNach);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
138
src/schule/ngb/zm/Layer.java
Normal file
138
src/schule/ngb/zm/Layer.java
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public abstract class Layer extends Constants implements Drawable, Updatable {
|
||||||
|
|
||||||
|
protected BufferedImage buffer;
|
||||||
|
|
||||||
|
protected Graphics2D drawing;
|
||||||
|
|
||||||
|
protected boolean visible = true;
|
||||||
|
|
||||||
|
protected boolean active = true;
|
||||||
|
|
||||||
|
|
||||||
|
public Layer() {
|
||||||
|
this(STD_WIDTH, STD_HEIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Layer( int width, int height ) {
|
||||||
|
createCanvas(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() {
|
||||||
|
return buffer.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHeight() {
|
||||||
|
return buffer.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSize( int width, int height ) {
|
||||||
|
if( buffer != null ) {
|
||||||
|
if( buffer.getWidth() != width || buffer.getHeight() != height ) {
|
||||||
|
recreateCanvas(width, height);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
createCanvas(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
drawing.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen neuen Puffer für die Ebene und konfiguriert diesen.
|
||||||
|
*
|
||||||
|
* @param width Width des neuen Puffers.
|
||||||
|
* @param height Höhe des neuen Puffers.
|
||||||
|
*/
|
||||||
|
private void createCanvas( int width, int height ) {
|
||||||
|
buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
drawing = buffer.createGraphics();
|
||||||
|
|
||||||
|
// add antialiasing
|
||||||
|
RenderingHints hints = new RenderingHints(
|
||||||
|
RenderingHints.KEY_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_ANTIALIAS_ON
|
||||||
|
);
|
||||||
|
hints.put(
|
||||||
|
RenderingHints.KEY_TEXT_ANTIALIASING,
|
||||||
|
RenderingHints.VALUE_TEXT_ANTIALIAS_ON
|
||||||
|
);
|
||||||
|
hints.put(
|
||||||
|
RenderingHints.KEY_RENDERING,
|
||||||
|
RenderingHints.VALUE_RENDER_QUALITY
|
||||||
|
);
|
||||||
|
drawing.addRenderingHints(hints);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen neuen Puffer für dei Ebene mit der angegebenen Größe
|
||||||
|
* und kopiert den Inhalt des alten Puffers in den Neuen.
|
||||||
|
*
|
||||||
|
* @param width Width des neuen Puffers.
|
||||||
|
* @param height Höhe des neuen Puffers.
|
||||||
|
*/
|
||||||
|
private void recreateCanvas( int width, int height ) {
|
||||||
|
BufferedImage oldCanvas = buffer;
|
||||||
|
createCanvas(width, height);
|
||||||
|
drawing.drawImage(oldCanvas, 0, 0, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Leert die Ebene und löscht alles bisher gezeichnete. Alle Pixel der
|
||||||
|
* Ebene werden transparent, damit unterliegende Ebenen durchscheinen können.
|
||||||
|
*/
|
||||||
|
public void clear() {
|
||||||
|
// https://stackoverflow.com/questions/31149206/set-pixels-of-bufferedimage-as-transparent
|
||||||
|
drawing.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR));
|
||||||
|
drawing.setColor(new Color(255, 255, 255, 255));
|
||||||
|
drawing.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
|
||||||
|
drawing.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zeichnet den Puffer auf die Grafik-Instanz.
|
||||||
|
*
|
||||||
|
* @param pGraphics
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D pGraphics ) {
|
||||||
|
if( visible ) {
|
||||||
|
pGraphics.drawImage(buffer, 0, 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void view() {
|
||||||
|
visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggle() {
|
||||||
|
visible = !visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update( double delta ) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import schule.ngb.zm.formen.Formenebene;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Eine Leinwand ist die Hauptkomponente einer Zeichenmaschine. Sie besteht aus
|
|
||||||
* mehreren Ebenen, auf denen auf verschiedene Arten gezeichnet werden kann. Die
|
|
||||||
* Ebenen lassen sich beliebig übereinander anordenen, ausblenden oder wieder
|
|
||||||
* löschen.
|
|
||||||
*
|
|
||||||
* Jede Ebene besitzt eine Zeichenfläche, auf der ihre Zeichnung liegt. Diese
|
|
||||||
* zeichenflächen werden pro Frame einmal von "unten" nach "oben" auf diese
|
|
||||||
* Leinwand gezeichnet.
|
|
||||||
*/
|
|
||||||
public class Leinwand extends JComponent {
|
|
||||||
|
|
||||||
|
|
||||||
private LinkedList<Ebene> ebenen;
|
|
||||||
|
|
||||||
public Leinwand( int pBreite, int pHoehe ) {
|
|
||||||
Dimension dim = new Dimension(pBreite, pHoehe);
|
|
||||||
super.setSize(pBreite, pHoehe);
|
|
||||||
this.setPreferredSize(dim);
|
|
||||||
this.setMinimumSize(dim);
|
|
||||||
|
|
||||||
ebenen = new LinkedList<>();
|
|
||||||
ebenen.add(new Zeichenebene());
|
|
||||||
ebenen.add(new Formenebene());
|
|
||||||
setBackground(Konstanten.STD_HINTERGRUND);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setSize( int pBreite, int pHoehe ) {
|
|
||||||
Dimension dim = new Dimension(pBreite, pHoehe);
|
|
||||||
super.setSize(pBreite, pHoehe);
|
|
||||||
this.setPreferredSize(dim);
|
|
||||||
this.setMinimumSize(dim);
|
|
||||||
|
|
||||||
for( Ebene ebene : ebenen ) {
|
|
||||||
ebene.setGroesse(getWidth(), getHeight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hinzu( Ebene pEbene ) {
|
|
||||||
if( pEbene != null ) {
|
|
||||||
pEbene.setGroesse(getWidth(), getHeight());
|
|
||||||
ebenen.add(pEbene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hinzu( int pIndex, Ebene pEbene ) {
|
|
||||||
if( pEbene != null ) {
|
|
||||||
pEbene.setGroesse(getWidth(), getHeight());
|
|
||||||
ebenen.add(pIndex, pEbene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.util.List<Ebene> getEbenen() {
|
|
||||||
return ebenen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holt die {@link Ebene} am Index <var>i</var> (beginnend bei <code>0</code>).
|
|
||||||
*
|
|
||||||
* @param i Index der Ebene (beginnend bei <code>0</code>).
|
|
||||||
* @return Die Ebene am Index <var>i</var> oder <code>null</code>.
|
|
||||||
* @throws IndexOutOfBoundsException Falls der Index nicht existiert.
|
|
||||||
*/
|
|
||||||
public Ebene getEbene( int i ) {
|
|
||||||
if( ebenen.size() > i ) {
|
|
||||||
return ebenen.get(i);
|
|
||||||
} else {
|
|
||||||
throw new IndexOutOfBoundsException("Keine Ebene mit dem Index " + i + " vorhanden (maximum: " + (ebenen.size() - 1) + ").");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holt die erste Ebene des angegebenen Typs aus der Liste der Ebenen.
|
|
||||||
* Existiert keine solche Ebene, wird <code>null</code> zurückgegeben.
|
|
||||||
*
|
|
||||||
* @param pClazz Typ der Ebene.
|
|
||||||
* @param <L>
|
|
||||||
* @return Erste Ebene vom angegeben Typ.
|
|
||||||
*/
|
|
||||||
public <L extends Ebene> L getEbene( Class<L> pClazz ) {
|
|
||||||
for( Ebene ebene : ebenen ) {
|
|
||||||
if( ebene.getClass().equals(pClazz) ) {
|
|
||||||
return pClazz.cast(ebene);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <L extends Ebene> java.util.List<L> getEbenen( Class<L> pClazz ) {
|
|
||||||
ArrayList<L> result = new ArrayList<>(ebenen.size());
|
|
||||||
for( Ebene ebene : ebenen ) {
|
|
||||||
if( ebene.getClass().equals(pClazz) ) {
|
|
||||||
result.add(pClazz.cast(ebene));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void paintComponent( Graphics g ) {
|
|
||||||
Graphics2D g2d = (Graphics2D) g.create();
|
|
||||||
|
|
||||||
for( Ebene ebene : ebenen ) {
|
|
||||||
ebene.zeichnen(g2d);
|
|
||||||
}
|
|
||||||
|
|
||||||
g2d.dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
67
src/schule/ngb/zm/Options.java
Normal file
67
src/schule/ngb/zm/Options.java
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import java.awt.geom.Arc2D;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Diese Klasse sammelt Enumerationen, die verschiedene Eigenschaften der
|
||||||
|
* zu zeichnenden Formen darstellen.
|
||||||
|
*/
|
||||||
|
public final class Options {
|
||||||
|
private Options() {}
|
||||||
|
|
||||||
|
public enum StrokeType {
|
||||||
|
SOLID, DASHED, DOTTED
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ArrowHead {
|
||||||
|
LINES, FILLED
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PathType {
|
||||||
|
OPEN(Arc2D.OPEN), CLOSED(Arc2D.CHORD), PIE(Arc2D.PIE);
|
||||||
|
public final int awt_type;
|
||||||
|
PathType( int type ) {
|
||||||
|
awt_type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum AppState {
|
||||||
|
INITIALIZING,
|
||||||
|
INITIALIZED,
|
||||||
|
RUNNING,
|
||||||
|
AUSED,
|
||||||
|
STOPPED,
|
||||||
|
TERMINATED
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Direction {
|
||||||
|
CENTER(0),
|
||||||
|
NORTH(1 << 0),
|
||||||
|
EAST(1 << 1),
|
||||||
|
SOUTH(1 << 2),
|
||||||
|
WEST(1 << 3),
|
||||||
|
|
||||||
|
NORTHEAST(NORTH.mask | EAST.mask),
|
||||||
|
SOUTHEAST(SOUTH.mask | EAST.mask),
|
||||||
|
NORTHWEST(NORTH.mask | WEST.mask),
|
||||||
|
SOUTHWEST(SOUTH.mask | WEST.mask),
|
||||||
|
|
||||||
|
MIDDLE(CENTER.mask),
|
||||||
|
UP(NORTH.mask),
|
||||||
|
DOWN(SOUTH.mask),
|
||||||
|
LEFT(WEST.mask),
|
||||||
|
RIGHT(EAST.mask);
|
||||||
|
|
||||||
|
public final byte mask;
|
||||||
|
Direction( int mask ) {
|
||||||
|
this.mask = (byte) mask;
|
||||||
|
}
|
||||||
|
public boolean is( int mask ) {
|
||||||
|
return (mask & this.mask) == this.mask;
|
||||||
|
}
|
||||||
|
public boolean is( Direction dir ) {
|
||||||
|
return (dir.mask & this.mask) == this.mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
166
src/schule/ngb/zm/Shape2DLayer.java
Normal file
166
src/schule/ngb/zm/Shape2DLayer.java
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public final class Shape2DLayer extends Layer {
|
||||||
|
|
||||||
|
protected Color strokeColor = STD_STROKECOLOR;
|
||||||
|
|
||||||
|
protected Color fillColor = STD_FILLCOLOR;
|
||||||
|
|
||||||
|
protected double strokeWeight = STD_STROKEWEIGHT;
|
||||||
|
|
||||||
|
protected Options.StrokeType strokeType = SOLID;
|
||||||
|
|
||||||
|
private LinkedList<java.awt.Shape> shapes;
|
||||||
|
|
||||||
|
private boolean instantDraw = false;
|
||||||
|
|
||||||
|
public Shape2DLayer() {
|
||||||
|
super();
|
||||||
|
shapes = new LinkedList<java.awt.Shape>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape2DLayer( boolean instantDraw ) {
|
||||||
|
super();
|
||||||
|
shapes = new LinkedList<java.awt.Shape>();
|
||||||
|
this.instantDraw = instantDraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape2DLayer( int width, int height ) {
|
||||||
|
super(width, height);
|
||||||
|
shapes = new LinkedList<java.awt.Shape>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape2DLayer( int width, int height, boolean instantDraw ) {
|
||||||
|
super(width, height);
|
||||||
|
shapes = new LinkedList<java.awt.Shape>();
|
||||||
|
this.instantDraw = instantDraw;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getFillColor() {
|
||||||
|
return fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int gray ) {
|
||||||
|
setFillColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( Color pColor ) {
|
||||||
|
fillColor = pColor;
|
||||||
|
drawing.setColor(pColor.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noFill() {
|
||||||
|
fillColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int gray, int alpha ) {
|
||||||
|
setFillColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int red, int green, int blue ) {
|
||||||
|
setFillColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setFillColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Color getStrokeColor() {
|
||||||
|
return strokeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray ) {
|
||||||
|
setStrokeColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( Color pColor ) {
|
||||||
|
strokeColor = pColor;
|
||||||
|
drawing.setColor(pColor.getColor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noStroke() {
|
||||||
|
strokeColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray, int alpha ) {
|
||||||
|
setStrokeColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue ) {
|
||||||
|
setStrokeColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setStrokeColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeWeight( double pWeight ) {
|
||||||
|
strokeWeight = pWeight;
|
||||||
|
drawing.setStroke(createStroke());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Stroke createStroke() {
|
||||||
|
switch( strokeType ) {
|
||||||
|
case DOTTED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{1.0f, 5.0f}, 0.0f);
|
||||||
|
case DASHED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{5.0f}, 0.0f);
|
||||||
|
default:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options.StrokeType getStrokeType() {
|
||||||
|
return strokeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeType( Options.StrokeType strokeType ) {
|
||||||
|
this.strokeType = strokeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.List<java.awt.Shape> getShapes() {
|
||||||
|
return shapes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( java.awt.Shape s ) {
|
||||||
|
shapes.add(s);
|
||||||
|
|
||||||
|
if( instantDraw ) {
|
||||||
|
drawing.setColor(fillColor.getColor());
|
||||||
|
drawing.fill(s);
|
||||||
|
|
||||||
|
drawing.setColor(strokeColor.getColor());
|
||||||
|
drawing.draw(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D pGraphics ) {
|
||||||
|
if( !instantDraw ) {
|
||||||
|
for( Shape shape : shapes ) {
|
||||||
|
drawing.setColor(fillColor.getColor());
|
||||||
|
drawing.fill(shape);
|
||||||
|
|
||||||
|
drawing.setColor(strokeColor.getColor());
|
||||||
|
drawing.draw(shape);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.draw(pGraphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -2,22 +2,22 @@ package schule.ngb.zm;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Aktualisierbare Objekte können in regelmäßigen Intervallen (meist einmal
|
* Aktualisierbare Objekte können in regelmäßigen Intervallen (meist einmal
|
||||||
* pro Frame) ihren Zustand aktualisieren. Diese Änderung kann abhängig vom
|
* pro Frame) ihren Zustand update. Diese Änderung kann abhängig vom
|
||||||
* Zeitintervall (in Sekunden) zum letzten Aufruf passieren.
|
* Zeitintervall (in Sekunden) zum letzten Aufruf passieren.
|
||||||
*/
|
*/
|
||||||
public interface Aktualisierbar {
|
public interface Updatable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gibt an, ob das Objekt gerade auf Aktualisierungen reagiert.
|
* Gibt an, ob das Objekt gerade auf Aktualisierungen reagiert.
|
||||||
* @return <code>true</code>, wenn das Objekt aktiv ist.
|
* @return <code>true</code>, wenn das Objekt aktiv ist.
|
||||||
*/
|
*/
|
||||||
public boolean istAktiv();
|
public boolean isActive();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Änderung des Zustandes des Objekts abhängig vom Zeitintervall
|
* Änderung des Zustandes des Objekts abhängig vom Zeitintervall
|
||||||
* <var>delta</var> in Sekunden.
|
* <var>delta</var> in Sekunden.
|
||||||
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
||||||
*/
|
*/
|
||||||
public void aktualisieren( double delta );
|
public void update( double delta );
|
||||||
|
|
||||||
}
|
}
|
||||||
253
src/schule/ngb/zm/Vector.java
Normal file
253
src/schule/ngb/zm/Vector.java
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
|
public class Vector extends Point2D.Double {
|
||||||
|
|
||||||
|
public static final Vector UP = new Vector(0, -1.0);
|
||||||
|
public static final Vector DOWN = new Vector(0, 1.0);
|
||||||
|
public static final Vector RIGHT = new Vector(1.0, 0);
|
||||||
|
public static final Vector LEFT = new Vector(-1.0, -1.0);
|
||||||
|
|
||||||
|
|
||||||
|
public Vector() {
|
||||||
|
x = 0.0;
|
||||||
|
y = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector( double x, double pY ) {
|
||||||
|
this.x = x;
|
||||||
|
y = pY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector( Point2D point ) {
|
||||||
|
x = point.getX();
|
||||||
|
x = point.getY();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector( Vector vec ) {
|
||||||
|
x = vec.x;
|
||||||
|
y = vec.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector random() {
|
||||||
|
return new Vector(Math.random() * 100, Math.random() * 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector random( double min, double max ) {
|
||||||
|
return new Vector(Math.random() * (max - min) + min, Math.random() * (max - min) + min);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector setLength( Vector vector, double length ) {
|
||||||
|
Vector vec = vector.copy();
|
||||||
|
vec.setLen(length);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector normalize( Vector vector ) {
|
||||||
|
Vector vec = vector.copy();
|
||||||
|
vec.normalize();
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector add( Vector vector1, Vector vector2 ) {
|
||||||
|
Vector vec = vector1.copy();
|
||||||
|
vec.add(vector2);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector sub( Vector vector1, Vector vector2 ) {
|
||||||
|
Vector vec = vector1.copy();
|
||||||
|
vec.sub(vector2);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector scale( Vector vector, double scalar ) {
|
||||||
|
Vector vec = vector.copy();
|
||||||
|
vec.scale(scalar);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector div( Vector vector, double scalar ) {
|
||||||
|
Vector vec = vector.copy();
|
||||||
|
vec.div(scalar);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double dist( Vector vector1, Vector vector2 ) {
|
||||||
|
return vector1.dist(vector2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double dot( Vector vector1, Vector vector2 ) {
|
||||||
|
return vector1.dot(vector2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double cross( Vector vector1, Vector vector2 ) {
|
||||||
|
return vector1.cross(vector2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector rotate( Vector vector, double degree ) {
|
||||||
|
Vector vec = vector.copy();
|
||||||
|
vec.rotate(degree);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Vector morph( Vector vector1, Vector vector2, float t ) {
|
||||||
|
Vector vec = vector1.copy();
|
||||||
|
vec.morph(vector2, t);
|
||||||
|
return vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector copy() {
|
||||||
|
return new Vector(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector set( double x, double y ) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector set( Vector vector ) {
|
||||||
|
x = vector.x;
|
||||||
|
y = vector.y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector set( Point2D pPunkt ) {
|
||||||
|
x = pPunkt.getX();
|
||||||
|
x = pPunkt.getY();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX( double x ) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY( double y ) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getPunkt() {
|
||||||
|
return new Point2D.Double(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double len() {
|
||||||
|
return Math.sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double lenSq() {
|
||||||
|
return x * x + y * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector setLen( double length ) {
|
||||||
|
normalize();
|
||||||
|
return scale(length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector normalize() {
|
||||||
|
double len = len();
|
||||||
|
if( len != 0 && len != 1 ) {
|
||||||
|
x /= len;
|
||||||
|
y /= len;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector add( Vector vector ) {
|
||||||
|
x += vector.x;
|
||||||
|
y += vector.y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector add( double x, double y ) {
|
||||||
|
this.x += x;
|
||||||
|
this.y += y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector sub( Vector vector ) {
|
||||||
|
x -= vector.x;
|
||||||
|
y -= vector.y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector sub( double x, double y ) {
|
||||||
|
this.x -= x;
|
||||||
|
this.y -= y;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector scale( double scalar ) {
|
||||||
|
x *= scalar;
|
||||||
|
y *= scalar;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector div( double scalar ) {
|
||||||
|
x /= scalar;
|
||||||
|
y /= scalar;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double dist( Vector vector ) {
|
||||||
|
double dx = x - vector.x;
|
||||||
|
double dy = y - vector.y;
|
||||||
|
return Math.sqrt(dx * dx + dy * dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double dot( Vector vector ) {
|
||||||
|
return x * vector.x + y * vector.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double dot( double x, double y ) {
|
||||||
|
return this.x * x + this.y * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
|
||||||
|
public double cross( Vector vector ) {
|
||||||
|
return x * vector.y - vector.x * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector limit( double max ) {
|
||||||
|
if( lenSq() > max * max ) {
|
||||||
|
setLen(max);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector limit( double min, double max ) {
|
||||||
|
if( min > max ) {
|
||||||
|
throw new IllegalArgumentException("HVector.constrain(): pMin muss kleiner sein als pMax.");
|
||||||
|
}
|
||||||
|
if( lenSq() < min * min ) {
|
||||||
|
setLen(min);
|
||||||
|
} else if( lenSq() > min * min ) {
|
||||||
|
setLen(max);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double angle() {
|
||||||
|
double angle = Math.atan2(y, x);
|
||||||
|
return Math.toDegrees(angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector rotate( double degree ) {
|
||||||
|
double temp = x, rad = Math.toRadians(degree);
|
||||||
|
x = x * Math.cos(rad) - y * Math.sin(rad);
|
||||||
|
y = temp * Math.sin(rad) + y * Math.cos(rad);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void morph( Vector vector, float t ) {
|
||||||
|
x = x + (vector.x - x) * t;
|
||||||
|
y = y + (vector.y - y) * t;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "schule.ngb.zm.Vector[x = " + x + ", y = " + y + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,251 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
|
|
||||||
public class Vektor extends Point2D.Double {
|
|
||||||
|
|
||||||
public Vektor() {
|
|
||||||
x = 0.0;
|
|
||||||
y = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor(double pX, double pY) {
|
|
||||||
x = pX;
|
|
||||||
y = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor(Point2D.Double pPunkt) {
|
|
||||||
x = pPunkt.getX();
|
|
||||||
x = pPunkt.getY();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor(Vektor pVektor) {
|
|
||||||
x = pVektor.x;
|
|
||||||
y = pVektor.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor zufall() {
|
|
||||||
return new Vektor(Math.random()*100, Math.random()*100);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor zufall( double min, double max ) {
|
|
||||||
return new Vektor(Math.random()*(max-min)+min, Math.random()*(max-min)+min);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor kopie() {
|
|
||||||
return new Vektor(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor set(double pX, double pY) {
|
|
||||||
x = pX;
|
|
||||||
y = pY;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor set(Vektor pVektor) {
|
|
||||||
x = pVektor.x;
|
|
||||||
y = pVektor.y;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor set(Point2D.Double pPunkt) {
|
|
||||||
x = pPunkt.getX();
|
|
||||||
x = pPunkt.getY();
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setX(double pX) {
|
|
||||||
x = pX;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY(double pY) {
|
|
||||||
y = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D.Double getPunkt() {
|
|
||||||
return new Point2D.Double(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double laenge() {
|
|
||||||
return Math.sqrt(x * x + y * y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double laengeQuad() {
|
|
||||||
return x * x + y * y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor setLaenge(double pLaenge) {
|
|
||||||
normalisieren();
|
|
||||||
return skalieren(pLaenge);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor setLaenge(Vektor pVektor, double pLaenge) {
|
|
||||||
Vektor vec = pVektor.kopie();
|
|
||||||
vec.setLaenge(pLaenge);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor normalisieren() {
|
|
||||||
double len = laenge();
|
|
||||||
if (len != 0 && len != 1) {
|
|
||||||
x /= len;
|
|
||||||
y /= len;
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor normalisieren(Vektor pVektor) {
|
|
||||||
Vektor vec = pVektor.kopie();
|
|
||||||
vec.normalisieren();
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor addieren(Vektor pVektor) {
|
|
||||||
x += pVektor.x;
|
|
||||||
y += pVektor.y;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor addieren(double pX, double pY) {
|
|
||||||
x += pX;
|
|
||||||
y += pY;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor addieren(Vektor pVektor1, Vektor pVektor2) {
|
|
||||||
Vektor vec = pVektor1.kopie();
|
|
||||||
vec.addieren(pVektor2);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void subtrahieren(Vektor pVektor) {
|
|
||||||
x -= pVektor.x;
|
|
||||||
y -= pVektor.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void subtrahieren(double pX, double pY) {
|
|
||||||
x -= pX;
|
|
||||||
y -= pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor subtrahieren(Vektor pVektor1, Vektor pVektor2) {
|
|
||||||
Vektor vec = pVektor1.kopie();
|
|
||||||
vec.subtrahieren(pVektor2);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor skalieren(double pSkalar) {
|
|
||||||
x *= pSkalar;
|
|
||||||
y *= pSkalar;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor skalieren(Vektor pVektor, double pSkalar) {
|
|
||||||
Vektor vec = pVektor.kopie();
|
|
||||||
vec.skalieren(pSkalar);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor dividieren(double pSkalar) {
|
|
||||||
x /= pSkalar;
|
|
||||||
y /= pSkalar;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor dividieren(Vektor pVektor, double pSkalar) {
|
|
||||||
Vektor vec = pVektor.kopie();
|
|
||||||
vec.dividieren(pSkalar);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double abstand(Vektor pVektor) {
|
|
||||||
double dx = x - pVektor.x;
|
|
||||||
double dy = y - pVektor.y;
|
|
||||||
return Math.sqrt(dx * dx + dy * dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double abstand(Vektor pVektor1, Vektor pVektor2) {
|
|
||||||
return pVektor1.abstand(pVektor2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double dot(Vektor pVektor) {
|
|
||||||
return x * pVektor.x + y * pVektor.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double dot(double pX, double pY) {
|
|
||||||
return x * pX + y * pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double dot(Vektor pVektor1, Vektor pVektor2) {
|
|
||||||
return pVektor1.dot(pVektor2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// See: http://allenchou.net/2013/07/cross-product-of-2d-vectors/
|
|
||||||
public double cross(Vektor pVektor) {
|
|
||||||
return x * pVektor.y - pVektor.x * y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static double cross(Vektor pVektor1, Vektor pVektor2) {
|
|
||||||
return pVektor1.cross(pVektor2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void limitieren(double pMax) {
|
|
||||||
if (laengeQuad() > pMax * pMax) {
|
|
||||||
normalisieren();
|
|
||||||
skalieren(pMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void beschraenken(double pMin, double pMax) {
|
|
||||||
if (pMin > pMax) {
|
|
||||||
throw new IllegalArgumentException("HVector.constrain(): pMin muss kleiner sein als pMax.");
|
|
||||||
}
|
|
||||||
if (laengeQuad() < pMin * pMin) {
|
|
||||||
normalisieren();
|
|
||||||
skalieren(pMin);
|
|
||||||
}
|
|
||||||
if (laengeQuad() > pMax * pMax) {
|
|
||||||
normalisieren();
|
|
||||||
skalieren(pMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double richtung() {
|
|
||||||
double angle = Math.atan2(y, x);
|
|
||||||
return angle;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double winkel() {
|
|
||||||
return richtung();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vektor drehen(double pWinkel) {
|
|
||||||
double temp = x;
|
|
||||||
x = x * Math.cos(pWinkel) - y * Math.sin(pWinkel);
|
|
||||||
y = temp * Math.sin(pWinkel) + y * Math.cos(pWinkel);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor drehen(Vektor pVektor, double pWinkel) {
|
|
||||||
Vektor vec = pVektor.kopie();
|
|
||||||
vec.drehen(pWinkel);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void linterp(Vektor pVektor, float t) {
|
|
||||||
x = x + (pVektor.x - x) * t;
|
|
||||||
y = y + (pVektor.y - y) * t;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Vektor linterp(Vektor pVektor1, Vektor pVektor2, float t) {
|
|
||||||
Vektor vec = pVektor1.kopie();
|
|
||||||
vec.linterp(pVektor2, t);
|
|
||||||
return vec;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "schule.ngb.zm.Vektor{x = " + x + ", y = " + y + "}";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,417 +0,0 @@
|
|||||||
package schule.ngb.zm;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.*;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
public class Zeichenebene extends Ebene {
|
|
||||||
|
|
||||||
private int default_anchor = ZENTRUM;
|
|
||||||
|
|
||||||
protected Color strokeColor;
|
|
||||||
|
|
||||||
protected Color fillColor;
|
|
||||||
|
|
||||||
protected double strokeWeight;
|
|
||||||
|
|
||||||
protected int konturArt = DURCHGEZOGEN;
|
|
||||||
|
|
||||||
public Color getColor() {
|
|
||||||
return fillColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void noFill() {
|
|
||||||
fillColor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int gray) {
|
|
||||||
setColor(gray, gray, gray, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int gray, int alpha) {
|
|
||||||
setColor(gray, gray, gray, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int red, int green, int blue) {
|
|
||||||
setColor(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(int red, int green, int blue, int alpha ) {
|
|
||||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
if (alpha < 0 || alpha >= 256) throw new IllegalArgumentException("alpha must be between 0 and 255");
|
|
||||||
|
|
||||||
setColor(new Color(red, green, blue, alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setColor(Color pColor) {
|
|
||||||
fillColor = pColor;
|
|
||||||
zeichnung.setColor(pColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Color getStrokeColor() {
|
|
||||||
return strokeColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void noStroke() {
|
|
||||||
strokeColor = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeColor(int gray) {
|
|
||||||
setStrokeColor(gray, gray, gray, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeColor(int gray, int alpha) {
|
|
||||||
setStrokeColor(gray, gray, gray, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeColor(int red, int green, int blue) {
|
|
||||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
setStrokeColor(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeColor(int red, int green, int blue, int alpha ) {
|
|
||||||
if (red < 0 || red >= 256) throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256) throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256) throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
if (alpha < 0 || alpha >= 256) throw new IllegalArgumentException("alpha must be between 0 and 255");
|
|
||||||
|
|
||||||
setStrokeColor(new Color(red, green, blue, alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeColor(Color pColor) {
|
|
||||||
strokeColor = pColor;
|
|
||||||
zeichnung.setColor(pColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStrokeWeight( double pWeight ) {
|
|
||||||
strokeWeight = pWeight;
|
|
||||||
zeichnung.setStroke(createStroke());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Stroke createStroke() {
|
|
||||||
switch(konturArt) {
|
|
||||||
case GEPUNKTET:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) strokeWeight,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND,
|
|
||||||
10.0f, new float[]{1.0f, 5.0f}, 0.0f);
|
|
||||||
case GESTRICHELT:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) strokeWeight,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND,
|
|
||||||
10.0f, new float[]{5.0f}, 0.0f);
|
|
||||||
default:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) strokeWeight,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKonturArt() {
|
|
||||||
return konturArt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturArt(int konturArt) {
|
|
||||||
this.konturArt = konturArt;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Stack<AffineTransform> transformStack = new Stack<>();
|
|
||||||
|
|
||||||
public Zeichenebene() {
|
|
||||||
super();
|
|
||||||
transformStack.push(new AffineTransform());
|
|
||||||
|
|
||||||
strokeColor = Color.BLACK;
|
|
||||||
fillColor = Color.WHITE;
|
|
||||||
strokeWeight = 1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Zeichenebene( int pWidth, int pHeight) {
|
|
||||||
super(pWidth, pHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnchor( int pAnchor ) {
|
|
||||||
default_anchor = pAnchor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void leeren() {
|
|
||||||
clear(200);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(int gray) {
|
|
||||||
clear(gray, gray, gray, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(int gray, int alpha) {
|
|
||||||
clear(gray, gray, gray, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(int red, int green, int blue) {
|
|
||||||
clear(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(int red, int green, int blue, int alpha) {
|
|
||||||
clear(new Color(red, green, blue, alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear(Color pColor) {
|
|
||||||
/*graphics.setBackground(pColor);
|
|
||||||
graphics.clearRect(0, 0, canvas.getWidth(), canvas.getHeight());*/
|
|
||||||
Color currentColor = zeichnung.getColor();
|
|
||||||
pushMatrix();
|
|
||||||
resetMatrix();
|
|
||||||
zeichnung.setColor(pColor);
|
|
||||||
zeichnung.fillRect(0, 0, puffer.getWidth(), puffer.getHeight());
|
|
||||||
zeichnung.setColor(currentColor);
|
|
||||||
popMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void line(double x1, double y1, double x2, double y2) {
|
|
||||||
Shape line = new Line2D.Double(x1, y1, x2, y2);
|
|
||||||
//line = transformToCanvas(line);
|
|
||||||
|
|
||||||
drawShape(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pixel(double x, double y) {
|
|
||||||
square(x, y, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void square(double x, double y, double w) {
|
|
||||||
rect(x, y, w, w);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void square(double x, double y, double w, int anchor) {
|
|
||||||
rect(x, y, w, w, anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void rect(double x, double y, double w, double h) {
|
|
||||||
rect(x, y, w, h, default_anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void rect(double x, double y, double w, double h, int anchor) {
|
|
||||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
|
||||||
Shape rect = new Rectangle2D.Double(
|
|
||||||
anchorPoint.getX(), anchorPoint.getY(), w, h
|
|
||||||
);
|
|
||||||
//rect = transformToCanvas(rect);
|
|
||||||
|
|
||||||
fillShape(rect);
|
|
||||||
drawShape(rect);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void point(double x, double y) {
|
|
||||||
circle(x - 1, y - 1, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void circle(double x, double y, double d) {
|
|
||||||
ellipse(x, y, d, d, default_anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void circle(double x, double y, double d, int anchor) {
|
|
||||||
ellipse(x, y, d, d, anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ellipse(double x, double y, double w, double h) {
|
|
||||||
ellipse(x, y, w, h, default_anchor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ellipse(double x, double y, double w, double h, int anchor) {
|
|
||||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, w, h, anchor);
|
|
||||||
Shape ellipse = new Ellipse2D.Double(
|
|
||||||
anchorPoint.x, anchorPoint.y, w, h
|
|
||||||
);
|
|
||||||
//ellipse = transformToCanvas(ellipse);
|
|
||||||
|
|
||||||
fillShape(ellipse);
|
|
||||||
drawShape(ellipse);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void arc( double x, double y, double d, double angle1, double angle2 ) {
|
|
||||||
while (angle2 < angle1) angle2 += 360.0;
|
|
||||||
|
|
||||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, ZENTRUM);
|
|
||||||
Shape arc = new Arc2D.Double(
|
|
||||||
anchorPoint.x,
|
|
||||||
anchorPoint.y,
|
|
||||||
d, d,
|
|
||||||
angle1, angle2 - angle1,
|
|
||||||
Arc2D.OPEN
|
|
||||||
);
|
|
||||||
//arc = transformToCanvas(arc);
|
|
||||||
|
|
||||||
drawShape(arc);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pie( double x, double y, double d, double angle1, double angle2 ) {
|
|
||||||
while (angle2 < angle1) angle2 += 360.0;
|
|
||||||
|
|
||||||
Point2D.Double anchorPoint = getAnchorPoint(x, y, d, d, ZENTRUM);
|
|
||||||
Shape arc = new Arc2D.Double(
|
|
||||||
anchorPoint.x,
|
|
||||||
anchorPoint.y,
|
|
||||||
d, d,
|
|
||||||
angle1, angle2 - angle1,
|
|
||||||
Arc2D.PIE
|
|
||||||
);
|
|
||||||
//arc = transformToCanvas(arc);
|
|
||||||
|
|
||||||
fillShape(arc);
|
|
||||||
drawShape(arc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double transformToCanvas(double x, double y) {
|
|
||||||
return transformToCanvas(new Point2D.Double(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double transformToCanvas( Point2D.Double pPoint ) {
|
|
||||||
AffineTransform matrix = getMatrix();
|
|
||||||
matrix.transform(pPoint, pPoint);
|
|
||||||
return pPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Shape transformToCanvas( Shape pShape ) {
|
|
||||||
AffineTransform matrix = getMatrix();
|
|
||||||
return matrix.createTransformedShape(pShape);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double transformToUser(double x, double y) {
|
|
||||||
return transformToUser(new Point2D.Double(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double transformToUser( Point2D.Double pPoint ) {
|
|
||||||
AffineTransform matrix = getMatrix();
|
|
||||||
|
|
||||||
try {
|
|
||||||
matrix.inverseTransform(pPoint, pPoint);
|
|
||||||
} catch (NoninvertibleTransformException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return pPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Shape transformToUser( Shape pShape ) {
|
|
||||||
AffineTransform matrix = getMatrix();
|
|
||||||
try {
|
|
||||||
matrix = matrix.createInverse();
|
|
||||||
pShape = matrix.createTransformedShape(pShape);
|
|
||||||
} catch (NoninvertibleTransformException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return pShape;
|
|
||||||
}
|
|
||||||
|
|
||||||
private AffineTransform getAnchorTransform( Shape pShape, int anchor ) {
|
|
||||||
AffineTransform at = new AffineTransform();
|
|
||||||
Rectangle2D bounds = pShape.getBounds2D();
|
|
||||||
switch(anchor) {
|
|
||||||
case ZENTRUM:
|
|
||||||
at.translate(
|
|
||||||
bounds.getWidth() / -2.0,
|
|
||||||
bounds.getHeight() / -2.0
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WESTEN:
|
|
||||||
at.translate(
|
|
||||||
0, bounds.getHeight() / -2.0
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SUEDWESTEN:
|
|
||||||
at.translate(
|
|
||||||
0, -1.0 * bounds.getHeight()
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return at;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double getAnchorPoint(double x, double y, double w, double h, int anchor) {
|
|
||||||
switch(anchor) {
|
|
||||||
case ZENTRUM:
|
|
||||||
x -= w / 2.0;
|
|
||||||
y -= h / 2.0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case WESTEN:
|
|
||||||
y -= h / 2.0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SUEDWESTEN:
|
|
||||||
y -= h;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Point2D.Double(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Point2D.Double getAnchorPoint(Shape pShape, int anchor) {
|
|
||||||
Rectangle2D bounds = pShape.getBounds2D();
|
|
||||||
return getAnchorPoint(
|
|
||||||
bounds.getX(), bounds.getY(),
|
|
||||||
bounds.getWidth(), bounds.getHeight(), anchor
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fillShape( Shape pShape ) {
|
|
||||||
if (fillColor != null && fillColor.getAlpha() > 0.0) {
|
|
||||||
zeichnung.setColor(fillColor);
|
|
||||||
zeichnung.fill(pShape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void drawShape( Shape pShape ) {
|
|
||||||
if (strokeColor != null && strokeColor.getAlpha() > 0.0
|
|
||||||
&& strokeWeight > 0.0 ) {
|
|
||||||
zeichnung.setColor(strokeColor);
|
|
||||||
zeichnung.draw(pShape);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void translate( double dx, double dy ) {
|
|
||||||
zeichnung.translate(dx, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void scale( double factor ) {
|
|
||||||
zeichnung.scale(factor, factor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void rotate( double pAngle ) {
|
|
||||||
zeichnung.rotate(Math.toRadians(pAngle));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void shear( double dx, double dy ) {
|
|
||||||
zeichnung.shear(dx, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AffineTransform getMatrix() {
|
|
||||||
return zeichnung.getTransform();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void pushMatrix() {
|
|
||||||
transformStack.push(zeichnung.getTransform());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void popMatrix() {
|
|
||||||
if( transformStack.isEmpty() ) {
|
|
||||||
resetMatrix();
|
|
||||||
} else {
|
|
||||||
zeichnung.setTransform(transformStack.pop());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void resetMatrix() {
|
|
||||||
zeichnung.setTransform(new AffineTransform());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
195
src/schule/ngb/zm/Zeichenleinwand.java
Normal file
195
src/schule/ngb/zm/Zeichenleinwand.java
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import schule.ngb.zm.formen.ShapesLayer;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferStrategy;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine Leinwand ist die Hauptkomponente einer Zeichenmaschine. Sie besteht aus
|
||||||
|
* mehreren Ebenen, auf denen auf verschiedene Arten gezeichnet werden kann. Die
|
||||||
|
* Ebenen lassen sich beliebig übereinander aNORTHen, ausblenden oder wieder
|
||||||
|
* löschen.
|
||||||
|
*
|
||||||
|
* Jede Ebene besitzt eine Zeichenfläche, auf der ihre Zeichnung liegt. Diese
|
||||||
|
* zeichenflächen werden pro Frame einmal von "DOWN" nach "UP" auf diese
|
||||||
|
* Leinwand gezeichnet.
|
||||||
|
*/
|
||||||
|
public class Zeichenleinwand extends Canvas {
|
||||||
|
|
||||||
|
private LinkedList<Layer> layers;
|
||||||
|
|
||||||
|
public Zeichenleinwand( int width, int height ) {
|
||||||
|
super.setSize(width, height);
|
||||||
|
this.setPreferredSize(this.getSize());
|
||||||
|
this.setMinimumSize(this.getSize());
|
||||||
|
this.setBackground(Constants.STD_BACKGROUND.getColor());
|
||||||
|
|
||||||
|
// Liste der Ebenen initialisieren und die Standardebenen einfügen
|
||||||
|
layers = new LinkedList<>();
|
||||||
|
layers.add(new ColorLayer(Constants.STD_BACKGROUND));
|
||||||
|
layers.add(new DrawingLayer());
|
||||||
|
layers.add(new ShapesLayer());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ändert die Größe der Zeichenleinwand auf die angegebene Größe in Pixeln.
|
||||||
|
* Eine Größenänderung hat auch eine Größenänderung aller Ebenen zur Folge.
|
||||||
|
*
|
||||||
|
* @param width Neue Width der Leinwand in Pixeln.
|
||||||
|
* @param height Neue Höhe der Leinwand in Pixeln.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void setSize( int width, int height ) {
|
||||||
|
super.setSize(width, height);
|
||||||
|
this.setPreferredSize(this.getSize());
|
||||||
|
this.setMinimumSize(this.getSize());
|
||||||
|
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
layer.setSize(width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fügt der Zeichenleinwand eine Ebene hinzu, die oberhalb aller bisherigen
|
||||||
|
* Ebenen eingefügt wird.
|
||||||
|
* @param layer Die neue Ebene.
|
||||||
|
*/
|
||||||
|
public void addLayer( Layer layer ) {
|
||||||
|
if( layer != null ) {
|
||||||
|
layer.setSize(getWidth(), getHeight());
|
||||||
|
layers.add(layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fügt der Zeichenleinwand eine Ebene an einer bestimmten Stelle hinzu.
|
||||||
|
* @param i Index der Ebene, beginnend mit <code>0</code>.
|
||||||
|
* @param layer Die neue Ebene.
|
||||||
|
*/
|
||||||
|
public void addLayer( int i, Layer layer ) {
|
||||||
|
if( layer != null ) {
|
||||||
|
layer.setSize(getWidth(), getHeight());
|
||||||
|
layers.add(i, layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gibt die Liste der bisher hinzugefügten Ebenen zurück.
|
||||||
|
* @return Liste der Ebenen.
|
||||||
|
*/
|
||||||
|
public java.util.List<Layer> getLayers() {
|
||||||
|
return layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holt die Ebene am Index <var>i</var> (beginnend bei <code>0</code>).
|
||||||
|
*
|
||||||
|
* @param i Index der Ebene (beginnend bei <code>0</code>).
|
||||||
|
* @return Die Ebene am Index <var>i</var> oder <code>null</code>.
|
||||||
|
* @throws IndexOutOfBoundsException Falls der Index nicht existiert.
|
||||||
|
*/
|
||||||
|
public Layer getLayer( int i ) {
|
||||||
|
if( layers.size() > i ) {
|
||||||
|
return layers.get(i);
|
||||||
|
} else {
|
||||||
|
throw new IndexOutOfBoundsException("No layer at index " + i + " (max: " + (layers.size() - 1) + ").");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sucht die erste Ebene des angegebenen Typs aus der Liste der Ebenen.
|
||||||
|
* Existiert keine solche Ebene, wird <code>null</code> zurückgegeben.
|
||||||
|
*
|
||||||
|
* @param clazz Typ der Ebene.
|
||||||
|
* @param <L>
|
||||||
|
* @return Erste Ebene vom angegeben Typ.
|
||||||
|
*/
|
||||||
|
public <L extends Layer> L getLayer( Class<L> clazz ) {
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
if( layer.getClass().equals(clazz) ) {
|
||||||
|
return clazz.cast(layer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sucht alle Ebenen von einem bestimmten Typ aus der Liste der Ebenen und
|
||||||
|
* gibt diese als Liste zurück. Die Reihenfolge in der Liste entspricht der
|
||||||
|
* Reihenfolge der Ebenen in der Leinwand (von unten nach oben).
|
||||||
|
*
|
||||||
|
* @param pClazz
|
||||||
|
* @param <L>
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public <L extends Layer> java.util.List<L> getLayers( Class<L> pClazz ) {
|
||||||
|
ArrayList<L> result = new ArrayList<>(layers.size());
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
if( layer.getClass().equals(pClazz) ) {
|
||||||
|
result.add(pClazz.cast(layer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void allocateBuffer() {
|
||||||
|
this.createBufferStrategy(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dispose() {
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
layer.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint( Graphics g ) {
|
||||||
|
render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render() {
|
||||||
|
if( getBufferStrategy() == null ) {
|
||||||
|
allocateBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( isDisplayable() ) {
|
||||||
|
BufferStrategy strategy = this.getBufferStrategy();
|
||||||
|
if( strategy != null ) {
|
||||||
|
do {
|
||||||
|
do {
|
||||||
|
Graphics2D g2d = (Graphics2D) strategy.getDrawGraphics();
|
||||||
|
g2d.clearRect(0, 0, getWidth(), getHeight());
|
||||||
|
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
layer.draw(g2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2d.dispose();
|
||||||
|
} while( strategy.contentsRestored() );
|
||||||
|
|
||||||
|
// Display the buffer
|
||||||
|
if (!strategy.contentsLost()) {
|
||||||
|
strategy.show();
|
||||||
|
|
||||||
|
Toolkit.getDefaultToolkit().sync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat the rendering if the drawing buffer was lost
|
||||||
|
} while( strategy.contentsLost() );
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Graphics2D g2d = (Graphics2D) g.create();
|
||||||
|
|
||||||
|
for( Layer layer : layers ) {
|
||||||
|
layer.draw(g2d);
|
||||||
|
}
|
||||||
|
|
||||||
|
g2d.dispose();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
471
src/schule/ngb/zm/Zeichenmaschine.java
Normal file
471
src/schule/ngb/zm/Zeichenmaschine.java
Normal file
@@ -0,0 +1,471 @@
|
|||||||
|
package schule.ngb.zm;
|
||||||
|
|
||||||
|
import schule.ngb.zm.formen.ShapesLayer;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.MouseInputListener;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hauptklasse der Zeichenmaschine.
|
||||||
|
*
|
||||||
|
* Projekte der Zeichenmaschine sollten als Unterklasse implementiert werden.
|
||||||
|
* Die Klasse übernimmt die Initialisierung eines Programmfensters und der
|
||||||
|
* nötigen Komponenten.
|
||||||
|
*/
|
||||||
|
public class Zeichenmaschine extends Constants implements MouseInputListener, KeyListener {
|
||||||
|
|
||||||
|
public static boolean IN_BLUEJ;
|
||||||
|
|
||||||
|
static {
|
||||||
|
IN_BLUEJ = System.getProperty("java.class.path").contains("bluej");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Attributes to be accessed by subclasses.
|
||||||
|
*/
|
||||||
|
protected Zeichenleinwand canvas;
|
||||||
|
|
||||||
|
protected DrawingLayer drawing;
|
||||||
|
|
||||||
|
protected ShapesLayer shapes;
|
||||||
|
|
||||||
|
protected int tick = 0;
|
||||||
|
|
||||||
|
protected long runtime = 0L;
|
||||||
|
|
||||||
|
protected double delta = 0.0;
|
||||||
|
|
||||||
|
protected double mouseX = 0.0, mouseY = 0.0, pmouseX = 0.0, pmouseY = 0.0;
|
||||||
|
|
||||||
|
protected int width = STD_WIDTH, height = STD_HEIGHT;
|
||||||
|
|
||||||
|
private Object mouseLock = new Object();
|
||||||
|
|
||||||
|
private Object keyboardLock = new Object();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Internal attributes for controlling the sketchmachine
|
||||||
|
* Interne Attribute zur Steuerung der Zeichenamschine.
|
||||||
|
*/
|
||||||
|
//
|
||||||
|
private JFrame frame;
|
||||||
|
|
||||||
|
private boolean running = false, isDrawing = false, isUpdating = false;
|
||||||
|
|
||||||
|
private int framesPerSecond;
|
||||||
|
|
||||||
|
private Thread mainThread;
|
||||||
|
|
||||||
|
private boolean quitAfterTeardown = false, initialized = false;
|
||||||
|
|
||||||
|
public Zeichenmaschine() {
|
||||||
|
this(APP_NAME + " " + APP_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Zeichenmaschine( String title ) {
|
||||||
|
this(STD_WIDTH, STD_HEIGHT, title);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Zeichenmaschine( int width, int height, String title ) {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch( Exception e ) {
|
||||||
|
System.err.println("Error setting the look and feel.");
|
||||||
|
}
|
||||||
|
|
||||||
|
GraphicsEnvironment environment =
|
||||||
|
GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||||
|
GraphicsDevice displayDevice = environment.getDefaultScreenDevice();
|
||||||
|
|
||||||
|
frame = new JFrame(displayDevice.getDefaultConfiguration());
|
||||||
|
frame.setTitle(title);
|
||||||
|
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||||
|
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
canvas = new Zeichenleinwand(width, height);
|
||||||
|
frame.add(canvas);
|
||||||
|
|
||||||
|
framesPerSecond = STD_FPS;
|
||||||
|
|
||||||
|
drawing = getDrawingLayer();
|
||||||
|
shapes = getShapesLayer();
|
||||||
|
|
||||||
|
settings();
|
||||||
|
|
||||||
|
canvas.addMouseListener(this);
|
||||||
|
canvas.addMouseMotionListener(this);
|
||||||
|
frame.addWindowListener(new WindowAdapter() {
|
||||||
|
@Override
|
||||||
|
public void windowClosing( WindowEvent e ) {
|
||||||
|
if( running ) {
|
||||||
|
running = false;
|
||||||
|
quitAfterTeardown = true;
|
||||||
|
} else {
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
frame.pack();
|
||||||
|
frame.setResizable(false);
|
||||||
|
frame.setLocationRelativeTo(null);
|
||||||
|
frame.setVisible(true);
|
||||||
|
|
||||||
|
canvas.allocateBuffer();
|
||||||
|
|
||||||
|
running = true;
|
||||||
|
mainThread = new Zeichenthread();
|
||||||
|
mainThread.start();
|
||||||
|
|
||||||
|
//frame.requestFocusInWindow();
|
||||||
|
canvas.requestFocus();
|
||||||
|
|
||||||
|
initialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final void createFrame( String title ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
if( !frame.isVisible() ) {
|
||||||
|
frame.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
if( frame.isVisible() ) {
|
||||||
|
frame.setVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void quit() {
|
||||||
|
quit(!IN_BLUEJ);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void quit( boolean exit ) {
|
||||||
|
frame.setVisible(false);
|
||||||
|
canvas.dispose();
|
||||||
|
frame.dispose();
|
||||||
|
|
||||||
|
if( exit ) {
|
||||||
|
System.exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setSize( int width, int height ) {
|
||||||
|
//frame.setSize(width, height);
|
||||||
|
|
||||||
|
if( canvas != null ) {
|
||||||
|
canvas.setSize(width, height);
|
||||||
|
}
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
frame.pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setTitle( String pTitel ) {
|
||||||
|
frame.setTitle(pTitel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final Zeichenleinwand getCanvas() {
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void addLayer( Layer layer ) {
|
||||||
|
canvas.addLayer(layer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public final DrawingLayer getDrawingLayer() {
|
||||||
|
DrawingLayer layer = canvas.getLayer(DrawingLayer.class);
|
||||||
|
if( layer == null ) {
|
||||||
|
layer = new DrawingLayer(getWidth(), getHeight());
|
||||||
|
canvas.addLayer(0, layer);
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ShapesLayer getShapesLayer() {
|
||||||
|
ShapesLayer layer = canvas.getLayer(ShapesLayer.class);
|
||||||
|
if( layer == null ) {
|
||||||
|
layer = new ShapesLayer(getWidth(), getHeight());
|
||||||
|
canvas.addLayer(layer);
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final int getFramesPerSecond() {
|
||||||
|
return framesPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final void setFramesPerSecond( int pFramesPerSecond ) {
|
||||||
|
framesPerSecond = pFramesPerSecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Methoden, die von Unterklassen überschrieben werden können / sollen.
|
||||||
|
*/
|
||||||
|
public void settings() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void draw() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void teardown() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update( double delta ) {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void delay( int ms ) {
|
||||||
|
if( ms <= 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
long timer = 0L;
|
||||||
|
if( isDrawing ) {
|
||||||
|
// Immediately show the current drawing before waiting
|
||||||
|
// Measure the render time and subtract from the waiting ms
|
||||||
|
timer = System.nanoTime();
|
||||||
|
canvas.render();
|
||||||
|
timer = System.nanoTime() - timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
int sub = (int) Math.ceil(timer / 1000000.0);
|
||||||
|
|
||||||
|
if( sub >= ms ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.sleep(ms - sub, (int) (timer % 1000000L));
|
||||||
|
} catch( InterruptedException ex ) {
|
||||||
|
// Nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mouse handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseClicked( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
mouseClicked();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseClicked() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mousePressed( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
mousePressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mousePressed() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseReleased( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
mouseReleased();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseReleased() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseEntered( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseExited( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseDragged( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
mouseDragged();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseDragged() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void mouseMoved( MouseEvent e ) {
|
||||||
|
saveMousePosition(e.getPoint());
|
||||||
|
mouseMoved();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseMoved() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveMousePosition( Point pLocation ) {
|
||||||
|
//pmouseX = mouseX;
|
||||||
|
//pmouseY = mouseY;
|
||||||
|
/*synchronized(mouseLock) {
|
||||||
|
mouseX = pLocation.getX()-this.getRootPane().getX();
|
||||||
|
mouseY = pLocation.getY()-this.getRootPane().getY();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveMousePosition() {
|
||||||
|
pmouseX = mouseX;
|
||||||
|
pmouseY = mouseY;
|
||||||
|
|
||||||
|
java.awt.Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
|
||||||
|
java.awt.Point compLoc = canvas.getLocationOnScreen();
|
||||||
|
mouseX = mouseLoc.x - compLoc.x;
|
||||||
|
mouseY = mouseLoc.y - compLoc.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyTyped( KeyEvent e ) {
|
||||||
|
keyTyped();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Keyboard handling
|
||||||
|
*/
|
||||||
|
|
||||||
|
public void keyTyped() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyPressed( KeyEvent e ) {
|
||||||
|
keyPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyPressed() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void keyReleased( KeyEvent e ) {
|
||||||
|
keyReleased();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void keyReleased() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Zeichenthread extends Thread {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void run() {
|
||||||
|
// Wait for full initialization before start
|
||||||
|
while( !initialized ) {
|
||||||
|
delay(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// start of thread in ms
|
||||||
|
final long start = System.currentTimeMillis();
|
||||||
|
// current time in ns
|
||||||
|
long beforeTime = System.nanoTime();
|
||||||
|
// store for deltas
|
||||||
|
long overslept = 0L;
|
||||||
|
// internal counters for tick and runtime
|
||||||
|
int _tick = 0;
|
||||||
|
long _runtime = 0;
|
||||||
|
// public counters for access by subclasses
|
||||||
|
tick = 0;
|
||||||
|
runtime = 0;
|
||||||
|
|
||||||
|
// call setup of subclass
|
||||||
|
setup();
|
||||||
|
|
||||||
|
while( running ) {
|
||||||
|
// delta in seconds
|
||||||
|
delta = (System.nanoTime() - beforeTime) / 1000000000.0;
|
||||||
|
beforeTime = System.nanoTime();
|
||||||
|
|
||||||
|
saveMousePosition();
|
||||||
|
|
||||||
|
handleUpdate(delta);
|
||||||
|
handleDraw();
|
||||||
|
|
||||||
|
if( canvas != null ) {
|
||||||
|
canvas.render();
|
||||||
|
//canvas.invalidate();
|
||||||
|
//frame.repaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
// delta time in ns
|
||||||
|
long afterTime = System.nanoTime();
|
||||||
|
long dt = afterTime - beforeTime;
|
||||||
|
long sleep = ((1000000000L / framesPerSecond) - dt) - overslept;
|
||||||
|
|
||||||
|
|
||||||
|
if( sleep > 0 ) {
|
||||||
|
try {
|
||||||
|
Thread.sleep(sleep / 1000000L, (int) (sleep % 1000000L));
|
||||||
|
} catch( InterruptedException e ) {
|
||||||
|
// Interrupt not relevant
|
||||||
|
}
|
||||||
|
|
||||||
|
overslept = (System.nanoTime() - afterTime) - sleep;
|
||||||
|
} else {
|
||||||
|
overslept = 0L;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
_tick += 1;
|
||||||
|
_runtime = System.currentTimeMillis() - start;
|
||||||
|
tick = _tick;
|
||||||
|
runtime = _runtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
teardown();
|
||||||
|
if( quitAfterTeardown ) {
|
||||||
|
quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleUpdate( double delta ) {
|
||||||
|
if( isUpdating ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isUpdating = true;
|
||||||
|
update(delta);
|
||||||
|
isUpdating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleDraw() {
|
||||||
|
if( isDrawing ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isDrawing = true;
|
||||||
|
draw();
|
||||||
|
isDrawing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
import java.awt.geom.RoundRectangle2D;
|
|
||||||
|
|
||||||
public class AbgerundetesRechteck extends Rechteck {
|
|
||||||
|
|
||||||
protected double rundung = 1.0;
|
|
||||||
|
|
||||||
public AbgerundetesRechteck( double pX, double pY, double pBreite, double pHoehe, double pRundung ) {
|
|
||||||
super(pX, pY, pBreite, pHoehe);
|
|
||||||
rundung = pRundung;
|
|
||||||
}
|
|
||||||
|
|
||||||
public AbgerundetesRechteck( Rechteck pRechteck ) {
|
|
||||||
super(
|
|
||||||
pRechteck.x, pRechteck.y,
|
|
||||||
pRechteck.breite, pRechteck.hoehe);
|
|
||||||
kopiere(pRechteck);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof AbgerundetesRechteck ) {
|
|
||||||
AbgerundetesRechteck rechteck = (AbgerundetesRechteck) pForm;
|
|
||||||
rundung = rechteck.rundung;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new RoundRectangle2D.Double(
|
|
||||||
0, 0, breite, hoehe, rundung, rundung
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
AbgerundetesRechteck rechteck = (AbgerundetesRechteck) o;
|
|
||||||
return super.equals(o) &&
|
|
||||||
Double.compare(rechteck.rundung, rundung) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + "[" +
|
|
||||||
"x=" + x +
|
|
||||||
",y=" + y +
|
|
||||||
",breite=" + breite +
|
|
||||||
",hoehe=" + hoehe +
|
|
||||||
",rundung=" + rundung +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
111
src/schule/ngb/zm/formen/Arc.java
Normal file
111
src/schule/ngb/zm/formen/Arc.java
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Arc2D;
|
||||||
|
|
||||||
|
public class Arc extends Shape {
|
||||||
|
|
||||||
|
protected double width;
|
||||||
|
|
||||||
|
protected double height;
|
||||||
|
|
||||||
|
protected double angle;
|
||||||
|
|
||||||
|
protected double startingangle;
|
||||||
|
|
||||||
|
protected Options.PathType type = OPEN;
|
||||||
|
|
||||||
|
public Arc( double x, double y, double radius, double angle ) {
|
||||||
|
this(x, y, radius, radius, angle, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Arc( double x, double y, double radius, double angle, double startingangle ) {
|
||||||
|
this(x, y, radius, radius, angle, startingangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Arc( double x, double y, double width, double height, double angle, double startingangle ) {
|
||||||
|
super(x, y);
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.angle = angle;
|
||||||
|
this.startingangle = startingangle;
|
||||||
|
setAnchor(CENTER);
|
||||||
|
|
||||||
|
noFill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Arc( Arc arc ) {
|
||||||
|
this(arc.x, arc.y, arc.width, arc.height, arc.angle, arc.startingangle);
|
||||||
|
copyFrom(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth( double width ) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight( double height ) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAngle() {
|
||||||
|
return angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngle( double angle ) {
|
||||||
|
this.angle = angle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getStartingangle() {
|
||||||
|
return startingangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartingangle( double startingangle ) {
|
||||||
|
this.startingangle = startingangle;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options.PathType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType( Options.PathType type ) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Arc(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Arc ) {
|
||||||
|
Arc arc = (Arc) shape;
|
||||||
|
width = arc.width;
|
||||||
|
height = arc.height;
|
||||||
|
angle = arc.angle;
|
||||||
|
startingangle = arc.startingangle;
|
||||||
|
type = arc.type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(width, height, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Arc2D.Double(0, 0, width, height, startingangle, angle, type.awt_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
178
src/schule/ngb/zm/formen/Arrow.java
Normal file
178
src/schule/ngb/zm/formen/Arrow.java
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
import schule.ngb.zm.Vector;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
|
||||||
|
public class Arrow extends Line {
|
||||||
|
|
||||||
|
// Spitzenarten
|
||||||
|
public static final int OPEN = 101;
|
||||||
|
|
||||||
|
public static final int CLOSED = 102;
|
||||||
|
|
||||||
|
private static final double BASE_HEADSIZE = 5.0;
|
||||||
|
|
||||||
|
protected Options.ArrowHead arrowhead = LINES;
|
||||||
|
|
||||||
|
protected double headsize = 1.0;
|
||||||
|
|
||||||
|
public Arrow( double x1, double y1, double x2, double y2 ) {
|
||||||
|
super(x1, y1, x2, y2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen Pfeil, der den übergebenen Vektor darstellt.
|
||||||
|
*
|
||||||
|
* @param vector
|
||||||
|
*/
|
||||||
|
public Arrow( Vector vector ) {
|
||||||
|
this(0, 0, vector.x, vector.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen Pfeil, der den Differenzvektor zwischen den übergebenen
|
||||||
|
* Vektoren darstellt.
|
||||||
|
*
|
||||||
|
* @param vector1
|
||||||
|
* @param vector2
|
||||||
|
*/
|
||||||
|
public Arrow( Vector vector1, Vector vector2 ) {
|
||||||
|
this(vector1.x, vector1.y, vector2.x, vector2.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen Pfeil, der den übergebenen Vektor um die angegeben
|
||||||
|
* Koordinaten verschoben darstellt.
|
||||||
|
*
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
* @param pVektor
|
||||||
|
*/
|
||||||
|
public Arrow( double x, double y, Vector pVektor ) {
|
||||||
|
this(x, y, x + pVektor.x, y + pVektor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt einen Pfeil als Kopie einer vorgegebenen Linie.
|
||||||
|
*
|
||||||
|
* @param pLine
|
||||||
|
*/
|
||||||
|
public Arrow( Line pLine ) {
|
||||||
|
this(pLine.x, pLine.y, pLine.x2, pLine.y2);
|
||||||
|
this.copyFrom(pLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeadsize() {
|
||||||
|
return headsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeadsize( double headsize ) {
|
||||||
|
this.headsize = headsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options.ArrowHead getArrowhead() {
|
||||||
|
return arrowhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setArrowhead( Options.ArrowHead arrowhead ) {
|
||||||
|
this.arrowhead = arrowhead;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kopiert die Werte des angegebenen Vektors.
|
||||||
|
*
|
||||||
|
* @param vector
|
||||||
|
*/
|
||||||
|
public void copyFrom( Vector vector ) {
|
||||||
|
if( vector != null ) {
|
||||||
|
x2 = x + vector.x;
|
||||||
|
y2 = y + vector.y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Arrow ) {
|
||||||
|
Arrow pArrow = (Arrow) shape;
|
||||||
|
headsize = pArrow.headsize;
|
||||||
|
arrowhead = pArrow.arrowhead;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Arrow copy() {
|
||||||
|
return new Arrow(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
/*Path2D.Double gruppe = new Path2D.Double();
|
||||||
|
gruppe.append(super.getShape(), false);
|
||||||
|
gruppe.append(getPfeilspitze(), false);
|
||||||
|
|
||||||
|
return gruppe;*/
|
||||||
|
return super.getShape();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected java.awt.Shape getHeadShape() {
|
||||||
|
AffineTransform af;
|
||||||
|
switch( arrowhead ) {
|
||||||
|
case LINES:
|
||||||
|
double len = BASE_HEADSIZE * headsize;
|
||||||
|
Path2D.Double sOPEN = new Path2D.Double();
|
||||||
|
sOPEN.moveTo(-len, -len);
|
||||||
|
sOPEN.lineTo(0, 0);
|
||||||
|
sOPEN.lineTo(-len, len);
|
||||||
|
|
||||||
|
af = new AffineTransform();
|
||||||
|
af.translate(x2-x, y2-y);
|
||||||
|
af.rotate(Math.atan2(y2 - y, x2 - x));
|
||||||
|
return af.createTransformedShape(sOPEN);
|
||||||
|
case FILLED:
|
||||||
|
default:
|
||||||
|
int ix = (int) x2, iy = (int) y2, pg = (int) (BASE_HEADSIZE * headsize);
|
||||||
|
java.awt.Polygon sCLOSED = new java.awt.Polygon(
|
||||||
|
new int[]{0, -pg, -pg},
|
||||||
|
new int[]{0, -pg, pg},
|
||||||
|
3
|
||||||
|
);
|
||||||
|
|
||||||
|
af = new AffineTransform();
|
||||||
|
af.translate(x2-x, y2-y);
|
||||||
|
af.rotate(Math.atan2(y2 - y, x2 - x));
|
||||||
|
return af.createTransformedShape(sCLOSED);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D graphics, AffineTransform at ) {
|
||||||
|
if( !visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
super.draw(graphics, at);
|
||||||
|
|
||||||
|
java.awt.Shape head = getHeadShape();
|
||||||
|
if( at != null ) {
|
||||||
|
head = at.createTransformedShape(head);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color currentColor = graphics.getColor();
|
||||||
|
if( strokeColor != null && strokeColor.getAlpha() > 0.0 ) {
|
||||||
|
graphics.setColor(strokeColor.getColor());
|
||||||
|
graphics.setStroke(new BasicStroke((float) strokeWeight));
|
||||||
|
if( arrowhead == FILLED ) {
|
||||||
|
graphics.fill(head);
|
||||||
|
} else {
|
||||||
|
graphics.draw(head);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
graphics.setColor(currentColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,147 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import javax.imageio.ImageIO;
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
import java.awt.image.BufferedImage;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
public class Bild extends Form {
|
|
||||||
|
|
||||||
private double breite;
|
|
||||||
|
|
||||||
private double hoehe;
|
|
||||||
|
|
||||||
private BufferedImage bild;
|
|
||||||
|
|
||||||
public Bild( String pQuelle ) {
|
|
||||||
this(0, 0, pQuelle);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bild( double pX, double pY, String pQuelle ) {
|
|
||||||
super(pX, pY);
|
|
||||||
|
|
||||||
if( pQuelle == null || pQuelle.length() == 0 )
|
|
||||||
throw new IllegalArgumentException("Bildquelle darf nicht null oder leer sein.");
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Bilddatei aus dem Arbeitsverzeichnis laden
|
|
||||||
File file = new File(pQuelle);
|
|
||||||
if( file.isFile() ) {
|
|
||||||
bild = ImageIO.read(file);
|
|
||||||
} else {
|
|
||||||
// relativ zur .class-Datei
|
|
||||||
URL url = getClass().getResource(pQuelle);
|
|
||||||
|
|
||||||
// relativ zum ClassLoader
|
|
||||||
if( url == null ) {
|
|
||||||
url = getClass().getClassLoader().getResource(pQuelle);
|
|
||||||
}
|
|
||||||
|
|
||||||
// aWebadresse oder JAR-Datei
|
|
||||||
if( url == null ) {
|
|
||||||
url = new URL(pQuelle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bild = ImageIO.read(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( bild == null ) {
|
|
||||||
throw new IllegalArgumentException("Bild konnte nicht aus " + pQuelle + " geladen werden!");
|
|
||||||
}
|
|
||||||
|
|
||||||
breite = bild.getWidth(null);
|
|
||||||
hoehe = bild.getHeight(null);
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
} catch( IOException ioe ) {
|
|
||||||
throw new IllegalArgumentException("Bild konnte nicht aus " + pQuelle + " geladen werden!", ioe);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bild( Bild pBild ) {
|
|
||||||
super(pBild.getX(), pBild.getY());
|
|
||||||
kopiere(pBild);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Bild(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Bild ) {
|
|
||||||
Bild pBild = (Bild)pForm;
|
|
||||||
bild = new BufferedImage(pBild.bild.getWidth(), pBild.bild.getHeight(), pBild.bild.getType());
|
|
||||||
Graphics2D g = bild.createGraphics();
|
|
||||||
g.drawImage(pBild.bild, 0, 0, null);
|
|
||||||
g.dispose();
|
|
||||||
|
|
||||||
breite = bild.getWidth(null);
|
|
||||||
hoehe = bild.getHeight(null);
|
|
||||||
setAnkerpunkt(pForm.getAnkerpunkt());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getBreite() {
|
|
||||||
return breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBreite( double pBreite ) {
|
|
||||||
skalieren(pBreite / breite);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHoehe() {
|
|
||||||
return hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHoehe( double pHoehe ) {
|
|
||||||
skalieren(pHoehe / hoehe);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(breite, hoehe, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
breite *= pFaktor;
|
|
||||||
hoehe *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new Rectangle2D.Double(0, 0, breite, hoehe);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
@Override
|
|
||||||
public AffineTransform getVerzerrung() {
|
|
||||||
AffineTransform verzerrung = new AffineTransform();
|
|
||||||
verzerrung.translate(x, y);
|
|
||||||
verzerrung.scale(skalierung, skalierung);
|
|
||||||
verzerrung.rotate(Math.toRadians(drehwinkel));
|
|
||||||
verzerrung.translate(-anker.x, -anker.y);
|
|
||||||
return verzerrung;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
|
||||||
if( !sichtbar ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AffineTransform current = graphics.getTransform();
|
|
||||||
graphics.transform(getVerzerrung());
|
|
||||||
graphics.drawImage(bild, 0, 0, (int) breite, (int) hoehe, null);
|
|
||||||
graphics.setTransform(current);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,110 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Arc2D;
|
|
||||||
|
|
||||||
public class Bogen extends Form {
|
|
||||||
|
|
||||||
protected double breite;
|
|
||||||
|
|
||||||
protected double hoehe;
|
|
||||||
|
|
||||||
protected double winkel;
|
|
||||||
|
|
||||||
protected double startwinkel;
|
|
||||||
|
|
||||||
protected int typ = OFFEN;
|
|
||||||
|
|
||||||
public Bogen( double pX, double pY, double pRadius, double pWinkel ) {
|
|
||||||
this(pX, pY, pRadius, pRadius, pWinkel, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bogen( double pX, double pY, double pRadius, double pWinkel, double pStartwinkel ) {
|
|
||||||
this(pX, pY, pRadius, pRadius, pWinkel, pStartwinkel);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bogen( double pX, double pY, double pBreite, double pHoehe, double pWinkel, double pStartwinkel ) {
|
|
||||||
super(pX, pY);
|
|
||||||
breite = pBreite;
|
|
||||||
hoehe = pHoehe;
|
|
||||||
winkel = pWinkel;
|
|
||||||
startwinkel = pStartwinkel;
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
|
|
||||||
keineFuellung();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Bogen( Bogen pBogen ) {
|
|
||||||
this(pBogen.x, pBogen.y, pBogen.breite, pBogen.hoehe, pBogen.winkel, pBogen.startwinkel);
|
|
||||||
kopiere(pBogen);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getBreite() {
|
|
||||||
return breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBreite( double pBreite ) {
|
|
||||||
this.breite = pBreite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHoehe() {
|
|
||||||
return hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHoehe( double pHoehe ) {
|
|
||||||
this.hoehe = pHoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getWinkel() {
|
|
||||||
return winkel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setWinkel( double pWinkel ) {
|
|
||||||
this.winkel = pWinkel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getStartwinkel() {
|
|
||||||
return startwinkel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStartwinkel( double pStartwinkel ) {
|
|
||||||
this.startwinkel = pStartwinkel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getTyp() {
|
|
||||||
return typ;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTyp( int pTyp ) {
|
|
||||||
this.typ = pTyp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Bogen(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere(Form pForm) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Bogen ) {
|
|
||||||
Bogen b = (Bogen) pForm;
|
|
||||||
breite = b.breite;
|
|
||||||
hoehe = b.hoehe;
|
|
||||||
winkel = b.winkel;
|
|
||||||
startwinkel = b.startwinkel;
|
|
||||||
typ = b.typ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(breite, hoehe, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new Arc2D.Double(0, 0, breite, hoehe, startwinkel, winkel, typ);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
76
src/schule/ngb/zm/formen/Circle.java
Normal file
76
src/schule/ngb/zm/formen/Circle.java
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
|
||||||
|
public class Circle extends Shape {
|
||||||
|
|
||||||
|
protected double radius;
|
||||||
|
|
||||||
|
public Circle( double x, double y, double radius ) {
|
||||||
|
super(x, y);
|
||||||
|
this.radius = radius;
|
||||||
|
setAnchor(CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Circle( Circle circle ) {
|
||||||
|
this(circle.x, circle.y, circle.radius);
|
||||||
|
copyFrom(circle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRadius() {
|
||||||
|
return radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRadius( double radius ) {
|
||||||
|
this.radius = radius;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
radius *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Circle ) {
|
||||||
|
radius = ((Circle) shape).radius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Circle copy() {
|
||||||
|
return new Circle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Ellipse2D.Double(0, 0, radius + radius, radius + radius);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(radius + radius, radius + radius, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Circle pCircle = (Circle) o;
|
||||||
|
return super.equals(o) && Double.compare(pCircle.radius, radius) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + "[" +
|
||||||
|
"x=" + x +
|
||||||
|
",y=" + y +
|
||||||
|
",radius=" + radius +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
182
src/schule/ngb/zm/formen/Curve.java
Normal file
182
src/schule/ngb/zm/formen/Curve.java
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.CubicCurve2D;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.awt.geom.QuadCurve2D;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Curve extends Shape {
|
||||||
|
|
||||||
|
protected double[] coordinates;
|
||||||
|
|
||||||
|
public Curve( double x, double y, double cx, double cy, double x2, double y2 ) {
|
||||||
|
super(x, y);
|
||||||
|
|
||||||
|
coordinates = new double[]{
|
||||||
|
cx, cy, x2, y2
|
||||||
|
};
|
||||||
|
|
||||||
|
noFill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Curve( double x, double y, double cx1, double cy1, double cx2, double cy2, double x2, double y2 ) {
|
||||||
|
super(x, y);
|
||||||
|
|
||||||
|
coordinates = new double[]{
|
||||||
|
cx1, cy1, cx2, cy2, x2, y2
|
||||||
|
};
|
||||||
|
|
||||||
|
noFill();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Curve( Curve curve ) {
|
||||||
|
super(curve.x, curve.y);
|
||||||
|
coordinates = Arrays.copyOf(curve.coordinates, curve.coordinates.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getStart() {
|
||||||
|
return new Point2D.Double(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStart( double x, double y ) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getEnd() {
|
||||||
|
return new Point2D.Double(
|
||||||
|
coordinates[coordinates.length - 2],
|
||||||
|
coordinates[coordinates.length - 1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnd( double x, double y ) {
|
||||||
|
coordinates[coordinates.length - 2] = x;
|
||||||
|
coordinates[coordinates.length - 1] = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getControl1() {
|
||||||
|
return new Point2D.Double(
|
||||||
|
coordinates[0],
|
||||||
|
coordinates[1]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControl1( double x, double y ) {
|
||||||
|
coordinates[0] = x;
|
||||||
|
coordinates[1] = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D getControl2() {
|
||||||
|
return new Point2D.Double(
|
||||||
|
coordinates[coordinates.length - 4],
|
||||||
|
coordinates[coordinates.length - 3]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setControl2( double x, double y ) {
|
||||||
|
coordinates[coordinates.length - 4] = x;
|
||||||
|
coordinates[coordinates.length - 3] = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoints( double x, double y, double cx, double cy, double x2, double y2 ) {
|
||||||
|
setStart(x, y);
|
||||||
|
coordinates = coordinates = new double[]{
|
||||||
|
cx, cy, x2, y2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoints( double x, double y, double cx1, double cy1, double cx2, double cy2, double x2, double y2 ) {
|
||||||
|
setStart(x, y);
|
||||||
|
coordinates = new double[]{
|
||||||
|
cx1, cy1, cx2, cy2, x2, y2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCubic() {
|
||||||
|
return coordinates.length == 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isQuad() {
|
||||||
|
return coordinates.length == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Curve(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Curve ) {
|
||||||
|
Curve k = (Curve) shape;
|
||||||
|
coordinates = Arrays.copyOf(k.coordinates, k.coordinates.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
if( isCubic() ) {
|
||||||
|
return new CubicCurve2D.Double(
|
||||||
|
0, 0,
|
||||||
|
coordinates[0] - x, coordinates[1] - y,
|
||||||
|
coordinates[2] - x, coordinates[3] - y,
|
||||||
|
coordinates[4] - x, coordinates[5] - y
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return new QuadCurve2D.Double(
|
||||||
|
0, 0,
|
||||||
|
coordinates[0] - x, coordinates[1] - y,
|
||||||
|
coordinates[2] - x, coordinates[3] - y
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
coordinates[coordinates.length - 4] *= factor;
|
||||||
|
coordinates[coordinates.length - 3] *= factor;
|
||||||
|
coordinates[coordinates.length - 2] *= factor;
|
||||||
|
coordinates[coordinates.length - 1] *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void move( double dx, double dy ) {
|
||||||
|
super.move(dx, dy);
|
||||||
|
for( int i = 0; i < coordinates.length; i += 2 ) {
|
||||||
|
coordinates[i] = coordinates[i] + dx;
|
||||||
|
coordinates[i + 1] = coordinates[i + 1] + dy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveTo( double x, double y ) {
|
||||||
|
double dx = x - x, dy = y - y;
|
||||||
|
move(dx, dy);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Curve pCurve = (Curve) o;
|
||||||
|
return super.equals(o) &&
|
||||||
|
getStart().equals(pCurve.getStart()) &&
|
||||||
|
getControl1().equals(pCurve.getControl1()) &&
|
||||||
|
getControl2().equals(pCurve.getControl2()) &&
|
||||||
|
getEnd().equals(pCurve.getEnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + "[" +
|
||||||
|
"x=" + x +
|
||||||
|
",y=" + y +
|
||||||
|
"x2=" + coordinates[coordinates.length - 2] +
|
||||||
|
",y2=" + coordinates[coordinates.length - 1] +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
53
src/schule/ngb/zm/formen/CustomShape.java
Normal file
53
src/schule/ngb/zm/formen/CustomShape.java
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
|
||||||
|
public class CustomShape extends Shape {
|
||||||
|
|
||||||
|
protected Path2D.Double path;
|
||||||
|
|
||||||
|
public CustomShape( double x, double y ) {
|
||||||
|
super(x, y);
|
||||||
|
path = new Path2D.Double();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CustomShape( CustomShape custom ) {
|
||||||
|
super(custom.x, custom.y);
|
||||||
|
path = custom.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lineTo( double x, double y ) {
|
||||||
|
path.lineTo(x - x, y - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void arcTo( double x1, double y1, double x2, double y2 ) {
|
||||||
|
path.quadTo(x1 - x, y1 - y, x2 - x, y2 - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void curveTo( double x1, double y1, double x2, double y2, double x3, double y3 ) {
|
||||||
|
path.curveTo(x1 - x, y1 - y, x2 - x, y2 - y, x3 - x, y3 - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
path.lineTo(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new CustomShape(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof CustomShape ) {
|
||||||
|
path = new Path2D.Double(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Path2D.Double(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
|
|
||||||
public class Drache extends Form {
|
|
||||||
|
|
||||||
private double breite;
|
|
||||||
|
|
||||||
private double hoehe;
|
|
||||||
|
|
||||||
private double verhaeltnis;
|
|
||||||
|
|
||||||
public Drache( double pX, double pY, double pBreite, double pHoehe ) {
|
|
||||||
this(pX, pY, pBreite, pHoehe, 0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drache( double pX, double pY, double pBreite, double pHoehe, double pVerhaeltnis ) {
|
|
||||||
super(pX, pY);
|
|
||||||
breite = pBreite;
|
|
||||||
hoehe = pHoehe;
|
|
||||||
verhaeltnis = pVerhaeltnis;
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Drache( Drache pDrache ) {
|
|
||||||
this(pDrache.x, pDrache.y, pDrache.breite, pDrache.hoehe, pDrache.verhaeltnis);
|
|
||||||
kopiere(pDrache);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getBreite() {
|
|
||||||
return breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBreite( double breite ) {
|
|
||||||
this.breite = breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHoehe() {
|
|
||||||
return hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHoehe( double hoehe ) {
|
|
||||||
this.hoehe = hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getVerhaeltnis() {
|
|
||||||
return verhaeltnis;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setVerhaeltnis( double pVerhaeltnis ) {
|
|
||||||
this.verhaeltnis = pVerhaeltnis;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Drache ) {
|
|
||||||
Drache d = (Drache) pForm;
|
|
||||||
breite = d.breite;
|
|
||||||
hoehe = d.hoehe;
|
|
||||||
verhaeltnis = d.verhaeltnis;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Drache kopie() {
|
|
||||||
return new Drache(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
breite *= pFaktor;
|
|
||||||
hoehe *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(breite, hoehe, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
double bHalb = breite * .5, hVerh = verhaeltnis*hoehe;
|
|
||||||
Path2D shape = new Path2D.Double();
|
|
||||||
shape.moveTo(bHalb, 0);
|
|
||||||
shape.lineTo(breite, hVerh);
|
|
||||||
shape.lineTo(bHalb, hoehe);
|
|
||||||
shape.lineTo(0, hVerh);
|
|
||||||
shape.closePath();
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Drache d = (Drache) o;
|
|
||||||
return super.equals(o) &&
|
|
||||||
Double.compare(d.breite, breite) == 0 &&
|
|
||||||
Double.compare(d.hoehe, hoehe) == 0 &&
|
|
||||||
Double.compare(d.verhaeltnis, verhaeltnis) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + '[' +
|
|
||||||
"breite=" + breite +
|
|
||||||
",hoehe=" + hoehe +
|
|
||||||
",verhaeltnis=" + verhaeltnis +
|
|
||||||
",x=" + x +
|
|
||||||
",y=" + y +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Dreieck extends Vieleck {
|
|
||||||
|
|
||||||
public Dreieck( double pX, double pY, Point2D... pEcken ) {
|
|
||||||
super(pX, pY, Arrays.copyOf(pEcken, 3));
|
|
||||||
if( pEcken.length < 3 ) {
|
|
||||||
throw new IllegalArgumentException("Ein Dreieck muss genau drei Eckpunkte besitzen.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dreieck( Point2D... pEcken ) {
|
|
||||||
super(Arrays.copyOf(pEcken, 3));
|
|
||||||
if( pEcken.length < 3 ) {
|
|
||||||
throw new IllegalArgumentException("Ein Dreieck muss genau drei Eckpunkte besitzen.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Dreieck( Dreieck pDreieck ) {
|
|
||||||
super(pDreieck.x, pDreieck.y);
|
|
||||||
kopiere(pDreieck);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Dreieck(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +1,73 @@
|
|||||||
package schule.ngb.zm.formen;
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
import java.awt.*;
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
import java.awt.geom.Ellipse2D;
|
import java.awt.geom.Ellipse2D;
|
||||||
|
|
||||||
public class Ellipse extends Form {
|
public class Ellipse extends Shape {
|
||||||
|
|
||||||
private double breite;
|
protected double width;
|
||||||
|
|
||||||
private double hoehe;
|
protected double height;
|
||||||
|
|
||||||
public Ellipse( double pX, double pY, double pBreite, double pHoehe ) {
|
public Ellipse( double x, double y, double width, double height ) {
|
||||||
super(pX, pY);
|
super(x, y);
|
||||||
breite = pBreite;
|
this.width = width;
|
||||||
hoehe = pHoehe;
|
this.height = height;
|
||||||
setAnkerpunkt(ZENTRUM);
|
setAnchor(CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Ellipse( Ellipse pEllipse ) {
|
public Ellipse( Ellipse ellipse ) {
|
||||||
this(pEllipse.x, pEllipse.y, pEllipse.breite, pEllipse.hoehe);
|
this(ellipse.x, ellipse.y, ellipse.width, ellipse.height);
|
||||||
kopiere(pEllipse);
|
copyFrom(ellipse);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getBreite() {
|
public double getWidth() {
|
||||||
return breite;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBreite( double breite ) {
|
public void setWidth( double width ) {
|
||||||
this.breite = breite;
|
this.width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getHoehe() {
|
public double getHeight() {
|
||||||
return hoehe;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHoehe( double hoehe ) {
|
public void setHeight( double height ) {
|
||||||
this.hoehe = hoehe;
|
this.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void kopiere( Form pForm ) {
|
public void copyFrom( Shape shape ) {
|
||||||
super.kopiere(pForm);
|
super.copyFrom(shape);
|
||||||
if( pForm instanceof Ellipse ) {
|
if( shape instanceof Ellipse ) {
|
||||||
Ellipse e = (Ellipse) pForm;
|
Ellipse e = (Ellipse) shape;
|
||||||
breite = e.breite;
|
this.width = e.width;
|
||||||
hoehe = e.hoehe;
|
this.height = e.height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Ellipse kopie() {
|
public Ellipse copy() {
|
||||||
return new Ellipse(this);
|
return new Ellipse(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skalieren( double pFaktor ) {
|
public void scale( double factor ) {
|
||||||
super.skalieren(pFaktor);
|
super.scale(factor);
|
||||||
breite *= pFaktor;
|
width *= factor;
|
||||||
hoehe *= pFaktor;
|
height *= factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
ankerBerechnen(breite, hoehe, pAnker);
|
calculateAnchor(width, height, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape getShape() {
|
public java.awt.Shape getShape() {
|
||||||
Shape shape = new Ellipse2D.Double(0, 0, breite, hoehe);
|
return new Ellipse2D.Double(0, 0, width, height);
|
||||||
return shape;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -76,15 +76,15 @@ public class Ellipse extends Form {
|
|||||||
if( o == null || getClass() != o.getClass() ) return false;
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
Ellipse ellipse = (Ellipse) o;
|
Ellipse ellipse = (Ellipse) o;
|
||||||
return super.equals(o) &&
|
return super.equals(o) &&
|
||||||
Double.compare(ellipse.breite, breite) == 0 &&
|
Double.compare(ellipse.width, width) == 0 &&
|
||||||
Double.compare(ellipse.hoehe, hoehe) == 0;
|
Double.compare(ellipse.height, height) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getCanonicalName() + '[' +
|
return getClass().getCanonicalName() + '[' +
|
||||||
"breite=" + breite +
|
"width=" + width +
|
||||||
",hoehe=" + hoehe +
|
",height=" + height +
|
||||||
",x=" + x +
|
",x=" + x +
|
||||||
",y=" + y +
|
",y=" + y +
|
||||||
']';
|
']';
|
||||||
|
|||||||
41
src/schule/ngb/zm/formen/FilledShape.java
Normal file
41
src/schule/ngb/zm/formen/FilledShape.java
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
|
||||||
|
public abstract class FilledShape extends StrokedShape {
|
||||||
|
|
||||||
|
protected Color fillColor = STD_FILLCOLOR;
|
||||||
|
|
||||||
|
public Color getFillColor() {
|
||||||
|
return fillColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( Color color ) {
|
||||||
|
fillColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int gray ) {
|
||||||
|
setFillColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noFill() {
|
||||||
|
fillColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int gray, int alpha ) {
|
||||||
|
setFillColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int red, int green, int blue ) {
|
||||||
|
setFillColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFillColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setFillColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetFill() {
|
||||||
|
setFillColor(STD_FILLCOLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
public abstract class Form extends Fuellform {
|
|
||||||
|
|
||||||
|
|
||||||
protected double x;
|
|
||||||
|
|
||||||
protected double y;
|
|
||||||
|
|
||||||
protected double drehwinkel = 0.0;
|
|
||||||
|
|
||||||
protected double skalierung = 1.0;
|
|
||||||
|
|
||||||
protected boolean sichtbar = true;
|
|
||||||
|
|
||||||
protected Point2D.Double anker = new Point2D.Double();
|
|
||||||
|
|
||||||
FormGruppe gruppe = null;
|
|
||||||
|
|
||||||
public Form( double pX, double pY ) {
|
|
||||||
x = pX;
|
|
||||||
y = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Form() {
|
|
||||||
this(0.0, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getX() {
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setX( double x ) {
|
|
||||||
this.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getY() {
|
|
||||||
return y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY( double y ) {
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getDrehwinkel() {
|
|
||||||
return drehwinkel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getSkalierung() {
|
|
||||||
return skalierung;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean istSichtbar() {
|
|
||||||
return sichtbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verstecken() {
|
|
||||||
sichtbar = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void zeigen() {
|
|
||||||
sichtbar = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void umschalten() {
|
|
||||||
sichtbar = !sichtbar;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D.Double getAnkerpunkt() {
|
|
||||||
return new Point2D.Double(anker.x, anker.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
Shape shape = getShape();
|
|
||||||
if( shape != null ) {
|
|
||||||
Rectangle2D bounds = shape.getBounds2D();
|
|
||||||
ankerBerechnen(bounds.getWidth(), bounds.getHeight(), pAnker);
|
|
||||||
} else {
|
|
||||||
anker.x = 0;
|
|
||||||
anker.y = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setAnkerpunkt( Point2D.Double pAnker ) {
|
|
||||||
anker.x = pAnker.x;
|
|
||||||
anker.y = pAnker.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void ankerBerechnen( double pBreite, double pHoehe, byte pAnker ) {
|
|
||||||
double bHalb = pBreite * .5, hHalb = pHoehe * .5;
|
|
||||||
// pAnker == CENTER
|
|
||||||
anker.x = bHalb;
|
|
||||||
anker.y = hHalb;
|
|
||||||
if( (pAnker & NORDEN) == NORDEN ) {
|
|
||||||
anker.y -= hHalb;
|
|
||||||
}
|
|
||||||
if( (pAnker & SUEDEN) == SUEDEN ) {
|
|
||||||
anker.y += hHalb;
|
|
||||||
}
|
|
||||||
if( (pAnker & WESTEN) == WESTEN ) {
|
|
||||||
anker.x -= bHalb;
|
|
||||||
}
|
|
||||||
if( (pAnker & OSTEN) == OSTEN ) {
|
|
||||||
anker.x += bHalb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
verschiebeNach(pForm);
|
|
||||||
setFuellfarbe(pForm.getFuellfarbe());
|
|
||||||
setKonturFarbe(pForm.getKonturFarbe());
|
|
||||||
setKonturDicke(pForm.getKonturDicke());
|
|
||||||
setKonturArt(pForm.getKonturArt());
|
|
||||||
sichtbar = pForm.istSichtbar();
|
|
||||||
drehwinkel = pForm.drehwinkel;
|
|
||||||
skalieren(pForm.skalierung);
|
|
||||||
setAnkerpunkt(pForm.getAnkerpunkt());
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Form kopie();
|
|
||||||
|
|
||||||
public Rechteck getBegrenzung() {
|
|
||||||
return new Rechteck(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verschieben( double dx, double dy ) {
|
|
||||||
x += dx;
|
|
||||||
y += dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verschiebeNach( double pX, double pY ) {
|
|
||||||
x = pX;
|
|
||||||
y = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void verschiebeNach( Form pForm ) {
|
|
||||||
verschiebeNach(pForm.x, pForm.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
skalierung = pFaktor;
|
|
||||||
anker.x *= pFaktor;
|
|
||||||
anker.y *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void skalierenUm( double pFaktor ) {
|
|
||||||
skalieren(skalierung * pFaktor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void drehen( double pWinkel ) {
|
|
||||||
drehwinkel += pWinkel % 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void drehenNach( double pWinkel ) {
|
|
||||||
drehwinkel = pWinkel % 360;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*public void scheren( double dx, double dy ) {
|
|
||||||
verzerrung.shear(dx, dy);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public AffineTransform getVerzerrung() {
|
|
||||||
AffineTransform verzerrung = new AffineTransform();
|
|
||||||
verzerrung.translate(x, y);
|
|
||||||
verzerrung.rotate(Math.toRadians(drehwinkel));
|
|
||||||
//verzerrung.scale(skalierung, skalierung);
|
|
||||||
verzerrung.translate(-anker.x, -anker.y);
|
|
||||||
return verzerrung;
|
|
||||||
}
|
|
||||||
|
|
||||||
public final void zeichnen( Graphics2D graphics ) {
|
|
||||||
zeichnen(graphics, getVerzerrung());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Zeichnet die Form, aber wendet zuvor noch eine zusätzliche Transformations-
|
|
||||||
* matrix an. Wird u.A. von der {@link FormGruppe} verwendet.
|
|
||||||
* @param graphics
|
|
||||||
* @param pVerzerrung
|
|
||||||
*/
|
|
||||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
|
||||||
if( !sichtbar ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Shape shape = getShape();
|
|
||||||
if( shape != null ) {
|
|
||||||
if( pVerzerrung != null ) {
|
|
||||||
shape = pVerzerrung.createTransformedShape(shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color currentColor = graphics.getColor();
|
|
||||||
if( fuellFarbe != null && fuellFarbe.getAlpha() > 0 ) {
|
|
||||||
graphics.setColor(fuellFarbe);
|
|
||||||
graphics.fill(shape);
|
|
||||||
}
|
|
||||||
if( konturFarbe != null && konturFarbe.getAlpha() > 0
|
|
||||||
&& konturDicke > 0.0 ) {
|
|
||||||
graphics.setColor(konturFarbe);
|
|
||||||
graphics.setStroke(createStroke());
|
|
||||||
graphics.draw(shape);
|
|
||||||
}
|
|
||||||
graphics.setColor(currentColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract Shape getShape();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Form form = (Form) o;
|
|
||||||
return Double.compare(form.x, x) == 0 &&
|
|
||||||
Double.compare(form.y, y) == 0 &&
|
|
||||||
Double.compare(form.drehwinkel, drehwinkel) == 0 &&
|
|
||||||
Double.compare(form.skalierung, skalierung) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class FormGruppe extends Form {
|
|
||||||
|
|
||||||
private List<Form> formen;
|
|
||||||
|
|
||||||
public FormGruppe() {
|
|
||||||
super();
|
|
||||||
formen = new ArrayList<>(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormGruppe( double pX, double pY ) {
|
|
||||||
super(pX, pY);
|
|
||||||
formen = new ArrayList<>(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FormGruppe( double pX, double pY, Form... pFormen ) {
|
|
||||||
super(pX, pY);
|
|
||||||
formen = new ArrayList<>(pFormen.length);
|
|
||||||
for( Form form : pFormen ) {
|
|
||||||
formen.add(form);
|
|
||||||
form.gruppe = this;
|
|
||||||
}
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Form kopie() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hinzu( Form... pFormen ) {
|
|
||||||
for( Form form : pFormen ) {
|
|
||||||
hinzu(form, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hinzu( Form pForm ) {
|
|
||||||
hinzu(pForm, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void hinzu( Form pForm, boolean pKoordinatenAnpassen ) {
|
|
||||||
if( pKoordinatenAnpassen ) {
|
|
||||||
pForm.x = pForm.x - x;
|
|
||||||
pForm.y = pForm.y - y;
|
|
||||||
}
|
|
||||||
formen.add(pForm);
|
|
||||||
pForm.gruppe = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
double minx = Double.MAX_VALUE, miny = Double.MAX_VALUE,
|
|
||||||
maxx = Double.MIN_VALUE, maxy = Double.MIN_VALUE;
|
|
||||||
for( Form form : formen ) {
|
|
||||||
Rechteck bounds = form.getBegrenzung();
|
|
||||||
if( bounds.x < minx )
|
|
||||||
minx = bounds.x;
|
|
||||||
if( bounds.y < miny )
|
|
||||||
miny = bounds.y;
|
|
||||||
if( bounds.x+bounds.breite > maxx )
|
|
||||||
maxx = bounds.x+bounds.breite;
|
|
||||||
if( bounds.y+bounds.hoehe > maxy )
|
|
||||||
maxy = bounds.y+bounds.hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
ankerBerechnen(maxx-minx, maxy-miny, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
Path2D.Double gruppe = new Path2D.Double();
|
|
||||||
for( Form form : formen ) {
|
|
||||||
gruppe.append(form.getShape(), false);
|
|
||||||
}
|
|
||||||
return gruppe;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
|
||||||
if( !sichtbar ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AffineTransform verzerrung = new AffineTransform();
|
|
||||||
verzerrung.translate(x, y);
|
|
||||||
verzerrung.rotate(Math.toRadians(drehwinkel));
|
|
||||||
//verzerrung.scale(skalierung, skalierung);
|
|
||||||
verzerrung.translate(-anker.x, -anker.y);
|
|
||||||
|
|
||||||
for( Form f: formen ) {
|
|
||||||
AffineTransform af = f.getVerzerrung();
|
|
||||||
af.preConcatenate(verzerrung);
|
|
||||||
f.zeichnen(graphics, af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,70 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import schule.ngb.zm.Ebene;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
|
|
||||||
public class Formenebene extends Ebene {
|
|
||||||
|
|
||||||
private LinkedList<Form> formen;
|
|
||||||
|
|
||||||
public Formenebene() {
|
|
||||||
super();
|
|
||||||
formen = new LinkedList<Form>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Formenebene( int pWidth, int pHeight ) {
|
|
||||||
super(pWidth, pHeight);
|
|
||||||
formen = new LinkedList<Form>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void anzeigen( Form... pFormen ) {
|
|
||||||
synchronized( formen ) {
|
|
||||||
for( Form f: pFormen ) {
|
|
||||||
formen.add(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void alleVerstecken() {
|
|
||||||
synchronized( formen ) {
|
|
||||||
for( Form form : formen ) {
|
|
||||||
form.verstecken();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void alleZeigen() {
|
|
||||||
synchronized( formen ) {
|
|
||||||
for( Form form : formen ) {
|
|
||||||
form.zeigen();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void leeren() {
|
|
||||||
Color currentColor = zeichnung.getBackground();
|
|
||||||
zeichnung.setBackground(new Color(0, 0, 0, 0));
|
|
||||||
zeichnung.clearRect(0, 0, puffer.getWidth(), puffer.getHeight());
|
|
||||||
zeichnung.setBackground(currentColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public java.util.List<Form> getShapes() {
|
|
||||||
return formen;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void zeichnen( Graphics2D pGraphics ) {
|
|
||||||
synchronized( formen ) {
|
|
||||||
for( Form form : formen ) {
|
|
||||||
if( form.istSichtbar() ) {
|
|
||||||
form.zeichnen(zeichnung);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.zeichnen(pGraphics);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
|
|
||||||
public class Freiform extends Form {
|
|
||||||
|
|
||||||
private Path2D.Double pfad;
|
|
||||||
|
|
||||||
public Freiform(double pX, double pY) {
|
|
||||||
super(pX, pY);
|
|
||||||
pfad = new Path2D.Double();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void linieNach( double pX, double pY ) {
|
|
||||||
pfad.lineTo(pX-x, pY-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void bogenNach( double pX1, double pY1, double pX2, double pY2 ) {
|
|
||||||
pfad.quadTo(pX1-x, pY1-y, pX2-x, pY2-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void kurveNach( double pX1, double pY1, double pX2, double pY2, double pX3, double pY3 ) {
|
|
||||||
pfad.curveTo(pX1-x, pY1-y, pX2-x, pY2-y, pX3-x, pY3-y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void schliessen() {
|
|
||||||
pfad.lineTo(0,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new Path2D.Double(pfad);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
public abstract class Fuellform extends Konturform {
|
|
||||||
|
|
||||||
public static final Color STD_FUELLFARBE = Color.WHITE;
|
|
||||||
|
|
||||||
protected Color fuellFarbe = STD_FUELLFARBE;
|
|
||||||
|
|
||||||
|
|
||||||
public Color getFuellfarbe() {
|
|
||||||
return fuellFarbe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFuellfarbe( Color pFuellFarbe) {
|
|
||||||
fuellFarbe = pFuellFarbe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void keineFuellung() {
|
|
||||||
fuellFarbe = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFuellfarbe( int gray) {
|
|
||||||
setFuellfarbe(gray, gray, gray, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFuellfarbe( int gray, int alpha) {
|
|
||||||
setFuellfarbe(gray, gray, gray, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFuellfarbe( int red, int green, int blue) {
|
|
||||||
setFuellfarbe(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFuellfarbe( int red, int green, int blue, int alpha) {
|
|
||||||
if (red < 0 || red >= 256)
|
|
||||||
throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256)
|
|
||||||
throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256)
|
|
||||||
throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
if (alpha < 0 || alpha >= 256)
|
|
||||||
throw new IllegalArgumentException("alpha must be between 0 and 255");
|
|
||||||
|
|
||||||
setFuellfarbe(new Color(red, green, blue, alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
118
src/schule/ngb/zm/formen/Kite.java
Normal file
118
src/schule/ngb/zm/formen/Kite.java
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
|
||||||
|
public class Kite extends Shape {
|
||||||
|
|
||||||
|
protected double width;
|
||||||
|
|
||||||
|
protected double height;
|
||||||
|
|
||||||
|
protected double ratio;
|
||||||
|
|
||||||
|
public Kite( double x, double y, double width, double height ) {
|
||||||
|
this(x, y, width, height, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Kite( double x, double y, double width, double height, double ratio ) {
|
||||||
|
super(x, y);
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
this.ratio = ratio;
|
||||||
|
setAnchor(CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Kite( Kite pKite ) {
|
||||||
|
this(pKite.x, pKite.y, pKite.width, pKite.height, pKite.ratio);
|
||||||
|
copyFrom(pKite);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth( double width ) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight( double height ) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRatio() {
|
||||||
|
return ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRatio( double ratio ) {
|
||||||
|
this.ratio = ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Kite ) {
|
||||||
|
Kite d = (Kite) shape;
|
||||||
|
width = d.width;
|
||||||
|
height = d.height;
|
||||||
|
ratio = d.ratio;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Kite copy() {
|
||||||
|
return new Kite(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
width *= factor;
|
||||||
|
height *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(width, height, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
double hHalf = width * .5, hRatio = ratio * height;
|
||||||
|
Path2D shape = new Path2D.Double();
|
||||||
|
shape.moveTo(hHalf, 0);
|
||||||
|
shape.lineTo(width, hRatio);
|
||||||
|
shape.lineTo(hHalf, height);
|
||||||
|
shape.lineTo(0, hRatio);
|
||||||
|
shape.closePath();
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Kite d = (Kite) o;
|
||||||
|
return super.equals(o) &&
|
||||||
|
Double.compare(d.width, width) == 0 &&
|
||||||
|
Double.compare(d.height, height) == 0 &&
|
||||||
|
Double.compare(d.ratio, ratio) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + '[' +
|
||||||
|
"width=" + width +
|
||||||
|
",height=" + height +
|
||||||
|
",verhaeltnis=" + ratio +
|
||||||
|
",x=" + x +
|
||||||
|
",y=" + y +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import schule.ngb.zm.Konstanten;
|
|
||||||
import schule.ngb.zm.Zeichenbar;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
public abstract class Konturform extends Konstanten implements Zeichenbar {
|
|
||||||
|
|
||||||
public static final int DURCHGEZOGEN = 16;
|
|
||||||
public static final int GESTRICHELT = 17;
|
|
||||||
public static final int GEPUNKTET = 18;
|
|
||||||
|
|
||||||
public static final Color STD_KONTURFABRE = Color.BLACK;
|
|
||||||
public static final double STD_KONTURDICKE = 1.0;
|
|
||||||
|
|
||||||
|
|
||||||
protected Color konturFarbe = STD_KONTURFABRE;
|
|
||||||
|
|
||||||
protected double konturDicke = STD_KONTURDICKE;
|
|
||||||
|
|
||||||
protected int konturArt = DURCHGEZOGEN;
|
|
||||||
|
|
||||||
|
|
||||||
public Color getKonturFarbe() {
|
|
||||||
return konturFarbe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturFarbe(Color pKonturFarbe) {
|
|
||||||
this.konturFarbe = pKonturFarbe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void keineKontur() {
|
|
||||||
konturFarbe = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturFarbe(int gray) {
|
|
||||||
setKonturFarbe(gray, gray, gray, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturFarbe(int gray, int alpha) {
|
|
||||||
setKonturFarbe(gray, gray, gray, alpha);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturFarbe(int red, int green, int blue) {
|
|
||||||
setKonturFarbe(red, green, blue, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturFarbe(int red, int green, int blue, int alpha) {
|
|
||||||
if (red < 0 || red >= 256)
|
|
||||||
throw new IllegalArgumentException("red must be between 0 and 255");
|
|
||||||
if (green < 0 || green >= 256)
|
|
||||||
throw new IllegalArgumentException("green must be between 0 and 255");
|
|
||||||
if (blue < 0 || blue >= 256)
|
|
||||||
throw new IllegalArgumentException("blue must be between 0 and 255");
|
|
||||||
if (alpha < 0 || alpha >= 256)
|
|
||||||
throw new IllegalArgumentException("alpha must be between 0 and 255");
|
|
||||||
|
|
||||||
setKonturFarbe(new Color(red, green, blue, alpha));
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getKonturDicke() {
|
|
||||||
return konturDicke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturDicke(double pKonturDicke) {
|
|
||||||
this.konturDicke = pKonturDicke;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getKonturArt() {
|
|
||||||
return konturArt;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKonturArt(int konturArt) {
|
|
||||||
switch (konturArt) {
|
|
||||||
case GESTRICHELT:
|
|
||||||
this.konturArt = GESTRICHELT;
|
|
||||||
break;
|
|
||||||
case GEPUNKTET:
|
|
||||||
this.konturArt = GEPUNKTET;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
this.konturArt = DURCHGEZOGEN;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void zeichnen(Graphics2D graphics);
|
|
||||||
|
|
||||||
protected Stroke createStroke() {
|
|
||||||
switch(konturArt) {
|
|
||||||
case GEPUNKTET:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) konturDicke,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND,
|
|
||||||
10.0f, new float[]{1.0f,5.0f}, 0.0f);
|
|
||||||
case GESTRICHELT:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) konturDicke,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND,
|
|
||||||
10.0f, new float[]{5.0f}, 0.0f);
|
|
||||||
case DURCHGEZOGEN:
|
|
||||||
default:
|
|
||||||
return new BasicStroke(
|
|
||||||
(float) konturDicke,
|
|
||||||
BasicStroke.CAP_ROUND,
|
|
||||||
BasicStroke.JOIN_ROUND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Ellipse2D;
|
|
||||||
|
|
||||||
public class Kreis extends Form {
|
|
||||||
|
|
||||||
public double radius;
|
|
||||||
|
|
||||||
public Kreis( double pX, double pY, double pRadius ) {
|
|
||||||
super(pX, pY);
|
|
||||||
radius = pRadius;
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Kreis( Kreis pKreis ) {
|
|
||||||
this(pKreis.x, pKreis.y, pKreis.radius);
|
|
||||||
kopiere(pKreis);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
radius *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Kreis ) {
|
|
||||||
radius = ((Kreis) pForm).radius;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Kreis kopie() {
|
|
||||||
return new Kreis(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new Ellipse2D.Double(0, 0, radius * 2.0, radius * 2.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(radius + radius, radius + radius, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Kreis kreis = (Kreis) o;
|
|
||||||
return super.equals(o) && Double.compare(kreis.radius, radius) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + "[" +
|
|
||||||
"x=" + x +
|
|
||||||
",y=" + y +
|
|
||||||
",radius=" + radius +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,183 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.CubicCurve2D;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.awt.geom.QuadCurve2D;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Kurve extends Form {
|
|
||||||
|
|
||||||
private double[] koordinaten;
|
|
||||||
|
|
||||||
public Kurve( double pX, double pY, double pCx, double pCy, double pX2, double pY2 ) {
|
|
||||||
super(pX, pY);
|
|
||||||
|
|
||||||
koordinaten = new double[]{
|
|
||||||
pCx, pCy, pX2, pY2
|
|
||||||
};
|
|
||||||
|
|
||||||
keineFuellung();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Kurve( double pX, double pY, double pCx1, double pCy1, double pCx2, double pCy2, double pX2, double pY2 ) {
|
|
||||||
super(pX, pY);
|
|
||||||
|
|
||||||
koordinaten = new double[]{
|
|
||||||
pCx1, pCy1, pCx2, pCy2, pX2, pY2
|
|
||||||
};
|
|
||||||
|
|
||||||
keineFuellung();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Kurve( Kurve pKurve ) {
|
|
||||||
super(pKurve.x, pKurve.y);
|
|
||||||
koordinaten = Arrays.copyOf(pKurve.koordinaten, pKurve.koordinaten.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D getStartpunkt() {
|
|
||||||
return new Point2D.Double(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStartpunkt( double pX, double pY ) {
|
|
||||||
x = pX;
|
|
||||||
y = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D getEndpunkt() {
|
|
||||||
return new Point2D.Double(
|
|
||||||
koordinaten[koordinaten.length - 2],
|
|
||||||
koordinaten[koordinaten.length - 1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndpunkt( double pX, double pY ) {
|
|
||||||
koordinaten[koordinaten.length - 2] = pX;
|
|
||||||
koordinaten[koordinaten.length - 1] = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D getKontrollpunkt1() {
|
|
||||||
return new Point2D.Double(
|
|
||||||
koordinaten[0],
|
|
||||||
koordinaten[1]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKontrollpunkt1( double pX, double pY ) {
|
|
||||||
koordinaten[0] = pX;
|
|
||||||
koordinaten[1] = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D getKontrollpunkt2() {
|
|
||||||
return new Point2D.Double(
|
|
||||||
koordinaten[koordinaten.length - 4],
|
|
||||||
koordinaten[koordinaten.length - 3]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setKontrollpunkt2( double pX, double pY ) {
|
|
||||||
koordinaten[koordinaten.length - 4] = pX;
|
|
||||||
koordinaten[koordinaten.length - 3] = pY;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPunkte( double pX, double pY, double pCx, double pCy, double pX2, double pY2 ) {
|
|
||||||
setStartpunkt(pX, pY);
|
|
||||||
koordinaten = koordinaten = new double[]{
|
|
||||||
pCx, pCy, pX2, pY2
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPunkte( double pX, double pY, double pCx1, double pCy1, double pCx2, double pCy2, double pX2, double pY2 ) {
|
|
||||||
setStartpunkt(pX, pY);
|
|
||||||
koordinaten = new double[]{
|
|
||||||
pCx1, pCy1, pCx2, pCy2, pX2, pY2
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean istKubisch() {
|
|
||||||
return koordinaten.length == 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean istQuadratisch() {
|
|
||||||
return koordinaten.length == 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Kurve(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Kurve ) {
|
|
||||||
Kurve k = (Kurve) pForm;
|
|
||||||
koordinaten = Arrays.copyOf(k.koordinaten, k.koordinaten.length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
if( istKubisch() ) {
|
|
||||||
return new CubicCurve2D.Double(
|
|
||||||
0, 0,
|
|
||||||
koordinaten[0] - x, koordinaten[1] - y,
|
|
||||||
koordinaten[2] - x, koordinaten[3] - y,
|
|
||||||
koordinaten[4] - x, koordinaten[5] - y
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return new QuadCurve2D.Double(
|
|
||||||
0, 0,
|
|
||||||
koordinaten[0] - x, koordinaten[1] - y,
|
|
||||||
koordinaten[2] - x, koordinaten[3] - y
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
koordinaten[koordinaten.length - 4] *= pFaktor;
|
|
||||||
koordinaten[koordinaten.length - 3] *= pFaktor;
|
|
||||||
koordinaten[koordinaten.length - 2] *= pFaktor;
|
|
||||||
koordinaten[koordinaten.length - 1] *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void verschieben( double dx, double dy ) {
|
|
||||||
super.verschieben(dx, dy);
|
|
||||||
for( int i = 0; i < koordinaten.length; i += 2 ) {
|
|
||||||
koordinaten[i] = koordinaten[i] + dx;
|
|
||||||
koordinaten[i + 1] = koordinaten[i + 1] + dy;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void verschiebeNach( double pX, double pY ) {
|
|
||||||
double dx = pX - x, dy = pY - y;
|
|
||||||
verschieben(dx, dy);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Kurve kurve = (Kurve) o;
|
|
||||||
return super.equals(o) &&
|
|
||||||
getStartpunkt().equals(kurve.getStartpunkt()) &&
|
|
||||||
getKontrollpunkt1().equals(kurve.getKontrollpunkt1()) &&
|
|
||||||
getKontrollpunkt2().equals(kurve.getKontrollpunkt2()) &&
|
|
||||||
getEndpunkt().equals(kurve.getEndpunkt());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + "[" +
|
|
||||||
"x=" + x +
|
|
||||||
",y=" + y +
|
|
||||||
"x2=" + koordinaten[koordinaten.length - 2] +
|
|
||||||
",y2=" + koordinaten[koordinaten.length - 1] +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
108
src/schule/ngb/zm/formen/Line.java
Normal file
108
src/schule/ngb/zm/formen/Line.java
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Line2D;
|
||||||
|
|
||||||
|
public class Line extends Shape {
|
||||||
|
|
||||||
|
protected double x2;
|
||||||
|
|
||||||
|
protected double y2;
|
||||||
|
|
||||||
|
public Line( double x1, double y1, double x2, double y2 ) {
|
||||||
|
super(x1, y1);
|
||||||
|
this.x2 = x2;
|
||||||
|
this.y2 = y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Line( Line line ) {
|
||||||
|
this(line.x, line.y, line.x2, line.y2);
|
||||||
|
copyFrom(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX2() {
|
||||||
|
return x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX2( double x ) {
|
||||||
|
this.x2 = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY2() {
|
||||||
|
return y2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY2( double y ) {
|
||||||
|
this.y2 = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
x2 *= factor;
|
||||||
|
y2 *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Line ) {
|
||||||
|
Line pLine = (Line) shape;
|
||||||
|
x2 = pLine.x2;
|
||||||
|
y2 = pLine.y2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Line copy() {
|
||||||
|
return new Line(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void move( double dx, double dy ) {
|
||||||
|
super.move(dx, dy);
|
||||||
|
x2 += dx;
|
||||||
|
y2 += dx;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void moveTo( double x, double y ) {
|
||||||
|
double dx = x2-this.x;
|
||||||
|
double dy = y2-this.y;
|
||||||
|
super.moveTo(x, y);
|
||||||
|
x2 += dx;
|
||||||
|
y2 += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(x2 - x, y2 - y, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Line2D.Double(0, 0, x2 - x, y2 - y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Line pLine = (Line) o;
|
||||||
|
return super.equals(o) &&
|
||||||
|
Double.compare(pLine.x2, x2) == 0 &&
|
||||||
|
Double.compare(pLine.y2, y2) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + "[" +
|
||||||
|
"x1=" + x +
|
||||||
|
",y1=" + y +
|
||||||
|
",x2=" + x2 +
|
||||||
|
",y2=" + y2 +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Line2D;
|
|
||||||
|
|
||||||
public class Linie extends Form {
|
|
||||||
|
|
||||||
protected double x2;
|
|
||||||
|
|
||||||
protected double y2;
|
|
||||||
|
|
||||||
public Linie( double pX1, double pY1, double pX2, double pY2 ) {
|
|
||||||
super(pX1, pY1);
|
|
||||||
x2 = pX2;
|
|
||||||
y2 = pY2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Linie( Linie pLinie ) {
|
|
||||||
this(pLinie.x, pLinie.y, pLinie.x2, pLinie.y2);
|
|
||||||
kopiere(pLinie);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setX2( double pX ) {
|
|
||||||
this.x2 = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setY2( double pY ) {
|
|
||||||
this.y2 = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getX2() {
|
|
||||||
return x2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getY2() {
|
|
||||||
return y2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
x2 *= pFaktor;
|
|
||||||
y2 *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Linie ) {
|
|
||||||
Linie linie = (Linie) pForm;
|
|
||||||
x2 = linie.x2;
|
|
||||||
y2 = linie.y2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Linie kopie() {
|
|
||||||
return new Linie(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(x2-x, y2-y, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
Line2D.Double linie = new Line2D.Double(0, 0, x2 - x, y2 - y);
|
|
||||||
return linie;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Linie linie = (Linie) o;
|
|
||||||
return super.equals(o) &&
|
|
||||||
Double.compare(linie.x2, x2) == 0 &&
|
|
||||||
Double.compare(linie.y2, y2) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + "[" +
|
|
||||||
"x1=" + x +
|
|
||||||
",y1=" + y +
|
|
||||||
",x2=" + x2 +
|
|
||||||
",y2=" + y2 +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,137 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import schule.ngb.zm.Vektor;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.AffineTransform;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
|
|
||||||
public class Pfeil extends Linie {
|
|
||||||
|
|
||||||
public static final int OFFEN = 101;
|
|
||||||
public static final int GESCHLOSSEN = 102;
|
|
||||||
private static final double BASIS_PFEILGROESSE = 5.0;
|
|
||||||
protected int pfeilspitze = OFFEN;
|
|
||||||
|
|
||||||
protected double pfeilgroesse = 1.0;
|
|
||||||
|
|
||||||
public Pfeil( double pX1, double pY1, double pX2, double pY2 ) {
|
|
||||||
super(pX1, pY1, pX2, pY2);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pfeil( Vektor pVektor ) {
|
|
||||||
this(0, 0, pVektor.x, pVektor.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pfeil( double pX, double pY, Vektor pVektor ) {
|
|
||||||
this(pX, pY, pX + pVektor.x, pY + pVektor.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pfeil( Linie pLinie ) {
|
|
||||||
this(pLinie.x, pLinie.y, pLinie.x2, pLinie.y2);
|
|
||||||
kopiere(pLinie);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getPfeilgroesse() {
|
|
||||||
return pfeilgroesse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPfeilgroesse( double pPfeilgroesse ) {
|
|
||||||
pfeilgroesse = pPfeilgroesse;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPfeilspitze() {
|
|
||||||
return pfeilspitze;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPfeilspitze( int pPfeilspitze ) {
|
|
||||||
this.pfeilspitze = pPfeilspitze;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void abbilden( Vektor pVektor ) {
|
|
||||||
x2 = x + pVektor.x;
|
|
||||||
y2 = y + pVektor.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Pfeil ) {
|
|
||||||
Pfeil pfeil = (Pfeil) pForm;
|
|
||||||
pfeilgroesse = pfeil.pfeilgroesse;
|
|
||||||
pfeilspitze = pfeil.pfeilspitze;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Pfeil kopie() {
|
|
||||||
return new Pfeil(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
/*Path2D.Double gruppe = new Path2D.Double();
|
|
||||||
gruppe.append(super.getShape(), false);
|
|
||||||
gruppe.append(getPfeilspitze(), false);
|
|
||||||
|
|
||||||
return gruppe;*/
|
|
||||||
return super.getShape();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Shape getSpitze() {
|
|
||||||
AffineTransform af;
|
|
||||||
switch( pfeilspitze ) {
|
|
||||||
case OFFEN:
|
|
||||||
double len = BASIS_PFEILGROESSE * pfeilgroesse;
|
|
||||||
Path2D.Double sOffen = new Path2D.Double();
|
|
||||||
sOffen.moveTo(-len, -len);
|
|
||||||
sOffen.lineTo(0, 0);
|
|
||||||
sOffen.lineTo(-len, len);
|
|
||||||
|
|
||||||
af = new AffineTransform();
|
|
||||||
af.translate(x2, y2);
|
|
||||||
af.rotate(Math.atan2(y2 - y, x2 - x));
|
|
||||||
return af.createTransformedShape(sOffen);
|
|
||||||
case GESCHLOSSEN:
|
|
||||||
default:
|
|
||||||
int ix = (int) x2, iy = (int) y2, pg = (int) (BASIS_PFEILGROESSE * pfeilgroesse);
|
|
||||||
Polygon sGeschlossen = new Polygon(
|
|
||||||
new int[]{0, -pg, -pg},
|
|
||||||
new int[]{0, -pg, pg},
|
|
||||||
3
|
|
||||||
);
|
|
||||||
|
|
||||||
af = new AffineTransform();
|
|
||||||
af.translate(x2, y2);
|
|
||||||
af.rotate(Math.atan2(y2 - y, x2 - x));
|
|
||||||
return af.createTransformedShape(sGeschlossen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
|
||||||
if( !sichtbar ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
super.zeichnen(graphics);
|
|
||||||
|
|
||||||
Shape spitze = getSpitze();
|
|
||||||
if( pVerzerrung != null ) {
|
|
||||||
spitze = pVerzerrung.createTransformedShape(spitze);
|
|
||||||
}
|
|
||||||
|
|
||||||
Color currentColor = graphics.getColor();
|
|
||||||
if( konturFarbe != null && konturFarbe.getAlpha() > 0.0 ) {
|
|
||||||
graphics.setColor(konturFarbe);
|
|
||||||
graphics.setStroke(new BasicStroke((float) konturDicke));
|
|
||||||
if( pfeilspitze == GESCHLOSSEN ) {
|
|
||||||
graphics.fill(spitze);
|
|
||||||
} else {
|
|
||||||
graphics.draw(spitze);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
graphics.setColor(currentColor);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
128
src/schule/ngb/zm/formen/Picture.java
Normal file
128
src/schule/ngb/zm/formen/Picture.java
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
import schule.ngb.zm.util.ImageLoader;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
public class Picture extends Shape {
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/14225518/tinting-image-in-java-improvement
|
||||||
|
protected Color tint;
|
||||||
|
|
||||||
|
private BufferedImage image;
|
||||||
|
|
||||||
|
private double width;
|
||||||
|
|
||||||
|
private double height;
|
||||||
|
|
||||||
|
public Picture( String source ) {
|
||||||
|
this(0, 0, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Picture( double x, double y, String source ) {
|
||||||
|
super(x, y);
|
||||||
|
image = ImageLoader.loadImage(source);
|
||||||
|
|
||||||
|
if( image == null ) {
|
||||||
|
throw new IllegalArgumentException("Could not initialize image from source " + source);
|
||||||
|
}
|
||||||
|
|
||||||
|
width = image.getWidth();
|
||||||
|
height = image.getHeight();
|
||||||
|
setAnchor(CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Picture( Picture picture ) {
|
||||||
|
super(picture.getX(), picture.getY());
|
||||||
|
copyFrom(picture);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Picture(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Picture ) {
|
||||||
|
Picture pic = (Picture) shape;
|
||||||
|
image = new BufferedImage(pic.image.getWidth(), pic.image.getHeight(), pic.image.getType());
|
||||||
|
Graphics2D g = image.createGraphics();
|
||||||
|
g.drawImage(pic.image, 0, 0, null);
|
||||||
|
g.dispose();
|
||||||
|
|
||||||
|
width = image.getWidth();
|
||||||
|
height = image.getHeight();
|
||||||
|
setAnchor(shape.getAnchor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth( double width ) {
|
||||||
|
scale(width / width);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight( double height ) {
|
||||||
|
scale(height / height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BufferedImage getImage() {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(width, height, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
width *= factor;
|
||||||
|
height *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Rectangle2D.Double(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
public AffineTransform getVerzerrung() {
|
||||||
|
AffineTransform verzerrung = new AffineTransform();
|
||||||
|
verzerrung.translate(x, y);
|
||||||
|
verzerrung.scale(skalierung, skalierung);
|
||||||
|
verzerrung.rotate(Math.toRadians(drehwinkel));
|
||||||
|
verzerrung.translate(-anker.x, -anker.y);
|
||||||
|
return verzerrung;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||||
|
if( !visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AffineTransform current = graphics.getTransform();
|
||||||
|
graphics.transform(getTransform());
|
||||||
|
graphics.drawImage(image, 0, 0, (int) width, (int) height, null);
|
||||||
|
graphics.setTransform(current);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
58
src/schule/ngb/zm/formen/Point.java
Normal file
58
src/schule/ngb/zm/formen/Point.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
|
public class Point extends Circle {
|
||||||
|
|
||||||
|
private static final double POINT_RADIUS = 2.0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Punktobjekt mit den angegebenen Koordinaten.
|
||||||
|
* @param x
|
||||||
|
* @param y
|
||||||
|
*/
|
||||||
|
public Point( double x, double y ) {
|
||||||
|
super(x, y, POINT_RADIUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Punktobjekt mit den Koordinaten des übergebenen
|
||||||
|
* {@link schule.ngb.zm.Vector Vektors}.
|
||||||
|
* @param point
|
||||||
|
*/
|
||||||
|
public Point( schule.ngb.zm.Vector vector ) {
|
||||||
|
super(vector.x, vector.y, POINT_RADIUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Punktobjekt mit den Koordinaten des übergebenen
|
||||||
|
* {@link java.awt.geom.Point2D Punktes}.
|
||||||
|
* @param point
|
||||||
|
*/
|
||||||
|
public Point( Point2D point ) {
|
||||||
|
super(point.getX(), point.getY(), POINT_RADIUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Punktobjekt mit den Koordinaten der angegeben Form.
|
||||||
|
* @param shape
|
||||||
|
*/
|
||||||
|
public Point( Shape shape ) {
|
||||||
|
super(shape.getX(), shape.getY(), POINT_RADIUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
// Skalierung ist für Punkte deaktiviert
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
// Punkte sind immer im Zentrum verankert
|
||||||
|
calculateAnchor(radius + radius, radius + radius, CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
82
src/schule/ngb/zm/formen/Polygon.java
Normal file
82
src/schule/ngb/zm/formen/Polygon.java
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
|
public class Polygon extends Shape {
|
||||||
|
|
||||||
|
protected Point2D[] points;
|
||||||
|
|
||||||
|
public Polygon( double x, double y, Point2D... points ) {
|
||||||
|
super(x, y);
|
||||||
|
|
||||||
|
this.points = new Point2D[points.length];
|
||||||
|
for( int i = 0; i < points.length; i++ ) {
|
||||||
|
this.points[i] = new Point2D.Double(points[i].getX() - x, points[i].getY() - y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Polygon( Point2D... points ) {
|
||||||
|
this.points = new Point2D[points.length];
|
||||||
|
for( int i = 0; i < points.length; i++ ) {
|
||||||
|
if( i == 0 ) {
|
||||||
|
x = points[i].getX();
|
||||||
|
y = points[i].getY();
|
||||||
|
}
|
||||||
|
this.points[i] = new Point2D.Double(points[i].getX() - x, points[i].getY() - y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Polygon( double x1, double y1, double x2, double y2, double... coordinates ) {
|
||||||
|
super(x1, y1);
|
||||||
|
|
||||||
|
int numPoints = coordinates.length / 2 + 2;
|
||||||
|
|
||||||
|
points = new Point2D[numPoints];
|
||||||
|
this.points[0] = new Point2D.Double(x1, y1);
|
||||||
|
this.points[1] = new Point2D.Double(x2 - x1, y2 - y1);
|
||||||
|
for( int i = 0; i < numPoints - 2; i += 1 ) {
|
||||||
|
this.points[i + 2] = new Point2D.Double(coordinates[i * 2] - x1, coordinates[i * 2 + 1] - y1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Polygon( Polygon polygon ) {
|
||||||
|
super(polygon.x, polygon.y);
|
||||||
|
copyFrom(polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D[] getPoints() {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Polygon ) {
|
||||||
|
Polygon v = (Polygon) shape;
|
||||||
|
|
||||||
|
points = new Point2D[v.points.length];
|
||||||
|
for( int i = 0; i < v.points.length; i++ ) {
|
||||||
|
points[i] = new Point2D.Double(v.points[i].getX(), v.points[i].getY());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Polygon(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
Path2D shape = new Path2D.Double();
|
||||||
|
//shape.moveTo(points[0].getX(), points[0].getY());
|
||||||
|
shape.moveTo(0, 0);
|
||||||
|
for( int i = 1; i < points.length; i++ ) {
|
||||||
|
shape.lineTo(points[i].getX(), points[i].getY());
|
||||||
|
}
|
||||||
|
shape.closePath();
|
||||||
|
return shape;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
|
|
||||||
public class Punkt extends Kreis {
|
|
||||||
|
|
||||||
private static final double PUNKT_RADIUS = 2.0;
|
|
||||||
|
|
||||||
|
|
||||||
public Punkt( double pX, double pY ) {
|
|
||||||
super(pX, pY, PUNKT_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Punkt( Point2D pPunkt ) {
|
|
||||||
super(pPunkt.getX(), pPunkt.getY(), PUNKT_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Punkt( Form pForm ) {
|
|
||||||
super(pForm.getX(), pForm.getY(), PUNKT_RADIUS);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
// Skalierung ist für Punkte deaktiviert
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
// Punkte sind immer im Zentrum verankert
|
|
||||||
ankerBerechnen(radius + radius, radius + radius, ZENTRUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
36
src/schule/ngb/zm/formen/Quad.java
Normal file
36
src/schule/ngb/zm/formen/Quad.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Quad extends Polygon {
|
||||||
|
|
||||||
|
public Quad( double x, double y, Point2D... points ) {
|
||||||
|
super(x, y, Arrays.copyOf(points, 4));
|
||||||
|
if( points.length < 4 ) {
|
||||||
|
throw new IllegalArgumentException("A quadrilateral requires exactly four points.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quad( Point2D... points ) {
|
||||||
|
super(Arrays.copyOf(points, 4));
|
||||||
|
if( points.length < 4 ) {
|
||||||
|
throw new IllegalArgumentException("A quadrilateral requires exactly four points.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quad( double x1, double y1, double x2, double y2, double x3, double y3, double x4, double y4 ) {
|
||||||
|
super(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Quad( Quad pViereck ) {
|
||||||
|
super(pViereck.x, pViereck.y);
|
||||||
|
copyFrom(pViereck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Quad(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
|
|
||||||
public class Raute extends Drache {
|
|
||||||
|
|
||||||
private double breite;
|
|
||||||
|
|
||||||
private double hoehe;
|
|
||||||
|
|
||||||
public Raute( double pX, double pY, double pBreite, double pHoehe ) {
|
|
||||||
super(pX, pY, pBreite, pHoehe, 0.5);
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Raute( Raute pRaute ) {
|
|
||||||
this(pRaute.x, pRaute.y, pRaute.breite, pRaute.hoehe);
|
|
||||||
kopiere(pRaute);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setVerhaeltnis( double pVerhaeltnis ) {
|
|
||||||
super.setVerhaeltnis(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
super.setVerhaeltnis(0.5);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Drache kopie() {
|
|
||||||
return new Drache(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Rectangle2D;
|
|
||||||
|
|
||||||
public class Rechteck extends Form {
|
|
||||||
|
|
||||||
protected double breite;
|
|
||||||
|
|
||||||
protected double hoehe;
|
|
||||||
|
|
||||||
public Rechteck( double pX, double pY, double pBreite, double pHoehe ) {
|
|
||||||
super(pX, pY);
|
|
||||||
breite = pBreite;
|
|
||||||
hoehe = pHoehe;
|
|
||||||
setAnkerpunkt(NORDWESTEN);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rechteck( Rechteck pRechteck ) {
|
|
||||||
this(
|
|
||||||
pRechteck.x, pRechteck.y,
|
|
||||||
pRechteck.breite, pRechteck.hoehe);
|
|
||||||
kopiere(pRechteck);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Rechteck( Form pForm ) {
|
|
||||||
Shape s = pForm.getShape();
|
|
||||||
s = pForm.getVerzerrung().createTransformedShape(s);
|
|
||||||
Rectangle2D bounds = s.getBounds2D();
|
|
||||||
x = bounds.getX();
|
|
||||||
y = bounds.getY();
|
|
||||||
breite = bounds.getWidth();
|
|
||||||
hoehe = bounds.getHeight();
|
|
||||||
fuellFarbe = null;
|
|
||||||
konturArt = GESTRICHELT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getBreite() {
|
|
||||||
return breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBreite( double breite ) {
|
|
||||||
this.breite = breite;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getHoehe() {
|
|
||||||
return hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHoehe( double hoehe ) {
|
|
||||||
this.hoehe = hoehe;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Rechteck kopie() {
|
|
||||||
return new Rechteck(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Rechteck ) {
|
|
||||||
Rechteck rechteck = (Rechteck) pForm;
|
|
||||||
breite = rechteck.breite;
|
|
||||||
hoehe = rechteck.hoehe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skalieren( double pFaktor ) {
|
|
||||||
super.skalieren(pFaktor);
|
|
||||||
breite *= pFaktor;
|
|
||||||
hoehe *= pFaktor;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
return new Rectangle2D.Double(0, 0, breite, hoehe);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
|
||||||
ankerBerechnen(breite, hoehe, pAnker);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals( Object o ) {
|
|
||||||
if( this == o ) return true;
|
|
||||||
if( o == null || getClass() != o.getClass() ) return false;
|
|
||||||
Rechteck rechteck = (Rechteck) o;
|
|
||||||
return super.equals(o) &&
|
|
||||||
Double.compare(rechteck.breite, breite) == 0 &&
|
|
||||||
Double.compare(rechteck.hoehe, hoehe) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return getClass().getCanonicalName() + "[" +
|
|
||||||
"x=" + x +
|
|
||||||
",y=" + y +
|
|
||||||
",breite=" + breite +
|
|
||||||
",hoehe=" + hoehe +
|
|
||||||
']';
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
108
src/schule/ngb/zm/formen/Rectangle.java
Normal file
108
src/schule/ngb/zm/formen/Rectangle.java
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
public class Rectangle extends Shape {
|
||||||
|
|
||||||
|
protected double width;
|
||||||
|
|
||||||
|
protected double height;
|
||||||
|
|
||||||
|
public Rectangle( double x, double y, double width, double height ) {
|
||||||
|
super(x, y);
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
setAnchor(NORTHWEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle( Rectangle pRechteck ) {
|
||||||
|
this(
|
||||||
|
pRechteck.x, pRechteck.y,
|
||||||
|
pRechteck.width, pRechteck.height);
|
||||||
|
copyFrom(pRechteck);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rectangle( Shape pShape ) {
|
||||||
|
java.awt.Shape s = pShape.getShape();
|
||||||
|
s = pShape.getTransform().createTransformedShape(s);
|
||||||
|
Rectangle2D bounds = s.getBounds2D();
|
||||||
|
x = bounds.getX();
|
||||||
|
y = bounds.getY();
|
||||||
|
width = bounds.getWidth();
|
||||||
|
height = bounds.getHeight();
|
||||||
|
fillColor = null;
|
||||||
|
strokeType = DASHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getWidth() {
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth( double width ) {
|
||||||
|
this.width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getHeight() {
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeight( double height ) {
|
||||||
|
this.height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Rectangle copy() {
|
||||||
|
return new Rectangle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof Rectangle ) {
|
||||||
|
Rectangle rechteck = (Rectangle) shape;
|
||||||
|
width = rechteck.width;
|
||||||
|
height = rechteck.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void scale( double factor ) {
|
||||||
|
super.scale(factor);
|
||||||
|
width *= factor;
|
||||||
|
height *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new Rectangle2D.Double(0, 0, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
calculateAnchor(width, height, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Rectangle rechteck = (Rectangle) o;
|
||||||
|
return super.equals(o) &&
|
||||||
|
Double.compare(rechteck.width, width) == 0 &&
|
||||||
|
Double.compare(rechteck.height, height) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + "[" +
|
||||||
|
"x=" + x +
|
||||||
|
",y=" + y +
|
||||||
|
",width=" + width +
|
||||||
|
",height=" + height +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
32
src/schule/ngb/zm/formen/Rhombus.java
Normal file
32
src/schule/ngb/zm/formen/Rhombus.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
public class Rhombus extends Kite {
|
||||||
|
|
||||||
|
public Rhombus( double x, double y, double width, double height ) {
|
||||||
|
super(x, y, width, height, 0.5);
|
||||||
|
setAnchor(CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rhombus( Rhombus rhombus ) {
|
||||||
|
this(rhombus.x, rhombus.y, rhombus.width, rhombus.height);
|
||||||
|
this.copyFrom(rhombus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRatio( double ratio ) {
|
||||||
|
// Für eine Raute ist das Verhältnis immer 50/5ß
|
||||||
|
super.setRatio(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
super.setRatio(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Kite copy() {
|
||||||
|
return new Kite(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
57
src/schule/ngb/zm/formen/RoundedRectangle.java
Normal file
57
src/schule/ngb/zm/formen/RoundedRectangle.java
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
|
||||||
|
public class RoundedRectangle extends Rectangle {
|
||||||
|
|
||||||
|
protected double borderRadius = 1.0;
|
||||||
|
|
||||||
|
public RoundedRectangle( double x, double y, double width, double height, double borderRadius ) {
|
||||||
|
super(x, y, width, height);
|
||||||
|
this.borderRadius = borderRadius;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoundedRectangle( Rectangle pRechteck ) {
|
||||||
|
super(
|
||||||
|
pRechteck.x, pRechteck.y,
|
||||||
|
pRechteck.width, pRechteck.height);
|
||||||
|
copyFrom(pRechteck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
super.copyFrom(shape);
|
||||||
|
if( shape instanceof RoundedRectangle ) {
|
||||||
|
RoundedRectangle rechteck = (RoundedRectangle) shape;
|
||||||
|
borderRadius = rechteck.borderRadius;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
return new RoundRectangle2D.Double(
|
||||||
|
0, 0, width, height, borderRadius, borderRadius
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
RoundedRectangle rechteck = (RoundedRectangle) o;
|
||||||
|
return super.equals(o) &&
|
||||||
|
Double.compare(rechteck.borderRadius, borderRadius) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getCanonicalName() + "[" +
|
||||||
|
"x=" + x +
|
||||||
|
",y=" + y +
|
||||||
|
",width=" + width +
|
||||||
|
",height=" + height +
|
||||||
|
",rundung=" + borderRadius +
|
||||||
|
']';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
291
src/schule/ngb/zm/formen/Shape.java
Normal file
291
src/schule/ngb/zm/formen/Shape.java
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
|
public abstract class Shape extends FilledShape {
|
||||||
|
|
||||||
|
protected double x;
|
||||||
|
|
||||||
|
protected double y;
|
||||||
|
|
||||||
|
protected double rotation = 0.0;
|
||||||
|
|
||||||
|
protected double scale = 1.0;
|
||||||
|
|
||||||
|
protected boolean visible = true;
|
||||||
|
|
||||||
|
protected Point2D.Double anchor = new Point2D.Double();
|
||||||
|
|
||||||
|
public Shape( double x, double y ) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape() {
|
||||||
|
this(0.0, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX( double x ) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY( double y ) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getRotation() {
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getScale() {
|
||||||
|
return scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isVisible() {
|
||||||
|
return visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hide() {
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
visible = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void toggle() {
|
||||||
|
visible = !visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point2D.Double getAnchor() {
|
||||||
|
return new Point2D.Double(anchor.x, anchor.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den Ankerpunkt der Form basierend auf der angegebenen
|
||||||
|
* {@link Options.Direction Richtung}.
|
||||||
|
*
|
||||||
|
* Für das Setzen des Ankers muss das {@link #getBounds() begrenzende
|
||||||
|
* Rechteck} berechnet werden. Unterklassen sollten die Methode
|
||||||
|
* überschreiben, wenn der Anker auch direkt gesetzt werden kann.
|
||||||
|
* @param anchor
|
||||||
|
*/
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
java.awt.Shape shape = getShape();
|
||||||
|
if( shape != null ) {
|
||||||
|
Rectangle2D bounds = shape.getBounds2D();
|
||||||
|
calculateAnchor(bounds.getWidth(), bounds.getHeight(), anchor);
|
||||||
|
} else {
|
||||||
|
this.anchor.x = 0;
|
||||||
|
this.anchor.y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den Ankerpunkt explizit auf den angegebenen
|
||||||
|
* @param anchor
|
||||||
|
*/
|
||||||
|
public void setAnchor( Point2D.Double anchor ) {
|
||||||
|
setAnchor(anchor, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchor( Point2D.Double anchor, boolean isRelative ) {
|
||||||
|
if( anchor != null ) {
|
||||||
|
setAnchor(anchor.x, anchor.y, isRelative);
|
||||||
|
} else {
|
||||||
|
setAnchor(0, 0, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchor( double x, double y ) {
|
||||||
|
setAnchor(x, y, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAnchor( double x, double y, boolean isRelative ) {
|
||||||
|
if( isRelative ) {
|
||||||
|
this.anchor.x = x;
|
||||||
|
this.anchor.y = y;
|
||||||
|
} else {
|
||||||
|
this.anchor.x = this.x-x;
|
||||||
|
this.anchor.y = this.y-y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsmethode zur Berechnung eines Ankerpunktes relativ zu den angegebenen
|
||||||
|
* Begrenzungen basierend aus {@link #x}-, {@link #y}-Koordinate und
|
||||||
|
* <var>width</var> / <var>height</var> (Breite / Höhe).
|
||||||
|
* @param width
|
||||||
|
* @param height
|
||||||
|
* @param anchor
|
||||||
|
*/
|
||||||
|
protected void calculateAnchor( double width, double height, @NotNull Options.Direction anchor ) {
|
||||||
|
double bHalf = width * .5, hHalf = height * .5;
|
||||||
|
// pAnker == CENTER
|
||||||
|
this.anchor.x = bHalf;
|
||||||
|
this.anchor.y = hHalf;
|
||||||
|
if( NORTH.is(anchor) ) {
|
||||||
|
this.anchor.y -= hHalf;
|
||||||
|
}
|
||||||
|
if( SOUTH.is(anchor) ) {
|
||||||
|
this.anchor.y += hHalf;
|
||||||
|
}
|
||||||
|
if( WEST.is(anchor) ) {
|
||||||
|
this.anchor.x -= bHalf;
|
||||||
|
}
|
||||||
|
if( EAST.is(anchor) ) {
|
||||||
|
this.anchor.x += bHalf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kopiert die Eigenschaften der übergebenen Form in diese.
|
||||||
|
*
|
||||||
|
* Unterklassen sollten diese Methode überschreiben, um weitere Eigenschaften
|
||||||
|
* zu kopieren (zum Beispiel den Radius eines Kreises). Mit dem Aufruf
|
||||||
|
* <code>super.copyFrom(shape)</code> sollten die Basiseigenschaften
|
||||||
|
* kopiert werden.
|
||||||
|
* @param shape
|
||||||
|
*/
|
||||||
|
public void copyFrom( Shape shape ) {
|
||||||
|
moveTo(shape.x, shape.y);
|
||||||
|
setFillColor(shape.getFillColor());
|
||||||
|
setStrokeColor(shape.getStrokeColor());
|
||||||
|
setStrokeWeight(shape.getStrokeWeight());
|
||||||
|
setStrokeType(shape.getStrokeType());
|
||||||
|
visible = shape.isVisible();
|
||||||
|
rotation = shape.rotation;
|
||||||
|
scale(shape.scale);
|
||||||
|
setAnchor(shape.getAnchor());
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract Shape copy();
|
||||||
|
|
||||||
|
public abstract java.awt.Shape getShape();
|
||||||
|
|
||||||
|
public Rectangle getBounds() {
|
||||||
|
return new Rectangle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void move( double dx, double dy ) {
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moveTo( double x, double y ) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scale( double factor ) {
|
||||||
|
scale = factor;
|
||||||
|
anchor.x *= factor;
|
||||||
|
anchor.y *= factor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void scaleBy( double factor ) {
|
||||||
|
scale(scale * factor);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotate( double angle ) {
|
||||||
|
this.rotation += angle % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void rotateTo( double angle ) {
|
||||||
|
this.rotation = angle % 360;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*public void shear( double dx, double dy ) {
|
||||||
|
verzerrung.shear(dx, dy);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public AffineTransform getTransform() {
|
||||||
|
AffineTransform transform = new AffineTransform();
|
||||||
|
transform.translate(x, y);
|
||||||
|
transform.rotate(Math.toRadians(rotation));
|
||||||
|
//transform.scale(scale, scale);
|
||||||
|
transform.translate(-anchor.x, -anchor.y);
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zeichnet die Form.
|
||||||
|
*
|
||||||
|
* @param graphics
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public final void draw( Graphics2D graphics ) {
|
||||||
|
draw(graphics, getTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Zeichnet die Form, aber wendet zuvor noch eine zusätzliche Transformations-
|
||||||
|
* matrix an. Wird u.A. von der {@link ShapeGroup} verwendet.
|
||||||
|
*
|
||||||
|
* @param graphics
|
||||||
|
* @param pVerzerrung
|
||||||
|
*/
|
||||||
|
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||||
|
if( !visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
java.awt.Shape shape = getShape();
|
||||||
|
if( shape != null ) {
|
||||||
|
if( pVerzerrung != null ) {
|
||||||
|
shape = pVerzerrung.createTransformedShape(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
Color currentColor = graphics.getColor();
|
||||||
|
if( fillColor != null && fillColor.getAlpha() > 0 ) {
|
||||||
|
graphics.setColor(fillColor.getColor());
|
||||||
|
graphics.fill(shape);
|
||||||
|
}
|
||||||
|
if( strokeColor != null && strokeColor.getAlpha() > 0
|
||||||
|
&& strokeWeight > 0.0 ) {
|
||||||
|
graphics.setColor(strokeColor.getColor());
|
||||||
|
graphics.setStroke(createStroke());
|
||||||
|
graphics.draw(shape);
|
||||||
|
}
|
||||||
|
graphics.setColor(currentColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vergleicht die Form mit einem anderen Objekt. Handelt es sich bei dem
|
||||||
|
* Objekt um eine andere Form, werden Position, Drehwinkel und Skalierung
|
||||||
|
* verglichen. Unterklassen überschreiben die Methode, um weitere
|
||||||
|
* Eigenschaften zu berücksichtigen.
|
||||||
|
* <p>
|
||||||
|
* Die Eigenschaften von {@link FilledShape} und {@link StrokedShape} werden
|
||||||
|
* nicht verglichen.
|
||||||
|
*
|
||||||
|
* @param o Ein anderes Objekt.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals( Object o ) {
|
||||||
|
if( this == o ) return true;
|
||||||
|
if( o == null || getClass() != o.getClass() ) return false;
|
||||||
|
Shape pShape = (Shape) o;
|
||||||
|
return Double.compare(pShape.x, x) == 0 &&
|
||||||
|
Double.compare(pShape.y, y) == 0 &&
|
||||||
|
Double.compare(pShape.rotation, rotation) == 0 &&
|
||||||
|
Double.compare(pShape.scale, scale) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
138
src/schule/ngb/zm/formen/ShapeGroup.java
Normal file
138
src/schule/ngb/zm/formen/ShapeGroup.java
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.Path2D;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ShapeGroup extends Shape {
|
||||||
|
|
||||||
|
private List<Shape> shapes;
|
||||||
|
|
||||||
|
public ShapeGroup() {
|
||||||
|
super();
|
||||||
|
shapes = new ArrayList<>(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapeGroup( double x, double y ) {
|
||||||
|
super(x, y);
|
||||||
|
shapes = new ArrayList<>(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapeGroup( double x, double y, Shape... shapes ) {
|
||||||
|
super(x, y);
|
||||||
|
this.shapes = new ArrayList<>(shapes.length);
|
||||||
|
for( Shape pShape : shapes ) {
|
||||||
|
this.shapes.add(pShape);
|
||||||
|
}
|
||||||
|
setAnchor(CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape copy() {
|
||||||
|
// TODO: implement?
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( Shape... shapes ) {
|
||||||
|
for( Shape shape : shapes ) {
|
||||||
|
add(shape, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( Shape pShape, boolean relative ) {
|
||||||
|
if( relative ) {
|
||||||
|
pShape.x = pShape.x - x;
|
||||||
|
pShape.y = pShape.y - y;
|
||||||
|
}
|
||||||
|
shapes.add(pShape);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeAll() {
|
||||||
|
shapes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Shape> getShapes() {
|
||||||
|
return shapes;
|
||||||
|
}
|
||||||
|
public <ShapeType extends Shape> List<ShapeType> getShapes( Class<ShapeType> typeClass ) {
|
||||||
|
LinkedList<ShapeType> list = new LinkedList<>();
|
||||||
|
for( Shape s: shapes ) {
|
||||||
|
if( typeClass.getClass().isInstance(s) ) {
|
||||||
|
list.add((ShapeType)s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove( Shape shape ) {
|
||||||
|
shapes.remove(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Shape get( int index ) {
|
||||||
|
if( index < shapes.size() ) {
|
||||||
|
return shapes.get(index);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean contains( Shape shape ) {
|
||||||
|
return shapes.contains(shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int size() {
|
||||||
|
return shapes.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
|
double minx = Double.MAX_VALUE, miny = Double.MAX_VALUE,
|
||||||
|
maxx = Double.MIN_VALUE, maxy = Double.MIN_VALUE;
|
||||||
|
for( Shape pShape : shapes ) {
|
||||||
|
Rectangle bounds = pShape.getBounds();
|
||||||
|
if( bounds.x < minx )
|
||||||
|
minx = bounds.x;
|
||||||
|
if( bounds.y < miny )
|
||||||
|
miny = bounds.y;
|
||||||
|
if( bounds.x+bounds.width > maxx )
|
||||||
|
maxx = bounds.x+bounds.width;
|
||||||
|
if( bounds.y+bounds.height > maxy )
|
||||||
|
maxy = bounds.y+bounds.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateAnchor(maxx-minx, maxy-miny, anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public java.awt.Shape getShape() {
|
||||||
|
Path2D.Double gruppe = new Path2D.Double();
|
||||||
|
for( Shape pShape : shapes ) {
|
||||||
|
gruppe.append(pShape.getShape(), false);
|
||||||
|
}
|
||||||
|
return gruppe;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||||
|
if( !visible ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AffineTransform verzerrung = new AffineTransform();
|
||||||
|
verzerrung.translate(x, y);
|
||||||
|
verzerrung.rotate(Math.toRadians(rotation));
|
||||||
|
//verzerrung.scale(skalierung, skalierung);
|
||||||
|
verzerrung.translate(-anchor.x, -anchor.y);
|
||||||
|
|
||||||
|
for( Shape f: shapes ) {
|
||||||
|
AffineTransform af = f.getTransform();
|
||||||
|
af.preConcatenate(verzerrung);
|
||||||
|
f.draw(graphics, af);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
69
src/schule/ngb/zm/formen/ShapesLayer.java
Normal file
69
src/schule/ngb/zm/formen/ShapesLayer.java
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Layer;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
|
||||||
|
public class ShapesLayer extends Layer {
|
||||||
|
|
||||||
|
protected boolean clearBeforeDraw = true;
|
||||||
|
|
||||||
|
private LinkedList<Shape> formen;
|
||||||
|
|
||||||
|
public ShapesLayer() {
|
||||||
|
super();
|
||||||
|
formen = new LinkedList<Shape>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ShapesLayer( int width, int height ) {
|
||||||
|
super(width, height);
|
||||||
|
formen = new LinkedList<Shape>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add( Shape... pFormen ) {
|
||||||
|
synchronized( formen ) {
|
||||||
|
for( Shape f : pFormen ) {
|
||||||
|
formen.add(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void showAll() {
|
||||||
|
synchronized( formen ) {
|
||||||
|
for( Shape pShape : formen ) {
|
||||||
|
pShape.hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void hideAll() {
|
||||||
|
synchronized( formen ) {
|
||||||
|
for( Shape pShape : formen ) {
|
||||||
|
pShape.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public java.util.List<Shape> getShapes() {
|
||||||
|
return formen;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void draw( Graphics2D pGraphics ) {
|
||||||
|
if( clearBeforeDraw ) {
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized( formen ) {
|
||||||
|
for( Shape pShape : formen ) {
|
||||||
|
if( pShape.isVisible() ) {
|
||||||
|
pShape.draw(drawing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.draw(pGraphics);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
104
src/schule/ngb/zm/formen/StrokedShape.java
Normal file
104
src/schule/ngb/zm/formen/StrokedShape.java
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Color;
|
||||||
|
import schule.ngb.zm.Constants;
|
||||||
|
import schule.ngb.zm.Drawable;
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
|
||||||
|
public abstract class StrokedShape extends Constants implements Drawable {
|
||||||
|
|
||||||
|
protected Color strokeColor = STD_STROKECOLOR;
|
||||||
|
|
||||||
|
protected double strokeWeight = STD_STROKEWEIGHT;
|
||||||
|
|
||||||
|
protected Options.StrokeType strokeType = SOLID;
|
||||||
|
|
||||||
|
public Color getStrokeColor() {
|
||||||
|
return strokeColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( Color color ) {
|
||||||
|
this.strokeColor = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray ) {
|
||||||
|
setStrokeColor(gray, gray, gray, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void noStroke() {
|
||||||
|
strokeColor = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int gray, int alpha ) {
|
||||||
|
setStrokeColor(gray, gray, gray, alpha);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue ) {
|
||||||
|
setStrokeColor(red, green, blue, 255);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeColor( int red, int green, int blue, int alpha ) {
|
||||||
|
setStrokeColor(new Color(red, green, blue, alpha));
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getStrokeWeight() {
|
||||||
|
return strokeWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStrokeWeight( double weight ) {
|
||||||
|
this.strokeWeight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options.StrokeType getStrokeType() {
|
||||||
|
return strokeType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setzt den Typ der Kontur. Erlaubte Werte sind {@link #DASHED},
|
||||||
|
* {@link #DOTTED} und {@link #SOLID}.
|
||||||
|
* @param type
|
||||||
|
*/
|
||||||
|
public void setStrokeType( Options.StrokeType type ) {
|
||||||
|
this.strokeType = DASHED;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void draw( Graphics2D graphics );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein {@link Stroke} Objekt für den Konturtyp.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected Stroke createStroke() {
|
||||||
|
switch( strokeType ) {
|
||||||
|
case DOTTED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{1.0f, 5.0f}, 0.0f);
|
||||||
|
case DASHED:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND,
|
||||||
|
10.0f, new float[]{5.0f}, 0.0f);
|
||||||
|
case SOLID:
|
||||||
|
default:
|
||||||
|
return new BasicStroke(
|
||||||
|
(float) strokeWeight,
|
||||||
|
BasicStroke.CAP_ROUND,
|
||||||
|
BasicStroke.JOIN_ROUND);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetStroke() {
|
||||||
|
setStrokeColor(STD_STROKECOLOR);
|
||||||
|
setStrokeWeight(STD_STROKEWEIGHT);
|
||||||
|
setStrokeType(SOLID);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,56 +1,56 @@
|
|||||||
package schule.ngb.zm.formen;
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import schule.ngb.zm.Options;
|
||||||
|
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
import java.awt.geom.AffineTransform;
|
import java.awt.geom.AffineTransform;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
|
||||||
public class Text extends Form {
|
public class Text extends Shape {
|
||||||
|
|
||||||
private static final int DFT_FONT_SIZE = 14;
|
|
||||||
|
|
||||||
protected String text;
|
protected String text;
|
||||||
|
|
||||||
protected Font schriftart;
|
protected Font font;
|
||||||
|
|
||||||
protected int breite = 0, hoehe = 0, ascent = 0;
|
protected int width = 0, height = 0, ascent = 0;
|
||||||
|
|
||||||
public Text( double pX, double pY, String pText ) {
|
public Text( double x, double y, String text ) {
|
||||||
super(pX, pY);
|
super(x, y);
|
||||||
schriftart = new Font(Font.SANS_SERIF, Font.PLAIN, DFT_FONT_SIZE);
|
font = new Font(Font.SANS_SERIF, Font.PLAIN, STD_FONTSIZE);
|
||||||
setText(pText);
|
setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Text( Text pText ) {
|
public Text( Text text ) {
|
||||||
super(pText.getX(), pText.getY());
|
super(text.getX(), text.getY());
|
||||||
kopiere(pText);
|
copyFrom(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Form kopie() {
|
public Shape copy() {
|
||||||
return new Text(this);
|
return new Text(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void kopiere( Form pForm ) {
|
public void copyFrom( Shape shape ) {
|
||||||
super.kopiere(pForm);
|
super.copyFrom(shape);
|
||||||
if( pForm instanceof Text ) {
|
if( shape instanceof Text ) {
|
||||||
Text pText = (Text)pForm;
|
Text pText = (Text) shape;
|
||||||
this.text = pText.getText();
|
this.text = pText.getText();
|
||||||
this.schriftart = pText.getSchriftart();
|
this.font = pText.getFont();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void skalieren( double pFaktor ) {
|
public void scale( double factor ) {
|
||||||
super.skalieren(pFaktor);
|
super.scale(factor);
|
||||||
setSchriftgroesse(schriftart.getSize2D()*pFaktor);
|
setFontsize(font.getSize2D() * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Font getSchriftart() {
|
public Font getFont() {
|
||||||
return schriftart;
|
return font;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSchriftgroesse( double pGroesse ) {
|
public void setFontsize( double size ) {
|
||||||
schriftart = schriftart.deriveFont((float)pGroesse);
|
font = font.deriveFont((float) size);
|
||||||
setText(text);
|
setText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,34 +62,34 @@ public class Text extends Form {
|
|||||||
text = pText;
|
text = pText;
|
||||||
|
|
||||||
Canvas metricsCanvas = new Canvas();
|
Canvas metricsCanvas = new Canvas();
|
||||||
FontMetrics metrics = metricsCanvas.getFontMetrics(schriftart);
|
FontMetrics metrics = metricsCanvas.getFontMetrics(font);
|
||||||
breite = metrics.stringWidth(text);
|
width = metrics.stringWidth(text);
|
||||||
hoehe = metrics.getDescent() + metrics.getAscent();
|
height = metrics.getDescent() + metrics.getAscent();
|
||||||
ascent = metrics.getAscent();
|
ascent = metrics.getAscent();
|
||||||
|
|
||||||
setAnkerpunkt(ZENTRUM);
|
setAnchor(CENTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getBreite() {
|
public double getWidth() {
|
||||||
return breite;
|
return width;
|
||||||
}
|
}
|
||||||
|
|
||||||
public double getHoehe() {
|
public double getHeight() {
|
||||||
return hoehe;
|
return height;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAnkerpunkt( byte pAnker ) {
|
public void setAnchor( Options.Direction anchor ) {
|
||||||
ankerBerechnen(breite, ascent - hoehe, pAnker);
|
calculateAnchor(width, ascent - height, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape getShape() {
|
public java.awt.Shape getShape() {
|
||||||
return new Rectangle2D.Double(0, 0, breite, hoehe);
|
return new Rectangle2D.Double(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||||
if( !sichtbar ) {
|
if( !visible ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,11 +99,11 @@ public class Text extends Form {
|
|||||||
AffineTransform af = graphics.getTransform();
|
AffineTransform af = graphics.getTransform();
|
||||||
|
|
||||||
// Neue Werte setzen
|
// Neue Werte setzen
|
||||||
graphics.setFont(schriftart);
|
graphics.setFont(font);
|
||||||
graphics.setColor(konturFarbe);
|
graphics.setColor(strokeColor.getColor());
|
||||||
graphics.transform(getVerzerrung());
|
graphics.transform(pVerzerrung);
|
||||||
|
|
||||||
// Text zeichnen
|
// Draw text
|
||||||
FontMetrics fm = graphics.getFontMetrics();
|
FontMetrics fm = graphics.getFontMetrics();
|
||||||
//graphics.drawString(text, (float) (x - fm.stringWidth(text)/2.0), (float) (y + fm.getDescent()));
|
//graphics.drawString(text, (float) (x - fm.stringWidth(text)/2.0), (float) (y + fm.getDescent()));
|
||||||
graphics.drawString(text, 0, 0);
|
graphics.drawString(text, 0, 0);
|
||||||
@@ -121,13 +121,15 @@ public class Text extends Form {
|
|||||||
Text text = (Text) o;
|
Text text = (Text) o;
|
||||||
return super.equals(o) &&
|
return super.equals(o) &&
|
||||||
text.equals(text.text) &&
|
text.equals(text.text) &&
|
||||||
schriftart.equals(text.schriftart);
|
font.equals(text.font);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return getClass().getCanonicalName() + "[" +
|
return getClass().getCanonicalName() + "[" +
|
||||||
"text=" + text +
|
"text=" + text + ',' +
|
||||||
|
"font=" + font.getName() + ',' +
|
||||||
|
"size=" + font.getSize() +
|
||||||
']';
|
']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
36
src/schule/ngb/zm/formen/Triangle.java
Normal file
36
src/schule/ngb/zm/formen/Triangle.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package schule.ngb.zm.formen;
|
||||||
|
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class Triangle extends Polygon {
|
||||||
|
|
||||||
|
public Triangle( double x, double y, Point2D... points ) {
|
||||||
|
super(x, y, Arrays.copyOf(points, 3));
|
||||||
|
if( points.length < 3 ) {
|
||||||
|
throw new IllegalArgumentException("A triangle requires exactly three points.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Triangle( Point2D... points ) {
|
||||||
|
super(Arrays.copyOf(points, 3));
|
||||||
|
if( points.length < 3 ) {
|
||||||
|
throw new IllegalArgumentException("A triangle requires exactly three points.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Triangle( double x1, double y1, double x2, double y2, double x3, double y3 ) {
|
||||||
|
super(x1, y1, x2, y2, x3, y3);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Triangle( Triangle triangle ) {
|
||||||
|
super(triangle.x, triangle.y);
|
||||||
|
copyFrom(triangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Shape copy() {
|
||||||
|
return new Triangle(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Vieleck extends Form {
|
|
||||||
|
|
||||||
protected Point2D[] ecken;
|
|
||||||
|
|
||||||
public Vieleck( double pX, double pY, Point2D... pEcken ) {
|
|
||||||
super(pX, pY);
|
|
||||||
|
|
||||||
ecken = new Point2D[pEcken.length];
|
|
||||||
for( int i = 0; i < pEcken.length; i++ ) {
|
|
||||||
ecken[i] = new Point2D.Double(pEcken[i].getX()-pX, pEcken[i].getY()-pY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vieleck( Point2D... pEcken ) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
ecken = new Point2D[pEcken.length];
|
|
||||||
for( int i = 0; i < pEcken.length; i++ ) {
|
|
||||||
if( i == 0 ) {
|
|
||||||
x = pEcken[i].getX();
|
|
||||||
y = pEcken[i].getY();
|
|
||||||
}
|
|
||||||
ecken[i] = new Point2D.Double(pEcken[i].getX()-x, pEcken[i].getY()-y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vieleck( Vieleck pVieleck ) {
|
|
||||||
this(pVieleck.x, pVieleck.y);
|
|
||||||
kopiere(pVieleck);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Point2D[] getEcken() {
|
|
||||||
return ecken;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void kopiere( Form pForm ) {
|
|
||||||
super.kopiere(pForm);
|
|
||||||
if( pForm instanceof Vieleck ) {
|
|
||||||
Vieleck v = (Vieleck) pForm;
|
|
||||||
|
|
||||||
ecken = new Point2D[v.ecken.length];
|
|
||||||
for( int i = 0; i < v.ecken.length; i++ ) {
|
|
||||||
ecken[i] = new Point2D.Double(v.ecken[i].getX(), v.ecken[i].getY());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Vieleck(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Shape getShape() {
|
|
||||||
Path2D shape = new Path2D.Double();
|
|
||||||
shape.moveTo(ecken[0].getX(), ecken[0].getY());
|
|
||||||
for( int i = 1; i < ecken.length; i++ ) {
|
|
||||||
shape.lineTo(ecken[i].getX(), ecken[i].getY());
|
|
||||||
}
|
|
||||||
shape.closePath();
|
|
||||||
return shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package schule.ngb.zm.formen;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.geom.Path2D;
|
|
||||||
import java.awt.geom.Point2D;
|
|
||||||
import java.util.Arrays;
|
|
||||||
|
|
||||||
public class Viereck extends Vieleck {
|
|
||||||
|
|
||||||
public Viereck( double pX, double pY, Point2D... pEcken ) {
|
|
||||||
super(pX, pY, Arrays.copyOf(pEcken, 4));
|
|
||||||
if( pEcken.length < 4 ) {
|
|
||||||
throw new IllegalArgumentException("Ein Viereck muss genau vier Eckpunkte besitzen.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Viereck( Point2D... pEcken ) {
|
|
||||||
super(Arrays.copyOf(pEcken, 4));
|
|
||||||
if( pEcken.length < 4 ) {
|
|
||||||
throw new IllegalArgumentException("Ein Viereck muss genau vier Eckpunkte besitzen.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Viereck( Viereck pViereck ) {
|
|
||||||
super(pViereck.x, pViereck.y);
|
|
||||||
kopiere(pViereck);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Form kopie() {
|
|
||||||
return new Viereck(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
141
src/schule/ngb/zm/util/ImageLoader.java
Normal file
141
src/schule/ngb/zm/util/ImageLoader.java
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
package schule.ngb.zm.util;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
public class ImageLoader {
|
||||||
|
|
||||||
|
public static boolean cacheing = true;
|
||||||
|
|
||||||
|
private static HashMap<String, BufferedImage> imageCache = new HashMap<>();
|
||||||
|
|
||||||
|
public static BufferedImage loadImage( String source ) {
|
||||||
|
return loadImage(source, cacheing);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Läadt ein Bild von der angegebenen Quelle <var>source</var> und gibt das
|
||||||
|
* Bild zurück oder <code>null</code>, wenn das Bild nicht geladen werden
|
||||||
|
* konnte. Ist ein Bild mit der angegebenen Quelle im Cache, wird das
|
||||||
|
* gechachete Bild zurückgegeben. Dies kann mit <code>cacheing = false</code>
|
||||||
|
* verhindert werden.
|
||||||
|
* <p>
|
||||||
|
* Wurde chacheing global deaktiviert, kann mit <code>cacheing = true</code>
|
||||||
|
* das Bild trotzdem aus dem Cache geladen werden, wenn es vorhanden ist.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
* @param cacheing
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static BufferedImage loadImage( String source, boolean cacheing ) {
|
||||||
|
if( source == null || source.length() == 0 )
|
||||||
|
throw new IllegalArgumentException("Image source may not be null or empty.");
|
||||||
|
|
||||||
|
if( cacheing && imageCache.containsKey(source) ) {
|
||||||
|
BufferedImage cachedImage = imageCache.get(source);
|
||||||
|
if( cachedImage != null ) {
|
||||||
|
return cachedImage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
BufferedImage img;
|
||||||
|
|
||||||
|
// Load image from working dir
|
||||||
|
File file = new File(source);
|
||||||
|
if( file.isFile() ) {
|
||||||
|
img = ImageIO.read(file);
|
||||||
|
} else {
|
||||||
|
// load ressource relative to .class-file
|
||||||
|
URL url = ImageLoader.class.getResource(source);
|
||||||
|
|
||||||
|
// relative to ClassLoader
|
||||||
|
if( url == null ) {
|
||||||
|
url = ImageLoader.class.getClassLoader().getResource(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
// load form web or jar-file
|
||||||
|
if( url == null ) {
|
||||||
|
url = new URL(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
img = ImageIO.read(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cacheing && img != null ) {
|
||||||
|
imageCache.put(source, img);
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
} catch( IOException ioe ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads an image into the cache with a user specified name that may differ
|
||||||
|
* from the image source string.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @param source
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean preloadImage( String name, String source ) {
|
||||||
|
BufferedImage img = loadImage(source, true);
|
||||||
|
if( cacheing && img != null ) {
|
||||||
|
imageCache.put(name, img);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an image with the given name is currently cached.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isCached( String name ) {
|
||||||
|
if( imageCache.containsKey(name) ) {
|
||||||
|
return imageCache.get(name) != null;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified key from the cache.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
public static void invalidateCache( String name ) {
|
||||||
|
if( imageCache.containsKey(name) ) {
|
||||||
|
imageCache.remove(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prevents caching for the specified source.
|
||||||
|
*
|
||||||
|
* @param source
|
||||||
|
*/
|
||||||
|
public static void noCache( String source ) {
|
||||||
|
imageCache.put(source, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearCache() {
|
||||||
|
imageCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void enableCaching() {
|
||||||
|
cacheing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void disableCaching() {
|
||||||
|
cacheing = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
349
src/schule/ngb/zm/util/List.java
Normal file
349
src/schule/ngb/zm/util/List.java
Normal file
@@ -0,0 +1,349 @@
|
|||||||
|
package schule.ngb.zm.util;
|
||||||
|
|
||||||
|
import javax.swing.text.AbstractDocument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Materialien zu den zentralen NRW-Abiturpruefungen im Fach Informatik ab 2018
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Generische Klasse List<ContentType>
|
||||||
|
* </p>
|
||||||
|
* <p>
|
||||||
|
* Objekt der generischen Klasse List verwalten beliebig viele linear
|
||||||
|
* angeordnete Objekte vom Typ ContentType. Auf hoechstens ein Listenobjekt,
|
||||||
|
* aktuellesObjekt genannt, kann jeweils zugegriffen werden.<br />
|
||||||
|
* Wenn eine Liste leer ist, vollstaendig durchlaufen wurde oder das aktuelle
|
||||||
|
* Objekt am Ende der Liste geloescht wurde, gibt es kein aktuelles Objekt.<br />
|
||||||
|
* Das erste oder das letzte Objekt einer Liste koennen durch einen Auftrag zum
|
||||||
|
* aktuellen Objekt gemacht werden. Ausserdem kann das dem aktuellen Objekt
|
||||||
|
* folgende Listenobjekt zum neuen aktuellen Objekt werden. <br />
|
||||||
|
* Das aktuelle Objekt kann gelesen, veraendert oder geloescht werden. Ausserdem
|
||||||
|
* kann vor dem aktuellen Objekt ein Listenobjekt eingefuegt werden.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Qualitaets- und UnterstuetzungsAgentur - Landesinstitut fuer Schule
|
||||||
|
* @version Generisch_06 2015-10-25
|
||||||
|
*/
|
||||||
|
public class List<ContentType> {
|
||||||
|
|
||||||
|
/* --------- Anfang der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
private class ListNode {
|
||||||
|
|
||||||
|
private ContentType contentObject;
|
||||||
|
private ListNode next;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ein neues Objekt wird erschaffen. Der Verweis ist leer.
|
||||||
|
*
|
||||||
|
* @param pContent das Inhaltsobjekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
private ListNode(ContentType pContent) {
|
||||||
|
contentObject = pContent;
|
||||||
|
next = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Inhalt des Knotens wird zurueckgeliefert.
|
||||||
|
*
|
||||||
|
* @return das Inhaltsobjekt des Knotens
|
||||||
|
*/
|
||||||
|
public ContentType getContentObject() {
|
||||||
|
return contentObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Inhalt dieses Kontens wird gesetzt.
|
||||||
|
*
|
||||||
|
* @param pContent das Inhaltsobjekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void setContentObject(ContentType pContent) {
|
||||||
|
contentObject = pContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Nachfolgeknoten wird zurueckgeliefert.
|
||||||
|
*
|
||||||
|
* @return das Objekt, auf das der aktuelle Verweis zeigt
|
||||||
|
*/
|
||||||
|
public ListNode getNextNode() {
|
||||||
|
return this.next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Der Verweis wird auf das Objekt, das als Parameter uebergeben
|
||||||
|
* wird, gesetzt.
|
||||||
|
*
|
||||||
|
* @param pNext der Nachfolger des Knotens
|
||||||
|
*/
|
||||||
|
public void setNextNode(ListNode pNext) {
|
||||||
|
this.next = pNext;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------- Ende der privaten inneren Klasse -------------- */
|
||||||
|
|
||||||
|
// erstes Element der Liste
|
||||||
|
ListNode first;
|
||||||
|
|
||||||
|
// letztes Element der Liste
|
||||||
|
ListNode last;
|
||||||
|
|
||||||
|
// aktuelles Element der Liste
|
||||||
|
ListNode current;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Eine leere Liste wird erzeugt.
|
||||||
|
*/
|
||||||
|
public List() {
|
||||||
|
first = null;
|
||||||
|
last = null;
|
||||||
|
current = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert den Wert true, wenn die Liste keine Objekte enthaelt,
|
||||||
|
* sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, wenn die Liste leer ist, sonst false
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
// Die Liste ist leer, wenn es kein erstes Element gibt.
|
||||||
|
return first == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Anfrage liefert den Wert true, wenn es ein aktuelles Objekt gibt,
|
||||||
|
* sonst liefert sie den Wert false.
|
||||||
|
*
|
||||||
|
* @return true, falls Zugriff moeglich, sonst false
|
||||||
|
*/
|
||||||
|
public boolean hasAccess() {
|
||||||
|
// Es gibt keinen Zugriff, wenn current auf kein Element verweist.
|
||||||
|
return current != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, es ein aktuelles Objekt gibt und dieses
|
||||||
|
* nicht das letzte Objekt der Liste ist, wird das dem aktuellen Objekt in
|
||||||
|
* der Liste folgende Objekt zum aktuellen Objekt, andernfalls gibt es nach
|
||||||
|
* Ausfuehrung des Auftrags kein aktuelles Objekt, d.h. hasAccess() liefert
|
||||||
|
* den Wert false.
|
||||||
|
*/
|
||||||
|
public void next() {
|
||||||
|
if (this.hasAccess()) {
|
||||||
|
current = current.getNextNode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, wird das erste Objekt der Liste aktuelles
|
||||||
|
* Objekt. Ist die Liste leer, geschieht nichts.
|
||||||
|
*/
|
||||||
|
public void toFirst() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
current = first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls die Liste nicht leer ist, wird das letzte Objekt der Liste
|
||||||
|
* aktuelles Objekt. Ist die Liste leer, geschieht nichts.
|
||||||
|
*/
|
||||||
|
public void toLast() {
|
||||||
|
if (!isEmpty()) {
|
||||||
|
current = last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
|
||||||
|
* aktuelle Objekt zurueckgegeben, andernfalls (hasAccess() == false) gibt
|
||||||
|
* die Anfrage den Wert null zurueck.
|
||||||
|
*
|
||||||
|
* @return das aktuelle Objekt (vom Typ ContentType) oder null, wenn es
|
||||||
|
* kein aktuelles Objekt gibt
|
||||||
|
*/
|
||||||
|
public ContentType getContent() {
|
||||||
|
if (this.hasAccess()) {
|
||||||
|
return current.getContentObject();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true) und pContent
|
||||||
|
* ungleich null ist, wird das aktuelle Objekt durch pContent ersetzt. Sonst
|
||||||
|
* geschieht nichts.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das zu schreibende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void setContent(ContentType pContent) {
|
||||||
|
// Nichts tun, wenn es keinen Inhalt oder kein aktuelles Element gibt.
|
||||||
|
if (pContent != null && this.hasAccess()) {
|
||||||
|
current.setContentObject(pContent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird ein neues
|
||||||
|
* Objekt vor dem aktuellen Objekt in die Liste eingefuegt. Das aktuelle
|
||||||
|
* Objekt bleibt unveraendert. <br />
|
||||||
|
* Wenn die Liste leer ist, wird pContent in die Liste eingefuegt und es
|
||||||
|
* gibt weiterhin kein aktuelles Objekt (hasAccess() == false). <br />
|
||||||
|
* Falls es kein aktuelles Objekt gibt (hasAccess() == false) und die Liste
|
||||||
|
* nicht leer ist oder pContent gleich null ist, geschieht nichts.
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das einzufuegende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void insert(ContentType pContent) {
|
||||||
|
if (pContent != null) { // Nichts tun, wenn es keinen Inhalt gibt.
|
||||||
|
if (this.hasAccess()) { // Fall: Es gibt ein aktuelles Element.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
if (current != first) { // Fall: Nicht an erster Stelle einfuegen.
|
||||||
|
ListNode previous = this.getPrevious(current);
|
||||||
|
newNode.setNextNode(previous.getNextNode());
|
||||||
|
previous.setNextNode(newNode);
|
||||||
|
} else { // Fall: An erster Stelle einfuegen.
|
||||||
|
newNode.setNextNode(first);
|
||||||
|
first = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else { //Fall: Es gibt kein aktuelles Element.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: In leere Liste einfuegen.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
first = newNode;
|
||||||
|
last = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls pContent gleich null ist, geschieht nichts.<br />
|
||||||
|
* Ansonsten wird ein neues Objekt pContent am Ende der Liste eingefuegt.
|
||||||
|
* Das aktuelle Objekt bleibt unveraendert. <br />
|
||||||
|
* Wenn die Liste leer ist, wird das Objekt pContent in die Liste eingefuegt
|
||||||
|
* und es gibt weiterhin kein aktuelles Objekt (hasAccess() == false).
|
||||||
|
*
|
||||||
|
* @param pContent
|
||||||
|
* das anzuhaengende Objekt vom Typ ContentType
|
||||||
|
*/
|
||||||
|
public void append(ContentType pContent) {
|
||||||
|
if (pContent != null) { // Nichts tun, wenn es keine Inhalt gibt.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: An leere Liste anfuegen.
|
||||||
|
this.insert(pContent);
|
||||||
|
} else { // Fall: An nicht-leere Liste anfuegen.
|
||||||
|
|
||||||
|
// Neuen Knoten erstellen.
|
||||||
|
ListNode newNode = new ListNode(pContent);
|
||||||
|
|
||||||
|
last.setNextNode(newNode);
|
||||||
|
last = newNode; // Letzten Knoten aktualisieren.
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls es sich bei der Liste und pList um dasselbe Objekt handelt,
|
||||||
|
* pList null oder eine leere Liste ist, geschieht nichts.<br />
|
||||||
|
* Ansonsten wird die Liste pList an die aktuelle Liste angehaengt.
|
||||||
|
* Anschliessend wird pList eine leere Liste. Das aktuelle Objekt bleibt
|
||||||
|
* unveraendert. Insbesondere bleibt hasAccess identisch.
|
||||||
|
*
|
||||||
|
* @param pList
|
||||||
|
* die am Ende anzuhaengende Liste vom Typ List<ContentType>
|
||||||
|
*/
|
||||||
|
public void concat(List<ContentType> pList) {
|
||||||
|
if (pList != this && pList != null && !pList.isEmpty()) { // Nichts tun,
|
||||||
|
// wenn pList und this identisch, pList leer oder nicht existent.
|
||||||
|
|
||||||
|
if (this.isEmpty()) { // Fall: An leere Liste anfuegen.
|
||||||
|
this.first = pList.first;
|
||||||
|
this.last = pList.last;
|
||||||
|
} else { // Fall: An nicht-leere Liste anfuegen.
|
||||||
|
this.last.setNextNode(pList.first);
|
||||||
|
this.last = pList.last;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Liste pList loeschen.
|
||||||
|
pList.first = null;
|
||||||
|
pList.last = null;
|
||||||
|
pList.current = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wenn die Liste leer ist oder es kein aktuelles Objekt gibt (hasAccess()
|
||||||
|
* == false), geschieht nichts.<br />
|
||||||
|
* Falls es ein aktuelles Objekt gibt (hasAccess() == true), wird das
|
||||||
|
* aktuelle Objekt geloescht und das Objekt hinter dem geloeschten Objekt
|
||||||
|
* wird zum aktuellen Objekt. <br />
|
||||||
|
* Wird das Objekt, das am Ende der Liste steht, geloescht, gibt es kein
|
||||||
|
* aktuelles Objekt mehr.
|
||||||
|
*/
|
||||||
|
public void remove() {
|
||||||
|
// Nichts tun, wenn es kein aktuelle Element gibt oder die Liste leer ist.
|
||||||
|
if (this.hasAccess() && !this.isEmpty()) {
|
||||||
|
|
||||||
|
if (current == first) {
|
||||||
|
first = first.getNextNode();
|
||||||
|
} else {
|
||||||
|
ListNode previous = this.getPrevious(current);
|
||||||
|
if (current == last) {
|
||||||
|
last = previous;
|
||||||
|
}
|
||||||
|
previous.setNextNode(current.getNextNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
ListNode temp = current.getNextNode();
|
||||||
|
current.setContentObject(null);
|
||||||
|
current.setNextNode(null);
|
||||||
|
current = temp;
|
||||||
|
|
||||||
|
//Beim loeschen des letzten Elements last auf null setzen.
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
last = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert den Vorgaengerknoten des Knotens pNode. Ist die Liste leer, pNode
|
||||||
|
* == null, pNode nicht in der Liste oder pNode der erste Knoten der Liste,
|
||||||
|
* wird null zurueckgegeben.
|
||||||
|
*
|
||||||
|
* @param pNode
|
||||||
|
* der Knoten, dessen Vorgaenger zurueckgegeben werden soll
|
||||||
|
* @return der Vorgaenger des Knotens pNode oder null, falls die Liste leer ist,
|
||||||
|
* pNode == null ist, pNode nicht in der Liste ist oder pNode der erste Knoten
|
||||||
|
* der Liste ist
|
||||||
|
*/
|
||||||
|
private ListNode getPrevious(ListNode pNode) {
|
||||||
|
if (pNode != null && pNode != first && !this.isEmpty()) {
|
||||||
|
ListNode temp = first;
|
||||||
|
while (temp != null && temp.getNextNode() != pNode) {
|
||||||
|
temp = temp.getNextNode();
|
||||||
|
}
|
||||||
|
return temp;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user