Ticket #1243 (closed feature: fixed)

Opened 5 years ago

Last modified 5 years ago

allow for non-discrete resolution/zoom levels (fractional zoom)

Reported by: tschaub Owned by: tschaub
Priority: major Milestone: 2.6 Release
Component: Map Version: 2.5
Keywords: Cc:
State: Complete

Description

For base layers that support it, we should be able to zoom to an arbitrary resolution.

Attachments

fractional.patch Download (12.2 KB) - added by tschaub 5 years ago.
allow for non discrete zoom levels

Change History

  Changed 5 years ago by tschaub

This needs solid testing, and I welcome comments on the approach - for an example, see  http://dev.openlayers.org/sandbox/tschaub/fractional/examples/fractional-zoom.html

follow-up: ↓ 7   Changed 5 years ago by bartvde

Tim, I tested this with WMS layers and it works like a charm. Can't test it with commercial layers though.

One question though: it appeared like this won't work if the map has a scales array, so I had to use minScale and maxScale to get it to work. But I guess that's to be expected.

  Changed 5 years ago by pspencer

Tim, I love this change and I think it will be an important addition for several projects using OpenLayers. Mike will be testing this with Fusion, this week hopefully, and providing feedback as required.

  Changed 5 years ago by tschaub

Thanks Paul. Yeah, it needs some real field testing. Will be good to get your feedback.

  Changed 5 years ago by tschaub

  • owner set to tschaub
  • status changed from new to assigned

follow-up: ↓ 8   Changed 5 years ago by tschaub

I think this is a fairly non-invasive change to get this functionality. The things it does change aren't liable to haunt us (in my opinion). If an app designer sets map.fractionalZoom to true, they should know not to access layer.resolutions[zoom] directly.

I added a map.allowFracZoom method. I don't necessarily like this, but it makes things degrade well for commercial layers. The part I don't like is the check for a RESOLUTIONS constant. But I like less the alternative of modifying anything in the FixedZoomLevels layers.

(As an aside, I'm also curious about the this.resolutions != null checks in FixedZoomLevels. Since all the classes in our lib that inherit from FZL have a RESOLUTIONS constant, and initResolutions sets resolutions, I don't immediately see when this condition would ever be met. But I'll leave that for elsewhere.)

in reply to: ↑ 2   Changed 5 years ago by tschaub

Replying to bartvde:

Tim, I tested this with WMS layers and it works like a charm. Can't test it with commercial layers though. One question though: it appeared like this won't work if the map has a scales array, so I had to use minScale and maxScale to get it to work. But I guess that's to be expected.

Hmm. Maybe I need more info. If I create a map like

            var options = {
                scales: [442943842.5, 221471921.25, 110735960.625, 55367980.3125, 27683990.15625, 13841995.078125, 6920997.5390625, 3460498.76953125, 1730249.384765625, 865124.6923828125, 432562.34619140625, 216281.17309570312, 108140.58654785156, 54070.29327392578, 27035.14663696289, 13517.573318481445]
            };
            map = new OpenLayers.Map('map', options);
            var wms = new OpenLayers.Layer.WMS(
                "OpenLayers WMS",
                "http://labs.metacarta.com/wms/vmap0",
                {layers: 'basic'}
            );
            map.addLayer(wms);

everything works as I'd expect. How are you setting your scales array?

in reply to: ↑ 6 ; follow-up: ↓ 11   Changed 5 years ago by elemoine

Replying to tschaub:

I think this is a fairly non-invasive change to get this functionality. The things it does change aren't liable to haunt us (in my opinion). If an app designer sets map.fractionalZoom to true, they should know not to access layer.resolutions[zoom] directly. I added a map.allowFracZoom method. I don't necessarily like this, but it makes things degrade well for commercial layers. The part I don't like is the check for a RESOLUTIONS constant. But I like less the alternative of modifying anything in the FixedZoomLevels layers. (As an aside, I'm also curious about the this.resolutions != null checks in FixedZoomLevels. Since all the classes in our lib that inherit from FZL have a RESOLUTIONS constant, and initResolutions sets resolutions, I don't immediately see when this condition would ever be met. But I'll leave that for elsewhere.)


Tim,

Some questions/comments on your patch:

  • the getResolutionForZoom method of the Map class checks whether that a method of the same name is defined on the base layer. Since the getResolutionForZoom method is part of the generic Layer class, I don't see how this condition wouldn't be met.
  • I'm also not a big fan of the RESOLUTIONS check in allowFracZoom. Why not define the new property allowFracZoom in the Layer class and have the FixedZoomLevels class set this property to false? In that way, layers that don't permit fractional zoom can advertize it - the TileCache layer might be of those classes by the way, and this isn't caught by your RESOLUTIONS check (I'm not too familiar with the TileCache layer and be cautious with my assessments :-)
  • Line 820 of the patch, you use the i variable while it was defined outside the current scope in the for loop above.

  Changed 5 years ago by bartvde

  • milestone set to 2.6 Release

  Changed 5 years ago by bartvde

Hi Tim, another question about this. Why is map.zoomTo not adapted to also take in floats? When I want to zoom now to a fractional level I have to do the following detour:

var zoomLevel = this.map.zoom + (deltaY/this.zoomStopHeight);
var scale = OpenLayers.Util.getScaleFromResolution(
    this.map.getResolutionForZoom(zoomLevel), this.map.units );
this.map.zoomToScale(scale);

Whereas I would want to do:

var zoomLevel = this.map.zoom + (deltaY/this.zoomStopHeight);
this.map.zoomTo(zoomLevel);

in reply to: ↑ 8   Changed 5 years ago by tschaub

Replying to elemoine:

* the getResolutionForZoom method of the Map class checks whether that a method of the same name is defined on the base layer. Since the getResolutionForZoom method is part of the generic Layer class, I don't see how this condition wouldn't be met.

Yeah, was thinking a layer might set it to null to exclude itself from this fractional business. Thanks for the tip, I've removed it.

* I'm also not a big fan of the RESOLUTIONS check in allowFracZoom. Why not define the new property allowFracZoom in the Layer class and have the FixedZoomLevels class set this property to false? In that way, layers that don't permit fractional zoom can advertize it - the TileCache layer might be of those classes by the way, and this isn't caught by your RESOLUTIONS check (I'm not too familiar with the TileCache layer and be cautious with my assessments :-)

Gone now. The fractionalZoom property is now a "user beware" property. Works for layers where non-discrete zoom levels makes sense. Doesn't otherwise.

* Line 820 of the patch, you use the i variable while it was defined outside the current scope in the for loop above.

Can you restate this? The patched code does not use i while it is undefined, nor are there scope issues as far as I can tell. I did move the zoom = Math.max(0, i-1) statement into an else block, but i is always defined there. I'm updating the patch. Let me know if you still see issues with it.

Changed 5 years ago by tschaub

allow for non discrete zoom levels

  Changed 5 years ago by tschaub

  • priority changed from minor to major
  • state set to Review

Tests pass in FF and IE7. Thanks for any review.

follow-up: ↓ 15   Changed 5 years ago by ahocevar

Tim, I also do not see anything wrong with using the i outside the loop. Furthermore, I have applied your patch and modified my local MapBuilder copy to make use of fractionalZoom. I tested with all MapBuilder examples, and it just works.

The code is non-invasive and intuitive to read. With other words: great work! My vote on this ticket is "Please commit", but I leave the "Review" state untouched, because there is promised feedback pending from pspencer/madair.

  Changed 5 years ago by crschmidt

  • state changed from Review to Commit

I don't think we need to wait for Paul/Mike on this: 3 weeks is long enough to give something a try. (We can always update things before the 2.6 release anyway.) Tim, this looks good; go ahead with it as is, in my opinion.

in reply to: ↑ 13   Changed 5 years ago by elemoine

Replying to ahocevar:

Tim, I also do not see anything wrong with using the i outside the loop.


I doubled check and there's indeed nothing wrong with using the i outside the loop.

-- Eric

  Changed 5 years ago by pspencer

Yeah, don't wait on us. I've looked this patch over a couple of times but I don't think that Mike has had a chance to try it out.

  Changed 5 years ago by tschaub

  • status changed from assigned to closed
  • state changed from Commit to Complete
  • resolution set to fixed

(In [5982]) Adding fractionalZoom property to the map. This allows zooming to an arbitrary level, making it possible to have non-discrete resolutions for layers that support it. This property should not be set to true for layers with fixed zoom levels (commercial layers or others with cached tiles). r=elemoine,crschmidt,ahocevar (closes #1243)

Note: See TracTickets for help on using tickets.