839. Segments
intersection
Given two line segments on
a plane with integer coordinates of their endpoints in the Cartesian coordinate
system. Determine whether the segments have at least one common point.
Input. The first line contains the coordinates of the first endpoint
of the first segment, and the second line contains the coordinates of the
second endpoint of the first segment. The third and fourth lines contain the
coordinates of the endpoints of the second segment. All coordinates are
integers with absolute values not exceeding 104.
Output. Print “Yes” if the segments have a
common point, and “No” otherwise.
|
Sample
input 1 |
Sample
output 1 |
|
0 0 1 0 1 0 1 1 |
Yes |
|
|
|
|
Sample
input 2 |
Sample
output 2 |
|
0 0 1 0 2 0 3 0 |
No |
geometry
The bounding rectangle of a geometric figure is the smallest rectangle with sides parallel to the coordinate axes that completely
contains the given figure.
In simpler terms, if we want to “fit” the
figure into a rectangle so that all its points lie inside it, the bounding
rectangle will have the minimum possible size.
Consider a segment with endpoints at (x1, y1) and (x2, y2). To find its bounding rectangle:
·
Determine
the lower-left corner of the rectangle:
x1’ = min(x1,
x2), y1’ = min(y1, y2)
·
Determine
the upper-right corner of the rectangle:
x2’ = max(x1,
x2), y2’ = max(y1, y2)
Thus, the bounding rectangle is the rectangle with
corners (x1’,
y1’) and (x2’, y2’) that contains our segment.

Lemma. Suppose two segments (x1, x2) and (x3, x4) are given on a line, where x1 < x2 and x3 < x4. The segments do not intersect if and only if either the first
segment lies entirely to the left of the second, or the second lies entirely to
the left of the first.

Lemma. Suppose two rectangles (x1, y1) – (x2, y2) and (x3, y3) – (x4, y4) are given in the plane, where
x1 < x2, y1 < y2 and x3 < x4, y3 < y4. The rectangles do not intersect if and only if either
the segments (x1, x2) and (x3, x4) do not intersect, or the segments (y1, y2) and (y3, y4) do not intersect.

Intersection criterion for two
segments
Two segments AB and CD intersect
if and only if the following three conditions hold:
1. Their bounding rectangles intersect.
2. Points C and D lie on different sides of the line AB, or
at least one of the points C or D lies on the line AB. This means that
[AB ? AC] * [AB ? AD] ? 0

3. Points A and B lie on different sides of the line CD, or
at least one of the points A or B lies on the line CD. This means that
[CD ? CA] * [CD ? CB] ? 0

Below are various cases of
the relative positions of two segments and the corresponding values of the
cross products.

In the next example, each segment
intersects the line containing the other segment. However, their bounding
rectangles do not intersect.

In the first example, the segments intersect. In the second example,
they do not.

Since the coordinates of the segment endpoints are integers, we’ll use
only the integer type long long for calculations. Later, we’ll
need a function sgn that determines the sign of a number n.
int sgn(long
long n)
{
return (n
> 0) - (n < 0);
}
The function RectanglesIntersects takes
as arguments the coordinates of the bounding rectangles for segments AB and CD. It returns 1, if the rectangles (x1, y1) – (x2, y2) and (x3, y3) – (x4, y4) intersect,
and 0 otherwise.
int RectanglesIntersect(long long x1, long long y1,
long long x2, long long y2,
long long x3, long long y3,
long long x4, long long y4)
{
if (x2 < x3 || x4 < x1) return 0;
if (y2 < y3 || y4 < y1) return 0;
return 1;
}
The function cross computes the cross product of two vectors (Ax,
Ay) and (Bx, By).
long long
cross(long long Ax, long long Ay,
long long Bx, long long By)
{
return Ax * By - Ay * Bx;
}
The function intersect checks
whether the segments AB and CD intersect.
int segmentsIntersect(long long x1, long long y1,
long long x2, long long y2,
long long x3, long long y3,
long long x4, long long y4)
{
Check the intersection of the bounding rectangles. If they do not
intersect, return 0.
if (!RectanglesIntersect(
min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2),
min(x3, x4), min(y3, y4), max(x3, x4), max(y3, y4))
) return 0;
Construct the vectors AB, AC, AD.
long long ABx = x2 - x1, ABy = y2 - y1;
long long ACx = x3 - x1, ACy = y3 - y1;
long long ADx = x4 - x1, ADy = y4 - y1;
Construct the vectors CD, CA, CB.
long long CDx = x4 - x3, CDy = y4 - y3;
long long CAx = x1 - x3, CAy = y1 - y3;
long long CBx = x2 - x3, CBy = y2 - y3;
Compute the cross products.
long long ABxAC = cross(ABx, ABy, ACx, ACy); // AB x AC
long long ABxAD = cross(ABx, ABy, ADx, ADy); // AB x AD
long long CDxCA = cross(CDx, CDy, CAx, CAy); // CD x CA
long long CDxCB = cross(CDx, CDy, CBx, CBy); // CD x CB
Check points 2 and 3 of the segment intersection
criterion. If they are not satisfied, return 0. To avoid overflow, the
comparison with zero should be done not on the product of the numbers
themselves, but on the product of their signs.
if (sgn(ABxAC) * sgn(ABxAD)
> 0) return 0;
if (sgn(CDxCA) * sgn(CDxCB)
> 0) return 0;
return 1; // Segments intersect
}
The main part of the
program. Read
the input data.
scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
scanf("%lld %lld %lld %lld",&x3,&y3,&x4,&y4);
Check the intersection of the segments.
if (segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4))
puts("Yes");
else
puts("No");