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

Suggestions #78

Closed
zafrirron opened this issue Mar 3, 2019 · 48 comments
Closed

Suggestions #78

zafrirron opened this issue Mar 3, 2019 · 48 comments
Labels

Comments

@zafrirron
Copy link
Contributor

Hi @dceejay, thanks for this great node!

I added few enhancements into my fork (in dev private branches now), before submitting yet another pull request , please consider it and I'll send pull requests according to your guidance:

  1. Grid options: grid option by @cloudybay
  2. Mouse coordinates box option: Coordinates box by @powerpan
  3. Improved measuring tool: Measure Tool by @ppete2
  4. Tooltip option: Tooltip by @aratcliffe
  5. Left button inject commands: enhancing currently limited context menu, by adding injection of commands to allow different map / server map entity interactions (additional dynamic buttons added to the context menu when pressed sends predefined commands)
  6. Enhanced Add marker option: add configurable add marker form, allowing setting additional map entity attributes.
@dceejay
Copy link
Owner

dceejay commented Mar 5, 2019

Hi, thanks for the ideas. I'm a bit wary of adding too many options as they all need to be configured which is going to get confusing for users (the config dialog is getting a bit too crowded already...) but...

  1. Grid - like it - May need to to think about styling a bit to make it work with the many maps available - like the default grey map layer.
  2. Not so sure - What does this one look like ? I have experimented with several in the past and they all looked a bit rubbish, or took up too much space, or didn't seem to add much value, so I always ended up removing again.
  3. Yes - looks good - prefer without the bearings. (presumably to replace the existing one - though I like the fact the existing one only needs one button on the map.)
  4. Do we really need this ? We already have popup and label. (though not totally against. It is just another variation I suppose)
  5. Not sure I understand ? any chance of a screenshot ? what sort of interactions do you have a use case for ? dm me @ gmail if you like
  6. Again - screenshot, more details ? (but in theory definitely maybe, but I definitely don't want this too complex. I'd still like it to be useable when map is inside a widget.)

So I would say the priority order is
PR 1,3 More info/discuss 4,6,5,2
And please PR them one at a time

@dceejay
Copy link
Owner

dceejay commented Mar 8, 2019

  1. 1. PR for Suggestion 1 - Latlng graticule #79 - closed (didn't work). May be revived as part of moving to leaflet1.4 work
  2. 2. Added as part of 7e70f16
  3. 3. (not so sure about this one)- not really feeling the need - but... maybe PR
  4. 4. Added as part of 2de1b0b
  5. 5. .contextmenu option added as part of release 1.5.32
  6. 6. control.contextmenu added as part of release 1.5.34

@zafrirron
Copy link
Contributor Author

zafrirron commented Mar 28, 2019

Hi,
thanks again for a great work,
Few suggestions regarding "tracks" option:

  1. Have tracks unique "tracks" layer (will enable simple hide/show all tracks).
  2. Allow getting number of track points as input parameter (more node-red style?).
  3. Allow some track styling...(dots/line; color...)

although I've done this in my private branch, my PR's track record are quite embarrassing to offer my help again.... :-(

@dceejay
Copy link
Owner

dceejay commented Mar 29, 2019

  1. Surely you want track to stay with their marker so when you turn off that layer of markers their tracks go too ?
  2. Input parameter to what ? You set them in the node edit panel (very Node-RED style :-). You don't want to add that to every input message ? Or did you just mean as an overall command message style ?
  3. Like it.. - but again - not sure you would want this on every input message ?

Your PR was probably fine... - if I was on later leaflet and you had actually tried it against the shipped version :-)... There is a branch that now is work in progress to later leaflet - but it keeps blowing it's stack for some reason... doesn't like popups... so I can't release it in that state.

@zafrirron
Copy link
Contributor Author

zafrirron commented Mar 30, 2019

  1. User preference (I use both options, hide markers layers with/wo tracks)
  2. Some node red nodes have the option to set parameter value in node edit or override it with message (I guess you are correct in this specific node, setting the track history size in every message doesn't make sense)
  3. same as 2...so if the user doesn't supply initial value he can set the value by message with property set (like setting url in http request node).

@dceejay
Copy link
Owner

dceejay commented Mar 31, 2019

So if you have a tracks layer for every other type of layer you could end up with 2x the layers ?
eg ships and ships_tracks, planes and planes_tracks, etc ? If so, on leaflet 0.7 the layer control is not scrollable so you would need to not use too many layers or it won't fit on the page.

Digging into the code.. I see I can already set the tracks (and area) options, as they get picked up from the data anyway... so maybe just need more docs ?

    var opt = {};
    opt.color = data.color || "#910000";
    opt.fillColor = data.fillColor || "#910000";
    opt.stroke = (data.hasOwnProperty("stroke")) ? data.stroke : true;
    opt.weight = data.weight || 2;
    opt.opacity = data.opacity || 1;
    opt.fillOpacity = data.fillOpacity || 0.2;
    opt.clickable = (data.hasOwnProperty("clickable")) ? data.clickable : false;
    opt.fill = (data.hasOwnProperty("fill")) ? data.fill : true;
	if (data.hasOwnProperty("dashArray")) { opt.dashArray = data.dashArray; }

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 1, 2019

@dceejay
thanks!
I checked the "weight"option and it worked, I agree it needs some docs....(even after your response, it took me a while to figure out that sending a weight property of/for a marker should affect the marker track, its "inheritance" of properties.

regarding layer, I thought only about a single "tracks" layer containing all tracks of all moving markers...if and only if the user had set it in the node config form (and if users decide push too many layers into a map...)

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 1, 2019

@dceejay
One other observation I had on "tracks" option, is that I need to create some kind "same location" filter.
I'm not sure about other implementations, but I do have some cases, where some markers get redraw on same location (the use case is changing some other marker attributes or "wrong redraw" implementation).
tracks however I expect to show last X marker locations, so currently, sending X times same location will "shorten" the track until it disappears... with filtering sending same location will not update the tracked location list of that marker.

@dceejay
Copy link
Owner

dceejay commented Apr 1, 2019

Thinking about it - it's a fairly simple option to add to the tracks node - to let the user select the behaviour... - as-is, a single "tracks" layer, or a tracks layer per marker layer. Then it's up to the user not to over clutter the menu :-).

image

@zafrirron
Copy link
Contributor Author

looks FANTASTIC!
(shame on me, I will need to code it into my forked version)....

@dceejay
Copy link
Owner

dceejay commented Apr 1, 2019

pushed as 1.5.37

@zafrirron
Copy link
Contributor Author

@dceejay
One other observation I had on "tracks" option, is that I need to create some kind "same location" filter.
I'm not sure about other implementations, but I do have some cases, where some markers get redraw on same location (the use case is changing some other marker attributes or "wrong redraw" implementation).
tracks however I expect to show last X marker locations, so currently, sending X times same location will "shorten" the track until it disappears... with filtering sending same location will not update the tracked location list of that marker.

@dceejay ,
I'de appreciate your view on this....(before I do something wrong....)

@dceejay
Copy link
Owner

dceejay commented Apr 2, 2019

will be easy to add a check in the track node to only update if lat or lon have changed.

@dceejay
Copy link
Owner

dceejay commented Apr 2, 2019

and actually - should also be possible to allow updates to objects by adding to them in-situ... ie be able to send just name plus new parameter without lat lon... by keeping a list of objects and just adding to them as info comes in. Would make changing icons or colours a lot simpler.... maybe.

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 20, 2019

Thanks!

One other suggestion (I'm using in my implementation), is adding the popup option to other map entities (like area, circle, line) similar to the marker popup handler (defaults to "name")....
(I didn't try to also add the context menu option but this may also be considered).

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 21, 2019

For removing unwanted fields of the marker default info box (where popup option not used), I use an array (including the wanted fields names) a default one replaced by optional injected one, using this default/optional array saving the need to delete each option separately (just before building the "words" variable - for cleaner code, since using the new popup option is encouraged it mostly for wm developers convenience).

@zafrirron
Copy link
Contributor Author

Also consider running HTML validator on index.html (use https://validator.w3.org), I've cleaned some errors using it....

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 21, 2019

The new added "feedback" function (sending map in actions), I suggest to allow other actions than "feedback" and add property (for backwards compatibility, I've added the two as last function parameters function(n,v,p="",a="feedback)) .

The use case:
most convenient way to handle "Map In" node is to attach a "large" "switch" node immediately after ""Map In" switching based on "action" name...and use it to allow setting of markers properties(p parameter).
so:
a = action name defaults to "feedback"
n = marker name
p = marker property
v = property value

@zafrirron
Copy link
Contributor Author

Leaflet V1.4
BTW - after working extensively for quite some time already with V1.4, I have not experienced any issues related to v1.4 so far....

@dceejay
Copy link
Owner

dceejay commented Apr 21, 2019

yes I have a 1.4 branch (leaflet-upgrade) almost ready to go... just "baking" it for a while to check before releasing it as beta.
Will run html check - but nothing serious so far. just w3c being picky.
Other popups - yes maybe - no-one has asked for them so...
Feedback - not quite sure I get the use case fully, yes I understand the switch part. Is this to save having another switch to switch based on all the "feedback"s ? Why is property needed as a separate property, why not make value an object ?

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 21, 2019

For the new context menu option, while most of the html panel configuration and parameters should be set by server nodes. The only internal "map" parameter is the click position (for markers usually its should be also "known" by the server).
Worth mentioning (DOC) the ability yo use the internal rclk.lat, rclk.lng in the context menu callbacks...

Use case:
Creating a customised "add marker" map context menu panel, that includes multiple marker properties, using context menu option, bypassing the default "Add marker" (addThing) rightmenuMap option.

possible bug: in map.on('contextmenu', function(e) {... there is assumption that field name 'rinput' exists, this may not be the case when using customised rightmenu (consider using try {}..catch{}...)

possible bug: in function setMarker(data) {... at the end of the function there is handler for if (popped == true) {...else {popmark.openPopup();... this code raises exception when opening a rightMenu on the map (not on marker...)

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 21, 2019

yes I have a 1.4 branch (leaflet-upgrade) almost ready to go... just "baking" it for a while to check before releasing it as beta.
Will run html check - but nothing serious so far. just w3c being picky.
Other popups - yes maybe - no-one has asked for them so...
Feedback - not quite sure I get the use case fully, yes I understand the switch part. Is this to save having another switch to switch based on all the "feedback"s ? Why is property needed as a separate property, why not make value an object ?

HTML - yesy nothing serious for me only hels while debugging front end...
Other Popups - I found that creating popups for drawing elements enables efficient map functionality to handle these entities (delete, hide, send, color, opacity, edit....some of my actions...)
Feedback - regarding the switch, indeed, a cleaner node red implementation is a single switch handling all map in actions...
Objects - Correct! creating object is a better option, thanks.

@dceejay
Copy link
Owner

dceejay commented Apr 21, 2019

so function(n,v,(optional a)) would be ok and then send {action:a||"feedback", name:n, value:v}

@dceejay
Copy link
Owner

dceejay commented Apr 21, 2019

PS - I published the v2.0.0-beta to npm which uses leaflet 1.4.x if you wish to try it.

@zafrirron
Copy link
Contributor Author

so function(n,v,(optional a)) would be ok and then send {action:a||"feedback", name:n, value:v}

Sure, thanks!

@zafrirron
Copy link
Contributor Author

PS - I published the v2.0.0-beta to npm which uses leaflet 1.4.x if you wish to try it.

Thanks, I'will.
(unfortunately. since I already forked away....my merges back are taking time...)...

@dceejay
Copy link
Owner

dceejay commented Apr 22, 2019

I added the other grid overlay back now ... it works on leaflet 1.x .
And added popups to lines and areas (as long as clickable is set true).

Happy for the suggestions in parallel, I'm on a slower path than you :-)

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 25, 2019

Thanks!

I'm not sure, but isn't leaflet rectangle object type handled by "worldmap"? (only as polygons?)...
use cases:

  1. Rectangle attributes are special (were bounding box needed)
  2. I'm adding Editing option to all red injected objects, rectangle editing however is different than polygon's

my code: (requires adding 'type' attribute = 'rectangle')
near:
else if (data.hasOwnProperty("area") && Array.isArray(data.area)) {

change to:

 var polyarea;
if (data.hasOwnProperty("type") && data.type == "rectangle") polyarea = L.rectangle(data.area, opt);
else polyarea = L.polygon(data.area, opt);

BTW - the nice part of externalizing the "popup" is the ability now to inject many additional functionality with almost no code changes (the "editing" option for example was added by adding the js files and setting a popup command button to :
"<button id='editzone' class='tcmd' onclick='polygons[\"{{name}}\"].enableEdit();'>Edit</button>";
were {{name}} is a generic replacer in the injecting node to set object name...

@dceejay
Copy link
Owner

dceejay commented Apr 26, 2019

why are rectangles special ?
Editable looks interesting - might make for a better drawing layer than the existing draw plugin ?
it is yet another 75k library though so would need to be a replace I think.

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 27, 2019

Rectangles: since leaflet draw has two different shapes for rectangles and polygons, maintaining leaflet conventions should be a good reason... Editing a rectangle is different from editing a polygon in all editing tools, also when returning a shape from drawing tool, the type of the shape might be of importance to the user (in my case I use the shape type to allow certain options based on shape type).

Editable: I found this extension easier to use for allowing editing to existing "worldmap" injected shapes by use of only a popup button and sending the edited shape to NR by the "feedback" function in the popup html:
feedback(\"{{name}}\",\"SaveZ\",{{saveData}});

{{name}} - area/rectangle/circle name
{{saveData}} - any worldmap latlang array (polygons["{{name}}"]._latlngs[0] for example)

Also Editable allows editing for its created shapes...but requires rewriting the NR feedback

Anyway - adding a usable drawing tool to "worldmap" should include the ability to edit existing shapes, draw new shapes, save an edited/created shape, cancel currently edited/created activity...

I suggest allowing handling a single drawing entity at a time only (so if I'm drawing a new shape I can only cancel or save it - return the data to NR for handling. but allowing creating multiple shapes on the map at the same time, doesn't make a lot of sense)

@dceejay
Copy link
Owner

dceejay commented Apr 27, 2019

Ah right. once again moving to leaflet 1.x has caused a bump in the road. The old drawing layer was editable, so you could re-edit shapes. They have changed the API and now they aren't currently editable. I'll see if I can work it out and restore it as was. That may remove the need for editable... but it did seem to have some nice extra capability - but then the basic tools need to be re-created in that so it's a bit 50/50 at the moment.

OK - update - I'm leaning towards replacing Draw with Editable - so fingers crossed we can get best of both.

@zafrirron
Copy link
Contributor Author

zafrirron commented Apr 29, 2019

This is the code that works for me with Editable for creating new shapes (first proto code...), same look and feel like Draw with small changes (sorry I don't use lines...should be added):

var editToolbar = L.DomUtil.create('div', 'leaflet-control leaflet-bar'); //for hide/show

var shapeType = ''; 

editToolbar.setAttribute("id", "edittoolbar");

L.EditControl = L.Control.extend({

        options: {
            position: 'topleft',
            callback: null,
            kind: '',
            html: '',
			class: null,
			icon: null,
			id: null
        },

        onAdd: function (map) {
			var link = L.DomUtil.create('a', this.options.class, editToolbar);

            link.href = '#';
	    link.title = this.options.kind;
	    link.id = this.options.id;
	    if (this.options.icon)  link.innerHTML = "<i class=\"" + this.options.icon + "\" aria-hidden=\"true\"></i>"
            else link.innerHTML = this.options.html;
           	L.DomEvent.on(link, 'click', L.DomEvent.stop)
                      .on(link, 'click', function () {
                        					window.LAYER = this.options.callback.call(map.editTools);
											shapeType = this.options.id;
                      					}
					  , this);
            //return container;
			return editToolbar;
        }
    });
  	L.NewPolygonControl = L.EditControl.extend({
        options: {
            position: 'topleft',
            callback: map.editTools.startPolygon,
            kind: 'create new polygon',
            html: '▰',
	   id: 'poly'
        }
    });
    L.NewRectangleControl = L.EditControl.extend({
        options: {
            position: 'topleft',
            callback: map.editTools.startRectangle,
            kind: 'crearte new rectangle',
            html: '⬛',
	    id: 'rect'
        }
    });
    L.NewCircleControl = L.EditControl.extend({
        options: {
            position: 'topleft',
            callback: map.editTools.startCircle,
            kind: 'create new circle',
            html: '⬤',
          //icon: 'fa fa-trash fa-lg'
	   id: 'circ'
        }
    });
   	map.addControl(new L.NewPolygonControl());
   	map.addControl(new L.NewRectangleControl());
        map.addControl(new L.NewCircleControl());
	var removeButton = L.easyButton({
							states:[{
								icon:'fa fa-trash fa-lg',
								onClick:function() { 
									map.removeLayer(window.LAYER); //cancel edits
									editToolbar.style.display = "block"; //restore toolbar
								}, 
								title:'Remove'
							}], 
							position:"topleft"
						}).addTo(map);
	var saveButton = L.easyButton({
							states:[{
								icon:'fa fa-save',
								onClick:function() { 
									var name = prompt("Please enter zone name", ""); //ugly get name
									if (name != null && name != "") {
										var shapeArr = [];
										var shape = null;
										switch (shapeType) {
											case 'rect':   //need better way to find the Editable created data
												shape = window.LAYER.editing._shape._latlngs[0];
												for (var i=0; i<shape.length; i++) {
													shapeArr.push({'lat': shape[i].lat, 'lon':shape[i].lng});
												};
												break;
											case 'poly':
												shape = window.LAYER.editing._poly._latlngs[0];
												for (var i=0; i<shape.length; i++) {
													shapeArr.push({'lat': shape[i].lat, 'lon':shape[i].lng});
												};
												break;
											case 'circ':
												shape = window.LAYER.editing._shape;
												shapeArr.push({'lat': shape._latlng.lat, 'lon':shape._latlng.lng, 'center':shape._mRadius });
												break;
											default:
												break;
										};
										console.log(shapeArr);
										feedback(name, 'addzone', {'type': shapeType,'data':shapeArr}); //use feedback to send data back to NR
										map.removeLayer(window.LAYER);
										editToolbar.style.display = "block";
									};
								}, 
								title:'Save'
							}], 
							position:"topleft"
						}).addTo(map);

	map.on('editable:created', function(e) {
		editToolbar.style.display = "none"; //allow only single entity at a time by hiding the toolbar 
	});

for editing existing shapes I use the following "popup" option (my NR function), use as popup is better usability since the user selects the entity directly on the map w/o the need to access the toolbar:

....
popup       += "<button id='editzone' class='tcmd' onclick='map.closePopup();polygons[\"{{name}}\"].enableEdit();'>Edit</button>";
popup       += "<button id='savezone' class='tcmd' onclick='map.closePopup();polygons[\"{{name}}\"].toggleEdit();feedback(\"{{name}}\",\"SaveZ\",{{saveData}});'>Save</button><br/>";

....
 thispop = thispop.replace(/{{saveData}}/g,"polygons[{{name}}]._latlng.lat,polygons[{{name}}]._latlng.lng,polygons[{{name}}]._mRadius]");
thispop = thispop.replace(/{{name}}/g,range.CODE); //name of the NR entity

@dceejay
Copy link
Owner

dceejay commented Apr 29, 2019

hmm - having gone someway down this path... I found the "old" measure control was broken (as it relied on Draw which I had removed... So I tried that other measure you initially mentioned - only to find it's yet another 76k library, so it would be smaller to leave Draw and the old measure in place, and just add editable for extra editing. This is all somewhat frustrating :-(

@zafrirron
Copy link
Contributor Author

You are correct!
I took the path W/O paying too much attention to library size, focusing on the features I needed...
(new measuring tool as example)...

@dceejay
Copy link
Owner

dceejay commented May 1, 2019

I have made Draw handle individual edits and added an editPoly function to help make that easier from a popup/contextmenu.

@zafrirron
Copy link
Contributor Author

zafrirron commented May 29, 2019

@dceejay Great Job...
Looking at V2.0.12 - great additional features since 1.5.3 (time were I forked and added most of these features....).
Now you gave me the merge hell....signal!
thanks again for this "super node" - in case you would like to see my use case in action

, I'd be happy to send you a link and access (pp me).

@dceejay
Copy link
Owner

dceejay commented May 29, 2019

Hah ! - well the big jump was to move to leaflet 1.4 which is where you were anyway - so hopefully some of the other addons will be easier / more compatible as we move forward.

@zafrirron
Copy link
Contributor Author

Hi @dceejay
Just added legend option to my private branch, noticed the current implementation removes and add the legend control, for each new legend insert.
Suggesting to consider revising implementation to use getContainer() Control method (instead of try catch for removing the control each time)
use case:
when setting legend multiple times, and having more controls (bottomleft positioned) removing and adding legend control will bump the legend position...

@dceejay
Copy link
Owner

dceejay commented Dec 21, 2019

PR - or example code welcome

@zafrirron
Copy link
Contributor Author

zafrirron commented Dec 21, 2019

if (cmd.hasOwnProperty("legend")) {
	if (typeof cmd.legend === "string" && cmd.legend.length > 0) {
		if (!legend.getContainer()) {							//if legend not exist create it
			legend.onAdd = function() {
				var div = L.DomUtil.create("div", "legend");
				div.innerHTML = cmd.legend;
				return div;
			};
			legend.addTo(map);
		};
		legend.getContainer().style.visibility = 'visible';     // if already exist use visibility to show/hide
		legend.getContainer().innerHTML = cmd.legend;			//  set content of legend
    } else {
		if (legend.getContainer())	legend.getContainer().style.visibility = 'hidden'; //if empty string and legend already created hide it
	}
}

@dceejay
Copy link
Owner

dceejay commented Dec 23, 2019

Excellent ! Yes I can see that is better - will implement. Thanks as always.
Happy holidays

@Slamkryp
Copy link

Suggestion.

I use worldmap for survailence/monitoring of services and i would like to be able to play a sound in the browser of the client screen if a object on the map needs attention.

@Shalvan
Copy link

Shalvan commented Sep 29, 2023

Hi @dceejay,

Thanks for a great work with this node, its outstanding :)

I have a question, would it be difficoult to add two options:

  1. Rotate the map according to point heading lighe its done in google maps when You drive a car, there is an option for true north and second north = vechicle heading.
    I found the plugin for leaflet but i dont know how to implement it to the node
    https://raruto.github.io/leaflet-rotate/examples/leaflet-rotate.html

  2. second thing is to add point height for topo maps, so i place a point by right click output node will send cords as id does now but also it will send the heihgt of that point.
    I found website using leaflet with the exact plugin i was loogin for, but same as point one i dont know how to implement it as well as what kind of plugin it is :( maybe link below will help.
    https://www.advancedconverter.com/map-tools/altitude-on-google-maps

What do You think about those options ?

@dceejay
Copy link
Owner

dceejay commented Sep 30, 2023

Hi,

  1. Rotate seems to require Leaflet 1.9. I'm currently using 1.7. I tried a simple upgrade to 1.9 but it then broke the Draw functionality (and probably some other things I didn't spot) so I'm not going to rush into this although it looks nice.

  2. In order to get height you need to call some third party service. For that you probably need an api key - though I'm not sure which one that example uses. When you drop a point on the map you get an event on the worldmap-in node with the lat and lon so you can use that to do an http request in your flow to get the altitude from whichever service provider you like and then update the point. As this requires an always on internet connection I'm not going to build it into the node as it is intended to work both on and offline. (plus if you need a subscription for an API key that would need to be personal to the user)

@Shalvan
Copy link

Shalvan commented Oct 3, 2023

Hello,

Thank You for the reply :)

according to Your answer is there a simple way i can update to leaflet 1.9 ? And try it out even if it will break my library ?

thanks also for the info with altitude measurement i will try to figure it out how can i get this measurement to work basing on your info with http get node :)

@dceejay
Copy link
Owner

dceejay commented Oct 3, 2023

I'm working on upgrading to 1.9 and replacing Draw with Geoman instead so hopefully I can add in rotation at the same time. Will be version 3.0 hopefully in a day or so.
image

@Shalvan
Copy link

Shalvan commented Oct 3, 2023

Woow that's outstanding work :D

EDIT:

I've found one solution for altitude measurement and it's free for non comercial use and has a lot of daily requests.
Maybe someone will find it usefull as i did so i'll leave link here :)

https://open-meteo.com/en/docs/elevation-api

@dceejay
Copy link
Owner

dceejay commented Oct 3, 2023

Nice find. v3 now published

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

No branches or pull requests

4 participants