Merge branch 'main' into turtle
This commit is contained in:
commit
271b65bce1
|
@ -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()));
|
||||
}
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
* 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
|
||||
|
@ -14,11 +14,11 @@ public interface Zeichenbar {
|
|||
*
|
||||
* @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>
|
||||
* zu zeichnen.
|
||||
* zu draw.
|
||||
* <p>
|
||||
* Das Objekt muss dafür Sorge tragen, dass der Zustand der Zeichenfläche
|
||||
* (Transformationsmatrix, Farbe, ...) erhalten bleibt. Das Objekt sollte
|
||||
|
@ -26,6 +26,6 @@ public interface Zeichenbar {
|
|||
*
|
||||
* @param graphics Die Zeichenfläche.
|
||||
*/
|
||||
public void zeichnen( Graphics2D graphics );
|
||||
void draw( Graphics2D graphics );
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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
|
||||
* 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.
|
||||
*/
|
||||
public interface Aktualisierbar {
|
||||
public interface Updatable {
|
||||
|
||||
/**
|
||||
* Gibt an, ob das Objekt gerade auf Aktualisierungen reagiert.
|
||||
* @return <code>true</code>, wenn das Objekt aktiv ist.
|
||||
*/
|
||||
public boolean istAktiv();
|
||||
public boolean isActive();
|
||||
|
||||
/**
|
||||
* Änderung des Zustandes des Objekts abhängig vom Zeitintervall
|
||||
* <var>delta</var> in Sekunden.
|
||||
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
|
||||
*/
|
||||
public void aktualisieren( double delta );
|
||||
public void update( double delta );
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,313 +1,6 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.Formenebene;
|
||||
// TODO: Auslagern des Frames in diese Klasse (Trennung Swing-GUI/Canvas, Zeichenmaschine und Drawing-Thread)
|
||||
public class Zeichenfenster {
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.MouseInputListener;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class Zeichenfenster extends Konstanten implements Runnable, MouseInputListener, KeyListener {
|
||||
|
||||
protected Object mouseLock = new Object();
|
||||
/*
|
||||
* Attribute für den Zugriff aus Unterklassen.
|
||||
*/
|
||||
protected Leinwand leinwand;
|
||||
protected Zeichenebene zeichnung;
|
||||
protected Formenebene formen;
|
||||
protected int tick = 0;
|
||||
protected long laufzeit = 0L;
|
||||
protected double delta = 0.0;
|
||||
protected double mausX = 0.0, mausY = 0.0, lmausX = 0.0, lmausY = 0.0;
|
||||
protected int breite = STD_BREITE, hoehe = STD_HOEHE;
|
||||
/*
|
||||
* Interne Attribute zur Steuerung der Zeichenamschine.
|
||||
*/
|
||||
//
|
||||
private JFrame frame;
|
||||
private boolean running = false;
|
||||
private int framesPerSecond;
|
||||
|
||||
public Zeichenfenster() {
|
||||
this(APP_NAME);
|
||||
}
|
||||
|
||||
public Zeichenfenster( String pTitel ) {
|
||||
this(STD_BREITE, STD_HOEHE, pTitel);
|
||||
}
|
||||
|
||||
public Zeichenfenster( int pBreite, int pHoehe, String pTitel ) {
|
||||
frame = new JFrame(pTitel);
|
||||
|
||||
try {
|
||||
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||
} catch( Exception e ) {
|
||||
System.err.println("Fehler beim Setzen des look and feel.");
|
||||
}
|
||||
|
||||
breite = pBreite;
|
||||
hoehe = pHoehe;
|
||||
|
||||
frame.setResizable(false);
|
||||
frame.setLocationRelativeTo(null);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
leinwand = new Leinwand(pBreite, pHoehe);
|
||||
frame.setContentPane(leinwand);
|
||||
|
||||
framesPerSecond = STD_FPS;
|
||||
|
||||
zeichnung = getZeichenEbene();
|
||||
formen = getFormenEbene();
|
||||
|
||||
einstellungen();
|
||||
|
||||
frame.addMouseListener(this);
|
||||
frame.addMouseMotionListener(this);
|
||||
frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing( WindowEvent e ) {
|
||||
running = false;
|
||||
super.windowClosing(e);
|
||||
}
|
||||
});
|
||||
|
||||
frame.pack();
|
||||
frame.requestFocusInWindow();
|
||||
frame.setVisible(true);
|
||||
|
||||
running = true;
|
||||
new Thread(this).start();
|
||||
}
|
||||
|
||||
public final void setSize( int pWidth, int pHeight ) {
|
||||
//frame.setSize(pWidth, pHeight);
|
||||
|
||||
if( leinwand != null ) {
|
||||
leinwand.setSize(pWidth, pHeight);
|
||||
}
|
||||
breite = pWidth;
|
||||
hoehe = pHeight;
|
||||
frame.pack();
|
||||
}
|
||||
|
||||
public final int getBreite() {
|
||||
return breite;
|
||||
}
|
||||
|
||||
public final int getHoehe() {
|
||||
return hoehe;
|
||||
}
|
||||
|
||||
public final void setTitel( String pTitel ) {
|
||||
frame.setTitle(pTitel);
|
||||
}
|
||||
|
||||
public final Leinwand getLeinwand() {
|
||||
return leinwand;
|
||||
}
|
||||
|
||||
public final void hinzu( Ebene pEbene ) {
|
||||
leinwand.hinzu(pEbene);
|
||||
}
|
||||
|
||||
public final Zeichenebene getZeichenEbene() {
|
||||
Zeichenebene layer = leinwand.getEbene(Zeichenebene.class);
|
||||
if( layer == null ) {
|
||||
layer = new Zeichenebene(getBreite(), getHoehe());
|
||||
leinwand.hinzu(0, layer);
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
public final Formenebene getFormenEbene() {
|
||||
Formenebene layer = leinwand.getEbene(Formenebene.class);
|
||||
if( layer == null ) {
|
||||
layer = new Formenebene(getBreite(), getHoehe());
|
||||
leinwand.hinzu(layer);
|
||||
}
|
||||
return layer;
|
||||
}
|
||||
|
||||
public final int getFramesPerSecond() {
|
||||
return framesPerSecond;
|
||||
}
|
||||
|
||||
public final void setFramesPerSecond( int pFramesPerSecond ) {
|
||||
framesPerSecond = pFramesPerSecond;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void run() {
|
||||
long start = System.currentTimeMillis();
|
||||
long current = System.nanoTime();
|
||||
int _tick = 0;
|
||||
long _runtime = 0;
|
||||
tick = 0;
|
||||
laufzeit = 0;
|
||||
|
||||
vorbereiten();
|
||||
|
||||
while( running ) {
|
||||
int dt = (int) ((System.nanoTime() - current) / 1E6);
|
||||
current = System.nanoTime();
|
||||
delta = (dt / 1000.0);
|
||||
|
||||
saveMousePosition();
|
||||
|
||||
aktualisieren(delta);
|
||||
zeichnen();
|
||||
|
||||
if( leinwand != null ) {
|
||||
//drawing.invalidate();
|
||||
frame.repaint();
|
||||
}
|
||||
|
||||
try {
|
||||
int sleep = Math.round(1000 / framesPerSecond);
|
||||
if( dt >= sleep ) {
|
||||
sleep -= dt % sleep;
|
||||
}
|
||||
Thread.sleep(Math.max(0, sleep));
|
||||
} catch( InterruptedException e ) {
|
||||
// Interrupt not relevant
|
||||
} finally {
|
||||
_tick += 1;
|
||||
_runtime = System.currentTimeMillis() - start;
|
||||
tick = _tick;
|
||||
laufzeit = _runtime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Methoden, die von Unterklassen überschrieben werden können / sollen.
|
||||
*/
|
||||
public void einstellungen() {
|
||||
|
||||
}
|
||||
|
||||
public void vorbereiten() {
|
||||
|
||||
}
|
||||
|
||||
public void zeichnen() {
|
||||
|
||||
}
|
||||
|
||||
public void aktualisieren( double delta ) {
|
||||
running = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Mouse handling
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void mouseClicked( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
mausklick();
|
||||
}
|
||||
|
||||
public void mausklick() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
maustasteRunter();
|
||||
}
|
||||
|
||||
public void maustasteRunter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
maustasteHoch();
|
||||
}
|
||||
|
||||
public void maustasteHoch() {
|
||||
}
|
||||
|
||||
@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());
|
||||
mausGezogen();
|
||||
}
|
||||
|
||||
public void mausGezogen() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved( MouseEvent e ) {
|
||||
saveMousePosition(e.getPoint());
|
||||
mausBewegt();
|
||||
}
|
||||
|
||||
public void mausBewegt() {
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
lmausX = mausX;
|
||||
lmausY = mausY;
|
||||
|
||||
java.awt.Point mouseLoc = MouseInfo.getPointerInfo().getLocation();
|
||||
java.awt.Point compLoc = leinwand.getLocationOnScreen();
|
||||
mausX = mouseLoc.x - compLoc.x;
|
||||
mausY = mouseLoc.y - compLoc.y;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keyboard handling
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void keyTyped( KeyEvent e ) {
|
||||
tastendruck();
|
||||
}
|
||||
|
||||
public void tastendruck() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyPressed( KeyEvent e ) {
|
||||
tasteRunter();
|
||||
}
|
||||
|
||||
public void tasteRunter() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void keyReleased( KeyEvent e ) {
|
||||
tasteHoch();
|
||||
}
|
||||
|
||||
public void tasteHoch() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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 +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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] +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
import java.awt.*;
|
||||
import schule.ngb.zm.Options;
|
||||
|
||||
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 ) {
|
||||
super(pX, pY);
|
||||
breite = pBreite;
|
||||
hoehe = pHoehe;
|
||||
setAnkerpunkt(ZENTRUM);
|
||||
public Ellipse( double x, double y, double width, double height ) {
|
||||
super(x, y);
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
setAnchor(CENTER);
|
||||
}
|
||||
|
||||
public Ellipse( Ellipse pEllipse ) {
|
||||
this(pEllipse.x, pEllipse.y, pEllipse.breite, pEllipse.hoehe);
|
||||
kopiere(pEllipse);
|
||||
public Ellipse( Ellipse ellipse ) {
|
||||
this(ellipse.x, ellipse.y, ellipse.width, ellipse.height);
|
||||
copyFrom(ellipse);
|
||||
}
|
||||
|
||||
public double getBreite() {
|
||||
return breite;
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setBreite( double breite ) {
|
||||
this.breite = breite;
|
||||
public void setWidth( double width ) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public double getHoehe() {
|
||||
return hoehe;
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHoehe( double hoehe ) {
|
||||
this.hoehe = hoehe;
|
||||
public void setHeight( double height ) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kopiere( Form pForm ) {
|
||||
super.kopiere(pForm);
|
||||
if( pForm instanceof Ellipse ) {
|
||||
Ellipse e = (Ellipse) pForm;
|
||||
breite = e.breite;
|
||||
hoehe = e.hoehe;
|
||||
public void copyFrom( Shape shape ) {
|
||||
super.copyFrom(shape);
|
||||
if( shape instanceof Ellipse ) {
|
||||
Ellipse e = (Ellipse) shape;
|
||||
this.width = e.width;
|
||||
this.height = e.height;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ellipse kopie() {
|
||||
public Ellipse copy() {
|
||||
return new Ellipse(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skalieren( double pFaktor ) {
|
||||
super.skalieren(pFaktor);
|
||||
breite *= pFaktor;
|
||||
hoehe *= pFaktor;
|
||||
public void scale( double factor ) {
|
||||
super.scale(factor);
|
||||
width *= factor;
|
||||
height *= factor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAnkerpunkt( byte pAnker ) {
|
||||
ankerBerechnen(breite, hoehe, pAnker);
|
||||
public void setAnchor( Options.Direction anchor ) {
|
||||
calculateAnchor(width, height, anchor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape() {
|
||||
Shape shape = new Ellipse2D.Double(0, 0, breite, hoehe);
|
||||
return shape;
|
||||
public java.awt.Shape getShape() {
|
||||
return new Ellipse2D.Double(0, 0, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,15 +76,15 @@ public class Ellipse extends Form {
|
|||
if( o == null || getClass() != o.getClass() ) return false;
|
||||
Ellipse ellipse = (Ellipse) o;
|
||||
return super.equals(o) &&
|
||||
Double.compare(ellipse.breite, breite) == 0 &&
|
||||
Double.compare(ellipse.hoehe, hoehe) == 0;
|
||||
Double.compare(ellipse.width, width) == 0 &&
|
||||
Double.compare(ellipse.height, height) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getCanonicalName() + '[' +
|
||||
"breite=" + breite +
|
||||
",hoehe=" + hoehe +
|
||||
"width=" + width +
|
||||
",height=" + height +
|
||||
",x=" + x +
|
||||
",y=" + y +
|
||||
']';
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
|
@ -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] +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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 +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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 +
|
||||
']';
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
||||
import schule.ngb.zm.Options;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
public class Text extends Form {
|
||||
|
||||
private static final int DFT_FONT_SIZE = 14;
|
||||
public class Text extends Shape {
|
||||
|
||||
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 ) {
|
||||
super(pX, pY);
|
||||
schriftart = new Font(Font.SANS_SERIF, Font.PLAIN, DFT_FONT_SIZE);
|
||||
setText(pText);
|
||||
public Text( double x, double y, String text ) {
|
||||
super(x, y);
|
||||
font = new Font(Font.SANS_SERIF, Font.PLAIN, STD_FONTSIZE);
|
||||
setText(text);
|
||||
}
|
||||
|
||||
public Text( Text pText ) {
|
||||
super(pText.getX(), pText.getY());
|
||||
kopiere(pText);
|
||||
public Text( Text text ) {
|
||||
super(text.getX(), text.getY());
|
||||
copyFrom(text);
|
||||
}
|
||||
|
||||
public Form kopie() {
|
||||
public Shape copy() {
|
||||
return new Text(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kopiere( Form pForm ) {
|
||||
super.kopiere(pForm);
|
||||
if( pForm instanceof Text ) {
|
||||
Text pText = (Text)pForm;
|
||||
public void copyFrom( Shape shape ) {
|
||||
super.copyFrom(shape);
|
||||
if( shape instanceof Text ) {
|
||||
Text pText = (Text) shape;
|
||||
this.text = pText.getText();
|
||||
this.schriftart = pText.getSchriftart();
|
||||
this.font = pText.getFont();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void skalieren( double pFaktor ) {
|
||||
super.skalieren(pFaktor);
|
||||
setSchriftgroesse(schriftart.getSize2D()*pFaktor);
|
||||
public void scale( double factor ) {
|
||||
super.scale(factor);
|
||||
setFontsize(font.getSize2D() * factor);
|
||||
}
|
||||
|
||||
public Font getSchriftart() {
|
||||
return schriftart;
|
||||
public Font getFont() {
|
||||
return font;
|
||||
}
|
||||
|
||||
public void setSchriftgroesse( double pGroesse ) {
|
||||
schriftart = schriftart.deriveFont((float)pGroesse);
|
||||
public void setFontsize( double size ) {
|
||||
font = font.deriveFont((float) size);
|
||||
setText(text);
|
||||
}
|
||||
|
||||
|
@ -62,34 +62,34 @@ public class Text extends Form {
|
|||
text = pText;
|
||||
|
||||
Canvas metricsCanvas = new Canvas();
|
||||
FontMetrics metrics = metricsCanvas.getFontMetrics(schriftart);
|
||||
breite = metrics.stringWidth(text);
|
||||
hoehe = metrics.getDescent() + metrics.getAscent();
|
||||
FontMetrics metrics = metricsCanvas.getFontMetrics(font);
|
||||
width = metrics.stringWidth(text);
|
||||
height = metrics.getDescent() + metrics.getAscent();
|
||||
ascent = metrics.getAscent();
|
||||
|
||||
setAnkerpunkt(ZENTRUM);
|
||||
setAnchor(CENTER);
|
||||
}
|
||||
|
||||
public double getBreite() {
|
||||
return breite;
|
||||
public double getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public double getHoehe() {
|
||||
return hoehe;
|
||||
public double getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setAnkerpunkt( byte pAnker ) {
|
||||
ankerBerechnen(breite, ascent - hoehe, pAnker);
|
||||
public void setAnchor( Options.Direction anchor ) {
|
||||
calculateAnchor(width, ascent - height, anchor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getShape() {
|
||||
return new Rectangle2D.Double(0, 0, breite, hoehe);
|
||||
public java.awt.Shape getShape() {
|
||||
return new Rectangle2D.Double(0, 0, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zeichnen( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||
if( !sichtbar ) {
|
||||
public void draw( Graphics2D graphics, AffineTransform pVerzerrung ) {
|
||||
if( !visible ) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -99,11 +99,11 @@ public class Text extends Form {
|
|||
AffineTransform af = graphics.getTransform();
|
||||
|
||||
// Neue Werte setzen
|
||||
graphics.setFont(schriftart);
|
||||
graphics.setColor(konturFarbe);
|
||||
graphics.transform(getVerzerrung());
|
||||
graphics.setFont(font);
|
||||
graphics.setColor(strokeColor.getColor());
|
||||
graphics.transform(pVerzerrung);
|
||||
|
||||
// Text zeichnen
|
||||
// Draw text
|
||||
FontMetrics fm = graphics.getFontMetrics();
|
||||
//graphics.drawString(text, (float) (x - fm.stringWidth(text)/2.0), (float) (y + fm.getDescent()));
|
||||
graphics.drawString(text, 0, 0);
|
||||
|
@ -121,13 +121,15 @@ public class Text extends Form {
|
|||
Text text = (Text) o;
|
||||
return super.equals(o) &&
|
||||
text.equals(text.text) &&
|
||||
schriftart.equals(text.schriftart);
|
||||
font.equals(text.font);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getCanonicalName() + "[" +
|
||||
"text=" + text +
|
||||
"text=" + text + ',' +
|
||||
"font=" + font.getName() + ',' +
|
||||
"size=" + font.getSize() +
|
||||
']';
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
|
||||
import schule.ngb.zm.*;
|
||||
|
||||
public class Attractor extends Mover {
|
||||
|
||||
private static final int G = 10;
|
||||
|
||||
private int mass = 0;
|
||||
|
||||
public Attractor( int x, int pY, int pMass ) {
|
||||
this(x, pY, pMass, new Vector());
|
||||
}
|
||||
|
||||
public Attractor( int x, int pY, int pMass, Vector pVelocity ) {
|
||||
super(x, pY, pVelocity);
|
||||
mass = pMass;
|
||||
|
||||
setFillColor(YELLOW);
|
||||
}
|
||||
|
||||
public void attract( Mover pMover ) {
|
||||
if( pMover != this ) {
|
||||
Vector force = new Vector(this.x, this.y);
|
||||
force.sub(pMover.getX(), pMover.getY()).scale(mass*G).limit(0, 50*G);
|
||||
pMover.applyForce(force);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
import schule.ngb.zm.Zeichenmaschine;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Beschreiben Sie hier die Klasse BluejTest.
|
||||
*
|
||||
* @author (Ihr Name)
|
||||
* @version (eine Versionsnummer oder ein Datum)
|
||||
*/
|
||||
public class BluejTest extends Zeichenmaschine
|
||||
{
|
||||
public void setup() {
|
||||
if( !IN_BLUEJ ) {
|
||||
drawing.clear(schule.ngb.zm.Color.HGRED);
|
||||
} else {
|
||||
drawing.clear(schule.ngb.zm.Color.HGGREEN);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void listClasses() {
|
||||
// find all classes in classpath
|
||||
List<String> allClasses = ClasspathInspector.getAllKnownClassNames();
|
||||
System.out.printf("There are %s classes available in the classpath\n", allClasses.size());
|
||||
|
||||
for (String clazz : allClasses) {
|
||||
if( clazz.contains("Boot") || clazz.contains("Main") ) {
|
||||
System.out.printf("%s\n", clazz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.Serializable;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* Find classes in the classpath (reads JARs and classpath folders).
|
||||
*
|
||||
* @author Pål Brattberg, brattberg@gmail.com
|
||||
* @see http://gist.github.com/pal
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class ClasspathInspector {
|
||||
static boolean DEBUG = false;
|
||||
|
||||
|
||||
public static List<String> getAllKnownClassNames() {
|
||||
List<String> classNames = new ArrayList<String>();
|
||||
List<File> classLocations = getClassLocationsForCurrentClasspath();
|
||||
for (File file : classLocations) {
|
||||
classNames.addAll(getClassNamesFromPath(file));
|
||||
}
|
||||
return classNames;
|
||||
}
|
||||
|
||||
public static List<Class> getAllKnownClasses() {
|
||||
List<Class> classFiles = new ArrayList<Class>();
|
||||
List<File> classLocations = getClassLocationsForCurrentClasspath();
|
||||
for (File file : classLocations) {
|
||||
classFiles.addAll(getClassesFromPath(file));
|
||||
}
|
||||
return classFiles;
|
||||
}
|
||||
|
||||
public static List<Class> getMatchingClasses(Class interfaceOrSuperclass) {
|
||||
List<Class> matchingClasses = new ArrayList<Class>();
|
||||
List<Class> classes = getAllKnownClasses();
|
||||
log("checking %s classes", classes.size());
|
||||
for (Class clazz : classes) {
|
||||
if (interfaceOrSuperclass.isAssignableFrom(clazz)) {
|
||||
matchingClasses.add(clazz);
|
||||
log("class %s is assignable from %s", interfaceOrSuperclass, clazz);
|
||||
}
|
||||
}
|
||||
return matchingClasses;
|
||||
}
|
||||
|
||||
public static List<Class> getMatchingClasses(String validPackagePrefix, Class interfaceOrSuperclass) {
|
||||
throw new IllegalStateException("Not yet implemented!");
|
||||
}
|
||||
|
||||
public static List<Class> getMatchingClasses(String validPackagePrefix) {
|
||||
throw new IllegalStateException("Not yet implemented!");
|
||||
}
|
||||
|
||||
private static Collection<? extends Class> getClassesFromPath(File path) {
|
||||
if (path.isDirectory()) {
|
||||
return getClassesFromDirectory(path);
|
||||
} else {
|
||||
return getClassesFromJarFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static Collection<String> getClassNamesFromPath(File path) {
|
||||
if (path.isDirectory()) {
|
||||
return getClassNamesFromDirectory(path);
|
||||
} else {
|
||||
return getClassNamesFromJarFile(path);
|
||||
}
|
||||
}
|
||||
|
||||
private static String fromFileToClassName(final String fileName) {
|
||||
return fileName.substring(0, fileName.length() - 6).replaceAll("/|\\\\", "\\.");
|
||||
}
|
||||
|
||||
private static List<Class> getClassesFromJarFile(File path) {
|
||||
List<Class> classes = new ArrayList<Class>();
|
||||
log("getClassesFromJarFile: Getting classes for " + path);
|
||||
|
||||
try {
|
||||
if (path.canRead()) {
|
||||
JarFile jar = new JarFile(path);
|
||||
Enumeration<JarEntry> en = jar.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
JarEntry entry = en.nextElement();
|
||||
if (entry.getName().endsWith("class")) {
|
||||
String className = fromFileToClassName(entry.getName());
|
||||
log("\tgetClassesFromJarFile: found " + className);
|
||||
Class claz = Class.forName(className);
|
||||
classes.add(claz);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to read classes from jar file: " + path, e);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static List<String> getClassNamesFromJarFile(File path) {
|
||||
List<String> classes = new ArrayList<>();
|
||||
log("getClassNamesFromJarFile: Getting classes for " + path);
|
||||
|
||||
try {
|
||||
if (path.canRead()) {
|
||||
JarFile jar = new JarFile(path);
|
||||
Enumeration<JarEntry> en = jar.entries();
|
||||
while (en.hasMoreElements()) {
|
||||
JarEntry entry = en.nextElement();
|
||||
if (entry.getName().endsWith("class")) {
|
||||
String className = fromFileToClassName(entry.getName());
|
||||
classes.add(className);
|
||||
log("\tgetClassesFromJarFile: found " + className);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to read classnames from jar file: " + path, e);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static List<Class> getClassesFromDirectory(File path) {
|
||||
List<Class> classes = new ArrayList<Class>();
|
||||
log("getClassesFromDirectory: Getting classes for " + path);
|
||||
|
||||
// get jar files from top-level directory
|
||||
List<File> jarFiles = listFiles(path, new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".jar");
|
||||
}
|
||||
}, false);
|
||||
for (File file : jarFiles) {
|
||||
classes.addAll(getClassesFromJarFile(file));
|
||||
}
|
||||
|
||||
// get all class-files
|
||||
List<File> classFiles = listFiles(path, new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".class");
|
||||
}
|
||||
}, true);
|
||||
|
||||
// List<URL> urlList = new ArrayList<URL>();
|
||||
// List<String> classNameList = new ArrayList<String>();
|
||||
int substringBeginIndex = path.getAbsolutePath().length() + 1;
|
||||
for (File classfile : classFiles) {
|
||||
String className = classfile.getAbsolutePath().substring(substringBeginIndex);
|
||||
className = fromFileToClassName(className);
|
||||
log("Found class %s in path %s: ", className, path);
|
||||
try {
|
||||
classes.add(Class.forName(className));
|
||||
} catch (Throwable e) {
|
||||
log("Couldn't create class %s. %s: ", className, e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static List<String> getClassNamesFromDirectory(File path) {
|
||||
List<String> classes = new ArrayList<>();
|
||||
log("getClassNamesFromDirectory: Getting classes for " + path);
|
||||
|
||||
// get jar files from top-level directory
|
||||
List<File> jarFiles = listFiles(path, new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".jar");
|
||||
}
|
||||
}, false);
|
||||
for (File file : jarFiles) {
|
||||
classes.addAll(getClassNamesFromJarFile(file));
|
||||
}
|
||||
|
||||
// get all class-files
|
||||
List<File> classFiles = listFiles(path, new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith(".class");
|
||||
}
|
||||
}, true);
|
||||
|
||||
// List<URL> urlList = new ArrayList<URL>();
|
||||
// List<String> classNameList = new ArrayList<String>();
|
||||
int substringBeginIndex = path.getAbsolutePath().length() + 1;
|
||||
for (File classfile : classFiles) {
|
||||
String className = classfile.getAbsolutePath().substring(substringBeginIndex);
|
||||
className = fromFileToClassName(className);
|
||||
log("Found class %s in path %s: ", className, path);
|
||||
classes.add(className);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private static List<File> listFiles(File directory, FilenameFilter filter, boolean recurse) {
|
||||
List<File> files = new ArrayList<File>();
|
||||
File[] entries = directory.listFiles();
|
||||
|
||||
// Go over entries
|
||||
for (File entry : entries) {
|
||||
// If there is no filter or the filter accepts the
|
||||
// file / directory, add it to the list
|
||||
if (filter == null || filter.accept(directory, entry.getName())) {
|
||||
files.add(entry);
|
||||
}
|
||||
|
||||
// If the file is a directory and the recurse flag
|
||||
// is set, recurse into the directory
|
||||
if (recurse && entry.isDirectory()) {
|
||||
files.addAll(listFiles(entry, filter, recurse));
|
||||
}
|
||||
}
|
||||
|
||||
// Return collection of files
|
||||
return files;
|
||||
}
|
||||
|
||||
public static List<File> getClassLocationsForCurrentClasspath() {
|
||||
List<File> urls = new ArrayList<File>();
|
||||
String javaClassPath = System.getProperty("java.class.path");
|
||||
if (javaClassPath != null) {
|
||||
for (String path : javaClassPath.split(File.pathSeparator)) {
|
||||
urls.add(new File(path));
|
||||
}
|
||||
}
|
||||
return urls;
|
||||
}
|
||||
|
||||
// todo: this is only partial, probably
|
||||
public static URL normalize(URL url) throws MalformedURLException {
|
||||
String spec = url.getFile();
|
||||
|
||||
// get url base - remove everything after ".jar!/??" , if exists
|
||||
final int i = spec.indexOf("!/");
|
||||
if (i != -1) {
|
||||
spec = spec.substring(0, spec.indexOf("!/"));
|
||||
}
|
||||
|
||||
// uppercase windows drive
|
||||
url = new URL(url, spec);
|
||||
final String file = url.getFile();
|
||||
final int i1 = file.indexOf(':');
|
||||
if (i1 != -1) {
|
||||
String drive = file.substring(i1 - 1, 2).toUpperCase();
|
||||
url = new URL(url, file.substring(0, i1 - 1) + drive + file.substring(i1));
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
private static void log(String pattern, final Object... args) {
|
||||
if (DEBUG)
|
||||
System.out.printf(pattern + "\n", args);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// find all classes in classpath
|
||||
List<Class> allClasses = ClasspathInspector.getAllKnownClasses();
|
||||
System.out.printf("There are %s classes available in the classpath\n", allClasses.size());
|
||||
|
||||
// find all classes that implement/subclass an interface/superclass
|
||||
List<Class> serializableClasses = ClasspathInspector.getMatchingClasses(Serializable.class);
|
||||
for (Class clazz : serializableClasses) {
|
||||
System.out.printf("%s is Serializable\n", clazz);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import schule.ngb.zm.*;
|
||||
|
||||
public class Gravity extends Zeichenmaschine {
|
||||
|
||||
private LinkedList<Mover> movers = new LinkedList<>();
|
||||
|
||||
private LinkedList<Attractor> attractors = new LinkedList<>();
|
||||
|
||||
public void setup(){
|
||||
for( int i = 0; i < 10; i++ ) {
|
||||
Mover m = new Mover(random(10, width-10), random(10, height-10));
|
||||
movers.add(m);
|
||||
shapes.add(m);
|
||||
}
|
||||
|
||||
attractors.add(new Attractor(width/2, height/2, 10));
|
||||
shapes.add(attractors.get(0));
|
||||
}
|
||||
|
||||
public void update( double delta ) {
|
||||
for( Attractor a: attractors ) {
|
||||
for( Mover m: movers ) {
|
||||
a.attract(m);
|
||||
}
|
||||
}
|
||||
|
||||
for( Mover m: movers ) {
|
||||
m.update(delta);
|
||||
}
|
||||
shapes.clear();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
shapes.clear();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
|
||||
import schule.ngb.zm.*;
|
||||
import schule.ngb.zm.formen.*;
|
||||
|
||||
public class Mover extends Circle implements Updatable {
|
||||
|
||||
private Vector velocity;
|
||||
private Vector acceleration = new Vector();
|
||||
|
||||
public Mover( int x, int pY ) {
|
||||
this(x, pY, new Vector());
|
||||
}
|
||||
|
||||
public Mover( int x, int pY, Vector pVelocity ) {
|
||||
super(x, pY, 10);
|
||||
this.velocity = pVelocity.copy();
|
||||
}
|
||||
|
||||
public void applyForce( Vector force ) {
|
||||
acceleration.add(force);
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void update( double delta ) {
|
||||
acceleration.scale(delta);
|
||||
velocity.add(acceleration);
|
||||
acceleration.scale(0.0);
|
||||
|
||||
this.x += velocity.x;
|
||||
this.y += velocity.y;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
#BlueJ package file
|
||||
dependency1.from=BluejTest
|
||||
dependency1.to=ClasspathInspector
|
||||
dependency1.type=UsesDependency
|
||||
dependency2.from=Gravity
|
||||
dependency2.to=Mover
|
||||
dependency2.type=UsesDependency
|
||||
dependency3.from=Gravity
|
||||
dependency3.to=Attractor
|
||||
dependency3.type=UsesDependency
|
||||
editor.fx.0.height=728
|
||||
editor.fx.0.width=1037
|
||||
editor.fx.0.x=95
|
||||
editor.fx.0.y=53
|
||||
objectbench.height=94
|
||||
objectbench.width=776
|
||||
package.divider.horizontal=0.6
|
||||
package.divider.vertical=0.8305369127516778
|
||||
package.editor.height=488
|
||||
package.editor.width=661
|
||||
package.editor.x=374
|
||||
package.editor.y=158
|
||||
package.frame.height=660
|
||||
package.frame.width=800
|
||||
package.numDependencies=3
|
||||
package.numTargets=5
|
||||
package.showExtends=true
|
||||
package.showUses=true
|
||||
project.charset=UTF-8
|
||||
readme.height=60
|
||||
readme.name=@README
|
||||
readme.width=48
|
||||
readme.x=10
|
||||
readme.y=10
|
||||
target1.height=70
|
||||
target1.name=Mover
|
||||
target1.showInterface=false
|
||||
target1.type=ClassTarget
|
||||
target1.width=120
|
||||
target1.x=320
|
||||
target1.y=200
|
||||
target2.height=70
|
||||
target2.name=BluejTest
|
||||
target2.showInterface=false
|
||||
target2.type=ClassTarget
|
||||
target2.width=120
|
||||
target2.x=70
|
||||
target2.y=10
|
||||
target3.height=70
|
||||
target3.name=Attractor
|
||||
target3.showInterface=false
|
||||
target3.type=ClassTarget
|
||||
target3.width=120
|
||||
target3.x=390
|
||||
target3.y=350
|
||||
target4.height=70
|
||||
target4.name=ClasspathInspector
|
||||
target4.showInterface=false
|
||||
target4.type=ClassTarget
|
||||
target4.width=130
|
||||
target4.x=380
|
||||
target4.y=30
|
||||
target5.height=70
|
||||
target5.name=Gravity
|
||||
target5.showInterface=false
|
||||
target5.type=ClassTarget
|
||||
target5.width=120
|
||||
target5.x=100
|
||||
target5.y=300
|
|
@ -1,114 +1,112 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.Form;
|
||||
import schule.ngb.zm.formen.Rechteck;
|
||||
import schule.ngb.zm.formen.Rectangle;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
public class TestAttraction extends Zeichenfenster {
|
||||
public class TestAttraction extends Zeichenmaschine {
|
||||
|
||||
public static void main(String[] args) {
|
||||
new TestAttraction();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void einstellungen() {
|
||||
public void settings() {
|
||||
setSize(800, 600);
|
||||
setTitel("My test Window");
|
||||
setTitle("My test Window");
|
||||
//setFramesPerSecond(5);
|
||||
|
||||
s2dl = new Shape2DEbene();
|
||||
hinzu(s2dl);
|
||||
s2dl = new Shape2DLayer();
|
||||
addLayer(s2dl);
|
||||
}
|
||||
|
||||
Shape2DEbene s2dl;
|
||||
Shape2DLayer s2dl;
|
||||
|
||||
Vektor posA, posB, velB, posC, velC;
|
||||
Vector posA, posB, velB, posC, velC;
|
||||
|
||||
double massA = 500, massB = 1, massC = 4.3, G = 5.0;
|
||||
|
||||
Rechteck recht;
|
||||
Rectangle recht;
|
||||
|
||||
@Override
|
||||
public void vorbereiten() {
|
||||
public void setup() {
|
||||
//zeichnung.hide();
|
||||
zeichnung.clear(200);
|
||||
posA = new Vektor(0, 0);
|
||||
posB = new Vektor(-100, -100);
|
||||
velB = new Vektor(10, -10);
|
||||
posC = new Vektor(200, 100);
|
||||
velC = new Vektor(1, 14);
|
||||
drawing.clear(200);
|
||||
posA = new Vector(0, 0);
|
||||
posB = new Vector(-100, -100);
|
||||
velB = new Vector(10, -10);
|
||||
posC = new Vector(200, 100);
|
||||
velC = new Vector(1, 14);
|
||||
|
||||
zeichnung.translate(breite /2, hoehe /2);
|
||||
zeichnung.shear(0.1, 0.5);
|
||||
drawing.translate(width /2, height /2);
|
||||
drawing.shear(0.1, 0.5);
|
||||
|
||||
recht = new Rechteck(50, 50, 150, 75);
|
||||
recht.setFuellfarbe(200);
|
||||
recht.setKonturFarbe(255, 0, 64);
|
||||
recht.setKonturDicke(2.5);
|
||||
recht.setKonturArt(Form.GESTRICHELT);
|
||||
formen.anzeigen(recht);
|
||||
recht = new Rectangle(50, 50, 150, 75);
|
||||
recht.setFillColor(200);
|
||||
recht.setStrokeColor(255, 0, 64);
|
||||
recht.setStrokeWeight(2.5);
|
||||
recht.setStrokeType(DASHED);
|
||||
shapes.add(recht);
|
||||
|
||||
zeichnung.verstecken();
|
||||
drawing.hide();
|
||||
//schule.ngb.zm.formen.verstecken();
|
||||
|
||||
s2dl.setColor(64,200,128);
|
||||
s2dl.setFillColor(64,200,128);
|
||||
s2dl.add(new Rectangle2D.Double(100, 100, 120, 80));
|
||||
}
|
||||
|
||||
public void zeichnen() {
|
||||
zeichnung.setStrokeColor(255);
|
||||
zeichnung.setStrokeWeight(4.0);
|
||||
zeichnung.setKonturArt(GESTRICHELT);
|
||||
zeichnung.clear(33, 33, 33, 100);
|
||||
public void draw() {
|
||||
drawing.setStrokeColor(255);
|
||||
drawing.setStrokeWeight(4.0);
|
||||
drawing.setStrokeType(DASHED);
|
||||
drawing.clear(33, 33, 33, 100);
|
||||
|
||||
zeichnung.setColor(Color.ORANGE);
|
||||
zeichnung.pie(posA.x, posA.y, 80, 30, 60);
|
||||
zeichnung.setColor(Color.YELLOW);
|
||||
zeichnung.circle(posA.x, posA.y, 60);
|
||||
drawing.setColor(Color.ORANGE);
|
||||
drawing.pie(posA.x, posA.y, 80, 30, 60);
|
||||
drawing.setColor(Color.YELLOW);
|
||||
drawing.circle(posA.x, posA.y, 60);
|
||||
|
||||
Vektor acc = acceleration(posA, posB, massA, massB);
|
||||
velB.addieren(acc);
|
||||
posB.addieren(velB);
|
||||
Vector acc = acceleration(posA, posB, massA, massB);
|
||||
velB.add(acc);
|
||||
posB.add(velB);
|
||||
|
||||
zeichnung.setColor(Color.BLUE);
|
||||
zeichnung.circle(posB.x, posB.y, 20);
|
||||
drawing.setColor(Color.BLUE);
|
||||
drawing.circle(posB.x, posB.y, 20);
|
||||
|
||||
acc = acceleration(posA, posC, massA, massC);
|
||||
velC.addieren(acc);
|
||||
posC.addieren(velC);
|
||||
velC.add(acc);
|
||||
posC.add(velC);
|
||||
|
||||
zeichnung.setColor(Color.GREEN);
|
||||
zeichnung.circle(posC.x, posC.y, 20);
|
||||
drawing.setColor(Color.GREEN);
|
||||
drawing.circle(posC.x, posC.y, 20);
|
||||
|
||||
zeichnung.rotate(1);
|
||||
drawing.rotate(1);
|
||||
|
||||
formen.leeren();
|
||||
shapes.clear();
|
||||
double x = recht.getX();
|
||||
x = (x+100*delta)% breite;
|
||||
x = (x+100*delta)% width;
|
||||
recht.setX(x);
|
||||
}
|
||||
|
||||
Vektor acceleration(Vektor a, Vektor b, double ma, double mb ) {
|
||||
Vektor acc = Vektor.subtrahieren(a, b);
|
||||
double draw = (G*ma*mb)/acc.laengeQuad();
|
||||
acc.setLaenge(draw*delta);
|
||||
acc.beschraenken(3, 30);
|
||||
Vector acceleration( Vector a, Vector b, double ma, double mb ) {
|
||||
Vector acc = Vector.sub(a, b);
|
||||
double draw = (G*ma*mb)/acc.lenSq();
|
||||
acc.setLen(draw*delta);
|
||||
acc.limit(3, 30);
|
||||
return acc;
|
||||
}
|
||||
|
||||
public void mouseDragged() {
|
||||
zeichnung.translate(mausX - lmausX, mausY - lmausY);
|
||||
drawing.translate(mouseX - pmouseX, mouseY - pmouseY);
|
||||
}
|
||||
|
||||
boolean zoom = true;
|
||||
public void mouseClicked() {
|
||||
//canvas.translateToCanvas(mouseX-width/2.0, mouseY-height/2.0);
|
||||
if( zoom ) {
|
||||
zeichnung.scale(2.0);
|
||||
drawing.scale(2.0);
|
||||
} else {
|
||||
zeichnung.scale(.5);
|
||||
drawing.scale(.5);
|
||||
}
|
||||
zoom = !zoom;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class TestColor {
|
||||
|
||||
@Test
|
||||
public void colors() {
|
||||
Color c;
|
||||
|
||||
c = new Color();
|
||||
assertEquals(0, c.getRed());
|
||||
assertEquals(0, c.getGreen());
|
||||
assertEquals(0, c.getBlue());
|
||||
assertEquals(255, c.getAlpha());
|
||||
|
||||
c = Color.BLUE;
|
||||
assertEquals(0, c.getRed());
|
||||
assertEquals(0, c.getGreen());
|
||||
assertEquals(255, c.getBlue());
|
||||
assertEquals(255, c.getAlpha());
|
||||
|
||||
c = new Color(50, 133, 64, 33);
|
||||
assertEquals(50, c.getRed());
|
||||
assertEquals(133, c.getGreen());
|
||||
assertEquals(64, c.getBlue());
|
||||
assertEquals(33, c.getAlpha());
|
||||
|
||||
c = new Color(255, 0, 0);
|
||||
assertEquals(Color.RED, c);
|
||||
|
||||
c = new Color(33, 50);
|
||||
assertEquals(33, c.getRed());
|
||||
assertEquals(33, c.getGreen());
|
||||
assertEquals(33, c.getBlue());
|
||||
assertEquals(50, c.getAlpha());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseColors() {
|
||||
Color c;
|
||||
|
||||
c = Color.parseRGB(0x00FF00FF);
|
||||
assertEquals(0x00FF00FF, c.getRGBA());
|
||||
assertEquals(255, c.getRed());
|
||||
assertEquals(0, c.getGreen());
|
||||
assertEquals(255, c.getBlue());
|
||||
assertEquals(0, c.getAlpha());
|
||||
|
||||
c = Color.parseRGB(0x33FF3333);
|
||||
assertEquals(0x33FF3333, c.getRGBA());
|
||||
assertEquals(255, c.getRed());
|
||||
assertEquals(51, c.getGreen());
|
||||
assertEquals(51, c.getBlue());
|
||||
assertEquals(51, c.getAlpha());
|
||||
|
||||
c = Color.parseHexcode("FF00FF");
|
||||
assertEquals(0xFFFF00FF, c.getRGBA());
|
||||
assertEquals(255, c.getRed());
|
||||
assertEquals(0, c.getGreen());
|
||||
assertEquals(255, c.getBlue());
|
||||
assertEquals(255, c.getAlpha());
|
||||
|
||||
c = Color.parseHexcode("#FF00FF00");
|
||||
assertEquals(0x00FF00FF, c.getRGBA());
|
||||
assertEquals(255, c.getRed());
|
||||
assertEquals(0, c.getGreen());
|
||||
assertEquals(255, c.getBlue());
|
||||
assertEquals(0, c.getAlpha());
|
||||
|
||||
c = Color.parseHexcode("#333");
|
||||
assertEquals(0xFF333333, c.getRGBA());
|
||||
assertEquals(51, c.getRed());
|
||||
assertEquals(51, c.getGreen());
|
||||
assertEquals(51, c.getBlue());
|
||||
assertEquals(255, c.getAlpha());
|
||||
|
||||
c = Color.parseHexcode("#33FF0033");
|
||||
assertEquals(0x3333FF00, c.getRGBA());
|
||||
assertEquals(51, c.getRed());
|
||||
assertEquals(255, c.getGreen());
|
||||
assertEquals(0, c.getBlue());
|
||||
assertEquals(51, c.getAlpha());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hsl() {
|
||||
Color c;
|
||||
float[] hsl;
|
||||
|
||||
c = Color.RED;
|
||||
hsl = Color.RGBtoHSL(c.getRGBA(), null);
|
||||
assertArrayEquals(new float[]{0f,1f,.5f}, hsl, 0.0001f);
|
||||
|
||||
c = new Color(255, 33, 64);
|
||||
hsl = Color.RGBtoHSL(c.getRGBA(), null);
|
||||
assertEquals(352, hsl[0], 1.0f);
|
||||
assertEquals(1.0f, hsl[1], .0001f);
|
||||
assertEquals(.5647f, hsl[2], .0001f);
|
||||
}
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new ColorPalette();
|
||||
}
|
||||
|
||||
static class ColorPalette extends Zeichenmaschine {
|
||||
public static final int SIZE = 10, COLORS = 16;
|
||||
|
||||
public void setup() {
|
||||
setSize(SIZE*COLORS, SIZE*COLORS);
|
||||
setTitle("Colors");
|
||||
|
||||
drawing.noStroke();
|
||||
drawing.setAnchor(NORTHWEST);
|
||||
|
||||
int steps = (int) (255.0/COLORS);
|
||||
Color c;
|
||||
for( int i = 0; i < COLORS; i++ ) {
|
||||
for( int j = 0; j < COLORS; j++ ) {
|
||||
c = new Color(i * steps, j * steps, (i+j)/2 * steps);
|
||||
drawing.setColor(c);
|
||||
drawing.rect(i*SIZE, j*SIZE, SIZE, SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
Color c = Color.HGGREEN;
|
||||
drawing.setColor(c);
|
||||
drawing.rect(0, 0, width/2, height);
|
||||
|
||||
for( int p = 10; p < 100; p += 10 ) {
|
||||
drawing.setColor(c.brighter(p));
|
||||
drawing.rect(width / 2, 0, width / 2, height / 2);
|
||||
drawing.setColor(c.darker(p));
|
||||
drawing.rect(width / 2, height / 2, width / 2, height / 2);
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.util.List;
|
||||
|
||||
public class TestDrawing extends Zeichenmaschine {
|
||||
|
||||
private final double w = 100, h = 50;
|
||||
|
||||
private double xa = 50, ya = 50;
|
||||
|
||||
private double x2 = 200, y2 = 50;
|
||||
|
||||
int frames = 0;
|
||||
long start = 0;
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new TestDrawing();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setup() {
|
||||
drawing.setFont("AvenirNext-Medium", 14);
|
||||
drawing.setAnchor(NORTHWEST);
|
||||
|
||||
start = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update( double delta ) {
|
||||
ya = (ya+1)%350;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw() {
|
||||
long ms = System.currentTimeMillis();
|
||||
|
||||
drawing.clear();
|
||||
|
||||
// x2 = mouseX;
|
||||
// y2 = mouseY;
|
||||
|
||||
drawing.resetStroke();
|
||||
drawing.rect(xa, ya, w, h);
|
||||
|
||||
//drawing.image("WitchCraftIcons_122_t.PNG", width/2, height/2, .5, CENTER);
|
||||
|
||||
for( int i = 0; i < 4; i++ ) {
|
||||
//delay(1000);
|
||||
drawing.resetStroke();
|
||||
drawing.rect(x2 + i*10, y2 + i * 75, w, h);
|
||||
connect(xa + w, ya + h / 2.0, x2 + i*10, y2 + i * 75 + h / 2.0);
|
||||
drawing.text("Rect " + i, x2 + i*10 + w / 2.0, y2 + i * 75 + h / 2.0, CENTER);
|
||||
}
|
||||
|
||||
|
||||
if( (System.currentTimeMillis()-start) >= 1000 ) {
|
||||
System.out.printf("FPS: %d\n", frames);
|
||||
frames = 0;
|
||||
start = System.currentTimeMillis();
|
||||
} else {
|
||||
frames += 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void connect( double x1, double y1, double x2, double y2 ) {
|
||||
double midx = (x1 + x2) / 2.0;
|
||||
drawing.setStrokeType(DASHED);
|
||||
drawing.setStrokeWeight(2.4);
|
||||
drawing.curve(x1, y1, midx, y1, midx, y2, x2, y2);
|
||||
//drawing.curve(x1, y1, x2, y1, x1, y2, x2, y2);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,57 +1,104 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.formen.*;
|
||||
import schule.ngb.zm.formen.Point;
|
||||
import schule.ngb.zm.formen.Polygon;
|
||||
import schule.ngb.zm.formen.Rectangle;
|
||||
import schule.ngb.zm.formen.Shape;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.Random;
|
||||
|
||||
public class TestFormen extends Zeichenfenster {
|
||||
public class TestFormen extends Zeichenmaschine {
|
||||
|
||||
Random rand = new Random();
|
||||
|
||||
public static void main( String[] args ) {
|
||||
new TestFormen();
|
||||
}
|
||||
|
||||
|
||||
Kurve k;
|
||||
|
||||
@Override
|
||||
public void vorbereiten() {
|
||||
public void setup() {
|
||||
setSize(400, 400);
|
||||
|
||||
k = new Kurve(50, 50, 100, 50, 100, 100,150, 100);
|
||||
//formen.anzeigen(new Kurve(50, 50, 100, 50, 150, 100));
|
||||
formen.anzeigen(k);
|
||||
add(new Rectangle(20, 10, 40, 20));
|
||||
add(new Ellipse(40, 50, 40, 20));
|
||||
add(new Circle(40, 80, 10));
|
||||
|
||||
k.verschiebeNach(200, 200);
|
||||
k.skalieren(1.1);
|
||||
add(new Line(40, 100, 100, 40));
|
||||
add(new Arrow(200, 200, 105, 45));
|
||||
|
||||
showDot(k.getStartpunkt());
|
||||
showDot(k.getKontrollpunkt1());
|
||||
showDot(k.getKontrollpunkt2());
|
||||
showDot(k.getEndpunkt());
|
||||
shapes.add(new Point(200, 200));
|
||||
|
||||
add(new Rhombus(40, 200, 50, 120));
|
||||
add(new Kite(40, 200, 50, 120, .75));
|
||||
add(new Kite(40, 200, 50, 120, .25));
|
||||
|
||||
add(new RoundedRectangle(20, 300, 100, 60, 30));
|
||||
|
||||
add(new Arc(200, 200, 60, 90, 120));
|
||||
|
||||
add(new Polygon(250, 40, 300, 55, 321, 83, 200, 300));
|
||||
shapes.add(new Point(250, 40));
|
||||
shapes.add(new Point(300, 55));
|
||||
shapes.add(new Point(321, 83));
|
||||
shapes.add(new Point(200, 300));
|
||||
|
||||
add(new Triangle(300, 55, 355, 75, 345, 25));
|
||||
add(new Quad(300, 55, 355, 75, 345, 25, 300, 10));
|
||||
|
||||
add(new Curve(50, 50, 350, 50, 350, 350));
|
||||
add(new Curve(50, 50, 50, 350, 350, 50, 350, 350));
|
||||
|
||||
shapes.add(new Picture(300, 300, "WitchCraftIcons_122_t.PNG"));
|
||||
|
||||
add(new Text(200, 40, "Shapes 😊"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void aktualisieren( double delta ) {
|
||||
|
||||
public void update( double delta ) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void zeichnen() {
|
||||
formen.leeren();
|
||||
public void mouseClicked() {
|
||||
for( Shape s : shapes.getShapes() ) {
|
||||
randomizeShape(s);
|
||||
s.move(10, 10);
|
||||
}
|
||||
}
|
||||
|
||||
private void add( Shape s ) {
|
||||
shapes.add(randomizeShape(s));
|
||||
}
|
||||
|
||||
private Shape randomizeShape( Shape s ) {
|
||||
if( !(s instanceof Arc) && !(s instanceof Curve) && !(s instanceof Line) && !(s instanceof Arrow) ) {
|
||||
s.setFillColor(randomColor());
|
||||
}
|
||||
s.setStrokeColor(randomColor());
|
||||
s.setStrokeWeight(random(.75, 2.25));
|
||||
if( randomBool(20) ) {
|
||||
s.setStrokeType(DASHED);
|
||||
} else {
|
||||
s.setStrokeType(SOLID);
|
||||
}
|
||||
|
||||
//s.moveTo(random(20, 380), random(20, 380));
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private void showDot( Point2D p ) {
|
||||
showDot(p.getX(), p.getY(), randomColor());
|
||||
}
|
||||
private void showDot( double x, double y, Color clr ) {
|
||||
Punkt p = new Punkt(x, y);
|
||||
p.setFuellfarbe(clr);
|
||||
p.setKonturFarbe(clr);
|
||||
formen.anzeigen(p);
|
||||
}
|
||||
|
||||
Random rand = new Random();
|
||||
private void showDot( double x, double y, Color clr ) {
|
||||
Point p = new Point(x, y);
|
||||
p.setFillColor(clr);
|
||||
p.setStrokeColor(clr);
|
||||
shapes.add(p);
|
||||
}
|
||||
|
||||
private Color randomColor() {
|
||||
return new Color(
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package schule.ngb.zm;
|
||||
|
||||
public class TestVector {
|
||||
|
||||
}
|
Loading…
Reference in New Issue