-
-
Notifications
You must be signed in to change notification settings - Fork 50
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1370 from NSUWAL123/feat-project-details-geolocat…
…ion-integration Feat project details geolocation integration
- Loading branch information
Showing
5 changed files
with
143 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import pngbluedot from '@/assets/images/png bluedot.png'; | ||
import { Fill } from 'ol/style'; | ||
import VectorSource from 'ol/source/Vector'; | ||
import OLVectorLayer from 'ol/layer/Vector'; | ||
import { Feature } from 'ol'; | ||
import { Point } from 'ol/geom'; | ||
import { fromLonLat } from 'ol/proj'; | ||
import { circular } from 'ol/geom/Polygon'; | ||
import { Style } from 'ol/style'; | ||
import { Icon } from 'ol/style'; | ||
|
||
const locationIconStyle = new Style({ | ||
fill: new Fill({ | ||
color: 'rgba(0, 0, 255, 0.2)', | ||
}), | ||
image: new Icon({ | ||
src: pngbluedot, | ||
scale: 0.09, | ||
imgSize: [27, 55], | ||
rotateWithView: true, | ||
}), | ||
}); | ||
|
||
export const Geolocation = (map) => { | ||
if (!map) return; | ||
const source = new VectorSource(); | ||
const layer = new OLVectorLayer({ | ||
source: source, | ||
properties: { | ||
name: 'geolocation', | ||
}, | ||
}); | ||
map?.addLayer(layer); | ||
|
||
navigator.geolocation.watchPosition( | ||
function (pos) { | ||
const coords = [pos.coords.longitude, pos.coords.latitude]; | ||
source.clear(true); | ||
source.addFeatures([ | ||
new Feature(circular(coords, pos.coords.accuracy).transform('EPSG:4326', map.getView().getProjection())), | ||
new Feature(new Point(fromLonLat(coords))), | ||
]); | ||
}, | ||
function (error) { | ||
alert(`ERROR: ${error.message}`); | ||
}, | ||
{ | ||
enableHighAccuracy: true, | ||
}, | ||
); | ||
|
||
layer.setStyle(locationIconStyle); | ||
|
||
function handleReading(quaternion) { | ||
// https://w3c.github.io/orientation-sensor/#model explains the order of | ||
// the 4 elements in the sensor.quaternion array. | ||
let [qx, qy, qz, qw] = quaternion; | ||
|
||
// When the phone is lying flat, we want to treat the direction toward the | ||
// top of the phone as the "forward" direction; when the phone is held | ||
// upright, we want to treat the direction out the back of the phone as the | ||
// "forward" direction. So, let's determine the compass heading of the | ||
// phone based on the vector between these directions, i.e. at a 45-degree | ||
// angle between the positive Y-axis and the negative Z-axis in this figure: | ||
// https://w3c.github.io/orientation-sensor/#absoluteorientationsensor-model | ||
|
||
// To find the current "forward" direction of the phone, we want to take this | ||
// vector, (0, 1, -1), and apply the same rotation as the phone's rotation. | ||
const y = 1; | ||
const z = -1; | ||
|
||
// From experimentation, it looks like the quaternion from the sensor is | ||
// the inverse rotation, so we need to flip the fourth component. | ||
qw = -qw; | ||
|
||
// This section explains how to convert the quaternion to a rotation matrix: | ||
// https://w3c.github.io/orientation-sensor/#convert-quaternion-to-rotation-matrix | ||
// Now let's multiply the forward vector by the rotation matrix. | ||
const rx = y * (2 * qx * qy + 2 * qw * qz) + z * (2 * qx * qz - 2 * qw * qy); | ||
const ry = y * (1 - 2 * qx * qx - 2 * qz * qz) + z * (2 * qy * qz + 2 * qw * qx); | ||
const rz = y * (2 * qy * qz + 2 * qw * qx) + z * (1 - 2 * qx * qx - 2 * qy * qy); | ||
|
||
// This gives us a rotated vector indicating the "forward" direction of the | ||
// phone with respect to the earth. We only care about the orientation of | ||
// this vector in the XY plane (the plane tangential to the ground), i.e. | ||
// the heading of the (rx, ry) vector, where (0, 1) is north. | ||
|
||
const radians = Math.atan2(ry, rx); | ||
const degrees = (radians * 180) / Math.PI; // counterclockwise from +X axis | ||
let heading = 90 - degrees; | ||
if (heading < 0) heading += 360; | ||
heading = Math.round(heading); | ||
|
||
// To make the arrow point north, rotate it opposite to the phone rotation. | ||
locationIconStyle.getImage().setRotation((Math.PI / 180) * heading); | ||
} | ||
|
||
// See the API specification at: https://w3c.github.io/orientation-sensor | ||
// We use referenceFrame: 'screen' because the web page will rotate when | ||
// the phone switches from portrait to landscape. | ||
const sensor = new AbsoluteOrientationSensor({ | ||
frequency: 60, | ||
referenceFrame: 'screen', | ||
}); | ||
sensor.addEventListener('reading', (event) => { | ||
layer.on('postrender', handleReading(sensor.quaternion)); | ||
}); | ||
// handleReading([0.509, -0.071, -0.19, 0.836]); | ||
|
||
Promise.all([ | ||
navigator.permissions.query({ name: 'accelerometer' }), | ||
navigator.permissions.query({ name: 'magnetometer' }), | ||
navigator.permissions.query({ name: 'gyroscope' }), | ||
]).then((results) => { | ||
if (results.every((result) => result.state === 'granted')) { | ||
sensor.start(); | ||
// stat.value = "Sensor started!"; | ||
} else { | ||
// stat.value = "No permissions to use AbsoluteOrientationSensor."; | ||
} | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters