Как мне отрезать отрезок от усеченного конуса? - PullRequest
4 голосов
/ 17 сентября 2008

Даны два вектора A и B , которые образуют отрезок L = A-B. Кроме того, учитывая усеченный вид F , который определяется его левой, правой, нижней, верхней, ближней и дальней плоскостями.

Как мне обрезать L против F ?

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

Если возможно, приведите пример кода, пожалуйста (предпочтительно C ++ или Python).

Ответы [ 3 ]

4 голосов
/ 17 сентября 2008

Я не хочу сейчас писать код для этого, но если я правильно понимаю «frustum», должно работать следующее:

  1. Пересечь линию со всеми заданными плоскостями
  2. Если у вас есть два пересечения, все готово.
  3. Если у вас есть только одно пересечение, вычислите переднюю плоскость и пересечение.
  4. Если у вас все еще есть только одно пересечение, рассчитайте заднюю плоскость и пересечение.

Но я, возможно, совершенно не понял. В этом случае, пожалуйста, уточните:)

1 голос
/ 23 января 2016

Сначала извлеките самолеты из матрицы вида .

Затем используйте ваши точки, чтобы определить вектор и min / max как (0, 1), затем итерируйте по плоскостям и пересекайте их с сегментом, обновляя min / max, выручая рано, если min > max.

Вот пример чистой функции Python, без внешних deps.

def clip_segment_v3_plane_n(p1, p2, planes):
    """
    - p1, p2: pair of 3d vectors defining a line segment.
    - planes: a sequence of (4 floats): `(x, y, z, d)`.

    Returns 2 vector triplets (the clipped segment)
    or (None, None) then segment is entirely outside.
    """
    dp = sub_v3v3(p2, p1)

    p1_fac = 0.0
    p2_fac = 1.0

    for p in planes:
        div = dot_v3v3(p, dp)
        if div != 0.0:
            t = -plane_point_side_v3(p, p1)
            if div > 0.0:  # clip p1 lower bounds
                if t >= div:
                    return None, None
                if t > 0.0:
                    fac = (t / div)
                    if fac > p1_fac:
                        p1_fac = fac
                        if p1_fac > p2_fac:
                            return None, None
            elif div < 0.0:  # clip p2 upper bounds
                if t > 0.0:
                    return None, None
                if t > div:
                    fac = (t / div)
                    if fac < p2_fac:
                        p2_fac = fac
                        if p1_fac > p2_fac:
                            return None, None

    p1_clip = add_v3v3(p1, mul_v3_fl(dp, p1_fac))
    p2_clip = add_v3v3(p1, mul_v3_fl(dp, p2_fac))

    return p1_clip, p2_clip


# inline math library
def add_v3v3(v0, v1):
    return (
        v0[0] + v1[0],
        v0[1] + v1[1],
        v0[2] + v1[2],
        )

def sub_v3v3(v0, v1):
    return (
        v0[0] - v1[0],
        v0[1] - v1[1],
        v0[2] - v1[2],
        )

def dot_v3v3(v0, v1):
    return (
        (v0[0] * v1[0]) +
        (v0[1] * v1[1]) +
        (v0[2] * v1[2])
        )

def mul_v3_fl(v0, f):
    return (
        v0[0] * f,
        v0[1] * f,
        v0[2] * f,
        )

def plane_point_side_v3(p, v):
    return dot_v3v3(p, v) + p[3]
1 голос
/ 18 сентября 2008

В дополнение к тому, что сказал капрал Сенси выше, вам нужно знать, как пересечь отрезок с плоскостью . В описании на этой странице u представляет параметр в параметрическом определении вашей строки. Сначала вычислите u, используя один из 2 описанных методов. Если значение u находится в диапазоне от 0,0 до 1,0, то плоскость обрезает линию где-то на вашем сегменте. Включение u обратно в уравнение линии дает вам точку, где происходит это пересечение.

Другой подход заключается в том, чтобы найти направленное расстояние каждой точки к плоскости. Если расстояние одной точки положительно, а другой отрицательно, то они лежат на противоположных сторонах плоскости. Затем вы знаете, какая точка находится за пределами вашего усеченного конуса (в зависимости от того, каким образом нормальные точки вашего самолета). Используя этот подход, можно найти точку пересечения быстрее, выполнив линейную интерполяцию на основе отношения направленных расстояний. Например. если расстояние от одной точки равно +12, а для другой - -12, вы знаете, что плоскость разрезает отрезок пополам, а ваш параметр u равен 0,5.

Надеюсь, это поможет.

...