How to draw a curve passing through three points?

I am trying to create a curve that passes through three given points in Java (I draw curves through a class that extends JPanel). How can i do this?

enter image description here

+3
source share
5 answers

You should learn something like Catmull-Rom splines, which are basically curves passing through multiple control points (in your case, your three points).

Here is an example that I found after a quick google: http://www.mvps.org/directx/articles/catmull/

Hope this helps :)

+5
source

, . , , 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);
}
+4

google . 2D-, 3D, .

, , , . , N , N-1, , " ", "s".

/:

( CapBBeard!), . , , . (- O (n) N)

+2

use 2 curves
curveLine1 created with three points: P1, C1, E1.
curveLine2 is created with three points: P2 = E1, C2, E2.
do C1, E1, C2 in 1 line.
Example here: 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);
0
source

Source: https://habr.com/ru/post/1711952/


All Articles