Как нарисовать непрерывную кривую линию из 3 заданных точек за раз

Я пытаюсь нарисовать непрерывную изогнутую линию во flash. Существует много методов, но ни один из найденных мною пока не соответствует моим требованиям. Прежде всего, я хочу использовать метод curveTo () api flash-графики. Я НЕ хочу моделировать кривую с сотнями вызовов lineTo () на сегмент кривой . По моему опыту и пониманию, линейные сегменты тяжелы для процессора. Вспышка' Квадратичная кривая Безье должна потреблять меньше мощности процессора. Если вы считаете, что я ошибаюсь, оспорите это предположение.

Я также не хочу использовать готовый метод, который принимает всю строку в качестве аргумента (например, mx.charts.chartClasses.GraphicsUtilities.drawPolyline ()). Причина в том, что мне нужно будет изменить логику, чтобы в конечном итоге добавить украшения к линии, которую я рисую, поэтому мне нужно что-то, что я понимаю на самом низком уровне.

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

Вот изображение:

A continuous curved line using the actual points as control points

Проблема в том, что линии на самом деле не проходят через «реальные» точки линии (серые круги). Есть ли способ, используя математические возможности, настроить контрольную точку так, чтобы кривая действительно проходила через «настоящую» точку? Учитывая только текущую точку и ее предыдущую / следующую точку в качестве аргументов? Код для дублирования изображения выше приведен ниже. Было бы здорово, если бы я мог изменить его в соответствии с этим требованием (обратите внимание на исключение для первого и последнего пункта).

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);
  }
}

Позже я добавлю стрелки и прочее в метод рисования.

7
задан jpwrunyan 11 May 2011 в 00:58
поделиться