Thursday, July 14, 2011

Data decimation

The some times u just cant send out 100s of MBs of data, hell sometimes you cant process it. Basically you need to decimate the results into a usable shape. The average joe understands averages and maximums. So break it down based on what you need to see for the current level of zoom.


function decimate($points, $bounds)
{
  $lngcnt = 20;
  $latcnt = 20;
  
  $cdl = array();
  foreach($points as &$p)
  {
    $lngper = ($p['long'] - $bounds[1])/($bounds[3] - $bounds[1]);
    $latper = ($p['lat']  - $bounds[0])/($bounds[2] - $bounds[0]);
    $latidx = intVal($latcnt*$latper);
    $lngidx = intVal($lngcnt*$lngper); 
    $val = $p['cpm'];

    #create arrays if needed
    if(!isset($cdl[$lngidx]))
    {
      $cdl[$lngidx] = array();
    }

    if(!isset($cdl[$lngidx][$latidx]))
    {
      $cdl[$lngidx][$latidx] = array();
      $cp = &$cdl[$lngidx][$latidx];
      $cp['sum'] = $val;
      $cp['cnt'] = 1;
      $cp['max'] = $val;
      $cp['max_long'] = $p['long'];
      $cp['max_lat']  = $p['lat'];
      # $cp['min'] = $val;
      # $cp['min_long'] = $p['long'];
      # $cp['min_lat']  = $p['lat'];
    }
    else
    {
      $cp = &$cdl[$lngidx][$latidx];
      $cp['sum'] += $val;
      $cp['cnt']++;
      if ($val > $cp['max'])
      {
        $cp['max']      = $val;
        $cp['max_long'] = $p['long'];
        $cp['max_lat']  = $p['lat'];
      }
      # if ($val < $cp['min'])
      # {
      #   $cp['min']      = $val;
      #   $cp['min_long'] = $p['long'];
      #   $cp['min_lat']  = $p['lat'];
      # }
    }
  }
  
  $res = array();
  foreach($cdl as $lng => &$lngcdl)
  {
    foreach($lngcdl as $lat => &$cp)
    {
      if($cp['cnt'] > 0)
      {
        $pnt = array();
        $pnt['cpm']      = $cp['sum']/$cp['cnt'];
 $pnt['long1']    = ($bounds[3] - $bounds[1])*$lng/$lngcnt + $bounds[1];
 $pnt['lat1']     = ($bounds[2] - $bounds[0])*$lat/$latcnt + $bounds[0];
 $pnt['long2']    = ($bounds[3] - $bounds[1])*($lng+1)/$lngcnt + $bounds[1];
 $pnt['lat2']     = ($bounds[2] - $bounds[0])*($lat+1)/$latcnt + $bounds[0];
        $pnt['max']      = $cp['max']     ;
        $pnt['max_long'] = $cp['max_long'];
        $pnt['max_lat']  = $cp['max_lat'] ; 
        # $pnt['min']      = $cp['min']     ;
        # $pnt['min_long'] = $cp['min_long'];
        # $pnt['min_lat']  = $cp['min_lat'] ;
 array_push($res, $pnt);
      }
    }
  }
  return $res;
}

No comments:

Post a Comment