]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Sysdyn dependency arrow to stop overlapping valve texts. (refs #4482)
authormiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 29 Oct 2013 14:30:55 +0000 (14:30 +0000)
committermiettinen <miettinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Tue, 29 Oct 2013 14:30:55 +0000 (14:30 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28152 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveFactory.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/ValveOutline.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/Arcs.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyEdgeClass.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/elements/connections/DependencyNode.java

index edc3785e2e143841b1853bc1020500b98454f7bb..12ddbbd5775bc815717de0f3b5d7391d048b5571 100644 (file)
@@ -13,6 +13,9 @@ package org.simantics.sysdyn.ui.elements;
 \r
 import java.awt.BasicStroke;\r
 import java.awt.Color;\r
+import java.awt.Font;\r
+import java.awt.font.FontRenderContext;\r
+import java.awt.font.TextLayout;\r
 import java.awt.geom.AffineTransform;\r
 import java.awt.geom.Path2D;\r
 import java.awt.geom.Rectangle2D;\r
@@ -59,6 +62,7 @@ public class ValveFactory extends SysdynElementFactory {
     public static final Key             KEY_ROTATED        = new KeyOf(Boolean.class, "ROTATED");\r
 \r
     public static final double          VALVE_SIZE         = 1.5;\r
+    public static final double          VALVE_TEXT_SHIFT_BOTTOM = 3.0;\r
 \r
     private static final BasicStroke    STROKE             = new BasicStroke(1f);\r
     public static final Image          VALVE_STATIC_IMAGE = new ShapeImage(createShape(VALVE_SIZE, false), null, STROKE, true);\r
@@ -184,7 +188,7 @@ public class ValveFactory extends SysdynElementFactory {
                     String location = e.getHint(SysdynElementHints.KEY_LOCATION);\r
                     if(location != null) {\r
                         if(location.equals("Bottom")) {\r
-                            at2.translate(0, VALVE_SIZE + 3.0);\r
+                            at2.translate(0, VALVE_SIZE + VALVE_TEXT_SHIFT_BOTTOM);\r
                         } else if(location.equals("Top")) {\r
                             at2.translate(0, -VALVE_SIZE - 1);\r
                         } else if(location.equals("Left")) {\r
@@ -240,6 +244,66 @@ public class ValveFactory extends SysdynElementFactory {
             return size;\r
         }\r
 \r
+        private Rectangle2D getBoundsText(IElement e, Rectangle2D size) {\r
+               HoverTextNode node = (HoverTextNode) e.getHint(SG_NODE);\r
+            if (size == null)\r
+                size = new Rectangle2D.Double();\r
+            if (node != null) {\r
+                Rectangle2D local = node.getBoundsInLocal();\r
+                local.setRect(local.getX(), \r
+                                         local.getY() + VALVE_SIZE + VALVE_TEXT_SHIFT_BOTTOM, \r
+                                         local.getWidth(), \r
+                                         local.getHeight());\r
+                size.setRect(local);\r
+            }\r
+            else {\r
+                String text = e.getHint(ElementHints.KEY_TEXT);\r
+                Font font = e.getHint(ElementHints.KEY_FONT);\r
+                if(text == null || font == null)\r
+                    size.setFrame(0, 0, 0, 0);\r
+                else {\r
+                    FontRenderContext FRC = new FontRenderContext(new AffineTransform(), true, true);\r
+                    TextLayout tl = new TextLayout(text, font, FRC);\r
+                    Rectangle2D bounds = tl.getLogicalHighlightShape(0, text.length()).getBounds2D();   \r
+                    size.setFrame(\r
+                            bounds.getX() * SCALE - paddingX,\r
+                            (bounds.getY() + VALVE_SIZE) * SCALE - paddingY, \r
+                            bounds.getWidth()* SCALE + paddingX + paddingX, \r
+                            bounds.getHeight()* SCALE + paddingY + paddingY);\r
+                }\r
+            }\r
+            return size;\r
+        }\r
+        \r
+        public Path2D.Double getBoundsPath(IElement e, Path2D.Double size) {\r
+            if (size == null)\r
+                size = new Path2D.Double();\r
+\r
+            // Get the rectangles for the Valve symbol and the text field.\r
+            Rectangle2D valve = getBounds(e, new Rectangle2D.Double());\r
+            Rectangle2D text = getBoundsText(e, new Rectangle2D.Double());\r
+            \r
+            // Combine the two.\r
+            double xV = valve.getX();\r
+            double xVM = valve.getMaxX();\r
+            double yV = valve.getY();\r
+            double xT = text.getX();\r
+            double xTM = text.getMaxX();\r
+            double yT = text.getY();\r
+            double yTM = text.getMaxY();\r
+               size.moveTo(xV, yV);\r
+            size.lineTo(xVM, yV);\r
+            size.lineTo(xVM, yT);\r
+            size.lineTo(xTM, yT);\r
+            size.lineTo(xTM, yTM);\r
+            size.lineTo(xT, yTM);\r
+            size.lineTo(xT, yT);\r
+            size.lineTo(xV, yT);\r
+            size.closePath();\r
+               \r
+            return size;\r
+        }\r
+\r
     }\r
 \r
 }\r
index 8e35e6953884a28f1b5ad91c88fa3ae91c9ca91c..37b6969bb56227262a6db26eacb917255dfb89f8 100644 (file)
@@ -1,10 +1,13 @@
 package org.simantics.sysdyn.ui.elements;\r
 \r
-import java.awt.Polygon;\r
 import java.awt.Shape;\r
+import java.awt.geom.Path2D;\r
+import java.awt.geom.Rectangle2D;\r
 \r
 import org.simantics.g2d.element.IElement;\r
+import org.simantics.g2d.element.handler.InternalSize;\r
 import org.simantics.g2d.element.handler.impl.BoundsOutline;\r
+import org.simantics.sysdyn.ui.elements.ValveFactory.ValveSceneGraph;\r
 \r
 public class ValveOutline extends BoundsOutline {\r
 \r
@@ -18,10 +21,10 @@ public class ValveOutline extends BoundsOutline {
 \r
        @Override\r
        public Shape getElementShape(IElement e) {\r
-               return super.getElementShape(e);\r
-               /*int[] xs = {-5,5,5,20,20,-20,-20,-5};\r
-               int[] ys = {-5,-5,5,5,15,15,5,5};\r
-               Polygon poly = new Polygon(xs, ys, 8);\r
-               return poly;*/\r
+        InternalSize b = e.getElementClass().getSingleItem(InternalSize.class);\r
+        if (b instanceof ValveSceneGraph)\r
+               return ((ValveSceneGraph)b).getBoundsPath(e, new Path2D.Double());\r
+        else\r
+               return b.getBounds(e, new Rectangle2D.Double());\r
        }\r
 }\r
index 602796de95460fd14b416c679fdf2fcf42207fa1..c054d41b46d3cbf1cd63e3d68041c7371b4c2a2a 100644 (file)
@@ -66,101 +66,74 @@ public class Arcs {
             \r
         }\r
     }\r
+        \r
+    /**\r
+     * \r
+     * @param startX Start point x coord\r
+     * @param startY Start point y coord\r
+     * @param cx Center of the circle x coord\r
+     * @param cy Center of the circle y coord\r
+     * @param r Radius of the circle\r
+     * @param curAngle Start angle\r
+     * @param endBounds Shape\r
+     * @param dir direction to which is iterated\r
+     * @param move amount of which is iterated\r
+     * @param noOfIteration current number of itartion\r
+     * @param turn true iff we are increasing the angle\r
+     * @param crossed true if we have crossed the boundary we're targeting\r
+     * @return new angle\r
+     */\r
+    private static double iterateAngle(double startX, double startY, \r
+               double cx, double cy, double r,\r
+            double curAngle, Shape endBounds, boolean dir, double move,\r
+            int noOfIteration, boolean turn, boolean crossed) {\r
+       // Do this many steps\r
+       if (noOfIteration > 16)\r
+               return normalizeAngle(curAngle);\r
+       \r
+       if (crossed) // When we have crossed the boundary, start split half method\r
+               move *= 0.5;\r
+       double x_rad, y_rad;\r
+       if (dir != turn) { // The direction of iteration is based on dir and turn bits\r
+               x_rad = startX + (move * Math.sin(curAngle));\r
+               y_rad = startY + (move * Math.cos(curAngle));\r
+       } else {\r
+               x_rad = startX - (move * Math.sin(curAngle));\r
+               y_rad = startY - (move * Math.cos(curAngle));\r
+       }\r
+       curAngle = -Math.atan((y_rad-cy)/(x_rad-cx));\r
+               if (x_rad-cx < 0)\r
+                       curAngle += Math.PI;\r
+       curAngle = normalizeAngle(curAngle);\r
+               \r
+               if (endBounds.contains(x_rad, y_rad)) {\r
+                       return iterateAngle(x_rad, y_rad,\r
+                                       cx,cy,r,curAngle,endBounds,dir, move, noOfIteration+1, false, crossed);\r
+       }\r
+       else {\r
+               // Crossed is hereafter true\r
+               return iterateAngle(x_rad, y_rad,\r
+                                       cx,cy,r,curAngle,endBounds,dir, move, noOfIteration+1, true, true);\r
+       }\r
+    }\r
     \r
-    private static double updateBestNextAngle(double curAngle, double bestAngle, double newAngle) {\r
-        if(newAngle < curAngle)\r
-            newAngle += PI2;\r
-        if(newAngle < bestAngle)\r
-            return newAngle;\r
-        return bestAngle;        \r
-    }   \r
-    \r
-    private static double updateBestPrevAngle(double curAngle, double bestAngle, double newAngle) {\r
-        if(newAngle > curAngle)\r
-            newAngle -= PI2;\r
-        if(newAngle > bestAngle)\r
-            return newAngle;\r
-        return bestAngle;        \r
-    }   \r
-    \r
+    /**\r
+     * \r
+     * @param cx x coord of the center point of the circle \r
+     * @param cy y coord of the center point of the circle\r
+     * @param r radius of the circle\r
+     * @param curAngle angle of the arc\r
+     * @param endBounds bounding shape\r
+     * @param dir direction of the arc\r
+     * @return\r
+     */\r
     public static double nextIntersectingAngle(double cx, double cy, double r,\r
         double curAngle, Shape endBounds, boolean dir) {\r
-        if(!dir) {\r
-            double bestAngle = curAngle + PI2;\r
-            {\r
-                double dx = endBounds.getBounds2D().getMinX() - cx;\r
-                if(Math.abs(dx) < r) {\r
-                    double angle = normalizeAngle(Math.acos(dx / r));\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle);\r
-                }\r
-            }\r
-            {\r
-                double dx = endBounds.getBounds2D().getMaxX() - cx;\r
-                if(Math.abs(dx) < r) {\r
-                    double angle = normalizeAngle(Math.acos(dx / r));\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, -angle);\r
-                }\r
-            }\r
-            {\r
-                double dy = cy - endBounds.getBounds2D().getMinY();\r
-                if(Math.abs(dy) < r) {\r
-                    double angle = Math.asin(dy / r);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, \r
-                        normalizeAngle(Math.PI-angle));\r
-                }\r
-            }\r
-            {\r
-                double dy = cy - endBounds.getBounds2D().getMaxY();\r
-                if(Math.abs(dy) < r) {\r
-                    double angle = Math.asin(dy / r);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestNextAngle(curAngle, bestAngle, \r
-                        normalizeAngle(Math.PI-angle));\r
-                }\r
-            }\r
-            return normalizeAngle(bestAngle);\r
-        }   \r
-        else {\r
-            double bestAngle = curAngle - PI2;\r
-            {\r
-                double dx = endBounds.getBounds2D().getMinX() - cx;\r
-                if(Math.abs(dx) < r) {\r
-                    double angle = normalizeAngle(Math.acos(dx / r));\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle);\r
-                }\r
-            }\r
-            {\r
-                double dx = endBounds.getBounds2D().getMaxX() - cx;\r
-                if(Math.abs(dx) < r) {\r
-                    double angle = normalizeAngle(Math.acos(dx / r));\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, -angle);\r
-                }\r
-            }\r
-            {\r
-                double dy = cy - endBounds.getBounds2D().getMinY();\r
-                if(Math.abs(dy) < r) {\r
-                    double angle = Math.asin(dy / r);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, \r
-                        normalizeAngle(Math.PI-angle));\r
-                }\r
-            }\r
-            {\r
-                double dy = cy - endBounds.getBounds2D().getMaxY();\r
-                if(Math.abs(dy) < r) {\r
-                    double angle = Math.asin(dy / r);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, angle);\r
-                    bestAngle = updateBestPrevAngle(curAngle, bestAngle, \r
-                        normalizeAngle(Math.PI-angle));\r
-                }\r
-            }\r
-            return normalizeAngle(bestAngle);\r
-        }\r
+       // Move this much per iteration till the border is crossed.\r
+       double move = 3.0;\r
+        return iterateAngle(endBounds.getBounds2D().getCenterX(),\r
+                                               endBounds.getBounds2D().getCenterY(),\r
+                                               cx,cy,r,curAngle,endBounds,dir,move, 0, false, false);\r
     }\r
     \r
        public static boolean hitTest(Shape beginBounds, Shape endBounds, double angle, double x, double y, double tolerance) {\r
index 385a44928d09327b98a0d75bf0f812938e5bfd05..3e04c80137416d60f274d420dc1e7bbe25b21876 100644 (file)
@@ -210,8 +210,8 @@ public class DependencyEdgeClass {
             node.setEditable(false);\r
             node.setFont(font);\r
             \r
-            node.setBeginBounds(beginTerminalShape.getBounds2D());\r
-            node.setEndBounds(endTerminalShape.getBounds2D());\r
+            node.setBeginBounds(beginTerminalShape);\r
+            node.setEndBounds(endTerminalShape);\r
             node.setStroke(stroke);\r
             node.setColor(color);\r
             node.setShapes(DependencyRouter.createArrowShape(node.getShapes(), node.getBeginBounds(), node.getEndBounds(), node.getAngle()));\r
index bfb4474b4effc753da14f1df6e3260193fa3797f..24178b011b15479bc36d4117c23ebd08f55f74da 100644 (file)
@@ -124,13 +124,13 @@ public class DependencyNode extends TextNode implements ISelectionPainterNode {
 \r
     @PropertySetter("beginBounds")\r
     @SyncField("beginBounds")\r
-    public void setBeginBounds(Rectangle2D beginBounds) {\r
+    public void setBeginBounds(Shape beginBounds) {\r
         this.beginBounds = beginBounds;\r
     }\r
 \r
     @PropertySetter("endBounds")\r
     @SyncField("endBounds")\r
-    public void setEndBounds(Rectangle2D endBounds) {\r
+    public void setEndBounds(Shape endBounds) {\r
         this.endBounds = endBounds;\r
     }\r
 \r