Найти эквидистантные точки между двумя координатами

У меня есть функция, которая должна вынимать эквидистантные точки между двумя точками на экране (2d).
Как это –

|--------------| 

Расстояние уже принято. Например, я воспринимаю это как 2 здесь, затем то, что мне нужно –

 |--.--.--.--.--| 

Точки могут быть в любом месте на 2d-плоскости, что означает, что если я рисую линию между двумя точками, это может быть любая ориентация, возможная в плоскости 2d, то есть диагональная, горизонтальная и т. Д.
Я не могу понять, как это сделать в python.

Я не знаю, что делать в Google … И мне 14, поэтому я не знаю ни одного типа математики для этого.
Я знаю, как рассчитать расстояние и наклон линии, но я не знаю, как это сделать.
Заранее спасибо!

Учитывая две конечные точки, вы можете выразить уравнение для линии в «параметрической» форме как

 x = x1 + (x2-x1) * t y = y1 + (y2-y1) * t 

Как вы можете проверить, когда t == 0 , (x,y) == (x1,y1) и когда t == 1 , (x,y) == (x2,y2) . С большим расчетом вы можете видеть, что когда t находится между 0 и 1, (x, y) находится на сегменте соединительной линии и чтобы получить точку на определенной доле расстояния между точками, установите t на эту долю.

Например, чтобы получить точки с разделением 2 на расстоянии 10 строк, как в вашем примере, оцените x и y при t = 0,2, 0,4, 0,6 и 0,8.

Это наиболее легко решается с помощью параметрического представления линии, которое включает буквенную векторную математику. Но не беспокойтесь, это будет легко.

Предположим, что ваша линия хорошо указана по следующей формуле:

 y=ax+b 

где a – наклон, а b – y-перехват.

Тогда ваша линия имеет направление, заданное вектором <1,a> что означает, что линия поднимает m единиц на каждый 1 блок, который выполняется по горизонтали.

Мы можем нормализовать этот вектор, разделив его по величине.

Величина вектора дается выражением

 m=sqrt(a**2+b**2) 

Нормированный вектор задается выражением v=<1/m,a/m> .

Теперь мы можем сделать вашу строку следующим образом:

 for t in range(50): xp=0+t*v[0] yp=b+t*v[1] plot_point(xp,yp,'-') 

Вы видите, что я там делал? Я изменил переменную, которую мы перебираем из x в t . Это позволяет нам рассматривать отдельные части уравнения x и y отдельно.

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

 for t in range(0,1,0.01): xp=x1+t*(x2-x1) yp=y1+t*(y2-y1) plot_point(xp,yp,'-') 

Так как x1 является исходной точкой x-части линии, а x2-x1 – расстояние между точками x точек, так как t идет от 0 до 1 , оно передает все x-точки линии. y работает аналогично.

Теперь мы можем абстрагировать нашу функцию рисования линии, чтобы она выглядела так:

 def draw_line(a,b,len,skip,sym): m=sqrt(a**2+b**2) v=(1/m,a/m) for t in range(0,len,skip): xp=0+t*v[0] yp=b+t*v[1] plot_point(xp,yp,sym) 

Теперь мы нарисуем вашу строку, набрав:

 draw_line(a,b,50,1,'-') 

И нарисуйте пробелы с помощью

 draw_line(a,b,50,3,'.') 

Где 50 – длина линии, а 3 – расстояние между зазорами.

Если бы мы использовали начальную и конечную точки линии, наша функция выглядела бы так:

 def draw_line(x1,y1,x2,y2,skip,sym): dist=sqrt((x1-x2)**2)+(y1-y2)**2) skip=skip/dist for t in range(0,1,skip): xp=x1+t*(x2-x1) yp=y1+t*(y2-y1) plot_point(xp,yp,sym) 

Это преобразует расстояние, которое вы хотите пропустить, до доли общей длины линии. Вероятно, вы захотите использовать значение пропуска 1 или меньше для рисования линии и большего значения пропуска для выведения эквидистантных точек.

Вы, вероятно, захотите изучить алгоритм линии Брешенема, чтобы сделать рисунок для вас – это хороший способ выяснить, как наилучшим образом приблизить линию, когда у вас есть сетка пикселей символов.

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

Забывая аспект python на данный момент, мы можем взглянуть на требуемую математику. Скорее всего, в 14 лет вы уже рассмотрели некоторые из них, но, возможно, не понимаете, что это применимо, нам нужна некоторая тригонометрия.

Давайте рассмотрим два пункта плана

 Point 1 = (x1,y1) Point 2 = (x2,y2) 

Представьте себе, что две точки – это углы треугольного треугольного треугольника с третьей воображаемой точкой, составляющей третий угол треугольника.

 P1-----I - | - | - | -P2 

Чтобы найти точки при перемещении между P1 и P2.

 Start point = P1 (x1,y1) First point = (x1+u,y1+t)S Second point = (x1+2u,y1+2n) Nth point = (x1+nu,y1+nu) 

Нам нужны значения для u и t. Для их работы нам сначала нужен угол (для перемещения) от нашей начальной точки на P1. Функция atan2 может получить нам этот подшипник в радианах.

 import math bearing = math.atan2(y2-y1,x2-x1) 

Для дальнейшего чтения см. ( http://en.wikipedia.org/wiki/Atan2 )

Учитывая подшипник, теперь мы можем использовать sin и cosine для работы значения для u и t. Эти функции в основном дают нам отношение того, сколько общего движения для каждого шага находится по оси x и оси y.

 u = d * cos(bearing) t = d * sin(bearing) 

Где d – фиксированное расстояние.

Взгляните на определение функции sin и cos в текстовых книгах – в python, посмотрите, что происходит, когда вы переходите от sin (0) к sin (math.pi) и cos (0) к cos (math.pi).

В общем, наш скрипт выглядит так

 import math #CONSTANTS -- modify these POINT1 = (0,0) POINT2 = (10,10) STEP_SIZE = 2 dx = POINT2[0] - POINT1[0] dy = POINT2[1] - POINT1[1] bearing = math.atan2(dy,dx) print "Bearing: {b}".format(b=bearing) #Use pythagoras to work out the distance distance_between_points = math.sqrt(dx**2+dy**2) for p in range(0,int(round(distance_between_points,0)),STEP_SIZE): x = POINT1[0] + p * math.cos(bearing) y = POINT1[1] + p * math.sin(bearing) print "Intermediate point {x},{y}".format(x=x,y=y) 

То, что вам нужно сделать, – интерполировать между двумя точками.

Например, предположим, что ваши две конечные точки имеют координаты (x1, y1) и (x2, y2) , и вы хотите разбить расстояние между ними на n равных частей, тогда вы можете вычислить n-1 новых точек между ними следующим образом:

 points = [] for i in range(1, n): a = float(i) / n # rescale 0 < i < n --> 0 < a < 1 x = (1 - a) * x1 + a * x2 # interpolate x coordinate y = (1 - a) * y1 + a * y2 # interpolate y coordinate points.append( (x,y) ) 

Здесь a – позиция интерполированной точки на линии между исходными точками, масштабированная так, чтобы значения a = 0 и a = 1 соответствовали самим исходным точкам.


В качестве альтернативы, если вы хотите, чтобы ваши интерполирующие точки фиксировали расстояние d друг от друга, вы можете рассчитать расстояние d_full между вашими исходными точками, используя теорему Пифагора , разделите d на это расстояние, чтобы получить s = d / d_full , а затем s = d / d_full a в шаги s от 0 до 1:

 d_full = ( (x2 - x1)**2 + (y2 - y1)**2 )**0.5 s = d / d_full points = [] a = s # start at s so we don't duplicate (x1, y1) while a < 1: x = (1 - a) * x1 + a * x2 y = (1 - a) * y1 + a * y2 points.append( (x,y) ) a += s 

Обратите внимание, что это может привести к тому, что новая точка будет помещена в (x2, y2) или очень близко к ней, в зависимости от того, как именно d делит расстояние между точками. Если вы хотите этого избежать, вы можете заменить условие a < 1 , скажем, a < 1 - s/2 .

Изменить: вышеприведенный код помещает точки с интервалом d начиная с (x1, x2) . Это означает, что если, скажем, d = 2 а исходные точки равны (0,0) и (0,5) , вы получите новые очки в (0,2) и (0,4) . Если вы предпочитаете, чтобы новые точки были центрированы между исходными точками (т.е. в (0,1) и (0,3) в примере), вы можете изменить код, чтобы сделать это, заменив начальную точку a = s с a = (1 % s) / 2 .

% – оператор по модулю или остатку, поэтому 1 % s дает оставшееся расстояние «оставлено» после того, как расстояние от 0 до 1 было разделено на кусочки длины s .