[Processing] 筒を描く

#こんな
![Tubeクラス.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554244/6fc97e26-2d8d-806d-d7e0-7c341c76bee2.gif)

#プログラム

コンストラクタの引数はとりあえず2種類
`Tube(半径,淵の厚さ,長さ,角度)`
`Tube(半径,淵の厚さ,角度)`

使う時は
`tube.draw(角度);`
`tube.draw();`

難点はインスタンス生成時にstrokeとfillが決まること

```Tube.java
Tube t;

void setup() {
  size(800, 800, P3D);
  frameRate(30);
  t = new Tube(200, 50, 500, 360);
}

void draw() {
  background(50);
  translate(width/2, height/2);
  rotateY(frameCount * 0.016f);
  t.draw(frameCount);
  //t.draw();
}

public class Tube {
  private PVector[] inLine, outLine;
  public float radius;
  public float width,length;
  public int maxRadian;
  public PShape[] tube;
  public Tube(float radius, float width,float length, int maxRadian) {
    this.radius = radius;
    this.width = width;
    this.length = length;
    this.maxRadian = min(max(maxRadian, 0), 360) + 1;//clamp
    init();
  }
  public Tube(float radius, float width, int maxRadian){
    this(radius,width,width,maxRadian);
  }

  private void init() {
    inLine = new PVector[maxRadian];
    outLine = new PVector[maxRadian];
    float z = this.length * 0.5f;
    for (int i=0; i<maxRadian; i++) {
      float x = radius * cos(radians(i - 90));
      float y = radius * sin(radians(i - 90));
      PVector in = new PVector(x, y, z);
      x = this.width * cos(radians(i - 90));
      y = this.width * sin(radians(i - 90));
      PVector out = PVector.add(in, new PVector(x, y));
      inLine[i] = in;
      outLine[i] = out;
    }

    tube = createTube(maxRadian);
  }

  private PShape[] createTube(int radian) {
    PShape[] tube = new PShape[6];
    float z = this.length * 0.5f;
    for (int i=0; i<6; i++) {
      tube[i] = createShape();
    }
    
    tube[0].beginShape(TRIANGLE_STRIP);//手前
    tube[1].beginShape(TRIANGLE_STRIP);//奥
    tube[2].beginShape(QUAD_STRIP);//内側
    tube[3].beginShape(QUAD_STRIP);//外側
    for (int i=0; i<radian; i++) {
      tube[0].vertex(inLine[i].x, inLine[i].y, z);
      tube[0].vertex(outLine[i].x, outLine[i].y, z);
      tube[1].vertex(inLine[i].x, inLine[i].y, -z);
      tube[1].vertex(outLine[i].x, outLine[i].y, -z);
      tube[2].vertex(inLine[i].x, inLine[i].y, -z);
      tube[2].vertex(inLine[i].x, inLine[i].y, z);
      tube[3].vertex(outLine[i].x, outLine[i].y, -z);
      tube[3].vertex(outLine[i].x, outLine[i].y, z);
    }
    tube[0].endShape();
    tube[1].endShape();
    tube[2].endShape();
    tube[3].endShape();
    
    //始まりの蓋
    tube[4].beginShape();
    tube[4].vertex(inLine[0].x, inLine[0].y, -z);
    tube[4].vertex(outLine[0].x, outLine[0].y, -z);
    tube[4].vertex(outLine[0].x, outLine[0].y, z);
    tube[4].vertex(inLine[0].x, inLine[0].y, z);
    tube[4].endShape();
    //終わりの蓋
    int last = radian -1;
    tube[5].beginShape();
    tube[5].vertex(inLine[last].x, inLine[last].y, -z);
    tube[5].vertex(outLine[last].x, outLine[last].y, -z);
    tube[5].vertex(outLine[last].x, outLine[last].y, z);
    tube[5].vertex(inLine[last].x, inLine[last].y, z);
    tube[5].endShape();
    
    return tube;
  }

  private void draw(PShape[] tube){
    for (int i=0; i<tube.length; i++) {
      shape(tube[i]);
    }
  }
  
  public void draw(int radian) {
    radian = max(radian, 0);
    if (radian >= maxRadian) {
      draw();
      return;
    }
    PShape[] t = createTube(radian);
    draw(t);
  }
  public void draw() {
    draw(tube);
  }
}


```