I'm trying to find the inflection points relative to given axis (green line) given a series of (blue) points that form a path. We can see from the diagram below there are two inflection points (pink lines), or places where the path changes direction relative to the task axis.
The tricky part is that the direction of the axis may change, so it has to work going in any direction. My first attempt takes 2 consecutive points along the path, gets the direction between them, and then compares it to the direction of the axis.
Skipping a few boring steps (like recording previous points), the pseudocode looks like this:
foreach point cur_point in path:
direction = prev_point - cur_point
(normalize direction)
relative_direction = dir_towards_axis - direction
(normalize relative direction)
if the sign of either x or y has changed between relative_direction and prev_relative_direction
# we have found an inflection point
Unfortunately this does not work. Any pointers on where I'm going wrong?
To find needed points, you can detect sign change of cross product between axis and current curve direction (orientation/handedness test).
axis_direction = axis_end - axis_start = B - A
....
direction = cur_point - prev_point
cross = cross_product(direction, axis_direction) =
direction.x * axis_direction.y - direction.y * axis_direction.x
Note: If your curve is continuous and analytic, closed-form formula might exist
Have a look at https://pomax.github.io/bezierinfo/#aligning - the idea is to align your baseline with the x or y axis, by moving every point by {-p1.x, -p1.y} and then rotating all the coordinates that define your curve (provided your curve is invariant to affine transforms!) so that your last coordinate lies on the axis (for which you use the atan2 function to find the angle to rotate by, which virtually all programming languages come with).
Once axis-aligned, you can perform whatever analysis "with respect to the axis" you need done.
Related
Given this simple setup:
Node Tree
Viewport Preview
How can I align the planes instances such that the y axis of each plane is parallel to the curve, and the x axis of the planes are parallel to the ground plane (x and Y axis)?
I've tried various combinations with "Align Eular to Vector" node, but as soon as the curve does not face a specific axis the planes get tilted and the alignment to ground plane is lost.
any suggestions?
So after some research I found a solution to my own question. I'm posting it in case anyone else needs to find this out.
Note that I'm not a mathematician and there might be a shorter solution (or specific nodes that I'm not aware of that can perform some of the steps). Also note that this is a solution for instances on a straight line which is what I was aiming for, I didn't test this setup on a curved line but my guess is that it will not work.
For that you'll need to perform step 3 for every point or something like that.
Ok here we go:
Generate instances on a line with the instance on point node.
Auto orient the instances on the z axis with the align Euler to vector node based on the normal of the line.
Calculate a vector between 2 points on the line (which point is not important since the line is straight but the order of the subtraction does!). To calculate the vector from point 1 to point 2 you'll have to subtract point 1 from point 2 (like so: point 2 - point 1).
Calculate the angle between the new vector and the vector of the ground plane [0,0,1]. to do that use this formula:
θ = arccosine ( dot product/ ( length(v1) * length(v2) ) ).
Calculate the complementary angle which is 90 degrees - θ
*** convert 90 to radians of course
rotate the instances on x axis by the result value.
Node Tree
Result
If there is a shorter/easier solution, let me know.
I am working on something that can fit a set of Bezier curves through a set of points. I've been able to do this using the curve fitting method from Pomax. The problem with this method is that it cannot fit a low order Bezier curve through a line that has many inflections. Therefore in order to make this work, I need to be able to get a piecewise cubic-bezier by splitting the curve at its inflection points and then running the curve fitting algo from there.
The problem is that I'm not sure how to find the derivative of a set of points that have no clear function. I guess I could always calculate the slope of the secant line instead of the tangent line, but I'm not sure if that would work well.
Does anybody have any better ideas on how to find the inflection points of a set of points?
Inflex point is dividing curve where the curvature winding goes from CW to CCW or vice versa. So first detect the winding.
Assuming 2D case...
If your points are { p0,p1,p2,...,p(n-1) } then winding at p(i) is the sign of z coordinate of 3D cross product of 2 consequent tangents:
w(i) = cross (
( p(i).x-p(i-1).x , p(i).y-p(i-1).y , 0)
( p(i+1).x-p(i).x , p(i+1).y-p(i).y , 0)
).z
So if p(i) is inflex then:
w(i)*w(i-1) < 0
The problem is if w(i) or w(i-1) is zero such winding must be skipped or specially handled.
I start this thread asking for your help in Excel.
The main goal is to determine the coordinates of the intersection point P=(x,y) between two curves (curve A, curve B) modeled by points.
The curves are non-linear and each defining point is determined using complex equations (equations are dependent by a lot of parameters chosen by user, as well as user will choose the number of points which will define the accuracy of the curves). That is to say that each curve (curve A and curve B) is always changing in the plane XY (Z coordinate is always zero, we are working on the XY plane) according to the input parameters and the number of the defining points is also depending by the user choice.
My first attempt was to determine the intersection point through the trend equations of each curve (I used the LINEST function to determine the coefficients of the polynomial equation) and by solving the solution putting them into a system. The problem is that Excel is not interpolating very well the curves because they are too wide, then the intersection point (the solution of the system) is very far from the real solution.
Then, what I want to do is to shorten the ranges of points to be able to find two defining trend equations for the curves, cutting away the portion of curves where cannot exist the intersection.
Today, in order to find the solution, I plot the curves on Siemens NX cad using multi-segment splines with order 3 and then I can easily find the coordinates of the intersection point. Please notice that I am using the multi-segment splines to be more precise with the approximation of the functions curve A and curve B.
Since I want to avoid the CAD tool and stay always on Excel, is there a way to select a shorter range of the defining points close to the intersection point in order to better approximate curve A and curve B with trend equations (Linest function with 4 points and 3rd order spline) and then find the solution?
I attach a picture to give you an example of Curve A and Curve B on the plane:
https://postimg.cc/MfnKYqtk
At the following link you can find the Excel file with the coordinate points and the curve plot:
https://www.mediafire.com/file/jqph8jrnin0i7g1/intersection.xlsx/file
I hope to solve this problem with your help, thank you in advance!
kalo86
Your question gave me some days of thinking and research.
With the help of https://pomax.github.io/bezierinfo/
§ 27 - Intersections (Line-line intersections)
and
§ 28 - Curve/curve intersection
your problem can be solved in Excel.
About the mystery of Excel smoothed lines you find details here:
https://blog.splitwise.com/2012/01/31/mystery-solved-the-secret-of-excel-curved-line-interpolation/
The author of this fit is Dr. Brian T. Murphy, PhD, PE from www.xlrotor.com. You find details here:
https://www.xlrotor.com/index.php/our-company/about-dr-murphy
https://www.xlrotor.com/index.php/knowledge-center/files
=>see Smooth_curve_bezier_example_file.xls
https://www.xlrotor.com/smooth_curve_bezier_example_file.zip
These knitted together you get the following results for the intersection of your given curves:
for the straight line intersection:
(x = -1,02914127711195 / y = 23,2340949174492)
for the smooth line intersection:
(x = -1,02947493047196 / y = 23,2370611219553)
For a full automation of your task you would need to add more details regarding the needed accuracy and what details you need for further processing (and this is actually not the scope of this website ;-).
Intersection of the straight lines:
Intersection of the smoothed lines:
comparison charts:
solution,
Thank you very much for the anwer, you perfectly centered my goal.
Your solution (for the smoothed lines) is very very close to what I determine in Siemens NX.
I'm going to read the documentation at the provided link https://pomax.github.io/bezierinfo/ in order to better understand the math behind this argument.
Then, to resume my request, you have been able to find the coordinates (x,y) of the intersection point between two curves without passing through an advanced CAD system with a very good precision.
I am starting to study now, best regards!
kalo86
I've spent a good amount of time getting intersections working correctly between various 2D shapes (circle-circle, circle-tri, circle-rect, rect-rect - a huge thanks to those who've solved such problems from which I drew my solutions from) for a simple project and am now in the process of trying to implement an triangle-AABB intersection test.
I'm a bit stuck however. I've tried searching online and thinking it through however I've been unable to get any ideas. The thing that's given me the biggest issue at the moment is checking whether the edges of triangle (which is an isosceles btw) intersect the rectangle when no vertexes lie within the rectangle.
Any ideas how I could get this working?
EDIT: To give a bit more insight as to stages as I think they should occur:
1 - Check to see if any vertexes lie with in the rectangle (this part is easy). If yes, collision, otherwise continue.
2 - Check to see if any edges are intersecting the rectangle. This is where I'm stuck. I have little idea how to implement this.
I'd calculate a collection of equations which define the 4 lines of the rectangle, and then solve against a collection of equations which define lines of the triangle.
For example, gievn a rectangle with lowest point (x1, y1) and one side having a gradient of g, one of the lines of the rectangle will be y = gx + y1. Find equations to represent the other 3 sides of the rectangle as well.
The lines which form the sides of the triangle will be calculated similarly. The equation for a line given two points is
y - y1 = (x - x1) * (y2 - y1)/(x2 - x1)
If there are any possible x & y values that satisy all 7 equations then you have an intersection.
edit: I realise that although this is a simple algorithm it might be tricky to code; another option is to calculate formulae for the intervals that form each edge (essentially lines with a min and max value) and solve these.
I want an efficient algorithm to fill polygon with an Image, I want to fill an Image into Trapezoid. currently I am doing it in two steps
1) First Perform StretchBlt on Image,
2) Perform Column by Column vertical StretchBlt,
Is there any better method to implement this? Is there any Generic and Fast algorithm which can fill any polygon?
Thanks,
Sunny
I can't help you with the distortion part, but filling polygons is pretty simple, especially if they are convex.
For each Y scan line have a table indexed by Y, containing a minX and maxX.
For each edge, run a DDA line-drawing algorithm, and use it to fill in the table entries.
For each Y line, now you have a minX and maxX, so you can just fill that segment of the scan line.
The hard part is a mental trick - do not think of coordinates as specifying pixels. Think of coordinates as lying between the pixels. In other words, if you have a rectangle going from point 0,0 to point 2,2, it should light up 4 pixels, not 9. Most problems with polygon-filling revolve around this issue.
ADDED: OK, it sounds like what you're really asking is how to stretch the image to a non-rectangular shape (but trapezoidal). I would do it in terms of parameters s and t, going from 0 to 1. In other words, a location in the original rectangle is (x + w0*s, y + h0*t). Then define a function such that s and t also map to positions in the trapezoid, such as ((x+t*a) + w0*s*(t-1) + w1*s*t, y + h1*t). This defines a coordinate mapping between the two shapes. Then just scan x and y, converting to s and t, and mapping points from one to the other. You probably want to have a little smoothing filter rather than a direct copy.
ADDED to try to give a better explanation:
I'm supposing both your rectangle and trapezoid have top and bottom edges parallel with the X axis. The lower-left corner of the rectangle is <x0,y0>, and the lower-left corner of the trapezoid is <x1,y1>. I assume the rectangle's width and height are <w,h>.
For the trapezoid, I assume it has height h1, and that it's lower width is w0, while it's upper width is w1. I assume it's left edge "slants" by a distance a, so that the position of its upper-left corner is <x1+a, y1+h1>. Now suppose you iterate <x,y> over the rectangle. At each point, compute s = (x-x0)/w, and t = (y-y0)/h, which are both in the range 0 to 1. (I'll let you figure out how to do that without using floating point.) Then convert that to a coordinate in the trapezoid, as xt = ((x1 + t*a) + s*(w0*(1-t) + w1*t)), and yt = y1 + h1*t. Then <xt,yt> is the point in the trapezoid corresponding to <x,y> in the rectangle. Now I'll let you figure out how to do the copying :-) Good luck.
P.S. And please don't forget - coordinates fall between pixels, not on them.
Would it be feasible to sidestep the problem and use OpenGL to do this for you? OpenGL can render to memory contexts and if you can take advantage of any hardware acceleration by doing this that'll completely dwarf any code tweaks you can make on the CPU (although on some older cards memory context rendering may not be able to take advantage of the hardware).
If you want to do this completely in software MESA may be an option.