I want to get a "sub-Polyline" of a given polyline that is determined by a certain start and end point (in meters).
For example I have a polyline that is 500 meters (build using 30 coordinates (not seperated in same spaces)) and I want to color the line between meter 200 and 300 in a different color. Is it possible using Leaflet functions?
Take a look at the LineStringSelect plugin here: https://github.com/w8r/L.Control.LineStringSelect
With the demo (click in 2 different locations on the polyline):
https://w8r.github.io/L.Control.LineStringSelect
So basically you are asking "If I have a polyline and a distance value, what is the point along the polyline with the desired length-distance to the line's starting point"?
This algorithm has been covered a multitude of times, e.g.:
http://www.postgis.org/docs/ST_Line_Interpolate_Point.html, http://www.postgis.org/docs/ST_Line_Substring.html
http://turfjs.org/docs/#along
https://github.com/IvanSanchez/Leaflet.Polyline.SnakeAnim
The algorithm is always the same: divide the polyline/linestring into segments, measure length of each segment, locate the point, apply direct interpolation in the segment that the point is in.
Keep in mind that geometry in a 2D cartesian plane is different than geometry in the surface of a geoid, particularly when it comes to measuring distances. Do a bit of research on GeographicLib and its methods for manipulating geodesic lines.
To your question «Is it possible using Leaflet functions?», the answer is «no, Leaflet does not implement this algorithm». The easiest way for you should be to read the source code of the mentioned Leaflet plugins in the answers, or use the along() method from the Turf library.
Related
At the moment I am trying to figure out a nice way to split up a polygon that has multiple points inside (in some cases more than 10k) into smaller ones that will have 100 points each (the max number of points within a small polygon will be dynamic, provided by the user, in this example I am using 100).
Please note that the 100 is not written in stone but should be respected (ex 95-105 points should be ok as when we try to balance things, sometimes we can not achieve perfect balance!)
Is there any algorithm that could help me achieve the above request?
The language I am using is javascript and so far I've been using turf.js and my data is in geoJSON format.
I am adding an image to highlight my goal:
In the image you can see that I already have a centroid point of my polygon (I used this point to make a voronoi diagram already and inside this polygon I have multiple point-features.
My goal is to split this polygon to smaller polygons that will hold only 100 points inside them.
(hope that clarifies my goal further)
Creating a map similar to the one found here:
https://www.plantmaps.com/interactive-california-2012-usda-plant-zone-hardiness-map.php
Have all the data needed.
Create polygons around each one without distance inbetween. No overlapping or similar.
Drawing it all by hand on geojson.io, seems impossible.
I want to create polygons around each [point] and make sure there is no distance between them.
What you're describing here is a tessellation. Depending on your data, you might opt for a regular tessellation (i.e. creating a grid of squares or hexagons, paying a modicum of attention to the units of your coordinate system) or the well-known-among-GIS-people Voronoi tessellation. Note that a Voronoi tessellation created over a regular grid of points will result in a regular grid of polygons.
There are plenty of tools for Voronoi tessellations. For javascript and GeoJSON, my tool of choice would be turf.js's voronoi module.
Here are some things to consider:
creating polygon from a point is simple enough. For example you use the point as the center of a regular polygon and devide 2PI by the number of sides and step through the points to create the polygon. But, what is the radius? That depends on the projection you are using. I happen to use OpenLayers and really like this map control. It's default projection it EPSG:3857. So, the coordinates are already in meters - so easy. But if your points are in long/lat then you have to do some math. it may be easier to transform to a different projection temporarily. An opensource library that is really nice for gis calculations if you need one is Turf.
You mentioned also about having non-overlapping polygons? Well, in this case you will have a lot of gaps if you use regular polygons. To have non-overlapping polygons with, as you put it no distance between them is an interesting constraint. Now you are dealing with different shaped polygons. And an algorithm for handling that is pretty intense. I know that MapInfo GIS has a feature for adjusting polygons to be non-overlapping. But, in a JavaScript environment with GeoJSON, you are probably talking about server side logic for this.
That map you are looking at looks like it is using Leaflet with svg overlays.
I am working on a data set of coordinate points(many dots in area) either (x,y) or (lat,lon) which fall into multiple categories. What I am trying to do is get polygons of areas from those points which are called concave or non-convex as far as I know, but also those polygons have to be next to each other with no gaps between them.
These are the initial points(example)
This is the approximate result I am aiming for
Real life example would be European geopolitical map, if you had all of the addresses of all countries and wanted to get area of each country as a polygon and end up with a map.
I have come across many questions related to getting polygons from set of points, but were unable to use it in my scenario. If you need any more information please let me know. Thank you for your help.
You could use a Voronoi tesselation of the input space. Instead of having point you have sets of points though. Basically, you take each point in space, and look at the closest point to it. It then gets the same "class" as that point. For smoother outputs you could look at a k majority out of N nearest points. It would mean working with a bitmap image rather than 2D coordinates, but you'd get something workable. You could then use simpler image manipulation tricks (edge detection, binary set operations etc to get just the edges, and then perhaps superimpose those on the image).
As an alternative, you could run a convex hull algorithm on each data set, and then try to fix the overlap areas.
What is the neatest (code design) and most per-formant way of getting an array of points for an arc (polyline), for the purpose of animating using Cesium's timer/clock.
Variable inputs include (start/end location), height (highest point) from earth's surface and number of points for drawing.
I'm currently using a polyline collection, so the answer should describe how to generate the points for existing polylines or convert to a different approach.
I would also need the arc (color) to fadeIn or fadeOut to opacity 0.
Multiple arcs may be added or removed from the collection per second. Each arc will have different start and end points
The start and end location should have height 0 (touching the earth).
(For Cesium version b26)
Just to be sure I understand your question, you have a bunch of polylines on a map and you want to get a bunch of data points along the line for use in animating the something along the path. I'll also assume you want geodesic lines/arcs for the polylines rather than the straight lines that are normally drawn on Mercator maps as geodesic lines actually follow the spatially accurate path of the polyline i.e. the same path a plane would take. If this is the case then take a look at this blog post: http://alastaira.wordpress.com/2011/06/27/geodesics-on-bing-maps-v7/ This post describes how to calculate data points along the geodesic path of a polyline.
CesiumJS includes several spline functions that can be used. One of the easier ones to use that an accomplish what you want with just three points is the Catmull-Rom Spline:
http://cesiumjs.org/Cesium/Build/Documentation/CatmullRomSpline.html
You will need to produce a middle point. To do this you can take a mean of the lat/lon coordinates and add a large height. Because of the spline used and the low number of points, it does end up looking a little egg shaped. The benefit to this is that you can ask the spline object for an arbitrary number of points, so the arc can be as smooth as you want. Just don't forget to add the first and last points to the array returned by the spline as those are omitted.
There are other types of splines, but I found the Catmull-Rom spline the easiest to use. You can search the CesiumJS documentation for some of the other included splines.
I've been looking into the same thing (minus the time aspect) and I found Cesium.EllipsoidGeodesic(start, end, ellipsoid), which allows you to get points at fractions of the path. It seems to me that you can choose the fraction based on the distance and calculate regular points using the result.
https://cesiumjs.org/Cesium/Build/Documentation/EllipsoidGeodesic.html
I haven't tried it yet, but it's on my list of things to do.
I have an exercise in problem solving for those who like that kind of thing. I'm working on a mapping application that uses Google Maps. A user first enters a series of coordinates and a "radius". The user then requests either a line or an area be plotted. The plots are taking place on Google Maps using polygons. In other words, given the blue line (or area) defined by the blue points and a distance, calculate the red points and draw the red polygon where the edges are of the given distance away from the user-provided edges:
I have managed to get this to work in "most" situations by calculate forward and reverse bearings, then finding the points with a bearing 90 degrees off these in the appropriate direction. For the arcs I just calculated the location points along that arc at 5 degree intervals. In the case of the inside of an acute angle, I determine where the two lines intersect and use that point, but this fails miserably sometimes when the cross-track distance at that point is greater than the radius that was provided.
I'm hoping someone knows of an easier way? Maybe one that works all the time regardless of the ratio of the cross-track to radius distances? Or maybe a library already exists to do this?
I hope what I'm trying to do makes sense... It's hard to put in words. Maybe if I had the words a search would have been helpful even.
Well, the answer turned out to be simpler than I thought. It took me back to a lesson I was taught during CompSci 101 almost 15 years ago:
"Use existing libraries whenever possible."
Once I found out (via googling), that what I'm looking for isn't called an "offset" or a "scale" but is actually called a "buffer" in GIS computing, it was simple. There are some great libraries like Clipper by Angus Johnson that can do it, but I wanted something JavaScript specific.
That brought me to arcGIS's GeometryService. They even have a Google Maps version but it's only API v2. Luckily, there's an official, unsupported version I found via the arcGIS forums that works with GMaps API v3.
So, my solution was to use that, called arcgislink, and it's buffer function works perfectly with Google Maps LatLng points, Google Maps Polygons/Polylines, and any of the standard arcGIS types. Anyone else needing to do this with Google Maps, I highly recommend looking at their libraries.
In the general setting, this problem is quite difficult because it is a global one (you cannot just solve locally, at each polygon vertex but just handling the two incoming edges). And also uneasy because it involves circular arcs.
There is a solution which is quite unefficient but safe: assume you have a general polygon union algorithm (like http://gvu.gatech.edu/~jarek/graphics/papers/04PolygonBooleansMargalit.pdf); you will add inflated versions of every edge one by one (every time a rectangle and two half-disks approximated by polygons), together with the original polygon for closed shapes.
For the sake of efficiency, you can design a "sweepline" algorithm that works by slicing the plane with horizontal lines at every "event point", i.e. segment/arc endpoints and arc apexes, so that the configuration in every slice is simpler. Do you see what I mean ?
BTW, what do you call the "cross-track distance" ?