EOS 2  1.1.0
Einfache Objektbasierte Sprache
Picture2D.java
gehe zur Dokumentation dieser Datei
1 package de.lathanda.eos.base;
2 
3 import java.awt.BasicStroke;
4 import java.awt.Component;
5 import java.awt.Font;
6 import java.awt.Graphics2D;
7 import java.awt.Polygon;
8 import java.awt.RenderingHints;
9 import java.awt.Shape;
10 import java.awt.geom.AffineTransform;
11 import java.awt.geom.Ellipse2D;
12 import java.awt.geom.Rectangle2D;
13 import java.util.LinkedList;
14 
15 import de.lathanda.eos.base.layout.Transform;
16 import de.lathanda.eos.base.math.Point;
17 
23 public class Picture2D extends Picture {
24 
25  private Graphics2D g;
26  private AffineTransform baseTrans;
27  //drawing information
28  private Transform transform;
29  private final LinkedList<Transform> storedTransform;
30  private final LinkedList<AffineTransform> storedAffineTransform;
31  //Grid
32  private double gridwidth = 10;
33  private static double GRID_LINE_WIDTH = 0.25;
34  private static double AXIS_LINE_WIDTH = 1;
35  private final LineDescriptor gridline = new LineDescriptor(MutableColor.GRID, LineStyle.SOLID, GRID_LINE_WIDTH);
36  private final LineDescriptor axesline = new LineDescriptor(MutableColor.GRID, LineStyle.SOLID, AXIS_LINE_WIDTH);
37  private boolean gridvisible = true;
38  //coordinate transformation
39  protected int pCenterX;
40  protected int pCenterY;
41  private int pWidth;
42  private int pHeight;
43  private Component target;
48  private static double ZOOM = 128d;
49  public Picture2D(double width, double height, Component target) {
50  super();
51  this.target = target;
52  font = new Font("Serif", Font.PLAIN, 12);
53  transform = Transform.ID;
54  storedTransform = new LinkedList<>();
55  storedAffineTransform = new LinkedList<>();
56  setSize(mm2pixel(width), mm2pixel(height));
57  }
62  public void setGraphics(Graphics2D g) {
63  this.g = g;
64  g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
65  RenderingHints.VALUE_ANTIALIAS_ON);
66 
67  g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
68  RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
69  g.translate(pCenterX, pCenterY);
70  g.scale(1/ZOOM, 1/ZOOM);
71  g.translate(mm2unit(-centerX), mm2unit(centerY));
72  baseTrans = g.getTransform();
73  }
79  public final void setSize(int width, int height) {
80  pWidth = width;
81  pHeight = height;
82  this.pCenterX = width/2;
83  this.pCenterY = height/2;
84  this.halfwidth = pixel2mmInternal(pWidth/2);
85  this.halfheight = pixel2mmInternal(pHeight/2);
86  }
91  public void setScale(double scale) {
92  this.scale = scale;
93  this.halfwidth = pixel2mmInternal(pWidth/2);
94  this.halfheight = pixel2mmInternal(pHeight/2);
95  }
100  public double getScale() {
101  return scale;
102  }
108  public void drag(int dx, int dy) {
109  centerX += pixel2mmInternal(dx);
110  centerY -= pixel2mmInternal(dy);
111  }
117  public void setCenter(double x, double y) {
118  centerX = x;
119  centerY = y;
120  }
126  private double pixel2mmInternal(int pixel) {
127  return pixel / scale / scaleBase;
128  }
134  public double pixel2mm(int pixel) {
135  return pixel / scaleBase;
136  }
142  public int mm2pixel(double mm) {
143  return (int)(mm * scaleBase);
144  }
150  private int mm2unit(double mm) {
151  return (int)mm2unitd(mm);
152  }
158  private float mm2unitf(double mm) {
159  return (float)mm2unitd(mm);
160  }
167  private double mm2unitd(double mm) {
168  return mm * scaleBase * scale * ZOOM;
169  }
176  public Point pointFromPixel(int x, int y) {
177  return new Point(pixel2mmInternal(x - pCenterX) + centerX, centerY - pixel2mmInternal(y - pCenterY));
178  }
179 
180  @Override
181  public void drawLine(double x1, double y1, double x2, double y2) {
182  applyLine();
183  g.drawLine(mm2unit(x1), -mm2unit(y1), mm2unit(x2), -mm2unit(y2));
184  }
185 
186  @Override
187  public void pushTransform() {
188  storedTransform.push(transform);
189  storedAffineTransform.push(g.getTransform());
190  }
191  @Override
192  public void restoreTransform() {
193  g.setTransform(storedAffineTransform.pop());
194  transform = storedTransform.pop();
195  }
196  @Override
197  public void applyTransform(Transform tf) {
198  transform = transform.transform(tf);
199  g.setTransform(baseTrans);
200  g.translate(mm2unitd(transform.getdx()), -mm2unitd(transform.getdy()));
201  g.rotate(-transform.getAngle());
202  if (transform.getMirrorX()) {
203  g.scale(-transform.getScale(),transform.getScale());
204  } else {
205  g.scale(transform.getScale(),transform.getScale());
206  }
207  }
208  @Override
209  public void translate(double dx, double dy) {
210  transform.translate(dx, dy);
211  g.setTransform(baseTrans);
212  g.translate(mm2unitd(transform.getdx()), -mm2unitd(transform.getdy()));
213  g.rotate(-transform.getAngle());
214  g.scale(transform.getScale(), transform.getScale());
215  if (transform.getMirrorX()) {
216  g.scale(-1,1);
217  }
218  }
219  @Override
220  public void rotate(double angle) {
221  transform.rotate(angle);
222  g.setTransform(baseTrans);
223  g.translate(mm2unitd(transform.getdx()), -mm2unitd(transform.getdy()));
224  g.rotate(-transform.getAngle());
225  g.scale(transform.getScale(), transform.getScale());
226  if (transform.getMirrorX()) {
227  g.scale(-1,1);
228  }
229  }
234  private boolean applyLine() {
235  g.setColor(line.getColor().getColor());
236  switch (line.getLineStyle()) {
237  case DASHED:
238  g.setStroke(new BasicStroke(
239  mm2unitf(line.getDrawWidth()),
240  BasicStroke.CAP_ROUND,
241  BasicStroke.JOIN_ROUND,
242  1f,
243  new float[]{mm2unitf(5), mm2unitf(5)},
244  0
245  ));
246  break;
247  case SOLID:
248  g.setStroke(new BasicStroke(
249  mm2unitf(line.getDrawWidth()),
250  BasicStroke.CAP_ROUND,
251  BasicStroke.JOIN_ROUND
252  ));
253  break;
254  case DOTTED:
255  g.setStroke(new BasicStroke(
256  mm2unitf(line.getDrawWidth()),
257  BasicStroke.CAP_ROUND,
258  BasicStroke.JOIN_ROUND,
259  1f,
260  new float[]{mm2unitf(0.5), mm2unitf(3)},
261  0
262  ));
263  break;
264  case DASHED_DOTTED:
265  g.setStroke(new BasicStroke(
266  mm2unitf(line.getDrawWidth()),
267  BasicStroke.CAP_ROUND,
268  BasicStroke.JOIN_ROUND,
269  1f,
270  new float[]{mm2unitf(5), mm2unitf(1),
271  mm2unitf(0.5), mm2unitf(1)},
272  0
273  ));
274  break;
275  case INVISIBLE:
276  return false;
277  }
278  return true;
279  }
280 
281  @Override
282  public void drawPolygon(double[] x, double[] y) {
283  int[] xPoints = new int[x.length];
284  int[] yPoints = new int[y.length];
285  for (int i = 0; i < x.length; i++) {
286  xPoints[i] = mm2unit(x[i]);
287  yPoints[i] = -mm2unit(y[i]);
288  }
289  drawShape(new Polygon(xPoints, yPoints, x.length));
290  }
291 
292  @Override
293  public void drawRect(double x, double y, double width, double height) {
294  drawShape(new Rectangle2D.Double(
295  mm2unitd(x),
296  -mm2unitd(y+height),
297  mm2unitd(width),
298  mm2unitd(height)
299  )
300  );
301  }
302 
303  @Override
304  public void drawEllipse(double x, double y, double radiusX, double radiusY) {
305  drawShape(new Ellipse2D.Double(
306  mm2unitd(x-radiusX),
307  -mm2unitd(y+radiusY),
308  2*mm2unitd(radiusX),
309  2*mm2unitd(radiusY)
310  )
311  );
312  }
313 
314  @Override
315  public void drawStringAt(String text, double x, double y) {
316  applyLine();
317  g.setFont(font.deriveFont((float)(font.getSize()*scale*ZOOM)));
318  g.drawString(text, mm2unit(x), -mm2unit(y));
319  }
320 
321  @Override
322  protected double getStringWidth(String text) {
323  return pixel2mm(target.getFontMetrics(font).stringWidth(text));
324  }
325 
326  @Override
327  protected double getStringHeight() {
328  return pixel2mm(target.getFontMetrics(font).getHeight());
329  }
330 
331  @Override
332  protected double getStringDescent() {
333  return pixel2mm(target.getFontMetrics(font).getDescent());
334  }
335  //********
336  //* Grid *
337  //********
341  public void drawCoordinateSystem() {
342  if (!gridvisible) return;
343  setLine(gridline);
344  line.setDrawWidth(GRID_LINE_WIDTH / scale);
345  for(double x = 0; x < getMaxX(); x += gridwidth) {
346  drawLine(x, getMinY(), x, getMaxY());
347  }
348  for(double x = 0; x > getMinX(); x -= gridwidth) {
349  drawLine(x, getMinY(), x, getMaxY());
350  }
351  for(double y = 0; y < getMaxY(); y += gridwidth) {
352  drawLine(getMinX(), y, getMaxX(), y);
353  }
354  for(double y = 0; y > getMinY(); y -= gridwidth) {
355  drawLine(getMinX(), y, getMaxX(), y);
356  }
357  setLine(axesline);
358  line.setDrawWidth(AXIS_LINE_WIDTH / scale);
359  drawLine(0, getMinY(), 0, getMaxY());
360  drawLine(getMinX(), 0, getMaxX(), 0);
361  }
366  public void setGridColor(MutableColor color) {
367  gridline.setColor(color);
368  axesline.setColor(color);
369  }
375  return gridline.getColor();
376  }
381  public void setGridWidth(double gridwidth) {
382  this.gridwidth = gridwidth;
383  }
388  public double getGridWidth() {
389  return gridwidth;
390  }
395  public void setGridVisible(boolean b) {
396  gridvisible = b;
397  }
402  public boolean getGridVisible() {
403  return gridvisible;
404  }
405  @Override
406  public void drawImage(Image image, double x, double y, double width, double height) {
407  g.drawImage(
408  image.getImage(),
409  mm2unit(x),
410  -mm2unit(y+height),
411  mm2unit(x+width),
412  -mm2unit(y),
413  image.getImageX(),
414  image.getImageY(),
415  image.getImageX()+image.getImageWidth(),
416  image.getImageX()+image.getImageHeight(),
417  null
418  );
419  }
420  @Override
421  public void drawImage(Image image, double x, double y, double width, double height, Scaling scale) {
422  if (scale == Scaling.STRETCH) {
423  g.drawImage(
424  image.getImage(),
425  mm2unit(x),
426  -mm2unit(y+height),
427  mm2unit(x+width),
428  -mm2unit(y),
429  image.getImageX(),
430  image.getImageY(),
431  image.getImageX()+image.getImageWidth(),
432  image.getImageY()+image.getImageHeight(),
433  null
434  );
435  } else {
436  double imageProportion = (double)image.getImageWidth() / (double)image.getImageHeight();
437  double targetProportion = width / height;
438  double s = imageProportion / targetProportion;
439  if (scale == Scaling.FIT) {
440  if (s > 1d) {
441  //image wide, adjust height
442  g.drawImage(
443  image.getImage(),
444  mm2unit(x),
445  -mm2unit(y+height*(0.5+0.5/s)),
446  mm2unit(x+width),
447  -mm2unit(y+height*(0.5-0.5/s)),
448  image.getImageX(),
449  image.getImageY(),
450  image.getImageX()+image.getImageWidth(),
451  image.getImageY()+image.getImageHeight(),
452  null
453  );
454  } else {
455  g.drawImage(
456  image.getImage(),
457  mm2unit(x+width*(0.5-s/2)),
458  -mm2unit(y+height),
459  mm2unit(x+width*(0.5+s/2)),
460  -mm2unit(y),
461  image.getImageX(),
462  image.getImageY(),
463  image.getImageX()+image.getImageWidth(),
464  image.getImageY()+image.getImageHeight(),
465  null
466  );
467  }
468  } else if (scale == Scaling.CUT) {
469  if (s > 1) {
470  g.drawImage(
471  image.getImage(),
472  mm2unit(x),
473  -mm2unit(y+height),
474  mm2unit(x+width),
475  -mm2unit(y),
476  image.getImageX()+(int)(image.getImageWidth()*(0.5-0.5/s)),
477  image.getImageY(),
478  image.getImageX()+(int)(image.getImageWidth()*(0.5+0.5/s)),
479  image.getImageY()+image.getImageHeight(),
480  null
481  );
482  } else {
483  g.drawImage(
484  image.getImage(),
485  mm2unit(x),
486  -mm2unit(y+height),
487  mm2unit(x+width),
488  -mm2unit(y),
489  image.getImageX(),
490  image.getImageY()+(int)(image.getImageHeight()*(0.5-s/2)),
491  image.getImageX()+image.getImageWidth(),
492  image.getImageY()+(int)(image.getImageHeight()*(0.5+s/2)),
493  null
494  );
495  }
496  }
497  }
498  }
499 
500  @Override
501  public void drawImage(Image image, double x, double y, double width, double height, boolean mirror,
502  double angle) {
503  AffineTransform at = g.getTransform();
504  g.translate(mm2unit(x+width/2), -mm2unit(y+height/2));
505  g.rotate(angle);
506  g.scale(-1, 1);
507  g.drawImage(
508  image.getImage(),
509  mm2unit(-width/2),
510  -mm2unit(-height/2),
511  mm2unit(width/2),
512  -mm2unit(height/2),
513  image.getImageX(),
514  image.getImageY(),
515  image.getImageX()+image.getImageWidth(),
516  image.getImageX()+image.getImageHeight(),
517  null
518  );
519  g.setTransform(at);
520  }
524  public void restoreStyles() {
525  line = new LineDescriptor();
526  fill = new FillDescriptor();
527  }
532  private void drawShape(Shape shape) {
533  //fill
534  g.setColor(fill.getColor().getColor());
535  g.setPaint(fill.getColor().getColor());
536  switch (fill.getFillStyle()) {
537  case FILLED:
538  g.fill(shape);
539  break;
540  case RULED:
541  {
542  Shape old = g.getClip();
543  double linegap = mm2unitd(2);
544  g.setClip(shape);
545  g.setStroke(new BasicStroke(mm2unitf(0.25f)));
546  Rectangle2D border = shape.getBounds2D();
547  for( double y = border.getMinY() + border.getWidth() % linegap; y < border.getMaxY(); y += linegap ) {
548  g.drawLine((int)border.getMinX(), (int)y, (int)border.getMaxX(), (int)y);
549  }
550  g.setClip(old);
551  break;
552  }
553  case CHECKED:
554  {
555  Shape old = g.getClip();
556  double checksize = mm2unitd(5);
557  g.setClip(shape);
558  g.setStroke(new BasicStroke(mm2unitf(0.25f)));
559  Rectangle2D border = shape.getBounds2D();
560  for( double y = border.getMinY() + border.getHeight() % checksize; y < border.getMaxY(); y += checksize ) {
561  g.drawLine((int)border.getMinX(), (int)y, (int)border.getMaxX(), (int)y);
562  }
563  for( double x = border.getMinX() + border.getWidth() % checksize; x < border.getMaxX(); x += checksize ) {
564  g.drawLine((int)x, (int)border.getMinY(), (int)x, (int)border.getMaxY());
565  }
566  g.setClip(old);
567  break;
568  }
569  case TRANSPARENT:
570  //invisible
571  }
572  //draw line
573  if(applyLine()) {
574  g.draw(shape);
575  }
576  }
577 }
BufferedImage getImage()
Definition: Image.java:42
static final MutableColor GRID
double pixel2mm(int pixel)
Definition: Picture2D.java:134
void setGridColor(MutableColor color)
Definition: Picture2D.java:366
void drawImage(Image image, double x, double y, double width, double height)
Definition: Picture2D.java:406
void drawStringAt(String text, double x, double y)
Definition: Picture2D.java:315
void rotate(double angle)
Definition: Picture2D.java:220
void setGridWidth(double gridwidth)
Definition: Picture2D.java:381
Picture2D(double width, double height, Component target)
Definition: Picture2D.java:49
final void setSize(int width, int height)
Definition: Picture2D.java:79
void translate(double dx, double dy)
Definition: Picture2D.java:209
void drawLine(double x1, double y1, double x2, double y2)
Definition: Picture2D.java:181
void applyTransform(Transform tf)
Definition: Picture2D.java:197
void setGridVisible(boolean b)
Definition: Picture2D.java:395
Point pointFromPixel(int x, int y)
Definition: Picture2D.java:176
void drawPolygon(double[] x, double[] y)
Definition: Picture2D.java:282
void setScale(double scale)
Definition: Picture2D.java:91
void drawImage(Image image, double x, double y, double width, double height, boolean mirror, double angle)
Definition: Picture2D.java:501
void setGraphics(Graphics2D g)
Definition: Picture2D.java:62
void drag(int dx, int dy)
Definition: Picture2D.java:108
double getStringWidth(String text)
Definition: Picture2D.java:322
void drawImage(Image image, double x, double y, double width, double height, Scaling scale)
Definition: Picture2D.java:421
void drawRect(double x, double y, double width, double height)
Definition: Picture2D.java:293
void drawEllipse(double x, double y, double radiusX, double radiusY)
Definition: Picture2D.java:304
void setCenter(double x, double y)
Definition: Picture2D.java:117
void setLine(LineDescriptor line)
Definition: Picture.java:421
Geometrische Transformation.
Definition: Transform.java:13
Transform rotate(double angle)
Definition: Transform.java:34
Transform translate(double dx, double dy)
Definition: Transform.java:67
Transform transform(Transform child)
Definition: Transform.java:83
abstract void draw(Picture picture)
Impressum