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

Working with location data: distance(lat1, lon1, lat2, lon2, unit) function? #154

Closed
Moonbase59 opened this issue Apr 26, 2021 · 2 comments
Closed

Comments

@Moonbase59
Copy link

@Moonbase59 Moonbase59 commented Apr 26, 2021

In the Obsidian forum, we came across an interesting point today: Calculating distances between locations and finding nearby locations.

Since Dataview doesn’t offer access to Javascript or SQL syntax, we don’t have things like cos(), sqrt() and others to build our own functions for doing "real earth" coordinate calculations.

One of the most sought functions is surely the distance between two coordinates (usually given as WGS-84 or EPSG:4326 coordinates).

In my case, all friends, family, and interesting location notes in Obsidian get a front-matter entry like this:

---
location: [51.133333,10.416667]
---

I can build links from these, but it would be great if this data could also be used to, say, find interesting places within a 20km radius around afriend’s place I wish to visit.

Do you think it might be feasible integrating a function for this, like maybe distance(lat1, lon1, lat2, lon2, unit), so list and table views could use the distance as maybe m, km, miles?

Didn’t check too much, but maybe the distance code from the Obsidian Leaflet plugin could be reused, so we get the same (and hopefully correct, since Earth is spherical) results?

@Moonbase59
Copy link
Author

@Moonbase59 Moonbase59 commented May 7, 2021

Would still be nice (for non-dataviewjs users), but I solved it in the meantime with a little Javascript. Here is an example (just a test):

function getDistance(origin, destination, unit='m') {
    // return distance in selected unit (m,km,yd,mi)
    // 2021-05-08 - Matthias C. Hormann (Moonbase59)

    var factor = 1.0;
    switch (unit) {
      case 'm':
        factor = 1.0;
        break;
      case 'km':
        factor = 1000.0;
        break;
      case 'yd':
        factor = 0.9144;
        break;
      case 'mi':
        factor = 1609.344;
        break;
      default:
        factor = 1.0;
        console.warn("getDistance: Invalid unit '%s', using 'm'. Valid units are: m,km,yd,mi.",unit);
    }

    var lon1 = toRadian(origin[1]),
        lat1 = toRadian(origin[0]),
        lon2 = toRadian(destination[1]),
        lat2 = toRadian(destination[0]);

    var deltaLat = lat2 - lat1;
    var deltaLon = lon2 - lon1;

    var a = Math.pow(Math.sin(deltaLat/2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(deltaLon/2), 2);
    var c = 2 * Math.asin(Math.sqrt(a));
    var EARTH_RADIUS = 6371000; // 6,371 km in metres
    return c * EARTH_RADIUS / factor;
}
function toRadian(degree) {
    return degree*Math.PI/180;
}
// Below example should result in 416093.4 metres
let unit = 'm';
dv.paragraph(getDistance([48.23875,10.37595], [51.7599915, 8.404249],unit).toLocaleString(moment.locale(), {maximumFractionDigits: 1}) + " " + unit + " Luftlinie");

Feel free to use it, if it helps.

@blacksmithgu
Copy link
Owner

@blacksmithgu blacksmithgu commented Aug 22, 2021

Going to close this issue since it can be worked around with DataviewJS; wonce custom function support rolls around later, this will be able to be exposed as a generic script that users can download and use in both DataviewJS and dataview.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants