]> gerrit.simantics Code Review - simantics/district.git/commitdiff
Refactoring MapNode rendering & zooming to even zoom levels (0-20) 35/2735/2
authorjsimomaa <jani.simomaa@gmail.com>
Thu, 28 Feb 2019 07:11:50 +0000 (09:11 +0200)
committerJani Simomaa <jani.simomaa@semantum.fi>
Thu, 28 Feb 2019 10:03:26 +0000 (10:03 +0000)
* With this change the map background bitmap-images are always sharp and
not blurred on e.g. zooming level 5.42 which was previously possible

gitlab #32

Change-Id: I1fd84ef25154f454efbff0b0195c447d90bd30fd

14 files changed:
org.simantics.district.maps/src/org/simantics/maps/MapScalingTransform.java
org.simantics.district.maps/src/org/simantics/maps/eclipse/MapPainter.java
org.simantics.district.maps/src/org/simantics/maps/sg/MapNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictDiagramViewer.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictPanZoomRotateHandler.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictTransformUtil.java [new file with mode: 0644]
org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/adapters/DistrictNetworkEdgeElement.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/adapters/DistrictNetworkVertexElement.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkNodeUtils.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/DistrictNetworkVertexNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/DNPointerInteractor.java
org.simantics.district.network.ui/src/org/simantics/district/network/ui/participants/MapRulerPainter.java

index f64a99f43c108e5931c822b10deb4c4d8f4fa99e..e29e8e553fc9fadc90c326dcb28f704c3fabf171 100644 (file)
@@ -6,8 +6,8 @@ public class MapScalingTransform {
 
     private MapScalingTransform() {
     }
-
-    public static final AffineTransform INSTANCE = new AffineTransform(10000, 0, 0, 10000, 0, 0);
+    public static final double scale = 256.0d / 360.0d;
+    public static final AffineTransform INSTANCE = new AffineTransform(scale, 0, 0, scale, 0, 0);
 
     public static double getScaleX() {
         return INSTANCE.getScaleX();
@@ -16,4 +16,15 @@ public class MapScalingTransform {
     public static double getScaleY() {
         return INSTANCE.getScaleY();
     }
+    
+    public static int zoomLevel(AffineTransform current) {
+        double org = INSTANCE.getScaleX();
+        double cur = current.getScaleX();
+        double f = cur / org;
+        double zoomLevel = Math.log10(f) / Math.log10(2);
+        if (zoomLevel < 0) {
+            zoomLevel = 0;
+        }
+        return (int) zoomLevel;
+    }
 }
index 853982214d933a49cf60c2348215c06bb5b5dc0b..c519b9a5f1a3d53cadb779ded4ce78e07929b249 100644 (file)
@@ -138,6 +138,7 @@ public class MapPainter extends AbstractCanvasParticipant {
 
     protected void updateNode() {
         node.setEnabled(isPaintingEnabled());
+        node.setEnabled(isMapEnabled());
         node.setBackgroundColor(getBackgroundColor());
     }
 
index f9c6abf9af2fee69d4871965ac006cec329c9d51..7ca092cf74b711939b460ab3b9e2b24edbe4a296 100644 (file)
@@ -36,6 +36,7 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
 
+import org.simantics.maps.MapScalingTransform;
 import org.simantics.maps.WebService;
 import org.simantics.maps.osm.OSMTileProvider;
 import org.simantics.maps.pojo.TileJobQueue;
@@ -233,14 +234,16 @@ public class MapNode extends G2DNode implements ITileListener  {
 
         
         AffineTransform ot = g2d.getTransform();
+        //System.err.println("ot " + ot);
         g2d.transform(transform);
         
         AffineTransform tr = g2d.getTransform();
-        
+        //System.err.println("tr " + tr);
 //        Graphics2D g = (Graphics2D)g2d.create();
 //        AffineTransform tr = (AffineTransform)g.getTransform().clone();
         
         double scaleX = Math.abs(tr.getScaleX());
+        //System.err.println("scaleX : " + scaleX);
         double scaleY = Math.abs(tr.getScaleY());
         if (scaleX <= 0 || scaleY <= 0) {
             // Make sure that we don't end up in an eternal loop below.
@@ -255,20 +258,21 @@ public class MapNode extends G2DNode implements ITileListener  {
         Rectangle2D b = (Rectangle2D)((Rectangle)g2d.getRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS)).getBounds2D(); // getClipBounds is not accurate enough, use original clipbounds and scale here
 
         Rectangle2D viewbox = new Rectangle2D.Double(offsetX/scaleX, offsetY/scaleY, b.getWidth()/sp.getWidth(), b.getHeight()/sp.getHeight()); //g.getClipBounds();
-
         if (enabled) {
-        
-            double smallerViewboxDimension = viewbox.getWidth() < viewbox.getHeight() ? viewbox.getWidth() * MAP_SCALE : viewbox.getHeight() * MAP_SCALE;
-            int level = 0;
-            double tileSize = 360 * MAP_SCALE*2;
-            while (level < MAX_TILE_LEVEL) {
-                double ratio = smallerViewboxDimension / tileSize;
-                if (ratio >= 0.85) {
-                    break;
-                }
-                tileSize *= 0.5;
-                level++;
-            }
+            
+            int level = MapScalingTransform.zoomLevel(ot);
+            
+//            double smallerViewboxDimension = viewbox.getWidth() < viewbox.getHeight() ? viewbox.getWidth() * MAP_SCALE : viewbox.getHeight() * MAP_SCALE;
+//            int level = 0;
+//            double tileSize = 360 * MAP_SCALE*2.5;
+//            while (level < MAX_TILE_LEVEL) {
+//                double ratio = smallerViewboxDimension / tileSize;
+//                if (ratio >= 0.85) {
+//                    break;
+//                }
+//                tileSize *= 0.5;
+//                level++;
+//            }
             /*
              *  To convert y-coordinates to map coordinates in ruler, use:
              *    double val = (y-offsetY)/scaleY;
@@ -281,26 +285,31 @@ public class MapNode extends G2DNode implements ITileListener  {
     
             double miny = Math.min(360, Math.max(viewbox.getMinY()+180, 0));
             double maxy = Math.min(360, Math.max(viewbox.getMaxY()+180, 0));
-    
+            //System.err.println("minx " + minx + " maxx " + maxx + " miny " + miny + " maxy " + maxy);
             g2d.setTransform(new AffineTransform());
             g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
     
             int levels = (1 << level);
-    
+            //System.err.println("level " + level);
+            //System.err.println("levels " + levels);
             // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
             int left = (int)Math.floor( (minx + 180) / 360 * (1<<level) );
             int right = (int)Math.floor( (maxx + 180) / 360 * (1<<level) );
             int top = (int)Math.floor(miny / 360 * (1<<level));//  (int)Math.floor( (1 - Math.log(Math.tan(Math.toRadians(miny)) + 1 / Math.cos(Math.toRadians(miny))) / Math.PI) / 2 * (1<<level) );
             int bottom = (int)Math.floor(maxy / 360 * (1<<level));//  (int)Math.floor( (1 - Math.log(Math.tan(Math.toRadians(maxy)) + 1 / Math.cos(Math.toRadians(maxy))) / Math.PI) / 2 * (1<<level) );
-    
+            //System.err.println("left " + left + " right " + right + " bottom " + bottom + " top " + top);
             double tsx = 360 / (double)levels; // Size of tile on zoom level
-            for(int tx = left; tx <= right; tx++) {
-                if(tx < 0 || tx >= levels) continue;
-                for(int ty = top; ty <= bottom; ty++) {
-                    if(ty < 0 || ty >= levels) continue;
+            //System.err.println("tileSize " + tsx);
+            for (int tx = left; tx <= right; tx++) {
+                if (tx < 0 || tx >= levels)
+                    continue;
+                for (int ty = top; ty <= bottom; ty++) {
+                    if (ty < 0 || ty >= levels)
+                        continue;
                     TileKey tile = new TileKey(level, tx, ty);
-                    double y = (double)ty - (double)levels/2; // In level 0 we have only one tile
-                    paintTile(tileCache, g2d, tr, tile, tx*tsx-180, y*tsx, tsx);
+                    double y = (double) ty - (double) levels / 2; // In level 0 we have only one tile
+                    
+                    paintTile(tileCache, g2d, tr, tile, tx * tsx - 180, y * tsx, tsx);
                 }
             }
     //        g.dispose();
index f0c76954fb954cf91c46a46c2fdd9c71ea400e2c..6175ace7cb1885d60d3f920ba551ae8fe3d92801 100644 (file)
@@ -1,6 +1,7 @@
 package org.simantics.district.network.ui;
 
 import java.awt.Color;
+import java.awt.geom.AffineTransform;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Consumer;
 import java.util.function.Supplier;
@@ -26,6 +27,7 @@ import org.simantics.g2d.participant.BackgroundPainter;
 import org.simantics.g2d.participant.GridPainter;
 import org.simantics.g2d.participant.PanZoomRotateHandler;
 import org.simantics.g2d.participant.RenderingQualityInteractor;
+import org.simantics.g2d.participant.TransformUtil;
 import org.simantics.g2d.participant.ZoomToAreaHandler;
 import org.simantics.maps.MapScalingTransform;
 import org.simantics.maps.eclipse.MapPainter;
@@ -48,9 +50,10 @@ public class DistrictDiagramViewer extends DiagramViewer {
         ctx.add(new ElementPainter());
         ctx.add(new DNPointerInteractor());
         
-        ctx.add(new MapPainter(MapScalingTransform.INSTANCE));
+        AffineTransform tr = new AffineTransform(MapScalingTransform.INSTANCE);
+        ctx.add(new MapPainter(tr));
         
-        ctx.add(new NetworkDrawingParticipant(MapScalingTransform.INSTANCE));
+        ctx.add(new NetworkDrawingParticipant(tr));
     }
     
     protected String getPopupId() {
@@ -80,6 +83,11 @@ public class DistrictDiagramViewer extends DiagramViewer {
     }
     
     protected void addViewManipulationParticipants(CanvasContext ctx) {
+        // Let's replace with our special util
+        TransformUtil util = ctx.getAtMostOneItemOfClass(TransformUtil.class);
+        if (util != null)
+            ctx.remove(util);
+        ctx.add(new DistrictTransformUtil());
         ctx.add(new DistrictPanZoomRotateHandler());
         //ctx.add(new MousePanZoomInteractor());
         //ctx.add(new MultitouchPanZoomRotateInteractor());
index 1a4f83d8aaea80ddee799f399d4a0f68084bbbe3..f9d9fccca449b8a265d4f0983d41952138cd39e8 100644 (file)
 package org.simantics.district.network.ui;
 
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.util.Set;
+
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Reference;
+import org.simantics.g2d.diagram.participant.Selection;
+import org.simantics.g2d.element.ElementUtils;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.participant.CanvasBoundsParticipant;
 import org.simantics.g2d.participant.PanZoomRotateHandler;
+import org.simantics.maps.MapScalingTransform;
+import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseWheelMovedEvent;
+import org.simantics.scenegraph.g2d.events.command.Command;
+import org.simantics.scenegraph.g2d.events.command.CommandEvent;
+import org.simantics.scenegraph.g2d.events.command.Commands;
 import org.simantics.scenegraph.g2d.nodes.NavigationNode;
 
 public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
 
+    public static final int DISTRICT_TRANSLATE_AMOUNT = 2;
+
+    @Dependency DistrictTransformUtil util;
+    @Reference  Selection selection;
+
     public DistrictPanZoomRotateHandler() {
     }
+    
+    @Override
+    public void addedToContext(ICanvasContext ctx) {
+        super.addedToContext(ctx);
+        setHint(KEY_TRANSLATE_AMOUNT, DISTRICT_TRANSLATE_AMOUNT);
+    }
 
     @Override
     protected Class<? extends NavigationNode> getNavigationNodeClass() {
         return DistrictNavigationNode.class;
     }
 
+    @Override
+    public double getTranslateAmount() {
+        return 15 * super.getTranslateAmount();
+    }
+    
+    @Override
+    public double limitScaleFactor(double scaleFactor) {
+        return scaleFactor;
+    }
+    
+    @Override
+    @EventHandler(priority = 1)
+    public boolean handleEvent(CommandEvent e) {
+        super.update();
+        Command c = e.command;
+        boolean zoomDisabled = Boolean.TRUE.equals(getHint(KEY_DISABLE_ZOOM)) ? true : false;
+        // custom handling of zoom to fit & selection
+        if (Commands.ZOOM_TO_FIT.equals(c) && !zoomDisabled) {
+            boolean result = zoomToFit();
+            if (!result)
+                result = zoomToPage();
+            return result;
+        }
+        if (Commands.ZOOM_TO_PAGE.equals(c) && !zoomDisabled) {
+            return zoomToPage();
+        }
+        if (Commands.ZOOM_TO_SELECTION.equals(c) && !zoomDisabled) {
+            return zoomToSelection();
+        }
+        return super.handleEvent(e);
+    }
+
+    private boolean zoomToFit() {
+        return false;
+    }
+
+    private boolean zoomToPage() {
+        int currentZoomLevel = MapScalingTransform.zoomLevel(util.getTransform());
+        
+        util.setTransform(new AffineTransform(2,0,0,2,270,270));
+//        util.setTransform(new AffineTransform(MapScalingTransform.INSTANCE));
+        return true;
+    }
+    
+    private boolean zoomToSelection() {
+        CanvasBoundsParticipant boundsParticipant = getContext().getAtMostOneItemOfClass(CanvasBoundsParticipant.class);
+        if (boundsParticipant == null)
+            return false;
+
+        final Rectangle2D controlBounds = boundsParticipant.getControlBounds().getFrame();
+        if (controlBounds == null || controlBounds.isEmpty())
+            return false;
+        
+        Set<IElement> selections = selection.getAllSelections();
+        Rectangle2D diagramRect = ElementUtils.getSurroundingElementBoundsOnDiagram(selections);
+        
+        // Make sure that even empty bounds can be zoomed into.
+        org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, 1);
+        
+        util.fitArea(controlBounds, diagramRect, null);
+        return true;
+    }
+
     public static class DistrictNavigationNode extends NavigationNode {
 
         private static final long serialVersionUID = 5452897272925816875L;
 
+        public DistrictNavigationNode() {
+            setAdaptViewportToResizedControl(false);
+        }
+
         @Override
         public Double getZoomInLimit() {
             return super.getZoomInLimit();
@@ -28,23 +122,40 @@ public class DistrictPanZoomRotateHandler extends PanZoomRotateHandler {
             return super.getZoomOutLimit();
         }
 
+        @Override
+        public void setAdaptViewportToResizedControl(Boolean adapt) {
+            super.setAdaptViewportToResizedControl(false);
+            // no op
+        }
+
+        @Override
+        public boolean getAdaptViewportToResizedControl() {
+            return false;
+        }
+
         @Override
         public boolean mouseWheelMoved(MouseWheelMovedEvent me) {
             if (navigationEnabled && zoomEnabled) {
-                double scroll = Math.min(0.9, -me.wheelRotation / 20.0);
-                double z = 1 - scroll;
+                double z;
+                if (me.wheelRotation > 0) {
+                    z = DISTRICT_TRANSLATE_AMOUNT;
+                } else {
+                    z = 1.0d / DISTRICT_TRANSLATE_AMOUNT;
+                }
+                //double scroll = Math.min(0.9, -me.wheelRotation / 20.0);
+                //double z = 1 - scroll;
                 double dx = (me.controlPosition.getX() - transform.getTranslateX()) / transform.getScaleX();
                 double dy = (me.controlPosition.getY() - transform.getTranslateY()) / transform.getScaleY();
                 dx = dx * (1 - z);
                 dy = dy * (1 - z);
-                double limitedScale = limitScaleFactor(z);
-                if (limitedScale != 1.0) {
+//                double limitedScale = limitScaleFactor(z);
+//                if (limitedScale != 1.0) {
                     translate(dx, dy);
                     scale(z, z);
                     transformChanged();
                     dropQuality();
                     repaint();
-                }
+//                }
             }
             return false;
         }
diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictTransformUtil.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/DistrictTransformUtil.java
new file mode 100644 (file)
index 0000000..230c17c
--- /dev/null
@@ -0,0 +1,75 @@
+package org.simantics.district.network.ui;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.g2d.participant.TransformUtil;
+import org.simantics.scenegraph.utils.GeometryUtils;
+import org.simantics.utils.page.MarginUtils;
+import org.simantics.utils.page.MarginUtils.Margins;
+
+public class DistrictTransformUtil extends TransformUtil {
+
+    @Override
+    public void fitArea(Rectangle2D controlArea, Rectangle2D diagramArea, Margins margins) {
+        if (margins == null) {
+            MarginUtils.Margin margin = MarginUtils.marginOf(40, 0, 0);
+            margins = new MarginUtils.Margins(margin, margin, margin, margin);
+        }
+        org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramArea, -1);
+        diagramArea = GeometryUtils.expandRectangle(diagramArea,
+                margins.top.diagramAbsolute,
+                margins.bottom.diagramAbsolute,
+                margins.left.diagramAbsolute,
+                margins.right.diagramAbsolute);
+        controlArea = GeometryUtils.expandRectangle(controlArea,
+                -margins.top.controlAbsolute    - margins.top.controlRelative * controlArea.getHeight(),
+                -margins.bottom.controlAbsolute - margins.bottom.controlRelative * controlArea.getHeight(),
+                -margins.left.controlAbsolute   - margins.left.controlRelative * controlArea.getWidth(),
+                -margins.right.controlAbsolute  - margins.right.controlRelative * controlArea.getWidth());
+
+        double controlAspectRatio = controlArea.getWidth() / controlArea.getHeight();
+        double canvasAspectRatio  = diagramArea.getWidth() / diagramArea.getHeight();
+        // Control is really wide => center canvas horizontally, match vertically
+        double scale = 1.0;
+        double tx = 0.0;
+        double ty = 0.0;
+        if (controlAspectRatio>canvasAspectRatio)
+        {
+            scale = controlArea.getHeight() / diagramArea.getHeight();
+            tx = ( controlArea.getWidth() - diagramArea.getWidth() * scale ) / 2;
+        } else
+            // Control is really tall => center canvas vertically, match horizontally
+        {
+            scale = controlArea.getWidth() / diagramArea.getWidth();
+            ty = ( controlArea.getHeight() - diagramArea.getHeight() * scale ) / 2;
+        }
+        AffineTransform current = getTransform();
+        double currentX = current.getScaleX();
+        double targetX = scale;
+        double toBeX = currentX;
+        if (targetX > 0) {
+            if (toBeX < targetX) {
+                while ((toBeX) < targetX) {
+                    toBeX = toBeX * 2;
+                }
+            } else {
+                while ((toBeX * 0.5) > targetX) {
+                    toBeX = toBeX * 0.5;
+                }
+            }
+            //tx = tx * (1 - toBeX);
+            //ty = ty * (1 - toBeX);
+            AffineTransform at = new AffineTransform();
+            at.translate(tx, ty);
+            at.translate(controlArea.getMinX(), controlArea.getMinY());
+            at.scale(toBeX, toBeX);
+            at.translate(-diagramArea.getMinX(), -diagramArea.getMinY());
+            
+            setTransform(at);
+        } else {
+            // negative, how, no can do?
+            
+        }
+    }
+}
index 73abf31e575bb7f03047793df0f272146ba67c01..69d1f724193fcbb797ae1eeb0edc403463758c81 100644 (file)
@@ -59,7 +59,7 @@ public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
     }
 
     public boolean pickHoveredElement(Point2D currentMousePos) {
-        PickRequest req = new PickRequest(currentMousePos.getX(), currentMousePos.getY()).context(getContext());
+        PickRequest req = new PickRequest(currentMousePos).context(getContext());
         List<IElement> pickables = new ArrayList<IElement>();
         pick.pick(diagram, req, pickables);
         
index d47580074a9d5a3ef23855bc78745d44be726d4d..ce57e0a21fd7f12b0f8968b74af4899a1092cbaf 100644 (file)
@@ -163,7 +163,7 @@ public class DistrictNetworkEdgeElement {
         }
 
         private boolean pickIntersectingObjects(DistrictNetworkEdge edge, Rectangle2D bounds) {
-            double tolerance = (bounds.getHeight() + bounds.getHeight()) * 0.25 / MapScalingTransform.getScaleX();
+            double tolerance = (bounds.getHeight() + bounds.getHeight()) * 1 / MapScalingTransform.getScaleX();
             Line2D line = new Line2D.Double(edge.getStartPoint(), edge.getEndPoint());
             double sx = bounds.getCenterX() / MapScalingTransform.getScaleX();
             double sy = bounds.getCenterY() / MapScalingTransform.getScaleY();
index 7be6a14faa659abb28df213e694b14e9094dd848..b3e7fda3b822401b2d525d51ef7f0c1c0bb70e38 100644 (file)
@@ -1,21 +1,28 @@
 package org.simantics.district.network.ui.adapters;
 
 import java.awt.Color;
+import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 
+import org.simantics.diagram.elements.DiagramNodeUtil;
 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;
 import org.simantics.g2d.element.ElementClass;
 import org.simantics.g2d.element.ElementUtils;
 import org.simantics.g2d.element.IElement;
 import org.simantics.g2d.element.SceneGraphNodeKey;
 import org.simantics.g2d.element.handler.InternalSize;
+import org.simantics.g2d.element.handler.Pick;
 import org.simantics.g2d.element.handler.SceneGraph;
 import org.simantics.g2d.element.handler.impl.DefaultTransform;
 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;
 import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.g2d.G2DParentNode;
 import org.simantics.scenegraph.g2d.nodes.SVGNode;
+import org.simantics.scenegraph.utils.GeometryUtils;
 import org.simantics.utils.datastructures.hints.IHintContext.Key;
 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
 
@@ -77,7 +84,7 @@ public class DistrictNetworkVertexElement {
         }
     }
     
-    static final class DNVertexInternalSize implements InternalSize {
+    static final class DNVertexInternalSize implements InternalSize, Pick {
 
         public static final DNVertexInternalSize INSTANCE = new DNVertexInternalSize();
         
@@ -87,9 +94,42 @@ public class DistrictNetworkVertexElement {
         public Rectangle2D getBounds(IElement e, Rectangle2D size) {
             DistrictNetworkVertexNode node = e.getHint(KEY_DN_VERTEX_NODE);
             Rectangle2D boundsInLocal = node.getBoundsInLocal();
-            size.setFrame(boundsInLocal);
+            ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
+            AffineTransform canvasTransform = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
+            // for some reason PickContextImpl expands the rectangle by 0.001 (too much) - let's counter it
+            double counterExpansion = 0.001;
+            double x = boundsInLocal.getX() + counterExpansion;
+            double y = boundsInLocal.getY() + counterExpansion;
+            double scaledWidth = boundsInLocal.getWidth() / canvasTransform.getScaleX() / 10000.0;
+            double scaledHeight = boundsInLocal.getHeight() / canvasTransform.getScaleY() / 10000.0;
+            double width = scaledWidth - 2*counterExpansion;
+            double height = scaledHeight - 2*counterExpansion;
+            size.setFrame(x, y, width, height);
+            
             return size;
         }
+
+        @Override
+        public boolean pickTest(IElement e, Shape s, PickPolicy policy) {
+            DistrictNetworkVertexNode node = e.getHint(KEY_DN_VERTEX_NODE);
+            Rectangle2D boundsInLocal = node.getBounds();
+            ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
+            AffineTransform canvasTransform = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
+            Rectangle2D scaledBounds = new Rectangle2D.Double(boundsInLocal.getX(), boundsInLocal.getY(), boundsInLocal.getWidth() / canvasTransform.getScaleX() * 2, boundsInLocal.getHeight() / canvasTransform.getScaleY() * 2);
+            Rectangle2D bounds = getBounds(s);
+            switch (policy) {
+            case PICK_CONTAINED_OBJECTS:
+                return org.simantics.g2d.utils.GeometryUtils.contains(bounds, boundsInLocal);
+            case PICK_INTERSECTING_OBJECTS:
+                return org.simantics.g2d.utils.GeometryUtils.intersects(boundsInLocal, bounds);
+            }
+            return false;
+        }
         
+        private Rectangle2D getBounds(Shape shape) {
+            if (shape instanceof Rectangle2D)
+                return (Rectangle2D) shape;
+            return shape.getBounds2D();
+        }
     }
 }
index 8a369e26391d9efb77e458891824617f9a9c9231..c48693ac4470b94122bf6f47c13a87a7031a9b01 100644 (file)
@@ -5,6 +5,8 @@ import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 
 import org.simantics.district.network.ModelledCRS;
+import org.simantics.maps.MapScalingTransform;
+import org.simantics.scenegraph.utils.GeometryUtils;
 
 public class DistrictNetworkNodeUtils {
 
@@ -35,4 +37,11 @@ public class DistrictNetworkNodeUtils {
         return transform;
     }
 
+    public static double calculateScaleRecip(AffineTransform tr) {
+        int zoomLevel = MapScalingTransform.zoomLevel(tr);
+        double scale = GeometryUtils.getScale(tr);
+        double sqrt = Math.sqrt(scale / zoomLevel);
+        double viewScaleRecip = (sqrt / zoomLevel);
+        return viewScaleRecip;
+    }
 }
index 377c7f7e8d11840ff6c706b0798a52e9e61fe43f..6fb075eb8fd0c95b4ce1561a3d56f59280e472c3 100644 (file)
@@ -23,13 +23,13 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti
 
     private static final long serialVersionUID = -2641639101400236719L;
 
-    private static final BasicStroke STROKE           = new BasicStroke(4, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
-    private static final Color       SELECTION_COLOR  = new Color(255, 0, 255, 96);
+    private static final double left = -0.00005;
+    private static final double top = left;
+    public static final double width = 0.0001;
+    private static final double height = width;
 
-    private static final double left = -0.25;
-    private static final double top = -0.25;
-    private static final double width = 0.5;
-    private static final double height = 0.5;
+    private static final BasicStroke STROKE           = new BasicStroke((float)width, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
+    private static final Color       SELECTION_COLOR  = new Color(255, 0, 255, 96);
 
     private static final Rectangle2D NORMAL = new Rectangle2D.Double(left, top, width, height);
     private static final Rectangle2D HOVERED = new Rectangle2D.Double(left * 3, top * 3, width * 3, height * 3);
@@ -63,7 +63,7 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti
         AffineTransform t = getTransform();
         if (t != null && !t.isIdentity()) {
             ot = g2d.getTransform();
-            g2d.transform(getTransform());
+            g2d.transform(t);
         }
 
         Object oaaHint = null;
@@ -77,11 +77,9 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti
         Color newColor = dynamicColor != null ? dynamicColor : color;
         boolean changeColor = !oldColor.equals(newColor);
 
-        double viewScaleRecip = 10;
+        double viewScaleRecip = 1;
         if (scaleStroke) {
-            double scale = GeometryUtils.getScale(g2d.getTransform());
-            scale = Math.max(10000, Math.min(scale, 50000));
-            viewScaleRecip /= scale;
+            viewScaleRecip *= DistrictNetworkNodeUtils.calculateScaleRecip(g2d.getTransform());
         }
         double scaleRecip = viewScaleRecip * nodeSize;
 
@@ -152,7 +150,11 @@ public class DistrictNetworkVertexNode extends G2DParentNode implements ISelecti
     private Rectangle2D calculateBounds(Rectangle2D rect) {
         Point2D calcPoint = DistrictNetworkNodeUtils.calculatePoint2D(vertex.getPoint(), point);
         AffineTransform at = getTransform();
-        return new Rectangle2D.Double(calcPoint.getX(), calcPoint.getY(), width / at.getScaleX(), height / at.getScaleY()).getBounds2D();
+        double x = calcPoint.getX();
+        double y = calcPoint.getY();
+        double widthh = width / at.getScaleX();
+        double heighth = height / at.getScaleY();
+        return new Rectangle2D.Double(x - widthh, y - heighth, widthh * 2, heighth * 2).getBounds2D();
     }
 
     public void setVertex(DistrictNetworkVertex vertex) {
index 71ccb781a1f1a0b0bf74df1d14430a5937a6e6db..674702b8476276103d90301e36dd7e80e24143c6 100644 (file)
@@ -4,6 +4,7 @@ import java.awt.BasicStroke;
 import java.awt.Color;
 import java.awt.Graphics2D;
 import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Path2D;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
@@ -16,11 +17,13 @@ import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.diagram.elements.DiagramNodeUtil;
 import org.simantics.diagram.ui.DiagramModelHints;
 import org.simantics.district.network.ModelledCRS;
 import org.simantics.district.network.ui.DNEdgeBuilder;
 import org.simantics.district.network.ui.NetworkDrawingParticipant;
 import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.canvas.IToolMode;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.scenegraph.g2d.G2DNode;
@@ -158,8 +161,14 @@ public class NetworkDrawingNode extends G2DNode {
 
     private void createEdge(Point2D start, Point2D end) {
         
-        double padding = GeometryUtils.getScale(getTransform());
-        
+        double currentPadding = DistrictNetworkVertexNode.width;
+        AffineTransform test = getTransform();
+        ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(this);
+        AffineTransform tr = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
+        AffineTransform testing = new AffineTransform(tr); 
+        testing.concatenate(test);
+        double calculateScaleRecip = DistrictNetworkNodeUtils.calculateScaleRecip(testing);
+        double padding = currentPadding * calculateScaleRecip;
         /*
          *  To convert y-coordinates to map coordinates in ruler, use:
          *    double val = (y-offsetY)/scaleY;
@@ -184,7 +193,7 @@ public class NetworkDrawingNode extends G2DNode {
             
             @Override
             public void perform(WriteGraph graph) throws DatabaseException {
-                builder.create(graph, startCoords, endCoords, 1 / padding);
+                builder.create(graph, startCoords, endCoords, padding);
             }
         });
         
index c61adba9fa335f7303a75bc223080dd42f4d4fa5..9df6e5efbc2646a67fd165b43d90c1d436f44937 100644 (file)
@@ -81,4 +81,8 @@ public class DNPointerInteractor extends PointerInteractor {
         return false;
     }
 
+    @Override
+    public double getPickDistance() {
+        return 0.00001;
+    }
 }
index ecdbf275d207f2eeb9f1f3c8554db97e672f93bb..cdf0b53069578b182456519a3b8cd18c150eaf92 100644 (file)
@@ -1,5 +1,7 @@
 package org.simantics.district.network.ui.participants;
 
+import java.awt.geom.AffineTransform;
+
 import org.simantics.district.network.ui.nodes.MapRulerNode;
 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
 import org.simantics.g2d.participant.RulerPainter;
@@ -12,7 +14,7 @@ public class MapRulerPainter extends RulerPainter {
     @Override
     public void initSG(G2DParentNode parent) {
         node = parent.addNode("ruler", getNodeClass());
-        node.setTransform(MapScalingTransform.INSTANCE);
+        node.setTransform(new AffineTransform(MapScalingTransform.INSTANCE));
         node.setZIndex(PAINT_PRIORITY);
         updateNode();
     }