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

У меня есть очень простой вопрос о MATLAB. Что является самым легким способом найти точку пересечения между двумя векторами. Я не знаком с различными функциями MATLAB - кажется, что должно быть один для этого.

Например, если у меня есть один вектор от (0,0) до (6,6) и другой вектор от (0,6) до (6,0), я должен решить, что они пересекаются в (3,3).

13
задан Peter Mortensen 10 March 2018 в 13:34
поделиться

3 ответа

Боюсь, это не сработает, поскольку объявленные вами два лямбда-выражения (и делегаты) фактически являются разными объектами и возвращают разные ссылки. Следовательно, удаление обработчика ( - = ) всегда будет неуспешным.

Общим решением этой проблемы (где необходимо удалить обработчик) является просто переформатирование выражения лямбы в правильный метод. Альтернативой является сохранение переменной класса для делегата обработчика событий и добавление и удаление этого, хотя лично я не являюсь его поклонником. (Это больше хлопот, чем просто создание обычного метода, если что.)

-121--1019982-
// Uses the compiler's type inference mechanisms for generics to find out the type
// 'self' was declared with in the current scope.
static public Type GetDeclaredType<TSelf>(TSelf self)
{
    return typeof(TSelf);
}

void Main()
{
    // ...

    Foo bar;
    bar = null;

    Type myType = GetDeclaredType(bar);
    Console.Write(myType.Name);
}

Принты:

Foo

Я разместил это также на аналогичную тему, я надеюсь, что это может быть использовано для вас.; -)

-121--933713-

Одним из решений является использование уравнений, полученных в данном руководстве, для нахождения точки пересечения двух линий в 2-D ( обновление: это ссылка на архив в Интернете, поскольку сайт больше не существует). Сначала можно создать две матрицы: одну для хранения координат x конечных точек линии и одну для сохранения координат y.

x = [0 0; 6 6];  %# Starting points in first row, ending points in second row
y = [0 6; 6 0];

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

dx = diff(x);  %# Take the differences down each column
dy = diff(y);
den = dx(1)*dy(2)-dy(1)*dx(2);  %# Precompute the denominator
ua = (dx(2)*(y(1)-y(3))-dy(2)*(x(1)-x(3)))/den;
ub = (dx(1)*(y(1)-y(3))-dy(1)*(x(1)-x(3)))/den;

Теперь можно вычислить точку пересечения двух строк:

xi = x(1)+ua*dx(1);
yi = y(1)+ua*dy(1);

Для примера в вопросе приведенный выше код дает xi = 3 и yi = 3 , как и ожидалось. Если требуется проверить, что точка пересечения лежит между конечными точками линий (т.е. они являются конечными отрезками ), необходимо просто проверить, что значения ua и ub лежат между 0 и 1:

isInSegment = all(([ua ub] >= 0) & ([ua ub] <= 1));

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

  • Если знаменатель den равен 0, то две линии параллельны.
  • Если знаменатель и числитель для уравнений ua и ub 0, то две строки совпадают.
13
ответ дан 1 December 2019 в 21:52
поделиться

Благодаря Кевину, Митчу и Нафтоли Гугенхайму и Даниэлю Собралу из списка рассылки пользователей, у меня есть хороший ответ. Два предыдущих ответа работают, но приводят к экспоненциальному взрыву в количестве признаков, классов и конструкторов. Однако использование имплицитов и границ просмотра позволяет избежать этой проблемы. Шаги решения:

1) Задать нормальный параметр типа, представляющий тип его аргумента. 2) Определите импликты, принимающие Normal с правильным типом аргумента для того, который реализует соответствующий алгоритм. Например, makeImpression принимает нормальное значение [Важность] и создает нормальное значение важности. 3) Имплицитам нужно дать привязку типа. Причина в том, что без ограничения типа, если вы пытаетесь передать нормальный [T] makeImpression, где T является подтипом важности, он не будет работать, потому что нормальный [T] не является подтипом нормального [важности], потому что нормальный не является ковариантным. 4) Эти границы типа должны быть границами просмотра, чтобы позволить имплицитам связываться.

Вот полное решение:

class Model

trait Importance extends Model {
  def forward: Int
}

trait MCMC extends Model {
  def propose: String
}

class Normal[T <% Model](val arg: T) extends Model

class NormalImportance(arg: Importance) extends Normal(arg) with Importance {
  def forward = arg.forward + 1
}

class NormalMCMC(arg: MCMC) extends Normal(arg) with MCMC {
  def propose = arg.propose + "N"
}

object Normal {
  def apply[T <% Model](a: T) = new Normal[T](a)
}

object Importance {
  implicit def makeImportance[T <% Importance](n: Normal[T]): Importance = 
    new NormalImportance(n.arg)
}

object MCMC {
  implicit def makeMCMC[T <% MCMC](n: Normal[T]): MCMC = new NormalMCMC(n.arg)
}

object Uniform extends Model with Importance with MCMC {
  def forward = 4
  def propose = "Uniform"
}

def main(args: Array[String]) {
  val n = Normal(Normal(Uniform))
  println(n.forward) 
  println(n.propose)
}
-121--3926565-
SELECT  *
FROM    mytable
ORDER BY
        column1 DESC, column2 ASC
-121--1786312-

Ну, у вас действительно есть две точки на двух разных прямых, и вы хотите найти пересечение. Самый простой способ - найти уравнения двух прямых и затем вычислить пересечение.

Уравнение прямой задается как y = mx + b , где m - наклон, а b - y-перехват. Для одной прямой у вас есть две точки, которые дают два уравнения. Таким образом, можно решить для констант m и b . Это дает следующие два уравнения:

 0 = 0*m + 1*b  % Using the first point x=y=0 into y=m*x+b
 6 = 6*m + 1*b  % Using the second point x=y=6

Или в матричной форме:

 [ 0 ] = [ 0 1 ]* [ m ]
 [ 6 ]   [ 6 1 ]  [ b ]

Для первой строки константы могут быть вычислены в MATLAB

 C1 = inv([0 1;6 1]*[1;0]; % m=C1(1) and b=C(2)

Теперь, когда у вас есть уравнение для двух прямых, вы можете решить для пересечения путем решения следующей системы уравнений (которые получены путем манипулирования уравнением для прямой):

 m_1*x-y = -b_1
 m_2*x-y = -b_2

Все, что осталось, это написать вышеуказанную систему уравнений в матричной форме и решить:

 [x] = inv [m_1 -1] * [-b_1]
 [y]       [m_2 -1]   [-b_2]

Или в синтаксисе MATLAB:

 I = inv([m_1 -1; m_2 -1])*[-b_1;-b_2]; % I is the intersection.

Примечания

  • В соответствии с комментарием gnovice, если линии на самом деле являются сегментами линий, необходимо проверить, находится ли пересечение между конечными точками сегментов линий.

  • Если два наклона равны, m_1 = m_2, то пересечений либо не будет, либо будет бесконечно много.

8
ответ дан 1 December 2019 в 21:52
поделиться

Для общего многоразмерного решения вы действительно делаете, решает серию линейных систем.

Сначала вам нужно уменьшить уравнения к линейной форме: AX + by = C (расширить размеры по мере необходимости)

для двух точек:

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

A = (y1 - y2)
B = (x2 - x1)
C = (y1 - y2) * x1 + (x2 - x1) * y1 = A * x1 + B * y1

для вашего примера:

x1 = 0, x2 = 6, y1 = 0, y2 = 6
A1 = (0 - 6) = -6
B1 = (6 - 0) = 6
C1 = A1 * 0 + B1 * 0 = 0

x1 = 0, x2 = 6, y1 = 6, y2 = 0
A2 = (6 - 0) = 6
B2 = (6 - 0) = 6
C2 = A2 * 0 + B2 * 6 = 6 * 6 = 36

затем Сформируйте матрицу, с AB и C в рядах:

[A1 B1 C1]
[A2 B2 C2]

[-6 6 0]
[ 6 6 36]

Теперь уменьшается к уменьшению эшелонной формы с использованием функции MATLAB RREF (MATRIX) :

[ 1 0 3]
[ 0 1 3]

Как вы можете догадаться, последний столбец является вашим пересечением точка. Это расширяется до такой же размеры, по мере необходимости. Если ваша уменьшающаяся форма эшелона имеет что-то кроме матрицы личности для передней части его, ваши векторы либо не имеют уникальной точки пересечения, либо не имеют точки пересечения, в зависимости от формы матрицы.

dim = 2;

% Do other stuff, ending with rref(matrix)

if (matrix(:,1:dim) == eye(dim))
    % Matrix has unique solution.
    solution = (matrix(:,dim+1))'
else
    % No unique solution.
end

В двух измерениях вариации являются:

  • линейным раствором, указывающим раствор, является линейкой формы x + by = C :
  • [ 1 B C]
    [ 0 0 0]
    

  • :
  • [ 1 B C]
    [ 0 0 0]
    

  • Нет решения, указывающих на линии, не пересекающиеся, где C2 <> 0 :
  • [ 1 B C1]
    [ 0 0 C2]
    

    2
    ответ дан 1 December 2019 в 21:52
    поделиться
    Другие вопросы по тегам:

    Похожие вопросы: