[ka-Map-users] Scalebar and javascript distance calculation errors

Stephen Woodbridge woodbri at swoodbridge.com
Mon Feb 6 09:02:49 EST 2006


Hi Daniel,

I think the difference you are seeing in these two case below is due to 
the fact the you are operating under the misinformed concept that 
cellsize is rectangular when it is not, despite that fact that it is 
being displayed as rectangular on the image.

One degree of longitude is approximately 69+ miles at the equator. You 
can do the math to verify this. How many miles are in one degree of 
longitude at the poles? But one degree of latitude is always approx. 69+ 
miles regardless where you are on the sphere.

Ka-map assumes all calculation are done in the x-y plane using 
cartessian coordinate math, hence cellsize represents an approximation 
based on the value at the equator. As you move off the equator you get 
more and more error.

I am not familiar with pg_sphere, but I assume (maybe wrongly) that it 
is doing spherical math calculation which take into account the issues 
above and hence you mismatch in expectations.

-Steve W.

Daniel Ceregatti wrote:
> Hi,
> 
> I'm using pg_sphere and some of my own javascript code in an application
> I'm building which uses the ka-map "API". I keep the "API" files synced
> with ka-map CVS, then I use my own startup.js and index.php to produce
> my app, a stable version of which can be seen here:
> 
> http://map.sh.nu/release
> 
> My work-in-progress can be seen here:
> 
> http://map.sh.nu/prototype6
> 
> (Both developed in Firefox 1.5, not guaranteed to work in IE, or
> safari...yet)
> 
> I've implemented it with the relatively new 100% javascript scalebar in
> ka-map's scalebar subdirectory.
> 
> Anyhow, everything looked fine until I started adding points and radii
> to the map. I'm using pg_sphere for radius searches, as it's easier to
> use than postgis for the purposes of searching within a circle on a
> spheroid (IMHO). The problem is that the scalebar and pg_sphere don't
> agree in terms of distances.
> 
> Recently, while discussing my app with Paul Spencer on IRC, he was kind
> enough to supply me with a javascript function to determine pixels per
> mile from the myKaMap object's cellsize property:
> 
> function milesToPixels (miles) {
>     var ddPerPixel = myKaMap.cellSize;
>     var metersPerDD = 110570;
>     //adjust for latitude
>     kmPerDD = 110.570 * Math.cos (ddPerPixel * Math.PI / 180);
>     var kmPerPixel = kmPerDD * ddPerPixel;
>     var miPerPixel = kmPerPixel * 0.621371192;
>     var pixelPerMi = 1 / miPerPixel;
>     var pixels = Math.round (miles * pixelPerMi);
>     debugLog ('Calculated pixels for ' + miles + ' mile(s): ' + pixels);
>     return pixels;
> }
> 
> I use this function to tell me the number of pixels per mile for the
> current zoom level. I use its return value to overlay a pre-rendered
> image of a circle whose radius in pixels matches the return value to
> graphically illustrate the radius of a search. I found that the circles
> I'm adding to my map match very closely with the scalebar by dragging
> the circle, which is currently bisected horizontally and vertically for
> the purposes of debugging, to the scalebar and eye-balling the radius
> against the scalebar. They seem to match quite well.
> 
> The problem is, pg_sphere doesn't agree. I supply a query to pg_sphere
> telling it to "get me all points for a particular crime code within an X
> mile radius, within a specific time interval". This query returns not
> only the points, but the distance from the center as well. Since
> pg_sphere expects latitude, longitude, and radius in radians, I must
> convert these before supplying them to the query:
> 
> $radians_per_mile = 0.00025; // Found on google.
> $lon = $_GET["lon"] * pi () / 180.0; // Convert to radians
> $lat = $_GET["lat"] * pi () / 180.0; // Convert to radians
> $radius = (($_GET["radius"] + .05) * $radians_per_mile); // Add a little
> padding so all my points are not less than the radius
> 
> A sample query:
> 
> select
>     cd.dr as id,
>     cd.lon,
>     cd.lat,
>     cd.crimeclass,
>     cd.crimeloc as description,
>     cc.description as desc,
>     to_char (cd.begdate, 'DD/MM/YYYY') as thedate,
>     cd.begtime as thetime,
>     round ((cd.location <-> @@ scircle '<(-2.06427127801,
> 0.59322154771), 0.0002625>')::numeric / 0.00025, 2) as distance
> from
>     crimedata cd,
>     crimecodes cc
> where
>     cd.crimeclass = cc.id
>     and cd.location @ scircle '<(-2.06427127801, 0.59322154771), 0.0002625>'
>     and cd.enddate >= to_timestamp ('11/09/2005', 'DD/MM/YYYY')
>     and cd.enddate <= to_timestamp ('11/09/2005', 'DD/MM/YYYY') + '7
> days'::interval
>     and cd.crimeclass in (110, 113, 121, 122, 210, 220, 230, 231, 235,
> 236, 250, 251, 310, 320, 330, 331, 341, 343, 345, 350, 351, 352, 353,
> 410, 420, 421, 440, 441, 442, 443, 444, 445, 450, 451, 452, 453, 470,
> 471, 472, 473, 474, 475, 480, 485, 487, 491, 510, 520)
> limit 100
> 
> This query is the one that's performed by default when the "search"
> button is pressed with the pre-popullated form on
> http://map.sh.nu/release. The request first perfoms a geocode search
> using Geo::Coder::US (http://geocoder.us). This first search returns the
> latitude and longitude (and more) of the search query, in this case the
> corner of Main St. and Slauson Ave. in Los Angeles, California, USA. The
> next part of the search is the pg_sphere query which uses the lat/lon
> returned from the geocode search and adds the radius. I then use
> ka-map's addObjectGeo function to add the search point, the circle, and
> all queried crime points to my map.
> 
> As you can see, the search point as well as the circle center seem to be
> placed perfectly. My crime data isn't actually very accurate, as some
> precision was lost when the LAPD provided me a sample of their data, so
> the points can be off by as much as 400 feet in some cases, but again,
> that's attributable to the loss in precision. Anyhow, if you mouse over
> the points, their metadata is shown in a popup, and one such datum is
> the distance, which comes from the sql query. If you drag the map to the
> left, you will expose a blue dot that's parallel to the circle's
> horizontal bisector, on the corner of Central Ave. and Slauson Ave. I've
> manually placed this point there, as denoted by the metadata. Using
> google maps, I tried to find two points that seemed to be very close to
> being 1 mile apart. I found that the corner of Main and Slauson seems to
> be very close to 1 mile from the corner of Central and Slauson, and
> Slauson runs East/West, parallel to lines on latitude. As you can see,
> the circle doesn't encompass that point. If you zoom out twice, to the
> point where 1 mile can be seen on the scalebar, you can also see that
> the scalebar falls short of 1 mile, when comparing the distance between
> the search point (the center of the circle) and this manually placed
> point. But pg_sphere reports that these points are exactly 1 mile apart.
> 
> I must confess that I'm not a "cartographer" by trade. I'm a programmer,
> and thus I do not understand what I'm doing some times with regards to
> mapping applications. Terms like "re-projection" make my eyes glaze
> over. All I can go with is what I know: All geocode searches which yield
> a lat/lon fall on my map with a very high degree of accuracy, so it
> seems that at least that part works properly. I also trust that
> pg_sphere is not at fault here, as I've done some math on my points, and
> they agree with the results provided by pg_sphere. My assumption is that
> somehow the math in ka-map's new scalebar, as well as my milesToPixels
> function, is faulty.
> 
> Thoughts?
> 
> Daniel Ceregatti (Primer in #mapserver on irc.freenode.net)
> _______________________________________________
> ka-Map-users mailing list
> ka-Map-users at lists.maptools.org
> http://lists.maptools.org/mailman/listinfo/ka-map-users
> 



More information about the ka-Map-users mailing list