4

I am trying to figure out how to set the zoom scales to match those meant for OpenStreetMaps and Google Maps, etc., as I am using OSM for a basemap. I've looked all over the internet and can't seem to find any support for this particular goal.

I have an XML document (scales.xml) with all of the scales needed, but I just can't figure out how to implement it:

<qgsScales version="1.0">
    <scale value="1:591657528"/>
    <scale value="1:295828764"/>
    <scale value="1:147914382"/>
    <scale value="1:73957191"/>
    <scale value="1:36978595"/>
    <scale value="1:18489298"/>
    <scale value="1:9244649"/>
    <scale value="1:4622324"/>
    <scale value="1:2311162"/>
    <scale value="1:1155581"/>
    <scale value="1:577791"/>
    <scale value="1:288895"/>
    <scale value="1:144448"/>
    <scale value="1:72224"/>
    <scale value="1:36112"/>
    <scale value="1:18056"/>
    <scale value="1:9028"/>
    <scale value="1:4514"/>
    <scale value="1:2257"/>
    <scale value="1:1128"/>
    <scale value="1:564"/>
    <scale value="1:282"/>
    <scale value="1:141"/>
    <scale value="1:71"/>
</qgsScales>

I've tried reworking some of the code from thr QuickMapServices plugin, but I get no results from it:

def _load_scales_list(self):
    scales_filename = os.path.join(self.plugin_dir, 'scales.xml')
    scales_list = []

    xml_root = ET.parse(scales_filename).getroot()
    for scale_el in xml_root.findall('scale'):
        scales_list.append(scale_el.get('value'))
    return scales_list

def scales_list(self):
    if not self._scales_list:
        self._scales_list = self._load_scales_list()
    return self._scales_list

def set_nearest_scale(self):
    #get current scale
    curr_scale = self.mapCanvas().scale()
    #find nearest
    nearest_scale = sys.maxint
    for scale_str in self.scales_list:
        scale = scale_str.split(':')[1]
        scale_int = int(scale)
        if abs(scale_int-curr_scale) < abs(nearest_scale - curr_scale):
            nearest_scale = scale_int

    #set new scale
    if nearest_scale != sys.maxint:
        self.mapCanvas().zoomScale(nearest_scale)

This code neither throws an error nor does anything at all. Any ideas as to how I can get this working in a standalone window?

| improve this question | | | | |
3
+50

You should place the definition of the list of predefined scales in your init-method.

self.predefinedScale = [...]

Then connect the scaleChanged event to the function actually setting the proper scale.

self.mapCanvas.scaleChanged.connect(self.zoomToScale)

Define this function as class method, not as local function of some other method, so that it will be executed in the global context.

def zoomToScale(self)
    self.mapCanvas.scaleChanged.disconnect(self.zoomToScale)
    scale = self.mapCanvas.scale()
    targetScale = min(self.predefinedScales, key=lambda x: abs(x - scale))
    self.mapCanvas.zoomScale(targetScale)
    self.mapCanvas.scaleChanged.connect(self.zoomToScale)
| improve this answer | | | | |
3

you can define this scale in predefined scale for qgisenter image description here

USING Python :

def forcedScale(scales):
    def zoomToScale(scale):
        self.iface.mapCanvas().scaleChanged.disconnect(zoomToScale)
        targetScale = min(scales, key=lambda x:abs(x-scale))
        self.iface.mapCanvas().zoomScale( targetScale )
        self.iface.mapCanvas().scaleChanged.connect(zoomToScale)

    predefinedScales = [
        591657528,
        295828764,
        147914382,
        73957191,
        36978595,
        18489298,
        9244649,
        4622324,
        2311162,
        1155581,
        577791,
        288895,
        144448,
        72224,
        36112,
        18056,
        9028,
        4514,
        2257,
        1128,
        564,
        282,
        141,
        71
    ]

    self.iface.mapCanvas().scaleChanged.connect(zoomToScale)
    scales = predefinedScales
| improve this answer | | | | |
  • This is helpful for QGIS Desktop, but I'm coding out of the QGIS API. I need to figure out how to do this in python. Thanks though. – Alex92 Oct 21 '15 at 3:57
  • I tried your Python with a few changes, as the "iface" variable is not usable outside of QGIS proper. For the purposes of using this standalone, I changed all instances of "iface" to "self", and added "self" to the list of arguments in each definition. Also needed to add commas in the scales list. However, the code ends up not working, and my scales have not changed. – Alex92 Oct 27 '15 at 15:12
  • did you try to add print statement to check if this function is called ? because i tried this now it works for me. – Nikhil Murarka Oct 27 '15 at 18:38
  • 1
    I did, and it appears the function is not called. Here is a link to a gist of my code. It begins at line 142. Could I have implemented it wrong? – Alex92 Oct 27 '15 at 20:13
  • you are not calling forcedScale anywhere in your code. call this function in main or somewhere else. – Nikhil Murarka Oct 27 '15 at 21:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.