Algorithm to decompose Polygons into lineStrings (Headlands from Plots) - javascript

Consider the following polygon (an agricultural plot)
From this polygon, I would like to extract the "headlands" of the plot, being the consecutive lines (sides) of the polygon (Wikipedia) used for turning on the field. While often only the rows running perpendicular to the lay of the field are considered, I need all sides of the polygon.
Here, a consecutive line means any set of coordinates, where the angle between any two coordinates of the set is not larger than a value X (e.g 30 degrees).
For the given example, the resulting headlands should look like the following:
I wrote a small algorithm trying to accomplish this, basically checking the angle between two coordinates and either pushing the given coordinate to the existing lineString if the angle is below X degrees or creating a new lineString (headland) if not.
Check out the following Gist
However, in some cases corners of a field are rounded, therefore may consist of many coordinates within small distances of each other. The relative angles then may be less than the value X, even though the corner is too sharp to actually be cultivated without turning.
In order to overcome that issue, I added an index that increases whenever a coordinate is too close for comparison, so that the next coordinate will be checked against the initial coordinate. Check out the following Gist.
This works for simple plots like the one in the example, however I am struggling with more complex ones as the following.
Here, the bottom headland is recognised as one lineString together with the headland on the right, even though optically a sharp corner is given. Also, two coordinates in the upper right corner were found to be a separate headland even though they should be connected to the right headland. The result should therefore yield in the following:
What I would like to know is if there is an approach that efficiently decomposes any polygon into it's headlands, given a specific turning angle. I set up a repo for the code here, and an online testing page with many examples here if that helps.

Related

How to scatter shapes without overlapping while keeping them close together?

here's something I have been trying to figure out but couldn't because I suck at math or statistics :S
There are a lot of ways to scatter i.e. a bunch of divs or a p5 canvas element (sized slightly differently) without them overlapping - this is an example of doing it with circles. But if the total number of those elements is low, then there’s a chance that the cluster will be very far apart from each other, and the overall density can be quite inconsitent. Is there a way to scatter similarly sized rectangles without overlapping and remains a minimum distance from each other, but is never too far away?
Ideally something like this:
And not this (which is the outcome if the only criteria is "no overlapping"):
You could translate to the centre before drawing the shapes and then give them a distance from the centre using the random function where the max value for random will be calculated according to the total number of elements. While doing this, you may also check for overlapping and call the random function again if any two objects overlap.

Threejs draw a shape from just points

Given a list of Vector3s in no order, I would like to create an ordering of the elements such that when I draw a Shape from those points, I will be outlining the shape without ever going across its face.
How would you do this? I think the first thing is to always pick the point closest to you, but what if more than one point have exactly the same distance from a point?
Let's call the point we're on x, and a potential "neighbor" (point whose distance to x is minimal) y where there can be multiple ys.
I've thought about these two approaches:
Find the center of mass by averaging out the positions of the points, then make sure that going from x to y never goes through the center. This approach has many problems like 1. it's not guaranteed to cross the CoM or 2. imagine a fidget spinner with just two circles, and one much smaller than the other. When tracing the smaller bit, the center of mass is never crossed (or come close to), but we might still ran into problems
Randomly pick any other three points, and make sure that y is not within the triangle created. But there are cases where y is the correct choice, but still falls within the triangle (imagine a shape one of whose edge is created by two tangent circles).
Any help would be much appreciated!

Merge two svg path elements programmatically

I am rendering a map out of SVG paths (using jVectormap).
There are cases where one region has to be merged with the neighboring region.
Unfortunately both regions don't touch each other and I have to interpolate to fill the space in between.
jVectormap uses very simple SVG paths with M to set the the absolute startpoint and l to connect relative points.
Does any of the SVG libraries cover such an operation?
I haven't tried this, but you may get around it by running the converter at jVectormap with the following parameters:
--buffer_distance=0
--where="ISO='region_1' OR ISO='region_2'"
Where region_1 and region_2 are the two regions that you need to merge.
Solving the problem this way also means that the generated SVG paths are true to the original coordinates, whereas a following fix may lead to some (probably minor) inconsistencies.
This might not be the kind of answer you're looking for, but using Raphael.js you could loop over the entire length of the path of one region getPointAtLength(), comparing it with all points of the second region. If the coordinates are closer than n pixels from any coordinates on the second region and the previous coordinates weren't, than that could be regarded a "glue" point. You would then jump to the second regio and start looping over it, if the next point is still closer than n points, than go in the opposite direction, if still closer change direction and go farther along the path till finding a point that's farther away from the original region than n pixels. Continue looping in that direction till once again finding a new "glue" point, where once again you will switch to the original region in the manner described and all points which weren't covered in this final loop could be discarded (or you could simply create a new shape based on the points you came across whilst looping over the length of the original region.
True enough, it's not the easiest script to make, but it should be quite do-able I believe, especially when you can use a function like getPointAtLength to find the points between the defined svg points (though you need to only 'record' the defined points, and that's sort of the hard path as Raphael.js doesn't excitedly have any functions which would help with this, still even that shouldn't be too hard to match up by hand (in code of course)).

Plotting mathematical functions without rendering artefacts

I don't think there's a good answer to this, but I'd like to find out if there's a better way to do this.
I need to plot a mathematical function, which is nearly flat at one end of the display, and nearly vertical at the other end. The bottom left quadrant of a circle would be a good model. I can auto-generate as many points as required.
The problem is, I can't do this without all sorts of artefacts.
I haven't tried Bezier fitting; I don't think this would be even close. My understanding is that Bezier is for one-off manually-constructed pretty graphics, and not for real curve-fitting.
That leaves polylines. There are only 2 things I can do with polylines - I can select the line length (in other words, the number of points I auto-generate), and I can disable anti-aliasing (setAttributeNS(null, "shape-rendering", "crisp-edges").
If I generate lots of points, then I get jaggies everywhere, and the result is unusable. It can also look very much like it's oscillating, which makes it appear that I've incorrectly calculated the function. The anti-aliasing doesn't make any difference, since it doesn't operate across point boundaries.
The only solution I've got is to draw fewer points, so that it's obvious that I'm drawing segments. It's no longer smooth, but at least there are no jaggies or oscillation. I draw this with the default anti-aliasing.
Any ideas?
Edit:
It seems like the only answer to this is actually Bezier curve fitting. You have to preprocess to find the parameters of the required segments, and then plot the results. Google comes up with a number of hits on curve fitting with Beziers.
You have the mathematical function, and can therefore generate as many points as you need.
I assume the problem is that because you do not know the output resolution (SVG is device independent) you do not know how many points to generate. Otherwise you could just create a polyline where each line is approximately 1 pixel long.
Fitting your mathematical function to a bezier curve is (probably) not going to get a perfect match - just like a circle cannot be matched perfectly by a cubic bezier curve. And I think the task of fitting your function to a bezier curve would not be trivial (I've never done this).
Could you rather output your mathematical function to a canvas element? Then you could write some javascript code to plot your mathematical function dependant on the output resolution. Similar to how a graphics system renders a Bezier curve.
Do you know how graphics systems render Bezier curves? They approximate the bezier curve with a polyline, and then measure the error difference between the polyline and the bezier curve. If the difference is greater than a certain tolerance - where the tolerance is determined by the output resolution - the bezier is subdivided and the process repeated for each bezier curve. When the difference between beziers and polylines is below the tolerance, the polylines are drawn. http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Computer_graphics
I suppose you want to draw y=f(x) over a certain interval [a,b]
A classical solution is to take N points uniformly distributed over [a,b], to compute f over these points and draw lines (or polynoms).
It of course doesn't work in your case, since y is nearly vertical in certain area. But why don't you take more points in these areas (and less points where the function is nearly horizontal) ?
You can compute the derivative of your function (or approximate this derivative with (f(x+h)-f(x))/h and h small) and determine the step between two successive points with this derivative

how to "sort" polygons 3d?

I am still working on my "javascript 3d engine" (link inside stackoverflow).
at First, all my polygons were faces of cubes, so sorting them by average Z was working fine.
but now I've "evolved" and I want to draw my polygons (which may contain more than 4 vertices)
in the right order, namely, those who are close to the camera will be drawn last.
basically,
I know how to rotate them and "perspective"-ize them into 2D,
but don't know how to draw them in the right order.
just to clarify:
//my 3d shape = array of polygons
//polygon = array of vertices
//vertex = point with x,y,z
//rotation is around (0,0,0) and my view point is (0,0,something) I guess.
can anyone help?
p.s: some "catch phrases" I came up with, looking for the solution: z-buffering, ray casting (?!), plane equations, view vector, and so on - guess I need a simple to understand answer so that's why I asked this one. thanks.
p.s2: i don't mind too much about overlapping or intersecting polygons... so maybe the painter's algorthm indeed might be good. but: what is it exactly? how do I decide the distance of a polygon?? a polygon has many points.
The approach of sorting polygons and then drawing them bottom-to-top is called the "Painter's algorithm". Unfortunately the sorting step is in general an unsolvable problem, because it's possible for 3 polygons to overlap each other:
Thus there is not necessarily any polygon that is "on top". Alternate approaches such as using a Z buffer or BSP tree (which involves splitting polygons) don't suffer from this problem.
how do I decide the distance of a polygon?? a polygon has many points.
Painter's algorithm is the simplest to implement, but it works only in very simple cases because it assumes that there is only a single "distance" or z-value for each polygon (which you could approximate to be the average of z-values of all points in the polygon). Of course, this will produce wrong results if two polygons intersect each other.
In reality, there isn't a single distance value for a polygon -- each point on the surface of a polygon can be at a different distance from the viewer, so each point has its own "distance" or depth.
You already mentioned Z-buffering, and that is one way of doing this. I don't think you can implement this efficiently on a HTML canvas, but here's the general idea:
You need to maintain an additional canvas, the "z-buffer", where each pixel's colour represents the z-depth of the corresponding pixel on the main canvas.
To draw a polygon, you go through each point on its surface and draw only those points which are closer to the viewer than any previous objects, as indicated by the z-buffer.
I think you will have some ideas by investigating BSP tree ( binary spaces partition tree ), even if the algo will require to split some of your polygon in two.
Some example could be find here http://www.devmaster.net/articles/bsp-trees/ or by google for BSP tree. Posting some code as a reply is, in my opinion, not serious since is a complex topic.

Categories

Resources