why fillWater stopped working

Recently i'm pretty interested in chaos theory in general and the "Lorenz Mill" (youtube.com/watch?v=SlwEt5QhAGY). Tried to replicate one here. I have everything pretty much set up and the program does pretty much what i expected. But every time when the border between Holder[0] and Holder[11] crossed the positive y axis, the fillWater function doesn't seem to work and do nothing instead.

Holder[0] color is made different to track where everything is. Although i haven't tried to change it, i speculated that it can't be the problem because the math is separated from the deco

every Holder from 0 to 11 are virtually identical so it's strange to have the problem only in two of them (the code is pretty compact (i don't want to waste lines) so i suggest hit ctrl+T first) Thank you in advanced, here: PVector limits=new PVector(4*PI/3,5*PI/3);/*angles to pour water*/ class holder{ float theta;float level;/*level:0→1 drain:max(0.02,0.1*level) fill: 0.2*/ /*theta: 0→2PI*/ holder(float theta){this.theta=theta;} void fillWater(){float ang=angle+theta;if(ang>limits.x && ang<limits.y){level=constrain(level+0.2,0,1);}} void drainWater(){level=constrain(level-max(0.02,0.1*level),0,1);} void update(){drainWater();fillWater();} float torque(){return level*getLoc().x;} PVector getLoc(){float angl=angle+theta;PVector V=new PVector(cos(angl),sin(angl));return V;} } holder[] Holder;color green=color(69,128,100), blue=color(0,215,250);float angle=0.01,aV=0;/*angle & angular velcity*/ void setup(){ size(1200,600);background(0);fill(0);stroke(green);frameRate(10); Holder=new holder[12];for(int i=0;i<Holder.length;i++){Holder[i]=new holder(i*PI/6+0.01);} } float calTorque(){float sum=0;for(holder H : Holder){sum+=H.torque();}return sum/(10*Holder.length);} void update(){for(holder H : Holder){H.update();}aV+=calTorque();aV*=0.99;aV=constrain(aV,-0.1,0.1);angle+=aV;} void drawHolder(int index,int r){PVector loc=Holder[index].getLoc();loc.mult(r);fill(0);rect(300+loc.x-15,300+loc.y-25,30,50);fill(blue);rect(300+loc.x-15,300+loc.y-25+50*(1-Holder[index].level),30,50*Holder[index].level);text(index,300+loc.x,300+loc.y);} void draw(){ background(0); update(); ellipse(300,300,300,300); stroke(blue);/**/stroke(green);strokeWeight(5);for(int j=0;j<Holder.length;j++){drawHolder(j,150);stroke(blue);strokeWeight(1);}stroke(green);fill(0); for(holder H : Holder){print(H.level," ");}println(aV); }

Answers

  • Provide the entire code in a readable form using the forum's tools

  • edited January 2016

    Wow.. I need to think about it a little, but at least, I'll format your code for you now:

    PVector limits=new PVector(4*PI/3, 5*PI/3); 
    
    class holder {
      float theta;
      float level;
      holder(float theta) {
        this.theta=theta;
      }
      void fillWater() {
        float ang=angle+theta;
        if (ang>limits.x && ang<limits.y) {
          level=constrain(level+0.2, 0, 1);
        }
      }
      void drainWater() {
        level=constrain(level-max(0.02, 0.1*level), 0, 1);
      }
      void update() {
        drainWater();
        fillWater();
      }
      float torque() {
        return level*getLoc().x;
      }
      PVector getLoc() {
        float angl=angle+theta;
        PVector V=new PVector(cos(angl), sin(angl));
        return V;
      }
    }
    holder[] Holder;
    color green=color(69, 128, 100), blue=color(0, 215, 250);
    float angle=0.01, aV=0;
    
    void setup() {
      size(1200, 600);
      background(0);
      fill(0);
      stroke(green);
      frameRate(10);
      Holder=new holder[12];
      for (int i=0; i<Holder.length; i++) {
        Holder[i]=new holder(i*PI/6+0.01);
      }
    }
    float calTorque() {
      float sum=0;
      for (holder H : Holder) {
        sum+=H.torque();
      }
      return sum/(10*Holder.length);
    }
    void update() {
      for (holder H : Holder) {
        H.update();
      }
      aV+=calTorque();
      aV*=0.99;
      aV=constrain(aV, -0.1, 0.1);
      angle+=aV;
    }
    
    void drawHolder(int index, int r) {
      PVector loc=Holder[index].getLoc();
      loc.mult(r);
      fill(0);
      rect(300+loc.x-15, 300+loc.y-25, 30, 50);
      fill(blue);
      rect(300+loc.x-15, 300+loc.y-25+50*(1-Holder[index].level), 30, 50*Holder[index].level);
      text(index, 300+loc.x, 300+loc.y);
    }
    
    void draw() {
      background(0);
      update();
      ellipse(300, 300, 300, 300);
      stroke(blue);/**/
      stroke(green);
      strokeWeight(5);
      for (int j=0; j<Holder.length; j++) {
        drawHolder(j, 150);
        stroke(blue);
        strokeWeight(1);
      }
      stroke(green);
      fill(0);
      for (holder H : Holder) {
        print(H.level, " ");
      }
      println(aV);
    }
    
  • edited January 2016 Answer ✓

    The problem lies within line 11. The if statement works perfectly for the first trigonometric circle. After that, ang exceeds every limit.x and so no holders can fill. In the if statement, you should reference the angle ang in the first trigonometric circle, like this

      if (ang%(2*PI)>limits.x && ang%(2*PI)<limits.y) {
        level=constrain(level+0.2, 0, 1);
      }
    
  • I also wanted to recommend you to create a class WaterMill and create holders there. You'll be able to easily create another mill and place them side by side to see the effect demonstrated in video.

  • edited January 2016

    (i don't want to waste lines)

    yeah, those pixels are really expensive.

    so instead you end up with something that is unreadable, takes twice as long to develop / debug...

  • edited January 2016

    end up with something that is unreadable

    well i only compressed really concrete parts that're near impossible to be wrong... and the trade off is that you can see the whole program in 1 short piece (tabs just segment out the program and formatted just takes too much time to scroll down)

    By the way, i've perfected it now (just want to share it with you guys):

    PVector limits=new PVector(4*PI/3, 5*PI/3);
    float fillRate=0.02, fillDrainRatio=0.1;
    class holder {
      float theta;
      float level;/**level:0→1   drain:max(0.02,0.1*level)  fill: 0.2*/
      holder(float theta) {
        this.theta=theta;
      }
      void fillWater() {
        float ang=angle+theta;
        if (ang%TWO_PI>limits.x && ang%TWO_PI<limits.y) {
          level=constrain(level+fillRate, 0, 1);
        }
      }
      void drainWater() {
        level=constrain(level-0.05*fillDrainRatio, 0, 1);
      }/**max(0.005,0.01)*/
      void update() {
        drainWater();
        fillWater();
      }
      float torque() {
        return level*getLoc().x;
      }
      PVector getLoc() {
        float ang=angle+theta;
        PVector V=new PVector(cos(ang), sin(ang));
        return V;
      }
      PVector centerOfMass() {
        float ang=angle+theta;
        PVector V=new PVector(cos(ang), sin(ang));
        V.mult(level);
        return V;
      }
    }
    holder[] Holder;
    color green=color(69, 128, 100), blue=color(0, 215, 250);
    float angle=0.01, aV=0;/**angle & angular velcity*/
    void setup() {
      size(1200, 600);
      background(0);
      fill(0);
      stroke(green);
      frameRate(30);
      Holder=new holder[12];
      for (int i=0; i<Holder.length; i++) {
        Holder[i]=new holder(i*PI/6+0.01);
      }
    }
    float calTorque() {
      float sum=0;
      for (holder H : Holder) {
        sum+=H.torque();
      }
      return sum/(30*Holder.length);
    }
    void update() {
      for (holder H : Holder) {
        H.update();
      }
      aV+=calTorque();
      aV*=0.9678;/**aV=constrain(aV,-0.1,0.1);*/
      angle+=aV;
      angle+=TWO_PI;
      angle%=TWO_PI;
    }
    void drawHolder(int index, int r) {
      PVector loc=Holder[index].getLoc();
      loc.mult(r);
      fill(0);
      rect(300+loc.x-15, 300+loc.y-25, 30, 50);
      fill(blue);
      rect(300+loc.x-15, 300+loc.y-25+50*(1-Holder[index].level), 30, 50*Holder[index].level);
      text(index, 300+loc.x, 300+loc.y);
    }
    PVector centerOfMass() {
      PVector result=new PVector(0, 0);
      for (holder H : Holder) {
        result.add(H.centerOfMass());
      }
      return result;
    }
    void draw() {
      fill(0);
      rect(0, 0, 600, 600);
      ellipse(300, 300, 300, 300);
      update();
      strokeWeight(5);
      drawHolder(0, 150);
      stroke(blue);
      strokeWeight(1);
      for (int j=1; j<Holder.length; j++) {
        drawHolder(j, 150);
      }
      stroke(green);
      //for(holder H:Holder){print(H.level," ");}println(aV);
      translate(900, 300);
      fill(green);
      PVector V=centerOfMass();
      ellipse(100*V.x, 700*aV, 1, 1);
    }
    
Sign In or Register to comment.