Coder Social home page Coder Social logo

Comments (8)

mhulse avatar mhulse commented on June 10, 2024

https://stackoverflow.com/questions/9104908/random-geographic-coordinates-on-land-avoid-ocean

http://jsfiddle.net/erickerr/4uj8m/2/

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Here's an alternative/simpler way of getting rand lat/lon:

<script src="https://maps.googleapis.com/maps/api/js?v=3&key=xxxxxx"></script>
<script>
function TryRandomLocation(callback) {
  //var lat = (Math.random() * 90) - 90;
  var lat = Math.random() * Math.max((180 - 0 * .25), 120) - (90 - Math.min(0 * .25, 45));
  var lng = Math.random() * 360 - 180;
  var sv = new google.maps.StreetViewService();

  // Try to find a panorama within 50 metres 
  sv.getPanorama({
      location: new google.maps.LatLng(lat, lng),
      radius: 50
  }, callback);
}

function HandleCallback(data, status) {
    if (status == 'OK') {
      // Call your code to display the panorama here.
      console.log(data)
    } else {
		console.log('Trying again')
      // Nothing here! Let's try another location.
      TryRandomLocation(HandleCallback);
    }
}

window.onload = function() {
  TryRandomLocation(HandleCallback);
}
</script>

https://stackoverflow.com/a/44478605/922323

Might need to rethink my approach.

Some have suggested working with bounds of a country as the earth has a lot of ocean.

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Some good info here:

https://stackoverflow.com/questions/990148/how-to-add-random-markers-to-a-map-but-avoiding-the-sea

Good to mention that I got a lot of the original code here:

http://vispo.com/go/index.htm

/* Teleporter by Jim Andrews, March 2014. All rights reserved.
See vispo.com for contact details.

Transports the user to a random location on the planet at the click
of a button. No, wait. What it actually does is generate a random
latitude and a random longitude and then find the closest Google 
maps panorama to that random LatLng. If we haven't visited that 
panorama, we visit it. If we have, then we select a different 
random LatLng and get the closest panorama to it, etc. */
	 
//************************************************************
// GLOBAL VARIABLES
//************************************************************
var webService, panorama, map, marker, marker2;
// panorama is a Google Maps StreetViewPanorama object.
// map is a Google Maps map object.
// marker is a Google Marker object; the red map marker.
// marker2 is the cross-hair image on the map. 
var MY_MAPTYPE_ID = 'custom_style';
// for the custom noir map.
var locations=[];
// array of LatLng locations we have seen panoramas at.
var infoWindow;
// displays the address when you click the marker.
var geocoder;
// used to find the address from a LatLng.
var URLparams = new URLparameters();
var URLparamsToGo = new URLparameters(0);
// objects for URL parameters. Used for 'share' button.
var teleportCounter=0;
// Counts the number of clicks on the Teleport button

//************************************************************
// PROCESS ANY PARAMETERS ATTACHED TO THE URL
//************************************************************

function getInitialInfoFromParams() {
	// Called in function initialize to get info from URLparams.
	// Returns an object containing URL params latLng, heading,
	// pitch, and zoom. These exist when Teleport is being 
	// started up from a sharing of a panorama. 
	var numOfParams=URLparams.length()
	if (numOfParams) {
		var lat=URLparams.getValue('la');
		var lon=URLparams.getValue('lo');
		var pitch=parseInt(URLparams.getValue('pi'));
		var heading=parseInt(URLparams.getValue('he'));
		var zoom=parseInt(URLparams.getValue('zo'));
		if (lat && lon) {
			var loc=new google.maps.LatLng(lat,lon);
		}
		else {
			var loc=false;
		}
		return {latLng:loc, heading:heading, pitch:pitch, zoom:zoom}
	}
	else {
		return false;
	}
}

//************************************************************
// SHARE BUTTON
//************************************************************

function getAddressAndURL() {
	// Runs when the user clicks the Share button.
	var latlng=panorama.getPosition();
	geocoder.geocode({'latLng': latlng}, writeAddressAndURL);
	// geocode gets the address of latlng.
	function writeAddressAndURL(results, status) {
		// writeAddressAndURL runs when geocode has results.
		if (status == google.maps.GeocoderStatus.OK) {
			if (results[0]) {
				var string= results[0].formatted_address + '\n\n' + createURLToShare();
				openShareDialog(string);
			} else {
				var string= createURLToShare();
				openShareDialog(string);
			}
		} else {
			var string= createURLToShare();
			openShareDialog(string);
		}
	}
}

function createURLToShare() {
	// Called by getAddressAndURL when the user clicks the Share.
	// button. Manufactures a URL which, when pasted into a
	// browser, starts Teleport at the current location.
	var currentCenter=panorama.getPosition();
	var pov=panorama.getPov();
	var heading = pov.heading;
	var pitch= pov.pitch;
	var zoom=panorama.getZoom();
	var URLparamsToGo = new URLparameters(0);
	URLparamsToGo.add(['la',currentCenter.lat().toFixed(6)])
	URLparamsToGo.add(['lo',currentCenter.lng().toFixed(6)]);
	URLparamsToGo.add(['he',heading.toFixed(2)]);
	URLparamsToGo.add(['pi',pitch.toFixed(2)]);
	URLparamsToGo.add(['zo',zoom]);
	return URLparamsToGo.getFullyConstructedURLWithParameters();
}

function openShareDialog(addressAndURL) {
	var s="Copy and paste to share:\n\n" + addressAndURL;
	alert(s);
}

//************************************************************
// TELEPORTER BUTTON FUNCTIONS
//************************************************************

function clickTeleportButton() {
	// Called when the user clicks the Teleport button.
	randomPanorama();
	teleportCounter++;
	document.getElementById('teleporter').innerHTML= 'Teleport ' + teleportCounter;
} // End of clickTeleportButton
//------------------------------------------------------------

function randomPanorama() {
	// Generates a random location. Then it finds the closest
	// panorama to that random location. 
	var randomLocation = randomLatLng();
	// randomLocation is a random location on planet Earth.
	// randomLocation is of type LatLng.
	setNearestPanorama(randomLocation, 50, false);
	// Finds the nearest Google panorama to randomLocation
	// and then displays that panorama.
} // End of randomPanorama
//------------------------------------------------------------

function randomLatLng() {
		// Returns a random location on the planet as a LatLng.
		var randomLatitude = Math.random()*Math.max((180-teleportCounter*0.25), 120) - (90 - Math.min(teleportCounter*0.25, 45));
		// randomLatitude starts out as a random number between -90 and 90.
		// Then we slowly decrease the range from 180 to 120 cuz there are
		// 60 degrees of antarctica and the arctic where we have few photos.
		var randomLongitude = Math.random() * 360 - 180;
		// randomLongitude is a random number between -180 and 180.
		return new google.maps.LatLng(randomLatitude, randomLongitude);
}  // End of randomLatLng
//------------------------------------------------------------

function setNearestPanorama(latLng, bounds, allowRepeatedVisits) {
	/* This function finds the closest panorama to the supplied
	latLng parameter, within the specified bounds (in meters). 
	If no panorama exists within those bounds, we increase the 
	bounds by a factor of 2 and recursively call setNearestPanorama
	with the same latLng and allowRepeatedVisits parameters. If, on
	the other hand, we find the closest panorama within the specified
	bounds then, if we have not visited it, we display it and add
	it to the list of visited panoramas. If we already have visited
	it, then, if allowRepeatedVisits is true, we display it, but if
	allowRepeatedVisits is false, we select a new random latLng and
	call setNearestPanorama with bounds set to 50 and allowRepeatedVisits
	set to false. */
	var checkaround = bounds || 50;
	// The function will search within checkaround meters of latLng.
	webService.getPanoramaByLocation(latLng, checkaround, checkNearestStreetView);
	/* checkNearestStreetView is a callback function. That is, it 
	gets called when getPanoramaByLocation has results */
	//``````````````````````````````````````````````````````````````
	function checkNearestStreetView(panoData) {
		// Called when getPanoramaByLocation has results. Could have
		// timed out with no results or have a panorama for us.
		var found=false;
		if (panoData) {
			 if (panoData.location) {
					if (panoData.location.latLng) {
						// We have a nearest streetview panorama.
						found=true;
					}
			 }
		}
		if (found) {
			// We have a nearest panorama. 
			var loc=panoData.location.latLng;
			if (allowRepeatedVisits || !alreadyVisited(loc)) {
				// If repeated visits are allowed or if we have not
				// already visited the panorama, we display it.
				panorama.setPosition(loc);
				map.setCenter(loc);
				marker.setPosition(loc);
				var panoramaIsVisible = panorama.getVisible();
				if ( !panoramaIsVisible) toggleStreetView();
				// Set the panorama!
			}
			else {
				// If we do not allow repeated visits to the same panorama
				// and we have already visited this panorama, we start the
				// process of selecting a panorama from the beginning.
				randomPanorama();
			}
		}
		else {
			setNearestPanorama(latLng, checkaround*2, allowRepeatedVisits);
			// We have not found a streetview panorama within checkaround
			// meters of latLng. So we recursively call setNearestPanorama
			// with larger bounds, ie, we search a larger circle or area.
		}
		//...............................................................
		function alreadyVisited(pos) {
			/*  Defined within setNearestPanorama. alreadyVisited is called
			by setNearestPanorama to determine if we have already visited a
			location. pos is a LatLng. alreadyVisited returns a boolean.
			Returns true if we have already visited the location, false
			otherwise. The locations array is an array of LatLng objects
			that we have already visited this session. */
			var notFound=true;
			// notFound is a boolean that's true while we have not found
			// a location that is really close to pos.
			var i=0;
			while (notFound && i<locations.length) {
				// While we have not found a location in the list that is
				// really close to pos and we have not looked at all the
				// LatLng values in the list, continue looping.
				var ob=locations[i];
				var areEqual = equalLatLngs(pos,ob);
				if (areEqual) {
					notFound=false;
				}
				else {
					i++;
				}
			}
			if (notFound) {
				locations.push(pos);
			}
			return !notFound;
		}
		//...............................................................
		function equalLatLngs(o1,o2) {
			// Returns true if the distance between the two LatLng objects o1
			// and o2 is less than 10 meters. Returns false otherwise.
			if (google.maps.geometry.spherical.computeDistanceBetween(o1,o2) < 10) {
				return true
			}
			else {
				return false;
			}
		}
	} // end of checkNearestStreetView
} // end of setNearestPanorama
//------------------------------------------------------------

//************************************************************
// TOGGLE BUTTON
//************************************************************

function toggleStreetView() {
		// Called when the user clicks the button to go from
		// Street View to Map View or Map View to Street View.
		var panoramaIsVisible = panorama.getVisible();
		if (panoramaIsVisible == false) {
			// We move from map view to panorama view.
			var currentCenter=map.getCenter();
			// currentCenter is the current center of the map.
			setNearestPanorama(currentCenter, 50, true);
			// Display the closest panorama to the current center.
			// If we've already seen it, that's OK, display it anyway.
			panorama.setVisible(true);
			document.getElementById('butt1').innerHTML='Map';
			// Set the button to say 'Map'.
		} else {
			// We move from panorama view to map view.
			var currentCenter=panorama.getPosition();
			map.setCenter(currentCenter);
			marker.setPosition(currentCenter);
			setAddress(currentCenter);
			marker2.setVisible(false);
			panorama.setVisible(false);
			document.getElementById('butt1').innerHTML='Street';
		}
	}
	
	function setAddress(latlng) {
		// Sets the address you see when you click the marker on the map.
		if (latlng) {
			// Then we have a location
			geocoder.geocode({'latLng': latlng}, function(results, status) {
				if (status == google.maps.GeocoderStatus.OK) {
					if (results[0]) {
						infoWindow.setContent(results[0].formatted_address);
					} else {
						infoWindow.setContent('Address unavailable. Address status: ' + status);
					}
				} else {
					infoWindow.setContent('Address unavailable. Address status: ' + status);
				}
			});
		}
		else {
			// In this case latlng is undefined.
			infoWindow.setContent('Location undefined.');
		}
	infoWindow.close();
	}

//************************************************************
// INITIALIZATION
//************************************************************

function initialize() {
	// Called at the beginning of the program after the window has loaded.
	webService = new google.maps.StreetViewService(); 
	geocoder = new google.maps.Geocoder(); 
	var initialLatLng = new google.maps.LatLng(51.492177,-0.193015);
	// See http://tinyurl.com/lroeh5w for info on the opening panorama.
	var initialHeading=130;
	var initialPitch=0;
	var initialZoom=1;
	var initialInfo=getInitialInfoFromParams();
	// If the session involves URL parameters, the 
	// params will be in initialInfo.
	if (initialInfo) {
		// If there are URL parameters, then they will 
		// at least include a latLng, so set it.
		initialLatLng=initialInfo.latLng;
		if (initialInfo.heading) {
			initialHeading=initialInfo.heading;
		}
		if (initialInfo.pitch) {
			initialPitch=initialInfo.pitch;
		}
		if (initialInfo.zoom) {
			initialZoom=initialInfo.zoom;
		}
	}
	/*-------------------------------------------------------------- 
	See http://tinyurl.com/l3xs7v2 for info on panorama options. */
	var panoramaOptions = {
		position: initialLatLng,
		pov: {
			heading: initialHeading,
			pitch: initialPitch
		},
		addressControl:false,
		/* addressControlOptions: {
			position: google.maps.ControlPosition.BOTTOM
	}, */
	};
	//----------------------------------------------------------------
	// featureOpts styles the noir map.
	var featureOpts = [
		{
			stylers: [ 
				{ hue: '#777777' },
				{ gamma: 0.3},
				{ weight: 1 },
				{ saturation: -100},
				{lightness: -30}
			]
		},
		{
			elementType: 'labels',
			stylers: [
				{ visibility: 'on' }
			]
		},
		{
			featureType: 'water',
			stylers: [
				{ color: '#333333' }
			]
		}
	];
	//-----------------------------------------------------------------
	var mapOptions = {
		zoom: 12,
		center: initialLatLng,
		mapTypeControlOptions: {
			mapTypeIds: [MY_MAPTYPE_ID, google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.SATELLITE]
		},
		mapTypeId: MY_MAPTYPE_ID,
		streetViewControl:false
	};
	//------------------------------------------------------------------			
	var el=document.getElementById('pano'); // the panorama and map div
	//------------------------------------------------------------------		
	map = new google.maps.Map(el, mapOptions); // create the map!
	var styledMapOptions = {
		name: 'Noir'
	};
	//------------------------------------------------------------------		
	// now we'll style the map.
	var customMapType = new google.maps.StyledMapType(featureOpts, styledMapOptions);
	map.mapTypes.set(MY_MAPTYPE_ID, customMapType);
	//------------------------------------------------------------------
	// now create the location marker on the map
	marker=new google.maps.Marker({
		position:initialLatLng,
	});
	marker.setMap(map); 
	//------------------------------------------------------------------		
	// the info window opens when you click the location marker.
	infoWindow = new google.maps.InfoWindow({content: "A Tardis"}); 
	google.maps.event.addListener(marker, 'click', function() {
    infoWindow.open(map,marker);
  });
	infoWindow.close();
	//------------------------------------------------------------------		
	// the cross-hair is used to pinpoint where you will go in street view
	var crosshairShape = {coords:[0,0,0,0],type:'rect'};
	marker2 = new google.maps.Marker({
		map: map,
		icon: 'images/cross-hairs.gif',
		shape: crosshairShape,
		zIndex: 99999999
	});
	marker2.bindTo('position', map, 'center'); 
	// The crosshairs stays in the center of the map.
	// bindTo is a method of MVCObjects.
	// make the cross-hair visible when the user clicks the map.
	map.addListener('mousedown', makeCrosshairVisible);
	function makeCrosshairVisible() {marker2.setVisible(true)};
	//------------------------------------------------------------------		
	panorama = new  google.maps.StreetViewPanorama(el,panoramaOptions);
	panorama.setZoom(initialZoom);
	// panorama is initially visible
	//----------------------------------------------------------------
	// Button styling.
	document.getElementById('butt1').onmouseover=buttHover;
	document.getElementById('butt1').onmouseout=buttLeave;
	document.getElementById('teleporter').onmouseover=buttHover;
	document.getElementById('teleporter').onmouseout=buttLeave;
	document.getElementById('credits').onmouseover=buttHover;
	document.getElementById('credits').onmouseout=creditsLeave;
	
	function buttHover() {
		this.style.color='red';
	}
	
	function buttLeave() {
		this.style.color='black';
	}
	
	function creditsLeave() {
		this.style.color='white';
	}
	
} // end of initialize

google.maps.event.addDomListener(window, 'load', initialize);
// Calls the function initialize after the document has loaded.
// This is the first thing to happen.

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

There's also this one:

http://www.mapcrunch.com/js/main.min.js?v=6a

But IIRC, they use a defined set of lat/lons as starting locations. I think I had to use wayback machine to find the uniminified source of the JS; from there I was able to read the code. Etc.

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Liking the idea of using equirectangular map image, like:

https://visibleearth.nasa.gov/view.php?id=73963

Just created this:

map

Going to use a function from this repo:

https://github.com/ahalota/gridCoordinates

Next, need to read image and pick rando point and see if the pixel data is black; if white, pick another rando point.

This should save from API calls to Google!

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Random thoughts for docs later:

screenshot 2019-02-03 16 40 58

Using Photoshop, I open the info palette and can see pixel x/y.

Then using this bit of code:

getPixels("./test/map/map.png", function(err, pixels) {

  if (err) {
    console.log('Bad image path');
  } else {
    let width = pixels.shape[0];
    let height = pixels.shape[1];
    console.log('got pixels', pixels.get(1685, 832, 0))
  }


});

Pixel data at 1685 x and 832 y is: 255 white (only need one channel as this is black or white)

Pixel at 1686 and 832 is: 0 black.

So easy!

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Created:

https://github.com/mhulse/rand-land-coords

from kludgy.

mhulse avatar mhulse commented on June 10, 2024

Feature added to v2.0.0! It works!

Closing.

from kludgy.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.