# Bezier Curve move weight points

**URL:** <https://discourse.processing.org/t/bezier-curve-move-weight-points/8872>\
**Category:** Coding Questions\
**Created:** [March 3, 2019, 12:30am UTC](https://discourse.processing.org/t/bezier-curve-move-weight-points/8872 "2019-03-03T00:30:44Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ankita](https://avatars.discourse-cdn.com/v4/letter/a/91b2a8/32.png) [@ankita](https://discourse.processing.org/u/ankita)\
**Post date:** [March 3, 2019, 12:30am UTC](https://discourse.processing.org/t/bezier-curve-move-weight-points/8872/1 "2019-03-03T00:30:44Z")

</div>

I have a java code which moves control points (Corner points) according to the mouse movement. I need to modify the code so that it moves the weight points (the points in between the control points) according to the mouse drag.

```auto
PGraphics pg;
float scale, dW;
float [][] pt;
float [][] wpt;
boolean pressed;
int selected;

// Bezier curve
int order;

void setup() {
  // setup the screen
  size(600,400);
  pg = createGraphics(600,400);
  // scale of the image
  scale = 150;
  
  // prepare the Bezier curve
  order = 3;
  // declare the control polygon
  pt = new float[order + 1][3];
  // delcare the weight points
  wpt = new float[order][3];
  
  // initialize the control polygon
  float angle;
  int i;
  for(i = 0; i <= order; i += 1) {
    angle = 1.25*PI-1.5*PI*i/order;
    pt[i] = new float[] { 1, cos(angle), sin(angle) };
  }
  
  // set mouse to not pressed
  pressed = false;
  
  // initialize selected point: nothing = -1
  selected = -1;
  
  // initialize delta Weight
  dW = 0.05;
}

// convert from world coordinate to image coordinates x
float convertX(float x) {
  return 300 + scale*x;
}

// convert from image to world coordinates x
float convertXback(float x) {
  return (x - 300)/scale;
}

// convert from world coordinate to image coordinates y
float convertY(float y) {
  return 200 - scale*y;
}

// convert from image to world coordinate y
float convertYback(float y) {
  return (200 - y)/scale;
}

// draw edge of polygon
void drawLine(float[] p0, float[] p1) {
  pg.line(convertX(p0[1]/p0[0]), convertY(p0[2]/p0[0]), convertX(p1[1]/p1[0]), convertY(p1[2]/p1[0]));
}

// draw control polygon
void drawPolygon(float[][] pol, int n) {
  for(int i = 0; i < n; i += 1) {
    drawLine(pol[i], pol[i+1]);
  }
}

// make nice circles around points
void drawPoints(float pol[][], int n) {
  for(int i = 0; i <= n; i += 1) {
    pg.ellipse(convertX(pol[i][1]/pol[i][0]), convertY(pol[i][2]/pol[i][0]), 8, 8);
  }
}

// interpolate two points at value t
float[] interpolate(float[] p0, float[] p1) {
  return new float[] { (p0[0]+p1[0])/2, (p0[1]+p1[1])/2, (p0[2]+p1[2])/2 };
}

// compute one step in the deCasteljau algorithm, i is the number of the step (order-i) is the total number of points
float[][] deCasteljauStep(float [][] B, int i) {
  float[][] Bnext = new float[order-i][3];
  for(int j = 0; j < order-i; j += 1) {
    Bnext[j] = interpolate(B[j], B[j+1]);
  }
  return Bnext;
}

// full deCasteljau algorithm
void deCasteljau(float[][] pol, int level) {
  
  // initialise left and right control polygon
  float[][] lPol = new float[order+1][3];
  float[][] rPol = new float[order+1][3];
  
  // first and last point remain the same
  lPol[0] = pol[0];
  rPol[order] = pol[order];
  
  for(int i = 1; i <= order; i += 1) {
    pol = deCasteljauStep(pol, i-1);
    lPol[i] = pol[0];
    rPol[order-i] = pol[order-i];
  }
  
  if(level>0) {
    deCasteljau(lPol, level-1);
    deCasteljau(rPol, level-1);
  } else {
    drawPolygon(lPol, order);
    drawPolygon(rPol, order);
  }
}

// move control point
void moveControlPoint() {
  if(mousePressed) {
    // x and y of mouse in world coordinates
    float mx = convertXback(mouseX);
    float my = convertYback(mouseY);
    
    // if just pressed go through all control points and select closest one
    if(pressed == false) {
      pressed = true;
      
      // initialize selected point to be -1
      selected = -1;
      
      // variables to keep track of distance
      float dist = 999999999;
      float dist0;
      
      for(int i=0; i <= order; i += 1) {
        // use square of distance instead of distance to minimize computations
        dist0 = sq(pt[i][1]/pt[i][0]-mx) + sq(pt[i][2]/pt[i][0]-my);
        if(dist0 < dist) {
          dist = dist0;
          selected = i;
        }
      }
    } // end if pressed

    // change the selected control point to mouse location
    float w = pt[selected][0];
    
    // change weight
    if(keyPressed) {
      switch(keyCode) {
        case UP:
          w += dW;
          break;
        case DOWN:
          w -= dW;
          // make sure w is always positive (but not 0)
          if(w<=0) {
            w = 0.00001;
          }
          break;
      }
    }
    
    pt[selected] = new float[] { w, w*mx, w*my };
    
  } else { // end if pressed
    pressed = false;
  }
}

// calculate weight points
void calcWpt() {
  for(int i = 0; i < order; i += 1) {
    wpt[i][0] = pt[i][0]+pt[i+1][0];
    wpt[i][1] = pt[i][1]+pt[i+1][1];
    wpt[i][2] = pt[i][2]+pt[i+1][2];
  }
}

void draw() {
  // start drawing
  pg.beginDraw();
  pg.background(200);
  pg.fill(200);
  
  // draw control polygon
  pg.strokeWeight(2);
  drawPolygon(pt, order);
  // draw Bezier curve
  pg.strokeWeight(4);
  deCasteljau(pt,8);
  //draw control points
  pg.strokeWeight(2);
  drawPoints(pt, order);
  
  // calculate the weight points
  calcWpt();
  pg.strokeWeight(1);
  drawPoints(wpt, order-1);
  
  // move selected control point
  moveControlPoint();

  // end drawing
  pg.endDraw();
  image(pg,0,0);
}

```

---

<div class="post-metadata">

**Author:** ![jeremydouglass](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/jeremydouglass/32/20_2.png) [@jeremydouglass](https://discourse.processing.org/u/jeremydouglass)\
**Post date:** [March 9, 2019, 7:53pm UTC](https://discourse.processing.org/t/bezier-curve-move-weight-points/8872/2 "2019-03-09T19:53:34Z")

</div>

I believe that @Chrisir has written a number of graphical interfaces for 2D (and possibly 3D?) curve editing – perhaps he can share some links and / or give you advice on your method.

See his gallery post:

> [@Some Graphical Editors I made](https://discourse.processing.org/t/some-graphical-editors/5347):
>
> Some Graphical Editors (for all editors see the link below) : my Bezier Editor: here you can draw beziers with the mouse and the sketch generates your code that you can use in the other sketch (your target sketch) another version: like the above but you can now add points BETWEEN existing points and you can also select GROUPS of points (button “Select”) and then drag the entire group (button “Drag”) Similar to the programs above, I made a shape / PShape editor, where you can draw by cli…

Related past discussions:

- [Pro-Question: place a point in 3D with mouse](https://discourse.processing.org/t/pro-question-place-a-point-in-3d-with-mouse/6664)
- [Curve Graphs? - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/26628/curve-graphs)
- [[FIXED] Make bezier curve pass through control points - Processing 2.x and 3.x Forum](https://forum.processing.org/two/discussion/21355/fixed-make-bezier-curve-pass-through-control-points)

I can’t remember, but the ProScene library might also have some curve editing tools in it?

There is also an old (2009) tool called TimeLine which might be interesting to look at: its bezier curve interface is similar to one I used before in Quartz Composer.

[http://www.drifkin.net/timeline/#timeline](http://www.drifkin.net/timeline/#timeline)

![](https://yyz2.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/3/35aa415ed78430149539d41fb261fc6fe484dd0e.png)

For a simple Java-style curve editor that runs in processing.js (but no control points) see:

> **[Curve Editor v1 - Eric Colby - OpenProcessing](https://openprocessing.org/sketch/376966/)**
>
> Simple Curve Editor - to understand the shapes that can be created using curveVertex
> 
> Some GUI buttons were added to exposed addition functionality.

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [March 9, 2019, 8:53pm UTC](https://discourse.processing.org/t/bezier-curve-move-weight-points/8872/3 "2019-03-09T20:53:33Z")

</div>

In addition to my post (that has been linked above) a small sketch.

Chrisir

```auto

ArrayList<SimplePoint> bList = new ArrayList();

boolean runPoints=false;
float t; 

// drag with mouse
SimplePoint holding; 
boolean hold=false; 

void setup() {
  size(800, 800);
  bList = new ArrayList();
  background(0);
}

void draw() {
  background(0);

  // Run green ball 
  if (runPoints&&bList.size()==4) {
    displayRunningBall();
  }

  // decoration and showing curve ---------
  // show points
  int i_show_points=0;
  for (SimplePoint bz : bList) {
    bz.display( i_show_points );
    i_show_points++;
  }

  // show Bezier
  if (bList.size()==4) {
    showBezier();
  }

  // text 
  fill(255);
  text("Enter 4 points with the mouse (0 and 3 are anchors, 1 and 2 control points). \n"
    +"Then hit Enter to run a ball on the curve (Enter to stop). C to clear list.", 
    20, 20);

  // drag mouse 
  if (hold) {
    holding.x=mouseX; 
    holding.y=mouseY;
  }//if
}//func 

// ---------------------------------------------------------------------

void keyPressed() {
  if (keyCode == ENTER||keyCode == RETURN) { 
    runPoints = !runPoints; 
    // reset 
    t=0;
  } else if (key=='c') {
    bList.clear();
  }
}

void mousePressed() {
  // Do we have 4 points already? 
  if (bList.size()<4) {
    // No
    SimplePoint myBezier = new SimplePoint(mouseX, mouseY);  
    bList.add(myBezier); 
    runPoints=false;
  } else 
  {
    // Yes, drag with mouse 
    for (SimplePoint bz : bList) {
      if (dist(mouseX, mouseY, bz.x, bz.y) < 10) {
        hold=true; 
        holding=bz;
      }
    }
  }//else
}//

void mouseReleased() {
  hold = false; 
  holding = null;
}

// -------------------------------------------------------------------

void displayRunningBall() {

  int i=0;
  SimplePoint a1Point=(SimplePoint)bList.get(i);
  SimplePoint c1Point=(SimplePoint)bList.get(i+1);
  SimplePoint c2Point=(SimplePoint)bList.get(i+2);
  SimplePoint a2Point=(SimplePoint)bList.get(i+3);

  float x = bezierPoint(a1Point.x, c1Point.x, c2Point.x, a2Point.x, t/10);
  float y = bezierPoint(a1Point.y, c1Point.y, c2Point.y, a2Point.y, t/10);

  noStroke(); 
  fill(0, 255, 0); 
  ellipse(x, y, 10, 10); 

  strokeWeight (1);
  t += 0.1;
  if (t>10) {
    t=0;
  }
}// func

void showBezier() {
  int i2=0; 
  SimplePoint a1Point=(SimplePoint)bList.get(i2);
  SimplePoint c1Point=(SimplePoint)bList.get(i2+1);
  SimplePoint c2Point=(SimplePoint)bList.get(i2+2);
  SimplePoint a2Point=(SimplePoint)bList.get(i2+3);

  stroke(255);
  noFill(); 
  bezier ( a1Point.x, a1Point.y, 
    c1Point.x, c1Point.y, 
    c2Point.x, c2Point.y, 
    a2Point.x, a2Point.y);
}//func 

// ===================================================================

class SimplePoint {

  float x; 
  float y; 

  SimplePoint(float _x, float _y ) {
    x = _x; 
    y = _y;
  }

  void display( int i ) {
    stroke(255); 
    point(x, y); 
    point(x+1, y+1);
    fill(255);
    text(i, 
      x+4, y+5);
  }
}//class 
//

```
