Cubic Bézier: What to do when leading coefficient is zero? - c++

I use a fairly standard method to retrieve the monic polynomial coefficients from a cubic Bézier curve's control points:
std::array<double, 3> getBezierCubicCoefficients( const std::array<double, 4>& bezier )
{
const auto d = 1.0 / ( bezier[3] - 3*bezier[2] + 3*bezier[1] - bezier[0] );
return { ( 3*bezier[2] - 6*bezier[1] + 3*bezier[0] ) * d,
( 3*bezier[1] - 3*bezier[0] ) * d,
bezier[0] * d };
}
This works fine 99% of the time, but as you have probably guessed, fails under certain coordinates which cause d's divisor to evaluate to zero - causing d to evaluate to Inf.
My question is: what to do under this circumstance?
Have I actually got a quadratic curve in disguise, and should I perform degree reduction instead? Should I just fudge the numbers so d is very large, but won't cause Infs? (I really hope that isn't the answer).

As you probably already know, the monomic coefficients c can be calculated from the Bezier coefficients by multiplying with the following matrix:
/ 1 -3 3 -1 \
| 3 -6 3 |
(c0 c1 c2 c3) = (b0 b1 b2 b3) | 3 -3 |
\ 0 1 /
If the resulting c3 = -b0 + 3b1 - 3b2 + b3 is zero, then you'll get a quadratic polynomial (at most). In degenerate cases, other coefficients can yield 0, too. In the edge case, you end up with a constant.

Related

2 Intersection Lines

i have this code to find the status of 2 lines there are 3 cases:
1- the lines are intersect in one point
2- they are parallel
3- special case of parallel they are identical[same line]
and here is my code but i still can't understand this two parts of code
if(!D && (Dx || Dy))
puts("NONE"); // the lines are parallel
if(!D && !Dx && !Dy)
puts("LINE"); // they are the same lime
why when the determinater is zero and dx = 0 or dy = 0 then they are parallel and when d = 0 and dx = 0 and dy = 0 then they are the same line
i know when determinater equal to zero then there is no unique solution but can't understand the part of !DX and !DY and DX || DY
Here is the full code
#include <iostream>
using namespace std;
struct point{
int x , y;
};
struct segment{
point s , e;
};
int main(){
int n;
scanf("%d" , &n);
puts("INTERSECTING LINES OUTPUT");
while(n--){
segment a , b;
scanf("%d%d%d%d" , &a.s.x , &a.s.y , &a.e.x , &a.e.y);
scanf("%d%d%d%d" , &b.s.x , &b.s.y , &b.e.x , &b.e.y);
double a1 , b1 , c1 , a2 , b2 , c2 , D , Dx , Dy;
a1 = a.e.y - a.s.y;
b1 = a.s.x - a.e.x;
c1 = a1 * (a.s.x) + b1 * (a.s.y);
a2 = b.e.y - b.s.y;
b2 = b.s.x - b.e.x;
c2 = a2 * (b.s.x) + b2 * (b.s.y);
D = a1 * b2 - a2 * b1;
Dx = c1 * b2 - c2 * b1;
Dy = a1 * c2 - a2 * c1;
if(!D && (Dx || Dy))
puts("NONE"); // the lines are parallel
if(!D && !Dx && !Dy)
puts("LINE"); // they are the same line
else printf("POINT %.2f %.2f\n" , (double)Dx / D , (double) Dy / D);
}
return 0;
}
One way to think about this, roughly speaking, is that when D==0 and Dx==0 and Dy==0, then the "coordinates of the intersection point" Dx/D and Dy/D are indeterminate forms 0/0 which could be any number. That means that the lines intersect in a whole bunch of points, which is only possible if they are the same line.
On the other hand, if D==0 and Dx!=0 or Dy!=0 (or both), then the value of Dx/D or Dy/D (or both) is infinity. In other words, the lines intersect at infinity (only), which is another way of saying that the lines are parallel and not coincident.
Testing if(D) for a double is a bad idea, for a couple of reasons. 1) It's not clear. Understanding that expression requires some fairly detailed knowledge of type conversions in the language that frankly not every programmer has. 2) Rounding errors and other numerical instability issues could interfere with the calculation and instead of D==0 you have some tiny D not equal to 0. Then !D is considered true, even though it should be false without the rounding error. Instead you should compare whether abs(D) < some tolerance which is slightly bigger than 0.
Finally your program is vulnerable to overflow issues: if the two lines are close in slope, but otherwise completely reasonable, the intersection point may be extremely large. This is a situation that makes sense in a purely mathematical context, but not so much sense on a computer. Instead, a better question to ask would be whether the intersection lies within the line segments defined by the points. There is a discussion of that problem on the Wikipedia page.
The feedback that worries about floating point arithmetic is on point (Ha!). Since the input is integral, though, I might suggest doing the math with integer types.
The questions you are asking boil down to seeing if two fractions are equivalent. I suggest the following helper class:
struct ratio {
int dx;
int dy;
ratio(int dxIn, int dyIn) :
dx(dxIn), dy(dyIn) {
}
bool isEquivalent(ratio rhs) const {
if ((dx == 0 && dy == 0) || (rhs.dx == 0 && rhs.dy == 0))
return (dx == 0 && dy == 0) && (rhs.dx == 0 && rhs.dy == 0);
return dx * rhs.dy == dy * rhs.dx;
}
};
Each line segment is converted into (a,b,c) coordinates for the extended line which form the line equation a*x+b*y+c=0. What you need to know, is that the vector (a,b) is orthogonal to the line.
The quantity D = a1*b2 - a2*b1 is the cross product between the two orthogonal vectors. As you know the cross product of two parallel vectors is 0. So if that is true, the two lines are either coincident or parallel.
The intersection point is defined as (Dx/D,Dy/D) where Dx=b1*c2-b2*c1 and Dy=a2*c1-a1*c2, so when all equals zero Dx=Dy=D=0 the intersection point is undefined, meaning the lines are coincident. Otherwise if only D=0 the intersection point is at infinity and the lines are parallel.
The rest is just typical confusing C syntax.

Determining dz/dx value from Triangle 3D Vertices

I have 3D Vertices of a triangle as (x1,y1,z1) ; (x2,y2,z2) and (x3,y3,z3).
I would like to know the value of dz/dx.
I have been looking into various 3D Geometry forums,but could not find relevant things.I am trying to write the algorithm in C++.
I would be really glad,if someone can help me.
Thanks in Advance.
The general plane equation is:
a*x + b*y + c*z + d = 0
where a, b, c and d are floating numbers. So, at first you need to find these numbers. Note, however, that you can set the d = 0, because all planes with the same a, b, c coefficients and different d are parallel to each other. So, you get a system of linear equations:
a*x1 + b*y1 + c*z1 = 0
a*x2 + b*y2 + c*z2 = 0
a*x3 + b*y3 + c*z3 = 0
After you solve the system you'll have these three coefficients - then you can express z as a function of x and y:
z = - (a*x + b*y) / c
Then it'll be easy to find the dz/dx:
dz/dx = - a / c
There are some special cases, which you'll need to care of in your code - for example, what if all your points are collinear, or you got c = 0. You'll need to be very careful to cover ALL the corner cases.

Bresenham's algorithm

How to find the decision parameter for drawing different functions like parabola, sine curve, bell curve?
Please tell me about the approach why do we sometimes multiply by constant?
For Example
in case of ellipse, p = a^2(d1 - d2),p = b^2(d1 - d2) for upper and lower half region
respectively where a, b constants
in case of line, p = deltax(d1 - d2) where p is decision parameter d1,d2 are
distances,deltax is constant and is equal to xend - xstart
why not only take (d1 -d2) as parameter
Bresenham's algorithm as stated by the OP is a bit amiss, but I assume the following.
The decision parameter could adjust d1 - d2 and not scale by some constant as you suggest were it not for the initialization of the decision parameter. It is not generally scalable by that constant.
// code from http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
plotLine(x0,y0, x1,y1)
dx=x1-x0
dy=y1-y0
D = 2*dy - dx // Not scalable by 2
plot(x0,y0)
y=y0
for x from x0+1 to x1
if D > 0
y = y+1
plot(x,y)
D = D + (2*dy-2*dx) // Scalable by 2
else
plot(x,y)
D = D + (2*dy) // Scalable by 2

algorithms for modular inverses

i have read section about The Extended Euclidean Algorithm & Modular Inverses,which states that it not only computes GCD(n,m) but also a and b such that a*n+b*b=1;
algorithm is described by by this way:
Write down n, m, and the two-vectors (1,0) and (0,1)
Divide the larger of the two numbers by the smaller - call this
quotient q
Subtract q times the smaller from the larger (ie reduce the larger
modulo the smaller)
(i have question here if we denote by q n/m,then n-q*m is not equal to 0?because q=n/m;(assume that n>m),so why it is necessary such kind of operation?
then 4 step
4.Subtract q times the vector corresponding to the smaller from the
vector corresponding to the larger
5.Repeat steps 2 through 4 until the result is zero
6.Publish the preceding result as gcd(n,m)
so my question for this problem also is how can i implement this steps in code?please help me,i dont know how start and from which point could i start to solve such problem,for clarify result ,it should look like this
An example of this algorithm is the following computation of 30^(-1)(mod 53);
53 30 (1,0) (0,1)
53-1*30=23 30 (1,0)-1*(0,1)=(1,-1) (0,1)
23 30-1*23=7 (1,-1) (0,1)-1*(1,-1)=(-1,2)
23-3*7=2 7 (1,-1)-3*(-1,2)=(4,-7) (-1,2)
2 7-3*2=1 (4,-7) (-1,2)-3*(4,7)=(-13,23)
2-2*1=0 1 (4,-7)-2*(-13,23)=(30,-53) (-13,23)
From this we see that gcd(30,53)=1 and, rearranging terms, we see that 1=-13*53+23*30,
so we conclude that 30^(-1)=23(mod 53).
The division is supposed to be integer division with truncation. The standard EA for gcd(a, b) with a <= b goes like this:
b = a * q0 + r0
a = r0 * q1 + r1
r0 = r1 * q2 + r2
...
r[N+1] = 0
Now rN is the desired GCD. Then you back-substitute:
r[N-1] = r[N] * q[N+1]
r[N-2] = r[N-1] * q[N] + r[N]
= (r[N] * q[N+1]) * q[N] + r[N]
= r[N] * (q[N+1] * q[N] + 1)
r[N-3] = r[N-2] * q[N-1] + r[N-1]
= ... <substitute> ...
Until you finally reach rN = m * a + n * b. The algorithm you describe keeps track of the backtracking data right away, so it's a bit more efficient.
If rN == gcd(a, b) == 1, then you have indeed found the multiplicative inverse of a modulo b, namely m: (a * m) % b == 1.

Normalizing from [0.5 - 1] to [0 - 1]

I'm kind of stuck here, I guess it's a bit of a brain teaser. If I have numbers in the range between 0.5 to 1 how can I normalize it to be between 0 to 1?
Thanks for any help, maybe I'm just a bit slow since I've been working for the past 24 hours straight O_O
Others have provided you the formula, but not the work. Here's how you approach a problem like this. You might find this far more valuable than just knowning the answer.
To map [0.5, 1] to [0, 1] we will seek a linear map of the form x -> ax + b. We will require that endpoints are mapped to endpoints and that order is preserved.
Method one: The requirement that endpoints are mapped to endpoints and that order is preserved implies that 0.5 is mapped to 0 and 1 is mapped to 1
a * (0.5) + b = 0 (1)
a * 1 + b = 1 (2)
This is a simultaneous system of linear equations and can be solved by multiplying equation (1) by -2 and adding equation (1) to equation (2). Upon doing this we obtain b = -1 and substituting this back into equation (2) we obtain that a = 2. Thus the map x -> 2x - 1 will do the trick.
Method two: The slope of a line passing through two points (x1, y1) and (x2, y2) is
(y2 - y1) / (x2 - x1).
Here we will use the points (0.5, 0) and (1, 1) to meet the requirement that endpoints are mapped to endpoints and that the map is order-preserving. Therefore the slope is
m = (1 - 0) / (1 - 0.5) = 1 / 0.5 = 2.
We have that (1, 1) is a point on the line and therefore by the point-slope form of an equation of a line we have that
y - 1 = 2 * (x - 1) = 2x - 2
so that
y = 2x - 1.
Once again we see that x -> 2x - 1 is a map that will do the trick.
Subtract 0.5 (giving you a new range of 0 - 0.5) then multiply by 2.
double normalize( double x )
{
// I'll leave range validation up to you
return (x - 0.5) * 2;
}
To add another generic answer.
If you want to map the linear range [A..B] to [C..D], you can apply the following steps:
Shift the range so the lower bound is 0. (subract A from both bounds:
[A..B] -> [0..B-A]
Scale the range so it is [0..1]. (divide by the upper bound):
[0..B-A] -> [0..1]
Scale the range so it has the length of the new range which is D-C. (multiply with D-C):
[0..1] -> [0..D-C]
Shift the range so the lower bound is C. (add C to the bounds):
[0..D-C] -> [C..D]
Combining this to a single formula, we get:
(D-C)*(X-A)
X' = ----------- + C
(B-A)
In your case, A=0.5, B=1, C=0, D=1 you get:
(X-0.5)
X' = ------- = 2X-1
(0.5)
Note, if you have to convert a lot of X to X', you can change the formula to:
(D-C) C*B - A*D
X' = ----- * X + ---------
(B-A) (B-A)
It is also interesting to take a look at non linear ranges. You can take the same steps, but you need an extra step to transform the linear range to a nonlinear range.
Lazyweb answer: To convert a value x from [minimum..maximum] to [floor..ceil]:
General case:
normalized_x = ((ceil - floor) * (x - minimum))/(maximum - minimum) + floor
To normalize to [0..255]:
normalized_x = (255 * (x - minimum))/(maximum - minimum)
To normalize to [0..1]:
normalized_x = (x - minimum)/(maximum - minimum)
× 2 − 1
should do the trick
You could always use clamp or saturate within your math to make sure your final value is between 0-1. Some saturate at the end, but I've seen it done during a computation, too.