]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/InstancingShapeNode.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / InstancingShapeNode.java
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/InstancingShapeNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/InstancingShapeNode.java
new file mode 100644 (file)
index 0000000..a064ed9
--- /dev/null
@@ -0,0 +1,91 @@
+/*******************************************************************************\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.scenegraph.g2d.nodes;
+
+import java.awt.Graphics2D;
+import java.awt.Paint;
+import java.awt.Shape;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * A scene graph node that renders multiple separately transformed instances of
+ * a {@link Shape} by optionally filling or stroking it.
+ * 
+ * If filling is enabled, it will be performed before stroking the shape.
+ * 
+ * @author Tuukka Lehtonen
+ */
+public class InstancingShapeNode extends ShapeNode {
+
+    private static final long serialVersionUID = -681327976554446434L;
+
+    AffineTransform[] transforms = {};
+    Paint[] paints = {};
+
+    @SyncField({"instances", "paints"})
+    public void setInstances(AffineTransform[] transforms, Paint[] paints) {
+        if (transforms.length != paints.length)
+            throw new IllegalArgumentException("transforms.length (" + transforms.length + ") != paints.length (" + paints.length + ")");
+
+        this.transforms = transforms;
+        this.paints = paints;
+    }
+
+    @Override
+    public void render(Graphics2D g2d) {
+        if (shape == null)
+            return;
+        if (transforms == null || transforms.length == 0)
+            return;
+
+        setupRender(g2d);
+
+        AffineTransform startTr = g2d.getTransform();
+        Paint startPaint = g2d.getPaint();
+
+        for (int i = 0; i < transforms.length; ++i) {
+            if (transforms[i] != null)
+                g2d.transform(transforms[i]);
+
+            if (paints[i] != null)
+                g2d.setPaint(paints[i]);
+            else
+                g2d.setPaint(startPaint);
+
+            renderShape(g2d, shape);
+
+            g2d.setTransform(startTr);
+        }
+    }
+
+    @Override
+    public Rectangle2D getBoundsInLocal() {
+        if (shape == null)
+            return null;
+        if (transforms == null || transforms.length == 0)
+            return null;
+
+        Rectangle2D result = null;
+        Rectangle2D sb = shape.getBounds2D();
+        for (AffineTransform at : transforms) {
+            Rectangle2D instanceBounds = at.createTransformedShape(sb).getBounds2D();
+            if (result == null)
+                result = instanceBounds;
+            else
+                Rectangle2D.union(result, instanceBounds, result);
+        }
+
+        return result;
+    }
+
+}