3

我正在尝试创建一条通过 Java 中三个给定点的曲线(我正在通过扩展 JPanel 的类绘制曲线)。我怎样才能做到?

在此处输入图像描述

4

5 回答 5

5

您应该研究类似 Catmull-Rom 样条的东西,它们基本上是通过多个控制点(在您的情况下是三个点)的曲线。

这是我在快速谷歌后找到的一个例子:http ://www.mvps.org/directx/articles/catmull/

希望这可以帮助 :)

于 2009-07-06T23:57:31.120 回答
5

一个圆将通过平面上的三个点。这个页面解释了几何: http: //www.mathopenref.com/const3pointcircle.html

于 2009-07-07T00:01:40.033 回答
4

我只是花了一些时间让它以一种健壮的方式工作。有一些支持功能,然后是用圆的三个点创建 Arc2D 的东西。出于我的目的,我有一个起点和终点,以及一个中间的“中间”点(尽管它实际上不必在中间——它的目的是告诉我我想要哪个圆弧)。

以下是源代码的直接链接:

org.six11.util.gui.shape.ShapeFactory

org.six11.util.pen.Functions

public static Pt getCircleCenter(Pt a, Pt b, Pt c) {
  double ax = a.getX();
  double ay = a.getY();
  double bx = b.getX();
  double by = b.getY();
  double cx = c.getX();
  double cy = c.getY();

  double A = bx - ax;
  double B = by - ay;
  double C = cx - ax;
  double D = cy - ay;

  double E = A * (ax + bx) + B * (ay + by);
  double F = C * (ax + cx) + D * (ay + cy);

  double G = 2 * (A * (cy - by) - B * (cx - bx));
  if (G == 0.0)
    return null; // a, b, c must be collinear

  double px = (D * E - B * F) / G;
  double py = (A * F - C * E) / G;
  return new Pt(px, py);
}

public static double makeAnglePositive(double angleDegrees) {
  double ret = angleDegrees;
  if (angleDegrees < 0) {
    ret = 360 + angleDegrees;
  }
  return ret;
}

public static double getNearestAnglePhase(double limitDegrees, double sourceDegrees, int dir) {
  double value = sourceDegrees;
  if (dir > 0) {
    while (value < limitDegrees) {
      value += 360.0;
    }
  } else if (dir < 0) {
    while (value > limitDegrees) {
      value -= 360.0;
    }
  }
  return value;
}

public static Arc2D makeArc(Pt s, Pt mid, Pt e) {
  Pt c = Functions.getCircleCenter(s, mid, e);
  double radius = c.distance(s);

  double startAngle = Functions.makeAnglePositive(Math.toDegrees(-Math
      .atan2(s.y - c.y, s.x - c.x)));
  double midAngle = Functions.makeAnglePositive(Math.toDegrees(-Math.atan2(mid.y - c.y, mid.x
      - c.x)));
  double endAngle = Functions
      .makeAnglePositive(Math.toDegrees(-Math.atan2(e.y - c.y, e.x - c.x)));

  // Now compute the phase-adjusted angles begining from startAngle, moving positive and negative.
  double midDecreasing = Functions.getNearestAnglePhase(startAngle, midAngle, -1);
  double midIncreasing = Functions.getNearestAnglePhase(startAngle, midAngle, 1);
  double endDecreasing = Functions.getNearestAnglePhase(midDecreasing, endAngle, -1);
  double endIncreasing = Functions.getNearestAnglePhase(midIncreasing, endAngle, 1);

  // Each path from start -> mid -> end is technically, but one will wrap around the entire
  // circle, which isn't what we want. Pick the one that with the smaller angular change.
  double extent = 0;
  if (Math.abs(endDecreasing - startAngle) < Math.abs(endIncreasing - startAngle)) {
    extent = endDecreasing - startAngle;
  } else {
    extent = endIncreasing - startAngle;
  }

  return new Arc2D.Double(c.x - radius, c.y - radius, radius * 2, radius * 2, startAngle, extent,
      Arc2D.OPEN);
}
于 2010-01-28T22:18:43.197 回答
2

尝试在贝塞尔样条曲线上进行谷歌搜索。这可能是一个 2D 解决方案,但如果您需要它应该可以扩展到 3D。

基本上,使用这三个点作为参数,您可以获得一个适合三个点的二阶多项式.. 并且它是可扩展的,如果您有 N 个点,您将获得一个 N-1 阶多项式,该多项式参数化地生成从第一个到第一个点的所有点最后,当您“调整”一个标量参数时,通常表示为“s”。

编辑/添加:

正如所指出的(信用 CapBBeard!),贝塞尔曲线实际上并没有达到中间点。拉格朗日插值确实达到了这些点,但随着点数的增加,它变得更加丑陋。(类似于每个 N 阶的 O(n) 多项式分数)

于 2009-07-07T00:00:44.327 回答
0

使用由 3 个点创建的 2 条曲线
curveLine1:P1、C1、E1。
用 3 个点创建的曲线线 2:P2 = E1、C2、E2。
在 1 行中制作 C1、E1、C2。
在此处查看示例:http: //i.stack.imgur.com/I901q.png

QuadCurve2D.Double curveLine1 = new QuadCurve2D.Double(30, 75, 195, 23, 280, 143);
//QuadCurve2D.Double curveLine1 = new QuadCurve2D.Double(P1.x, P1.y, C1.x, C1.y, E1.x, E1.y);
QuadCurve2D.Double curveLine2 = new QuadCurve2D.Double(280, 143, 366, 260, 466, 193);
//QuadCurve2D.Double curveLine2 = new QuadCurve2D.Double(E1.x, E1.y, C2.x, C2.y, E2.x, E2.y);
Graphics2D g2 = (Graphics2D) g;
g2.draw(curveLine1);
g2.draw(curveLine2);
于 2013-11-11T11:14:06.590 回答