отрезок с использованием четырехточечного пересечения - PullRequest
0 голосов
/ 28 августа 2011

У меня есть четыре точки p0, p1, p1 ', p2', каждая из которых определяется компонентами x, y, z, и все они лежат на одной линии, как на рисунке

enter image description here

Я хочу получить результат отрезка (пунктирная часть) от пересечения между четырьмя точками

любое предложение или пример кода с использованием C #

Ответы [ 2 ]

1 голос
/ 28 августа 2011

Это более или менее тот же самый ответ, который дал Говард, но вдавленный в C # ... Надеюсь, это поможет с вашей базой кода.

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

private struct Vector3D
{
    public double X { get; set; }
    public double Y { get; set; }
    public double Z { get; set; }
}
static class Vectors
{
    static public double ScalProd(Vector3D v1, Vector3D v2)
    {
        return v1.X*v2.X + v1.Y*v2.Y + v1.Z*v2.Z;
    }

    static public Vector3D Minus(Vector3D v1, Vector3D v2)
    {
        return new Vector3D {X = v1.X - v2.X, Y = v1.Y - v2.Y, Z = v1.Z - v2.Z};
    }

    static public Vector3D Normalize(Vector3D v)
    {
        var len = Math.Sqrt(ScalProd(v, v));
        return new Vector3D {X = v.X/len, Y = v.Y/len, Z = v.Z/len};
    }
}

private Vector3D[]  FindIntersectionOnCoLinearVectors(params Vector3D[] input)
{
    if (input.Length < 2) throw new Exception("you need a minimum of two vectors");
    var v0 = input[0];
    var direction = Vectors.Normalize(Vectors.Minus(input[1], v0));
    Func<Vector3D, double> projectOntoLineStartingAtv0 =
        v => Vectors.ScalProd(direction, Vectors.Minus(v, v0));
    var mapped = input.OrderBy(projectOntoLineStartingAtv0).ToArray();
    return new Vector3D[] {mapped[1], mapped[2] };
}
0 голосов
/ 28 августа 2011

Вы можете действовать следующим образом:

Шаг 1: Преобразование в одномерную задачу

  • определить t(P) = (P-P0).(P1-P0) / (P1-P0).(P1-P0), где точка обозначает скалярное произведение
  • t - это линейная мера на линии, проходящей через P1 и P0
  • Таким образом, мы имеем t(P0)=0, t(P1)=1

Шаг 2: Решить проблему в 1D

  • Мы предполагаем t(P0') <= t(P1') (в противном случае поменяйте местами P0' и P1' в следующих строках)
  • Теперь возможны следующие случаи
    • t(P1') < 0 => нет пересечения
    • 1 < t(P0') => нет пересечения
    • t(P0') <= 0 <= t(P1') <= 1 => пересечение является сегментом (P0,P1')
    • t(P0') <= 0 < 1 < t(P1') => пересечение является сегментом (P0,P1)
    • 0 <= t(P0') <= t(P1') <= 1 => пересечение является сегментом (P0',P1')
    • 0 <= t(P0') <= 1 < t(P1') => пересечение является сегментом (P0',P1)
  • альтернативно, если вас интересуют только значения t, пересечение дается отрезком между t0 = max(0, t(P0')) и t1 = min(1, t(P1')) тогда и только тогда t0 <= t1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...