Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a gradient in a Bezier curve?

Tags:

processing

I have drawn curves that denote the customer country and the country where he is headed for a trip in a map. enter image description here

But I could not add a gradient so that the lines would denote the said information and gives this random color between two colors at random. Here's what I tried.

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);
    }
like image 265
Samit Paudel Avatar asked Feb 23 '20 10:02

Samit Paudel


1 Answers

You can decompose a bezier curve into points using the bezierPoint()method and then draw straight line segments between successive points, specifying the colour for each individual line segment (meanwhile gradually lerping the colour of course).

I've produced a method which can do that in the code example below.

Additionally, with the method, you can specify the curve's magnitude (curve) and the direction of the curve (dir); the method calculates the bezier control point using the point on a line perpendicular to the midpoint between the start point (head) and end point (tail).

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

Result:

enter image description here

like image 133
micycle Avatar answered Oct 13 '22 00:10

micycle