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

Материал из Олимпиадное программирование в УлГТУ
Перейти к навигации Перейти к поиску
(Новая страница: « #include <stdio.h> #include <math.h> #include <vector> #include <algorithm> using namespace std; const double EPS = 1e-9; struct Point { double x,…»)
 
Нет описания правки
Строка 6: Строка 6:
   
   
  const double EPS = 1e-9;
  const double EPS = 1e-9;
   
   
  struct Point {
  struct Point {
     double x, y;
     double x, y;
     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) {}
    double angle() const {
        double a = atan2(y, x);
        if (a < -EPS)
            a += 2 * acos(-1.0);
        return a;
    }
     double length() const {
     double length() const {
         return sqrt(x * x + y * y);
         return sqrt(x * x + y * y);
     }
     }
     Point setLength(double newLength) const {
     double distanceTo(const Point &that) const {
        double k = newLength / length();
         return Point(*this, that).length();
         return Point(x * k, y * k);
     }
     }
     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);
Строка 26: Строка 35:
     }
     }
     Point operator * (double k) const {
     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);
         return Point(x * k, y * k);
     }
     }
     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 crossProduct(const Point &that) const {
        return x * that.y - y * that.x;
    }
    double angle() const {
        double a = atan2(y, x);
        if (a < -EPS)
            a += 2 * acos(-1.0);
        return a;
    }
     double angleTo(const Point &that) const {
     double angleTo(const Point &that) const {
         return acos(dotProduct(that) / (length() * that.length()));
         return acos(dotProduct(that) / (length() * that.length()));
     }
     }  
     bool isOrthogonalTo(const Point &that) const {
     bool isOrthogonalTo(const Point &that) const {
         return fabs(dotProduct(that)) < EPS;
         return fabs(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 {
     bool isCollinearTo(const Point &that) const {
         return fabs(crossProduct(that)) < EPS;
         return fabs(crossProduct(that)) < EPS;
    } 
    double distanceTo(const Point &that) const {
        return Point(*this, that).length();
     }
     }
  };
  };
   
   
  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) {
        return Line(p, p + v);
    }
     static Line LineByNormal(const Point &p, const Point &n) {
     static Line LineByNormal(const Point &p, const Point &n) {
         return Line(n.x, n.y, -p.dotProduct(n));
         return LineByVector(p, n.orthogonalPoint());
     }
     }
     Point normal() const {
     Point normal() const {
         return Point(a, b);
         return Point(a, b);
     }
     }
     Line orthogonalLine(const Point &p) const {
     Line orthogonalLine(const Point &p) const {
         return Line(b, -a, a * p.y - b * p.x);
         return LineByVector(p, normal());
     }   
     }   
     Line parallelLine(const Point &p) const {
     Line parallelLine(const Point &p) const {
Строка 75: Строка 90:
         return LineByNormal(p, normal());
         return LineByNormal(p, normal());
     }
     }
     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;
Строка 85: Строка 101:
         return fabs(a * p.x + b * p.y + c) / sqrt(a * a + b * b);
         return fabs(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 {
     double distanceTo(const Line &that) const {
         if (normal().isCollinearTo(that.normal())) {
         if (normal().isCollinearTo(that.normal())) {
Строка 91: Строка 111:
         } else
         } else
             return 0;
             return 0;
    }
    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
     }   
     }   
     bool intersectsWith(const Line &that) const {
     bool intersectsWith(const Line &that) const {
Строка 105: Строка 122:
     }   
     }   
  };
  };
   
   
  struct Ray {
  struct Ray {
     Point p1, p2;
     Point p1, p2;
     double a, b, c;
     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) {}
     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)
Строка 116: Строка 136:
             return p1.distanceTo(p);
             return p1.distanceTo(p);
     }
     }
    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
    }
     double distanceTo(const Ray &that) const {
     double distanceTo(const Ray &that) const {
         Line l(a, b, c), thatL(that.a, that.b, that.c);
         Line l(a, b, c), thatL(that.a, that.b, that.c);
Строка 124: Строка 148:
         }
         }
         return min(distanceTo(that.p1), that.distanceTo(p1));
         return min(distanceTo(that.p1), that.distanceTo(p1));
    }
    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
     }
     }
     bool intersectsWith(const Ray &that) const {
     bool intersectsWith(const Ray &that) const {
Строка 132: Строка 153:
     }
     }
  };
  };
   
   
  struct Segment {
  struct Segment {
     Point p1, p2;
     Point p1, p2;
     double a, b, c;
     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) {}
     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)
Строка 143: Строка 167:
             return min(p1.distanceTo(p), p2.distanceTo(p));
             return min(p1.distanceTo(p), p2.distanceTo(p));
     }
     }
    bool has(const Point &p) const {
        return distanceTo(p) < EPS;
    }
     double distanceTo(const Segment &that) const {
     double distanceTo(const Segment &that) const {
         Line l(a, b, c), thatL(that.a, that.b, that.c);
         Line l(a, b, c), thatL(that.a, that.b, that.c);
Строка 151: Строка 179:
         }
         }
         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 has(const Point &p) const {
        return distanceTo(p) < EPS;
    }
     bool intersectsWith(const Segment &that) const {
     bool intersectsWith(const Segment &that) const {
         return distanceTo(that) < EPS;
         return distanceTo(that) < EPS;
     }
     }
  };
  };
   
   
  struct Polygon {
  struct Polygon {

Версия от 00:17, 1 июня 2017

#include <stdio.h>
#include <math.h>
#include <vector>
#include <algorithm>
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) {}

    double angle() const {
        double a = atan2(y, x);
        if (a < -EPS)
            a += 2 * acos(-1.0);
        return a;
    }
    double length() const {
        return sqrt(x * x + y * y);
    }
    double distanceTo(const Point &that) const {
        return Point(*this, that).length();
    }

    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);
    }

    double dotProduct(const Point &that) const {
        return x * that.x + y * that.y;
    }   
    double angleTo(const Point &that) const {
        return acos(dotProduct(that) / (length() * that.length()));
    }   
    bool isOrthogonalTo(const Point &that) const {
        return fabs(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 fabs(crossProduct(that)) < EPS;
    }
};


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 = (a ? Point(-c / a, 0) : Point(0, -c / b)) + normal().setLength(distance);
        return LineByNormal(p, normal());
    }

    int side(const Point &p) const {
        double r = a * p.x + b * p.y + c;
        if (fabs(r) < EPS)
            return 0;
        else
            return r > 0 ? 1 : -1;
    }
    double distanceTo(const Point &p) const {
        return fabs(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 = (a ? Point(-c / a, 0) : Point(0, -c / b));
            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);
    }   
};


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 fabs(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 fabs(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);
    }
    double area() const {
        double s = 0;
        for (int i = 1; i < points.size(); i++)
            s += points[i - 1].crossProduct(points[i]);
        s += points[points.size() - 1].crossProduct(points[0]);
        return s;
    }
};

Ссылки

Теория:

Задачи: