Как добавить градиент в кривой Безье? - PullRequest
6 голосов
/ 23 февраля 2020

Я нарисовал на карте кривые, обозначающие страну клиента и страну, куда он направляется для поездки. enter image description here

Но я не мог добавить градиент, чтобы линии обозначали указанную информацию и давали этот случайный цвет между двумя цветами в случайном порядке. Вот что я попробовал.

int steps = 10;
    noFill();
    //stroke(#5A38FA, 50);
    strokeWeight(1);
    for(int i=0; i<steps; i++) {
      strokeWeight(1);
      noFill();
      stroke(lerpColor(#31B5E8, #F0E62E, (float)i/steps));
      bezier(locationX, locationY, locationX+random(15, 50), locationY+random(13,50), customerLocationX+random(15, 30), customerLocationY+random(15, 70), customerLocationX, customerLocationY);
    }

1 Ответ

3 голосов
/ 23 февраля 2020

Вы можете разложить кривую Безье на точки, используя метод bezierPoint(), а затем нарисовать отрезки прямых линий между последовательными точками, указав цвет для каждого отдельного отрезка (в то же время постепенно изменяя цвет, конечно).

Я создал метод, который может сделать это в приведенном ниже примере кода.

Кроме того, с помощью метода вы можете указать величину кривой (curve) и направление кривой (dir); метод вычисляет контрольную точку Безье, используя точку на линии, перпендикулярной средней точке между начальной точкой (головой) и конечной точкой (хвостом).

void setup() {
  size(500, 500);
  smooth(4);
  noLoop();
  redraw();
  strokeWeight(5);
  noFill();
}

void draw() {
  background(35);
  drawCurve(new PVector(50, 50), new PVector(456, 490), #31B5E8, #F0E62E, 50, -1);
  drawCurve(new PVector(150, 75), new PVector(340, 410), #B9FF00, #FF00C5, 150, 1);
  drawCurve(new PVector(200, 480), new PVector(480, 30), #007CFF, #89CA7F, 100, 1);
}

void drawCurve(PVector head, PVector tail, color headCol, color tailCol, float curve, int curveDir) {

  final float theta2 = angleBetween(tail, head);
  final PVector midPoint = new PVector((head.x + tail.x) / 2, 
    (head.y + tail.y) / 2);
  final PVector bezierCPoint = new PVector(midPoint.x + (sin(-theta2) * (curve * 2 * curveDir)), 
    midPoint.y + (cos(-theta2) * (curve * 2 * curveDir)));

  PVector point = head.copy();
  for (float t=0; t<=1; t+=0.025) {
    float x1 = bezierPoint(head.x, bezierCPoint.x, bezierCPoint.x, tail.x, t);
    float y1 = bezierPoint(head.y, bezierCPoint.y, bezierCPoint.y, tail.y, t);
    PVector pointB = new PVector(x1, y1);
    stroke(lerpColor(headCol, tailCol, t));
    line(point.x, point.y, pointB.x, pointB.y);
    point = pointB.copy();
  }
}  

static float angleBetween(PVector tail, PVector head) {
  float a = PApplet.atan2(tail.y - head.y, tail.x - head.x);
  if (a < 0) {
    a += PConstants.TWO_PI;
  }
  return a;
}

Результат:

enter image description here

...