Question

I have a two segments AB and CD (in red). These two segments are facing each others. They are not completely parallel but will never be perpendicular to each others either.

From that, I need to find the two normals of these segments (in blue) that oppose each others (i.e. the two normals are outside ABCD). I know how to calculate the normals of the segments but obviously each segment has two normals, and I cannot figure out how to programmatically select the ones I need. Any suggestion?

enter image description here

Was it helpful?

Solution

Calculate the vector v between the midpoints of the two segments, pointing from AB to CD. Now the projection of the desired normal to AB onto v must be negative and the projection of the desired normal to CD onto v must be positive. So just calculate the normals, check against v, and negate the normals if needed to make them satisfy the condition.

Here it is in Python:

# use complex numbers to define minimal 2d vector datatype
def vec2d(x,y): return complex(x,y)
def rot90(v): return 1j * v
def inner_prod(u, v): return (u * v.conjugate()).real

def outward_normals(a, b, c, d):
    n1 = rot90(b - a)
    n2 = rot90(d - c)
    mid = (c + d - a - b) / 2
    if inner_prod(n1, mid) > 0:
        n1 = -n1
    if inner_prod(n2, mid) < 0:
        n2 = -n2
    return n1, n2

Note that I assume the endpoints define lines meeting the conditions in the problem. Nor do I check for the edge case when the lines have the same midpoint; the notion of "outside" doesn't apply in that case.

OTHER TIPS

I think there are two cases to consider:

Case 1: Intersection between lines occurs outside the endpoints of either segment.

In this case the midpoint method suggested by @Michael J. Barber will work for sure. So form a vector between the midpoints of the segments, compute the dot product of your normal vectors with this midpoint vector and check the sign.

If you're computing the normal for lineA, the dot product of the normal with the vector midB -> midA should be +ve.

Case 2: Intersection between lines occurs inside the endpoints of one segment.

In this case form a vector between either one of the endpoints of the segment that does not enclose the intersection point and the intersection point itself.

The dot product of the normal for the segment that does enclose the intersection point and this new vector should be +ve.

You can find the outward normal for the other segment by requiring that the dot product between the two normals is -ve (which would only be ambiguous in the case of perpendicular segments).

I've assumed that the segments are not co-linear or actually intersecting.

Hope this helps.

You can reduce the four combinations for the signs as follows:

  1. Calculate the dot product of the normals, a negative sign indicates that both show outside or inside.

    As I suppose that your normals have unit lenght, you can detect parallelity if the dot product has magnitude one. A positive value indicates that both show in the same direction, a negative value says that both show in different directions.

  2. It the normals are not parallel: parametrize lines as x(t) = x0 + t * n for a normal n and calculate the t for which both intersect. A negative t will indicate that both show outside. It is enough if you do this for one of the normals, as you reduced your combinations from 4 to 2 in step 1.

  3. If both normals are parralel: Calculate the time t for which the normals hit the midpoint between of your segments. As in 2. is enough if you do this for one of the normals, as you reduced your combinations from 4 to 2 in step 1.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top