Форум программистов, компьютерный форум, киберфорум
Геометрия
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/88: Рейтинг темы: голосов - 88, средняя оценка - 4.80
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
26.01.2016, 13:20
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от Igor3D Посмотреть сообщение
Просто переводите точки в 2D
Без If и алгоритма?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
26.01.2016, 13:20
Ответы с готовыми решениями:

Найти координаты центра окружности по трём точкам
Дано координаты 3-х точек: 1. Точка Р1 с координатами Х1 и Y1; 2. Точка Р2 с координатами Х2 и Y2; 3. Точка Р3 с координатами Х3 и...

Уравнение окружности по трем точкам в пространстве
\begin{cases}(x-x_0)^2+(y-y_0)^2+(z-z_0)^2=R^2,\\ a{\cdot}(x-x_0)+b{\cdot}(y-y_0)+c{\cdot}(z-z_0) = 0.\end{cases} Надо...

Массивы. Геометрия. Об окружности минимального радиуса по трем точкам
Определить радиус и центр окружности минимального радиуса, проходящей хотя бы через три различные точки заданного множества точек на...

46
1977 / 833 / 115
Регистрация: 01.10.2012
Сообщений: 5,156
Записей в блоге: 2
26.01.2016, 14:04
Цитата Сообщение от Excalibur921 Посмотреть сообщение
Без If и алгоритма?
Простой матрицей по 20 копеек
0
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
26.01.2016, 14:16
ТС не любит матрицы)). А как знать куда поворачивать? Мне видеться тут только алгоритм поиска минимум Z вершины, замер двух углов. Поворот вокруг Y вокруг X, найти центр D по 3 точкам и повернуть обратно.
Итого 4 поворота матрицами.
0
827 / 244 / 47
Регистрация: 24.01.2013
Сообщений: 750
26.01.2016, 14:25
"Углы Эйлера" - https://ru.wikipedia.org/wiki/... 1%80%D0%B0
максимум три поворота из любого положения...
ставим нормаль к треугольнику по оси Z
дальше стандартное определение circumcenter в 2D
0
1977 / 833 / 115
Регистрация: 01.10.2012
Сообщений: 5,156
Записей в блоге: 2
26.01.2016, 14:29
Цитата Сообщение от Excalibur921 Посмотреть сообщение
ТС не любит матрицы)). А как знать куда поворачивать? Мне видеться тут только алгоритм поиска минимум Z вершины, замер двух углов. Поворот вокруг Y вокруг X, найти центр D по 3 точкам и повернуть обратно.
Итого 4 поворота матрицами.
Здесь повороты не нужны, просто получаем 3 оси матрицы
C++
1
2
3
4
Vec3 axis_z = cross(b - a, c - a).normalized();
Vec3 axis_x(rand() / RAND_MAX, rand() / RAND_MAX, rand() / RAND_MAX);
Vec3 axis_y = cross(axiz_z, axis_x).normalized();
axis_x = cross(axis_y, axis_z);
Да, при каждом запуске мы будем получать разные матрицы (rand) - но все они будут работать правильно
0
 Аватар для palva
4278 / 2970 / 693
Регистрация: 08.06.2007
Сообщений: 9,931
Записей в блоге: 5
26.01.2016, 18:26
Довольно просто для стороны треугольника AB написать уравнение плоскости перпендикулярной AB и проходящей через середину AB, то есть через точку K=(B-A)/2. Если обозначить M=(x,y,z) координаты точки плоскости, то уравнение плоскости через скалярное произведение векторов будет такое: (B-A,M-K)=0. Нужно написать еще два таких уравнения для сторон BC и CA. Получится система трех уравнений, которую нужно решить относительно x,y,z, например, по формулам Крамера. Это будет центр окружности. По-моему, на C# нормально ляжет. Никаких извлечений корней и итераций.

Добавлено через 10 минут
На фортран, где есть операции между векторами и матрицами, конечно, легло бы лучше. А здесь при любом чихе приходится писать циклы по трем координатам. Но для трех координат будет логично заменять массивы из трех элементов тремя обычными переменными, типа Ax, Ay, Az, а циклы заменять тремя операторами присваивания.
0
827 / 244 / 47
Регистрация: 24.01.2013
Сообщений: 750
26.01.2016, 21:01
Да тут можно обойтись всего одним поворотом! так как направление осей координат в плоскости треугольника неважно.

1) сдвигаем начало координат в точку А -> А = 0; B = B - A; C = C - A.
2) находим нормаль к треугольнику -> N = cross(B, C).normalized();
3) находим ось вращения как векторное произведение нормали и вектора "вверх" Z(0,0,1) -> R = cross(N, Z);
4) находим угол поворота -> U = acos(dot(N, Z));
5) вращаем вектора В и С, тем самым "ложим" треугольник на плоскость X-Y.
6) находим центр окружности O.
7) возвращаемся в исходную СК -> вращаем на угол (-U) и перенос начала координат O = O + A.

Добавлено через 4 минуты
Для пункта 6:
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
vec2 TriangleCircumcenter2D(vec2 triV0, vec2 triV1, vec2 triV2);
{
  float X1, X2, Y1, Y2, A, L10, L20;
  vec2 ret;
 
  X1 = triV1.x - triV0.x;
  X2 = triV2.x - triV0.x;
  Y1 = triV1.y - triV0.y;
  Y2 = triV2.y - triV0.y;
 
  L10 = X1*X1 + Y1*Y1;
  L20 = X2*X2 + Y2*Y2;
 
  A = 0.5*(X1*Y2 - X2*Y1);
  A = 1/(4*A);
 
  ret.x = triV0.x + (Y2*L10 - Y1*L20) * A;
  ret.y = triV0.y + (X1*L20 - X2*L10) * A;
 
  return ret;
}
0
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
26.01.2016, 22:32
Цитата Сообщение от _Develop Посмотреть сообщение
TriangleCircumcenter2D
Это дело есть в вики и я кидал ссылку на формулы.

Цитата Сообщение от Igor3D Посмотреть сообщение
Здесь повороты не нужны, просто получаем 3 оси матрицы
Понятия не имею зачем это делать. Но не хочу терзать нубскими вопросами.
В итоге предложено порядка 5 методов.

Интересно ТС хоть что то попытался решить, а то вы тут распинаетесь. Мне бы так помогали в Mathematica…
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
27.01.2016, 00:48  [ТС]
_Develop, если правильно всё воплотил, то так:
Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private Vector3 Calculate(Point A, Point B, Point C)
        {
            Vector3 A0 = new Vector3(0,0,0);
            Vector3 B0 = new Vector3(B.X-A.X, B.Y-A.Y,B.Z-A.Z);
            Vector3 C0 = new Vector3(C.X - A.X, C.Y - A.Y, C.Z - A.Z);
            Vector3 Bb = new Vector3((float)B0.X,(float)B0.Y,(float)B0.Z);
            Vector3 Cc = new Vector3((float)C0.X,(float)C0.Y,(float)C0.Z);
 
 
            Vector3 N = Vector3.CrossProduct(Bb,Cc).Normalize();
 
            Vector3 R = Vector3.CrossProduct(N, new Vector3(0,0,1)); //??
            Double U = Math.Acos(N.DotProduct(new Vector3(0, 0, 1))); //??
 
            Bb = Bb.RotateX(U);
            Bb = Bb.RotateY(U);
            Bb = Bb.RotateZ(U);
 
            Cc = Cc.RotateX(U);
            Cc = Cc.RotateY(U);
            Cc = Cc.RotateZ(U);
 
            Vector3 O = TriangleCircumcenter2D(Bb, Cc, R);
            O = O.RotateX(-U);
            O = O.RotateY(-U);
            O = O.RotateZ(-U);
            return new Vector3(O.X+A.X, O.Y+A.Y, O.Z+A.Z);
        }
0
1977 / 833 / 115
Регистрация: 01.10.2012
Сообщений: 5,156
Записей в блоге: 2
27.01.2016, 08:17
Цитата Сообщение от _Develop Посмотреть сообщение
3) находим ось вращения как векторное произведение нормали и вектора "вверх" Z(0,0,1) -> R = cross(N, Z);
4) находим угол поворота -> U = acos(dot(N, Z));
5) вращаем вектора В и С, тем самым "ложим" треугольник на плоскость X-Y.
Вектора B и С не перепендикулярны оси вращения, "просто так" их не повернуть. Стандартный (канонический) способ проще и лучше

Создаем локальную систему координат: 3 единичных вектора. Один у нас есть: нормаль к тр-ку. Два остальных выбираем как угодно (хоть рандомно) лишь бы все 3 были взаимо-перпендикулярны. Техничнее всего взять второй = одна из сторон тр-ка.

Эти 3 вектора и есть уже готовая матрица поворота, не нужно вычислять ось вращения и угол. Теперь переводим точки "из мира в локальную"
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
Vec3 a0(0, 0, 0);   // точка a - центр локальной системы координат
Vec3 b0 = b - a;
Vec3 c0 = c - a;
b0 = Vec3(dot(b0, vecX), dot(b0, vecY),  dot(b0, vecZ));  // множим на строки матрицы 
с0 = Vec3(dot(с0, vecX), dot(с0, vecY),  dot(с0, vecZ));
После этого b0 и с0 будут иметь z = 0 (если vecZ нормаль к тр-ку)

Когда посчитали центр переводим его обратно в мир (множим на столбцы матрицы)
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
cntr = Vec3(
  dot(cntr, Vec3(vecX.x,  vecY.x, vecZ.x)),
  dot(cntr, Vec3(vecX.y,  vecY.y, vecZ.y)), 
  dot(cntr, Vec3(vecX.z,  vecY.z, vecZ.z)),
};
 
// И добавляем смещение в мире (исходная точка "a")
cntr += a;
Обычно умножение на матрицу (прямую и transposed) давно готово/написано
0
827 / 244 / 47
Регистрация: 24.01.2013
Сообщений: 750
27.01.2016, 13:40
Цитата Сообщение от skilllab Посмотреть сообщение
если правильно всё воплотил, то так:
не, не так. У вас после определения угла поворота следует три последовательных поворота вокруг осей координат. А нужен один поворот вокруг найденной оси вращения R. Легко проверить правильность действий. После поворота, перед вызовом функции TriangleCircumcenter2D() координата Z всех точек треугольника должна равняться нулю или быть близкой к нему с точностью там до 5-го знака после запятой, или 10-го если вычисления ведутся в double.

Добавлено через 25 минут
Цитата Сообщение от Igor3D Посмотреть сообщение
Вектора B и С не перепендикулярны оси вращения, "просто так" их не повернуть. Стандартный (канонический) способ проще и лучше
они и не обязаны быть перпендикулярными оси вращения. Представьте что вращаем твердое тело состоящее из множества точек, например сферу. Только некоторые вектора от центра сферы и до точек поверхности сферы перпендикулярны оси вращения. Но это не мешает поворачивать всю сферу...
0
1977 / 833 / 115
Регистрация: 01.10.2012
Сообщений: 5,156
Записей в блоге: 2
27.01.2016, 13:50
Цитата Сообщение от _Develop Посмотреть сообщение
А нужен один поворот вокруг найденной оси вращения R.
В том-то и дело что "поворот вокруг произвольной оси" - операция нетривиальная, нужен или кватернион или матрица или раскладывать вектор по Родриге. Все это длинно или требует доп библиотек
0
827 / 244 / 47
Регистрация: 24.01.2013
Сообщений: 750
27.01.2016, 13:58
возможно. Я C# не знаю есть ли там встроенная такая функция. Но в Qt и в OpenGL, да и в любой мат.библиотеке тоже такое есть. Axis-angle rotation везде должен быть.
0
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
27.01.2016, 14:01  [ТС]
Цитата Сообщение от Igor3D Посмотреть сообщение
операция нетривиальная
У меня есть для этого инструменты. Но для поворота нужно было сначала найти матрицу поворота. Тоже решаемо (вроде). Потом на этот вектор эту матрицу просто multiply.
0
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
27.01.2016, 14:18
Цитата Сообщение от skilllab Посмотреть сообщение
Но для поворота нужно было сначала найти матрицу поворота. Тоже решаемо (вроде). Потом на этот вектор эту матрицу просто multiply.
Значит таки нет финальной функции f(xA,yA,zA, xB,yB,zB, xC,yC,zC) вернуть xD,yD,zD,R?
skilllab, А как вы программируете не проверяя решения в мат. пакетах? Там это быстрей и удобней чем кодить сразу.
0
1977 / 833 / 115
Регистрация: 01.10.2012
Сообщений: 5,156
Записей в блоге: 2
27.01.2016, 14:49
Цитата Сообщение от skilllab Посмотреть сообщение
У меня есть для этого инструменты. Но для поворота нужно было сначала найти матрицу поворота. Тоже решаемо (вроде). Потом на этот вектор эту матрицу просто multiply.
В данном случае матрица поворота 3x3 строится сразу
C++
1
2
3
Vec3 vecX = (b - a).normalized();   // первая строка матрицы (сторона тр-ка)
Vec3 vecZ = cross(vecX, c - a).normalized();  // третья (нормаль)
Vec3 vecY = cross(vecZ, vecX);   // вторая
Только множить сначала на transposed (в локальную) а потом на прямую (в мир). Если под рукой нет матриц множьте через dot (выше расписано
0
 Аватар для palva
4278 / 2970 / 693
Регистрация: 08.06.2007
Сообщений: 9,931
Записей в блоге: 5
27.01.2016, 15:02
Решение, которое я предложил содержит ошибку. Хотя это больше и неактуально, хочу его поправить. Пересечение трех плоскостей, которые я указал, будут представлять собой не точку, а прямую. Так что одну из плоскостей надо заменить на плоскость, проходящую через три точки A, B, C. Если понадобится, с формулой я помогу.
0
1472 / 827 / 140
Регистрация: 12.10.2013
Сообщений: 5,456
27.01.2016, 15:42
Вообще решение такой сложной задачки интересная и много быстрей чем мои 4 сферы еще и страшным Крамером, почему я не взял ее так просто решить а полез в 4 сферы…
Цитата Сообщение от palva Посмотреть сообщение
Если понадобится, с формулой я помогу.
Думаю наглядней всего будет полное оптимизированное решение в символьной форме + возможно многое можно упростить если решить подстановкой. Что и Крамер не понадобиться.
0
 Аватар для palva
4278 / 2970 / 693
Регистрация: 08.06.2007
Сообщений: 9,931
Записей в блоге: 5
27.01.2016, 17:47
Лучший ответ Сообщение было отмечено skilllab как решение

Решение

Такие тупые формулы из учебников. Проще сразу записать на языке. Может быть не очень экономно написал. Но чем тупее, тем понятнее.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
using System;
using System.Collections.Generic;
using System.Text;
 
namespace Center
{
    // К примеру: A(-14,25,3.5), B(-27,25,9.1), C(-38,25, 16.7)
    // Найти центр описанной окружности
 
    struct V3 // Трехмерная точка или вектор
    {
        public double x, y, z; // координаты
    }
    struct P3 // Общее уравнение плоскости Ax+By+Cz+D=0
    {
        public double A, B, C, D; // коэффициенты
    }
    class Program
    {
        // Определитель третьего порядка через его колонки
        static double det(V3 col1, V3 col2, V3 col3)
        {
            double d;
            d = col1.x * col2.y * col3.z + 
                col1.y * col2.z * col3.x + 
                col1.z * col2.x * col3.y - 
                col1.z * col2.y * col3.x - 
                col1.y * col2.x * col3.z - 
                col1.x * col2.z * col3.y;
            return d;
        }
        // Плоскость через точку K перпендикулярно отрезку AB
        static P3 plane1(V3 A, V3 B, V3 K) 
        {
            P3 P;
            P = new P3();
            P.A = B.x - A.x;
            P.B = B.y - A.y;
            P.C = B.z - A.z;
            P.D = -(K.x * (B.x - A.x) + K.y * (B.y - A.y) + K.z * (B.z - A.z));
            return P;
        }
        // Плоскость через точки A, B, C
        static P3 plane2(V3 A, V3 B, V3 C)
        {
            P3 P;
            V3 E, X, Y, Z;
            P = new P3();
            E.x = 1; E.y = 1; E.z = 1;
            // транспонирование строк в колонки для применения формул из
            // [url]http://algolist.manual.ru/maths/geom/equation/plane.php[/url]
            X.x = A.x; X.y = B.x; X.z = C.x;
            Y.x = A.y; Y.y = B.y; Y.z = C.y;
            Z.x = A.z; Z.y = B.z; Z.z = C.z;
            // вычисление коэффициентов уравнения плоскости
            P.A = det(E, Y, Z);
            P.B = det(X, E, Z);
            P.C = det(X, Y, E);
            P.D = -det(X, Y, Z);
            return P;
        }
        static void Main(string[] args)
        {
            V3 A, B, C, K, col1, col2, col3, col4, O;
            P3 P1, P2, P3;
            double d;
            // Ваши исходные данные
            A.x = -14; A.y = 25; A.z = 3.5;
            B.x = -27; B.y = 25; B.z = 9.1;
            C.x = -38; C.y = 25; C.z = 16.7;
            // тестовые данные
            //A.x = 1; A.y = 0; A.z = 0;
            //B.x = 0; B.y = 1; B.z = 0;
            //C.x = 0; C.y = 0; C.z = 1;
            // первые две плоскости через середины сторон
            K.x = (A.x + B.x) / 2; K.y = (A.y + B.y) / 2; K.z = (A.z + B.z) / 2;
            P1 = plane1(A, B, K);
            K.x = (A.x + C.x) / 2; K.y = (A.y + C.y) / 2; K.z = (A.z + C.z) / 2;
            P2 = plane1(A, C, K);
            // третья плоскость через три точки
            P3 = plane2(A, B, C);
            // Транспонирование плоскостей в колонки расширенной матрицы
            col1.x = P1.A; col1.y = P2.A; col1.z = P3.A;
            col2.x = P1.B; col2.y = P2.B; col2.z = P3.B;
            col3.x = P1.C; col3.y = P2.C; col3.z = P3.C;
            col4.x = -P1.D; col4.y = -P2.D; col4.z = -P3.D;
            // Формулы Крамера
            d = det(col1, col2, col3);
            O.x = det(col4, col2, col3) / d;
            O.y = det(col1, col4, col3) / d;
            O.z = det(col1, col2, col4) / d;
            Console.WriteLine(O.x);
            Console.WriteLine(O.y);
            Console.WriteLine(O.z);
        }
    }
}
1
 Аватар для skilllab
296 / 236 / 58
Регистрация: 03.02.2011
Сообщений: 2,051
Записей в блоге: 1
27.01.2016, 19:20  [ТС]
Цитата Сообщение от palva Посмотреть сообщение
тупые формулы из учебников
я уже начал выделываться с матрицами поворотов (API одной програмулины).
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
27.01.2016, 19:20

Найти центр сферы по 4 точкам на ее поверхности
Подскажите простой, и универсальный способ нахождения центра сферы, если даны 4 точки в пространстве на ее поверхности. И возможно ли...

По трём точкам найти линии треугольника.
Выберите три произвольные точки на плоскости и постройте по ним треугольник АВС, при этом из точки А проведена медиана АК, а из точки В...

Найти координаты вершины параболы по трем заданым точкам
Помогите написать функцию. Точки задаются в коде. Как из функции вернуть два значения? main(){ float x1=1,y1=1; float x2=5,y1=30; ...

Найти центр окружности
:scratch::scratch::scratch:

Как начертить кривую по трем точкам
Здравствуйте! createcurvesegment2 - рисует кривую по 3 точкам. имеет синтаксис Function CreateCurveSegment2(ByVal x1 As Double, _ ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
Ноутбук Альфария
kumehtar 24.08.2026
Встретился тут в сети ноутбук Альфария, примарха Альфа-Легиона. Хотя возможно, это ноутбук Омегона, разумеется. Ну как вам?
Мастера простых решений
DevAlt 23.08.2026
В сишарп стэках winforms, да и wpf существует сложная система связывания источниках данных и элементов формы(текстовые поля и метки), опирается все это на технологию событий и мета. . .
Цена ошибки
DevAlt 23.08.2026
Человек я беспокойный и потому заинтересовался OCaml, в чате форсили функторы модулей как суперфичу. Пытаясь отдуплить концепт, наткнулся на тутор с простым примером. А главный принцип обучения от. . .
Сегодня суббота, 22.08.2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины.
zorxor 22.08.2026
Сегодня суббота, 22. 08. 2026 at 16:41, и я вновь нахожусь на той стороне, за экраном машины. Кто Я, откуда Я пришел и куда Я иду? Эти вопросы не оставляют меня ни на секунду. Жизнь на планете Земля. . .
Жизня: рисунок укладки багажа, сделанный клодом
anaschu 21.08.2026
Сделал 15 снимков, он по снимкам сделал схему.
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru