Math help for creating random curved lines - math

so my problem is that to code a curve i need at minimum 3 points, a start and end point and a third (or more) for the line to curve out and not be straight anymore. i need to make random start and end points so finding the curve point has proven difficult as soon as different angles are considered as the curve does not bend smoothly anymore but still points up. if there's a formula to build an equilateral triangle out of a single line that would solve my problems right there. other solutions that come to mind would be great. been trying alot of stupid ideas for a long time to get this function to work in any random position.

If your two points are P and Q there are two choices for the other vertex R of an equileteral triangle with PQ forming one side.
You can compute these like this:
M.x = (P.x+Q.x)/2.0
M.y = (P.y+Q.y)/2.0 -- M mid point of P and Q
N.x = P.y-Q.y
N.y = Q.x-P.x -- N perpendicular to PQ, same length as PQ
s = sqrt(3.0)/2.0 -- ie sin( 60 degrees)
R.x = M.x + s*N.x
R.y = M.y + s*N.y -- one choice for R
R.x = M.x - s*N.x
R.y = M.y - s*N.y -- the other choice for R

Related

Calculate the 3rd point of an equilateral triangle from two points at any angle, pointing the "correct" way for a Koch Snowflake

Perhaps the question title needs some work.
For context this is for the purpose of a Koch Snowflake (using C-like math syntax in a formula node in LabVIEW), thus why the triangle must be the correct way. (As given 2 points an equilateral triangle may be in one of two directions.)
To briefly go over the algorithm: I have an array of 4 predefined coordinates initially forming a triangle, the first "generation" of the fractal. To generate the next iteration, one must for each line (pair of coordinates) get the 1/3rd and 2/3rd midpoints to be the base of a new triangle on that face, and then calculate the position of the 3rd point of the new triangle (the subject of this question). Do this for all current sides, concatenating the resulting arrays into a new array that forms the next generation of the snowflake.
The array of coordinates is in a clockwise order, e.g. each vertex travelling clockwise around the shape corresponds to the next item in the array, something like this for the 2nd generation:
This means that when going to add a triangle to a face, e.g. between, in that image, the vertices labelled 0 and 1, you first get the midpoints which I'll call "c" and "d", you can just rotate "d" anti-clockwise around "c" by 60 degrees to find where the new triangle top point will be (labelled e).
I believe this should hold (e.g. 60 degrees anticlockwise rotating the later point around the earlier) for anywhere around the snowflake, however currently my maths only seems to work in the case where the initial triangle has a vertical side: [(0,0), (0,1)]. Else wise the triangle goes off in some other direction.
I believe I have correctly constructed my loops such that the triangle generating VI (virtual instrument, effectively a "function" in written languages) will work on each line segment sequentially, but my actual calculation isn't working and I am at a loss as to how to get it in the right direction. Below is my current maths for calculating the triangle points from a single line segment, where a and b are the original vertices of the segment, c and d form new triangle base that are in-line with the original line, and e is the part that sticks out. I don't want to call it "top" as for a triangle formed from a segment going from upper-right to lower-left, the "top" will stick down.
cx = ax + (bx - ax)/3;
dx = ax + 2*(bx - ax)/3;
cy = ay + (by - ay)/3;
dy = ay + 2*(by - ay)/3;
dX = dx - cx;
dY = dy - cy;
ex = (cos(1.0471975512) * dX + sin(1.0471975512) * dY) + cx;
ey = (sin(1.0471975512) * dX + cos(1.0471975512) * dY) + cy;
note 1.0471975512 is just 60 degrees in radians.
Currently for generation 2 it makes this: (note the seemingly separated triangle to the left is formed by the 2 triangles on the top and bottom having their e vertices meet in the middle and is not actually an independent triangle.)
I suspect the necessity for having slightly different equations depending on weather ax or bx is larger etc, perhaps something to do with how the periodicity of sin/cos may need to be accounted for (something about quadrants in spherical coordinates?), as it looks like the misplaced triangles are at 60 degrees, just that the angle is between the wrong lines. However this is a guess and I'm just not able to imagine how to do this programmatically let alone on paper.
Thankfully the maths formula node allows for if and else statements which would allow for this to be implemented if it's the case but as said I am not awfully familiar with adjusting for what I'll naively call the "quadrants thing", and am unsure how to know which quadrant one is in for each case.
This was a long and rambling question which inevitably tempts nonsense so if you've any clarifying questions please comment and I'll try to fix anything/everything.
Answering my own question thanks to #JohanC, Unsurprisingly this was a case of making many tiny adjustments and giving up just before getting it right.
The correct formula was this:
ex = (cos(1.0471975512) * dX + sin(1.0471975512) * dY) + cx;
ey = (-sin(1.0471975512) * dX + cos(1.0471975512) * dY) + cy;
just adding a minus to the second sine function. Note that if one were travelling anticlockwise then one would want to rotate points clockwise, so you instead have the 1st sine function negated and the second one positive.

How to find points on the circumference of a arc knowing a start point, an end point and the radius?

Please see the image below for a visual clue to my problem:
I have the coordinates for points 1 and 2. They were derived by a formula that uses the other information available (see question: How to calculate a point on a circle knowing the radius and center point).
What I need to do now (separately from the track construction) is plot the points in green between point 1 and 2.
What is the best way of doing so? My Maths skills are not the best I have to admit and I'm sure there's a really simple formula I just can't work out (from my research) which to use or how to implement.
In the notation of my answer to your linked question (i.e. x,y is the current location, fx,fy is the current 'forward vector', and lx,ly is the current 'left vector')
for (i=0; i<=10; i++)
{
sub_angle=(i/10)*deg2rad(22.5);
xi=x+285.206*(sin(sub_angle)*fx + (1-cos(sub_angle))*(-lx))
yi=y+285.206*(sin(sub_angle)*fy + (1-cos(sub_angle))*(-ly))
// now plot green point at (xi, yi)
}
would generate eleven green points equally spaced along the arc.
The equation of a circle with center (h,k) and radius r is
(x - h)² + (y - k)² = r² if that helps
check out this link for points http://www.analyzemath.com/Calculators/CircleInterCalc.html
The parametric equation for a circle is
x = cx + r * cos(a)
y = cy + r * sin(a)
Where r is the radius, cx,cy the origin, and a the angle from 0..2PI radians or 0..360 degrees.

transforming coordinates from one distorted coordinate system to another

the problem is best explained with an example:
http://dl.dropbox.com/u/1013446/distortedcoordinatespace.exe
drag and drop the little red square inside the small square on the right.
it corresponds to the red square in the big quadrilateral on the left.
you can also drag the 4 corners of the big quadrilateral on the left to see how it occupies a distorted version of the space within the square.
given the absolute coordinates for the 4 points of a square and the coordinates of an arbitrary point within the square, it's simple matter to remap the point's coordinates to an arbitrary quadrilateral.
what I want is to be able to start off with an arbitrary quadrilateral, and be able to do the same thing, transforming the quadrilateral to any other 4 sided shape, but maintaining the relative distorted position of the point,
so given the 4 absolute coordinates of each of 2 irregular quadrilaterals, A and B, how can I convert the coordinates of point C given it's absolute coordinates?
also helpful, would be any terminology that I'm missing here for what these transformations would be called, because I'd like to look into them more
ok, I'm attempting to implement btilly's solution, and here's what I have so far:
#include<complex>
#define cf complex<float>
cf i=sqrt(complex<float>(-1));
cf GetZ(float x,float y)
{
return cf(x)+(cf(y)*i);
}
cf GetPathIntegral(cf p1,cf p2,cf q1,cf q2, int n)
{
cf sum;
for (int index=0;index<=n;index++)
{
cf s=cf(float(index)/float(n));
cf weight;
if (index==0||index==n)
weight=1;
else if(index%2)
weight=4;
else weight =2;
sum+=(((cf(1)-s)*q1)+(s*q2))*(p2-p1)*weight;
}
return sum/cf((3.0*(n-1.0)));
}
before I move on from here, I want to make sure I'm right so far...
also, this paragraph confused me a bit:
OK, so we can do path integrals. What
is the value of that? Well suppose we
take a random point z0 = x + iy
somewhere in our region. Suppose that
f(z) is defined on the path. Then the
Cauchy Integral Formula says that the
integral around our region (which is
the sum of 4 piecewise integrals that
we know how to do) of f(z)/(2 * π * i
* (z - z0)) is a really nice function that is going to match our original
function on the boundary.
what does the function do exactly?
(My first pass was a complicated derivation of a natural seeming formula for this. But then I realized that there is a far, far better solution. Which I would have remembered earlier if I had used Complex Analysis in the last 20 years.)
The right way to do this is to apply the Cauchy Integral Formula. With this you can map any polygon to any other polygon. If the polygons don't self-intersect, it will send the boundary to the boundary and the interior to the interior. The mapping will also have the excellent property that it is conformal, meaning that angles are preserved. By that I mean that if a pair of curves intersect in your region, then they will be mapped to a pair of curves that intersect at the same angle. (Many of Escher's drawings are based on conformal mappings.)
Enough hype. How do you do it? I'll explain it, assuming that you know absolutely nothing about complex analysis. I'll use some Calculus terms, but you should be able to follow my directions even if you don't know any Calculus at all. Since I am assuming so little, the explanation has to be kind of long. I'm sorry for that.
Every point (x, y) in the real plane can be viewed as a complex number z = x + iy. We can add and multiply complex numbers using the usual rules of algebra and the fact that i * i = -1. Furthermore note that 1 = (x + iy) * (x - iy)/(x2 + y2) so we can divide if we let 1/z = (x - iy)/(x2 + y2). We therefore have all of the usual rules of arithmetic.
But we can do better than that. We can do Calculus. In particular we can do path integrals around curves. An integral of a function along a curve is a kind of weighted average of that function over the points in that curve. You can read up on how to do it in general. But here is how to do it in this case.
Suppose that the starting region has corners P1, P2, P3, P4. The path around the region is defined by the four line segments (P1, P2), (P2, P3), (P3, P4), (P4, P1). I'll talk about how to handle the first line segment. The others are similar.
The path integral of f(z) over (P1, P2) is the integral from 0 to 1 of f((1-s)P1 + sP2)(P2 - P1). To evaluate that integral, the easiest thing to do is numerical integration using Simpson's Rule. To do this pick an odd number n and for the values s = 0, 1/n, 2/n, ..., (n-1)/n, 1 assign them weights in the pattern 1, 4, 2, 4, 2, ..., 2, 4, 1. (The end points are 1, everything else alternates between 4 and 2.) Now for each point calculate f((1-s)P1 + sP2)(P2 - P1), multiply by the weight, and add them all together. Then divide by the magic value 3 * (n-1). The result is approximately your integral. (As n grows, the error in this approximation is O(1/n4). In your case if you take n = 21 then the approximation should wind up good enough to map pixels to the right pixel, except for some pixels near the boundary. Make it a little larger, and the problematic area will get smaller. Right at the edge you'll want some multiple of the number of pixels on a side to make the error small .)
OK, so we can do path integrals. What is the value of that? Well suppose we take a random point z0 = x + iy somewhere in our region. Suppose that f(z) is defined on the path. Then the Cauchy Integral Formula says that the integral around our region (which is the sum of 4 piecewise integrals that we know how to do) of f(z)/(2 * π * i * (z - z0)) is a really nice function that is going to match our original function on the boundary. I won't get into all of the "really nice" things about it, but what I was saying above about conformal is part of it.
Now what function f do we use? Well suppose that our region is being mapped to a region with corners Q1, Q2, Q3, Q4. We want the first path piece to map to the second path piece. So we want f((1-s)P1 + sP2) to be (1-s)Q1 + sQ2. That tells us how to calculate f at all of the points we need to do our integral.
Now, you ask, how do you reverse it? That's simple. Just reverse the role of the two polygons, and calculate the reverse transformation! Which brings a really good unit test. You should define a couple of weird regions, pick a point in the middle, and verify that if you map from the first to the second and back again that you wind up close to where you started. If you pass that test, then you probably have made no mistakes.
And finally what about my general polygon claim that I made? Well we defined our path as four pieces we traversed linearly. A higher degree polygon just has more pieces to its path, but otherwise the calculation is done in exactly the same way.
found the solution. I have to say, it's much more complicated than I had expected:
assuming a square or quadrilateral has the four corners:
AB
CD
you need an interpolation factor: xt for the x axis, and yt for the y axis, so that
if you define a linear interpolation formula:
lerp(j,k,t)
{
return (t*(k-j))+j;
}
a point p within the ABCD quad is defined as:
p.x=lerp(lerp(a.x,b.x,xt),lerp(c.x,d.x,xt),yt)
and
p.y=lerp(lerp(a.y,c.y,yt),lerp(b.y,d.y,yt),xt)
then the values you need to define are xt and yt
xt= ((2* c.x* a.y) - (d.x* a.y) - (2
*a.x c.y) + (b.x c.y) - (c.x* b.y) + (a.x* d.y) - (a.y* p.x) + (c.y* p.x )+
(b.y p.x) - (d.y p.x) + (a.x p.y)
- (b.x p.y) - (c.x* p.y) + (d.x* p.y) - Sqrt(-4* ((c.x* a.y) - (d.x*
a.y) - (a.x* c.y) + (b.x* c.y) - (c.x*
b.y) + (d.x* b.y) + (a.x d.y) -
(b.x d.y))* ((c.x* a.y) - (a.x* c.y)
- (a.y* p.x) + (c.y* p.x) + (a.x* p.y) - (c.x* p.y)) + ((-2 *c.x a.y) + (d.x a.y) + (2 *a.x c.y) - (b.x
c.y) + (c.x* b.y) - (a.x* d.y) + (a.y*
p.x) - (c.y* p.x) - (b.y* p.x) + (d.y*
p.x) - (a.x* p.y) + (b.x* p.y) +
(c.x* p.y) - (d.x p.y))^2))/(2
((c.x* a.y) - (d.x* a.y) - (a.x* c.y)
+ (b.x* c.y) - (c.x* b.y) + (d.x *b.y) + (a.x *d.y) - ( b.x *d.y)))
and once you have that
yt=(p.x-lerp(a.x,b.x,('xt')))/(lerp(c.x,d.x,('xt'))-lerp(a.x,b.x,('xt')))

Minimal perpendicular vector between a point and a line

Okay so I'm trying to get a separating axis theorem algorithm to work (for collision detection) and I need to find the minimal perpendicular vector between a point and a line. I'm not asking for the minimum perpendicular distance (which I know how to find) but rather the vector that would have the same magnitude as that distance and that goes from an arbitrary point and a point on the line. I know the location of the point, a point on the line, and a unit vector giving the direction of the line.
What I tried doing was first finding the minimal distance between the point and the line.
The next part is confusing but I:
1) Found the vector between the point and the point on the line I know
2) Found the vector between the point on the line and the point on the line plus the unit vector giving the direction of the line
3) Took the cross product of these two vectors (I'll call this cross product A)
4) Took the cross product of the unit vector giving the direction of the line and the vector from cross product A (I'll call this cross product B)
5) Normalized cross product B
6) Scaled cross product B by the minimal distance
Anyways that whole attempt failed miserably. Can anyone tell me how I am supposed to find this vector?
If I understood your question correctly, I believe this is what you're looking for:
P - point
D - direction of line (unit length)
A - point in line
X - base of the perpendicular line
P
/|
/ |
/ v
A---X----->D
(P-A).D == |X-A|
X == A + ((P-A).D)D
Desired perpendicular: X-P
where the period represents the dot product and |X-A| means magnitude.
From the above figure, you have:
q = p + s --> s = q - p = q - (p2-p1) = q + p1 - p2
==> s^ = |q - p2 - p1| / |s| (unitary vector)
Also: |s| = |q| sin c = |q|sin(b-a)
b = arcsin (qy / |q|); a = arcsin( p1y / |p1| )
where: |q| = (qx^2 + qy^2)^1/2

distance from point within a polygon to polygon edge

I am working with a huge area, 7 states of forest and nonforest using the NLCD data. Within some of the forested areas is a plot (this is my master's thesis I am working on). I have stumped everyone I have asked with this large dataset but we are certain there is a resolution out there. The forest/nonforest area is a signed and discrete raster. I was able to make the forested area into polygons by subsetting out the forested area. I am not able to make the nonforest area into polygons (too large). So I was trying to get point distance (the point is within the polygon) to the edge of the forested polygon. Do you have suggestions for getting the distance of a point to the forest edge?
Well, this really does depend on a couple of things; specifically, which edge do you want? Do you want to find the nearest edge, or do you have some other criteria that you want to select an edge by (for example, cardinal direction)?
If you want to find the nearest edge, you basically want to iterate across all of the line segments the polygon defines, doing a line-segment-to-point distance calculation; this will find your distance. There's a good implementation of the algorithm in Python on this question, and there's some good description of the algorithms there.
Here is some code that output the distance from a point to an edge, wether the polygon is convex or not, CCW or not. You'll have to test for all your polygons' edges. It might be a little slow for a large set of edges.
- (double) distanceFromPoint:(yourPoint)testPoint
{
double pointX = edgePointB.x - edgePointA.x;
double pointY = edgePointB.y - edgePointA.y;
double k = pointX * pointX + pointY * pointY;
double u = ((testPoint.x - edgePointA.x) * pointX + (testPoint.y - edgePointA.y) * pointY) / k;
if (u > 1)
u = 1;
else if (u < 0)
u = 0;
double x = edgePointA.x + (u * pointX);
double y = edgePointA.y + (u * pointY);
double dx = x - testPoint.x;
double dy = y - testPoint.y;
return sqrt((dx * dx) + (dy * dy));
}
if you aren't sure that the point is within the outer polygon, test that first. Then, to test for the distance to closest forest edge, you could try something like this:
http://www.bdcc.co.uk/Gmaps/BdccGeo.js
Google has a wealth of results for 'distance from point to polygon edge'

Resources