Геометрические примитивы: различия между версиями

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
Нет описания правки
Нет описания правки
 
(не показано 12 промежуточных версий этого же участника)
Строка 1: Строка 1:
  #include <stdio.h>
== Точка ==
  #include <math.h>
 
  #include <algorithm>
  #include <cmath>
  #include <vector>
  #include <vector>
#include <algorithm>
  using namespace std;
  using namespace std;
   
   
  const double EPS = 1e-9;
  const double EPS = 1e-9;
   
   
  struct Point {
  struct Point {
Строка 12: Строка 12:
   
   
     Point() {}
     Point() {}
     Point(double x, double y) : x(x), y(y) {}
     Point(double x, double y) : x(x), y(y) {}
     Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {}
     Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {}
    bool operator == (const Point &that) const {
        return abs(x - that.x) < EPS && abs(y - that.y) < EPS;
    }
    bool operator < (const Point &that) const {
        if (abs(x - that.x) >= EPS)
            return x < that.x;
        return y + EPS < that.y;
    }
   
   
     double angle() const {
     double angle() const {
Строка 21: Строка 33:
         return a;
         return a;
     }
     }
     double length() const {
     double length() const {
         return sqrt(x * x + y * y);
         return hypot(x, y);
     }
     }
     double distanceTo(const Point &that) const {
     double distanceTo(const Point &that) const {
         return Point(*this, that).length();
         return hypot(x - that.x, y - that.y);
     }
     }
   
   
Строка 31: Строка 45:
         return Point(x + that.x, y + that.y);
         return Point(x + that.x, y + that.y);
     }
     }
     Point operator - (const Point &that) const {
     Point operator - (const Point &that) const {
         return Point(x - that.x, y - that.y);
         return Point(x - that.x, y - that.y);
     }
     }
     Point operator * (double k) const {
     Point operator * (double k) const {
         return Point(x * k, y * k);
         return Point(x * k, y * k);
     }  
     }
     Point setLength(double newLength) const {
     Point setLength(double newLength) const {
         double k = newLength / length();
         double k = newLength / length();
         return Point(x * k, y * k);
         return Point(x * k, y * k);
    }
    Point rotate(double angle) {
        return Point(x * cos(angle) - y * sin(angle), y * cos(angle) + x * sin(angle));
     }
     }
   
   
     double dotProduct(const Point &that) const {
     double dotProduct(const Point &that) const {
         return x * that.x + y * that.y;
         return x * that.x + y * that.y;
     }  
     }
     double angleTo(const Point &that) const {
     double angleTo(const Point &that) const {
         return acos(dotProduct(that) / (length() * that.length()));
         return acos(max(-1.0, min(1.0, dotProduct(that) / (length() * that.length()))));
     }  
     }
     bool isOrthogonalTo(const Point &that) const {
     bool isOrthogonalTo(const Point &that) const {
         return fabs(dotProduct(that)) < EPS;
         return abs(dotProduct(that)) < EPS;
     }  
     }
     Point orthogonalPoint() const {
     Point orthogonalPoint() const {
         return Point(-y, x);
         return Point(-y, x);
Строка 58: Строка 82:
         return x * that.y - y * that.x;
         return x * that.y - y * that.x;
     }
     }
     bool isCollinearTo(const Point &that) const {
     bool isCollinearTo(const Point &that) const {
         return fabs(crossProduct(that)) < EPS;
         return abs(crossProduct(that)) < EPS;
     }
     }
};
   
   
    friend istream &operator >> (istream &in, Point &p) {
        return in >> p.x >> p.y;
    }
   
   
    friend ostream &operator << (ostream &out, const Point &p) {
        return out << p.x << " " << p.y;
    }
};
== Прямая ==
  struct Line {
  struct Line {
     double a, b, c;
     double a, b, c;
   
   
     Line() {}
     Line() {}
     Line(double a, double b, double c) : a(a), b(b), c(c) {}
     Line(double a, double b, double c) : a(a), b(b), c(c) {}
     Line(const Point &p1, const Point &p2) : a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
     Line(const Point &p1, const Point &p2) : a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
     static Line LineByVector(const Point &p, const Point &v) {
     static Line LineByVector(const Point &p, const Point &v) {
         return Line(p, p + v);
         return Line(p, p + v);
     }
     }
     static Line LineByNormal(const Point &p, const Point &n) {
     static Line LineByNormal(const Point &p, const Point &n) {
         return LineByVector(p, n.orthogonalPoint());
         return LineByVector(p, n.orthogonalPoint());
Строка 80: Строка 118:
         return Point(a, b);
         return Point(a, b);
     }
     }
     Line orthogonalLine(const Point &p) const {
     Line orthogonalLine(const Point &p) const {
         return LineByVector(p, normal());
         return LineByVector(p, normal());
     }  
     }
     Line parallelLine(const Point &p) const {
     Line parallelLine(const Point &p) const {
         return LineByNormal(p, normal());
         return LineByNormal(p, normal());
     }
     }
     Line parallelLine(double distance) const {
     Line parallelLine(double distance) const {
         Point p = (fabs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
         Point p = (abs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
         Point p1 = p + normal().setLength(distance);
         Point p1 = p + normal().setLength(distance);
         return LineByNormal(p1, normal());
         return LineByNormal(p1, normal());
Строка 94: Строка 135:
     int side(const Point &p) const {
     int side(const Point &p) const {
         double r = a * p.x + b * p.y + c;
         double r = a * p.x + b * p.y + c;
         if (fabs(r) < EPS)
         if (abs(r) < EPS)
             return 0;
             return 0;
         else
         else
             return r > 0 ? 1 : -1;
             return r > 0 ? 1 : -1;
     }
     }
     double distanceTo(const Point &p) const {
     double distanceTo(const Point &p) const {
         return fabs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
         return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
     }
     }
     bool has(const Point &p) const {
     bool has(const Point &p) const {
         return distanceTo(p) < EPS;
         return distanceTo(p) < EPS;
Строка 108: Строка 151:
     double distanceTo(const Line &that) const {
     double distanceTo(const Line &that) const {
         if (normal().isCollinearTo(that.normal())) {
         if (normal().isCollinearTo(that.normal())) {
             Point p = (fabs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
             Point p = (abs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
             return that.distanceTo(p);
             return that.distanceTo(p);
         } else
         } else
             return 0;
             return 0;
     }  
     }
     bool intersectsWith(const Line &that) const {
     bool intersectsWith(const Line &that) const {
         return distanceTo(that) < EPS;
         return distanceTo(that) < EPS;
     }
     }
     Point intersection(const Line &that) const {
     Point intersection(const Line &that) const {
         double d = a * that.b - b * that.a;
         double d = a * that.b - b * that.a;
Строка 121: Строка 166:
         double dy = a * -that.c - -c * that.a;
         double dy = a * -that.c - -c * that.a;
         return Point(dx / d, dy / d);
         return Point(dx / d, dy / d);
     }  
     }
};
   
   
    friend istream &operator >> (istream &in, Line &l) {
        return in >> l.a >> l.b >> l.c;
    }
   
   
    friend ostream &operator << (ostream &out, const Line &l) {
        return out << l.a << " " << l.b << " " << l.c;
    }
};
== Луч ==
  struct Ray {
  struct Ray {
     Point p1, p2;
     Point p1, p2;
Строка 130: Строка 184:
   
   
     Ray(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
     Ray(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
   
     double distanceTo(const Point &p) const {
     double distanceTo(const Point &p) const {
         if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS)
         if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS)
             return fabs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
             return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
         else
         else
             return p1.distanceTo(p);
             return p1.distanceTo(p);
     }
     }
     bool has(const Point &p) const {
     bool has(const Point &p) const {
         return distanceTo(p) < EPS;
         return distanceTo(p) < EPS;
Строка 150: Строка 205:
         return min(distanceTo(that.p1), that.distanceTo(p1));
         return min(distanceTo(that.p1), that.distanceTo(p1));
     }
     }
     bool intersectsWith(const Ray &that) const {
     bool intersectsWith(const Ray &that) const {
         return distanceTo(that) < EPS;
         return distanceTo(that) < EPS;
     }
     }
  };
  };
 
== Отрезок ==
 
  struct Segment {
  struct Segment {
     Point p1, p2;
     Point p1, p2;
Строка 161: Строка 218:
   
   
     Segment(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
     Segment(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}
   
     double distanceTo(const Point &p) const {
     double distanceTo(const Point &p) const {
         if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS && Point(p2, p).dotProduct(Point(p2, p1)) >= -EPS)
         if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS && Point(p2, p).dotProduct(Point(p2, p1)) >= -EPS)
             return fabs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
             return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
         else
         else
             return min(p1.distanceTo(p), p2.distanceTo(p));
             return min(p1.distanceTo(p), p2.distanceTo(p));
     }
     }
     bool has(const Point &p) const {
     bool has(const Point &p) const {
         return distanceTo(p) < EPS;
         return distanceTo(p) < EPS;
Строка 180: Строка 238:
         }
         }
         return min(min(distanceTo(that.p1), distanceTo(that.p2)), min(that.distanceTo(p1), that.distanceTo(p2)));
         return min(min(distanceTo(that.p1), distanceTo(that.p2)), min(that.distanceTo(p1), that.distanceTo(p2)));
     }  
     }
     bool intersectsWith(const Segment &that) const {
     bool intersectsWith(const Segment &that) const {
         return distanceTo(that) < EPS;
         return distanceTo(that) < EPS;
     }
     }
  };
  };
 
== Многоугольник ==
 
  struct Polygon {
  struct Polygon {
     vector<Point> points;
     vector<Point> points;
     void addPoint(const Point &p) {
     void addPoint(const Point &p) {
         points.push_back(p);
         points.push_back(p);
     }
     }
    bool has(const Point &p) const {
        bool pos = 0, neg = 0;
        for (int i = 0; i < points.size(); i++) {
            const Point &a = points[i], &b = points[(i + 1) % points.size()];
            Point ab(a, b), ap(a, p);
            double cross = ab.crossProduct(ap);
            pos |= cross > EPS;
            neg |= cross < -EPS;
        }
        return !pos || !neg;
    }
    bool isConvex() {
        bool pos = 0, neg = 0;
        for (int i = 0; i < points.size(); i++) {
            const Point &a = points[i], &b = points[(i + 1) % points.size()], &c = points[(i + 2) % points.size()];
            Point ab(a, b), ac(a, c);
            double cross = ab.crossProduct(ac);
            pos |= cross > EPS;
            neg |= cross < -EPS;
        }
        return !pos || !neg;
    }
    double perimeter() const {
        double p = 0;
        for (int i = 0; i < points.size(); i++)
            p += points[i].distanceTo(points[(i + 1) % points.size()]);
        return p;
    }
     double area() const {
     double area() const {
         double s = 0;
         double s = 0;
         for (int i = 1; i < points.size(); i++)
         for (int i = 0; i < points.size(); i++)
             s += points[i - 1].crossProduct(points[i]);
             s += points[i].crossProduct(points[(i + 1) % points.size()]);
         s += points[points.size() - 1].crossProduct(points[0]);
         return abs(s) / 2;
         return fabs(s) / 2;
    }
};
 
== Точная проверка на пересечение отрезков с целыми координатами ==
struct Point {
    long long x, y;
    Point() {}
    Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {}
    long long crossProduct(const Point &that) const {
        return x * that.y - y * that.x;
    }
};
struct Segment {
    Point p1, p2;
    Segment(const Point &p1, const Point &p2) : p1(p1), p2(p2) {}
    bool intersectsWith(const Segment &that) const {
        long long abx1 = min(p1.x, p2.x), abx2 = max(p1.x, p2.x);
        long long cdx1 = min(that.p1.x, that.p2.x), cdx2 = max(that.p1.x, that.p2.x);
        if (max(abx1, cdx1) > min(abx2, cdx2))
            return 0;
        long long aby1 = min(p1.y, p2.y), aby2 = max(p1.y, p2.y);
        long long cdy1 = min(that.p1.y, that.p2.y), cdy2 = max(that.p1.y, that.p2.y);
        if (max(aby1, cdy1) > min(aby2, cdy2))
            return 0;
        Point ab(p1, p2), ac(p1, that.p1), ad(p1, that.p2);
        long long abc = ab.crossProduct(ac), abd = ab.crossProduct(ad);
        if (abc > 0 && abd > 0 || abc < 0 && abd < 0)
            return 0;
        Point cd(that.p1, that.p2), ca(that.p1, p1), cb(that.p1, p2);
        long long cda = cd.crossProduct(ca), cdb = cd.crossProduct(cb);
         if (cda > 0 && cdb > 0 || cda < 0 && cdb < 0)
            return 0;
        return 1;
     }
     }
  };
  };
Строка 204: Строка 340:
Теория:
Теория:
* [http://e-maxx.ru/bookz/files/andreeva.pdf Андреева Е. В., Егоров Ю. Е. Вычислительная геометрия на плоскости / Е. В. Андреева, Ю. Е. Егоров. // Информатика. &mdash; 2002. &mdash; №39, 40, 43, 44]
* [http://e-maxx.ru/bookz/files/andreeva.pdf Андреева Е. В., Егоров Ю. Е. Вычислительная геометрия на плоскости / Е. В. Андреева, Ю. Е. Егоров. // Информатика. &mdash; 2002. &mdash; №39, 40, 43, 44]
* [http://maratona.ic.unicamp.br/MaratonaVerao2017/documents/geom.pdf Ахмедов М. Geometry, stereometry and spherical geometry]
* [http://e-maxx.ru/algo/segments_intersection_checking E-maxx — Проверка двух отрезков на пересечение]
Задачи:
Задачи:
* [http://codeforces.com/gym/100168 Codeforces 100168 &mdash; 2012-2013 Тренировка СПбГУ C #8. Геометрия. База.]
* [http://codeforces.com/gym/100168 Codeforces 100168 &mdash; 2012-2013 Тренировка СПбГУ C #8. Геометрия. База.]

Текущая версия от 19:22, 4 июня 2023

Точка

#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;

const double EPS = 1e-9;

struct Point {
    double x, y;

    Point() {}

    Point(double x, double y) : x(x), y(y) {}

    Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {}

    bool operator == (const Point &that) const {
        return abs(x - that.x) < EPS && abs(y - that.y) < EPS;
    }

    bool operator < (const Point &that) const {
        if (abs(x - that.x) >= EPS)
            return x < that.x;
        return y + EPS < that.y;
    }

    double angle() const {
        double a = atan2(y, x);
        if (a < -EPS)
            a += 2 * acos(-1.0);
        return a;
    }

    double length() const {
        return hypot(x, y);
    }

    double distanceTo(const Point &that) const {
        return hypot(x - that.x, y - that.y);
    }

    Point operator + (const Point &that) const {
        return Point(x + that.x, y + that.y);
    }

    Point operator - (const Point &that) const {
        return Point(x - that.x, y - that.y);
    }

    Point operator * (double k) const {
        return Point(x * k, y * k);
    }

    Point setLength(double newLength) const {
        double k = newLength / length();
        return Point(x * k, y * k);
    }

    Point rotate(double angle) {
        return Point(x * cos(angle) - y * sin(angle), y * cos(angle) + x * sin(angle));
    }

    double dotProduct(const Point &that) const {
        return x * that.x + y * that.y;
    }

    double angleTo(const Point &that) const {
        return acos(max(-1.0, min(1.0, dotProduct(that) / (length() * that.length()))));
    }

    bool isOrthogonalTo(const Point &that) const {
        return abs(dotProduct(that)) < EPS;
    }

    Point orthogonalPoint() const {
        return Point(-y, x);
    }

    double crossProduct(const Point &that) const {
        return x * that.y - y * that.x;
    }

    bool isCollinearTo(const Point &that) const {
        return abs(crossProduct(that)) < EPS;
    }

    friend istream &operator >> (istream &in, Point &p) {
        return in >> p.x >> p.y;
    }

    friend ostream &operator << (ostream &out, const Point &p) {
        return out << p.x << " " << p.y;
    }
};

Прямая

struct Line {
    double a, b, c;

    Line() {}

    Line(double a, double b, double c) : a(a), b(b), c(c) {}

    Line(const Point &p1, const Point &p2) : a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}

    static Line LineByVector(const Point &p, const Point &v) {
        return Line(p, p + v);
    }

    static Line LineByNormal(const Point &p, const Point &n) {
        return LineByVector(p, n.orthogonalPoint());
    }

    Point normal() const {
        return Point(a, b);
    }

    Line orthogonalLine(const Point &p) const {
        return LineByVector(p, normal());
    }

    Line parallelLine(const Point &p) const {
        return LineByNormal(p, normal());
    }

    Line parallelLine(double distance) const {
        Point p = (abs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
        Point p1 = p + normal().setLength(distance);
        return LineByNormal(p1, normal());
    }

    int side(const Point &p) const {
        double r = a * p.x + b * p.y + c;
        if (abs(r) < EPS)
            return 0;
        else
            return r > 0 ? 1 : -1;
    }

    double distanceTo(const Point &p) const {
        return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
    }

    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
    }

    double distanceTo(const Line &that) const {
        if (normal().isCollinearTo(that.normal())) {
            Point p = (abs(a) < EPS ? Point(0, -c / b) : Point(-c / a, 0));
            return that.distanceTo(p);
        } else
            return 0;
    }

    bool intersectsWith(const Line &that) const {
        return distanceTo(that) < EPS;
    }

    Point intersection(const Line &that) const {
        double d = a * that.b - b * that.a;
        double dx = -c * that.b - b * -that.c;
        double dy = a * -that.c - -c * that.a;
        return Point(dx / d, dy / d);
    }

    friend istream &operator >> (istream &in, Line &l) {
        return in >> l.a >> l.b >> l.c;
    }

    friend ostream &operator << (ostream &out, const Line &l) {
        return out << l.a << " " << l.b << " " << l.c;
    }
};

Луч

struct Ray {
    Point p1, p2;
    double a, b, c;

    Ray(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}

    double distanceTo(const Point &p) const {
        if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS)
            return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
        else
            return p1.distanceTo(p);
    }

    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
    }

    double distanceTo(const Ray &that) const {
        Line l(a, b, c), thatL(that.a, that.b, that.c);
        if (l.intersectsWith(thatL)) {
            Point p = l.intersection(thatL);
            if (has(p) && that.has(p))
                return 0;
        }
        return min(distanceTo(that.p1), that.distanceTo(p1));
    }

    bool intersectsWith(const Ray &that) const {
        return distanceTo(that) < EPS;
    }
};

Отрезок

struct Segment {
    Point p1, p2;
    double a, b, c;

    Segment(const Point &p1, const Point &p2) : p1(p1), p2(p2), a(p1.y - p2.y), b(p2.x - p1.x), c(p1.x * p2.y - p2.x * p1.y) {}

    double distanceTo(const Point &p) const {
        if (Point(p1, p).dotProduct(Point(p1, p2)) >= -EPS && Point(p2, p).dotProduct(Point(p2, p1)) >= -EPS)
            return abs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
        else
            return min(p1.distanceTo(p), p2.distanceTo(p));
    }

    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
    }

    double distanceTo(const Segment &that) const {
        Line l(a, b, c), thatL(that.a, that.b, that.c);
        if (l.intersectsWith(thatL)) {
            Point p = l.intersection(thatL);
            if (has(p) && that.has(p))
                return 0;
        }
        return min(min(distanceTo(that.p1), distanceTo(that.p2)), min(that.distanceTo(p1), that.distanceTo(p2)));
    }

    bool intersectsWith(const Segment &that) const {
        return distanceTo(that) < EPS;
    }
};

Многоугольник

struct Polygon {
    vector<Point> points;

    void addPoint(const Point &p) {
        points.push_back(p);
    }

    bool has(const Point &p) const {
        bool pos = 0, neg = 0;
        for (int i = 0; i < points.size(); i++) {
            const Point &a = points[i], &b = points[(i + 1) % points.size()];
            Point ab(a, b), ap(a, p);
            double cross = ab.crossProduct(ap);
            pos |= cross > EPS;
            neg |= cross < -EPS;
        }
        return !pos || !neg;
    }

    bool isConvex() {
        bool pos = 0, neg = 0;
        for (int i = 0; i < points.size(); i++) {
            const Point &a = points[i], &b = points[(i + 1) % points.size()], &c = points[(i + 2) % points.size()];
            Point ab(a, b), ac(a, c);
            double cross = ab.crossProduct(ac);
            pos |= cross > EPS;
            neg |= cross < -EPS;
        }
        return !pos || !neg;
    }

    double perimeter() const {
        double p = 0;
        for (int i = 0; i < points.size(); i++)
            p += points[i].distanceTo(points[(i + 1) % points.size()]);
        return p;
    }

    double area() const {
        double s = 0;
        for (int i = 0; i < points.size(); i++)
            s += points[i].crossProduct(points[(i + 1) % points.size()]);
        return abs(s) / 2;
    }
};

Точная проверка на пересечение отрезков с целыми координатами

struct Point {
    long long x, y;

    Point() {}

    Point(const Point &a, const Point &b) : x(b.x - a.x), y(b.y - a.y) {}

    long long crossProduct(const Point &that) const {
        return x * that.y - y * that.x;
    }
};


struct Segment {
    Point p1, p2;

    Segment(const Point &p1, const Point &p2) : p1(p1), p2(p2) {}

    bool intersectsWith(const Segment &that) const {
        long long abx1 = min(p1.x, p2.x), abx2 = max(p1.x, p2.x);
        long long cdx1 = min(that.p1.x, that.p2.x), cdx2 = max(that.p1.x, that.p2.x);
        if (max(abx1, cdx1) > min(abx2, cdx2))
            return 0;

        long long aby1 = min(p1.y, p2.y), aby2 = max(p1.y, p2.y);
        long long cdy1 = min(that.p1.y, that.p2.y), cdy2 = max(that.p1.y, that.p2.y);
        if (max(aby1, cdy1) > min(aby2, cdy2))
            return 0;

        Point ab(p1, p2), ac(p1, that.p1), ad(p1, that.p2);
        long long abc = ab.crossProduct(ac), abd = ab.crossProduct(ad);
        if (abc > 0 && abd > 0 || abc < 0 && abd < 0)
            return 0;

        Point cd(that.p1, that.p2), ca(that.p1, p1), cb(that.p1, p2);
        long long cda = cd.crossProduct(ca), cdb = cd.crossProduct(cb);
        if (cda > 0 && cdb > 0 || cda < 0 && cdb < 0)
            return 0;

        return 1;
    }
};

Ссылки

Теория:

Задачи: