Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reversegeocode #5976

Merged
merged 16 commits into from
Nov 29, 2017
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Thumbs.db
/Apps/CesiumViewer/Gallery/gallery-index.js

/Apps/Sandcastle/jsHintOptions.js
/Apps/Sandcastle/gallery/gallery-index.js
#/Apps/Sandcastle/gallery/gallery-index.js
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you revert this change?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want to commit gallery-index.js. It is generated automatically when you run npm run build


/Source/Cesium.js

Expand Down
96 changes: 89 additions & 7 deletions Apps/Sandcastle/gallery/Custom Geocoder.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Attach a custom data source to the geocoder widget.">
<meta name="cesium-sandcastle-labels" content="Tutorials,Showcases">
<title>Cesium Demo</title>
<title>Custom Geocoder Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
Expand All @@ -32,28 +32,48 @@
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
<div id="reverseGeocodeButton"></div>
</div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
/**
* This class is an example of a custom geocoder. It provides geocoding through the OpenStreetMap Nominatim service.
* @alias OpenStreetMapNominatimGeocoder
* @constructor
*/
* This class is an example of a custom geocoder, and reverse geocoder. It provides both * * through the OpenStreetMap Nominatim service. Press the "Reverse Geocoder" button to go * * to OpenStreet Map headquarters. OpenStreetMap has more information in the UK than in the * US.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the * * intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I think it is a result of formatting when I got rid of the tabs...will fix : )

* @alias OpenStreetMapNominatimGeocoder
* @constructor
*/
function OpenStreetMapNominatimGeocoder() {
}

/**
* Object for both input and result. Could be in external file to avoid code redundancy
* Points to the headquarters of Open Street Map Foundation in the UK
*/
var geoLocation = {
latitude:52.551074,
longitude:-1.818343,
address:'default address'
};

/* search: looking for location of address, reverse: looking for address of a location */
var action = {
search: 'search?',
reverse: 'reverse?'
};

var endpoint = 'https://nominatim.openstreetmap.org/';

/**
* The function called to geocode using this geocoder service.
*
* @param {String} input The query to be sent to the geocoder service
* @returns {Promise<GeocoderResult[]>}
*/
OpenStreetMapNominatimGeocoder.prototype.geocode = function (input) {
var endpoint = 'https://nominatim.openstreetmap.org/search?';
var query = 'format=json&q=' + input;
var requestString = endpoint + query;
var requestString = endpoint + action.search + query;
return Cesium.loadJson(requestString)
.then(function (results) {
var bboxDegrees;
Expand All @@ -72,10 +92,72 @@
});
};

/**
* Instantiate the Cesium Viewer
*/
var viewer = new Cesium.Viewer('cesiumContainer', {
geocoder: new OpenStreetMapNominatimGeocoder()
});

/**
* The function called to reverse geocode using this geocoder service.
*
* @param {String} input The query to be sent to the geocoder service
*/
function getAddressFromLocation(geoLocation, callback) {
var query = 'format=json&lat=' + geoLocation.latitude + '&lon=' + geoLocation.longitude + '&zoom=18&addressdetails=1';
var requestString = endpoint + action.reverse + query;
var promise = Cesium.loadJson(requestString);
promise.then(function(result) {
console.log(result);
geoLocation.address = result.display_name;
setLocationPoint();
});
callback();
}

/**
* Add button to trigger reverse geocoding to hard-coded location
*/
Sandcastle.addToolbarButton('Reverse Geocoder', function() {
getAddressFromLocation(geoLocation, onReverseGeocodeCompletion);
});

/**
* Callback to fly the camera to the location chosen for reverse geocoding.
*/
function onReverseGeocodeCompletion() {
viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(geoLocation.longitude, geoLocation.latitude, 25000.0)
});
}

/**
* Set a point and mark the address at reverse geocoded location.
*/
function setLocationPoint() {
viewer.entities.add({
name : 'address location',
// Reverse the latitude and longitude when calling "fromDegrees"
position : Cesium.Cartesian3.fromDegrees(geoLocation.longitude, geoLocation.latitude),
point : {
pixelSize : 5,
color : Cesium.Color.BLUE,
outlineColor : Cesium.Color.WHITE,
outlineWidth : 2
},
label : {
text : geoLocation.address,
font : '14pt monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth : 2,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
pixelOffset : new Cesium.Cartesian2(0, -9)
}
});
}


//Sandcastle_End
Sandcastle.finishedLoading();
}
Expand Down
175 changes: 175 additions & 0 deletions Apps/Sandcastle/gallery/Reverse Geocoder.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Attach a custom data source to the geocoder widget.">
<meta name="cesium-sandcastle-labels" content="Tutorials,Showcases">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
require.config({
baseUrl : '../../../Source',
waitSeconds : 60
});
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
#toolbar {
background: rgba(42, 42, 42, 0.8);
padding: 4px;
border-radius: 4px;
}
#toolbar input {
vertical-align: middle;
padding-top: 2px;
padding-bottom: 2px;
}
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
/**
* This class is an example of reverse geocoder using the default geocoder service (Bing Maps)
* It also includes click handling and setting points at found or clicked locations.
* To reverse geocode, click on any location on the globe to show the address.
*/

/**
* Object for both input and result. Should be in external file, to avoid code redundancy.
*/
var geoLocation = {
latitude: 0.00,
longitude: 0.00,
address: 'default address'
};

var viewer = new Cesium.Viewer('cesiumContainer');

var baseUrl = 'https://dev.virtualearth.net/REST/v1/Locations/';

/**
* The function called to reverse geocode using this geocoder service.
*
* @param {String} input The query to be sent to the geocoder service
* Calling loadJsonp to bypass CORS on BingMaps
*/
function getAddressFromLocation(geoLocation) {
var url = baseUrl + geoLocation.latitude + "," + geoLocation.longitude;

var promise = Cesium.loadJsonp(url, {
parameters : {
key : Cesium.BingMapsApi.getKey()
},
callbackParameterName : 'jsonp'
});

promise.then(function(result) {
geoLocation.address = result.resourceSets[0].resources[0].name;
setAddressPoint();
}).otherwise(function(error) {
alert("ERROR getting address: " + error);
});
// We are not zooming in on the location.
}
/*********************************************************************
* Functions below, could be in an external file for this and Custom Geocoder.
* geoLocation object as well.
********************************************************************/
/**
* Listen for the geocode search to be complete, to mark it with a point.
*/
viewer.geocoder.viewModel.complete.addEventListener(function () {
if (!viewer.geocoder.viewModel.searchText.empty){
setPointForSearchLocation();
}
});

/**
* Find the camera position after search, and put a point there.
*/
function setPointForSearchLocation() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something in this function is causing an error to be thrown when you use the geocoder search


var camera = this.viewer.camera;
var ellipsoid = this.viewer.scene.globe.ellipsoid;
var coordinate = ellipsoid.cartesianToCartographic(camera.position);
var lat = Cesium.Math.toDegrees(coordinate.latitude);
var long = Cesium.Math.toDegrees(coordinate.longitude);
var announce = 'Latitude: ' + parseFloat(Math.round(lat * 100)/100).toFixed(4)+
',Longitude: ' + parseFloat(Math.round(long * 100)/100).toFixed(4);
var home = viewer.entities.add({
name : announce,
// For Cesium fromDegrees, longitude before latitude.
position : Cesium.Cartesian3.fromDegrees(long, lat),
point : {
pixelSize : 15,
color : Cesium.Color.AQUAMARINE,
outlineColor : Cesium.Color.BLACK,
outlineWidth : 2
}
});
}

/**
* Handler for left click of the mouse on the map, get latitude and longitude, and start reverse geocoding
*/
var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

// Catch the mouse click, and convert the location into degrees
handler.setInputAction(

// Translate mouse click into Geographic coordinates
function (click) {
var position = viewer.camera.pickEllipsoid(click.position);
var location = Cesium.Ellipsoid.WGS84.cartesianToCartographic(position);
geoLocation.latitude = Cesium.Math.toDegrees(location.latitude);
geoLocation.longitude = Cesium.Math.toDegrees(location.longitude);
// Reverse geocode to get the address
getAddressFromLocation(geoLocation);
},
Cesium.ScreenSpaceEventType.LEFT_CLICK
);

/**
* Set a point and mark the address at reverse geocoded location.
*/
function setAddressPoint() {
viewer.entities.add({
name : 'Latitude: ' + geoLocation.latitude + ', Longitude:' + geoLocation.longitude,
// Reverse the latitude and longitude when calling "fromDegrees"
position : Cesium.Cartesian3.fromDegrees(geoLocation.longitude, geoLocation.latitude),
point : {
pixelSize : 5,
color : Cesium.Color.RED,
outlineColor : Cesium.Color.WHITE,
outlineWidth : 2
},
label : {
text : geoLocation.address,
font : '14pt monospace',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
outlineWidth : 2,
verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
pixelOffset : new Cesium.Cartesian2(0, -9)
}
});
}

//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Binary file added Apps/Sandcastle/gallery/Reverse Geocoder.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading