Why does Google +1 record my mouse movements? [closed] - javascript

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
This is only on pages with a Google +1 box on my website:
It seems to be firing off an event on every mouse move. Anyone know what it is doing? I searched on Google (perhaps I should try Bing for once on this one!) but no one seems to have written about it. Is it recording information about my visitors browsing habits? Is it some sort of CAPTCHA to detect human like behviour?
Example URL, press F12 in chrome, go to timeline and press record, then move your mouse around this page (it plus ones this question, don't worry):
https://plusone.google.com/u/0/_/+1/button?hl=en-US&jsh=r%3Bgc%2F22224365-adc8a19e#url=https://stackoverflow.com/questions/6667544/google-1-recording-mouse-move&size=tall&count=true&id=I1_1310488711647&parent=https://plusone.google.com/u/0/_/+1/button?hl=en-US&jsh=r%3Bgc%2F22224365-adc8a19e#url=https://stackoverflow.com/questions/6667544/google-1-recording-mouse-move&size=tall&count=true&id=I1_1310488711647
For what it's worth (I can see this is going to be a popular question), I don't think there is anything sinister behind it, it might even be a useless artifact/bug, but if it is doing some sort of tracking, well, it seems a little deceptive to me.
Google +1 privacy policy
http://www.google.com/intl/en/privacy/plusone/
Google +1 Button Privacy Policy
June 28, 2011
The Google Privacy Policy describes how we treat personal information
when you use Google’s products and services, including information
provided when you use the Google +1 button. In addition, the following
describes our additional privacy practices specific to your use of the
+1 button.
Information we collect and how it is shared
The Google +1 button is a way for you to share information publicly
with the world. The Google +1 button helps you and others receive
personalized content from Google and our partners. The fact that you
+1’d something will be recorded by Google, along with information about the page you were viewing when you clicked on the +1 button.
Your +1’s may appear to others as an annotation with your profile name
and photo in Google services (such as in search results or on your
Google Profile) or elsewhere on websites and ads on the Internet.
We will record information about your +1 activity in order to provide
you and other users with a better experience on Google services.
In order to use the Google +1 button, you need to have a public Google
Profile visible to the world, which at a minimum includes the name you
chose for the profile. That name will be used across Google services
and in some cases it may replace another name you’ve used when sharing
content under your Google Account. We may display your Google Profile
identity to people who have your email address or other identifying
information.
Use of the collected information
In addition to the above-described uses, the information you provide
to us is used subject to our main Google Privacy Policy.
We may share aggregate statistics related to users’ +1 activity with
the public, our users, and partners, such as publishers, advertisers,
or connected sites. For example, we may tell a publisher that “10% of
the people who +1’d this page are in Tacoma, Washington.”
Your choices
You may view the list of items you have +1’d on the +1 tab on your
Profile. You can remove individual items from that list.
You may opt out of seeing +1 recommendations on third-party websites
(including on ads on third-party sites) from people you know.
We will store data (such as your recent +1’s) locally in your browser.
You may be able to access and clear this information in your browser
settings.
More information
Google adheres to the U.S. Safe Harbor privacy principles. For more
information about the Safe Harbor framework or our registration, see
the Department of Commerce’s website.

It appears to be seeding a random number generator with your mouse movements.
The mouse move handler itself does something along the lines of the following:
var b = ((event.X << 16) + event.Y) * (new Date().getTime() % 1000000);
c = c * b % d;
if (previousMouseMoveHandler) previousMouseMoveHandler.call(arguments);
d is (screen.width * screen.width + screen.height) * 1000000, and c is a variable that starts out as 1.
All of this is wrapped in the scope of an anonymous function, which itself is immediately evaluated to return a function that is assigned to a property named "random". That returned function looks something like this:
var b = c;
b += parseInt(hash.substr(0,20), 16);
hash = MD5(hash);
return b / (d + Math.pow(16, 20));
hash, BTW, is a variable that starts out as the MD5 hash of the page's cookies, location, the new Date().getTime(), and Math.random().
(Note, of course, that Google may change the script returned at any time and hence invalidate this analysis)

The actual code that is being executed is derived from the Shindig code found here:
http://svn.apache.org/repos/asf/shindig/trunk/features/src/main/javascript/features/shindig.random/random.js
A secure random number is needed to ensure that the secure postMessage channel created here cannot be compromised by scripts on the page to execute arbitrary actions.
Here's an article that explains why using Math.random() is bad:
http://baagoe.com/en/RandomMusings/javascript/

If you can get your script loaded first, you could hook addEventListener and log everyone who is setting addEventListener and see who's doing it and then, by looking at the relevant code, see what they're doing.
Put this in place before the Google code loads:
var oldListener = document.addEventListener;
document.addEventListener = function(type, listener, capture) {
if (type == "mousedown" || type == "mouseup" || type == "mousemove") {
console.log("type=" + type + " listener=" + listener.toString().slice(0, 80));
}
return (oldListener.apply(this, arguments));
}
To see what was listening to window.onmousemove, you'd have to do it afterwards because it's just a variable assignment, not a function that you can intercept. So sometimes after the initialization code of the page runs, you would do this to log what was hooked up to it:
if (window.onmousemove) {
console.log(window.onmousemove.toString().slice(0,80));
}

In the uncluttered code as of Jul 22, you'll notice the onmousemove is part of the Gb.random class:
Gb.random = function () {
function a(a) {
var b = Jb();
b.update(a);
return b.ib()
}
var b = la.random(),
c = 1,
d = (screen[za] * screen[za] + screen[J]) * 1E6,
e = i.onmousemove || Db();
i.onmousemove = function (a) {
if (i.event) a = i.event;
var b = a.screenX + a.clientX << 16;
b += a.screenY + a.clientY;
b *= (new Date)[Ta]() % 1E6;
c = c * b % d;
return e[G](i, ka[x][Aa][G](arguments))
};
var f = a(k.cookie + "|" + k[B] + "|" + (new Date)[Ta]() + "|" + b);
return function () {
var b = c;
b += ia(f[cb](0, 20), 16);
f = a(f);
return b / (d + la.pow(16, 20))
}
}();
It's multiplying sum of x and y by 2^16 using bitshift, then adding some other dimensions and multiplying all this by time in milliseconds mod 1000000. This definitely looks like a randomizing algorithm.
I'm not sure why the page would need something like this, perhaps it's using a cookie, preventing automated +1 clicking? When you click the "+1" the login screen that pops up appears to have a random number appended as the hash, the url ends with "&hl=en-US#RANDOMNUMBER"

I bet you its "In-Page Analytics" Beta. Making a cursor and click heat-map.

I think that the paper by Guo and Agichtein from CHI 2010 http://www.mathcs.emory.edu/~qguo3/wip287-guo11.pdf can provide further ideas on why Google is doing that.
Apparently mouse movements is a rough proxy for eye movement and allows people to approximate eye tracking results.

They probably use it to measure how quickly users move from one UI item to another, how often clicks miss etc.
I normally have a deeply cynical view of invasive features but I don't think this is a privacy risk. It's shocking because it's so unusually fine-grained, but it's not very revealing. Does your mouse movement encode bank details? Porn?
Google and the like have plenty of high-quality data to track you with. Mouse coordinates have very limited application.
To go off-topic a bit:
To an extent, the more data you collect about people the more problems you have. I hear (from Schneier and the like) that intelligence agencies are suffering from the huge numbers of false positives triggered by their ever-accelerating data aquisition -- the signal-to-noise ratio is abysmal. I find this somewhat amusing.

It's impossible to tell for certain, what Google does with this mouse movement data. As you can see yourself, it's not returning loads and loads of information back to the server, therefore, nothing to worry about.
The first is probably a generic event handler. Reason why I think that is if you read the source, you can see that on the line before there is throw Error("Invalid listener argument"); and next or one after the next there's throw Error("Invalid event type"). Since the fired line is in between these two (event related) exceptions, I'm pretty sure that it's some kind of an event handler. Using debugger, it doesn't do anything really (doesn't jump to some other function) so it seems that it's there for future implementation.
The second function is identical to the first one. Since it's gTalk's I suppose it updates your status (away, online etc).
The third seems to be content updater or something similar, since you can see strings like cacheTimeout etc scattered around it.
My 2 cents.

this is really beyond from far fetched, but here it goes anyway ...
it revolves around the type of trajectory & curvature of a mousemovement from a start point towards different attractors take i.e. 2 items/links on a page.
http://sciencestage.com/v/26698/dynamics-and-embodiment-in-language-comprehension.html
in short, if you put two competing links/buttons and analyze the trajectory towards one of those links, you can deduce a pattern or how you reached the decision to click only 1 of those links (see vid around 13:00)

Related

Why is JavaScript randomly adding '/1' to the end of URL bar?

So, me and a few friends are making a video game (text adventure) in JavaScript. In this game, you go around fighting monsters. It opens with a fight, but when you win, it randomly adds '/1' to the end of the URL. This is strange because window.location never appears in the program. Here is the code that is executed at the time of the problem:
function Places() {
location = 1
answer = prompt('Where do you go now? You have ' + totalGold + ' gold, and ' + hitPoints + ' health.', 'Town, Plains, Swamp, Menu').toUpperCase()
switch (answer) {
case 'TOWN':
if (aabeaDestroysTown === 0) {
alert('You walk into town, where there is a marketplace and an inn.')
InTown()
} else {
alert('As you near the outskirts of town, you notice the stream of people leaving town. Then you notice that the entire place is now just a gigantic blast crater. Somebody blew it up!!! You decide to investigate, and walk over to the stream of people.')
alert('When you reach the people, they all say this person named A\'Abea had just come to town and started fires all over, and then used some weird, magical powers to blow up Smatino.')
alert('You are sure this A\'Abea is the same as the one who you met in the swamp, and wish you had used some \'weird, magical powers\' to blow him up')
alert('You race back to the swamp, and see him from a distance. You can\'t, however, blow him up. There are too many vines in the way. So, you follow him. You see a large tower in the distance, and finally, after a few hours, reach it at night. You see A\'Abea enter, and then, as the gate is clanging down above him, you slide under it and manage to get in.')
inTower()
}
break;
etc. You only see the prompt() box for a split second, then it does the random addition.
Error Message:
/*
Exception: out of memory
*/
What is even stranger about this is that it seems to only do it when testing in Firefox.
It's because you're setting window.location to 1. Don't do that unless you want to update the page URL.
By default, variables are set on the global window object. If you'd like to set a local variable named location inside your function, use var location = 1.

CANNON.js: check if a body is being constrained

I've been trying to make a multiplayer game using javascript (most of which is on the server, using Node.js); one of the core mechanics I want to make is that players will be able to design their own fighting style (right down to how they swing their sword etc). Problem is that I can't find any simple way of constraining players' movements.
I first tried to write a method that checks then clamps the player's style so it doesn't look like they're breaking every limb simultaneously, but that didn't really work. I then found the wonderful CANNON.ConeTwistConstraint, but after looking through the documentation I've found that CANNON.js's constraints don't seem to have any sort of built-in function for just testing whether two bodies are exceeding the constraint's limits. I've thought about having my game just create objects in a separate simulation and check whether a force is being applied to either object, but I'm not sure about how to go about this, or if there's a better way.
Is there a simple/easier solution to my problem? If not, what would be the least CPU-intensive way of implementing the above?
You can manually check if the ConeTwistConstraint is hitting its limit. If you have a look at the method CANNON.ConeEquation.prototype.computeB, you can see that it computes the constraint violation, "g", using cos() and a dot product. You can simply do the same with the following code.
var eq = coneTwistConstraint.coneEquation;
var g = Math.cos(eq.angle) - eq.axisA.dot(eq.axisB);
if(g > 0) {
// Constraint limit exceeded
} else {
// Constraint is within limits
}
Using the same strategy, you can check if the twist limit is exceeded. Since the twist equation is a CANNON.RotationalEquation, the code becomes:
var eq2 = coneTwistConstraint.twistEquation;
var g2 = Math.cos(eq2.maxAngle) - eq2.axisA.dot(eq2.axisB);

checking whether part of google map is land or water [duplicate]

..and then Google-maps "divide the waters from the waters"
Well, not in the biblical sense but..
I would like to know what options I have in order to verify if a point of [Lat, Lon] is Land or Water.
Google Maps obviously has this data (the bodies of water are blue) - but is there something in the API that I can use for that? And if not - are they not serving it because they never thought of it? Or because it is too complicated?
I have not found any info on the matter - except some similar questions here (like finding type of terrain, or elevation - but it is not exactly what I need).
Is there separated layer for that? An option? Command? Or should I go to do that manually?
The only way that I can think of how to approach this (should I need to do that manually) is to check every served tile for the exact point - and then check RGB value for that Google map hue.
This is only on theory - because in practice - I have no idea how to accomplish that, the first obstacle being that I do not know how I can convert a pixel location on a tile to [LatLon] point for example
A ready made solution would be much easier.
Note that I do not need ALL the water in the world (for example - I do not care about streams, small ponds, most rivers or your neighbor's swimming pool. I need the points where a person can venture without the aid of a floating vehicle)
EDIT I
After reading comments:
The elevation method is not reliable, there are too many places BELOW sea-level (you can see a list of the "deepest" 10 here http://geology.com/below-sea-level/ ) and there are too many land-locked water bodies ABOVE sea level (lakes).
The reverse geolocation method is not reliable because it will return a Geo-political entity, like city, or state - or ZERO many times.
I have already looked into those pseudo-solutions before asking the question - but none of them actually answered the question - those methods are bad "guessing" at best.
These are 2 different ways, you may try:
You can use Google Maps Reverse Geocoding . In result set you can determine whether it is water by checking types. In waters case the type is natural_feature. See more at this link http://code.google.com/apis/maps/documentation/geocoding/#Types.
Also you need to check the names of features, if they contain Sea, Lake, Ocean and some other words related to waters for more accuracy. For example the deserts also are natural_features.
Pros - All detection process will be done on client's machine. No need of creating own server side service.
Cons - Very inaccurate and the chances you will get "none" at waters is very high.
You can detect waters/lands by pixels, by using Google Static Maps. But for this purpose you need to create http service.
These are steps your service must perform:
Receive latitude,longitude and current zoom from client.
Send http://maps.googleapis.com/maps/api/staticmap?center={latitude,longitude}&zoom={current zoom`}&size=1x1&maptype=roadmap&sensor=false request to Google Static Map service.
Detect pixel's color of 1x1 static image.
Respond an information about detection.
You can't detect pixel's color in client side. Yes , you can load static image on client's machine and draw image on canvas element. But you can't use getImageData of canvas's context for getting pixel's color. This is restricted by cross domain policy.
Prons - Highly accurate detection
Cons - Use of own server resources for detection
It doesn't seem possible with any current Google service.
But there are other services, like Koordinates Vector JSON Query service! You simply query the data in the URL, and you get back a JSON/XML response.
Example request: http://api.koordinates.com/api/vectorQuery.json?key=YOUR_GEODATA_KEY&layer=1298&x=-159.9609375&y=13.239945499286312&max_results=3&radius=10000&geometry=true&with_field_names=true
You have to register and supply your key and selected layer number. You can search all their repository of available layers. Most of the layers are only regional, but you can find global also, like the World Coastline:
When you select a layer, you click on the "Services" tab, you get the example request URL. I believe you just need to register and that's it!
And now the best:
You can upload your layer!
It is not available right away, hey have to process it somehow, but it should work! The layer repository actually looks like people uploaded them as they needed.
There is a free web API that solves exactly this problem called onwater.io. It isn't something built into Google maps, but given a latitude and longitude it will accurately return true or false via a get request.
Example on water:
https://api.onwater.io/api/v1/results/23.92323,-66.3
{
lat: 23.92323,
lon: -66.3,
water: true
}
Example on land:
https://api.onwater.io/api/v1/results/42.35,-71.1
{
lat: 42.35,
lon: -71.1,
water: false
}
Full disclosure I work at Dockwa.com, the company behind onwater. We built onwater to solve this problem ourselves and help the community. It is free to use (paid for high volume) and we wanted to share :)
I thought it was more interesting to do this query locally, so I can be more self-reliant: let's say I want to generate 25000 random land coordinates at once, I would rather want to avoid calls to possibly costly external APIs. Here is my shot at this in python, using the python example mentionned by TomSchober. Basically it looks up the coordinates on a pre-made 350MB file containing all land coordinates, and if the coordinates exist in there, it prints them.
import ogr
from IPython import embed
import sys
drv = ogr.GetDriverByName('ESRI Shapefile') #We will load a shape file
ds_in = drv.Open("land_polygons.shp") #Get the contents of the shape file
lyr_in = ds_in.GetLayer(0) #Get the shape file's first layer
#Put the title of the field you are interested in here
idx_reg = lyr_in.GetLayerDefn().GetFieldIndex("P_Loc_Nm")
#If the latitude/longitude we're going to use is not in the projection
#of the shapefile, then we will get erroneous results.
#The following assumes that the latitude longitude is in WGS84
#This is identified by the number "4236", as in "EPSG:4326"
#We will create a transformation between this and the shapefile's
#project, whatever it may be
geo_ref = lyr_in.GetSpatialRef()
point_ref=ogr.osr.SpatialReference()
point_ref.ImportFromEPSG(4326)
ctran=ogr.osr.CoordinateTransformation(point_ref,geo_ref)
def check(lon, lat):
#Transform incoming longitude/latitude to the shapefile's projection
[lon,lat,z]=ctran.TransformPoint(lon,lat)
#Create a point
pt = ogr.Geometry(ogr.wkbPoint)
pt.SetPoint_2D(0, lon, lat)
#Set up a spatial filter such that the only features we see when we
#loop through "lyr_in" are those which overlap the point defined above
lyr_in.SetSpatialFilter(pt)
#Loop through the overlapped features and display the field of interest
for feat_in in lyr_in:
# success!
print lon, lat
check(-95,47)
I tried a dozen coordinates, it works wonderfully. The "land_polygons.shp" file can be downloaded here, compliments of OpenStreetMaps. (I used the first WGS84 download link myself, maybe the second works as well)
This what I use and it is working not too bad... you can improve the test if you have more cpu to waste by adding pixels.
function isItWatter($lat,$lng) {
$GMAPStaticUrl = "https://maps.googleapis.com/maps/api/staticmap?center=".$lat.",".$lng."&size=40x40&maptype=roadmap&sensor=false&zoom=12&key=YOURAPIKEY";
//echo $GMAPStaticUrl;
$chuid = curl_init();
curl_setopt($chuid, CURLOPT_URL, $GMAPStaticUrl);
curl_setopt($chuid, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($chuid, CURLOPT_SSL_VERIFYPEER, FALSE);
$data = trim(curl_exec($chuid));
curl_close($chuid);
$image = imagecreatefromstring($data);
// this is for debug to print the image
ob_start();
imagepng($image);
$contents = ob_get_contents();
ob_end_clean();
echo "<img src='data:image/png;base64,".base64_encode($contents)."' />";
// here is the test : I only test 3 pixels ( enough to avoid rivers ... )
$hexaColor = imagecolorat($image,0,0);
$color_tran = imagecolorsforindex($image, $hexaColor);
$hexaColor2 = imagecolorat($image,0,1);
$color_tran2 = imagecolorsforindex($image, $hexaColor2);
$hexaColor3 = imagecolorat($image,0,2);
$color_tran3 = imagecolorsforindex($image, $hexaColor3);
$red = $color_tran['red'] + $color_tran2['red'] + $color_tran3['red'];
$green = $color_tran['green'] + $color_tran2['green'] + $color_tran3['green'];
$blue = $color_tran['blue'] + $color_tran2['blue'] + $color_tran3['blue'];
imagedestroy($image);
var_dump($red,$green,$blue);
//int(492) int(570) int(660)
if($red == 492 && $green == 570 && $blue == 660)
return 1;
else
return 0;
}
Checkout this article. It accurately detects if something is on the water without needing a server. It's a hack that relies on the custom styling feature in Google Maps.
In addition to the reverse geocoding -- as Dr Molle has pointed out, it may return ZERO_RESULTS -- you could use the Elevation service. If you get zero results by reverse geocoding, get the elevation of the location. Generally, the sea gets a negative number as the seabed is below sea level. There's a fully-worked example of the elevation service.
Bear in mind that as Google don't make this information available any other method is just a guess and guesses are inherently inaccurate. However using the type returned by reverse geocoding, or the elevation if type is not available, will cover most eventualities.
This method is totally unreliable.
In fact, the returned data will totally depend on what part of the world you are working with.
For example, I am working in France.
If I click on the sea on the coast of France, Google will return the nearest LAND location it can "guess" at.
When I requested information from Google for this same question, they answered that they are unable to accurately return that the point requested in on a water mass.
Not a very satisfactory answer, I know.
This is quite frustrating, especially for those of us who provide the user with the ability to click on the map to define a marker position.
If all else fails you could always try checking the elevation at the point and for some distance about - not many things other than water tend to be completely flat.
Unfortunately this answer isn't within the Google Maps API and the referenced resource is not free, but there's a web service provided by DynamicGeometry that exposes an operation GetWaterOrLand which accepts a latitude/longitude pair (you can see a demo here).
My understanding of how this is implemented is by using water body shape files. How exactly these shape files are used with the Google Maps API, but you might be able to get some insight from the linked demo.
Hope that helps in some way.
Here's another example in pure JavaScript: http://jsfiddle.net/eUwMf/
As you can see, the ideia is basically the same as rebe100x, getting the image from Google static map API, and read the first pixel:
$("#xGps, #yGps").change(function() {
var img = document.getElementById('mapImg');
// Bypass the security issue : drawing a canvas from an external URL.
img.crossOrigin='anonymous';
var xGps = $("#xGps").val();
var yGps = $("#yGps").val();
var mapUrl = "http://maps.googleapis.com/maps/api/staticmap?center=" + xGps + "," + yGps +
"&zoom=14&size=20x20&maptype=roadmap&sensor=false";
// mapUrl += "&key=" + key;
$(img).attr("src", mapUrl);
var canvas = $('<canvas/>')[0];
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);
var pixelData = canvas.getContext('2d').getImageData(1, 1, 1, 1).data;
if (pixelData[0] == 164 &&
pixelData[1] == 190 &&
pixelData[2] == 220) {
$("#result").html("Water");
} else {
$("#result").html("Not water");
}
});
See the answer I gave to a similar question - it uses "HIT_TEST_TERRAIN" from the Earth Api to achieve the function.
There is a working example of the idea I put together here: http://www.msa.mmu.ac.uk/~fraser/ge/coord/
If List<Address> address returns 0 , you can assume this location as ocean or Natural Resources.Just add Below Code in Your response Method of Google Places API Response.
Initialize Below List as mentioned
List<Address> addresses = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1);
if (addresses.size()==0)
{
Toast.MakeText(getApplicationContext,"Ocean or Natural Resources selected",Toast.LENGTH_SHORT).show();
}else{
}
I would recommend rolling your own here. You can use tools like GDAL to query the contents under a point in a shapefile. You can get shapefiles for US geography from many sources including the US Census Bureau.
This can be done via GDAL binaries, the source C, or via swig in Java, Python, and more.
Census Maps
GDAL Information
Point Query Example in Python
Here is a simple solution
Because Google does not provide reliable results with regards to coordinates that lay on either ocean or inland bodies of water you need to use another backup service, such as Yandex, to help provide that critical information when it is missing. You most likely would not want to use Yandex as your primary geocoder because Google is far superior in the reliability and completeness of the worlds data, however Yandex can be very useful for the purpose of retrieving data when it relates to coordinates over bodies of water, so use both.
Yandex Documentation: https://api.yandex.com.tr/maps/doc/geocoder/desc/concepts/input_params.xml
The steps to retrieve Ocean name:
1.) Use Google first to reverse geocode the coordinate.
2.) If Google returns zero results, it is 99% likely the coordinate lies over an ocean. Now make a secondary reverse geocoding request with the same coordinates to Yandex. Yandex will return a JSON response with for the exact coordinates, within this response will be two "key":"value" pairs of importance
["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]
and
["GeoObject"]["name"]
Check the kind key, if it == "hydro" you know you are over a body of water, and because Google returned zero results it is 99.99% likely this body of water is an ocean. The name of the ocean will be the above "name" key.
Here is an example of how I use this strategy written in Ruby
if result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"] == "hydro"
ocean = result.data["GeoObject"]["name"]
end
The steps to retrieve an Inland Body of Water name:
For this example assume our coordinate lies in a lake somewhere:
1.) Use Google first to reverse geocode the coordinate.
2.) Google will most likely return a result that is a prominent default address on land nearby. In this result it supplies the coordinates of the address it returned, this coordinate will not match the one you provided. Measure the distance between the coordinate you supplied and the one returned with the result, if it is significantly different (for example 100 yards) then perform a secondary backup request with Yandex and check to see the value of the "kind" key, if it is "hydro" then you know the coordinate lies on water. Because Google returned a result as opposed to the example above, it is 99.99% likely this is an inland body of water so now you can get the name. If "kind" does not == "hydro" then use the Google geocoded object.
["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"]
and
["GeoObject"]["name"]
Here is the same code written in Ruby to get inland_body_of_water
if result.data["GeoObject"]["metaDataProperty"]["GeocoderMetaData"]["kind"] == "hydro"
inland_body_of_water = result.data["GeoObject"]["name"]
end
A note about Licensing: As far as I know Google does not allow you to use their data to display on any other maps other than those Google offers. Yandex however has very flexible licensing, and you can use their data to be displayed on Google maps.
Also Yandex has a a high rate limit of 50,000 request / day free of charge, and with no required API key.
I managed to get quite close by using the Google Elevation API. Here's an image of the results:
You see the hexagons pretty much stay on land even though a rectangular perimeter is defined that goes partly over water. In this case I did a quick check from Google Maps itself and the minimum elevation on land was about 8-9m so that was my threshold. The code is mostly copy/pasted from Google documentation and Stack Overflow, here's the full gist:
https://gist.github.com/dvas0004/fd541a0502528ebfb825
As a complete novice to Python I couldn't get SylvainB's solution to work with the python script that checks if coordinates are on land. I managed to figure it out however, by downloading OSGeo4W (https://trac.osgeo.org/osgeo4w/) and then installed everything I needed pip, Ipython, and checked that all the imports specified were there. I saved the following code as a .py file.
Code to check if coordinates are on land
###make sure you check these are there and working separately before using the .py file
import ogr
from IPython import embed
from osgeo import osr
import osgeo
import random
#####generate a 1000 random coordinates
ran1= [random.uniform(-180,180) for x in range(1,1001)]
ran2= [random.uniform(-180,180) for x in range(1,1001)]
drv = ogr.GetDriverByName('ESRI Shapefile') #We will load a shape file
ds_in = drv.Open("D:\Downloads\land-polygons-complete-4326\land-polygons-complete-4326\land_polygons.shp") #Get the contents of the shape file
lyr_in = ds_in.GetLayer(0) #Get the shape file's first layer
#Put the title of the field you are interested in here
idx_reg = lyr_in.GetLayerDefn().GetFieldIndex("P_Loc_Nm")
#If the latitude/longitude we're going to use is not in the projection
#of the shapefile, then we will get erroneous results.
#The following assumes that the latitude longitude is in WGS84
#This is identified by the number "4236", as in "EPSG:4326"
#We will create a transformation between this and the shapefile's
#project, whatever it may be
geo_ref = lyr_in.GetSpatialRef()
point_ref=osgeo.osr.SpatialReference()
point_ref.ImportFromEPSG(4326)
ctran=osgeo.osr.CoordinateTransformation(point_ref,geo_ref)
###check if the random coordinates are on land
def check(runs):
lon=ran1[runs]
lat=ran2[runs]
#Transform incoming longitude/latitude to the shapefile's projection
[lon,lat,z]=ctran.TransformPoint(lon,lat)
#Create a point
pt = ogr.Geometry(ogr.wkbPoint)
pt.SetPoint_2D(0, lon, lat)
#Set up a spatial filter such that the only features we see when we
#loop through "lyr_in" are those which overlap the point defined above
lyr_in.SetSpatialFilter(pt)
#Loop through the overlapped features and display the field of interest
for feat_in in lyr_in:
return(lon, lat)
###give it a try
result = [check(x) for x in range(1,11)] ###checks first 10 coordinates
I tried to get it to work in R but I had a nightmare trying to get all the packages you need to install so stuck to python.
Here's a typed async function that returns true or false if a lat/lng is water or not. No need to pay for external api's. You must enable static maps on google cloud though.
async function isLatLngWater(lat: number, lng: number) {
return new Promise<boolean>((resolve) => {
const img = new Image();
img.crossOrigin = "Anonymous";
img.onload = () => {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
ctx!.drawImage(img, 0, 0);
const { data } = ctx!.getImageData(10, 10, 1, 1);
if (data[0] == 156 && data[1] == 192 && data[2] == 249) {
canvas.remove();
resolve(true);
} else {
canvas.remove();
resolve(false);
}
};
img.src =
"https://maps.googleapis.com/maps/api/staticmap?center=" +
lat +
"," +
lng +
"&size=40x40&maptype=roadmap&sensor=false&zoom=20&key=" +
import.meta.env.VITE_GM_MSTAT;
});
}
There an API service called IsItWater.com which will let you check:
Request
curl 'https://isitwater-com.p.rapidapi.com/?latitude=41.9029192&longitude=-70.2652276&rapidapi-key=YOUR-X-RAPIDAPI-KEY'
Response
{
"water": true,
"latitude": 41.9029192,
"longitude": -70.2652276
}
I have a different solution here.
In current google map implementation, it does not calculate direction/distance from a water location to land location and vice versa. Why dont we use this logic to determine if the point is land or water.
For example lets take this example
if we want to determine, if a point x is land or water, then
let us check the direction between point x and a known point y which is land. If it determines the direction/distance then point x is land or else it is water.

Multi-tempo/meter js DAW

Has anyone implemented a javascript audio DAW with multiple tempo and meter change capabilities like most of the desktop daws (pro tools, sonar, and the like)? As far as I can tell, claw, openDAW, and web audio editor don't do this. Drawing a grid meter, converting between samples and MBT time, and rendering waveforms is easy when the tempo and meter do not change during the project, but when they do it gets quite a bit more complicated. I'm looking for any information on how to accomplish something like this. I'm aware that the source for Audacity is available, but I'd love to not have to dig through an enormous pile of code in a language I'm not an expert in to figure this out.
web-based DAW solutions exists.web-based DAW's are seen as SaaS(Software as a Service) applications.
They are lightweight and contain basic fundamental DAW features.
For designing rich client applications(RCA) you should take a look at GWT and Vaadin.
I recommend GWT because it is mature and has reusable components and its also AJAX driven.
Also here at musicradar site they have listed nine different browser based audio workstations.you can also refer to popcorn maker which is entirely javascript code.You can get some inspiration from there to get started.
You're missing the last step, which will make it easier.
All measures are relative to fractions of minutes, based on the time-signature and tempo.
The math gets a little more complex, now that you can't just plot 4/4 or 6/8 across the board and be done with it, but what you're looking at is running an actual time-line (whether drawn onscreen or not), and then figuring out where each measure starts and ends, based on either the running sum of a track's current length (in minutes/seconds), or based on the left-most take's x-coordinate (starting point) + duration...
or based on the running total of each measure's length in seconds, up to the current beat you care about.
var measure = { beats : 4, denomination : 4, tempo : 80 };
Given those three data-points, you should be able to say:
var measure_length = SECONDS_PER_MINUTE / measure.tempo * measure.beats;
Of course, that's currently in seconds. To get it in ms, you'd just use MS_PER_MINUTE, or whichever other ratio of minutes you'd want to measure by.
current_position + measure_length === start_of_next_measure;
You've now separated out each dimension required to allow you to calculate each measure on the fly.
Positioning each measure on the track, to match up with where it belongs on the timeline is as simple as keeping a running tally of where X is (the left edge of the measure) in ms (really in screen-space and project-coordinates, but ms can work fine for now).
var current_position = 0,
current_tempo = 120,
current_beats = 4,
current_denomination = 4,
measures = [ ];
measures.forEach(function (measure) {
if (measure.tempo !== current_tempo) {
/* draw tempo-change, set current_tempo */
/* draw time-signature */
}
if (measure.beats !== current_beats ||
measure.denomination !== current_denomination) {
/* set changes, draw time-signature */
}
draw_measure(measure, current_position);
current_position = MS_PER_MINUTE / measure.beats * measure.tempo;
});
Drawing samples just requires figuring out where you're starting from, and then sticking to some resolution (MS/MS*4/Seconds).
The added benefit of separating out the calculation of the time is that you can change the resolution of your rendering on the fly, by changing which time-scale you're comparing against (ms/sec/min/etc), so long as you re-render the whole thing, after scaling.
The rabbit hole goes deeper (for instance, actual audio tracks don't really care about measures/beats, though quantization-processes do), so to write a non-destructive, non-linear DAW, you can just set start-time and duration properties on views into your audio-buffer (or views into view-buffers of your audio buffer).
Those views would be the non-destructive windows that you can resize and drag around your track.
Then there's just the logic of figuring out snaps -- what your screen-space is, versus project-space, and when you click on a track's clip, which measure, et cetera, you're in, to do audio-snapping on resize/move.
Of course, to do a 1:1 recreation of ProTools in JS in the browser would not fly (gigs of RAM for one browser tab won't do, media capture API is still insufficient for multi-tracking, disk-writes are much, much more difficult in browser than in C++, in your OS of choice, et cetera), but this should at least give you enough to run with.
Let me know if I'm missing something.

How can I make my counter look less fake?

I'm using this bit of code to display the number of users on a site.
My customer is complaining it looks fake. Any suggestions?
var visitors = 187584;
var updateVisitors = function()
{
visitors++;
var vs = visitors.toString(),
i = Math.floor(vs.length / 3),
l = vs.length % 3;
while (i-->0) if (!(l==0&&i==0))
vs = vs.slice(0,i*3+l)
+ ','
+ vs.slice(i*3+l);
$('#count').text(vs);
setTimeout(updateVisitors, Math.random()*2000);
};
setTimeout(updateVisitors, Math.random()*2000);
Edited:
alt text http://img695.imageshack.us/img695/4268/reachdevs2.png
Screenshot-Advertise - Stack Overflow - Chromium http://img130.imageshack.us/img130/8083/screenshotadvertisestac.png
http://inedomedia.com/stackoverflow.aspx
Everyone knows JS counters are fake, don't bother trying to make it look "less fake", bother making a real one.
If you don't have enough visitors to show around, just don't use a counter, they're so 90's.
Warning: Attempted Humour
Did he ask for a giant splash page to go along with the fake real-time visitor counter? How about some nice "Netscape Now!" button logos and blinking text? Here are some really cool "under construction" animated gifs you can use too.
http://www.animatedgif.net/underconstruction/construction.shtml
-Oisin
I'm guessing it looks fake because every time you load the page it starts at the same number and counts upwards?
Take a look at the javascript that tells you how many megabytes of email storage you get with a Gmail account. I think it bases the starting number on the date/time, so that if you load a page, watch it count up, and then load it again, it won't reload with a smaller number.
Be honest though... it is fake right? You aren't showing precisely how many users there are and updating it live as new users create accounts. The goal then is to make sure it is somewhat close to reality. Hopefully the rate at which the number increases in your script is based on past new-user subscription rates.
make the interval parameter of the setInterval random as well ... it will look more real as it will randomly increment the random numbers :)

Categories

Resources