powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Нужен математик уже не могу
20 сообщений из 20, страница 1 из 1
Нужен математик уже не могу
    #34955851
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Простая задача - найти точку пересечения двух прямых. Помню в
школе решали и все ок получалось, но забыла формулы и
весь алгоритм расчета. Нашла Inete вроде тот школьный метод.
Но с ним чудеса, то вычисляет, то черти шо..

Вот метод
Код: plaintext
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.
На плоскости заданы два отрезка a и b, a - точками A1(A1x,A1y) и A2(A2x,A2y), 
а b - точками B1(B1x,B1y) и B2(B2x,B2y). 
Найти и напечатать возможную точку их пересечения C(Cx,Cy). 
Задача в основном на геометрию, программирования особого здесь нет. 
Рассмотрим первый отрезок a. Уравнение прямой, на которой он лежит можно записать так:
xa = A1x + ta (A2x - A1x)
ya = A1y + ta (A2y - A1y)
Здесь, A1x,A1y,A2x,A2y - суть константы, xa,ya - суть точки отрезка, при ta 
пробегающем значения от [ 0 , 1 ] Аналогично для отрезка b:
xb = B1x + tb (B2x - B1x)
yb = B1y + tb (B2y - B1y)
Таким образом, приравнивая соответствующие координаты, получаем задачу 
нахождения параметров ta,tb, при которых бы выполнялись равенства:
A1x + ta (A2x - A1x) = B1x + tb (B2x - B1x)
A1y + ta (A2y - A1y) = B1y + tb (B2y - B1y)
После разрешения системы относительно ta,tb получаем:
ta (A1x - A2x) + tb (B2x - B1x) = A1x - B1x
ta (A1y - A2y) + tb (B2y - B1y) = A1y - B1y
А это есть система из двух линейных урвавнений относительно ta,tb. 
Известно, что система:
a1 x + b1 y = c1
a2 x + b2 y = c2
имеет следующее решение:
x = dx/d
y = dy/d,
где d - определитель матрицы, 
d = a1b2 - a2b1,
dx = c1b2 - c2b1,
dy = a1c2 - a2c1.
В нашей системе относительно ta,tb:
a1 = A1x - A2x 
b1 = B2x - B1x
c1 = A1x - B1x

a2 = A1y - A2y
b2 = B2y - B1y
c2 = A1y - B1y
откуда легко находится d,dx,dy. Если d отличен от нуля, то система имеет 
единственное решение. Правда, следует помнить, что искомые ta,tb -
 параметрически задают отрезки только если они лежат в диапазоне [ 0 , 1 ], 
в противном случае точка пересечения прямых, на которых лежат 
отрезки, находится вне этих самых отрезков.
Если d равен нулю, а хотя бы один из dx,dy отличен от нуля, то отрезки лежат 
на параллельных прямых, или как говорят математики, они коллинеарны. 
Если же все три d,dx,dy равны нулю, то это значит, что отрезки лежат 
на одной и той же прямой, где опять возможны три случая - либо отрезки не перекрываются, 
либо перекрываются в одной точке, либо перекрываются в бесконечном множестве точек. 

Вот программа
Код: plaintext
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.
import java.lang.Math;
import java.io.*;

public class findPoint{
  Double Ax1, Ax2, Ay1, Ay2;
  Double Bx1, Bx2, By1, By2;
  Double a1, b1, c1, a2, c2, b2;
  Double d, dx, dy;
  Double ta,tb;
  Double x, y, U, W;
  Double eps = new Double( 0 . 000001 );

  public findPoint(Double AX1, Double AX2, Double  AY1, Double  AY2,
                         Double BX1, Double BX2, Double  BY1, Double  BY2){
    Ax1 = new Double(AX1);
	Ax2 = new Double(AX2);
	Ay1 = new Double(AY1); 
	Ay2 = new Double(AY2);

	Bx1 = new Double(BX1);
	Bx2 = new Double(BX2);
	By1 = new Double(BY1); 
	By2 = new Double(BY2);

            a1 = new Double(Ax1 -Ax2);
	b1 = new Double(Bx2 -Bx1);
	c1 = new Double(Ax1 -Bx1);

	a2 = new Double(Ay1 -Ay2);
	b2 = new Double(By2 -By1);
	c2 = new Double(Ay1 -By1);
 
             d = new Double(a1*b2 - a2*b1);
	dx = new Double(c1*b2 - c2*b1);
            dy = new Double(a1*c2 - a2*c1);
	
	if (Math.abs(d) < eps)
	{
		x = new Double( 0 . 0 );
                          y = new Double( 0 . 0 );
		return;
	}

    ta = new Double(dx/d);
    tb = new Double(dy/d);

    x = new Double(Bx1 + tb * (Bx2 - Bx1));
    y = new Double(By1 + tb * (By2 - By1));

  }

  public Double axisX(){
    return x;
  }

  public Double axisY(){
    return y;
  }
}

Для все ок

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
findPoint fp = new findPoint(   30 . 0 ,  10 . 0 ,  0 . 0 , 10 . 0  , 10 . 0 ,  0 . 0 ,   10 . 0 , 20 . 0    );  
g2d.setColor(Color.orange);
g2d.draw(new Line2D.Double(  30 . 0 ,  10 . 0 ,  0 . 0 , 10 . 0   ));
g2d.draw(new Line2D.Double( 10 . 0 ,  0 . 0 ,   10 . 0 , 20 . 0 ));
...

Double X = new Double(fp.axisX());
Double Y = new Double(fp.axisY());
g2d.setColor(Color.black);
g2d.draw(new Line2D.Double(X, Y, X, Y));

Но все другие коор-ты не правильно вычисляются
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956177
помню в школе мы это дело решали дихотомией.
зы. приведенное решение не читал. Мошт оно и лучше.
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956184
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SATURN2 wrote:

> Простая задача - найти точку пересечения двух прямых
двумерных, трехмерных, отрезков, лучей, или бесконечных линий?
--
We are all going to hell and I'm driving the bus
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956197
тьпу ты. А для простых прямых - не легче ли простую формулу вывести?
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956201
Фотография Софтверный проктолог
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Простой вопрос: зачем вы постоянно используете объект Double вместо примитива double?
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956214
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, вот живой глюк

Так все ОК
Код: plaintext
1.
findPoint fp = new findPoint(   [color=red] 300 . 0 ,  100 . 0 , 100 . 0 , 100 . 0  [/color],     100 . 0 ,  100 . 0 ,   100 . 0 , 200 . 0    );   


А так в результате пересечения нет С(0,0)

Код: plaintext
findPoint fp = new findPoint(  [color=red] 100 . 0 , 100 . 0  ,  300 . 0 ,  100 . 0 [/color],     100 . 0 ,  100 . 0 ,   100 . 0 , 200 . 0    ); 

Помогите, так не хочется в библиотеку идти.
Чего-то методу не хватает.
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956238
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErV Простая задача - найти точку пересечения двух прямых
двумерных, трехмерных, отрезков, лучей, или бесконечных линий?

Двух отрезков в двумерном пространстве


тот самый любительА для простых прямых - не легче ли простую формулу вывести?
Что вы имеете в виду?
Метод вверху и так прост.

Софтверный проктологПростой вопрос: зачем вы постоянно используете объект Double вместо примитива double?

Плохо знаю жаву
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956273
SATURN2

тот самый любительА для простых прямых - не легче ли простую формулу вывести?
Что вы имеете в виду?
Метод вверху и так прост.



А вот на форуме жава у товарища expp возникла такая же простая мысль как и у меня.
зы. опять же не читал "верхний метод". уж больно много понаписано.
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956310
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Класно вам - вы умные.
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956346
Фотография Софтверный проктолог
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во всем этом меня смущает один момент
Код: plaintext
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.
 public   class  TwoLines {

     public  TwoLines() {
        Line first =  new  Line( 100 ,  300 ,  100 ,  100 );
        Line second =  new  Line( 100 ,  100 ,  100 ,  200 );

        Point res =  this .getIntersectOfLines(first, second);
         if  (res ==  null ) {
            System.out.println("Lines are collinear");
        }  else  {
            System.out.println("result : " + res + " for " + first + "/" + second);
        }
    }

     private   final   static   double  EPS =  0 . 000001 ;

     public  Point getIntersectOfLines(Line A, Line B) {
        Point returnPoint =  new  Point( 0 ,  0 );

         double  a1 = A.p1.x - A.p2.x;
         double  b1 = B.p2.x - B.p1.x;
         double  c1 = A.p1.x - B.p1.x;

         double  a2 = A.p1.y - A.p2.y;
         double  b2 = B.p2.y - B.p1.y;
         double  c2 = A.p1.y - B.p1.y;

         double  d = a1 * b2 - a2 * b1;
         double  dx = c1 * b2 - c2 * b1;
         double  dy = a1 * c2 - a2 * c1;

         if  (d < EPS) {
             if  (dx > EPS || dy > EPS) {
                 return   null ;
            }
        }  else  {
             double  ta = dx / d;
             double  tb = dy / d;

             double  x = B.p1.x + tb * (B.p2.x - B.p1.x);
             double  y = B.p1.y + tb * (B.p2.y - B.p1.y);
            
            returnPoint =  new  Point(x, y);
        }
         return  returnPoint;
    }

     public   static   void  main(String args[]) {
        TwoLines resolver =  new  TwoLines();
    }

     private   class  Point {

         public  Point( double  x,  double  y) {
             this .x = x;
             this .y = y;
        }


         private   double  x;
         private   double  y;

         public  String toString() {
             return  "x = " + x + ", y = " + y;
        }
    }


     private   class  Line {

         public  Line( double  A1x,  double  A1y,  double  A2x,  double  A2y) {
             this .p1 =  new  Point(A1x, A1y);
             this .p2 =  new  Point(A2x, A2y);
        }

         public  Line(Point p1, Point p2) {
             this .p1 = p1;
             this .p2 = p2;

        }

         private  Point p1;
         private  Point p2;

         public  String toString() {
             return  "Point 1 [" + p1 + "] Point 2 [" + p2 + "]";
        }

    }

}

a1, b1 и c1 при положении линии по-вертикали и совпадении одной координатой x со второй линией будут равны нулю.
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956418
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Софтверный проктолог Во всем этом меня смущает один момент
...


В том то ж и дело. Глючный метод. Но мне кажется, что в школе
мы использовали что очень похожее (надо будет проверить).

Кстати, а так все в порядке
Line first = new Line(300, 100, 100, 100);
Line second = new Line(100, 100, 100, 200);

Метод приведенный тут преподовали по
"вышке". Уже все забыла:(
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956422
Фотография Софтверный проктолог
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SATURN2
Кстати, а так все в порядке
Line first = new Line(300, 100, 100, 100);
Line second = new Line(100, 100, 100, 200);
Это да, как и у вас. Сам метод решения я не проверял (а просто показал, что можно сделать по-другому и что вы не ошиблись в кодировании).
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956491
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А, вообще б не плохо б было сделать
раздел "Алгоритмы расчета, математика, геометрия ..."
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956498
Фотография Софтверный проктолог
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SATURN2А, вообще б не плохо б было сделать
раздел "Алгоритмы расчета, математика, геометрия ..."
И будете там вместе с десятком школьников задачки решать? :)
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956527
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SATURN2 wrote:

> Двух отрезков в двумерном пространстве
"Код вверху" я ковырять не буду, так как мне влом восстанавливать
алгоритм по чужому коду.

Можно решить задачу как систему уравнений. (не тестил, опечатки могут
быть)

Пусть p1start - начало первого отрезка,
p1end - конец
p2start - начало второго
p2end - конец, тогда

v1 = p1end-p1start
v2 = p2end-p2start

тогда ищется точки I, для которой справедливо:
I = p1star + v1*t1 = p2start +v2*t2, где t1 и t2 скаляры в диапазоне от
0 до 1.

А теперь разворачиваем уравнение:
p1start +v1*t1 = p2start +v2*t2
v1*t1 - v2*t2 = p2start - p1start;

Поскольку аргументы двухкомпонентные, разворачиваем:
v1.x*t1 - v2.x*t2 = p2start.x - p1start.x;
v1.y*t1 - v2.y*t2 = p2start.y - p1start.y;
ищем t1 и t2:
t1 = (p2start.y - p1start.y + v2.y*t2)/v1.y
t2 = (v1.x*t1 - p2start.x + p1.start.x)/v2.x

Раскрываем скобки:
t1 = p2start.y/v2.y - p1start.y/v2.y + v2.y*t2/v1.y
t2 = v1.x*t1/v2.x - p2start.x/v2.x + p1.start.x/v2.x

Подставляем t2 в t1:
t1 = p2start.y/v2.y - p1start.y/v2.y + (v1.x*t1/v2.x - p2start.x/v2.x +
p1start.x/v2.x)*v2.y/v1.y

раскрываем скобки:
t1 = p2start.y/v2.y - p1start.y/v2.y +
v1.x*t1*v2.y/(v2.x*v1.y) - p2start.x*v2.y/(v2.x*v1.y) +
p1start.x*v2.y/(v2.x*v1.y)

либо наоборот, закрываем :)
t1 = (p2start.y - p1start.y)/v2.y + ((v1.x*t1 - p2start.x +
p1start.x)*v2.y/(v2.x*v1.y)

вычисляем значение t1, находим точку пересечения по
I = p1start + v1 * t1; если t1 < 0 или > 1, значит, функции не
пересекаются.

Да, и здесь могут быть опечатки, и деления на ноль при определенных
входных данных :)

Второй вариант:
геометрически.
отрезки p1start - p1end и p2start и p2end образуют треугольник p1start -
I - p2start, если линии пересекауются.
вводим вектор diff = p2start - p1start.
используем те же вектора v1 = p1end - p1start и v2 = p2end - p1start
далее.
обозначаем dot как дот.продукт (т.е. скалярное произведение, если оно
по-русски так называется - dot(v1, v2) = v1.x*v2.y + v1.y*v2.y)
далее:
1) Если dot(v1, diff) <= 0 и dot(v2,diff) >= 0, отрезки не пересекаются.
2) Если не жалко нормализовывать вектора (normalize(v1) = v1/length(v1),
то можно добавить проверки:
2.1) если dot(normalize(v1), normalize(diff)) < 0 и dot(normalize(v2),
normalize(diff)) < 0, то лучи исходящие из p1start и p2start,
пересекаются, если dot(normalize(v1), normalize(diff)) >
dot(normalize(v2), normalize(diff))
2.2) если dot(normalize(v1), normalize(diff)) > 0 и dot(normalize(v2),
normalize(diff)) > 0, то лучи исходящие из p1start и p2start,
пересекаются, если dot(normalize(v1), normalize(diff)) <
dot(normalize(v2), normalize(diff))

далее.
После прохождения проверок имеем "треугольник" с основанием diff и
боковыми сторонами, образованными лучами v1 и v2 и точкой их
пересечение. Из вектора diff можно получить перпендикуляр к основанию,
повернув вектор на 90градусов (называем его difft, где difft.x
= -diff.y и difft.y = diff.x). Нафига это надо? А фишка в том, что
получаем новую координатную систему, где diff - это ось x, а difft -
ось y, и в новой координатной системе задача проще - так как обе точки
будут иметь одинаковые y-координаты. (y-координаты в новой системе
вычисляются через pnew = dot(normalize(difft), p) , x - вычисляются
через pnew = dot(normalize(diff), p)

После перевода в новую систему имеем задачу с ограничениями типа:
pnew1start.y = pnew2start.y = 0
pnew1start.x = 0
Inew.x = vnew1.x*t1 = pnew2start.x + v2.x*t2
Inew.y = vnew1.y*t1 = vnew2.y*t2

Далее решаем математически. (потому что уже проще)

ЗЫ. Да, и если сильно влом, то можно просто тупо взять маткад, вбить
туда стартовые формулы и попросить его решить задачу символически для
нужной переменной.

--
We are all going to hell and I'm driving the bus
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956548
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErV wrote:

> ...
По-моему, я загнался... :-\

--
We are all going to hell and I'm driving the bus
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956804
mikhail_n
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Если у Вас до сих пор нет варианта корректно работающего для любых входных данных, то просто используйте следующие формулы. В Вашей нотации:


На плоскости заданы два отрезка a и b, a - точками A1(A1x,A1y) и A2(A2x,A2y),
а b - точками B1(B1x,B1y) и B2(B2x,B2y).

const double EPS = 1.0D-16;

double xdet, ydet;

double det = (B1x - B2x) * (A2y - A1y) - (A1x - A2x) * (B2y - B1y);


if(dabs(det) < EPS)
printf("The two segments are either parallel or too close to being parallel\n");
else
{
xdet = (A1x*A2y - A1y*A2x) * (B1x - B2x) - (B1x*B2y - B1y*B2x) * (A1x - A2x);
ydet = (B1x*B2y - B1y*B2x) * (A2y - A1y) - (A1x*A2y - A1y*A2x) * (B2y - B1y);

printf("X - coordinate of the intersection is %d\n", xdet/det);
printf("Y - coordinate of the intersection is %d\n", ydet/det);
}
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956810
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сходу, не проверяя никаких исходников...

Задача имеет 3 варианта ответа:

1) Бесконечное количество решений (прямые совпадают)
2) Пустое множество решений (прямые параллельны)
3) Единственное решение (точка).

Поиск необходимо осуществлять имеенно в этом порядке. Т.е. параллельность образующих векторов, векторное произведение и т.п. нужно вычислить перед тем как искать пункт (3).

Всего!
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34956911
ErV
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче, решение:

стартовая система уравнений:
p1x + v1x*t1 = p2x+v2x*t2
p1y+v1y*t1 = p2y+v2y*t2

где
p1x, p1y - начало первого отрезка
p2x, p2y - начало второго отрезка
v1x, v1y - конец первого отрезка минус начало первого отрезка
v2x, v2y - конец второго отрезка минус начало второго отрезка

точка пересечения находится как:
vec2(p1x + v1x*t1, p1y+v1y*y1) или
vec2(p2x + v2x*t2, p2y+v2y*y2)

а t1 или t2 находится как:
Код: plaintext
1.
2.
3.
4.
5.
6.
     - p2x v2y + p1x v2y + (p2y - p1y) v2x
t1 = -------------------------------------,
              v1y v2x - v1x v2y
    - p2x v1y + p1x v1y + (p2y - p1y) v1x
t2 = -------------------------------------
              v1y v2x - v1x v2y
Усе.
Posted via ActualForum NNTP Server 1.4
...
Рейтинг: 0 / 0
Нужен математик уже не могу
    #34961660
SATURN2
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ErV
- p2x v2y + p1x v2y + (p2y - p1y) v2x
t1 = -------------------------------------,
v1y v2x - v1x v2y
- p2x v1y + p1x v1y + (p2y - p1y) v1x
t2 = -------------------------------------
v1y v2x - v1x v2y
Усе.
Молодец 5 баллов.
...
Рейтинг: 0 / 0
20 сообщений из 20, страница 1 из 1
Форумы / Программирование [игнор отключен] [закрыт для гостей] / Нужен математик уже не могу
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]