Пересечения для 3D линий - PullRequest
0 голосов
/ 16 марта 2020

Я написал функцию, которая должна вычислять все точки пересечения между линией и всеми заданными ей линиями, и это в 3D. У меня эти параметры параметризованы, потому что это казалось самым простым способом работы с вещами. Проблема в том, что когда я снова вводю переменные "t1" и "t2" в функции строк, кажется, что есть слишком большая неточность, чтобы быть приемлемой для того, что мне нужно.

t1 - это параметр для линии, о которой вы хотели бы знать все пересечения, поэтому он записан в следующем виде:

x = xo + t1 * dx
y = yo + t1 * dy
z = zo + t1 * dz

Где [xo, yo, zo] представляет точку на линии, которую я называю «origin» и [dx, dy, dz] представляют направление этой линии. Другие строки приведены в той же форме, и функция, которую я написал, в основном решает следующее уравнение:

xo1 + t1 * dx1 = xo2 + t2 * dx2
yo1 + t1 * dy1 = yo2 + t2 * dy2
zo1 + t1 * dz1 = zo2 + t2 * dz2

Где все дано, кроме t1 и t2, это то, что я ищу здесь. Однако я не думаю, что на самом деле найти t1 и t2 - это проблема, у меня есть решение, которое дает мне какой-то результат. Как упоминалось ранее, проблема в том, что когда я возвращаю t1 и t2 в эти формулы, чтобы получить действительные точки пересечения, они немного отличаются друг от друга. Я говорю о различиях, которые в основном находятся на расстоянии 0,005-0,05 от друг друга на евклидовом расстоянии. Но в крайних случаях это может быть до 0,5 погрешности. Я знаю, что большинство линий в 3D не пересекаются и, следовательно, не имеют решения для этих уравнений, но для тестов, которые я сейчас делаю, я на 100% уверен, что все линии находятся в одной плоскости, но некоторые могут быть параллельны друг другу. Тем не менее, эти неточности встречаются для всех линий, и я действительно просто ищу решение, которое дает точное определение, когда они пересекаются.

Вот код, который у меня есть для этого:

def lineIntersection(self, lines):
    origins = np.zeros((len(lines), 3), dtype=np.float32)
    directions = np.zeros((len(lines), 3), dtype=np.float32)
    for i in range(0, len(lines)):
        origins[i] = lines[i].origin
        directions[i] = lines[i].direction

    ox = origins[:, 0]
    oy = origins[:, 1]
    dx = self.origin[0]
    dy = self.origin[1]
    x1 = directions[:, 0]
    y1 = directions[:, 1]
    x2 = self.direction[0]
    y2 = self.direction[1]
    t2 = np.divide((np.subtract(np.add(oy, np.multiply(np.divide(np.subtract(dx, ox), x1), y1)), dy)), np.subtract(y2, np.multiply(np.divide(x2, x1), y1)))
    t1 = np.divide((np.add(dx, np.subtract(np.multiply(t2, x2), ox))), x1)

    testx1 = np.add(ox, np.multiply(t1, x1))
    testx2 = np.add(dx, np.multiply(t2, x2))
    testy1 = np.add(oy, np.multiply(t1, y1))
    testy2 = np.add(dy, np.multiply(t2, y2))
    testz1 = np.add(origins[:, 2], np.multiply(t1, directions[:, 2]))
    testz2 = np.add(self.origin[2], np.multiply(t2, self.direction[2]))

    arr1 = np.array([testx1, testy1, testz1]).T
    arr2 = np.array([testx2, testy2, testz2]).T
    diff = np.linalg.norm(np.subtract(arr1, arr2), axis=1)
    narr = arr1[diff < 0.05] #Filtering out points that aren't actually intersecting
    nt2 = t2[diff < 0.05]

    return narr, nt2

Эта функция находится в классе «Линия» и имеет начало и направление, как объяснено ранее. Входные данные, которые он принимает, представляют собой массив объектов из класса "Line".

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

1 Ответ

0 голосов
/ 16 марта 2020

Неточность является распространенным случаем пересечения линий, образующих небольшой угол.
Я не проверял вашу правильность al go, но, кажется, вы просто решаете систему трех уравнений с помощью решателя linalg.
В случае почти параллельного промежуточные значения строк (определитель) могут быть небольшими, вызывая значительные ошибки.
Вы пробовали более надежные алгоритмы c, такие как SVD?

Но, возможно, они вам действительно не нужны:

Обратите внимание, что когда вы уверены, что все линии l ie в одной плоскости, вы можете использовать алгоритм 2D - просто проверьте, какой компонент из dx, dy, dz имеют наименьшую величину (проверьте наличие отдельных линий) и игнорируют соответствующий компонент - это похоже на проецирование линий на плоскость OXY, OXZ или OYZ. 2D-код должен быть намного проще .

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

Обратите внимание, что значение det (определитель) оценивается для проверки параллельных (и почти параллельных) линий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...