How do I obtain the longitude and latitude of the current location using the Mappoint 2010 Map Control

I have been asked to complete an application on behalf of a programmer who has left the Company.  The application is a fleet management system and ises Mappoint 2010 ( Europe ) for location and mapping.

I can find a location using the mappoint [FindPlaceResults] procedure but inorder to identify the nearest current ehicle I need to query the sql table which uses lat/longs to keep track of vehicle location.

Idealliy I would like to be able to find the Lat/Long of the current location returned by using the [FindPlaceResults] procedure.  I am only taking the top entry from the procedure so there will only be ever one location returned.  As the map centres on the location found I had hoped the the lat/long could be obatined.
GaryHoatherAsked:
Who is Participating?
 
Ray PaseurCommented:
Sorry I cannot help much with Mappoint, but I know a bit about Google Maps and its API.  I have an article here at EE that may be helpful.
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_3350-Using-the-Google-Maps-API-in-PHP.html

Proximity information can be calculated with reasonable accuracy using either plane geometry or the Haversine formula.
http://en.wikipedia.org/wiki/Haversine_formula

Haversine is more accurate over longer distances.  Neither geometry takes into account physical limitations -- if you want to go from point A to point B and there is a river in between, your closest result may take you across the river whether there is a bridge there or not!  You can probably use Google Maps and Waypoints to get a more accurate travel distance.

When I've done proximity matching for large numbers of clients, I have used a "down-select" from the tables to capture only a small number of locations.  I create a temporary table (engine = memory) with the closest locations based on a plus-or-minus difference in latitude and longitude, then compute the distances for only those closest points.  After that, I can select from the temporary table and ORDER BY distance to find the nearest locations.

Here is a function that computes distance.
<?php // RAY_compute_distance.php
error_reporting(E_ALL);
echo "<pre>\n";

// COMPUTE THE DISTANCE BETWEEN TWO LAT/LON PAIRS

// MAN PAGE: http://en.wikipedia.org/wiki/Haversine_formula
function compute_distance($from_lat, $from_lon, $to_lat, $to_lon, $units='KM')
{
    // CHOOSE A UNIT OF MEASURE BY THE FIRST CHARACTER
    $units = strtoupper(substr(trim($units),0,1));

    // ENSURE THAT ALL COORDINATES ARE FLOATING POINT VALUES
    $from_lat = floatval($from_lat);
    $from_lon = floatval($from_lon);
    $to_lat   = floatval($to_lat);
    $to_lon   = floatval($to_lon);

    // IF THE SAME POINT THE DISTANCE IS ZERO.  HAVERSINE FAILS ON THIS INSTANCES
    if ( ($from_lat == $to_lat) && ($from_lon == $to_lon) )
    {
        return 0.0;
    }

    // COMPUTE THE DISTANCE WITH THE HAVERSINE FORMULA
    $distance
    = acos
    ( sin(deg2rad($from_lat))
    * sin(deg2rad($to_lat))
    + cos(deg2rad($from_lat))
    * cos(deg2rad($to_lat))
    * cos(deg2rad($from_lon - $to_lon))
    )
    ;
    $distance = rad2deg($distance);

    // DISTANCE IN MILES AND KM - ADD OTHERS IF NEEDED
    $miles = (float) $distance * 69.0;
    $km    = (float) $miles * 1.61;

    // RETURN MILES
    if ($units == 'M') return round($miles,1);

    // RETURN KILOMETERS = MILES * 1.61
    if ($units == 'K') return round($km,2);

    // UNITS NOT UNDERSTOOD
    return('INVALID FIFTH ARGUMENT - USE MILES OR KM');
}


// SHOW THE FUNCTION IN ACTION
if (!empty($_GET))
{
    $distance = compute_distance($_GET["a_lat"], $_GET["a_lon"], $_GET["b_lat"], $_GET["b_lon"], $_GET["units"]);
    echo $distance . ' ' . $_GET["units"] . '<br/>' . PHP_EOL;
}


// END OF PHP - PUT UP THE FORM TO RECEIVE INPUT
?>
<a target="_blank" href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=camp+david+geolocation&sll=39.648333,-77.465&sspn=0.025972,0.057807&ie=UTF8&z=15&iwloc=lyrftr:m,10141899780758213082,39.648361,-77.465029">Camp David</a>
<a target="_blanl" href="http://maps.google.com/maps?f=q&source=s_q&hl=en&geocode=&q=White+House+Washington,+DC&sll=39.806296,-77.097044&sspn=0.414606,0.924911&ie=UTF8&hq=White+House&hnear=White+House,+Washington,+DC&ll=38.898047,-77.036562&spn=0.025417,0.057807&z=15&iwloc=A">White House</a>
TEST IT HERE:
<form>
POINT A LAT <input name="a_lat" value="38.898047"> LON <input name="a_lon" value="-77.036562" />
POINT B LAT <input name="b_lat" value="39.737554"> LON <input name="b_lon" value="-77.464943" />
<input type="radio" name="units" value="miles" checked="checked" />Miles
<input type="radio" name="units" value="km" />Kilometers
<input type="submit" />
</form>

Open in new window

0
 
Ray PaseurCommented:
In semi-related news, here is my teaching example of how to call the major geocoder APIs.  Give them an address and they can give you back the Lat/Lon pair in a decimal number, suitable for use in the Haversine formula.  Google has recently revised and extended its geocoder to make it perform reverse geo-coding.  You can give it a Lat/Lon pair and it will give you the nearest address.  How cool is that!

Please let me know if you have further questions or if I can help with anything else about the theory and practice of proximity calculation.  As I said, I do not know Mappoint, but the principles and geometry are going to be the same no matter what software you choose.  Best, ~Ray
<?php // RAY_class_SimpleGeoCoder.php
error_reporting(E_ALL);
echo "<pre>" . PHP_EOL;


// API KEYS, ETC., IF REQUIRED
// require_once('local_data.php');


// A FREEFORM NAMED LOCATION STATEMENT IS OPTIONAL - PROCESSED FIRST
if (!empty($_GET["n"]))
{
    $location = trim($_GET["n"]);
}
// ADDRESS, CITY, STATE, ZIP ARE OPTIONAL - PROCESSED IF FREEFORM LOCATION IS NOT PRESENT
else
{
    $location = '';
    if (!empty($_GET["a"])) { $location .= $_GET["a"] . ' '; }
    if (!empty($_GET["c"])) { $location .= $_GET["c"] . ' '; }
    if (!empty($_GET["s"])) { $location .= $_GET["s"] . ' '; }
    if (!empty($_GET["z"])) { $location .= $_GET["z"] . ' '; }
    $location = trim($location);
}

// IF WE HAVE A LOCATION STRING, RUN THE GEOCODERS
if ($location)
{
    // PREPARE THE SIMPLE GEO-CODER
    $demo = new SGC;

    // TEST THE YAHOO! GEOCODER
    $demo->YGC($location);
    echo PHP_EOL . "YAHOO! ";
    print_rr($demo);

    // TEST THE GOOGLE GEOCODER
    $demo->GGC($location);
    echo PHP_EOL . "GOOGLE ";
    print_rr($demo);
}
// ALL DONE PROCESSING THE INPUT, PUT UP THE FORM
?>
<html>
<head>
<title>Yahoo/Google SimpleGeoCoder Demo</title>
</head>
<body>
<form method="get">
Try using a full or partial address.
Addr: <input type="text" name="a" autocomplete="off" />
City: <input type="text" name="c" autocomplete="off" />
ST:   <input type="text" name="s" autocomplete="off" size="2" />
Zip:  <input type="text" name="z" autocomplete="off" size="8" />
<input type="submit" value="GeoCode This Address" />

Or use the name of a location.
Name: <input type="text" name="n" autocomplete="off" />
<input type="submit" value="GeoCode This Location Name" />
</form>
</body>
</html>

<?php
// SIMPLE GEOCODER CLASS
class SGC
{
    // DECLARE THE WORKING DATA
    private $precis;

    // DECLARE THE OUTPUT DATA
    public $latitude;
    public $longitude;
    public $precision;
    public $warning;
    public $error;
    public $geocoder;

    // DECLARE THE CONSTRUCTOR
    public function __construct()
    {
        $this->latitude  = 0.0;
        $this->longitude = 0.0;
        $this->precision = FALSE;  // WANT A VALUE OF 5 OR HIGHER, HIGHER IS BETTER, 8 IS ON THE ROOFTOP
        $this->warning   = '';
        $this->geocoder  = '';
        $this->error     = '';
        unset($this->precis);
    }

    // DECLARE THE DATA-CLEANUP
    private function _cleanup($str)
    {
        $str = preg_replace('/[^\' a-zA-Z0-9&!#$%()"+:?\/@,_\.\-]/', '', $str);
        return trim(preg_replace('/\s\s+/', ' ', $str));
    }

    // DECLARE THE YAHOO! VERSION OF THE WORKHORSE
    public function YGC($location)
    {
        $loc = $this->_cleanup($location);
        if (empty($loc))
        {
            $this->error = "LOCATION DATA IS EMPTY";
            return FALSE;
        }
        if (!defined('YAHOO_API')) define('YAHOO_API', 'YAHOO_API');
        $this->geocoder = 'Yahoo!';
        $yahooUrl = "http://local.yahooapis.com/MapsService/V1/geocode?&appid=" . YAHOO_API;
        $yahooUrl .= "&location=" . urlencode($loc);

        // EXECUTE YAHOO GEOCODER QUERY
        // NOTE - USE ERROR SUPPRESSION OR IT WILL BARK OUT THE YAHOO API KEY - ON FAILURE RETURNS HTTP 400 BAD REQUEST
        if ($yfp = @fopen($yahooUrl, 'r'))
        {
            $yahooResponse = '';
            while (!feof($yfp))
            {
                $yahooResponse .= fgets($yfp);
            }
            fclose($yfp);
        }
        // IF SOMETHING IS SICK AT YAHOO
        else
        {
            $this->error = "UNABLE TO OPEN $yahooUrl";
            return FALSE;
        }

        // EXAMINE THE RESULT
        if ($yahooResponse != '') // NOT EMPTY, WE GOT DATA
        {
            $ydata = new SimpleXMLElement($yahooResponse);

            // CHECK FOR ANY ERROR MESSAGE, IF NONE, EXTRACT THE DATA POINTS
            $yerror = $ydata->Message;
            if ($yerror == '')
            {
                $this->precis    = (string)$ydata->Result["precision"];
                $this->warning   = (string)$ydata->Result["warning"];
                $this->latitude  = (string)$ydata->Result->Latitude;
                $this->longitude = (string)$ydata->Result->Longitude;

                // THESE STATEMENTS CAN BE USED TO RETURN NORMALIZED ADDRESS
                $this->address   = (string)$ydata->Result->Address;
                $this->city      = (string)$ydata->Result->City;
                $this->state     = (string)$ydata->Result->State;
                $this->zip       = (string)$ydata->Result->Zip;

                // SET PRECISION TO A NUMBER VALUE
                if ($this->precis == 'zip')     { $this->precision = "5"; }
                if ($this->precis == 'street')  { $this->precision = "6"; }
                if ($this->precis == 'address') { $this->precision = "8"; }
            }
            else
            {
                $this->error = "ERROR: $yahooUrl SAYS $yerror";
                return FALSE;
            }
        }

        // NO RESULT - SOMETHING IS SICK AT YAHOO
        else
        {
            $this->error = "NO DATA RETURNED FROM $yahooUrl";
            return FALSE;
        }
        return TRUE;
    } // END function geocodeYahoo


    // DECLARE THE GOOGLE VERSION OF THE WORKHORSE
    public function GGC($location)
    {
        $loc = $this->_cleanup($location);
        if (empty($loc))
        {
            $this->error = "LOCATION DATA IS EMPTY";
            return FALSE;
        }

        if (!defined('GOOGLE_API')) define('GOOGLE_API', 'GOOGLE_API');
        $this->geocoder = 'Google';
        $googleUrl = "http://maps.google.com/maps/geo?key=" . GOOGLE_API . "&output=csv";
        $googleUrl .= "&q=" . urlencode($loc);

        // EXECUTE GOOGLE GEOCODER QUERY
        if ($gfp = @fopen($googleUrl, 'r'))
        {
            $googleResponse = '';
            while (!feof($gfp))
            {
                $googleResponse .= fgets($gfp);
            }
            fclose($gfp);
        }
        else
        {
            $this->error = "UNABLE TO OPEN $googleUrl";
            return FALSE;
        }

        // EXTRACT THE DATA FROM THE CSV STRING
        $gdata = explode(',',$googleResponse);
        if ($gdata[0] != '200') // RESPONSE CODE SHOULD BE '200' -- IF 602 - BAD ZIP CODE OR UNUSABLE ADDRESS
        {
            $this->error = "ERROR CODE {$gdata[0]} FROM $googleUrl";
            return FALSE;
        }
        $this->precision = $gdata[1]; // GEOCODE ACCURACY - ZIP CODE = 5, HIGHER NUMBERS ARE BETTER
        $this->latitude  = $gdata[2];
        $this->longitude = $gdata[3];
        return TRUE;
    } // END function geocodeGoogle

} // END class SimpleGeocoder




// UNRELATED FUNCTION TO MAKE THE OUTPUT SHOW THE PUBLIC INFORMATION ONLY
function print_rr($thing)
{
    $str = print_r($thing, TRUE);
    $arr = explode(PHP_EOL, $str);
    foreach ($arr as $ptr => $txt)
    {
        if (preg_match('/:private]/', $txt))
        {
            unset($arr[$ptr]);
        }
    }
    echo implode(PHP_EOL, $arr);
}

Open in new window

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.