3
function get_map_zoom_level(distance) {
    var zoom = 1;
    if (distance == 0)
        zoom = 11;
    else if (distance == 1)
        zoom = 15;
    else if (distance > 880 && distance <= 1760)
        zoom = 14;
    else if (distance > 1760 && distance <= 3520)
        zoom = 13;
    else if (distance > 3520 && distance <= 7040)
        zoom = 12;
    else if (distance > 7040 && distance <= 14080)
        zoom = 11;
    else if (distance > 14080 && distance <= 28160)
        zoom = 10;
    else if (distance > 28160 && distance <= 56320)
        zoom = 9;
    else if (distance > 56320 && distance <= 112640)
        zoom = 8;
    else if (distance > 112640 && distance <= 225280)
        zoom = 7;
    else if (distance > 225280 && distance <= 450560)
        zoom = 6;
    else if (distance > 450560 && distance <= 889120)
        zoom = 5;
    else if (distance > 889120 && distance <= 1718240)
        zoom = 4;
    else if (distance > 1718240)
        zoom = 3;
    return zoom;
}

I want to know if there is any way to avoid many if else in this code. Basically I want to find out zoom level on the basis of distance, this code is working perfectly but I need some better way to do this.

Sunny Kumar
  • 81
  • 1
  • 6
  • 1
    a switch with a interval condition ? Since there is a logic between the zoom of the map and the distance, I guess you should search a math formula to find the zoom value. – AxelH Jun 02 '16 at 10:19
  • 2
    @KartikeyaKhosla OK you have less `if` statements but you end with the same number of `case` statements, which defeats the object – Rhumborl Jun 02 '16 at 10:31
  • @Juhana `switch (true)`, but OP is better of defning an array of ranges and loop through it – PeeHaa Jun 02 '16 at 10:31
  • If you have found an answer helpful, do not forget to accept it! Have it in mind for the future too. Rhumborl's answer seems fine, since it transforms a sequence of conditions, checking a range each, into a search in a structure containing ranges (and their respective zoom values) to find the applicable range (and the respective zoom value). – xnakos Jun 09 '16 at 11:23

4 Answers4

3

When you have a large number of if statements comparing the same data as yours is, the usual approach is to create an Array, where each entry contains the data to compare and the result, in other words the minimum distance, the maximum distance, and the zoom level.

To do the comparison, you use a for loop to go through the array, checking the values for each. if you find a matching entry, then set the result and break out of the loop.

This is not more efficient or quicker than the way you have done it, but it means you can have any number of options and your actual code doesn't get bigger or more complicated.

Here is how you can do this with yours:

function get_map_zoom_level(distance) {

    // create the array of values. Each entry can be either an array or an object, doesn't matter too much.
    // I'll use an array set up as [minDistance, maxDistance, zoom]
    var zoomLevels = [
        [880, 1760, 14],
        [1760, 3520, 13],
        [3520, 7040, 12],
        [7040, 14080, 11],
        // ... etc.
    ]

    var zoom = 1;
    // special cases
    if (distance == 0)
        zoom = 11;
    else if (distance == 1)
        zoom = 15;
    else if (distance > 1718240)
        zoom = 3;
    else {
        for (var i = 0; i < zoomLevels.length; i++) {
            var zoomLevel = zoomLevels[i];
            if (distance > zoomLevel[0] && distance <= zoomLevel[1]) {
                zoom = zoomLevel[2];
                // found a match - stop the loop
                break;
            }
        }
    }

    return zoom;

}

By the way, zoom level 11 seems to have an error in it, 7040 and 1480 don't match.

xnakos
  • 9,870
  • 6
  • 27
  • 33
Rhumborl
  • 16,349
  • 4
  • 39
  • 45
3

This should work:

function get_map_zoom_level(distance) {
var zoom = 15;
var temp=880;
if (distance == 0)
    zoom = 11
while (distance > temp){
    temp=temp*2;
    zoom--;
}
return zoom;
}
agni10
  • 124
  • 3
  • 11
  • I was just gonna say. It looks like all you have to do is multiplication. This is the most elegant solution. – beingalex Jun 02 '16 at 10:47
  • 1
    Damn, same answer ^^ I lose time to create the example :P Our teacher were right, math are going to save us in the futur ;) – AxelH Jun 02 '16 at 10:51
  • Your solution is very simple to understand and precise but there is very small problem with zoom level 5 and 4 they not have radio of two , but i think i can make a list and via a loop i check n and n+1 element and and if distance lies between these then i return the zoom level else accordingly increase or decrees the zoom level . thanks – Sunny Kumar Jun 02 '16 at 11:11
  • 1
    If this was true you could do it even easier with `(15 - Math.log2(valueToTest/880))` but sadly `889120` and `1718240` don't fit. `get_map_zoom_level(889121)` for example will return a wrong zoom level. – AUsr19532 Jun 02 '16 at 11:22
  • 1
    15 - Math.ceil(Math.log2(distance / 1760)) to be more... integer, I believe. I also believe that the distances should have been multiples of 2, but were calculated erroneously. 889120 instead of 901120. – xnakos Jun 02 '16 at 11:25
  • No values are correct for height: 550px and width: 960px – Sunny Kumar Jun 02 '16 at 11:32
2

You could have an object like:

var zooms = [ { min:1480 , max:28160} ,  // array index is zoom level
              // ...
              { min:880 , max:1760} ];

and then iterate it until the zoom is found

for(var z = 1 ; z <= MAX_ZOOM ; z++) {
    if (distance > zooms[z].min && distance <= zooms[z].max) {
        return z;
    }
}

In Java, it would be easier.

Community
  • 1
  • 1
Luís Soares
  • 5,726
  • 4
  • 39
  • 66
0

The following code keeps the exact same edge cases (explicit, e.g. distance is 0 -> zoom is 11, and implicit, e.g. distance is 42 -> zoom is 1) that your code has in the same order as well, but, if we are not dealing with an edge case, decides on the applicable intermediate range using an array of distances in ascending order, representing inclusive upper bounds (of ranges). The exclusive lower bound is handled by iterating the array from the beginning, since the values are ascending.

function get_map_zoom_level(distance) {
    var distanceBreakpoints = [1760, 3520, 7040, 14080, 28160, 56320, 112640, 225280, 450560, 889120, 1718240];
    var zoom = 1;
    if (distance == 0)
        zoom = 11;
    else if (distance == 1)
        zoom = 15;
    else if (distance > 880 && distance <= 1718240) {
        for (var i = 0; i < distanceBreakpoints.length; ++i) {
            if (distance <= distanceBreakpoints[i]) {
                zoom = 14 - i;
                break;
            }
        }
    } else if (distance > 1718240)
        zoom = 3;
    return zoom;
}
xnakos
  • 9,870
  • 6
  • 27
  • 33