Bounding trapezoid / line on interval - line

I am looking for a way to find the line (red) that optimally (least area) bounds a set of 2d points (black stars).
I am having trouble googling, but the following terms seem related:
minimum bounding line on interval
minimum bounding cone / pyramid / trapezoid
this is a simplified case of finding a convex hull or polygon -- three sides are already known.
chi2 minimization / linear regression
Pareto front
If I assume the blue line is defined between (xmin, 0) and (xmax, 0), then I can parameterize the line with two points, at (xmin, ymin) and (xmax, ymax), where ymin and ymax are unknown parameters.
I need to adhere to
yi <= (xi - xmin) * (ymax - ymin) / (xmax - xmin) + ymin
for every point (xi, yi). This trivially implies ymin must be larger than the yi of the xmin point, and ymax must be larger than the yi of the xmax point.
I want to minimize the area:
min: A = |ymax - ymin| / 2 * (xmax - xmin)
which simplifies to
min: (ymax - ymin)^2
Do I need to solve this with (non-?)linear programming, exhaustive search (test the n*(n-1)/2 line combinations) or is there a easy and fast algorithmic solution?
I also know that the line will have a positive slope for my problem. I guess I can use that to eliminate points with a Pareto domination criterion: Any point (xi,yi) can remove a point (xj,yj) if xj > xi but yj < yi. That is, points that are right and below of another point can be removed. After that, testing n*(n-1)/2 line combinations may not be so bad.

Related

Subdivide multi segmented Cubic Bezier spline

First of let me apologies for a bad English and probably not very straight forward question, as I am not really sure how to call it.
I have a multi segmented Cubic Bezier curve In After Effects, it is is defined by 5 vertices with IN & OUT tangents. My task is to subdivide it into N small linear chunks in Java Script.
EDIT submited more info.
Given a multi segmented Cubic Bezier spline defined by 5 points with In & Out tangents, I need to get a linear representation of it. Where N is number of linear segments, defined by user.
Cubic Bezier Spline:
Segment1: P0, P0out, P1in, P1;
Segment2: P1, P1out, P2in, P2;
Segment3: P2, P2out, P3in, P3;
Segment4: P3, P3out, P4in, P4;
Expected output:
N = 1: linear spline with 2 anchors representing entire shape;
N = 2: linear spline with 3 anchors representing entire shape;
N = 3: linear spline with 4 anchors representing entire shape;
N = 4: linear spline with 5 anchors representing entire shape;
...
N = 8: linear spline with 9 anchors representing entire shape;
distance(L0,L1) = distance(L1,L2) = distance(L2,L3) = ... = distance(L-n, Ln)
In example image I use 4-segmented spline, where segment length is equal to one another - this is just easier to draw to explain my task. But in real project those segments will not be equal, and there will be more then 4 segments total.
I have looked at de Casteljau method, but as I can understand, it works with one segment spline. My math skills are dusty, so I am not really sure if I can use de Casteljau in my example.
This is conceptually straight forward, although it might involve quite a bit of code for reasons explained a little later on. What you're trying to do is flatten a (cubic) poly-Bezier, so let's start with that:
Individual cubic Bezier curves are generated by four points: a start point, a control point that determines the tangent at the start point, an end point, and a control point that determines the tangent at the end point. The curve, then, is a plot of the cubic Bezier function:
Bx(t) = p1.x × (1-t)³ + 2 × p2.x × (1-t)² × t + 2 × p3.x × (1-t) × t² + p4.x × t³
By(t) = p1.y × (1-t)³ + 2 × p2.y × (1-t)² × t + 2 × p3.y × (1-t) × t² + p4.y × t³
A single Bezier curve is plotted over the interval t=[0,1], so a poly-Bezier of N segments is plotted over a total interval N × [0,1].
First, the simple case: simple flattening. Bezier curves are non-linear curves and so let's first not bother to enforce "same length for each of the line segments". Given an N-segment poly-Bezier:
S = number of segments we want
points = empty list
for (s = 0):(s = S):(step = S/N):
v = s * step
segmentid = floor(v)
segment = polycurve.segments[segmentid]
t = v % 1
points.push(
segment.pointAt(t)
)
We now have all the points we need, and we just connect them with lines. Done.
However, Bezier curves are non-linear curves, so flattening in this way does not yield equidistant segments in the slightest. If we want to do that, we need to work with distance along the curve rather than t values.
S = number of segments we want
points = empty list
for (s = 0):(s = S):(step = S/N):
v = s * step
segmentid = floor(v)
segment = polycurve.segments[segmentid]
distanceRatio = v % 1
t = segment.getTforDistanceRatio(distanceRatio)
points.push(
segment.pointAt(t)
)
This will work exactly as you want, but getTforDistanceRatio is the hard part, because what we're doing here is reparameterizing the curve for distance, rather than time, and that is a very hard mathematical problem (for which no general symbolic solution exists). The cheapest way to do this is using a Lookup Table (LUT), which is explained in the link above, for "distance along the curve".
The de Casteljau method is used to compute a point on the Bezier curve and also obtain the control points for the two subdivided curves in the process. So, yes you should be able to use de Cateljau method to evaluate as many points as you want on a Bezier curve if you know the control points.
From the picture you show and the fact that your "cubic Bezier spline" takes in/out tangents as input, I think your spline is actually "cubic Hermite spline", in which each segment is indeed a cubic Bezier curve. You can convert each segment of your spline to a cubic Bezier curve, then use de Cateljau method to evaluate as many points as you want, then connect these points by straight lines.

Initial velocity vector for circular orbit

I'm trying to create a solar system simulation, and I'm having problems trying to figure out initial velocity vectors for random objects I've placed into the simulation.
Assume:
- I'm using Gaussian grav constant, so all my units are AU/Solar Masses/Day
- Using x,y,z for coordinates
- One star, which is fixed at 0,0,0. Quasi-random mass is determined for it
- I place a planet, at a random x,y,z coordinate, and its own quasi-random mass determined.
Before I start the nbody loop (using RK4), I would like the initial velocity of the planet to be such that it has a circular orbit around the star. Other placed planets will, of course, pull on it once the simulation starts, but I want to give it the chance to have a stable orbit...
So, in the end, I need to have an initial velocity vector (x,y,z) for the planet that means it would have a circular orbit around the star after 1 timestep.
Help? I've been beating my head against this for weeks and I don't believe I have any reasonable solution yet...
It is quite simple if you assume that the mass of the star M is much bigger than the total mass of all planets sum(m[i]). This simplifies the problem as it allows you to pin the star to the centre of the coordinate system. Also it is much easier to assume that the motion of all planets is coplanar, which further reduces the dimensionality of the problem to 2D.
First determine the magnitude of the circular orbit velocity given the magnitude of the radius vector r[i] (the radius of the orbit). It only depends on the mass of the star, because of the above mentioned assumption: v[i] = sqrt(mu / r[i]), where mu is the standard gravitational parameter of the star, mu = G * M.
Pick a random orbital phase parameter phi[i] by sampling uniformly from [0, 2*pi). Then the initial position of the planet in Cartesian coordinates is:x[i] = r[i] * cos(phi[i]) y[i] = r[i] * sin(phi[i])
With circular orbits the velocity vector is always perpendicular to the radial vector, i.e. its direction is phi[i] +/- pi/2 (+pi/2 for counter-clockwise (CCW) rotation and -pi/2 for clockwise rotation). Let's take CCW rotation as an example. The Cartesian coordinates of the planet's velocity are:vx[i] = v[i] * cos(phi[i] + pi/2) = -v[i] * sin(phi[i])vy[i] = v[i] * sin(phi[i] + pi/2) = v[i] * cos(phi[i])
This easily extends to coplanar 3D motion by adding z[i] = 0 and vz[i] = 0, but it makes no sense, since there are no forces in the Z direction and hence z[i] and vz[i] would forever stay equal to 0 (i.e. you will be solving for a 2D subspace problem of the full 3D space).
With full 3D simulation where each planet moves in a randomly inclined initial orbit, one can work that way:
This step is equal to step 1 from the 2D case.
You need to pick an initial position on the surface of the unit sphere. See here for examples on how to do that in a uniformly random fashion. Then scale the unit sphere coordinates by the magnitude of r[i].
In the 3D case, instead of two possible perpendicular vectors, there is a whole tangential plane where the planet velocity lies. The tangential plane has its normal vector collinear to the radius vector and dot(r[i], v[i]) = 0 = x[i]*vx[i] + y[i]*vy[i] + z[i]*vz[i]. One could pick any vector that is perpendicular to r[i], for example e1[i] = (-y[i], x[i], 0). This results in a null vector at the poles, so there one could pick e1[i] = (0, -z[i], y[i]) instead. Then another perpendicular vector can be found by taking the cross product of r[i] and e1[i]:e2[i] = r[i] x e1[i] = (r[2]*e1[3]-r[3]*e1[2], r[3]*e1[1]-r[1]*e1[3], r[1]*e1[2]-r[2]*e1[1]). Now e1[i] and e2[i] can be normalised by dividing them by their norms:n1[i] = e1[i] / ||e1[i]||n2[i] = e2[i] / ||e2[i]||where ||a|| = sqrt(dot(a, a)) = sqrt(a.x^2 + a.y^2 + a.z^2). Now that you have an orthogonal vector basis in the tangential plane, you can pick one random angle omega in [0, 2*pi) and compute the velocity vector as v[i] = cos(omega) * n1[i] + sin(omega) * n2[i], or as Cartesian components:vx[i] = cos(omega) * n1[i].x + sin(omega) * n2[i].xvy[i] = cos(omega) * n1[i].y + sin(omega) * n2[i].yvz[i] = cos(omega) * n1[i].z + sin(omega) * n2[i].z.
Note that by construction the basis in step 3 depends on the radius vector, but this does not matter since a random direction (omega) is added.
As to the choice of units, in simulation science we always tend to keep things in natural units, i.e. units where all computed quantities are dimensionless and kept in [0, 1] or at least within 1-2 orders of magnitude and so the full resolution of the limited floating-point representation could be used. If you take the star mass to be in units of Solar mass, distances to be in AUs and time to be in years, then for an Earth-like planet at 1 AU around a Sun-like star, the magnitude of the orbital velocity would be 2*pi (AU/yr) and the magnitude of the radius vector would be 1 (AU).
Just let centripetal acceleration equal gravitational acceleration.
m1v2 / r = G m1m2 / r2
v = sqrt( G m2 / r )
Of course the star mass m2 must be much greater than the planet mass m1 or you don't really have a one-body problem.
Units are a pain in the butt when setting up physics problems. I've spent days resolving errors in seconds vs timestep units. Your choice of AU/Solar Masses/Day is utterly insane. Fix that before anything else.
And, keep in mind that computers have inherently limited precision. An nbody simulation accumulates integration error, so after a million or a billion steps you will certainly not have a circle, regardless of the step duration. I don't know much about that math, but I think stable n-body systems keep themselves stable by resonances which absorb minor variations, whether introduced by nearby stars or by the FPU. So the setup might work fine for a stable, 5-body problem but still fail for a 1-body problem.
As Ed suggested, I would use the mks units, rather than some other set of units.
For the initial velocity, I would agree with part of what Ed said, but I would use the vector form of the centripetal acceleration:
m1v2/r r(hat) = G m1 m2 / r2 r(hat)
Set z to 0, and convert from polar coordinates to cartesian coordinates (x,y). Then, you can assign either y or x an initial velocity, and compute what the other variable is to satisfy the circular orbit criteria. This should give you an initial (Vx,Vy) that you can start your nbody problem from. There should also be quite a bit of literature out there on numerical recipes for nbody central force problems.

Draw line at center of circle with angle in objective-c

I want to draw line at the center of circle with fixed size. Please check the image, it will explain everything. I have P1 center of the circle and P2 somewhere at the border of the circle. P1 will always remain fixed and P2 will keep changing with mouse move and it will be any point at circle's border. Now, I want to draw line with fixed length shown in green color. I want to find the (x1,y1) and (x2,y2) with fixed distance, every time P2 get changed, i want to draw green line facing towards P2.
Hope, image explains everything, in short i need following.
angle between P1 and P2.
Draw green line with fixed distance with angle at the center of the circle.
Thanks
Since you (apparently) want the green line to be perpendicular to the red line, you don't need to compute the angle between p1 and p2. Rotating a vector by 90˚ is quite trivial.
I assume you have p1 and p2 as CGPoint (or NSPoint) variables.
First let's compute the vector from p1 to p2:
CGPoint p1p2 = CGPointMake(p2.x - p1.x, p2.y - p1.y);
Next we'll compute a vector that is perpendicular to the p1->p2 vector:
CGPoint p1p2Perp = CGPointMake(p1p2.y, -p1p2.x);
Now let's find the length of the perpendicular vector:
CGFloat radius = hypot(p1p2Perp.x, p1p2Perp.y);
Note that if the radius of the circle is constant, you can just use that instead of computing it. If you're on iOS, use hypotf instead of hypot.
So now we can “normalize” the perpendicular vector, making it have length 1, by dividing its coordinates by its length:
p1p2Perp.x /= radius;
p1p2Perp.y /= radius;
Next we can multiply it by half of the desired length of the green line. I assume you have the desired length of the green line in a constant or variable named greenLineLength.
p1p2Perp.x *= greenLineLength / 2;
p1p2Perp.y *= greenLineLength / 2;
Now we can create a path for the green line. I assume your CGContextRef is in a variable named gc:
CGContextBeginPath(gc);
CGContextMoveToPoint(gc, p1.x - p1p2Perp.x, p1.y - p1p2Perp.y);
CGContextAddLineToPoint(gc, p1.x + p1p2Perp.x, p1.y + p1p2Perp.y);
You can stroke the path however you like. For example:
CGContextSetRGBStrokeColor(gc, 0, 1, 0, 1);
CGContextSetLineWidth(gc, 2);
CGContextSetLineCap(gc, kCGLineCapRound);
CGContextStrokePath(gc);
The angle between the two, according to your question, is always perpendicular -- 90˚ or π/2 radians. You can get the angle of the red segment using atan2(); then subtract M_PI_2 for the angle of the green one.
From there, you are trying to find two points on the circumference of a circle whose diameter is the length of the segment. You can think about this in polar coordinates (r, theta) and convert to Cartesian (x, y):
x = (segment_length / 2) * cos(theta)
y = (segment_length / 2) * sin(theta)
Add M_PI to theta to get the other endpoint.

Can someone explain the logic behind these expressions used to calculate nonorthogonal collisions?

I'm following an example in a Processing book describing how to calculate nonorthogonal collisions (a ball bouncing on a non-horizontal plane), however, I don't really understand the logic behind these four expressions.
float groundXTemp = cosine * deltaX + sine * deltaY;
float groundYTemp = cosine * deltaY - sine * deltaX;
float velocityXTemp = cosine * velocity.vx + sine * velocity.vy;
float velocityYTemp = cosine * velocity.vy - sine * velocity.vx;
They're supposed to be calculating temporary values for the ground coordinates and velocity of the ball to calculate the collision as if it were orthogonal. Cosine and sine are the values for the rotation of the ground, and the velocity variables are the velocity of the ball. I can't grok what the expressions are actually doing to make the ground horizontal, and the book doesn't explain it very well. Any help would be appreciated.
These expressions are traditional expressions of a rotation. If you take a point (x,y), and you rotate it by an angle theta, you will obtain a point (x',y') with coordinates :
x' = cos(theta)*x - sin(theta)*y
y' = sin(theta)*x + cos(theta)*y
In your case, let's say that theta is the angle of the ground, you want to do the inverse rotation (so with angle -theta) to make the ground horizontal, this is why the sign is different from the formula above (cos(-theta) = cos(theta) and sin(-theta) = -sin(theta)).
If you want to go into details, check : http://en.wikipedia.org/wiki/Rotation_matrix

collision detection function in objective-c/core graphics

Is there a built-in function to detect collision between
two circles?
I have used CGRectIntersectsRect(rect1,rect2) to
find the intersection between two rectangles.But if I want to know in which axis x or y they intersect how will i find it?
Is there a built-in function or do you have any other ideas?
If they're circles, the collision point (if it exists) will lie on the line connecting their centres, and the impulse to each will act in the direction from that point to the circle's centre.
Assuming centres (x1, y1) and (x2, y2) and radii r1 and r2, the circles collide when
(x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) = (r1 + r2) * (r1 + r2)
This is just your basic Pythagorean theorem.
In most cases -- undoubtedly including yours -- collision detection is an approximate rather than analytic business. Which is to say, you move your objects by small steps and test for overlap, rather than solving the motion equations for the exact instant of contact. So instead of looking for the above case, you will use an inequality like this:
(x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) <= (r1 + r2) * (r1 + r2)
When this evaluates as true, the collision has basically already occurred, and you have two choices: you can work backwards to calculate exactly when and where that happened, or you can assume that your time steps are small enough that the time you notice an overlap is close enough to the moment of contact that it will serve as a reasonable substitute. Again, it is very likely this is what you want to do, but be aware that this is quite inexact: if your objects are moving quickly with respect to their size then it may look quite wrong, or even miss collisions altogether (sometimes humorously referred to as "quantum tunneling").
Since the circles probably overlap a little, you need to determine a proxy contact point -- let's call it (xp, yp). Since it's an approximation, there are several ways you might to choose to calculate it, but one reasonable choice might be:
xp = x1 + (x2 - x1) * r1 / (r1 + r2)
yp = y1 + (y2 - y1) * r1 / (r1 + r2)
That is, on the line between the centres, at a distance in proportion to the radii. If the overlap is small, this should be pretty close to the real collision point. If it's big, you're in trouble anyway.
Ignoring any rotation, each circular object will experience a push from this collision point towards its own centre. Eg, the push on object 1 will act in the direction (x1 - xp, y1 - yp).
To work out what the effect will be -- ie, how the objects will move afterwards -- you need to take into account the mass of each object and apply the law of conservation of momentum. Read up on elastic collisions and possibly, if you want to simulate collisions that are not perfectly elastic, the coefficient of restitution.
In the special case that the objects are the same size and mass and the collision is perfectly elastic -- which seldom occurs in real life but slightly more often in games -- you can break down the velocity of each object into the components parallel and perpendicular to the line between the centres, and then just swap the parallel components between the two objects.
If they're circles, the test is trivial. Just compare the distance between their centers to the sum of their radii.