Solved

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

Posted on 2010-09-20
2
1,115 Views
Last Modified: 2013-11-26
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.
0
Comment
Question by:GaryHoather
  • 2
2 Comments
 
LVL 108

Accepted Solution

by:
Ray Paseur earned 500 total points
ID: 33723945
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
 
LVL 108

Expert Comment

by:Ray Paseur
ID: 33723979
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Problem to Popup 2 52
Setting location of a form 4 22
Windows Service to Receive TCP Packets 4 45
XML & .net 5 21
Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
Welcome my friends to the second instalment and follow-up to our Minify and Concatenate Your Scripts and Stylesheets (http://www.experts-exchange.com/Programming/Languages/.NET/ASP.NET/A_4334-Minify-and-Concatenate-Your-Scripts-and-Stylesheets.html)…
This tutorial demonstrates how to identify and create boundary or building outlines in Google Maps. In this example, I outline the boundaries of an enclosed skatepark within a community park.  Login to your Google Account, then  Google for "Google M…
This tutorial walks through the best practices in adding a local business to Google Maps including how to properly search for duplicates, marker placement, and inputing business details. Login to your Google Account, then search for "Google Mapmaker…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now