Skip to content

Loading…

Add new 'accuracyGeometry' property to ol.Geolocation #1553

Merged
merged 4 commits into from

2 participants

@fredj
OpenLayers member

No description provided.

@fredj
OpenLayers member

Should the point resolution compensation be done in the ecample's style function?

@twpayne

Should the point resolution compensation be done in the ecample's style function?

Yes, although the code will confuse people who don't understand projections. I expect that it'll eventually get moved into the library, but it makes sense to start with the code in the example.

I recently had to solve this problem (compensating for EPSG:3857's distortion at different latitudes), so I'll send you some code off-line.

@fredj
OpenLayers member

Ready to review, thanks

@twpayne

Looks great!

@fredj fredj merged commit 2ed3b93 into openlayers:master

1 check passed

Details default The Travis CI build passed
@fredj fredj deleted the fredj:geolocation-geom branch
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 74 additions and 31 deletions.
  1. +0 −10 examples/geolocation.html
  2. +19 −20 examples/geolocation.js
  3. +27 −1 src/ol/geolocation.js
  4. +28 −0 src/ol/sphere/sphere.js
View
10 examples/geolocation.html
@@ -8,15 +8,6 @@
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap.min.css" type="text/css">
<link rel="stylesheet" href="../resources/layout.css" type="text/css">
<link rel="stylesheet" href="../resources/bootstrap/css/bootstrap-responsive.min.css" type="text/css">
- <style>
- .icon-flag {
- font-size: 22px;
- text-shadow: 2px 2px 3px #013;
- }
- .tooltip-inner {
- white-space: nowrap;
- }
- </style>
<title>Geolocation example</title>
</head>
<body>
@@ -63,7 +54,6 @@ <h4 id="title">Geolocation example</h4>
</div>
<script src="jquery.min.js" type="text/javascript"></script>
- <script src="../resources/bootstrap/js/bootstrap.min.js" type="text/javascript"></script>
<script src="../resources/example-behaviour.js" type="text/javascript"></script>
<script src="loader.js?id=geolocation" type="text/javascript"></script>
View
39 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} */ ($('<i/>').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]
+});
View
28 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);
};
@@ -208,6 +219,21 @@ goog.exportProperty(
/**
+ * 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.
* @todo stability experimental
View
28 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');
@@ -29,6 +31,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.<number>} */
+ 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.
*
* @param {ol.Coordinate} c1 Coordinate 1.
Something went wrong with that request. Please try again.