Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <cmath>
- #include <iomanip>
- using namespace std;
- const double SMALL_NUM = 0.000001; // Очень малое число
- // Структура точки
- struct Dot{
- double x; // Координата x
- double y; // Координата y
- double z; // Координата z
- explicit Dot(double X, double Y, double Z) : x(X), y(Y), z(Z) {} // Конструктор
- };
- Dot operator - (const Dot& first, const Dot& second){
- Dot tmp(first.x - second.x, first.y - second.y, first.z - second.z);
- return tmp;
- }
- // Структура отрезка.
- struct Segment{
- Dot P0; // Точка начала
- Dot P1; // Точка конца
- explicit Segment(Dot p0, Dot p1): P0(p0), P1(p1) {} // Конструктор
- };
- // Структура Геометрического вектора ( = Сегмент, где P0 = 0,0,0)
- struct Vect{
- double x;
- double y;
- double z;
- explicit Vect(Dot u) : x(u.x), y(u.y), z(u.z) {}
- };
- // Сложить два вектора - сложить их координаты
- Vect operator + (const Vect& v, const Vect& u){
- return Vect(Dot(v.x + u.x, v.y + u.y,v.z + u.z));
- }
- // Умножить вектор на число - умножить каждую координату на это число
- Vect operator * (const double& a, const Vect& v){
- return Vect(Dot(a*v.x, a*v.y,a*v.z));
- }
- // Разность двух векторов - u+(-1)*v
- Vect operator - (const Vect& v, const Vect& u){
- return v + (-1.0)*u;
- }
- // Расстояние между векторами (по определению)
- double dist_between_dots(Vect u, Vect v){
- return (u.x * v.x + u.y * v.y + u.z * v.z);
- }
- // Длина вектора (по определению)
- double length(Vect v){
- return sqrt(dist_between_dots(v,v));
- }
- double dist_between_Segments(Segment S1, Segment S2){
- Vect u(S1.P1-S1.P0);
- Vect v(S2.P1-S2.P0);
- Vect w(S1.P0-S2.P0);
- // Переменные для вычислений
- double a = dist_between_dots(u,u);
- double b = dist_between_dots(u,v);
- double c = dist_between_dots(v,v);
- double d = dist_between_dots(u,w);
- double e = dist_between_dots(v,w);
- double f = a*c - b*b;
- double sc = 0;
- double sN = 0;
- double sD = f;
- double tD = f;
- double tc;
- double tN;
- // Находим нужные точки
- if (f <= SMALL_NUM) {
- sN = 0.0;
- sD = 1.0;
- tN = e;
- tD = c;
- }
- else {
- sN = (b*e - c*d);
- tN = (a*e - b*d);
- if (sN < 0.0) {
- sN = 0.0;
- tN = e;
- tD = c;
- }
- else if (sN >= sD) {
- sN = sD;
- tN = e + b;
- tD = c;
- }
- }
- if (tN <= 0.0) {
- tN = 0.0;
- if (-d <= 0.0)
- sN = 0.0;
- else if (-d >= a)
- sN = sD;
- else {
- sN = -d;
- sD = a;
- }
- }
- else if (tN >= tD) {
- tN = tD;
- if ((-d + b) <= 0.0)
- sN = 0.0;
- else if ((-d + b) >= a)
- sN = sD;
- else {
- sN = (-d + b);
- sD = a;
- }
- }
- // Находим точки начала и конца вектора
- if(abs(sN) < SMALL_NUM){
- sc = 0.0;
- } else {
- sc = sN / sD;
- }
- if(abs(tN) < SMALL_NUM){
- tc = 0.0;
- } else {
- tc = tN / tD;
- }
- Vect dP = (w + (sc * u)) - (tc * v); // = Вектор, равный вектору из двух нужных нам точек
- return length(dP); // Возвращаем кратчайшее расстояние
- }
- int main() {
- double x = 0.0;
- double y = 0.0;
- double z = 0.0;
- cin >> x; cin >> y; cin >> z;
- Dot P0(x,y,z);
- cin >> x; cin >> y; cin >> z;
- Dot P1(x,y,z);
- Segment S1(P0, P1); // Первый отрезок
- cin >> x; cin >> y; cin >> z;
- Dot P2(x,y,z);
- cin >> x; cin >> y; cin >> z;
- Dot P3(x,y,z);
- Segment S2(P2, P3); // Второй отрезок
- std::cout << std::setprecision(15) << dist_between_Segments(S1,S2);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement