Creating Fuzzy Latitude And Longitude Values With A Given Amount Of Freedom

Posted February 7, 2011 at 10:01 AM by Ben Nadel

Tags: ColdFusion, Javascript / DHTML

Recently, I added location tracking to the Things-I-Give web application. As I talked about before, ThingsIGive.com allows users to track their own good deeds in an effort to "gamify" the act of giving; the hope, of course, being that users will become greedy for giving (built in an effort to combat my own anxiety about giving). Although the web application is completely anonymous, I know that people are still a bit weary of giving out location information. As such, I wanted to take the global position reported by the web application and make it a bit "fuzzy."

 
 
 
 
 
 
Things I Give (ThingsIGive.com) - A Digital Journal Of Your Awesome Self. 
 
 
 

When the browser reports its location, either through the Javascript Geolocation API or its remote IP address, the location is defined as latitude and longitude coordinates. These are given in degrees. I wanted to create a function that would take a latitude-longitude point and a given "miles of freedom" and then return a random position based on the miles of freedom.

Doing this simply required a little math to figure out how many miles-per-degree were available at the given latitude and longitude. Here's what I came up with:

  • <cffunction
  • name="fuzzyLatLong"
  • access="public"
  • returntype="struct"
  • output="false"
  • hint="I make the given latitude and longitude values a tiny bit fuzzy depending on the given miles of freedom.">
  •  
  • <!--- Define arguments. --->
  • <cfargument
  • name="latitude"
  • type="numeric"
  • required="true"
  • hint="I am the Float value indicating one of the latitdue degree value."
  • />
  •  
  • <cfargument
  • name="longitude"
  • type="numeric"
  • required="true"
  • hint="I am the Float value indicating one of the longitude degree value."
  • />
  •  
  • <cfargument
  • name="miles"
  • type="numeric"
  • required="false"
  • default="5"
  • hint="I am the number of miles of 'fuzziness' that we we'll use in our latitude / longitude randomization."
  • />
  •  
  • <!--- Define the local scope. --->
  • <cfset var local = {} />
  •  
  • <!---
  • Get the number of miles per degree. This is only an estimate
  • based on latitude. The longitude will have to be determined
  • based on teh latitude.
  • --->
  • <cfset local.milesPerDegreeLatitude = 69.09 />
  •  
  • <!---
  • Now that we have the miles per degree of latitude, we need to
  • figure out what the same distance is for the longitude at the
  • given latitude.
  •  
  • NOTE: This forumla was taken from the following Google
  • answers page:
  • http://answers.google.com/answers/threadview?id=577262
  • --->
  • <cfset local.milesPerDegreeLongitude = (local.milesPerDegreeLatitude * cos( arguments.latitude * pi() / 180 )) />
  •  
  • <!---
  • Determine the number of degrees that we will need to
  • randomize the latidude based on the miles of freedom.
  • --->
  • <cfset local.degreesOfLatitudeRandomness = (arguments.miles / local.milesPerDegreeLatitude) />
  •  
  • <!---
  • Determine the number of degrees that we will need to
  • randomize the longitude based on the miles of freedom.
  • --->
  • <cfset local.degreesOfLongitudeRandomness = (arguments.miles / local.milesPerDegreeLongitude) />
  •  
  • <!---
  • Create a struct to hold the fuzzy version of the
  • latitude and longitude values. For each of these values,
  • we'll subtract the maximum randominess then add a fraction
  • of 2x the randomness. This will give us a random value
  • between our negative random max and our positive random max.
  • --->
  • <cfset local.coordinates = {
  • latitude = (
  • (arguments.latitude - local.degreesOfLatitudeRandomness) +
  • (
  • local.degreesOfLatitudeRandomness *
  • (2 * rand( "sha1prng" ))
  • )
  • ),
  • longitude = (
  • (arguments.longitude - local.degreesOfLongitudeRandomness) +
  • (
  • local.degreesOfLongitudeRandomness *
  • (2 * rand( "sha1prng" ))
  • )
  • )
  • } />
  •  
  • <!--- Return the resultant coordinate value. --->
  • <cfreturn local.coordinates />
  • </cffunction>
  •  
  •  
  • <!--- ----------------------------------------------------- --->
  • <!--- ----------------------------------------------------- --->
  •  
  •  
  • <cfoutput>
  •  
  • <!DOCTYPE html>
  • <html>
  • <head>
  • <title>Creating Fuzzy Latitude And Longitude Values</title>
  • </head>
  • <body>
  •  
  • <!--- Our map container. --->
  • <div id="map" style="height: 950px ;"></div>
  •  
  • <!--- Link the Google maps API. --->
  • <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
  • <script type="text/javascript">
  •  
  • // Set up the Google map stuff.
  • var mapContainer = document.getElementById( "map" );
  •  
  • // The google map.
  • var map = new google.maps.Map(
  • mapContainer,
  • {
  • zoom: 13,
  • center: new google.maps.LatLng(
  • 40.725665,
  • -73.996353
  • ),
  • mapTypeId: google.maps.MapTypeId.ROADMAP
  • }
  • );
  •  
  •  
  • // I add maker to the map and initialize it such that it
  • // will respond to click events.
  • var addMarkerToMap = function( latLong ){
  • // Create new marker from the location.
  • var marker = new google.maps.Marker({
  • map: map,
  • position: latLong
  • });
  •  
  • // Return the newly created marker.
  • return( marker );
  • };
  •  
  •  
  • // ---------------------------------------------- //
  • // ---------------------------------------------- //
  •  
  •  
  • <!--- Add vertical markers. --->
  • <cfloop index="i" from="1" to="10">
  •  
  • <!---
  • Get our fuzzy position with a fuzzy freedomness
  • of one mile.
  • --->
  • <cfset position = fuzzyLatLong(
  • 40.725665,
  • -73.996353,
  • 1
  • ) />
  •  
  • <!--- Keep the longitude constant. --->
  • addMarkerToMap(
  • new google.maps.LatLng(
  • #position.latitude#,
  • -73.996353
  • )
  • );
  •  
  • </cfloop>
  •  
  •  
  • <!--- Add horizontal markers. --->
  • <cfloop index="i" from="1" to="10">
  •  
  • <!---
  • Get our fuzzy position with a fuzzy freedomness
  • of one mile.
  • --->
  • <cfset position = fuzzyLatLong(
  • 40.725665,
  • -73.996353,
  • 1
  • ) />
  •  
  • <!--- Keep the latitude constant. --->
  • addMarkerToMap(
  • new google.maps.LatLng(
  • 40.725665,
  • #position.longitude#
  • )
  • );
  •  
  • </cfloop>
  •  
  • </script>
  • </body>
  • </html>
  •  
  • </cfoutput>

As you can see, this function, fuzzyLatLong(), essentially determines how many degrees of freedom there are at the given location based on the given number of "fuzzy" miles. Once the degrees of freedom have been found, it then becomes a matter of randomly selecting a point between the -MAX and MAX degree values.

When we run the above page, we get the following Google Maps output:

 
 
 
 
 
 
A Random Distribution Of Latitude And Longitude Values Based On A Given Number Of Miles. 
 
 
 

As you can see, these points have been randomly distributed within a mile of the original position (where the two lines intersect). In this case, I have only randomized one of the coordinates in order to illustrate the distribution. However, when put into practice, both the latitude and longitude would be randomized.




Reader Comments

Feb 7, 2011 at 6:09 PM // reply »
18 Comments

We do something similar to mask real estate values for agents who wish to not display the exact address... Our geocodes would ruin that, so we randomize it within .05 miles, which ends up being 1-2 blocks.

We also make it a polygon circle to encompass that address. Pff. Real Estate :P


Feb 7, 2011 at 6:13 PM // reply »
10,743 Comments

@Brad,

Makes sense - you don't want to make it too easy for people to circumvent the agent. Doing a circle would probably be better; I assume the math gets a bit more complicated for that :)


Feb 7, 2011 at 6:21 PM // reply »
18 Comments

Well, we did it super simple. We offset the center much like you did, then drew a .075-.1 size circle with the center based on that point.

Because, even a circle alone you'd be able to find the center and circumvent the agent so the offset really helps.

It might be more paranoia then necessity, but that was the build request. REBNY (real estate board) actually requires that you limit returned search results and stuff... RE projects are the hardest.


Post A Comment

Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.

Please review the following issues:

Author Name:


Author Email:

Author Website:

Comment:

Supported HTML tags for formatting: <strong>bold</strong>   <em>italic</em>   <code>code</code>







  • Help Wanted - Find Your Next ColdFusion Job
InVision App - Prototyping Made Beautiful With Prototyping Tools Ben Nadel's Company - Epicenter Consulting Recent Blog Comments
May 16, 2012 at 8:18 PM
Best Of ColdFusion 10 Contest Entry - HTML Email Utility
Just found this, looks good! I'm trying to run it on local, it's the 64bit version and I'm experiencing horrible lag. On average the generate.cfm processes the content change in 60-90 seconds. I've ... read »
May 16, 2012 at 6:40 PM
Maintaining Sessions Across Multiple ColdFusion CFHttp Requests
I am trying to integrate this CFHTTPsession into an application that will log into zeekrewards.com to post ads and I am not having any luck. The code works perfectly for logging into other websites, ... read »
May 16, 2012 at 2:44 PM
Creating A Sometimes-Fixed-Position Element With jQuery
Thank you, very useful technique! Worked like a charm. ... read »
May 16, 2012 at 1:58 PM
Movies As A Religious Experience
Acting can, in a way, ruin the movie-goer's experience. I used to be able to get so caught up in movies and their plots, and totally engaged. But lately, I haven't been able to as much with a lot o ... read »
May 16, 2012 at 1:52 PM
The Science Of Optimal Post-Exercise Nutrition
children of this age eat very less vegetables so u can opt for salads they will like it also carrot ,cucumber,onion and as far as pulses are concerned u can boil them ,give him along with mashed rice ... read »
May 16, 2012 at 1:34 PM
Strange ColdFusion JRUN Stack Overflow Error
Hey, Recently I updated my jrun4 using the latest updater 7 and now i am having memory issues :(:(:( any help is appreciated ... read »
May 16, 2012 at 9:56 AM
ColdFusion 10 Beta, Apache Tomcat, And Symbolic Links On Mac OSX
Hi, Now that ColdFusion 10 is out I have stumbled over this as well and I cannot figure out the proper solution. We're running virtual hosts via Apache2; the ColdFusion-applications store their fil ... read »
May 15, 2012 at 6:03 PM
Movies As A Religious Experience
@Ben, I don't know whether you'd consider this a religious observation, but it seems to me, in a sense, movies multiply how many lives we get to have. Each movie is like a little extra life we get ... read »