ThinkGeo.com    |     Documentation    |     Premium Support

Restrict maximum extent of map

Hi guys,


Is there a way to restrict the maximum extent of the map so that the user cannot zoom out or pan outside that extent? I saw a RestrictedExtent property in the web edition. Is there something similar in the Silverlight edition? 


Thanks.


Nirish



Hi, Nirish



We don’t have RestrictedExtent property in our Silverlight edition product. However, we provide users with more flexibility to implement their requeirments in our products. Maybe you could implement it easily through inheriting ExtentInteractiveOverlay. The code likes below:




 public class RestrictedExtentInteractiveOverlay : ExtentInteractiveOverlay {
        private bool isDragging;
        public RectangleShape RestrictedExtent { get; set; }

        protected override InteractiveResult MouseDownCore(InteractionArguments interactionArguments) {
            isDragging = true;
            return base.MouseDownCore(interactionArguments);
        }

        protected override InteractiveResult MouseUpCore(InteractionArguments interactionArguments) {
            isDragging = false;
            return base.MouseUpCore(interactionArguments);
        }

        protected override InteractiveResult MouseMoveCore(InteractionArguments interactionArguments) {
            if (isDragging) {
                double offsetWidth = interactionArguments.CurrentExtent.Width * .5;
                double offsetHeight = interactionArguments.CurrentExtent.Height * .5;

                double rleft = RestrictedExtent.UpperLeftPoint.X + offsetWidth;
                double rtop = RestrictedExtent.UpperLeftPoint.Y - offsetHeight;
                double rright = RestrictedExtent.LowerRightPoint.X - offsetWidth;
                double rbottom = RestrictedExtent.LowerRightPoint.Y + offsetHeight;

                if (rleft >= rright || rtop <= rbottom) {
                    return new InteractiveResult();
                }

                PointShape currentCenter = interactionArguments.CurrentExtent.GetCenterPoint();
                RectangleShape newCenterRestrictExtent = new RectangleShape(rleft, rtop, rright, rbottom);
                if (!newCenterRestrictExtent.Contains(currentCenter)) {
                    InteractiveResult result = base.MouseMoveCore(interactionArguments);
                    //InteractiveResult result = new InteractiveResult();
                    PointShape newCenter = currentCenter;
                    PointShape restrictCenter = newCenterRestrictExtent.GetCenterPoint();
                    double offsetX = currentCenter.X - restrictCenter.X;
                    double offsetY = currentCenter.Y - restrictCenter.Y;
                    if (Math.Abs(offsetX) > newCenterRestrictExtent.Width * .5) {
                        if (offsetX < 0) {
                            newCenter.X = RestrictedExtent.UpperLeftPoint.X + offsetWidth;
                        }
                        else {
                            newCenter.X = RestrictedExtent.LowerRightPoint.X - offsetWidth;
                        }
                    }
                    if (Math.Abs(offsetY) > newCenterRestrictExtent.Height * .5) {
                        if (offsetY < 0) {
                            newCenter.Y = RestrictedExtent.LowerRightPoint.Y + offsetHeight;
                        }
                        else {
                            newCenter.Y = RestrictedExtent.UpperRightPoint.Y - offsetHeight;
                        }
                    }
                    result.NewCurrentExtent = new RectangleShape(newCenter.X - offsetWidth, newCenter.Y + offsetHeight, newCenter.X + offsetWidth, newCenter.Y - offsetHeight);
                    return result;
                }
                else {
                    return base.MouseMoveCore(interactionArguments);
                }
            }
            return new InteractiveResult();
        }

        protected override InteractiveResult MouseWheelCore(InteractionArguments interactionArguments) {
            int restrictedZoomId = MapInfo.GetClosestZoomLevelIdFromScale(ExtentHelper.GetScale(RestrictedExtent, MapInfo.Width, GeographyUnit.DecimalDegree));
            int zoomLevel = MapInfo.CurrentZoomLevelId;
            if (interactionArguments.MouseWheelDelta <= 0) {
                zoomLevel--;
            }
            else {
                zoomLevel++;
            }

            if (zoomLevel >= restrictedZoomId) {
                double deltaX = interactionArguments.MapWidth * .5 - interactionArguments.ScreenX;
                double deltaY = interactionArguments.ScreenY - interactionArguments.MapHeight * .5;
                double newResolution = MapInfo.GetResolutionFromZoomLevelId(zoomLevel);
                PointShape centerWorldCoordinate = MapInfo.ToWorldCoordinate(interactionArguments.ScreenX, interactionArguments.ScreenY);
                centerWorldCoordinate.X += deltaX * newResolution;
                centerWorldCoordinate.Y += deltaY * newResolution;
                MapInfo.ZoomTo(centerWorldCoordinate, zoomLevel);
                return new InteractiveResult();
            }
            else {
                return new InteractiveResult();
            }
        }
    }

And then you need to add this InteractiveOverlay to map control, the code likes below:




            RestrictedExtentInteractiveOverlay roverlay = new RestrictedExtentInteractiveOverlay();
            roverlay.RestrictedExtent = new RectangleShape(-131.22, 55.05, -54.03, 16.91);
            Map1.ExtentInteractiveOverlay = null;
            Map1.InteractiveOverlays.Add(roverlay);

If you still have any problem please let me know.


Thanks,


Khalil



Thanks Khalil,


Your code work fine for the zoom events. However, in pan mode, if the extents are beyond the restricted extent, then the user is not able to move the map at all, even within the unrestricted extents. I tried to simplify the logic in my own function as follows. All I'm doing is checking to see if the current extent is smaller than the restricted extent. If not, it fixes the spilling extents to be equal to the restricted extent boundaries.



protected override InteractiveResult MouseMoveCore(InteractionArguments interactionArguments)
{
    if (isDragging)
    {
        bool extentRestricted = false;
        if (interactionArguments.CurrentExtent.UpperLeftPoint.X < RestrictedExtent.UpperLeftPoint.X)
        {
            interactionArguments.CurrentExtent.UpperLeftPoint.X = RestrictedExtent.UpperLeftPoint.X;
            extentRestricted = true;
        }
        if (interactionArguments.CurrentExtent.UpperLeftPoint.Y > RestrictedExtent.UpperLeftPoint.Y)
        {
            interactionArguments.CurrentExtent.UpperLeftPoint.Y = RestrictedExtent.UpperLeftPoint.Y;
            extentRestricted = true;
        }
        if (interactionArguments.CurrentExtent.LowerRightPoint.X > RestrictedExtent.LowerRightPoint.X)
        {
            interactionArguments.CurrentExtent.LowerRightPoint.X = RestrictedExtent.LowerRightPoint.X;
            extentRestricted = true;
        }
        if (interactionArguments.CurrentExtent.LowerRightPoint.Y < RestrictedExtent.LowerRightPoint.Y)
        {
            interactionArguments.CurrentExtent.LowerRightPoint.Y = RestrictedExtent.LowerRightPoint.Y;
            extentRestricted = true;
        }
        if (extentRestricted)
        {
            InteractiveResult result = base.MouseMoveCore(interactionArguments);
            result.NewCurrentExtent = interactionArguments.CurrentExtent;
            return result;
        }
        else
        {
            return base.MouseMoveCore(interactionArguments);
        }
    }
    return new InteractiveResult();
}
 

 


Let me know if this method is appropriate. I did find that I am able to drag the map beyond the restricted extent 'forcefully' (repeatedly dragging the map beyond the restricted extents). 


Thanks,


Nirish



Nirish, 
  
 Yes, your method is appropriate, but there are two problems. One problem is just you have mentioned that you are still able to drag the map beyond the restricted extent, what I mean is that when your CurrentExtent is beyond the restricted extent, the map needs to render in restricted extent but CurrentExtent. Another one is flicker problem, that’s because MouseMoveCore is called frequently. 
  
 We have added this feature to the latest Dll package, please check it out. 
 If you still have any problem, please let me know. 
  
 Thanks, 
  
 Khalil 


Hi Khalil, 
  
 When can I find this feature? Are you referring to the DLL package published on 16 Nov 09? 
  
 Thanks, 
  
 Nirish

Hi, Nirish


Sorry for make you confused. What I mean is that we have added this new feature to Daily Development Build, please log on to crm.thinkgeo.com with your own username and password. Please refert to the screenshot below.



From last week on, uses could get latest Dll packages every day through crm.thinkgeo.com, and for Daily Development Build Download, we will add new features and fix bugs for it, but for Daily Production Build, we will only fix the bugs. So you just need to down SilverlightEdition dll package from Development Build section.


If you still have any problems please let me konw.


Thanks,


Khalil



Hi Khalil, 
  
 I get the following error on the map when I use the new DLLs and the map does not load: 
  
 ‘The GeoCanvas is currently not drawing. Please call the BeginDraw method before calling this method.’ 
  
 Also, were you referring to the Restricted Extent feature in the new build when wrote ‘We have added this feature to the latest Dll package’? Could you show a sample usage please? I was not able to find it. 
  
 Thanks, 
  
 Nirish

Nirish,



Yes, what I mean is the Restricted Extent feature.

Sorry for the inconvenience. Please contact the support@thinkgeo.com to get the latest dll package.


And then you could use this new feature like the code below:




   Map1.RestrictedExtent = new RectangleShape(-150, 60, -149, 59);

            Map1.CurrentExtent = new RectangleShape(-131.22, 55.05, -54.03, 16.91);


Thanks,


Khalil



Hi Johnny, 
  
 With the new DLLs, I get the following error when loading the ASPX page which hosts the map. 
  
 Object reference not set to an instance of an object. 
 Stack Trace:  
 [NullReferenceException: Object reference not set to an instance of an object.] 
    ThinkGeo.MapSuite.SilverlightEdition.SilverlightMapConnector.x1811944f4031e215() +1645 
    ThinkGeo.MapSuite.SilverlightEdition.SilverlightMapConnector.OnLoad(EventArgs e) +100 
    System.Web.UI.Control.LoadRecursive() +65 
    System.Web.UI.Control.LoadRecursive() +190 
    System.Web.UI.Control.LoadRecursive() +190 
    System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2427 
  
 Am I missing something with this new DLL package? 
  
 Thanks, 
  
 Nirish

Nirish, 
  
 On the server side, when the load event of SilverlightMapConnector is triggered, we will register httphandlers in the web configuration file. This error maybe is caused that you don’t have permission to modify Web.config file if you have deployed it to iis or you have checked it in to source control system. You could test our installed samples with the new DLLs and to see whether the problem exists. 
  
 If you still have this problem please let me know. 
  
 Thanks, 
  
 Khalil

Hi Khalil, 
  
 I removed the Web.config file from source control but it still throws the same error. I am testing this on my local machine. So I have full trust level set up in IIS. The samples work fine with the new DLLs though. :s 
  
 Thanks, 
  
 Nirish

Nirish,  
  
 When you remove the web.config file from the source control, also please make sure the file is not read only in the file system. Also, does the call stack is the same as you posted before? 
  
 Looking forward your feed back, thanks. 
 Howard

Hi Howard, 
  
 The web.config file’s writable in the file system. Yes, I get the same stack trace. 
  
 Thanks, 
  
 Nirish

Nirish,






I wonder what you mean when you said that you have full trust level set up in IIS. If you still deploy it in IIS, please try to set permission for “Everyone” and test it. If you till have this problem, please add the code below to httpHandler section of web.config file,





 <add path="GeoTile.axd" verb="*" type="ThinkGeo.MapSuite.SilverlightEdition.TileHandler" />



and if you are working in IIS7.0, please also add the code below to system.webServer section.





 <add name="GeoTileResource" path="GeoTile.axd" verb="*" type="ThinkGeo.MapSuite.SilverlightEdition.TileHandler" />



Thanks,






Khalil



Hi Khalil, 
  
 The exception still gets thrown after I set full permission to everyone in IIS. The line with GeoTile.axd is already there in the httpHandler section of web.config. I don’t understand why updating the DLLs require all these changes in the configuration and why the DLLs work in the sample app and not in our app. 
  
 Thanks, 
  
 Nirish

Hi, Nirish 
  
 We don’t require all these changes in the web.config file, and we will register httphandlers for you automatically. From the exception stack trace, we guess the problem is caused by that you don’t have permission on configuration file. You could try to use the web.config file in our installed samples 
 instead of yours. If you still have problem, could you provide us which version of iis and Silverlight Edition you are using. Also, send us the code and data to help us recreate your issue. We’ll check it out. If your project is too big, please send to support@thinkgeo.com and ask to forward to me. 
  
 Thanks, 
 Khalil

Hi Khalil, 
  
 Further to my previous post, I copied back the old SilverlightMapConnector.dll and the Silverlight application loads fine. Something to do with SilverlightMapConnector?  
  
 Now I get the following error on the map tiles and the map does not load: 
  
 ‘The GeoCanvas is currently not drawing. Please call the BeginDraw method before calling this method.’  
  
 Thanks, 
  
 Nirish

Hi, Nirish 
  
 We don’t change any thing with SilverlightMapConnector recently. Please try to update the all reference DLLs with the latest DLL package. Maybe there is some incompatible problem. 
 If you still have problem, please send us the code to help us recreate your issue. 
  
 Thanks, 
 Khalil