[Qgis-developer] Force canvas to predefined scales : help needed to improve a script

kimaidou kimaidou at gmail.com
Fri Apr 17 05:41:55 PDT 2015


Thanks a lot Nathan !

2015-04-17 14:40 GMT+02:00 Nathan Woodrow <madmanwoo at gmail.com>:

> And here is a different way using just functions:
>
> (https://gist.github.com/mdouchin/72a09b629a5557c1dc1c#comment-1435388)
>
> def forcedScale(*scales):
>     replayed = False
>
>     def setScale(scale ):
>         iface.mapCanvas().scaleChanged.disconnect(setScale)
>
>         print "initial scale: %s" % scale
>
>         targetScale = min(
>             scales,
>             key=lambda x:abs(x-scale)
>         )
>         if targetScale == scale:
>             return
>
>         print "zoom to %s" % targetScale
>         iface.mapCanvas().zoomScale( targetScale )
>         iface.mapCanvas().scaleChanged.connect(setScale)
>
>     # pre-defined scales
>     predefinedScales = [
>         5000,
>         10000,
>         25000,
>         50000,
>         100000,
>         250000,
>         500000
>     ]
>
>     # avoid loop
>
>     iface.mapCanvas().scaleChanged.connect(setScale)
>
>     if not scales:
>         scales = predefinedScales
>
> On Fri, 17 Apr 2015 at 22:34 kimaidou <kimaidou at gmail.com> wrote:
>
>> More pythonesque Nathan, thanks !
>>
>> 2015-04-17 14:32 GMT+02:00 Nathan Woodrow <madmanwoo at gmail.com>:
>>
>>> def __init__( self, *predefinedScales ):
>>> and you can do this
>>>
>>> forcedScale(25000, 50000, 100000)
>>>
>>> On Fri, 17 Apr 2015 at 22:30 kimaidou <kimaidou at gmail.com> wrote:
>>>
>>>> Hi all,
>>>>
>>>> Improve version here:
>>>> https://gist.github.com/mdouchin/72a09b629a5557c1dc1c
>>>>
>>>> with:
>>>>
>>>> * "replayed" variable to avoid probable infinite loop, thanks to Hugo's
>>>> proposal
>>>>
>>>> * you can now initialize the method with a python list of scales you
>>>> want to force canvas to:
>>>>
>>>> fs =  fs = forcedScale( [25000, 50000, 100000 ] )
>>>>
>>>> Cheers,
>>>> Michaël
>>>>
>>>> 2015-04-17 12:27 GMT+02:00 kimaidou <kimaidou at gmail.com>:
>>>>
>>>>> Hi Hugo,
>>>>>
>>>>> Thanks for the anwser. I used some "print scale" and "print
>>>>> targetScale" in my script to check the behavious, and I did not have any
>>>>> "infinite loop" or strange behaviour with it. It seems the related QGIS
>>>>> code is armed against this risks.
>>>>>
>>>>> This python script was only a prototype, and I will surely have a look
>>>>> at the cpp classes and propose a PR to add this option in QGIS core.
>>>>>
>>>>> Michaël
>>>>>
>>>>> 2015-04-17 11:26 GMT+02:00 Hugo Mercier <hugo.mercier at oslandia.com>:
>>>>>
>>>>>> Hi,
>>>>>>
>>>>>> Le 17/04/2015 10:46, kimaidou a écrit :
>>>>>> > Hi QGIS !
>>>>>> >
>>>>>> > I would like to be able in QGIS to force the canvas scales to some
>>>>>> > predefined ones. Since we now have project scales (and QGIS
>>>>>> pre-defined
>>>>>> > scales) in the scale selector, we could use them, and add a simple
>>>>>> > checkbox near the combobox "Stick to predefined scales".
>>>>>> >
>>>>>> > The aim is to force the canvas to render only at these scales. For
>>>>>> > example, if I use the rectangle zoom tool, and I should go toe
>>>>>> 1/56003,
>>>>>> > I would instead land on 1/50000 , the closest pre-defined scale.
>>>>>>
>>>>>> That would be nice to have it in the core. I already had to do
>>>>>> something
>>>>>> similar with a plugin.
>>>>>>
>>>>>> >
>>>>>> > I made a little python script as a proof of concept to illustrate
>>>>>> it :
>>>>>> > http://paste.debian.net/167247/
>>>>>> >
>>>>>> > In this script, I hard coded the scales, but oviously we should get
>>>>>> them
>>>>>> > from the project properties.
>>>>>> >
>>>>>> > I have a question regarding my script. Since I use the
>>>>>> > QgsMapCanvas::scaleChanged signal, I assume the rendering is done
>>>>>> twice
>>>>>> > ? Once the "normal" way, and once again after I use the
>>>>>> > QgsMapCanvas::zoomScale method after calculating the new target
>>>>>> scale.
>>>>>> >
>>>>>> > Any idea for improving it ? I assume I would have to disconnect one
>>>>>> (not
>>>>>> > found yet) signal/slot, then set the scale and reconnect this
>>>>>> > signal/slot afterwards ?
>>>>>>
>>>>>> QObject::blockSignals might be of help here. But in this case, you
>>>>>> don't
>>>>>> want to block all signals, only yours.
>>>>>>
>>>>>> I guess your solution would work.
>>>>>> You can also use a flag in your callback, something like :
>>>>>>
>>>>>>     def setScale( self, scale ):
>>>>>>         if self.reentrant:
>>>>>>                 return
>>>>>>
>>>>>>         targetScale = min(
>>>>>>             self.predefinedScales,
>>>>>>             key=lambda x:abs(x-scale)
>>>>>>         )
>>>>>>         self.reentrant = True
>>>>>>         self.mc.zoomScale( targetScale )
>>>>>>         self.reentrant = False
>>>>>>
>>>>>> _______________________________________________
>>>>>> Qgis-developer mailing list
>>>>>> Qgis-developer at lists.osgeo.org
>>>>>> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>>>>>
>>>>>
>>>>>
>>>> _______________________________________________
>>>> Qgis-developer mailing list
>>>> Qgis-developer at lists.osgeo.org
>>>> http://lists.osgeo.org/mailman/listinfo/qgis-developer
>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20150417/aaf18bf6/attachment.html>


More information about the Qgis-developer mailing list