# One Normal From Two Normals ?

This topic is 4124 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys, I'm working in 2D and want to create a normal that's a combination of two other normals. A good example is a corner with the two normals at right angles to each other, like this: norm_1=(0,1) norm_2=(1,0) un-normalized corner=(0.5,0.5) Do I just linearly interpolate with 0.5 ? I basically have two line segments that meet at a common vertex and I want the normal of that vertex. I know a point technically doesn't have a normal but I need it for collision response so I thought a good way would be to use the 'average' of the line segment normals. Thanks.

##### Share on other sites
I think that should be fine. Does your collision response work correctly using that method? If so, then it's fine. If not, we might need to know a bit more about what's going on.

##### Share on other sites
Assuming that you want a normalised normal from two normalised normals (am I seeing double?), then a equally weighted lerp won't do the trick. An equally weight slerp will, but there's no need to go around the houses.

The simple answer is to add the two normals, then normalise the result. The new vector will point in the same direction as in your 0.5-lerp approach, but is also guaranteed to have unit length. This will fail if the two source normals are anti-parallel, but it's very tricky to define a good answer in that case anyway.

##### Share on other sites
Vector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);

##### Share on other sites
Quote:
 Original post by pTymNVector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);
After factoring, this is the same as saying R = (P + Q) * K, in which case you might as well just write R = Normalize(P + Q).

##### Share on other sites
Surely

R = (P+Q)/2

is faster to avoid the normalisation?

##### Share on other sites
Quote:
 Original post by esuvsSurely R = (P+Q)/2 is faster to avoid the normalisation?

Um, but the OP wants a normalized vector and what you're proposing doesn't ensure that.

##### Share on other sites
Quote:
 Original post by pTymNVector2D P,Q; // normalized 2D vectorsdouble A = abs(atan2(P.y, P.x) - atan2(Q.y, Q.x));Vector2D R = (sin(A*0.5)*P+sin(A*0.5)*Q)/sin(A);

Hey, I didn't realise we were going for the over-complication award! Here's my entry (There's \$1,000,000 up for grabs if you can prove it works [wink])

Vector3 AverageNormal(Vector2 P, Vector2 Q) {    Polynomial zeta = Polynomial::Parse("sum[1/n^s, n=1..infinity]", "s");    Complex root = zeta.FindRoot();    while (!((root / -2).IsNatural())) {       zeta = zeta / Polynomial::Parse("s - {c1}", "s", root);    }    Real one_half = Complex::RealPart(zeta.Evaluate(root));       Vector2P P_polar = Vector2P::FromCartesian(P);    Vector2P Q_polar = Vector2P::FromCartesian(Q);    Real difference = LogNatural(Exp(P_polar.Arg()) / Exp(Q_polar.Arg()));    Integer even_int = Integer::Random(0, Integer::infinity) * 2;    Real abs_difference = Power(Power(difference, even_int.ToReal()), even_int.Reciprocal());    Real half_angle = Dot(one_half.ToVector1, abs_difference.ToVector1).X;    Complex i = Complex::FromImaginary(1);    Real weight_half = Complex::ImaginaryPart(Sinh(i * half_angle));    Real weight_total = Power(1 - Power(Cos(abs_difference), one_half.Reciprocal()), one_half);    Vector2 R1 = (P.CyclicPermute(1).ScalarMultiply(weight_half)).CyclicPermute(-1);    Vector2 R2 = (Q.CyclicPermute(-1).ScalarMultiply(weight_half)).CyclicPermute(1);    Vector2 R_scaled;    R_scaled.y = R2.x + R1.x;    R_scaled.x = -R1.y - (R2.y).Negate();    R_scaled.CyclicPermute(even_int - 7);    Vector2 R = R_scaled.ScalarDivide(weight_total);    Complex::Function f = Complex::Function::Parse("z - z^14", "z");    String sie = "1/(2 * pi * i) int[f(t) / t - z, t]";    Complex::Function g = Complex::Function::Parse(sie, "z");    Complex z = Complex::Random();    return R.ScalarMultiply(f(z) / g(z));}

Okay, so I'm just teasing. But your function seems a little over-the-top, considering the alternatives. I don't think it gets much cleaner than this:

Vector2D P,Q; // Any 2D vectorsVector2D R = P + Q;R.Normalise();

##### Share on other sites
R = (P+Q) * 0.707107

:p

##### Share on other sites
I guess that all of our methods fail if P and Q are opposing...

1. 1
2. 2
Rutin
22
3. 3
4. 4
5. 5
frob
12

• 17
• 9
• 31
• 16
• 9
• ### Forum Statistics

• Total Topics
632615
• Total Posts
3007441

×