Как разбить непрямую линию на четные отрезки? - PullRequest
3 голосов
/ 06 апреля 2011

У меня есть не прямая линия, определяемая серией координатных точек x, y.Я мог бы нарисовать прямую линию на экране прямо между этими точками без проблем.К сожалению, я должен нарисовать линию в отрезках равной длины.

Вот пример того, как мне нужно разбить непрямую линию с 3 точками на массив из нескольких равноотстоящих точек.(игнорируйте последнюю красную точку, это результат, когда линия не делится равномерно, и также является конечной точкой)

Here is an example of how I need to break up a non-straight line with 3 points into an array of several equidistant points

Обратите внимание на красную линию на «стыке».Предположим, что у меня есть прямая A-> B-> C с векторами AB и BC, образующими некоторый угол.По сути, линия изгибается в точке B.

Сегментация линии между точками A и B не представляет проблем вплоть до точки.Но когда AB не делится равномерно по длине сегмента, мне нужно сделать что-то особенное.Мне нужно взять оставшуюся длину и считать ее одной стороной треугольника.Постоянная длина сегмента - это другая сторона треугольника, которая соединяется с сегментом BC (красная линия выше).Мне нужно знать длину от точки B до этого пересечения.С помощью этой информации я могу продолжить вычисление отрезков на BC.

Вот треугольник, который я пытаюсь решить (далее я буду ссылаться на переменные, как они появляются на этом рисунке).Пока я разбил проблему с использованием закона косинусов.c 2 = a 2 + b 2 - 2ab * Cos ( y )

Проблема в том, что яуже знаю с, это длина сегмента.Мне нужно вычислить для a (я могу вычислить y).

Я дошел до написания полиномиального уравнения, но теперь я застрял: a 2 + b 2 - 2ab * Cos ( y ) - c 2 = 0

или топор 2 + Bx + C (A =1, B = -2b * Cos ( y ), C = b 2 - c 2 , x = a)

Этодаже правильный подход?Что мне делать дальше?Мне нужно реализовать это в Actionscript.

РЕДАКТИРОВАТЬ: Duh, я должен был бы использовать квадратную формулу.Итак, теперь я получаю:

a = b * Cos ( y ) +/- SqrRoot (c 2 - b 2 * Sin ( y ) 2 )

Теперь, как поместить это в код ...

1 Ответ

2 голосов
/ 11 апреля 2011

Вот как я это решил.B и C такие же, как вы их определили, я называю точку A концом последнего полного сегмента в первой строке.(последняя точка перед изгибом) Если вы нарисуете круг с центром в точке A и радиусом = длиной вашего сегмента, то в том месте, где этот круг пересекает линию BC, это конечная точка (назовите ее D) линии от A, которая обрезает ваш угол,Чтобы найти эту точку, я нашел аккуратную вспомогательную функцию Это не очень долго и для простоты, я просто вставляю ее сюда.

/*---------------------------------------------------------------------------
Returns an Object with the following properties:
    enter           -Intersection Point entering the circle.
    exit            -Intersection Point exiting the circle.
    inside          -Boolean indicating if the points of the line are inside the circle.
    tangent     -Boolean indicating if line intersect at one point of the circle.
    intersects      -Boolean indicating if there is an intersection of the points and the circle.

If both "enter" and "exit" are null, or "intersects" == false, it indicates there is no intersection.

This is a customization of the intersectCircleLine Javascript function found here:

http://www.kevlindev.com/gui/index.htm

----------------------------------------------------------------------------*/
function lineIntersectCircle(A : Point, B : Point, C : Point, r : Number = 1):Object {
    var result : Object = new Object ();
    result.inside = false;
    result.tangent = false;
    result.intersects = false;
    result.enter=null;
    result.exit=null;
    var a : Number = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
    var b : Number = 2 * ((B.x - A.x) * (A.x - C.x) +(B.y - A.y) * (A.y - C.y));
    var cc : Number = C.x * C.x + C.y * C.y + A.x * A.x + A.y * A.y - 2 * (C.x * A.x + C.y * A.y) - r * r;
    var deter : Number = b * b - 4 * a * cc;
    if (deter <= 0 ) {
        result.inside = false;
    } else {
        var e : Number = Math.sqrt (deter);
        var u1 : Number = ( - b + e ) / (2 * a );
        var u2 : Number = ( - b - e ) / (2 * a );
        if ((u1 < 0 || u1 > 1) && (u2 < 0 || u2 > 1)) {
            if ((u1 < 0 && u2 < 0) || (u1 > 1 && u2 > 1)) {
                result.inside = false;
            } else {
                result.inside = true;
            }
        } else {
            if (0 <= u2 && u2 <= 1) {
                result.enter=Point.interpolate (A, B, 1 - u2);
            }
            if (0 <= u1 && u1 <= 1) {
                result.exit=Point.interpolate (A, B, 1 - u1);
            }
            result.intersects = true;
            if (result.exit != null && result.enter != null && result.exit.equals (result.enter)) {
                result.tangent = true;
            }
        }
    }
    return result;
}

Это функция, которая возвращает объект снесколько свойств, поэтому реализовать в вашем коде очень просто.Вам нужно пройти три точки и радиус.Первые две точки - это просто B и C, как вы их определили выше, и точка A, как я объяснил в начале.Радиус, опять же, длина вашего сегмента.

//create an object
var myObject:Object = lineIntersectCircle(pointB, pointC, pointA, segmentLength);

Вот и все!Координаты точки D (см. Выше): (myObject.exit.x, myObject.exit.y)

...