Index: gcg/gcg_gmap_views.module
===================================================================
--- gcg/gcg_gmap_views.module	(revision 89)
+++ gcg/gcg_gmap_views.module	(working copy)
@@ -118,4 +118,97 @@
       return $output;
       break;
   }
-}
\ No newline at end of file
+}
+
+
+function gcg_gmap_views_views_arguments() {
+  $arguments = array(
+    'gcg_gmap_views_arg_proximity' => array(
+      'name' => t('GCG GMAP: Nodes within proximity'),
+      'handler' => 'gcg_gmap_views_arg_proximity',
+      'option' => 'string',
+      'help' => t('Within distance of defined lat and long, set <strong>Option</strong> to latitude,longitude,distance, ie: <i>-90.00,23.45,5km</i> '),
+    )
+  );
+   
+  return $arguments; 
+}
+
+
+/**
+ * Process the comma-seperate argument into an assoc array
+ *
+ * Note: You could use this to provide a whole markup system for doing clever things
+ *       - ie ",nid: 300" find nodes within distance from this
+ *            ",uid: 22" nodes close to this user
+ *           
+ * @param string $arg
+ */
+function _gcg_gmap_views_arg_process($arg) {
+
+  $tmp=explode(',',urldecode($arg));
+  if(!is_array($tmp) || sizeof($tmp)<2) {
+    return false;
+  }
+  
+  // basic sanity check, replace anything not a digit, a decimal or a - with ''
+  $proximity_info['lat']=preg_replace('/[^\d\.-]/i','',$tmp[0]);
+  $proximity_info['lon']=preg_replace('/[^\d\.-]/i','',$tmp[1]);
+  
+  if(sizeof($tmp)>2) {
+    $proximity_info['unit']=eregi('mi$',$tmp[2]) ? 'miles' : 'kilometers';
+    $proximity_info['distance']=preg_replace('/[^\d\.]/i','',$tmp[2]);
+  } else {
+    // default to something
+    $proximity_info['distance']=50;
+    $proximity_info['unit']='kilometers';
+  }
+  
+  return $proximity_info;
+}
+
+/**
+ * GCG GMAP Views argument handler
+ * 
+ * note: this uses earth.inc from location module, which is a really inefficient and mathematically 
+ *       expensive way todo things, BUT IT DOES WORK.
+ *
+ * @param unknown_type $op
+ * @param unknown_type $query
+ * @param unknown_type $argtype
+ * @param unknown_type $arg
+ * @param unknown_type $table
+ */
+function gcg_gmap_views_arg_proximity($op, &$query, $argtype, $arg = '', $table = 'gcg_views') {
+  
+  // ensure this doesnt collide with locations module's include of earth.inc
+  if(! function_exists('earth_latitude_range') ) {
+    $module_path = drupal_get_path('module', 'gcg_gmap_views');
+    include_once($module_path.'/earth.inc');
+  }
+  
+  switch($op) {
+    case 'filter':
+      $_info = _gcg_gmap_views_arg_process($arg);
+      if(!is_array($_info) || !strlen($_info['lat']) || !strlen($_info['lon']) || ! strlen($_info['distance'])) {
+        drupal_set_message('Invalid Longitude, Latitude or Distance defined.');
+        return;
+      }
+
+      $divisor = $_info['unit'] == 'kilometers' ? 1000 : 1609.347;
+      $latrange = earth_latitude_range($_info['lon'], $_info['lat'], ($_info['distance'] * $divisor));
+      $lonrange = earth_longitude_range($_info['lon'], $_info['lat'], ($_info['distance'] * $divisor));
+      
+      // a large enough distance will cause the earth function to pass something bad to asin()
+      if( is_nan($latrange[0])  || is_nan($lonrange[0])  ) {
+        drupal_set_message('Unable to calculate items within that distance, please specify a smaller radius to check within.');
+        return;
+      }
+      $query->ensure_table($table);
+      $query->add_orderby(NULL, "((". earth_distance_sql($_info['lon'], $_info['lat'],$table) .") / $divisor)", 'ASC', 'distance');
+      $query->add_where("$table.longitude IS NOT NULL");
+      $query->add_where("$table.latitude > %f AND $table.latitude < %f AND $table.longitude > %f AND $table.longitude < %f", $latrange[0], $latrange[1], $lonrange[0], $lonrange[1]);
+      break;
+  }
+  
+}
Index: gcg/earth.inc
===================================================================
--- gcg/earth.inc	(revision 0)
+++ gcg/earth.inc	(revision 103)
@@ -0,0 +1,155 @@
+<?php
+// $Id: earth.inc,v 1.4.4.1 2007/03/16 23:52:24 ankur Exp $
+
+// Trigonometry for calculating geographical distances.
+// All function arguments and return values measure distances in metres
+// and angles in degrees.  The ellipsoid model is from the WGS-84 datum.
+// Ka-Ping Yee, 2003-08-11
+
+//$earth_radius_semimajor = 6378137.0;
+//$earth_flattening = 1/298.257223563;
+//$earth_radius_semiminor = $earth_radius_semimajor * (1 - $earth_flattening);
+//$earth_eccentricity_sq = 2*$earth_flattening - pow($earth_flattening, 2);
+
+// I don't know what's up: PHP is hating on my global variables (commented out above), 
+// so I have to write functions that return them! (-Ankur)
+// Commenting out the global variables above and replacing them with functions that
+// return the same values is the only thing I changed since, for some reason, my
+// PHP wasn't acknowledging these global variables.
+// This library is an original implementation of UCB CS graduate student, Ka-Ping Yee (http://www.zesty.ca).
+
+function earth_radius_semimajor() {
+  return 6378137.0;
+}
+
+function earth_flattening() {
+  return (1/298.257223563);
+}
+
+function earth_radius_semiminor() {
+  return (earth_radius_semimajor() * (1 - earth_flattening()));
+}
+
+function earth_eccentricity_sq() {
+  return (2*earth_flattening() - pow(earth_flattening(), 2));
+}
+
+// Latitudes in all of U. S.: from -7.2 (American Samoa) to 70.5 (Alaska).
+// Latitudes in continental U. S.: from 24.6 (Florida) to 49.0 (Washington).
+// Average latitude of all U. S. zipcodes: 37.9.
+
+function earth_radius($latitude=37.9) {
+  //global $earth_radius_semimajor, $earth_radius_semiminor;
+  // Estimate the Earth's radius at a given latitude.
+  // Default to an approximate average radius for the United States.
+  
+  $lat = deg2rad($latitude);
+
+  $x = cos($lat)/earth_radius_semimajor();
+  $y = sin($lat)/earth_radius_semiminor();
+  return 1 / (sqrt($x*$x + $y*$y));
+}
+
+function earth_xyz($longitude, $latitude, $height = 0) {
+  // Convert longitude and latitude to earth-centered earth-fixed coordinates.
+  // X axis is 0 long, 0 lat; Y axis is 90 deg E; Z axis is north pole.
+  //global $earth_radius_semimajor, $earth_eccentricity_sq;
+  $long = deg2rad($longitude);
+  $lat = deg2rad($latitude);
+
+  $coslong = cos($long);
+  $coslat = cos($lat);
+  $sinlong = sin($long);
+  $sinlat = sin($lat);
+  $radius = earth_radius_semimajor() /
+    sqrt(1 - earth_eccentricity_sq() * $sinlat * $sinlat);
+  $x = ($radius + $height) * $coslat * $coslong;
+  $y = ($radius + $height) * $coslat * $sinlong;
+  $z = ($radius * (1 - earth_eccentricity_sq()) + $height) * $sinlat;
+  return array($x, $y, $z);
+}
+
+function earth_arclength($angle, $latitude=37.9) {
+  // Convert a given angle to earth-surface distance.
+  return deg2rad($angle) * earth_radius($latitude);
+}
+
+function earth_distance($longitude1, $latitude1, $longitude2, $latitude2) {
+  // Estimate the earth-surface distance between two locations.
+  $long1 = deg2rad($longitude1);
+  $lat1 = deg2rad($latitude1);
+  $long2 = deg2rad($longitude2);
+  $lat2 = deg2rad($latitude2);
+  $radius = earth_radius(($latitude1 + $latitude2) / 2);
+
+  $cosangle = cos($lat1)*cos($lat2) *
+    (cos($long1)*cos($long2) + sin($long1)*sin($long2)) +
+    sin($lat1)*sin($lat2);
+  return acos($cosangle) * $radius;
+}
+
+/*
+ * Returns the SQL fragment needed to add a column called 'distance'
+ * to a query that includes the location table
+ *
+ * @param $longitude   The measurement point
+ * @param $latibude    The measurement point
+ * @param $tbl_alias   If necessary, the alias name of the location table to work from.  Only required when working with named {location} tables
+ */
+function earth_distance_sql($longitude, $latitude, $tbl_alias = '') {
+  // Make a SQL expression that estimates the distance to the given location.
+  $long = deg2rad($longitude);
+  $lat = deg2rad($latitude);
+  $radius = earth_radius($latitude);
+
+  // If the table alias is specified, add on the separator.
+  $tbl_alias = empty($tbl_alias) ? $tbl_alias : ($tbl_alias . '.');
+
+  $coslong = cos($long);
+  $coslat = cos($lat);
+  $sinlong = sin($long);
+  $sinlat = sin($lat);
+  return "(IFNULL(ACOS($coslat*COS(RADIANS({$tbl_alias}latitude))*($coslong*COS(RADIANS({$tbl_alias}longitude)) + $sinlong*SIN(RADIANS({$tbl_alias}longitude))) + $sinlat*SIN(RADIANS({$tbl_alias}latitude))), 0.00000)*$radius)";
+}
+
+function earth_longitude_range($longitude, $latitude, $distance) {
+  // Estimate the min and max longitudes within $distance of a given location.
+  $long = deg2rad($longitude);
+  $lat = deg2rad($latitude);
+  $radius = earth_radius($latitude);
+
+  $angle = $distance / $radius;
+  $diff = asin(sin($angle)/cos($lat));
+  $minlong = $long - $diff;
+  $maxlong = $long + $diff;
+  if ($minlong < -pi()) { $minlong = $minlong + pi()*2; }
+  if ($maxlong > pi()) { $maxlong = $maxlong - pi()*2; }
+  return array(rad2deg($minlong), rad2deg($maxlong));
+}
+
+function earth_latitude_range($longitude, $latitude, $distance) {
+  // Estimate the min and max latitudes within $distance of a given location.
+  $long = deg2rad($longitude);
+  $lat = deg2rad($latitude);
+  $radius = earth_radius($latitude);
+
+  $angle = $distance / $radius;
+  $minlat = $lat - $angle;
+  $maxlat = $lat + $angle;
+  $rightangle = pi()/2;
+  if ($minlat < -$rightangle) { // wrapped around the south pole
+    $overshoot = -$minlat - $rightangle;
+    $minlat = -$rightangle + $overshoot;
+    if ($minlat > $maxlat) { $maxlat = $minlat; }
+    $minlat = -$rightangle;
+  }
+  if ($maxlat > $rightangle) { // wrapped around the north pole
+    $overshoot = $maxlat - $rightangle;
+    $maxlat = $rightangle - $overshoot;
+    if ($maxlat < $minlat) { $minlat = $maxlat; }
+    $maxlat = $rightangle;
+  }
+  return array(rad2deg($minlat), rad2deg($maxlat));
+}
+
+?>
