Polar curve equation with plus-minus sign (±) in Javascript - javascript
I am trying to draw polar curves on HTML canvas using Javascript. What should I do when I want to convert plus-minus sign (±)?
Example: Watt's curve
Below is what I tried. Since I need to get value of r, I enclose entire equation with square root, also I use it's absolute value, otherwise I get null for trying to get square root if number is negative. Following code draws something that looks like a polar curve, but not Watt's curve.
var a = 1;
var b = 1;
var c = 2;
r = Math.sqrt(Math.abs(Math.pow(b, 2) - Math.pow(a * Math.sin(t) * Math.sqrt(Math.abs(Math.pow(c, 2) - Math.pow(a, 2) * Math.pow(Math.cos(t), 2), 2)), 2) ));
I get similar deviations of expected results with other equations containing plus-minus sign (ones without it work fine), so I suppose the problem is that I wrongly 'translate' this symbol. What do I do wrong?
It looks like there is an incorrect multiplication of a squared theta with the inner square root (Math.sin(t) * Math.sqrt(...)).
To plot the equation, convert the plus-minus sign into two equations:
var a = 1;
var b = 1;
var c = 2;
var b2 = Math.pow(b, 2);
var asint = a * Math.sin(t);
var sqroot = Math.sqrt(Math.pow(c, 2) - Math.pow(a, 2) * Math.pow(Math.cos(t), 2), 2);
var r = Math.sqrt(b2 - Math.pow(asint + sqroot, 2));
// now plot r
r = Math.sqrt(b2 - Math.pow(asint - sqroot, 2));
// now plot r again
The Math.abs() shouldn't be necessary.
Related
Create a function that finds the points distanced r units by two lines
I have two lines defined by two points each(P1, P2, P3, P4). I'd like to find the 2 points(X0, Y0) that are distanced r units from both lines. I found a way but I think it's too long to solve(too difficult for me) and maybe there's one shorter(https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line). my way: Without solving it it's impossible tp create the function I'd like to have the solution not the sistem. Example(I'd like to find the yellow points knowing r): Thanks. (Sorry for my terrible english)
Variant A: represent your lines in general form a * x + b * y + c = 0 d * x + e * y + f = 0 with normalized coefficients (divide equation by Sqrt(a^2+b^2)) For this form point lies at distance r if |a * x + b * y + c| = r |d * x + e * y + f| = r Open absolute value brackets with all possible +/- sign combinations and get 4 linear systems for 4 possible points Variant B: 1) Find unit direction vectors of both lines da and db 2) Find intersection point C of two lines 3) Calculate angle between lines as Fi = atan2(da.cross.db, da.dot.db) 4) Find unit bisector vector b = (da + db).Normalized 5) Find perpendicular bisector pb = (-b.y, b.x) 6) Get needed points as C + b * r / Sin(Fi/2) C - b * r / Sin(Fi/2) C + pb * r / Cos(Fi/2) C - pb * r / Cos(Fi/2)
Program to find line segment and bezier curve intersection
Consider the given image of the soccer field As you can see in the image the various ball movements, some of them are curved(i.e. in case of (1), (2), (3) in the image)) and some may not(i.e a line(4)), so I need to find the intersection points of ball path with goalline and sideline. Sometimes the input may not be a curve(i.e a line) like in case of (4) given image I have written a program, I have no clue what is wrong - is this right way to solve this kind of program. if yes then, how to convert bezier curve into an equation for better solving considering the given as beizer curve eqaution -> a(x*x) + b*x + c and line segment equation -> y = y1 + m(x-x1) //maxCurvedPoint is the topmost of the curve var getIntersectionPoint = function (room, ballFromPosition, ballToPosition, maxCurvePoint) { var linepoints = [[m1,n1], [m2, n2], [m3, n3], [m4, n4]]; //converting three points(ballFromPosition, maxCurvePoint, ballToPosition) into the quadratic equation (Bezier curve) --(1) //getting the equation of the line segment using the linepoints --(2) //equating (1) and (2) and getting a quadratic equation and solving and finding intersection points return intersectionPoint; } // solves //(-b(+-)sqrt(b*b - 4ac)/2ac) function solve(a, b, c) { //check curve intersects line or not if((Math.pow(b, 2) - (4 * a * c)) >= 0) { result1 = (-1 * b + Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a); result2 = (-1 * b - Math.sqrt(Math.pow(b, 2) - (4 * a * c))) / (2 * a); return [result1, result2]; } return []; } Can anyone help me with this? Also is the most curve point can be called vertex of the curve?
I find it easier to work with vector equations since the algebra will be rotation-invariant (hence you don't have to re-write the code to deal with e.g. a "horizontal" parabola). 1. Curve representation + Intersection test Consider a quadratic Bezier curve with endpoints A, C, control point B and parameter t: And an infinite line with source O, direction D and parameter s: Equating P and R give a pair of quadratic simultaneous equations, which can be re-arranged to eliminate s and find the parabolic parameter t: Solve this quadratic equation for t, and only accept real roots in the range [0, 1]. This ensures that any intersection point is always on the segment itself. 2. Dealing with line segments You can also restrict the intersection point to a line segment, by computing s from t using the equations above, and limiting its value - which equals the distance along the line from O if D is normalized. 3. Computing the control point B Note that a general value of the control point B will not give a symmetrical parabola. To compute B for a general symmetric curve: Defining the variables: M: midpoint of AB n: clockwise normal to the direction AC q: signed bulge distance - absolute value is the distance from M to the midpoint of the curve k: signed distance from M to B A surprisingly simple result. 4. Sample C# (-style) code public static Vector2[] computeIntersection ( Vector2 A, Vector2 C, double q, // parabola segment Vector2 O, Vector2 P // line segment ) { // quadratic solve double[] solve(double a, double b, double c) { double d = b * b - 4.0 * a * c; if (d < 0.0) // imaginary roots - no intersection at all return null; if (d > 0.0) // two distinct real roots { double sd = Math.Sqrt(d); return new double[2] { (-b + sd) / (2.0 * a), (-b - sd) / (2.0 * a) }; } else // only one (line segment is tangent to curve) { return new double[1] { -b / (2.0 * a) }; } } // cross product (in-case undefined) double cross(Vector2 i, Vector2 j) { return i.x * j.y - i.y * j.x; } // validity check for t and s bool valid(double v) { return (v >= 0.0) && (v <= 1.0); } // compute control point B Vector2 E = C - A; Vector2 M = 0.5 * (A + C); Vector2 N = (new Vector2(E.y, -E.x)).normalize(); Vector2 B = M + (2.0 * q) * N; // solving for t Vector2 D = P - O; bool useX = Math.Abs(D.X) > Math.Abs(D.Y); double[] T = solve(cross(A + C - 2.0 * B, D), cross(B - A, D) * 2.0, cross(A - O, D)); if (T == null) return null; Vector2[] I = new Vector2[2]; int c = 0; for (int i = 0; i < T.Length; i++) { // check if t is within curve range double t = T[i]; if (!valid(t)) continue; // solve for s and check if is within line range double u = (1 - t) * (1 - t); double v = 2 * t * (1 - t); double w = t * t; double s = useX ? ((u * A.X + v * B.X + w * C.X - O.X) / D.X) : ((u * A.Y + v * B.Y + w * C.Y - O.Y) / D.Y); if (!valid(s)) continue; // compute the corresponding intersection point I[c++] = O + s * D; } // only return valid solutions if (c == 0) return null; Array.Resize(ref I, c); return I; }
If you translate and rotate all the endpoints in such a way that the line segment becomes (0, 0)-(d, 0), the problem simplifies. Let the control points be (Xk, Yk), k= 0, 1, 2. The intersections with the axis X are obtained by solving for t the quadratic equation Y0 (1-t)² + 2 Y1 t(1-t) + Y2 t² = 0. The corresponding abscissas are given by X0 (1-t)² + 2 X1 t(1-t) + X2 t² = 0. You can check if these belong to the interval [0, d]. Then apply the reverse rotation and translation. Addendum: intersection of two quadratic Beziers The vector equation of one of the curves can be written P = P0 (1 - t)² + 2 P1 t (1 - t) + P2 t² = P0 + 2 (P1 - P0) t + (P0 - 2 P1 + P2) t². If you apply the affine change of coordinates such that the reference frame becomes (P0, P1 - P0, P0 - 2 P1 + P2), the equation simplifies to X = 2t Y = t² which is the implicit equation X² = 4Y. Now by applying the same transform to the control points of the second curve and plugging the parametric equations in the above, you get a quartic equation in t (square of a quadratic polynomial on one side, quadratic polynomial on the other). There are closed-form formulas for the roots of a quartic equation, and there can be four of them. After selecting the real roots in [0, 1], you evaluate the t parameter of the first curve and also check membership in [0, 1]. Don't forget to restore the original coordinates.
Get coords of the intersection of the line in the plane
I have a canvas with this params: width = 400, height = 400 and have a line passing through the point cursor[x1,y1] at an angle Q (in degree) I need get all coords of the intersection of the line in the plane and write it to array. Now i use this equation: y - y1 = k * (x - x1) to check all point I use this code: var rad = Q * Math.PI/180; for (ctrY = 0; ctrY < 400; ctrY += 1) { for (ctrX = 0; ctrX < 400; ctrX += 1) { if ( (ctrY - cursor.y) === ~~(Math.tan(rad) * (ctrX - cursor.x)) ) { z.push([ctrX, ctrY]); } } } For example when 0 < Q < 90 and cursor[x1,y1] = [200,200] z.length = 0 and it's not correct. Where i'm wrong? Maybe there is a more convenient algorithm? P.S. Sorry for my english
Seems you need line rastering algorithm. Consider Bresenham algorithm. You can also look at DDA algorithm
I imagine an algorithm like this. (I only consider the case when 0 < Q < 90). First I will want to calculate the points where the line will intersect the Ox and Oy axes, considering the origin (0,0) point the upper left corner and if we imagine that the negative x and y values are respectively to the left and to the top of this point. Let x2 and y2 be the values where the line will intersect Ox and Oy. We want to calculate these values. We now have a system with 2 unknown variables (x2 and y2): Math.tan(rad) = (y1 -y2)/x1 and Math.tan(rad) = y1/(x1-x2). We can deduct these equations by drawing the line on the coordinate system and analyzing a bit. If we solve the system of equations we find something like: x2 = (x1*y1 -x1 * x1 * Math.tan(rad)/(2 * y1-x1)) and y2= y1- x1 * Math.tan(rad) (These need to be verified, I haven't double checked my calculus). A linear equation can be defined by the formula y = a*x + b and in our case a = x2 and b = y2. We can then calculate the points like this: for (xIdx = 0; xIdx < 400; xIdx += 1) { var ctrX = xIdx; var ctrY = x2 * ctrX + y2 //todo: replace with the respective calculated variables x2 and y2(we could also define two functions in js) and proper rounding z.push([ctrX, ctrY]); } I'm not sure if I'm 100% accurate but I hope you understand my idea.
Why does my Perlin Noise Generator make this squiggly pattern?
I've started learning about perlin noise generation, and I wanted to try to make my own generator in JavaScript. To get me started, I've been following along with this youtube tutorial. to try and copy their basic implementation. I've also been reading this article. I've provided a jsFiddle of my implementation, which shows what I'm doing and what the output is. Instead of the smoothly-flowing, bubbling noise I see in the youtube tutorial, I get tightly-constricted black squiggles. Here's a picture: Here's my generator code: var p = [151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, 151,160,137,91,90,15, 131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23, 190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33, 88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166, 77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244, 102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196, 135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123, 5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42, 223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9, 129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228, 251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107, 49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254, 138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180] function generatePerlinNoise(x, y){ // Determine gradient cell corners var xi = Math.floor(x) & 255; var yi = Math.floor(y) & 255; var g1 = p[p[xi] + yi]; var g2 = p[p[xi + 1] + yi]; var g3 = p[p[xi] + yi + 1]; var g4 = p[p[xi + 1] + yi + 1]; // Get point within gradient cell var xf = x - Math.floor(x); var yf = y - Math.floor(y); // Get dot products at each corner of the gradient cell var d1 = generateGradient(g1, xf, yf); var d2 = generateGradient(g2, xf - 1, yf); var d3 = generateGradient(g3, xf, yf - 1); var d4 = generateGradient(g4, xf - 1, yf - 1); var xFade = fade(xf); var yFade = fade(yf); var x1Interpolated = linearInterpolate(xFade, d1, d2); var x2Interpolated = linearInterpolate(xFade, d3, d4); var noiseValue = linearInterpolate(yFade, x1Interpolated, x2Interpolated); return noiseValue; } function generateGradient(hash, x, y){ switch(hash & 3){ case 0: return x + y; case 1: return -x + y; case 2: return x - y; case 3: return -x - y; default: return 0; } } // This is the fade function described by Ken Perlin function fade(t){ return t * t * t * (t * (t * 6 - 15) + 10); } function linearInterpolate(amount, left, right){ return ((1-amount) * left + (amount * right)) } I'm utilizing the generator function by dividing the pixel x and y values by my canvas height, and scaling by a frequency variable: var freq = 12; var noise = generatePerlinNoise((x/canvas.offsetHeight)*freq, (y/canvas.offsetHeight)*freq); noise = Math.abs(noise); I'm currently just using the noise value to generate a greyscale color value: var blue = Math.floor(noise * 0xFF); // Scale 255 by our noise value, // and take it's integer portion var green = Math.floor(noise * 0xFF); var red = Math.floor(noise * 0xFF); data[i++] = red; data[i++] = green; data[i++] = blue; data[i++] = 255; The point of this for me is to learn more about noise generation and javascript. I've tried to think through the problem and made some observations: There are no visible artifacts, so it seems like my fade function is working fine. There don't seem to be any repeating patterns, so that's a good sign. I go generate a complete range of values in the greyscale - not just black and white. The general issue seems to be how the gradient at each pixel affects its neighbors: Mine seem to clump together in snake-like ropes of fixed widths. It seems like the gradient vector options supplied and the permutation table used to randomly-ish select them would govern this, but mine are an exact copy from the tutorial: The same 4 vectors each pointing into a quadrant at 45 degrees, and the standard permutation table. This leaves me stumped as to figuring out what the cause is. My general suspicions boil down to: I've messed up the algorithm somewhere in a subtle way that I keep overlooking. (Most likely) There's a subtle difference in the way JavaScript does something that i'm overlooking. (Maybe) I'm generating noise correctly, but incorrectly applying the result to the RGB values used in my canvas image data. (Least likely) I'd really like to get to the bottom of this. Thanks in advance for your help! :) Also: I DO think this pattern is cool, and this is a learning exercise, so if anyone can share insight into why I'm getting this pattern specifically, that'd be great!
How can I generate random points on a circles circumference in javascript
I am trying to write a function that will randomly return an (x,y) co-ordinates around a given circumference so if I have a point that's at (0,0) (being the center of the div) how can I write a function that randomly places other entities that appear among the outer edge of a circle. All I need is the equation i know it has something to do with getting the distance from the center to the circumference edge just no idea how to calculate it and randomize it so it looks good.
Just get a random angle: var angle = Math.random()*Math.PI*2; Then x = Math.cos(angle)*radius; y = Math.sin(angle)*radius; Done.
You can also avoid computing sin and cos via this formula: // Generate 2 random numbers in the [-1, 1] interval const u = Math.random()*2 - 1; const v = Math.random()*2 - 1; const u2 = u*u; const v2 = v*v; const r = u2 + v2; if (r <= 1) { x = (u2 - v2)/r; y = (2*u*v)/r; } if r > 1 you need to re-try, but the expected number of tries until you get a valid point is ~1.27. So this algorithm is very efficient and avoids the complex trigonometric functions. Visualization: https://observablehq.com/#kunigami/circles-and-randomness