cat brain.log | less

Getting it down on `paper`

Using Log Math to Solve Iterative Problems

Premise: You have a map of infinite resolution, but finite viewing space. You have points on that map that have a fixed foot print.

Question: How much do you need to zoom before the points are clearly distinguishable?

Let us arbitrarily define the criteria for distinguishability as an icon of 25 pixels in size. This icon, it can be said, has a radius of 13 pixels. In reality, icon size is a function of your viewport’s size. I leave that up to you to calculate.

Let us define the scale of the map as the absolute width of the map (in map units) divided by the width of the view port. As an example, let’s use the Earth’s longitude range: -180 to +180 degrees, but in a global Mercator projection. The coordinate range of longitude for this map is [-20037508,+20037508) meters. Our viewport has a range of [0,255] pixels (viewport units). The scale of this map in this viewport is (2*20037508)/256. Be careful not to double-count +20037508, as -20037508 = +20037508 and would yield an improper scale. The viewport size is an integer and does not wrap; there are no fractions of a pixel in a viewport.

We shall now define a target scale. The target scale is the desired scale of the map that allows our icons to become viewable. Our example will use buildings having a foot print of 300 meters (map units) in width and depth. Our target scale, therefore, is 300/25 = 12 meters per pixel.

Question: How much do we need to zoom in before our buildings are distinguishable?

Implementation 1 (naive, iterative):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function zoomLevel( $maprange, $viewport, $distFactor=0.10, $zoomFactor=2 ) {
  // $viewport = 256;
  // $maprange = 2*M_PI*6378137;
  $scale = $maprange / $viewport;
 
  // 10% of viewport required to distinguish an icon.
  $target = $distFactor * $viewport;
 
  $zoom = 0;
  while ( $scale > $target ) {
    $zoom += 1;
    $scale /= $zoomFactor;
  }
  return $zoom;
}

Implementations 2, 3 and 4:

1
2
3
4
5
6
7
8
9
10
11
12
13
function zoomLevel( $maprange, $viewport, $distFactor=0.10, $zoomFactor=2 ) {
  $scale = $maprange / $viewport;
  $target = $distFactor * $viewport;
 
  // naive log
  return ceil( (log($scale)/log($zoomFactor) - log($target)/log($zoomFactor)) );
 
  // commutative log
  return ceil( (log($scale) - log($target)) / log($zoomFactor) );
 
  // subtraction property of logs (best implementation)
  return ceil( log($scale/$target)/log($zoomFactor) );
}
 

Comments

No comments so far.

(comments are closed)