Как мне разбить не прямую линию на четные сегменты?

#actionscript-3 #geometry #polynomial-math #trigonometry #line-segment

#actionscript-3 #геометрия #многочлен-математика #тригонометрия #line-сегмент

Вопрос:

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

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

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

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

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

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

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

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

или Ax 2 Bx C (A = 1, B = -2b * Cos (y), C = b2 — c2, x = a)

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

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

a = b * Cos (y) /- SqrRoot(c2 — b2 * Sin(y)2)

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

Комментарии:

1. если вы добавите URL в img, я смогу отредактировать его в вашем сообщении.

2. Я поддержал ваш вопрос,, теперь у вас 13 повторений,, так что вы можете опубликовать изображение.

3. Спасибо! Я действительно ценю это. Я думаю, что нашел математическое решение (с помощью квадратичной формулы). Теперь мне просто нужно это закодировать. Тем временем мне пришлось перейти к другой проблеме, но когда я получу изменения в коде этого, я постараюсь вернуться и опубликовать ответ. Тем временем я был бы рад любым предложениям. Решение двух уравнений и последующая проверка того, какое из них является положительным, кажется довольно трудоемким. Но это должно быть необходимо только в местах соединения, так что, надеюсь, логика рисования не слишком замедлит процесс.

4. Вы хотите провести ломаную линию или кривую через контрольные точки? Для полилинии одинаковая длина всех сегментов невозможна без среза углов (в общем случае.)

5. ошибка, извините, либо я запутался, либо я запутал вас. Я буду рисовать сегменты прямой линии, а не кривые, поэтому я не вижу, где будут находиться контрольные точки. Я думаю, что ответ на ваш вопрос заключается в том, что я срежу угол, вставив линию длиной в 1 сегмент рядом с тем местом, где в противном случае соединялись бы две линии AB и BC, рассчитанные с использованием приведенной выше математики. Причина, по которой требуется, чтобы сегменты были одинаковой длины, заключается в том, что к ним будет прикреплено оформление установленного размера. Например, сегмент линии фронта холодной погоды будет иметь форму треугольника (как в новостях).

Ответ №1:

Вот как я решил эту проблему. 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) amp;amp; (u2 < 0 || u2 > 1)) {
            if ((u1 < 0 amp;amp; u2 < 0) || (u1 > 1 amp;amp; u2 > 1)) {
                result.inside = false;
            } else {
                result.inside = true;
            }
        } else {
            if (0 <= u2 amp;amp; u2 <= 1) {
                result.enter=Point.interpolate (A, B, 1 - u2);
            }
            if (0 <= u1 amp;amp; u1 <= 1) {
                result.exit=Point.interpolate (A, B, 1 - u1);
            }
            result.intersects = true;
            if (result.exit != null amp;amp; result.enter != null amp;amp; result.exit.equals (result.enter)) {
                result.tangent = true;
            }
        }
    }
    return resu<
}
  

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

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

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

Комментарии:

1. У Mathworld есть предыстория этого вычисления здесь: mathworld. wolfram.com/Circle-LineIntersection.html

2. Круто, это должно занять меньше времени, чем решение, которое я придумал, используя закон косинусов. Спасибо!