Как разбить непрямую линию на четные отрезки?
У меня есть не прямая линия, определенная серией координатных точек x, y. Я мог бы без проблем нарисовать прямую линию на экране между этими точками. К сожалению, я должен нарисовать линию в отрезках равной длины.
Вот пример того, как мне нужно разбить непрямую линию с 3 точками на массив из нескольких равноотстоящих точек. (игнорируйте последнюю красную точку, это результат, когда линия не делится равномерно и также является конечной точкой)
Пожалуйста, обратите внимание на красную линию на "стыке". Предположим, что у меня есть прямая A->B->C с векторами AB и BC, образующими некоторый угол. В основном, линия изгибается в точке B.
Сегментация линии между точками A и B не является проблемой вплоть до точки. Но когда AB не делится равномерно по длине сегмента, мне нужно сделать что-то особенное. Мне нужно взять оставшуюся длину и считать ее одной стороной треугольника. Постоянная длина сегмента - это другая сторона треугольника, которая соединяется с сегментом BC (красная линия выше). Мне нужно знать длину от точки B до этого пересечения. С этой информацией я могу продолжить вычисление отрезков на BC.
Вот треугольник, который я пытаюсь решить (здесь и далее я буду ссылаться на переменные в том виде, в каком они изображены на этой картинке). До сих пор я разбил проблему на использование закона косинусов. c2 = a2 + b2 - 2ab * Cos (y)
Проблема в том, что я уже знаю c, это длина сегмента. Мне нужно решить для (я могу рассчитать у).
Я дошел до написания полиномиального уравнения, но теперь я застрял: a2 + b2 - 2ab * Cos (y) - c2 = 0
или Ax2 + Bx + C (A = 1, B = -2b * Cos (y), C = b2 - c2, x = a)
Это даже правильный подход? Что мне делать дальше? Мне нужно реализовать это в Actionscript.
РЕДАКТИРОВАТЬ: Duh, я бы использовал квадратную формулу. Итак, я теперь получаю:
a = b * Cos (y) +/- SqrRoot (c2 - b2 * Sin (y)2)
Теперь, как поместить это в код...
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) && (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)