+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ * VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.g2d.elementclass.operationsymbols;\r
+\r
+import java.awt.BasicStroke;\r
+import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.Graphics2D;\r
+import java.awt.Polygon;\r
+import java.awt.Shape;\r
+import java.awt.Stroke;\r
+import java.awt.geom.Ellipse2D;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Rectangle2D;\r
+import java.util.EnumSet;\r
+\r
+import org.simantics.g2d.image.Image;\r
+import org.simantics.g2d.image.impl.Shadow;\r
+import org.simantics.g2d.image.impl.Shadow.ShadowParameters;\r
+import org.simantics.g2d.utils.GeometryUtils;\r
+import org.simantics.g2d.utils.PathUtils;\r
+import org.simantics.scenegraph.Node;\r
+import org.simantics.scenegraph.g2d.G2DParentNode;\r
+import org.simantics.utils.ObjectUtils;\r
+\r
+/**\r
+ * @author Toni Kalajainen\r
+ */\r
+public class OperationSymbols {\r
+\r
+ static final double SHADOW_SIZE = 100;\r
+ static final Color BORDER_COLOR = Color.GRAY;\r
+ static final Color FILL_COLOR = Color.GRAY;\r
+ static final Color SECONDARY_COLOR = Color.GREEN;\r
+ static final ShadowParameters SHADOW = new ShadowParameters(0.5, Color.BLACK, 2);\r
+\r
+ static final Color HOT = new Color(50, 50, 200);\r
+ static final Color COLD = new Color(190, 190, 255);\r
+\r
+ public static final BoilerHeatExchanger[] BOILER_HES = new BoilerHeatExchanger[] {\r
+ new BoilerHeatExchanger(null, HOT, HOT, null, HOT),\r
+ new BoilerHeatExchanger(HOT, null, COLD, COLD, HOT),\r
+ new BoilerHeatExchanger(HOT, null, COLD, null, HOT),\r
+ new BoilerHeatExchanger(HOT, null, null, HOT, HOT)\r
+ };\r
+\r
+ public static final Image BOILER_SYMBOL = new BoilerSymbol2(FILL_COLOR, FILL_COLOR, BOILER_HES);\r
+ public static final Image BOILER_SHADOW = new Shadow(BOILER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image COMPRESSOR_SYMBOL = new CompressorSymbol(FILL_COLOR, BORDER_COLOR);\r
+ public static final Image COMPRESSOR_SHADOW = new Shadow(COMPRESSOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image NO_SPIN_SYMBOL = new NoSpinSymbol(FILL_COLOR, BORDER_COLOR);\r
+ public static final Image NO_SPIN_SHADOW = new Shadow(NO_SPIN_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image CONTROLVALVE_SYMBOL = new ControlValveSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image CONTROLVALVE_SHADOW = new Shadow(CONTROLVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image THREEWAYVALVE_SYMBOL = new ThreeWayValveSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image THREEWAYVALVE_SHADOW = new Shadow(THREEWAYVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image HEATEXCHANGER_SYMBOL = new HeatExchangerSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image HEATEXCHANGER_SHADOW = new Shadow(HEATEXCHANGER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image PUMP_SYMBOL = new PumpSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image PUMP_SHADOW = new Shadow(PUMP_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image SHUTOFFVALVE_SYMBOL = new ShutoffValveSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image SHUTOFFVALVE_SHADOW = new Shadow(SHUTOFFVALVE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image SWITCH_SYMBOL = new SwitchSymbol(BORDER_COLOR);\r
+ public static final Image SWITCH_SHADOW = new Shadow(SWITCH_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image TURBINE_SYMBOL = new TurbineSymbol(BORDER_COLOR, FILL_COLOR);\r
+ public static final Image TURBINE_SHADOW = new Shadow(TURBINE_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image VOLTAGETRANSFORMER_SYMBOL = new VoltageTransformerSymbol(SECONDARY_COLOR, BORDER_COLOR);\r
+ public static final Image VOLTAGETRANSFORMER_SHADOW = new Shadow(VOLTAGETRANSFORMER_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image CHIMNEY_SYMBOL = new ChimneySymbol(SECONDARY_COLOR, BORDER_COLOR);\r
+ public static final Image CHIMNEY_SHADOW = new Shadow(CHIMNEY_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image GENERATOR_SYMBOL = new GeneratorSymbol(SECONDARY_COLOR, BORDER_COLOR);\r
+ public static final Image GENERATOR_SHADOW = new Shadow(GENERATOR_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image TANK_SYMBOL = new TankSymbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR);\r
+ public static final Image TANK_SHADOW = new Shadow(TANK_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static final Image TANK2_SYMBOL = new Tank2Symbol(new Rectangle2D.Double(0,0, 20.0, 8.0), 2.0, SECONDARY_COLOR, BORDER_COLOR, HOT);\r
+ public static final Image TANK2_SHADOW = new Shadow(TANK2_SYMBOL, SHADOW, SHADOW_SIZE, SHADOW_SIZE);\r
+\r
+ public static class BoilerSymbol extends PS implements Image {\r
+ public static final int DIM = 10;\r
+ public static final Polygon SHAPE =\r
+ new Polygon(new int[] {-DIM, -DIM, 0, DIM, DIM, 0}, new int[] {2*DIM, -2*DIM, -3*DIM, -2*DIM, 2*DIM, 3*DIM}, 6);\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public BoilerSymbol(Color bc, Color fc) {\r
+ super(SHAPE.getBounds2D(), bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+// if (fc!=null) {\r
+// g.setColor(fc);\r
+// g.fill(SHAPE);\r
+// }\r
+// if (bc!=null) {\r
+// g.setColor(bc);\r
+// g.draw(SHAPE);\r
+// }\r
+ }\r
+ }\r
+\r
+ public static class BoilerHeatExchanger {\r
+ public final Color color;\r
+ public final Color topLeft, topRight, bottomLeft, bottomRight;\r
+ public BoilerHeatExchanger(Color topLeft, Color topRight,\r
+ Color bottomLeft, Color bottomRight,\r
+ Color color) {\r
+ this.bottomLeft = bottomLeft;\r
+ this.bottomRight = bottomRight;\r
+ this.color = color;\r
+ this.topLeft = topLeft;\r
+ this.topRight = topRight;\r
+ }\r
+ }\r
+\r
+ public static class BoilerSymbol2 extends PS implements Image {\r
+\r
+ public static Path2D HE = PathUtils.path(10,0, 0,0, 0,5, 5,10, -5,10, 0,15, 0,20);\r
+\r
+ public static Rectangle2D getBoilerRect(BoilerHeatExchanger ... hes)\r
+ {\r
+ return new Rectangle2D.Double(-10, 0, 20, hes.length*25+25);\r
+ }\r
+\r
+ public static Shape getBoilerShape(BoilerHeatExchanger ... hes)\r
+ {\r
+ Path2D p = new Path2D.Double();\r
+ p.moveTo(-10, 10);\r
+ p.lineTo( 0, 0);\r
+ p.lineTo( 10, 10);\r
+ double h = hes.length * 25;\r
+ p.lineTo( 10, h+15);\r
+ p.lineTo( 0, h+25);\r
+ p.lineTo(-10, h+15);\r
+ p.closePath();\r
+ return p;\r
+ }\r
+\r
+ private final Shape shape;\r
+ private final BoilerHeatExchanger [] hes;\r
+\r
+ public BoilerSymbol2(Color fc, Color bc, BoilerHeatExchanger ... hes) {\r
+ super( getBoilerRect(hes), bc, fc, null, null);\r
+ shape = getBoilerShape(hes);\r
+ this.hes = hes;\r
+ }\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(shape);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(shape);\r
+ }\r
+ // paint heat exchangers\r
+ g.translate(0, 15);\r
+ for (BoilerHeatExchanger he : hes)\r
+ {\r
+ g.setColor(he.color);\r
+ g.draw(HE);\r
+ if (he.topLeft!=null) {\r
+ g.setColor(he.topLeft);\r
+ g.drawLine(-10, 0, 0, 0);\r
+ }\r
+ if (he.topRight!=null) {\r
+ g.setColor(he.topRight);\r
+ g.drawLine(0, 0, 10, 0);\r
+ }\r
+ if (he.bottomLeft!=null) {\r
+ g.setColor(he.bottomLeft);\r
+ g.drawLine(-10, 20, 0, 20);\r
+ }\r
+ if (he.bottomRight!=null) {\r
+ g.setColor(he.bottomRight);\r
+ g.drawLine(0, 20, 10, 20);\r
+ }\r
+ g.translate(0, 25);\r
+ }\r
+ }\r
+ }\r
+\r
+ public static class ChimneySymbol extends PS implements Image {\r
+\r
+ public static final int DIM = 10;\r
+ public static final int D2 = 8;\r
+ public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
+ public static final Shape C2 = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
+\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-10, -10, 20, 40);\r
+\r
+ public ChimneySymbol(Color fc, Color bc) {\r
+ super( BOUNDS, bc, fc, null, null);\r
+ assert(bc!=null);\r
+ }\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.fill(C2);\r
+ g.fillRect(-5, 14, 10, 8);\r
+ g.setColor(bc);\r
+ g.draw(C1);\r
+ g.draw(C2);\r
+\r
+ g.drawLine(0, DIM, 0, 15);\r
+ g.drawRect(-5, 14, 10, 8);\r
+ g.drawLine(-5, 14, 5, 22);\r
+ }\r
+ }\r
+\r
+\r
+ public static class GeneratorSymbol extends PS implements Image {\r
+\r
+ public static final int DIM = 10;\r
+ public static final Shape C1 = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
+\r
+ public static final Rectangle2D BOUNDS = C1.getBounds2D();\r
+ private final static Font FONT = Font.decode("Serif-12");\r
+\r
+ public GeneratorSymbol(Color fc, Color bc) {\r
+ super( BOUNDS, bc, fc, null, null);\r
+ assert(bc!=null && fc!=null);\r
+ }\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.fill(C1);\r
+ g.setColor(bc);\r
+ g.draw(C1);\r
+ g.setFont(FONT);\r
+ g.drawString("G", -4, 4);\r
+ }\r
+ }\r
+\r
+ public static class NoSpinSymbol extends PS {\r
+ public NoSpinSymbol(Color fc, Color bc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int DIM = 10;\r
+ public static final int D2 = 8;\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM, 2*DIM, 2*DIM);\r
+ public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setStroke(STROKE);\r
+ g.setColor(fc);\r
+ g.fillRect(-DIM, -DIM, DIM*2, DIM*2);\r
+ g.setColor(bc);\r
+ g.drawRect(-DIM, -DIM, DIM*2, DIM*2);\r
+ g.draw(CIRCLE);\r
+ g.drawLine(-DIM/3, -DIM/3, DIM/3, DIM/3);\r
+ g.drawLine(DIM/3, -DIM/3, -DIM/3, DIM/3);\r
+ }\r
+ }\r
+\r
+ public static class ControlValveSymbol extends PS implements Image {\r
+\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int D = 10;\r
+ public static final Path2D SHAPE =\r
+ PathUtils.closedPath(-D,-D, -D,D, D,-D, D,D );\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public ControlValveSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(SHAPE);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(SHAPE);\r
+ }\r
+ }\r
+ }\r
+\r
+ public static class ThreeWayValveSymbol extends PS implements Image {\r
+\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int D = 10;\r
+ public static final Path2D SHAPE =\r
+ PathUtils.closedPath(-D,D*2/3, -D,-D*2/3, 0,0, -D*2/3,-D, D*2/3,-D, 0,0, D,D*2/3, D,-D*2/3, 0,0 );\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public ThreeWayValveSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(SHAPE);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(SHAPE);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ public static class HeatExchangerSymbol extends PS {\r
+\r
+ public HeatExchangerSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int D = 10;\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D);\r
+ public static final int xPoints[] = new int [] {-D, 0, 0, -D/2, D/2, 0, 0, D};\r
+ public static final int yPoints[] = new int [] {D/2, D/2, D/8, 0, 0, -D/8, -D/2, -D/2};\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.fill(BOUNDS);\r
+ g.setColor(bc);\r
+ g.draw(BOUNDS);\r
+ g.setStroke(STROKE);\r
+ g.drawPolyline(xPoints, yPoints, xPoints.length);\r
+ }\r
+ }\r
+\r
+ public static class PumpSymbol extends PS {\r
+\r
+ public PumpSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int DIM = 10;\r
+ public static final int D2 = 12;\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D2, -D2, 2*D2, 2*D2);\r
+ public static final Shape CIRCLE = new Ellipse2D.Double(-D2, -D2, D2*2, D2*2);\r
+ public static final Polygon SHAPE =\r
+ new Polygon(new int[] {-DIM, -DIM, 0, 0, DIM, 0, 0}, new int[] {DIM/4, -DIM/4, -DIM/4, -DIM, 0, DIM, DIM/4}, 7);\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.fill(CIRCLE);\r
+ g.setColor(bc);\r
+ g.setStroke( STROKE );\r
+ g.draw(CIRCLE);\r
+ g.draw(SHAPE);\r
+ }\r
+ }\r
+\r
+\r
+ public static class ShutoffValveSymbol extends PS implements Image {\r
+\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int DIM = 10;\r
+ public static final Path2D SHAPE =\r
+ PathUtils.closedPath(-DIM,-DIM, -DIM,DIM, DIM,-DIM, DIM,DIM );\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public ShutoffValveSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(SHAPE);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(SHAPE);\r
+ g.drawLine(0, -DIM, 0, DIM);\r
+ }\r
+ }\r
+ }\r
+\r
+\r
+ public static class SwitchSymbol extends PS {\r
+\r
+ public SwitchSymbol(Color bc) {\r
+ super(BOUNDS, bc, null, null, null);\r
+ }\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int D = 10;\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-D, -D, 2*D, 2*D);\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(bc);\r
+ g.setStroke(STROKE);\r
+\r
+ g.drawLine(0, -D, 0, D);\r
+ g.drawLine(-D/4, -D/2, D/4, -D/2);\r
+ g.drawLine(-D, 0, D, 0);\r
+ g.drawLine(-D/4, D/2, D/4, D/2);\r
+ }\r
+ }\r
+\r
+\r
+ public static class TurbineSymbol extends PS implements Image {\r
+\r
+ public static final int DIM = 10;\r
+ public static final Polygon SHAPE =\r
+ new Polygon(new int[] {-DIM, -DIM, DIM, DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4);\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public TurbineSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(SHAPE);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(SHAPE);\r
+ }\r
+ }\r
+ }\r
+\r
+ public static class CompressorSymbol extends PS implements Image {\r
+\r
+ public static final int DIM = 10;\r
+ public static final Polygon SHAPE =\r
+ new Polygon(new int[] {DIM, DIM, -DIM, -DIM}, new int[] {-DIM, DIM, DIM*2, -DIM*2}, 4);\r
+ public static final Rectangle2D BOUNDS = SHAPE.getBounds2D();\r
+\r
+ public CompressorSymbol(Color bc, Color fc) {\r
+ super(BOUNDS, bc, fc, null, null);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ if (fc!=null) {\r
+ g.setColor(fc);\r
+ g.fill(SHAPE);\r
+ }\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(SHAPE);\r
+ }\r
+ }\r
+ }\r
+\r
+ public static class VoltageTransformerSymbol extends PS implements Image {\r
+\r
+ public static final Stroke STROKE = new BasicStroke(1.5f);\r
+ public static final int DIM = 10;\r
+ public static final Rectangle2D BOUNDS = new Rectangle2D.Double(-DIM, -DIM*1.7, 2*DIM, 2*DIM*1.7);\r
+ public static final Shape CIRCLE = new Ellipse2D.Double(-DIM, -DIM, DIM*2, DIM*2);\r
+\r
+ public VoltageTransformerSymbol(Color c1, Color c2) {\r
+ super(BOUNDS, null, null, c1, c2);\r
+ }\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setStroke(STROKE);\r
+ Graphics2D sg = (Graphics2D) g.create();\r
+\r
+ sg.clipRect(-DIM*2, -DIM*2, DIM*4, DIM*2);\r
+ sg.setColor(c1);\r
+ sg.translate(0, -0.7*DIM);\r
+ sg.draw(CIRCLE);\r
+ sg.setColor(c2);\r
+ sg.translate(0, 1.4*DIM);\r
+ sg.draw(CIRCLE);\r
+ sg.dispose();\r
+\r
+ g.clipRect(-DIM*2, 0, DIM*4, DIM*2);\r
+ g.setColor(c2);\r
+ g.translate(0, 0.7*DIM);\r
+ g.draw(CIRCLE);\r
+ g.setColor(c1);\r
+ g.translate(0, -1.4*DIM);\r
+ g.draw(CIRCLE);\r
+ }\r
+ }\r
+\r
+ public static class TankSymbol extends PS implements Image {\r
+\r
+ /**\r
+ * Create tank shape.\r
+ * @param r rectangle\r
+ * @param cap cap size\r
+ * @return tank shape\r
+ */\r
+ public static Path2D createTankShape(Rectangle2D r, double cap)\r
+ {\r
+ double x1 = r.getMinX();\r
+ double y1 = r.getMinY();\r
+ double x2 = r.getMaxX();\r
+ double y2 = r.getMaxY();\r
+ Path2D p = new Path2D.Double();\r
+ p.moveTo(x1+cap, y1);\r
+ p.lineTo(x2-cap, y1);\r
+ p.quadTo(x2,y1, x2,y1+cap);\r
+ p.lineTo(x2, y2-cap);\r
+ p.quadTo(x2, y2, x2-cap, y2);\r
+ p.lineTo(x1+cap, y2);\r
+ p.quadTo(x1, y2, x1, y2-cap);\r
+ p.lineTo(x1, y1+cap);\r
+ p.quadTo(x1, y1, x1+cap, y1);\r
+ return p;\r
+ }\r
+\r
+ Path2D shape;\r
+\r
+ public TankSymbol(Rectangle2D rect, double cap, Color bc, Color fc) {\r
+ super(rect, bc, fc, null, null);\r
+ shape = createTankShape(rect, cap);\r
+ }\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.setStroke(GeometryUtils.BASIC_STROKE);\r
+ g.fill(shape);\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(shape);\r
+ }\r
+ }\r
+\r
+ }\r
+\r
+ public static class Tank2Symbol extends PS implements Image {\r
+\r
+ public static Path2D createWShape()\r
+ {\r
+ Path2D p = new Path2D.Double();\r
+ double k = Math.sqrt(2);\r
+ p.moveTo(-1, -1);\r
+ p.quadTo(0, -k, 1, -1);\r
+ p.quadTo(k, 0, 1, 1);\r
+ p.quadTo(0, k, -1, 1);\r
+ p.quadTo(-k, 0, -1, -1);\r
+ p.lineTo(-1, 1);\r
+ p.lineTo(0,0);\r
+ p.lineTo(1, 1);\r
+ p.lineTo(1, -1);\r
+ return p;\r
+ }\r
+\r
+ Path2D shape;\r
+ Path2D shape2;\r
+\r
+ public Tank2Symbol(Rectangle2D rect, double cap, Color bc, Color fc, Color a1) {\r
+ super(rect, bc, fc, a1, null);\r
+ shape = TankSymbol.createTankShape(rect, cap);\r
+ shape2 = createWShape();\r
+ }\r
+\r
+ @Override\r
+ public void paint(Graphics2D g) {\r
+ g.setColor(fc);\r
+ g.setStroke(GeometryUtils.BASIC_STROKE);\r
+ g.setStroke(new BasicStroke(0.3f));\r
+ g.fill(shape);\r
+ if (bc!=null) {\r
+ g.setColor(bc);\r
+ g.draw(shape);\r
+ }\r
+ g.setColor(c1);\r
+ double d = Math.min(bounds.getHeight(), bounds.getWidth());\r
+ g.translate(bounds.getMinX()+d/2, bounds.getMinY()+d/2);\r
+ g.scale(d/3, d/3);\r
+ g.draw(shape2);\r
+ }\r
+\r
+ }\r
+\r
+ private abstract static class PS implements Image {\r
+\r
+\r
+ public final Rectangle2D bounds;\r
+ public final Color c1;\r
+ public final Color c2;\r
+ public final Color bc;\r
+ public final Color fc;\r
+ private final int hash;\r
+ public PS(Rectangle2D bounds, Color bc, Color fc, Color c1, Color c2) {\r
+ this.bounds = bounds;\r
+ this.bc = bc;\r
+ this.fc = fc;\r
+ this.c1 = c1;\r
+ this.c2 = c2;\r
+ int hash = this.getClass().hashCode();\r
+ if (bc!=null) hash += 3 * bc.hashCode();\r
+ if (fc!=null) hash += 5 * fc.hashCode();\r
+ if (c1!=null) hash += 7 * c1.hashCode();\r
+ if (c2!=null) hash += 11 * c2.hashCode();\r
+ this.hash = hash;\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return hash;\r
+ }\r
+\r
+ @Override\r
+ public boolean equals(Object obj) {\r
+ if (!obj.getClass().equals(getClass()))return false;\r
+ PS other = (PS) obj;\r
+ return\r
+ ObjectUtils.objectEquals(other.c1, c1) &&\r
+ ObjectUtils.objectEquals(other.c2, c2) &&\r
+ ObjectUtils.objectEquals(other.fc, fc) &&\r
+ ObjectUtils.objectEquals(other.bc, bc);\r
+ }\r
+ @Override\r
+ public Rectangle2D getBounds() {\r
+ return bounds;\r
+ }\r
+\r
+ @Override\r
+ public Shape getOutline() {\r
+ return bounds;\r
+ }\r
+\r
+ @Override\r
+ public Node init(G2DParentNode g) {\r
+// return init(g);\r
+ return null;\r
+ }\r
+\r
+ public void paint(Graphics2D g2d) { // FIXME: get rid of this\r
+\r
+ }\r
+\r
+ @Override\r
+ public void addImageListener(ImageListener listener) {\r
+ }\r
+\r
+ static EnumSet<Feature> caps = EnumSet.of(Feature.Vector);\r
+ @Override\r
+ public EnumSet<Feature> getFeatures() {\r
+ return caps;\r
+ }\r
+\r
+ @Override\r
+ public void removeImageListener(ImageListener listener) {\r
+ }\r
+\r
+ }\r
+\r
+}\r