diff --git a/examples/geolocation.html b/examples/geolocation.html
index 8b5ec77a5d..7fecca68de 100644
--- a/examples/geolocation.html
+++ b/examples/geolocation.html
@@ -8,15 +8,6 @@
-
Geolocation example
@@ -63,7 +54,6 @@
-
diff --git a/examples/geolocation.js b/examples/geolocation.js
index 8989dee7f7..b693c7efc5 100644
--- a/examples/geolocation.js
+++ b/examples/geolocation.js
@@ -1,12 +1,10 @@
-// FIXME use an ol.geom.Circle to display a circle with accuracy
-// FIXME this circle will need to compensate for the pointResolution of the
-// FIXME EPSG:3857 projection
-
+goog.require('ol.Feature');
+goog.require('ol.FeatureOverlay');
goog.require('ol.Geolocation');
goog.require('ol.Map');
-goog.require('ol.Overlay');
goog.require('ol.View2D');
goog.require('ol.dom.Input');
+goog.require('ol.geom.Point');
goog.require('ol.layer.Tile');
goog.require('ol.source.OSM');
@@ -22,7 +20,7 @@ var map = new ol.Map({
source: new ol.source.OSM()
})
],
- renderer: exampleNS.getRendererFromQueryString(),
+ renderer: 'canvas',
target: 'map',
view: view
});
@@ -41,22 +39,23 @@ geolocation.on('propertychange', function() {
$('#speed').text(geolocation.getSpeed() + ' [m/s]');
});
-var marker = new ol.Overlay({
- element: /** @type {Element} */ ($('').addClass('icon-flag').get(0)),
- positioning: 'bottom-left',
- stopEvent: false
-});
-map.addOverlay(marker);
-// bind the marker position to the device location.
-marker.bindTo('position', geolocation);
-
-geolocation.on('change:accuracy', function() {
- $(marker.getElement()).tooltip({
- title: this.getAccuracy() + 'm from this point'
- });
-});
geolocation.on('error', function(error) {
var info = document.getElementById('info');
info.innerHTML = error.message;
info.style.display = '';
});
+
+
+var accuracyFeature = new ol.Feature();
+accuracyFeature.bindTo('geometry', geolocation, 'accuracyGeometry');
+
+var positionFeature = new ol.Feature();
+positionFeature.bindTo('geometry', geolocation, 'position')
+ .transform(function() {}, function(coordinates) {
+ return coordinates ? new ol.geom.Point(coordinates) : null;
+ });
+
+var featuresOverlay = new ol.FeatureOverlay({
+ map: map,
+ features: [accuracyFeature, positionFeature]
+});
diff --git a/src/ol/geolocation.js b/src/ol/geolocation.js
index cc489b1b9e..0a1e621024 100644
--- a/src/ol/geolocation.js
+++ b/src/ol/geolocation.js
@@ -3,13 +3,16 @@
goog.provide('ol.Geolocation');
goog.provide('ol.GeolocationProperty');
+goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.EventType');
goog.require('goog.math');
goog.require('ol.BrowserFeature');
goog.require('ol.Coordinate');
goog.require('ol.Object');
+goog.require('ol.geom.Geometry');
goog.require('ol.proj');
+goog.require('ol.sphere.WGS84');
/**
@@ -17,6 +20,7 @@ goog.require('ol.proj');
*/
ol.GeolocationProperty = {
ACCURACY: 'accuracy',
+ ACCURACY_GEOMETRY: 'accuracyGeometry',
ALTITUDE: 'altitude',
ALTITUDE_ACCURACY: 'altitudeAccuracy',
HEADING: 'heading',
@@ -50,6 +54,8 @@ ol.GeolocationProperty = {
* @todo stability experimental
* @todo observable accuracy {number} readonly the accuracy of the position
* measurement in meters
+ * @todo observable accuracyGeometry {ol.geom.Geometry} readonly a
+ * geometry of the position accuracy.
* @todo observable altitude {number} readonly the altitude of the position in
* meters above mean sea level
* @todo observable altitudeAccuracy {number} readonly the accuracy of the
@@ -176,9 +182,14 @@ ol.Geolocation.prototype.positionChange_ = function(position) {
this.position_[0] = coords.longitude;
this.position_[1] = coords.latitude;
}
- this.set(ol.GeolocationProperty.POSITION, this.transform_(this.position_));
+ var projectedPosition = this.transform_(this.position_);
+ this.set(ol.GeolocationProperty.POSITION, projectedPosition);
this.set(ol.GeolocationProperty.SPEED,
goog.isNull(coords.speed) ? undefined : coords.speed);
+
+ var geometry = ol.sphere.WGS84.circle(this.position_, coords.accuracy);
+ geometry.transform(this.transform_);
+ this.set(ol.GeolocationProperty.ACCURACY_GEOMETRY, geometry);
};
@@ -207,6 +218,21 @@ goog.exportProperty(
ol.Geolocation.prototype.getAccuracy);
+/**
+ * Get a geometry of the position accuracy.
+ * @return {?ol.geom.Geometry} Accuracy geometry.
+ * @todo stability experimental
+ */
+ol.Geolocation.prototype.getAccuracyGeometry = function() {
+ return /** @type {?ol.geom.Geometry} */ (
+ this.get(ol.GeolocationProperty.ACCURACY_GEOMETRY) || null);
+};
+goog.exportProperty(
+ ol.Geolocation.prototype,
+ 'getAccuracyGeometry',
+ ol.Geolocation.prototype.getAccuracyGeometry);
+
+
/**
* Get the altitude associated with the position.
* @return {number|undefined} The altitude in meters above the mean sea level.
diff --git a/src/ol/sphere/sphere.js b/src/ol/sphere/sphere.js
index 825d843263..d63f8573c2 100644
--- a/src/ol/sphere/sphere.js
+++ b/src/ol/sphere/sphere.js
@@ -10,7 +10,9 @@
goog.provide('ol.Sphere');
+goog.require('goog.array');
goog.require('goog.math');
+goog.require('ol.geom.Polygon');
@@ -28,6 +30,32 @@ ol.Sphere = function(radius) {
};
+/**
+ * Returns an approximation to a circle centered on `center` with radius
+ * `radius` with `n` distinct points.
+ *
+ * @param {ol.Coordinate} center Center.
+ * @param {number} radius Radius.
+ * @param {number=} opt_n N.
+ * @return {ol.geom.Geometry} Circle geometry.
+ */
+ol.Sphere.prototype.circle = function(center, radius, opt_n) {
+ var n = goog.isDef(opt_n) ? opt_n : 32;
+ /** @type {Array.} */
+ var flatCoordinates = [];
+ var i;
+ for (i = 0; i < n; ++i) {
+ goog.array.extend(
+ flatCoordinates, this.offset(center, radius, 2 * Math.PI * i / n));
+ }
+ flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]);
+ var polygon = new ol.geom.Polygon(null);
+ polygon.setFlatCoordinates(
+ ol.geom.GeometryLayout.XY, flatCoordinates, [flatCoordinates.length]);
+ return polygon;
+};
+
+
/**
* Returns the distance from c1 to c2 using the spherical law of cosines.
*