[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
diff --git a/plugins/net.refractions.udig.project.ui/src/net/refractions/udig/project/ui/commands/TransformDrawCommand.java b/plugins/net.refractions.udig.project.ui/src/net/refractions/udig/project/ui/commands/TransformDrawCommand.java
index 2068980..eedef9f 100644
--- a/plugins/net.refractions.udig.project.ui/src/net/refractions/udig/project/ui/commands/TransformDrawCommand.java
+++ b/plugins/net.refractions.udig.project.ui/src/net/refractions/udig/project/ui/commands/TransformDrawCommand.java
@@ -14,6 +14,7 @@
*/
package net.refractions.udig.project.ui.commands;
+import java.awt.Point;
import java.awt.Rectangle;
import java.awt.geom.AffineTransform;
@@ -35,22 +36,30 @@ public class TransformDrawCommand extends AbstractDrawCommand
private int translateY;
private int translateX;
private double rotation;
+ private Point fixedPoint;
public Rectangle getValidArea() {
return null;
}
public synchronized void run( IProgressMonitor monitor ) throws Exception {
+ if (fixedPoint == null) {
+ fixedPoint = new Point(display.getWidth() / 2, display.getHeight() / 2);
+ }
AffineTransform t = new AffineTransform();
- t.translate((double)display.getWidth()/(double)2, (double)display.getHeight()/(double)2);
+ t.translate(fixedPoint.getX(), fixedPoint.getY());
t.rotate(rotation);
t.scale(scaleFactorX, scaleFactorY);
- t.translate((double)-display.getWidth()/(double)2, (double)-display.getHeight()/(double)2);
+ t.translate(-fixedPoint.getX(), -fixedPoint.getY());
t.translate(translateX, translateY);
t.concatenate(graphics.getTransform());
graphics.setTransform(t);
}
+ public synchronized void fixPoint( Point fixedPoint ) {
+ this.fixedPoint = fixedPoint;
+ }
+
public synchronized void zoom( double scaleFactorX, double scaleFactorY ) {
this.scaleFactorX=scaleFactorX;
this.scaleFactorY=scaleFactorY;
diff --git a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/command/navigation/ZoomCommand.java b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/command/navigation/ZoomCommand.java
index 6879a68..0d00bec 100644
--- a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/command/navigation/ZoomCommand.java
+++ b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/command/navigation/ZoomCommand.java
@@ -13,6 +13,8 @@ import net.refractions.udig.project.internal.Messages;
import org.eclipse.core.runtime.IProgressMonitor;
+import com.vividsolutions.jts.geom.Coordinate;
+
/**
* Increases or decreases the size of the viewport(in world space) by a constant factor, zoom. The
* zoom is equal in both directions. The function used is: bbox.height=bbox.height/divisor
@@ -24,6 +26,7 @@ import org.eclipse.core.runtime.IProgressMonitor;
public class ZoomCommand extends AbstractNavCommand {
private double zoomfactor;
+ private Coordinate fixedPoint;
/**
* Creates a new instance of ZoomCommand
@@ -39,6 +42,10 @@ public class ZoomCommand extends AbstractNavCommand {
this.zoomfactor = zoomfactor;
}
+ public void setFixedPoint( Coordinate fixedPoint ) {
+ this.fixedPoint = fixedPoint;
+ }
+
/**
* @see net.refractions.udig.project.internal.command.MapCommand#copy()
*/
@@ -50,7 +57,7 @@ public class ZoomCommand extends AbstractNavCommand {
* @see net.refractions.udig.project.internal.command.navigation.AbstractNavCommand#runImpl()
*/
protected void runImpl( IProgressMonitor monitor ) {
- model.zoom(zoomfactor);
+ model.zoom(zoomfactor, fixedPoint);
}
/**
diff --git a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/ViewportModel.java b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/ViewportModel.java
index f309ec0..ce1a5e7 100644
--- a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/ViewportModel.java
+++ b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/ViewportModel.java
@@ -359,6 +359,25 @@ public interface ViewportModel extends EObject, IMapDisplayListener, IViewportMo
public ViewportModel zoom( double zoom );
/**
+ * Increases or decreases the size of the viewport(in world space) by a constant factor, zoom.
+ * The zoom is equal in both directions. The function used is: bbox.height=bbox.height/divisor
+ * bbox.width=bbox.width/divisor
+ * <ul>
+ * <li>A zoom must be greater than 1.</li>
+ * <li>A zoom greater than 1 is a zoom towards the map(SimpleFeature appear larger.)</li>
+ * <li>A zoom less than 1 is a zoom away from the map</li>
+ * </ul>
+ * When get not null parameter fixedPoint then keep it fixed after zoom transform. In case of
+ * null parameter center point of map will be fixed
+ *
+ * @param zoom the zoom factor
+ * @param fixedPoint the point that will remain fixed after zoom, can be null
+ * @return This ViewportModel, allows for command chaining.
+ * @model
+ */
+ public ViewportModel zoom( double zoom, Coordinate fixedPoint );
+
+ /**
* sets the Viewport bounding box so that it fully contains the visible map extent
*
* @model
diff --git a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ScaleUtils.java b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ScaleUtils.java
index c7e53bc..125e779 100644
--- a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ScaleUtils.java
+++ b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ScaleUtils.java
@@ -469,4 +469,20 @@ public final class ScaleUtils {
.getDisplaySize(), mapDisplay.getDPI(), requestedBounds);
}
+ /**
+ * Creates affine transform for zooming that keeps <i>fixedPoint</i> stationary.
+ *
+ * @param zoom zoom ration
+ * @param fixedPoint point to keep stationary
+ * @return an <i>AffineTransform</i> object containing scale transform that keeps
+ * <i>fixedPoint</i> stationary
+ */
+ public static AffineTransform createScaleTransformWithFixedPoint( double zoom,
+ Coordinate fixedPoint ) {
+ AffineTransform t = new AffineTransform();
+ t.translate(fixedPoint.x, fixedPoint.y);
+ t.scale(1 / zoom, 1 / zoom);
+ t.translate(-fixedPoint.x, -fixedPoint.y);
+ return t;
+ }
}
diff --git a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ViewportModelImpl.java b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ViewportModelImpl.java
index 6cd3dc4..f501f2f 100644
--- a/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ViewportModelImpl.java
+++ b/plugins/net.refractions.udig.project/src/net/refractions/udig/project/internal/render/impl/ViewportModelImpl.java
@@ -6,6 +6,7 @@ package net.refractions.udig.project.internal.render.impl;
import java.awt.Dimension;
import java.awt.Point;
import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
import java.util.Collection;
import java.util.Date;
import java.util.Collections;
@@ -720,12 +721,33 @@ public class ViewportModelImpl extends EObjectImpl implements ViewportModel {
*/
public ViewportModel zoom( double zoom ) {
Coordinate center = getCenter();
- double height = getHeight() / zoom, width = getWidth() / zoom;
- double dh = height / 2, dw = width / 2;
- setBounds(center.x - dw, center.x + dw, center.y - dh, center.y + dh);
+ zoom(zoom, center);
return this;
}
+ public ViewportModel zoom( double zoom, Coordinate fixedPoint ) {
+ if (fixedPoint == null) {
+ fixedPoint = getCenter();
+ }
+ AffineTransform transformer = ScaleUtils.createScaleTransformWithFixedPoint(zoom,
+ fixedPoint);
+ ReferencedEnvelope srcEnvelope = getBounds();
+ Envelope transformedEnvelope = transformEnvelope(srcEnvelope, transformer);
+ setBounds(transformedEnvelope);
+ return this;
+ }
+
+ private Envelope transformEnvelope( ReferencedEnvelope srcEnvelope, AffineTransform transformer ) {
+ Point2D lowLeft = new Point2D.Double(srcEnvelope.getMinX(), srcEnvelope.getMinY());
+ Point2D transformedLowLeft = new Point2D.Double();
+ transformedLowLeft = transformer.transform(lowLeft, transformedLowLeft);
+ Point2D upRight = new Point2D.Double(srcEnvelope.getMaxX(), srcEnvelope.getMaxY());
+ Point2D transformedUpRight = new Point2D.Double();
+ transformedUpRight = transformer.transform(upRight, transformedUpRight);
+ return new Envelope(transformedLowLeft.getX(), transformedUpRight.getX(),
+ transformedLowLeft.getY(), transformedUpRight.getY());
+ }
+
/**
* <!-- begin-user-doc --> <!-- end-user-doc -->
*
diff --git a/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/ScrollZoom.java b/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/ScrollZoom.java
index 0c9cb5e..cec20c9 100644
--- a/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/ScrollZoom.java
+++ b/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/ScrollZoom.java
@@ -51,7 +51,8 @@ public class ScrollZoom extends AbstractTool {
public void mouseWheelMoved(MapMouseWheelEvent e) {
if( e.modifiersDown() )
return;
- UpdateThread.getUpdater().zoom(e.clickCount*3, getContext(), 500);
+ UpdateThread.getUpdater().zoomWithFixedPoint(e.clickCount * 3, getContext(), 500,
+ e.getPoint());
}
/**
diff --git a/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/UpdateThread.java b/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/UpdateThread.java
index abb9060..bd1c324 100644
--- a/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/UpdateThread.java
+++ b/plugins/net.refractions.udig.tool.default/src/net/refractions/udig/tools/internal/UpdateThread.java
@@ -14,12 +14,16 @@
*/
package net.refractions.udig.tools.internal;
+import java.awt.Point;
import java.util.ArrayList;
+import com.vividsolutions.jts.geom.Coordinate;
+
import net.refractions.udig.project.command.NavCommand;
import net.refractions.udig.project.command.factory.NavigationCommandFactory;
import net.refractions.udig.project.internal.command.navigation.NavComposite;
import net.refractions.udig.project.internal.command.navigation.PanCommand;
+import net.refractions.udig.project.internal.command.navigation.ZoomCommand;
import net.refractions.udig.project.ui.commands.TransformDrawCommand;
import net.refractions.udig.project.ui.tool.IToolContext;
@@ -44,6 +48,7 @@ public class UpdateThread implements Runnable {
private int horizontal=0;
private IToolContext context;
private volatile long updateDelay = 1000;
+ private Coordinate fixedPoint;
private UpdateThread(){}
@@ -133,7 +138,15 @@ public class UpdateThread implements Runnable {
}
requestStart();
}
+
public void zoom( int change, IToolContext context, int updateDelay ) {
+ zoomWithFixedPoint(change, context, updateDelay, null);
+ }
+ /**
+ * Makes zoom and keeps fixedPoint at the same place.
+ */
+ public void zoomWithFixedPoint( int change, IToolContext context, int updateDelay,
+ Point fixedPoint ) {
amount += change;
this.updateDelay = updateDelay;
@@ -142,16 +155,22 @@ public class UpdateThread implements Runnable {
synchronized (UpdateThread.class) {
if (command == null) {
TransformDrawCommand transformDrawCommand = new TransformDrawCommand();
- command=transformDrawCommand;
+ command = transformDrawCommand;
+ if (fixedPoint == null) {
+ fixedPoint = new Point(context.getViewportPane().getWidth() / 2, context
+ .getViewportPane().getHeight() / 2);
+ }
+ transformDrawCommand.fixPoint(fixedPoint);
+ this.fixedPoint = context.pixelToWorld(fixedPoint.x, fixedPoint.y);
transformDrawCommand.zoom(zoom, zoom);
- context.sendASyncCommand(transformDrawCommand );
+ context.sendASyncCommand(transformDrawCommand);
} else {
command.zoom(zoom, zoom);
context.getViewportPane().repaint();
}
}
- this.context=context;
+ this.context = context;
requestStart();
}
@@ -165,7 +184,9 @@ public class UpdateThread implements Runnable {
(NavCommand) new PanCommand((horizontal*-PAN_AMOUNT), (vertical*-PAN_AMOUNT)));
}
if( zoom>0.00000001 ){
- commands.add(factory.createZoomCommand(zoom));
+ ZoomCommand zoomCommand = new ZoomCommand(zoom);
+ zoomCommand.setFixedPoint(fixedPoint);
+ commands.add(zoomCommand);
}
if( commands.size()>0 ){
NavComposite composite = new NavComposite(commands);