Я пытаюсь нарисовать непрерывную изогнутую линию во вспышке. Существует много методов, но ни один из тех, которые я нашел, пока не соответствует моим требованиям. Прежде всего, Я хочу использовать метод кривых API flashTo (). Я НЕ хочу моделировать кривую с сотнями обращений к lineTo () на изогнутую линейный сегмент . По моему опыту и пониманию, линейные сегменты сильно загружены процессором. Квадратичная кривая Безье Flash должна потреблять меньше ресурсов процессора. Пожалуйста, бросьте вызов этому предположению, если вы думаете, что я неправ.
Я также не хочу использовать готовый метод, который принимает в качестве аргумента всю строку (например, mx.charts.chartClasses.GraphicsUtilities.drawPolyline ()).
Причина в том, что мне нужно будет в конечном итоге изменить логику, чтобы добавить украшения к линии, которую я рисую, поэтому мне нужно кое-что, что я понимаю, на самом низком уровне.
В настоящее время я создал метод, который будет рисовать кривую с учетом 3 точек, с использованием метода средней точки, найденного здесь .
Вот картинка:
Проблема в том, что линии на самом деле не изгибаются через «реальные» точки линии (серые кружки). Есть ли способ использовать силу математики, чтобы я мог настроить контрольную точку так, чтобы кривая действительно проходила через «реальную» точку? Учитывая только текущую точку и ее предыдущую / следующую точку в качестве аргументов? Код для дублирования рисунка выше. Было бы здорово, если бы я мог изменить его, чтобы он соответствовал этому требованию (обратите внимание на исключение для первого и последнего пункта).
package {
import flash.display.Shape;
import flash.display.Sprite;
import flash.display.Stage;
import flash.geom.Point;
[SWF(width="200",height="200")]
public class TestCurves extends Sprite {
public function TestCurves() {
stage.scaleMode = "noScale";
var points:Array = [
new Point(10, 10),
new Point(80, 80),
new Point(80, 160),
new Point(20, 160),
new Point(20, 200),
new Point(200, 100)
];
graphics.lineStyle(2, 0xFF0000);
var point:Point = points[0];
var nextPoint:Point = points[1];
SplineMethod.drawSpline(graphics, point, null, nextPoint);
var prevPoint:Point = point;
var n:int = points.length;
var i:int;
for (i = 2; i < n + 1; i++) {
point = nextPoint;
nextPoint = points[i]; //will eval to null when i == n
SplineMethod.drawSpline(graphics, point, prevPoint, nextPoint);
prevPoint = point;
}
//straight lines and vertices for comparison
graphics.lineStyle(2, 0xC0C0C0, 0.5);
graphics.drawCircle(points[0].x, points[0].y, 4);
for (i = 1; i < n; i++) {
graphics.moveTo(points[i - 1].x, points[i - 1].y);
graphics.lineTo(points[i].x, points[i].y);
graphics.drawCircle(points[i].x, points[i].y, 4);
}
}
}
}
import flash.display.Graphics;
import flash.geom.Point;
internal class SplineMethod {
public static function drawSpline(target:Graphics, p:Point, prev:Point=null, next:Point=null):void {
if (!prev && !next) {
return; //cannot draw a 1-dimensional line, ie a line requires at least two points
}
var mPrev:Point; //mid-point of the previous point and the target point
var mNext:Point; //mid-point of the next point and the target point
if (prev) {
mPrev = new Point((p.x + prev.x) / 2, (p.y + prev.y) / 2);
}
if (next) {
mNext = new Point((p.x + next.x) / 2, (p.y + next.y) / 2);
if (!prev) {
//This is the first line point, only draw to the next point's mid-point
target.moveTo(p.x, p.y);
target.lineTo(mNext.x, mNext.y);
return;
}
} else {
//This is the last line point, finish drawing from the previous mid-point
target.moveTo(mPrev.x, mPrev.y);
target.lineTo(p.x, p.y);
return;
}
//draw from mid-point to mid-point with the target point being the control point.
//Note, the line will unfortunately not pass through the actual vertex... I want to solve this
target.moveTo(mPrev.x, mPrev.y);
target.curveTo(p.x, p.y, mNext.x, mNext.y);
}
}
Позже я добавлю стрелки и другие элементы в метод рисования.