So I need a write method to create a curve between two points, with each point having a normalized vector pointing in an arbitrary direction. I have been trying to devise such a method but haven't been able to wrap my head around the math.
Here, since a picture is worth a thousand words this is what I need:
In the picture, the vectors are perpendicular to the red lines. I believe the vectors need to be weighted the same with a weight equivalent to the distance between the points. It needs to be so that when two points are on top of each other pointing in opposite directions it still all looks like one smooth curve (top curve in the picture). Also, I need to integrate the curves to find their lengths. I don't know why I haven't been able to think of how to calculate all of this but I haven't.
Also I'm using csharp the language doesn't really matter.
Cubic Bezier will indeed achieve the requested effect. You need four control points per curve segment. Two define the endpoints and two others the directions of the tangents at the endpoints. There are two degrees of freedom left, telling how far the control points can be along the tangents.
The arc length cannot be computed analytically and you will need numerical methods. This other question gives you useful information.
Related
I need to implement connections in the form of curved lines in C# (Unity). I would like to get the result as similar as possible to the implementation in Miro.com (see screenshot).
After attaching the curve, I calculate the path of the cubic Bezier curve. For this first segment, the anchor points and offsets from the objects it connects are used. There are no problems at this stage.
Problem: When dividing the curve into segments by clicking and dragging one of the blue points of the segment (see screenshot), it is split in two in the middle. At the junction of two new curves, a new interactive (movable) point is formed for which the tangent and coordinates of the control points are unknown. I need to find the position of these control points every time the position of the interactive points changes (white points in the picture below). Moreover, the curve should not drastically change its position when dividing, not form loops, have different lengths of control point vectors (I'm not sure here) and behave as adequately as possible (like on the board in Miro).
By control points I mean 2 invisible guide points for the Bezier segment.
In black I painted the known control points, and in red those that I need to find. (Pn - interactive points, Cn - control points)
The algorithms I have tried to find them give incorrect distances and directions of control points.
The following algorithms were tested:
Interpolation from Tacent - jumps of the curve when separating, inappropriate direction and amount of indentation of control points;
Chaikin's algorithm - curve jumps during separation, creates loops;
"Custom" interpolation based on guesses (takes into account the distance to the center of the segment between the start and end points of the segment, as well as the direction between the start and end points) - has all the same problems, but looks slightly better than those above.
I suspect the solution is to chordally interpolate the points using a Catmull-Rom spline and translate the result to points for a Bezier curve. However, there are still problems with implementation.
The curves from 3DMax also look very similar. In their documentation, I found only a mention of the parametric curve.
Methods that I did not use (or did not work):
Catmull-Rom interpolation;
B-spline interpolation;
Hermitian interpolation;
De Casteljau's algorithm (although it seems not for this)
I would be immensely grateful for any help, but I ask for as much detail as possible.
Find helpful sources to understand bezier curves here and here.
To do what you want, I would give a try to the Catmull-Rom approach which I believe is much more simple than Bezier's, which is the one used in the itween asset, that is free, and you got plenty of funtionality implemented.
If you want to stick to the bezier curves and finding the control points, I will tell you what I would do to find them.
For the case of 2 control point bezier curve:
P = (1-t)P1 + tP2
To get to know the control points P1(x1,y1) and P2(x2,y2), you need to apply the equation in a known point of your curve. Take into account that the 2D equation is vectorial, so each points provides 2 equations one for x and one for y, and you got 4 unknows, x and y for each point.
So for the first node of the curve (t=0), you would have:
Px = (1-0)P1x + 0*P2x
Py = (1-0)P1y + 0*P2y
For the last point (t=1)
Px = (1-1)P1x + 1*P2x
Py = (1-1)P1y + 1*P2y
With these 4 equations I would try to achieve the control points P1 and P2. You can do it with t=0 and t=1 which are the supposed points you know of your curve and the ones that simplify the math due to the t values, but you should be able to use any as long as you know the points coords in the curve for determined t.
If the curve is a 3 control point bezier, you would need 6 equations for the 3 control points and so on.
I think that the best approach is to compound the curve of cuadratic curves composition, and calculate the control points for each chunk, but I am not sure about this.
Once maths are understood and control points achieved, In case that was successful I would try to implement that in the code.
I'm working on a school project and my goal is to recognize objects. I started with taking pictures, applying various filters and doing boundary tracing. Fourier descriptors are to high for me, so I started approximating polygons from my List of Points. Now I have to match those polygons, which all have the same amount of vertices and all sites have the same length. More particular, I have two polygons and now I have to calculate some scale of similarity. This process has to be translation, rotation and scale invariant.
I tried turning and scaling one in different ways and calculate the distance between each pair of vertices, but this is very slow.
I tried turning the polygon in a set of vectors and calculate each angle of the corners and compare them. But this is also a bit slow.
I found an article called Contour Analysis. But i find this a bit difficult. In this article, firstly all vectors of each set are interpreted as complex numbers, so we only have two vectors with complex compounds. Then the cosine of both vectors is calculated. But the cosine is also a complex number and the norm of it is always 1 if both vectors are the same. So how does it make sense to interpret a set of vectors as one vector. I don't understand this practice.
Are there any other ways to compare two polygons or sets of vectors? Or can someone explain my 3rd try or do it with normal vectors?
I hope someone can help me out :-)
If your objects are well separated, you can characterize every contour using Hu's moments.
Description and basic math of image moments is rather simple and would be suitable for school project.
While I was trying to parse and convert a Gerber RS274X file to a GDSII file, I encountered a certain problem.
If you stroke a solid circle along a certain path (a polyline),
what you get is a solid shape, which can be subsequently converted
to a closed polygon. My question would be is there a library or
reliable algorithm to automate this process,where the input would be a
string of points signifying the polyline, the output would be the
resulting polygon.
Below is an image I uploaded to explain my problem.
The shape you seek can be calculated by placing a desired number of evenly spaced points in a circle around each input point, and then finding the convex hull for each pair of circles on a line segment.
The union of these polygons will make up the polygon you want.
There are a number of algorithms that can find the convex hull for a set of points, and also libraries which provide implementations.
The algorithm you are talking about is called "Minkowski sum" (in your case, of polyline and of a polygon, approximating a circle). In you case the second summand (the circle) is convex and it means the Minkowski sum can be computed rather efficiently using so called polygon convolution.
You did not specify the language you use. In C++ Minkowski sum is available as part of Boost.Polygon or as part of CGAL.
To use them you will probably need to convert your polyline into a (degenerated) polygon by traversing it twice: forward, then backward.
Union of convex hulls proposed by #melak47 will produce correct result but much less efficiently.
I am looking for an algorithm to generate equally distributed points inside a polygon.
Here is the scenario:
I have a polygon specified by the coordinates of the points at the corners (x, y) for each point. And I have the number of points to generate inside the polygon.
For example lets say I have a polygon containing 5 points: (1, 1) ; (1, 2) ; (2, 3) ; (3, 2) ; and (3, 1)
And I need to generate 20 equally distanced points inside that polygon.
Note: Some polygons may not support equally distributed points, but I'm looking to distribute the points in a way to cover all the region of the polygon with as much consistency as possible. (what i mean is I don't want a part with a lot more points than another)
Is there an algorithm to do so? or maybe a library
I am working on a C# application, but any language is ok, since I only need the algorithm and I can translate it.
Thanks a lot for any help
The simple approach I use is:
Triangulate the polygon. Ear clipping is entirely adequate, as all you need is a dissection of the polygon into a set of non-overlapping triangles.
Compute the area of each triangle. Sample from each triangle proportionally to the area of that triangle relative to the whole. This costs only a single uniform random number per sample.
Once a point is determined to have come from a given triangle, sample uniformly over the triangle. This is itself easier than you might think.
So really it all comes down to how do you sample within a triangle. This is easily enough done. A triangle is defined by 3 vertices. I'll call them P1, P2, P3.
Pick ANY edge of the triangle. Generate a point (P4) that lies uniformly along that edge. Thus if P1 and P2 are the coordinates of the corresponding end points, then P will be a uniformly sampled point along that edge, if r has uniform distribution on the interval [0,1].
P4 = (1-r)*P1 + r*P2
Next, sample along the line segment between P3 and P4, but do so non-uniformly. If s is a uniform random number on the interval [0,1], then
P5 = (1-sqrt(s))*P3 + sqrt(s)*P4
r and s are independent pseudo-random numbers of course. Then P5 will be randomly sampled, uniform over the triangle.
The nice thing is it needs no rejection scheme to implement, so long, thin polygons are not a problem. And for each sample, the cost is only in the need to generate three random numbers per event. Since ear clipping is rather simply done and an efficient task, the sampling will be efficient, even for nasty looking polygons or non-convex polygons.
An easy way to do this is this:
Calculate the bounding box
Generate points in that box
Discard all points not in the polygon of interest
This approach generates a certain amount of wasted points. For a triangle, it is never more than 50%. For arbitrary polygons this can be arbitrarily high so you need to see if it works for you.
For arbitrary polys you can decompose the polygon into triangles first which allows you to get to a guaranteed upper bound of wasted points: 50%.
For equally distanced points, generate points from a space-filling curve (and discard all points that are not in the polygon).
You can use Lloyd’s algorithm:
https://en.m.wikipedia.org/wiki/Lloyd%27s_algorithm
You can try the {spatialEco} package (https://cran.r-project.org/web/packages/spatialEco/index.html)
and apply the function sample.poly (https://www.rdocumentation.org/packages/spatialEco/versions/1.3-2/topics/sample.poly)
You can try this code:
library(rgeos)
library(spatialEco)
mypoly = readWKT("POLYGON((1 1,5 1,5 5,1 5,1 1))")
plot(mypoly)
points = sample.poly(mypoly, n= 20, type = "regular")
#points2 = sample.poly(mypoly, n= 20, type = "stratified")
#another type which may answer your problem
plot(points, col="red", add=T)
The easy answer comes from an easier question: How to generate a given number of randomly distributed points from the uniform distribution that will all fit inside a given polygon?
The easy answer is this: find the bounding box of your polygon (let's say it's [a,b] x [c,d]), then keep generating pairs of real numbers, one from U(a,b), the other from U(b,c), until you have n coordinate pairs that fit inside your polygon. This is simple to program, but, if your polygon is very jagged, or thin and skewed, very wasteful and slow.
For a better answer, find the smallest rotated rectangular bounding box, and do the above in transformed coordinates.
Genettic algorithms can do it rather quickly
Reffer to GENETIC ALGORITHMS FOR GRAPH LAYOUTS WITH GEOMETRIC CONSTRAINTS
You can use Force-Directed Graph for that...
Look at http://en.wikipedia.org/wiki/Force-based_algorithms_(graph_drawing)
it defiantly can throw you a bone.
I didn't try it ever,
but i remmember there is a possiblity to set a Fix for some Vertices in the Graph
Your Algorithm will eventually be like
Create a Graph G = Closed Path of the Vertices in V
Fix the Vertecies in place
Add N Verticies to the Graph and Fully connect them with Edges with equal tension value 1.0
Run_force_graph(G)
Scale Graph to bounded Box of
Though it wont be absolute because some convex shapes may produce wiered results (take a Star)
LASTLY: didn't read , but it seems relevant by the title and abstract
take a look at Consistent Graph Layout for Weighted Graphs
Hope this helps...
A better answer comes from a better question. Suppose you want to put a set of n watchtowers to cover a polygon. You could see this as an optimization problem: find the 2n coordinates of the n points that will minimize a cost function (or maximize a value function) that fits your goal. One possible cost function could calculate, for each point, the distance to its closest neighbor or the boundary of the polygon, whichever is less, and calculate the variance of this sequence as a measure of "non-uniformity". You could use a random set of n points, obtained as above, as your initial solution.
I've seen such a "watchtower problem" in some book. Algorithms, calculus, or optimization.
#Youssef: sorry about the delay; a friend came, and a network hiccuped.
#others: have some patience, don't be so trigger-happy.
I have a List of 2D points. What's an efficient way of iterating through the points in order to determine whether the list of points are in a straight line, or curved (and to what degree). I'd like to avoid simply getting slopes between smaller subsets. How would I go about doing this?
Thanks for any help
Edit: Thanks for the response. To clarify, I don't need it to be numerically accurate, but I'd like to determine if the user has created a curved shape with their mouse and, if so, how sharp the curve is. The values are not too important, as long as it's possible to determine the difference between a sharp curve and a slightly softer one.
If you simply want to know if all your points fit more or less on a curve of degree d, simply apply Lagrange interpolation on the endpoints and d-2 equally spaced points from inside your array. This will give you a polynomial of degree d.
Once you have your curve, simply iterate over the array and see how far away from the curve each point is. If they're farther than a threshold, your data doesn't fit your degree d polynomial.
Edit: I should mention that iterating through values of d is a finite process. Once d reaches the number of points you have, you'll get a perfect fit because of how Lagrange interpolation works.
To test if it's a straight line, compute the correlation coefficient. I'm sure that's covered on wikipedia.
To test if it's curved is more involved. You need to know what kind of curves you expect, and fit against those.
Here is a method to calculate angle: Calculate Angle between 2 points using C#
Simply calculate angle between each and every point in your list and create list of angles, then compare if angles list values are different. If they are not different then it means it's straight line, otherwise it's curve...
If it's a straight line then angle between all points has to be a same.
The question is really hazy here: "I'd like to avoid simply getting slopes between smaller substes"
You probably want interpolation a-la B-splines. They use two points and two extra control points if memory serves me. Implementations are ubiquitous since way back (at least 1980's). This should get you underway
Remember that you'll probably need to add control points to make the curve meet the endpoints. One trick to make sure those are reached is to simply duplicate the endpoints as extra controlpoints.
Cheers
Update Added link to codeproject
it would appear that what I remember from back in the 80's could have been Bezier curves - a predecessor of sorts.