[
  {
    "path": "Animation/OmbroCinema/OmbroCinema.pde",
    "content": "/*\n  OmbroCinema\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.10.1)\n\n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n  —\n  Keyboard : \n    - 'i' draws the composition\n    - 'c' draws the composition with mask\n    - 'a' draws animation frames\n    - 'e' exports composition (with timestamp) + mask to .pdf format\n\n*/\n\n// ------------------------------------------------------\nimport processing.pdf.*;\n\n// ------------------------------------------------------\nScanimation scanimation;\nint mode = 0;\n\n// ------------------------------------------------------\nvoid setup()\n{\n  size(600, 600);\n  // Create the Scanimation instance, which will be made of 6 frames\n  scanimation = new Scanimation(this, 6);\n  // Compose the final frame (this is calling \"drawScanimationFrame\" for each frame)\n  scanimation.composeFinalFrame();\n  // Set the animation period in seconds (use 'a' on keyboard)\n  scanimation.setTimerPeriod(0.5);\n}\n\n// ------------------------------------------------------\nvoid draw()\n{\n  background(255);\n  \n  // Draws the composition\n  if (mode == 0)\n  {\n    scanimation.draw();\n  }\n  // Draws the composition with mask\n  else if (mode == 1)\n  {\n    scanimation.drawWithMask();\n  }\n  // Draws the animation\n  else if (mode == 2)\n  {\n    scanimation.animate();\n  }\n}\n\n// ------------------------------------------------------\n// Automatically called by composeFinalFrame\nvoid drawScanimationFrame(PGraphics pg, int frame, int nbFrames)\n{\n    pg.translate(pg.width/2, pg.height/2);\n    pg.rotate( map(frame, 0, nbFrames, 0, radians(90)) );\n    pg.noStroke();\n    pg.rectMode(CENTER);\n    pg.rect(0,0,400,100);\n    pg.ellipse(30,60,100,100);\n  }\n\n\n// ------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == 'i')\n  {\n    mode = 0;\n  }\n  else if (key == 'c')\n  {\n    mode = 1;\n  }\n  else if (key == 'a')\n  {\n    mode = 2;\n  }\n  else if (key == 'e')\n  {\n    scanimation.exportPDF();\n  }\n}\n\n"
  },
  {
    "path": "Animation/OmbroCinema/Scanimation.pde",
    "content": "import java.lang.reflect.*;\n\n// ------------------------------------------------------\nclass Scanimation\n{\n  int nbFrames;\n  PApplet applet;\n  Method methodFrame;\n\n  ArrayList<PGraphics> listFrames;\n  ArrayList<PGraphics> listMaskedFrames;\n  PGraphics compositionFrame;\n  PGraphics maskFrame, maskFrameScreen, currentFrame;\n\n  Timer timer;\n  float periodChangeFrame = 0.25f; // seconds\n  float timeChangeFrame=0.0f;  \n  int framePlaying = 0;\n\n  boolean exportCompo = false;\n\n\n  // ------------------------------------------------------\n  Scanimation(PApplet applet, int nbFrames)\n  {\n    this.applet = applet;\n    this.nbFrames = nbFrames;\n    createFrames();\n    findMethodFrame();\n    createTimer();\n  }\n\n  // ------------------------------------------------------\n  Scanimation(PApplet applet)\n  {\n    this.applet = applet;\n    this.nbFrames = 6;\n    createFrames();\n    findMethodFrame();\n    createTimer();\n  }\n\n  // ------------------------------------------------------\n  void createFrames()\n  {\n    listFrames = new ArrayList<PGraphics>();\n    listMaskedFrames = new ArrayList<PGraphics>(); \n    for (int i=0;i<nbFrames;i++) {\n      listFrames.add( createGraphics(applet.width, applet.height) );\n      listMaskedFrames.add( createGraphics(applet.width, applet.height) );\n    }\n\n    compositionFrame = createGraphics(applet.width, applet.height);\n    maskFrame = createGraphics(applet.width, applet.height);\n    maskFrameScreen = createGraphics(applet.width, applet.height);\n\n    maskFrame.beginDraw();\n    maskFrame.background(255);\n    drawMaskStripes(maskFrame);\n    maskFrame.endDraw();\n\n    maskFrameScreen.beginDraw();\n    drawMaskStripes(maskFrameScreen);\n    maskFrameScreen.endDraw();\n  }\n\n  void drawMaskStripes(PGraphics maskFrame)\n  {\n    maskFrame.rectMode(CORNER);\n    maskFrame.noStroke();\n    maskFrame.fill(0);\n\n    int x = 0;\n    while (x<applet.width) {\n      maskFrame.rect(x, 0, nbFrames-1, applet.height);\n      x+=nbFrames;\n    }\n  }\n\n  // ------------------------------------------------------\n  void createTimer()\n  {\n    timer = new Timer();\n  }\n\n  // ------------------------------------------------------\n  void resetTimer()\n  {\n    timeChangeFrame = 0.0f;\n  }\n  \n  // ------------------------------------------------------\n  void setTimerPeriod(float period)\n  {\n    periodChangeFrame = period;\n  }\n\n  // ------------------------------------------------------\n  void animate()\n  {\n    float dt = timer.update();\n    timeChangeFrame+=dt;\n    if (timeChangeFrame>=periodChangeFrame)\n    {\n      framePlaying = (framePlaying+1)%getNumberFrames();\n      resetTimer();\n    }\n    PGraphics frame = getFrame(framePlaying); \n    image(frame, 0, 0, width, height);\n  }\n\n  // ------------------------------------------------------\n  int getNumberFrames()\n  {\n    return nbFrames;\n  }\n\n  // ------------------------------------------------------\n  PGraphics getFrame(int i)\n  {\n    return listFrames.get(i);\n  }\n\n  // ------------------------------------------------------\n  PGraphics getFrameMasked(int i)\n  {\n    return listMaskedFrames.get(i);\n  }\n\n  // ------------------------------------------------------\n  PGraphics getCompositionFrame()\n  {\n    return compositionFrame;\n  }\n\n  // ------------------------------------------------------\n  PGraphics getMaskFrame()\n  {\n    return maskFrame;\n  }\n\n  // ------------------------------------------------------\n  PGraphics getMaskFrameScreen()\n  {\n    return maskFrameScreen;\n  }\n\n  // ------------------------------------------------------\n  void findMethodFrame()\n  {\n    try \n    {\n      this.methodFrame = applet.getClass().getMethod(\"drawScanimationFrame\", new Class[] {\n        PGraphics.class, Integer.TYPE, Integer.TYPE\n      }\n      );\n      System.out.println(\"- \\\"findMethodFrame\\\" found.\");\n    } \n    catch (Exception e) \n    {\n      System.out.println(\"- no \\\"findMethodFrame\\\" found.\");\n    }\n  }\n\n  // ------------------------------------------------------\n  void composeFinalFrame()\n  {\n    if (methodFrame != null)\n    {\n\n      // Draw Each Frame\n      PGraphics frame, frameMasked;\n\n      for (int i=0;i<nbFrames;i++) {\n        beginFrame(i);\n        try {\n          frame = listFrames.get(i);\n          frameMasked = listMaskedFrames.get(i);\n\n          frame.pushMatrix();\n          frame.background(255);\n          frame.noStroke();\n          frame.fill(0);  \n          methodFrame.invoke( applet, new Object[] { \n            frame, i, nbFrames\n          } \n          );\n          frame.popMatrix();\n\n          PImage frameImg = frame.get();\n          frameImg.mask(maskFrame);\n\n          frameMasked.beginDraw();\n          frameMasked.image(frameImg, 0, 0, frame.width, frame.height);\n          frameMasked.endDraw();\n\n          //frameMasked.get().mask(maskFrame);\n        }\n        catch (Exception e) {\n        }\n        endFrame();\n      }\n\n      // Compose\n      compositionFrame.beginDraw();\n      compositionFrame.background(255);\n      for (int i=0;i<nbFrames;i++) {\n        frameMasked = listMaskedFrames.get(i);\n        compositionFrame.blend(frameMasked, 0, 0, frameMasked.width, frameMasked.height, i, 0, frameMasked.width, frameMasked.height, BLEND);\n      }\n      compositionFrame.endDraw();\n    }\n  }\n\n  // ------------------------------------------------------\n  void beginFrame(int i)\n  {\n    if (i>=nbFrames) return;\n    currentFrame = listFrames.get(i);\n    currentFrame.beginDraw();\n  }\n\n  // ------------------------------------------------------\n  void endFrame()\n  {\n    if (currentFrame!=null)\n      currentFrame.endDraw();\n  }\n\n  // ------------------------------------------------------\n  void draw()\n  {\n    if (exportCompo)\n    {\n      exportCompo = false;\n\n      String time = timestamp();\n      beginRecord(PDF, \"exports/\"+time+\"_export.pdf\");\n      strokeCap(SQUARE);\n      stroke(0, 255);\n      strokeWeight(2);\n\n      compositionFrame.loadPixels();\n      boolean isBeginLine = false;\n      int r = 0, i=0, j=0, jbegin=0;\n\n      for (i=0;i<compositionFrame.width;i++)\n      {\n        isBeginLine = false;\n        for (j=0;j<compositionFrame.height;j++)\n        {\n          r = (int)red( compositionFrame.get(i, j) );\n          if (isBeginLine)\n          {\n            if (r>=254) {\n              isBeginLine = false;\n              line(i, jbegin, i, j-1);\n              println(\"colonne end \"+i+\";j=\"+j);\n            }\n          }\n          else\n          {\n            if (r<=5) {\n              isBeginLine = true;\n              jbegin = j;\n              println(\"colonne begin \"+i+\";j=\"+j);\n            }\n          }\n        }\n\n        if (isBeginLine)\n        {\n          line(i, jbegin, i, compositionFrame.height);\n        }\n      }\n      endRecord();\n    }\n    image(compositionFrame, 0, 0, width, height);\n  }\n\n  // ------------------------------------------------------\n  void drawWithMask()\n  {\n    image(getCompositionFrame(),0,0);\n    blend(getMaskFrameScreen(), 0, 0, width, height, mouseX-width/2, 0, width, height, BLEND);\n  }\n  \n  // ------------------------------------------------------\n  void exportPDF()\n  {\n    exportCompo = true;\n  }\n};\n\n"
  },
  {
    "path": "Animation/OmbroCinema/Utils.pde",
    "content": "import java.util.Calendar;\n\n// ------------------------------------------------------\nclass Timer\n{\n  float now, before;\n  Timer()\n  {\n    now = before = millis();\n  }\n\n  float update()\n  {\n    now = millis();\n    float dt = now-before;\n    before = now;\n    \n    return dt/1000.0f;\n  }\n}\n\n// ------------------------------------------------------\nString timestamp() \n{\n  Calendar now = Calendar.getInstance();\n  return String.format(\"%1$ty%1$tm%1$td_%1$tH%1$tM%1$tS\", now);\n}\n"
  },
  {
    "path": "Forms/CellularAutomaton/Automaton.pde",
    "content": "class Automaton\n{\n  Grid grid;\n  int line=0;\n  boolean done = false;\n  int frameStep = 2;  \n  int rule = RULE_30;\n\n  final static int RANDOM = 0;\n  final static int CENTER = 1;\n  \n  final static int RULE_30   = 30;\n  final static int RULE_110  = 110;\n\n  Automaton(int rule, int initMode, int resx, int resy)\n  {\n    this.grid     = new Grid(resx, resy);\n    this.rule     = rule;\n    if (initMode == RANDOM)\n    {\n      for (int i=0; i<resx; i++)\n        if (random(1.0)>0.5)\n          this.grid.setState(i, 0, 1);\n    }\n    else if (initMode == CENTER)\n    {\n      this.grid.setState(resx/2, 0, 1);\n    }\n  }\n\n  void setFrameStep(int n)\n  {\n    this.frameStep = max(1,n);\n  }\n\n  void setRule(int which)\n  {\n    this.rule = which;\n  }\n\n  boolean applyRule(int which, int s_1, int s0, int s1)\n  {\n    if (which == 30)\n    {\n      return \n        ((s_1==1 && s0==0 && s1==0) ||\n        (s_1==0 && s0==1 && s1==1) ||\n        (s_1==0 && s0==1 && s1==0) ||\n        (s_1==0 && s0==0 && s1==1));\n    } else if (which == 110)\n    {\n      return \n        ((s_1==1 && s0==1 && s1==0) ||\n        (s_1==1 && s0==0 && s1==1) ||\n        (s_1==0 && s0==1 && s1==1) ||\n        (s_1==0 && s0==1 && s1==0) ||\n        (s_1==0 && s0==0 && s1==1));\n    }\n    return false;\n  }\n\n\n  void run()\n  {\n    if (this.done || frameCount%frameStep!=0) return;\n\n    int i, j = line;\n    int s_1, s0, s1;\n    for (i=1; i<this.grid.resx-1; i++)\n    {\n      s_1 = this.grid.getState(i-1, j);\n      s0  = this.grid.getState(i+0, j);\n      s1  = this.grid.getState(i+1, j);\n      if (applyRule(this.rule, s_1, s0, s1)) \n      {\n        this.grid.setState(i, j+1, 1);\n      } else\n      {\n        this.grid.setState(i, j+1, 0);\n      }\n    }\n\n    this.line++;\n    if (this.line >= this.grid.resy-1)\n      this.done = true;\n  }\n\n  void draw()\n  {\n    // this.grid.draw();\n    this.grid.drawState();\n  }\n}\n"
  },
  {
    "path": "Forms/CellularAutomaton/CellularAutomaton.pde",
    "content": "/*\n  CellularAutomaton\n —\nAn implementation of Rule 30 / 110 cellular automata described here:\nhttps://en.wikipedia.org/wiki/Rule_30\nhttps://en.wikipedia.org/wiki/Rule_110\n—\n Developped and tested on : \n - Processing 3.5.3 on Windows 10\n \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n */\n\nAutomaton automaton;\n\nvoid setup()\n{\n  size(500,500); \n  surface.setTitle(\"Rule 30 / 110\");\n\n  automaton = new Automaton(Automaton.RULE_110,Automaton.RANDOM,200,200);\n  automaton.setFrameStep(2); // every \"n\" frames\n}\n\nvoid draw()\n{\n  background(255);\n  automaton.run();\n  automaton.draw();\n}\n"
  },
  {
    "path": "Forms/CellularAutomaton/Grid.pde",
    "content": "class Grid\n{\n  int resx, resy;\n  int[] state;\n  float cellw, cellh;\n  \n  Grid(int resx, int resy)\n  {\n    this.resx = resx;\n    this.resy = resy;\n    this.state = new int[resx*resy];\n    this.cellw = float(width) / resx;\n    this.cellh = float(height) / resy;\n  }\n  \n  void setState(int i, int j, int state)\n  {\n    this.state[i+j*this.resx] = state;\n  }\n  \n  int getState(int i, int j)\n  {\n    return this.state[i+j*this.resx];\n  }\n\n  void draw()\n  {\n    pushStyle();\n    stroke(220);\n    float x=0.0, y=0.0;\n    for (int i=0; i<=this.resy; i++)\n    {\n       x = i*this.cellw;\n       line(x,0,x,height);\n    }\n    for (int i=0; i<=this.resy; i++)\n    {\n       y = i*this.cellh;\n       line(0,y,width,y);\n    }\n    popStyle();\n  }\n\n  void drawState()\n  {\n\n    pushStyle();\n    noStroke();\n    fill(0);\n    int i, j;\n    float x=0.0, y=0.0;\n    int c = 0;\n    for (j=0; j<this.resy; j++)\n    {\n      x = 0.0;\n      for (i=0; i<this.resx; i++)\n      {\n        c = this.state[i+j*this.resx];\n        if (c==1) \n          rect(x, y, cellw, cellh);\n        x+=this.cellw;\n      }\n      y+=this.cellh;\n    }\n    popStyle();\n  }\n}\n"
  },
  {
    "path": "Forms/Chladni/Chladni.pde",
    "content": "/*\n  Chladni plate interference surfaces\n \n —\n Based on :\n http://paulbourke.net/geometry/chladni/\n \n —\n Developped and tested on : \n - Processing 2.1.1 on MacOSX (10.9.2)\n  \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n \n */\n\n\n// ------------------------------------------------------------------------------------------------\nfloat m=10, n=2;\nfloat L = 500;\nfloat epsilon = 0.05;\nboolean recompute = true;\n\n// ------------------------------------------------------------------------------------------------\nvoid settings()\n{\n  size((int)L, (int)L);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  if (recompute) {\n    recompute = false;\n\n    background(255);\n    loadPixels();\n\n    float chladni = 0.0f;\n    int offset = 0;\n    for (float y=0; y<height; y++) {\n      for (float x=0; x<width; x++) {\n        chladni = cos(n*PI*x/L)*cos(m*PI*y/L) - cos(m*PI*x/L)*cos(n*PI*y/L);\n        if (abs(chladni)<=epsilon) {\n          offset = (int)x+(int)y*(int)L;\n          pixels[offset] = color(0, 0, 0);\n        }\n      }\n    }    \n    updatePixels();\n\n    /*\n    String infos = \"m=\"+(int)m+\";n=\"+(int)n+\"\\nepsilon=\"+nf(epsilon,1,4);\n    fill(255,0,0);\n    text(infos,4,16);\n    */\n  }\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == CODED)\n  {\n    if (keyCode == UP) { \n      m+=1; \n      recompute = true;\n    }\n    if (keyCode == DOWN) { \n      m-=1; \n      recompute = true;\n    }\n    if (keyCode == LEFT) { \n      n-=1; \n      recompute = true;\n    }\n    if (keyCode == RIGHT) { \n      n+=1; \n      recompute = true;\n    }\n  } else\n  {\n    if (key == '+') { \n      epsilon += 0.01; \n      recompute= true;\n    }\n    if (key == '-') { \n      epsilon -= 0.01; \n      recompute= true;\n    }\n  }\n\n  m = constrain(m, 1, 20);\n  n = constrain(n, 1, 20);\n}\n"
  },
  {
    "path": "Forms/Circles_recursion/Circle.pde",
    "content": "class Circle\n{\n  float radius;\n  float angle = 0.0;\n  float angleSpeed = 0.0;\n  int depth = 0;\n  boolean bPause = false;\n\n  Circle parent;\n  Circle child;\n\n  PVector pos = new PVector();\n\n  Circle(Circle parent_, float radius_)\n  {\n    this.angleSpeed = random(angle_speed_min, angle_speed_max);\n    this.parent = parent_;\n    this.radius = radius_;\n    if (this.parent != null)\n    {\n      this.angleSpeed = this.parent.angleSpeed + angle_speed_child;\n      this.depth = ++this.parent.depth;\n    }\n    if (this.radius > radius_min)\n      this.child = new Circle(this, this.radius * radius_size_factor);\n  }\n\n  void setRadius(float radius_)\n  {\n    this.radius = radius_;\n    if (this.child != null)\n      this.child.setRadius(radius_size_factor * this.radius);\n  }\n\n  void modifyAngleSpeed()\n  {\n    if (parent == null)\n    {\n      this.angleSpeed = random(angle_speed_min, angle_speed_max);\n      if (this.child != null)\n        this.child.modifyAngleSpeed();\n    } else\n    {\n      this.angleSpeed = this.parent.angleSpeed + angle_speed_child;\n    }\n  }\n\n  void setPos(float x, float y)\n  {\n    this.pos.set(x, y);\n  }\n\n  void setPause(boolean bPause_)\n  {\n    bPause = bPause_;\n    if (this.child != null) \n      this.child.setPause(bPause);\n  }\n\n  void update()\n  {\n    if (this.parent != null)\n    {\n      this.pos.x = this.parent.pos.x + (this.parent.radius - this.radius)*cos( radians(angle) ); \n      this.pos.y = this.parent.pos.y + (this.parent.radius - this.radius)*sin( radians(angle) ); \n\n      if (bPause == false)\n        this.angle += this.angleSpeed;\n    }\n\n    if (this.child != null)  \n      this.child.update();\n  }\n\n\n  void draw()\n  {\n    noFill();\n    if (bDrawFilled)\n      fill( depth%2 == 0 ? color(255) : color(0) );\n    else\n      stroke(0, 200);\n\n    ellipse(pos.x, pos.y, 2*radius, 2*radius);\n\n    if (this.child != null)  \n      this.child.draw();\n  }\n}"
  },
  {
    "path": "Forms/Circles_recursion/Circles_recursion.pde",
    "content": "/*\n  Circles_recursion\n\n  —\n  Developped and tested on : \n    - Processing 3.2.1 on MacOSX (10.12.5)\n    \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n\n// --------------------------------------------------\nfloat radius_min = 5;\nfloat radius_size_factor = 0.75;\nfloat radius_factor = 1.0;\nfloat angle_speed_min = 1, angle_speed_max = 3;\nfloat angle_speed_child = 0.5;\nboolean bDrawFilled = true;\n\nCircle circle;\n\n\n// --------------------------------------------------\nvoid setup()\n{\n  size(500,500);\n  circle = new Circle(null,0.5*0.95*min(width,height));\n  circle.setPos(width/2, height/2);\n}\n\n// --------------------------------------------------\nvoid draw()\n{\n  background(255);\n  circle.update();\n  circle.draw();\n}"
  },
  {
    "path": "Forms/HilbertCurve/HilbertCurve.pde",
    "content": "/*\n  Hilbert Curve\n  —\n  Based on explanations found here :\n  https://www.youtube.com/watch?v=3s7h2MHQtxc\n  —\n  Developped and tested on : \n    - Processing 3.2.1 on MacOSX (10.12.5)\n    \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n*/\n\n// ------------------------------------------------------------------------------------------------\nimport java.util.Collections;\n\n// ------------------------------------------------------------------------------------------------\nArrayList<PVector> hilbertPoints;\nint margin = 5;\n\n// ------------------------------------------------------------------------------------------------\nvoid setup()\n{\n  size(500, 500);\n  hilbertPoints = getHilbertPoints(6, margin, margin, width-2*margin, height-2*margin);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  background(255);\n  stroke(0);\n  strokeWeight(2);\n  int nbPoints = hilbertPoints.size();\n  PVector A = hilbertPoints.get(0);\n  PVector B = null;\n  for (int i=0; i<nbPoints-1; i++)\n  {\n    B = hilbertPoints.get(i+1);\n    line(A.x, A.y, B.x, B.y);\n\n    A = B;\n  }\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == 's') saveFrame(\"Hilbert.png\");\n}\n\n// ------------------------------------------------------------------------------------------------\nArrayList<PVector> getHilbertPoints(int order, float x, float y, float w, float h)\n{\n  ArrayList<PVector> points = new ArrayList<PVector>();\n\n  float w2 = w/2;\n  float h2 = h/2;\n\n  if (order == 1)\n  {\n    points.add(new PVector(x+w2/2, y+3*h2/2)); // SW\n    points.add(new PVector(x+w2/2, y+h2/2)); // NW\n    points.add(new PVector(x+3*w2/2, y+h2/2)); // NE\n    points.add(new PVector(x+3*w2/2, y+3*h2/2)); // SE\n  } else\n  {\n    ArrayList<PVector> pointsNW = getHilbertPoints(order-1, x,     y,     w2, h2);\n    ArrayList<PVector> pointsNE = getHilbertPoints(order-1, x+w2,  y,     w2, h2);\n    ArrayList<PVector> pointsSW = getHilbertPoints(order-1, x,     y+h2,  w2, h2);\n    ArrayList<PVector> pointsSE = getHilbertPoints(order-1, x+w2,   y+h2, w2, h2);\n\n    flipPoints(90,   pointsSW, x, y+h2, w2, h2);\n    flipPoints(-90,   pointsSE, x+w2, y+h2, w2, h2);\n\n    points.addAll(pointsSW);\n    points.addAll(pointsNW);\n    points.addAll(pointsNE);\n    points.addAll(pointsSE);\n  }\n\n  return points;\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid flipPoints(int which, ArrayList<PVector> source, float x, float y, float w, float h)\n{\n  if (which == 90)\n  {\n    for (PVector p : source)\n      p.set( x + w - (p.y-y), y + p.x-x );\n  } else if (which == -90)\n  {\n    for (PVector p : source)\n      p.set( x + (p.y-y), y + h-(p.x-x) );\n  }\n\n  Collections.reverse(source);\n}\n"
  },
  {
    "path": "Forms/L_System/LInterpreter.pde",
    "content": "interface LInterpreter\n{\n  void run(String s);\n}\n"
  },
  {
    "path": "Forms/L_System/LRule.pde",
    "content": "class LRule\n{\n  char variable;\n  String replacement;\n  \n  LRule(char v, String r)\n  {\n    this.variable = v;\n    this.replacement = r;\n  }\n  \n  String apply()\n  {\n    return replacement;\n  }\n}\n"
  },
  {
    "path": "Forms/L_System/LSystem.pde",
    "content": "class LSystem\n{\n  String seed = \"\";  \n  int generation = 0;\n  ArrayList<String> listGenerations;\n  ArrayList<LRule> listRules;\n  String str=\"\";\n  LInterpreter interpreter;\n  String infos=\"\";\n  \n  LSystem(String seed)\n  {\n    init(seed);\n  }\n\n  LSystem(String seed,LInterpreter interpreter)\n  {\n    init(seed);\n    setInterpreter(interpreter);\n  }\n  \n  void init(String seed)\n  {\n    this.seed = this.str = seed;\n    this.listGenerations = new ArrayList<String>(); \n    this.listRules = new ArrayList<LRule>();\n  \n    this.listGenerations.add(seed);\n  }\n\n  void setInterpreter(LInterpreter interpreter)\n  {\n    this.interpreter = interpreter;\n  }\n  void addRule(char c, String r)\n  {\n    addRule( new LRule(c,r) );\n  }\n  \n  void addRule(LRule r)\n  {\n    this.listRules.add(r);\n  }\n  \n  void grow(int generations)\n  {\n    for (int i=0;i<generations;i++) \n      grow();\n  }\n\n  void grow()\n  {\n    String newstr = applyRules();\n    listGenerations.add(newstr);\n    str = newstr;\n    generation++;\n  }\n  \n  String applyRules()\n  {\n    String newstr = \"\";\n    for (int i=0;i<str.length();i++){\n      char c = str.charAt(i);\n      LRule rule = getRuleFor(c);\n      if (rule != null){\n        newstr+=rule.apply();\n      }\n      else{\n        newstr+=c;\n      }\n    }\n    return newstr;\n  }\n  \n  LRule getRuleFor(char c)\n  {\n    for (LRule rule:listRules){\n      if (rule.variable == c)\n        return rule;\n    }    \n    return null;\n  }\n  \n  int getLastGeneration()\n  {\n    if (generation>0)  \n      return generation;\n    return -1;\n  }\n  \n  void draw()\n  {\n    draw(interpreter,getLastGeneration());\n  }\n  \n  void draw(LInterpreter interpreter, int generation)\n  {\n    if (interpreter!=null && generation!=-1)\n    {\n      interpreter.run( listGenerations.get(generation) );\n    }\n  }\n  \n  void drawInfos()\n  {\n    if (infos.equals(\"\")){\n      infos += seed+\"\\n\";\n      for (LRule rule:listRules)\n      {\n        infos+=rule.variable+\" to \"+rule.replacement+\"\\n\";\n      }\n    }\n    fill(0);\n    textSize(11);\n    text(infos,4,12);\n  }\n  \n  String toString()\n  {\n    String s = generation+\" generations\\n\";\n    s+=\"----\";\n    int i=0;\n    for (String str:listGenerations)\n    {\n      s+= i+\"-\"+str+\"[\"+str.length()+\" chars]\\n\";\n      i++;\n    }\n    return s;\n  }\n\n}\n"
  },
  {
    "path": "Forms/L_System/L_System.pde",
    "content": "/*\n  L_system\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.9.2)\n    \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n// ------------------------------------------------------------------------------------------------\nLSystem ls2;\n\n// ------------------------------------------------------------------------------------------------\nvoid setup()\n{\n  ls2 = new LSystem(\"X\", new LInterpreterF());\n  ls2.addRule('X', \"F-[[X]+X]+FF[+FX]-X\");\n  ls2.addRule('F', \"FF\");\n\n  ls2.grow(6);\n  println(ls2);\n  \n  size(500,500);\n  smooth();\n}\n\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  background(255);\n\n  pushMatrix();\n  translate(width/2, height);\n  ls2.draw();\n  popMatrix();\n  ls2.drawInfos();\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid mousePressed()\n{\n  saveFrame(\"lsystem.png\");\n}\n\n\n// ------------------------------------------------------------------------------------------------\nclass LInterpreterF implements LInterpreter\n{\n  float angle = PI/10;\n  float length = 2.1;\n  \n  LInterpreterF()\n  {\n  }\n  \n  void run(String s)\n  {\n    length=map(mouseY,0,height,1,3);\n    angle=map(mouseX,0,width,0,PI);\n\n    stroke(0);\n    noFill();\n    int nbChars = s.length();\n    char c;\n    for (int i=0;i<nbChars;i++){\n      c = s.charAt(i);\n      switch(c)\n      {\n        case 'F':\n          line(0,0,0,-length);\n          translate(0,-length);\n        break;\n\n        case '+':\n          rotate(angle);\n        break;\n\n        case '-':\n          rotate(-angle);\n        break;\n\n        case '[':\n          pushMatrix();\n        break;\n\n        case ']':\n          popMatrix();\n        break;\n      }\n    }\n    \n  }\n}"
  },
  {
    "path": "Forms/LangtonAnt/Ant.pde",
    "content": "class Ant\n{\n  Grid grid;\n  int i, j; // cell position on grid\n  int turn=0; // 0 -> 0, 1->90, 2->180, 3->270\n  Ant(Grid grid, int i, int j)\n  {\n    this.grid = grid;\n    this.i = i%this.grid.resx;\n    this.j = j%this.grid.resy;\n    this.turn=0;\n  }\n\n  void run()\n  {\n    //if (frameCount % 2 == 0)\n    {\n      // check the state of the grid\n      int c = this.grid.getState(this.i, this.j);\n      // White square\n      if (c == 0)\n      {\n        this.grid.setState(this.i, this.j, 1);\n        this.turn90CW();\n        this.move();\n      }\n      // Black square\n      else if (c == 1)\n      {\n        this.grid.setState(this.i, this.j, 0);\n        this.turn90CCW();\n        this.move();\n      }\n    }\n  }\n\n  void turn90CW()\n  {\n    turn = (turn+1)%4;\n  }\n\n  void turn90CCW()\n  {\n    turn = turn-1;\n    if (turn<0) turn = 3;\n  }\n\n  void move()\n  {\n    if (turn == 0)\n      this.i +=1;\n    else if (turn == 1)\n      this.j +=1;\n    else if (turn == 2)\n      this.i -=1;\n    else if (turn == 3)\n      this.j -=1;\n\n    if (this.i >= this.grid.resx) this.i=0;\n    else if (this.i < 0) this.i=this.grid.resx-1;\n    if (this.j >= this.grid.resy) this.j=0;\n    else if (this.j < 0) this.j=this.grid.resy-1;\n  }\n}\n"
  },
  {
    "path": "Forms/LangtonAnt/Grid.pde",
    "content": "class Grid\n{\n  int resx, resy;\n  int[] state;\n  float cellw, cellh;\n  \n  Grid(int resx, int resy)\n  {\n    this.resx = resx;\n    this.resy = resy;\n    this.state = new int[resx*resy];\n    this.cellw = float(width) / resx;\n    this.cellh = float(height) / resy;\n  }\n  \n  void setState(int i, int j, int state)\n  {\n    this.state[i+j*this.resx] = state;\n  }\n  \n  int getState(int i, int j)\n  {\n    return this.state[i+j*this.resx];\n  }\n\n  void draw()\n  {\n    pushStyle();\n    stroke(220);\n    float x=0.0, y=0.0;\n    for (int i=0; i<=this.resy; i++)\n    {\n       x = i*this.cellw;\n       line(x,0,x,height);\n    }\n    for (int i=0; i<=this.resy; i++)\n    {\n       y = i*this.cellh;\n       line(0,y,width,y);\n    }\n    popStyle();\n  }\n\n  void drawState()\n  {\n\n    pushStyle();\n    noStroke();\n    fill(0);\n    int i, j;\n    float x=0.0, y=0.0;\n    int c = 0;\n    for (j=0; j<this.resy; j++)\n    {\n      x = 0.0;\n      for (i=0; i<this.resx; i++)\n      {\n        c = this.state[i+j*this.resx];\n        if (c==1) \n          rect(x, y, cellw, cellh);\n        x+=this.cellw;\n      }\n      y+=this.cellh;\n    }\n    popStyle();\n  }\n}\n"
  },
  {
    "path": "Forms/LangtonAnt/LangtonAnt.pde",
    "content": "/*\n  LangtonAnt\n —\n An implementation of Langton's ant described here:\nhttps://en.wikipedia.org/wiki/Langton%27s_ant\n—\n Developped and tested on : \n - Processing 3.5.3 on Windows 10\n \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n */\n\nGrid grid; \nAnt ant;\nvoid setup()\n{\n  size(500,500); \n  grid = new Grid(80,80);\n  ant = new Ant(grid,40,40);\n}\n\nvoid draw()\n{\n  background(255);\n  ant.run();\n  grid.draw();\n  grid.drawState();\n}\n"
  },
  {
    "path": "Forms/LangtonAntMultiple/Ant.pde",
    "content": "class Ant\n{\n  Grid grid;\n  int i, j; // cell position on grid\n  int turn=0; // 0 -> 0, 1->90, 2->180, 3->270\n  Ant(Grid grid, int i, int j)\n  {\n    this.grid = grid;\n    this.i = i%this.grid.resx;\n    this.j = j%this.grid.resy;\n    this.turn=0;\n  }\n\n  void run()\n  {\n    //if (frameCount % 2 == 0)\n    {\n      // check the state of the grid\n      int c = this.grid.getState(this.i, this.j);\n      // White square\n      if (c == 0)\n      {\n        this.grid.setState(this.i, this.j, 1);\n        this.turn90CW();\n        this.move();\n      }\n      // Black square\n      else if (c == 1)\n      {\n        this.grid.setState(this.i, this.j, 0);\n        this.turn90CCW();\n        this.move();\n      }\n    }\n  }\n\n  void turn90CW()\n  {\n    turn = (turn+1)%4;\n  }\n\n  void turn90CCW()\n  {\n    turn = turn-1;\n    if (turn<0) turn = 3;\n  }\n\n  void move()\n  {\n    if (turn == 0)\n      this.i +=1;\n    else if (turn == 1)\n      this.j +=1;\n    else if (turn == 2)\n      this.i -=1;\n    else if (turn == 3)\n      this.j -=1;\n\n    if (this.i >= this.grid.resx) this.i=0;\n    else if (this.i < 0) this.i=this.grid.resx-1;\n    if (this.j >= this.grid.resy) this.j=0;\n    else if (this.j < 0) this.j=this.grid.resy-1;\n  }\n}\n"
  },
  {
    "path": "Forms/LangtonAntMultiple/Grid.pde",
    "content": "class Grid\n{\n  int resx, resy;\n  int[] state;\n  float cellw, cellh;\n  \n  Grid(int resx, int resy)\n  {\n    this.resx = resx;\n    this.resy = resy;\n    this.state = new int[resx*resy];\n    this.cellw = float(width) / resx;\n    this.cellh = float(height) / resy;\n  }\n  \n  void setState(int i, int j, int state)\n  {\n    this.state[i+j*this.resx] = state;\n  }\n  \n  int getState(int i, int j)\n  {\n    return this.state[i+j*this.resx];\n  }\n\n  void draw()\n  {\n    pushStyle();\n    stroke(220);\n    float x=0.0, y=0.0;\n    for (int i=0; i<=this.resy; i++)\n    {\n       x = i*this.cellw;\n       line(x,0,x,height);\n    }\n    for (int i=0; i<=this.resy; i++)\n    {\n       y = i*this.cellh;\n       line(0,y,width,y);\n    }\n    popStyle();\n  }\n\n  void drawState()\n  {\n\n    pushStyle();\n    noStroke();\n    fill(0);\n    int i, j;\n    float x=0.0, y=0.0;\n    int c = 0;\n    for (j=0; j<this.resy; j++)\n    {\n      x = 0.0;\n      for (i=0; i<this.resx; i++)\n      {\n        c = this.state[i+j*this.resx];\n        if (c==1) \n          rect(x, y, cellw, cellh);\n        x+=this.cellw;\n      }\n      y+=this.cellh;\n    }\n    popStyle();\n  }\n}\n"
  },
  {
    "path": "Forms/LangtonAntMultiple/LangtonAntMultiple.pde",
    "content": "/*\n  LangtonAntMultiple\n —\n An implementation of Langton's ant described here:\nhttps://en.wikipedia.org/wiki/Langton%27s_ant\n—\n Developped and tested on : \n - Processing 3.5.3 on Windows 10\n \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n */\n\nGrid grid; \nArrayList<Ant> ants = new ArrayList<Ant>();\nboolean bDrawGrid = false;\n\nvoid setup()\n{\n  size(500,500); \n  grid = new Grid(100,100);\n  addAnt(50,50);\n}\n\nvoid draw()\n{\n  background(255);\n  for (Ant ant : ants)\n    ant.run();\n  if (bDrawGrid)\n    grid.draw();\n  grid.drawState();\n}\n\nvoid mousePressed()\n{\n  addAnt(floor(mouseX/grid.cellw), floor(mouseY/grid.cellh));\n}\n\nvoid addAnt(int i, int j)\n{\n  ants.add( new Ant(grid,i,j) );\n}\n"
  },
  {
    "path": "Forms/Lorenz/Lorenz.pde",
    "content": "/*\n  Lorenz attractors\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.9.4)\n    \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n// ------------------------------------------------------------------------------------------------\nimport controlP5.*;\n\n// ------------------------------------------------------------------------------------------------\nPGraphics offscreen;\n\n// ------------------------------------------------------------------------------------------------\nfloat x=1.0, x1=0.0;\nfloat y=1.0, y1=0.0;\nfloat z=1.0, z1=0.0;\n\n// ------------------------------------------------------------------------------------------------\nfloat s = 5.0;\nfloat p = 15.0;\nfloat b = 1.0;\nfloat dt = 0.005;\nfloat scale = 6;\n\n// ------------------------------------------------------------------------------------------------\nControlP5 controls;\n\n// ------------------------------------------------------------------------------------------------\nvoid setup()\n{\n  size(800, 400, P3D);\n\n  controls = new ControlP5(this);\n  controls.begin(5,5);\n  controls.addSlider(\"s\", 1.0,30.0).linebreak();\n  controls.addSlider(\"p\", 1.0,30.0).linebreak();\n  controls.addSlider(\"b\", 1.0,30.0).linebreak();\n  controls.addSlider(\"scale\", 1.0,10.0).linebreak();\n  controls.addButton(\"reset\").setSize(30,14).linebreak();\n  controls.end();\n\n  offscreen = createGraphics(width, height,P3D);\n  reset();\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  drawOffscreen();\n  image(offscreen,0,0);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid clearOffscreen()\n{\n  offscreen.beginDraw();\n  offscreen.background(0);\n  offscreen.endDraw();\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid drawOffscreen()\n{\n  x1 = x + dt*s*(y-x);\n  y1 = y + dt*(p*x - y - x*z);\n  z1 = z + dt*(x*y - b*z);\n\n  offscreen.beginDraw();\n  offscreen.translate(width/2, height/2);\n  offscreen.stroke(255);\n  offscreen.line(scale*x1, scale*y1, scale*z1, scale*x, scale*y, scale*z);\n  offscreen.endDraw();\n\n  x = x1;\n  y = y1;\n  z = z1;\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid reset()\n{\n  x=random(-5,5); x1=0.0;\n  y=random(-5,5); y1=0.0;\n  z=random(-5,5); z1=0.0;\n\n  clearOffscreen();\n}\n\n"
  },
  {
    "path": "Forms/MazeGenerator/Maze.pde",
    "content": "class Maze\n{\n  // Maze structure\n  MazeCell[] cells;\n  int resx, resy, nbCells;\n\n  // Iteration variables\n  ArrayList<MazeCell> stack;\n  MazeCell cellCurrent;\n  int nbCellsVisited=0;\n  int cellStartx = 0, cellStarty = 0;\n  boolean computed = false;\n\n  // Step by step variables\n  boolean stepByStep = false;\n  float time = 0.0f;\n  float timeStep = 0.0015f;\n\n  // Solution\n  ArrayList<MazeCell> solution;\n\n  Maze(int resx, int resy)\n  {\n    this.resx = resx;\n    this.resy = resy;\n    this.nbCells = resx * resy;\n\n    resetCells();\n  }\n\n  void setCellStart(int x, int y)\n  {\n    if (x>=resx) x=0;\n    if (y>=resy) y=0;\n\n    this.cellStartx = x;\n    this.cellStarty = y;\n  }\n\n  void setTimeStepByStep(float t)\n  {\n    this.timeStep = t;\n  }\n\n  boolean isComputed()\n  {\n    return computed;\n  }\n\n  void resetCells()\n  {\n    this.cells = new MazeCell[nbCells];\n    int k=0;\n    for (int j=0; j<resy; j++)\n      for (int i=0; i<resx; i++)\n      {\n        this.cells[k++] = new MazeCell(i, j, this);\n      }\n    nbCells = resx*resy;\n    nbCellsVisited = 0;\n  }\n\n  MazeCell getCell(int x, int y)\n  {\n    if ((x>=0 && x<resx) && (y>=0 && y<resy)) \n      return this.cells[x+resx*y];\n    return null;\n  }\n\n  void setCellVisited(MazeCell c)\n  {\n    if (!c.visited)\n    {\n      c.visited = true;\n      nbCellsVisited++;\n    }\n  }\n\n  boolean hasCellNeightborUnvisited(MazeCell c)\n  {\n    MazeCell north = getCell(c.x, c.y-1);\n    if (north != null && !north.visited) return true;\n    MazeCell east = getCell(c.x+1, c.y);\n    if (east != null && !east.visited) return true;\n    MazeCell south = getCell(c.x, c.y+1);\n    if (south != null && !south.visited) return true;\n    MazeCell west = getCell(c.x-1, c.y);\n    if (west != null && !west.visited) return true;\n\n    return false;\n  }\n\n  int[][] dir = new int[][]\n    {\n    {0, 1}, \n    {0, -1}, \n    {1, 0}, \n    {-1, 0}\n  };\n  MazeCell findCellNeightborUnvisited(MazeCell c)\n  {\n    MazeCell n=null;\n    do\n    {\n      int rnd = (int) random(0, 3.99); // not sure about this\n\n      n = getCell(c.x+dir[rnd][0], c.y+dir[rnd][1]);\n    }\n    while (n==null || n.visited);\n    return n;\n  }\n\n  void removeCellsWalls(MazeCell cellCurrent, MazeCell cellNeighbor)\n  {\n    if (cellCurrent.x == cellNeighbor.x)\n    {\n      if (cellCurrent.y > cellNeighbor.y)\n      {\n        cellCurrent.hasNorth = false;\n        cellNeighbor.hasSouth = false;\n      } else\n      {\n        cellCurrent.hasSouth = false;\n        cellNeighbor.hasNorth = false;\n      }\n    } else if (cellCurrent.y == cellNeighbor.y)\n    {\n      if (cellCurrent.x > cellNeighbor.x)\n      {\n        cellCurrent.hasWest = false;\n        cellNeighbor.hasEast = false;\n      } else\n      {\n        cellCurrent.hasEast = false;\n        cellNeighbor.hasWest = false;\n      }\n    }\n  }\n\n  void reset()\n  {\n    resetCells();\n\n    cellCurrent = getCell(cellStartx, cellStarty);\n    setCellVisited(cellCurrent);\n\n    stack = new ArrayList<MazeCell>();\n  }\n\n  void compute()\n  {\n    reset();\n    stepByStep = false;\n    computed = false;\n\n    while (nbCellsVisited<nbCells)\n    {\n      step();\n    }\n    computed = true;\n  }\n\n  void beginComputeStepByStep()\n  {\n    time = millis();\n    reset();\n    stepByStep = true;\n  }\n\n  void computeStepByStep()\n  {\n    if (nbCellsVisited<nbCells)\n    {\n      float timeNow = millis();\n      if (timeNow - time >= timeStep*1000)\n      {\n        step();\n        time = timeNow;\n      }\n    } else\n      computed = true;\n  }\n\n\n  void step()\n  {\n    if (hasCellNeightborUnvisited(cellCurrent))\n    {\n      stack.add( cellCurrent );\n\n      MazeCell cellNeighbor = findCellNeightborUnvisited(cellCurrent);\n      removeCellsWalls(cellCurrent, cellNeighbor);\n\n      cellCurrent = cellNeighbor;\n      setCellVisited(cellCurrent);\n    } else\n    {\n      if (stack.size()>0)\n      {\n        cellCurrent = stack.remove( stack.size()-1 );\n      }\n    }\n  }\n\n  void draw()\n  {\n    for (int i=0; i<nbCells; i++)\n      this.cells[i].draw();\n  }\n\n  void findSolution(int cellStartx, int cellStarty, int cellEndx, int cellEndy)\n  {\n    if (isComputed())\n    {\n      solution = new ArrayList<MazeCell>();\n      MazeCell cellCurrent = getCell(cellStartx, cellStarty);\n      \n    }\n  }\n}\n\nclass MazeCell\n{\n  int x, y;\n  float w, h;\n  boolean hasNorth = true;\n  boolean hasEast = true;\n  boolean hasSouth = true;\n  boolean hasWest = true;\n  boolean visited = false;\n\n  Maze parent;\n\n  MazeCell(int x, int y, Maze parent)\n  {\n    this.x = x;\n    this.y = y;\n    this.parent = parent;\n    this.w = (float)width/(float)parent.resx;\n    this.h = (float)height/(float)parent.resy;\n  }\n\n  void draw()\n  {\n    float xx = (float)x;\n    float yy = (float)y;\n\n    float x1 = xx*w;\n    float x2 = (xx+1)*w;\n    float y1 = yy*h;\n    float y2 = (yy+1)*h;\n    if (x2>=width) x2=width-1;    \n    if (y2>=height) y2=height-1;    \n\n    if (visited && parent.stepByStep) {\n      pushStyle();\n      noStroke();\n      fill(200);\n      rectMode(CORNERS);\n      rect(x1, y1, x2, y2);\n      popStyle();\n    }\n    if (hasNorth) line(x1, y1, x2, y1);\n    if (hasEast) line(x2, y1, x2, y2);\n    if (hasSouth) line(x1, y2, x2, y2);\n    if (hasWest) line(x1, y1, x1, y2);\n  }\n}"
  },
  {
    "path": "Forms/MazeGenerator/MazeGenerator.pde",
    "content": "/*\n  MazeGenerator\n —\n An implementation of recursive backtracker algorithm described here:\n https://en.wikipedia.org/wiki/Maze_generation_algorithm\n —\n Developped and tested on : \n - Processing 3.0b4 on MacOSX (10.10.5)\n \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n */\n\nMaze maze;\n\nvoid setup()\n{\n  size(500, 500);\n  maze = new Maze(25, 25);\n  maze.setCellStart(0, 0);\n  //maze.compute();\n  maze.beginComputeStepByStep();\n}\n\nvoid draw()\n{\n  background(255);\n  stroke(0);\n  strokeWeight(1);\n  maze.computeStepByStep();\n  maze.draw();\n}\n\nvoid mousePressed()\n{\n  maze.compute();\n}\n\nvoid keyPressed()\n{\n  if (key == 'e')\n    saveFrame(\"maze.png\");\n}"
  },
  {
    "path": "Forms/Penrose/Penrose.pde",
    "content": "/*\n  Penrose\n  —\n  Based on explanations found here :\n  https://en.wikipedia.org/wiki/Penrose_tiling\n  http://preshing.com/20110831/penrose-tiling-explained/\n  —\n  Developped and tested on : \n    - Processing 3.2.1 on MacOSX (10.12.5)\n    \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n*/\n\n// ------------------------------------------------------------------------------------------------\nSun sun;\n\n// ------------------------------------------------------------------------------------------------\nvoid setup()\n{\n  size(500, 500,P2D);\n  sun = new Sun(7, 0.48*height);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  translate(width/2, height/2);\n\n  background(0);\n  noStroke();\n  sun.draw();\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == 's')\n    saveFrame(\"Penrose.png\");\n}\n"
  },
  {
    "path": "Forms/Penrose/Sun.pde",
    "content": "class Sun\n{\n  int nbTriangles = 10;\n  Triangle[] triangles = new Triangle[nbTriangles];\n\n\n  Sun(int subdivide, float r)\n  {\n    for (int i = 0; i < nbTriangles; i++)\n    {\n      float start = (2*i-1) * PI/nbTriangles;\n      float end = (2*i+1) * PI/nbTriangles;\n\n      PVector A = new PVector(0, 0);\n      PVector B = new PVector(r*cos(start), r*sin(start));\n      PVector C = new PVector(r*cos(end), r*sin(end));\n\n      triangles[i] = new Triangle(0, A, i%2 == 0 ? B : C, i%2 == 0 ? C : B);\n      triangles[i].subdivide(subdivide);\n    }\n  }\n\n  void draw()\n  {\n    for (int i = 0; i < nbTriangles; i++)\n      triangles[i].draw();\n  }\n}\n"
  },
  {
    "path": "Forms/Penrose/Triangle.pde",
    "content": "class Triangle\n{\n  final static float phi = 1.61803398875;\n\n  int type = 0;\n  int level = 0;\n\n  PVector A = new PVector();\n  PVector B = new PVector();\n  PVector C = new PVector();\n\n  Triangle[] children;\n\n\n  Triangle(int type, PVector A, PVector B, PVector C)\n  {\n    this.type = type;\n    this.level = 0;\n    this.A = A;\n    this.B = B;\n    this.C = C;\n  }\n\n  Triangle(int type, PVector A, PVector B, PVector C, int level)\n  {\n    this.type = type;\n    this.level = level;\n    this.A = A;\n    this.B = B;\n    this.C = C;\n  }\n\n  void draw()\n  {\n    if (children != null)\n    {\n      for (int i=0; i<children.length; i++)\n        children[i].draw();\n    } else\n    {\n      fill(type==0 ? 0 : 255);\n\n      beginShape(TRIANGLES);\n      vertex(A.x, A.y);\n      vertex(B.x, B.y);\n      vertex(C.x, C.y);\n      endShape();\n    }\n  }\n\n  void subdivide(int levelMax)\n  {\n    if (level == levelMax) return;\n\n    if (type == 0)\n    {\n      PVector P = new PVector(A.x + (B.x-A.x)/phi, A.y + (B.y-A.y)/phi);\n\n      children = new Triangle[2];\n      children[0] = new Triangle(0, C, P, B, level+1);\n      children[1] = new Triangle(1, P, C, A, level+1);\n    } else if (type == 1)\n    {\n      PVector Q = new PVector(B.x + (A.x-B.x)/phi, B.y + (A.y-B.y)/phi);\n      PVector R = new PVector(B.x + (C.x-B.x)/phi, B.y + (C.y-B.y)/phi);\n\n      children = new Triangle[3];\n      children[0] = new Triangle(1, R, C, A, level+1);\n      children[1] = new Triangle(1, Q, R, B, level+1);\n      children[2] = new Triangle(0, R, Q, A, level+1);\n    }\n\n    for (int i=0; i<children.length; i++)\n      children[i].subdivide(levelMax);\n  }\n}\n"
  },
  {
    "path": "Forms/RuttEtra/ImageSize.pde",
    "content": "class ImageResize\n{\n  PImage src;\n  PImage resized;\n  \n  ImageResize(PImage src, int divider)\n  {\n    this.resized = new PImage(src.width/divider, src.height/divider);\n    this.src = src;\n    println(\"ImageResize(\"+resized.width+\",\"+resized.height+\")\");\n  }\n  \n  void update()\n  {\n    resized.copy(src,0,0,src.width,src.height,0,0,resized.width,resized.height);\n  }\n  \n  PImage image()\n  {\n    return resized;\n  }\n  \n  int width()\n  {\n    return resized.width;\n  }\n\n  int height()\n  {\n    return resized.height;\n  }\n  \n};\n\n"
  },
  {
    "path": "Forms/RuttEtra/RuttEtra.pde",
    "content": "/*\n  RuttEtra\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.10.1)\n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n  —\n  Keyboard : \n   - '-' & '+' respectively decreases and increases blur level\n   - '1' to '6' : change draw mode \n*/\n\n// ------------------------------------------------------\nimport processing.video.*;\n\n// ------------------------------------------------------\nCapture video;\nRuttEtraizer re;\n\n// ------------------------------------------------------\nvoid setup()\n{\n  size(600, 600, P3D);\n  video = new Capture(this, 160, 120);\n  video.start();\n}\n\n// ------------------------------------------------------\nvoid draw()\n{\n  background(0);\n  stroke(255);\n  if (video.available())\n  {\n    video.read();\n\n    if (re == null)\n      re = new RuttEtraizer(video, 2);\n    if (re!=null)\n      re.apply();\n  }\n\n  if (re!=null)\n  {\n    pushMatrix();\n    translate(width/2, height/2, 300);\n    rotateX( map(mouseY,0,height,-PI,PI) );\n    rotateY( map(mouseX,0,width,-PI,PI) );\n    re.draw(this, 100);\n    popMatrix();\n    image(re.getImageResized(),0,0);\n  }\n}\n\n// ------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == '-') re.decreaseBlur();\n  if (key == '+') re.increaseBlur();\n  if (key >= '1' && key <='6') re.setDrawMode(key-'0');\n}\n\n"
  },
  {
    "path": "Forms/RuttEtra/RuttEtraizer.pde",
    "content": "class RuttEtraizer\n{\n  PGraphics imgSmall;\n  PImage imgRef;\n  int blurImgSmall = 1;\n  int drawMode = 1;\n  int s = 8;\n  float filterTh = 0.5;\n\n  // ------------------------------------------------------\n  // RuttEtra\n  // ------------------------------------------------------\n  RuttEtraizer(PImage img, int s)\n  {\n    imgRef = img;\n    setScale(s);\n    resizeImageSmall();\n  }\n\n  // ------------------------------------------------------\n  // setImgRef\n  // ------------------------------------------------------\n  void setImgRef(PImage img)\n  {\n    this.imgRef = img;\n    resizeImageSmall();    \n  }\n\n  // ------------------------------------------------------\n  // resizeImg\n  // ------------------------------------------------------\n  PImage getImageResized()\n  {\n    return imgSmall;\n  }\n\n  // ------------------------------------------------------\n  // setDrawMode\n  // ------------------------------------------------------\n  void setDrawMode(int i)\n  {\n    drawMode = i;\n  }\n\n  // ------------------------------------------------------\n  // setBlur\n  // ------------------------------------------------------\n  void setBlur(int b)\n  {\n    blurImgSmall = b;\n    blurImgSmall=constrain(blurImgSmall, 0, 10);\n  }\n\n  // ------------------------------------------------------\n  // increaseBlur\n  // ------------------------------------------------------\n  void increaseBlur()\n  {\n    setBlur(++blurImgSmall);\n  }\n\n  // ------------------------------------------------------\n  // decreaseBlur\n  // ------------------------------------------------------\n  void decreaseBlur()\n  {\n    setBlur(--blurImgSmall);\n  }\n\n  // ------------------------------------------------------\n  // setScale\n  // ------------------------------------------------------\n  void setScale(int s)\n  {\n    this.s = s;\n    this.s = constrain(s, 2, 8);\n    resizeImageSmall();\n  }\n\n\n  // ------------------------------------------------------\n  // apply\n  // ------------------------------------------------------\n  void apply()\n  {\n    imgSmall.beginDraw();\n    imgRef.filter(THRESHOLD, filterTh);\n    imgRef.filter(BLUR, blurImgSmall);\n    imgSmall.image(imgRef, 0, 0, imgSmall.width, imgSmall.height);\n    imgSmall.endDraw();\n  }\n\n  // ------------------------------------------------------\n  // resizeImageSmall\n  // ------------------------------------------------------\n  void resizeImageSmall()\n  {\n    imgSmall  = createGraphics(imgRef.width/s, imgRef.height/s);\n    apply();\n  }\n\n  // ------------------------------------------------------\n  // draw\n  // ------------------------------------------------------\n  void draw(PApplet applet, float h)\n  {\n    draw(applet.g, h);\n  }\n\n  // ------------------------------------------------------\n  // draw\n  // ------------------------------------------------------\n  void draw(PGraphics g, float h)\n  {\n    if (drawMode == 1)\n      drawLines(g,imgSmall, h);\n    else if (drawMode == 2)\n      drawPoints(g,imgSmall);\n    else if (drawMode == 3)\n      drawTriangles(g,imgSmall, h);\n    else if (drawMode == 4)\n      drawLines2(g,imgSmall, 280);\n    else if (drawMode == 5)\n    {\n      drawLines(g,imgSmall, h);\n      drawLines2(g,imgSmall, h);\n    }\n    else if (drawMode == 6)\n    {\n      drawMesh(g,imgSmall, h);\n      g.stroke(255,255);\n      g.pushMatrix();\n      g.translate(0,0,2);\n      drawLines(g, imgSmall, h);\n      g.popMatrix();\n    }\n  }\n\n\n  // ------------------------------------------------------\n  // drawPoints\n  // ------------------------------------------------------\n  void drawPoints(PGraphics g,PImage img)\n  {\n    int i, j, offset;\n    int w = img.width;\n    int h = img.height;\n    int gg = 0;\n\n    g.pushMatrix();\n    g.translate(-s*img.width/2, -s*img.height/2);\n    img.loadPixels();\n    for (j=0;j<h;j++)\n    {\n      for (i=0;i<w;i++)\n      {\n        offset = i+j*w;\n        gg = img.pixels[offset] & 0x000000FF;\n        g.point(i*s, j*s, float(gg)/255.0*100);\n      }\n    }\n    g.popMatrix();\n  }\n\n  // ------------------------------------------------------\n  // drawLines\n  // ------------------------------------------------------\n  void drawLines(PGraphics g,PImage img, float hh)\n  {\n    int i, j, offset1, offset2;\n    int w = img.width;\n    int h = img.height;\n    int p1, p2;\n    int r1, g1, b1;\n    int r2, g2, b2;\n    float i1, i2;\n\n    g.pushMatrix();\n    g.translate(-s*img.width/2, -s*img.height/2);\n    img.loadPixels();\n    for (j=0;j<h;j++)\n    {\n      for (i=0;i<w-1;i++)\n      {\n        offset1 = i+j*w;\n        offset2 = i+1+j*w;\n        p1 = img.pixels[offset1];\n        p2 = img.pixels[offset2];\n\n        r1 = p1 & 0x000000FF;\n        r2 = p2 & 0x000000FF;\n\n        i1 = float(r1)/(255.0);\n        i2 = float(r2)/(255.0);\n\n//        g.stroke( float(j)/float(h)*255 );\n        g.line(i*s, j*s, i1*hh, (i+1)*s, j*s, i2*hh);\n      }\n    }\n    g.popMatrix();\n  }\n\n  // ------------------------------------------------------\n  // drawLines2\n  // ------------------------------------------------------\n  void drawLines2(PGraphics g, PImage img, float hh)\n  {\n    int i, j, offset1, offset2;\n    int w = img.width;\n    int h = img.height;\n    int p1, p2;\n    int r1, g1, b1;\n    int r2, g2, b2;\n    float i1, i2;\n\n    g.pushMatrix();\n    g.translate(-s*img.width/2, -s*img.height/2);\n    img.loadPixels();\n    for (j=0;j<h-1;j++)\n    {\n      for (i=0;i<w;i++)\n      {\n        offset1 = i+j*w;\n        offset2 = i+(j+1)*w;\n        p1 = img.pixels[offset1];\n        p2 = img.pixels[offset2];\n\n        r1 = p1 & 0x000000FF;\n        r2 = p2 & 0x000000FF;\n\n        i1 = float(r1)/(255.0);\n        i2 = float(r2)/(255.0);\n\n        g.line(i*s, j*s, i1*hh, i*s, (j+1)*s, i2*hh);\n      }\n    }\n    g.popMatrix();\n  }\n\n\n  // ------------------------------------------------------\n  // drawTriangles\n  // ------------------------------------------------------\n  void drawTriangles(PGraphics g, PImage img, float hh)\n  {\n    int i, j, offset1, offset2;\n    int w = img.width;\n    int h = img.height;\n    int g1 = 0;\n    int g2 = 0;\n    float m =1.0;\n\n    g.pushMatrix();\n    g.translate(-s*img.width/2, -s*img.height/2);\n    img.loadPixels();\n    fill(0);\n    for (j=0;j<h;j++)\n    {\n      m = sin(float(j)/float(h)*PI);\n      g.beginShape();\n      for (i=0;i<w;i++)\n      {\n        offset1 = i+j*w;\n        g1 = img.pixels[offset1] & 0x000000FF;\n        g.vertex(i*s, j*s, m*float(g1)/255.0*hh);\n      }\n      g.endShape(CLOSE);\n    }\n    g.popMatrix();\n  }\n\n  // ------------------------------------------------------\n  // drawMesh\n  // ------------------------------------------------------\n  void drawMesh(PGraphics g, PImage img, float hh)\n  {\n    int i, j, offset1, offset2, offset3, offset4;\n    int w = img.width;\n    int h = img.height;\n    int g1 = 0;\n    int g2 = 0;\n    int g3 = 0;\n    int g4 = 0;\n    float m =1.0;\n\n    g.pushMatrix();\n    g.translate(-s*img.width/2, -s*img.height/2);\n    img.loadPixels();\n    g.fill(0);\n//    stroke(255);\n    g.noStroke();\n    for (j=0;j<h-1;j++)\n    {\n      m = 1;//sin(float(j)/float(h)*PI);\n      g.beginShape(QUAD_STRIP);\n      for (i=0;i<w;i++)\n      {\n        offset1 = i+j*w;\n        offset2 = i+(j+1)*w;\n        g1 = img.pixels[offset1] & 0x000000FF;\n        g2 = img.pixels[offset2] & 0x000000FF;\n        g.vertex(i*s, j*s, m*float(g1)/255.0*hh);\n        g.vertex(i*s, (j+1)*s, m*float(g2)/255.0*hh);\n      }\n      g.endShape();\n    }\n    g.popMatrix();\n  }\n  \n  // ------------------------------------------------------\n  // toMesh\n  // ------------------------------------------------------\n/*\n  TriangleMesh toMesh(float ground, float hMax)\n  {\n    Terrain terrain = new Terrain(imgSmall.width,imgSmall.height,1);\n    float[] elevation = new float[imgSmall.width*imgSmall.height];\n    imgSmall.loadPixels();\n    int offset=0;\n    for (int i=0;i<imgSmall.width;i++)\n      for (int j=0;j<imgSmall.height;j++)\n    {\n      offset = i+j*imgSmall.width;\n      elevation[offset] = float(imgSmall.pixels[offset] & 0x000000FF)/255.0f*hMax;\n    }\n    terrain.setElevation(elevation);\n    return (TriangleMesh)terrain.toMesh(ground);\n  }\n\n  // ------------------------------------------------------\n  // toMeshSTL\n  // ------------------------------------------------------\n  void toMeshSTL(String filename,float ground, float hMax)\n  {\n    toMesh(ground,hMax).saveAsSTL(sketchPath(timestamp()+\"_\"+filename+\".stl\")); \n  }\n*/\n\n}\n\n\n\n"
  },
  {
    "path": "Forms/Sunflower/Sunflower.pde",
    "content": "/*\n  Sunflower\n \n  —\n  Not sure where this code comes from.\n  \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n \n*/\n\n\nfloat r, x1, y1, golden=radians(180*(3-sqrt(5)));\n\nsize(500, 500);\nbackground(255);\nsmooth();\nnoStroke();\nfill(0);\nfor (int n=1; n<=520; n++) \n{\n  r = 5*sqrt(n);\n  x1 = width/2+2*r*cos(golden*n);\n  y1 = height/2+2*r*sin(golden*n);\n  ellipse(x1, y1, 10, 10);\n}\n\n// saveFrame(\"sunflower.jpg\");\n\n"
  },
  {
    "path": "Forms/Torus/Torus.pde",
    "content": "/*\n \n Torus Knot\n  \n —\n Julien @v3ga Gachadoat\n www.v3ga.net\n www.2roqs.com\n \n */\n\n// ----------------------------------------------------------------\nimport toxi.geom.*;\nimport toxi.geom.mesh.*;\nimport toxi.processing.*;\n\n// ----------------------------------------------------------------\nToxiclibsSupport gfx;\nTorusKnot knot;\n\n// ----------------------------------------------------------------\nvoid setup()\n{\n  size(800, 800,P3D);\n  gfx=new ToxiclibsSupport(this);\n  knot = new TorusKnot(140, 70, 4,5, 700, 50, 3); // global radius, inner radius, P,Q, res, res2 (around), render mode\n}\n\n// ----------------------------------------------------------------\nvoid draw()\n{\n  background(0);\n\n  translate(width/2, height/2);\n  rotateX( map(mouseY, 0, height, -PI, PI) );\n  rotateY( map(mouseX, 0, width, -PI, PI) );\n\n  fill(0);\n  noStroke();\n  gfx.mesh(knot);\n  noFill();\n  strokeWeight(2);\n  stroke(255);\n  scale(1.003);\n  knot.renderLines();\n}\n\n// ----------------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == 's')\n  {\n    saveFrame(\"Knot.png\"); \n  }\n}\n"
  },
  {
    "path": "Forms/Torus/TorusKnot.pde",
    "content": "// --------------------------------------------------------\n// TorusKnot code is dirty ... sorry.\nclass TorusKnot extends TriangleMesh\n{\n  public float R, P, Q;\n\n//  TriangleMesh mesh;\n\n  Vec3D points[][];\n  Vec3D normals[][];\n  ArrayList<TorusKnotLine> lines;\n\n  int res = 500;\n  int res2 = 60;\n  float r2 = 100.0;\n\n  int renderMode = 0;\n\n  // Constructor\n  TorusKnot(float R_, float R2_, float P_, float Q_, int res_, int res2_, int renderMode_)\n  {\n    R = R_;\n    r2 = R2_;\n    P = P_;\n    Q = Q_;\n    res = res_;\n    res2 = res2_;\n    renderMode = renderMode_;\n\n//    mesh = new TriangleMesh();\n    lines = new ArrayList<TorusKnotLine>();\n\n\n    PVector A, B;\n    float[] b;\n    Matrix4x4 transfo = new Matrix4x4();\n    Matrix4x4 basisM = new Matrix4x4();\n    float th  = 0.0;\n    float dth = 360.0/(res) ;\n\n    points = new Vec3D[res][res2];\n    normals = new Vec3D[res][res2];\n\n    for (int i=0; i<res; i++)\n    {\n      A = getPointAt(th);\n      b = getTangentBasis(th);\n\n      transfo.identity();\n      transfo.translateSelf(A.x, A.y, A.z);\n\n      basisM.set(\n        b[0], b[3], b[6], 0.0, \n        b[1], b[4], b[7], 0.0, \n        b[2], b[5], b[8], 0.0, \n        0.0, 0.0, 0.0, 1.0);\n\n      transfo.multiplySelf(basisM);\n\n\n      points[i] = new Vec3D[res2];      \n      normals[i] = new Vec3D[res2];\n\n      Vec3D A2 = new Vec3D(A.x, A.y, A.z);\n\n      float a = 0.0f;\n      for (int j=0; j<res2; j++)\n      {\n        points[i][j] = transfo.applyTo( new Vec3D( r2*cos(a), r2*sin(a), 0.0 ) );\n        normals[i][j] = points[i][j].sub(A2).normalize();\n\n        a+=TWO_PI/(res2);\n      }\n      th+=dth;\n    }\n\n    Vec3D n1 = new Vec3D(), n2 = new Vec3D();\n    Vec3D aa, bb, cc, dd;\n    for (int i=0; i<points.length; i++) {\n\n      for (int j=0; j<points[i].length; j++) {\n\n        n1 = ( points[i][(j+1)%res2].sub(points[i][j]) ).cross( points[(i+1)%res][j].sub(points[i][j]) );\n        n2 = ( points[(i+1)%res][(j+1)%res2].sub(points[i][(j+1)%res2]) ).cross( points[(i+1)%res][j].sub(points[(i+1)%res][(j+1)%res2]) );\n\n        n1 = n1.normalize();\n        n2 = n2.normalize();\n\n        aa = points[i][j];\n        bb = points[i][(j+1)%res2];\n        cc = points[(i+1)%res][(j+1)%res2];\n        dd = points[(i+1)%res][j];\n\n        addFace(aa, bb, dd, n1);\n        addFace(bb, cc, dd, n2);\n\n\n        if (renderMode == 0)\n        {\n          //          lines.add( new TorusKnotLine(aa,bb) );\n          lines.add( new TorusKnotLine(aa, cc) );\n        } else\n          if (renderMode == 1)\n          {\n            float rnd = random(1);\n            if (rnd<0.25) lines.add( new TorusKnotLine(aa, cc) );\n            else if (rnd < 0.5) lines.add( new TorusKnotLine(bb, dd) );\n          } else\n            if (renderMode == 2)\n            {\n              float rnd = random(1);\n              if (rnd<0.25)           lines.add( new TorusKnotLine(aa, bb) );\n              else if (rnd < 0.5)     lines.add( new TorusKnotLine(aa, dd) );\n              else if (rnd < 0.75)    lines.add( new TorusKnotLine(dd, cc) );\n              else                    lines.add( new TorusKnotLine(cc, bb) );\n            }\n        if (renderMode == 3)\n        {\n          lines.add( new TorusKnotLine(aa, bb) );\n        }\n      }\n    }\n\n    computeVertexNormals();\n  }\n\n\n  // Methods\n  void renderLines()\n  {\n    for (TorusKnotLine l : lines)\n      line(l.A.x, l.A.y, l.A.z, l.B.x, l.B.y, l.B.z);\n  }\n\n  PVector getPointAt(float th)\n  {\n    PVector p = new PVector();\n    float   rA\t= 0.5*(2.0+sin(radians(Q*th)));\n    p.x\t= R*rA*cos(radians(P*th));\n    p.y\t= R*rA*cos(radians(Q*th));\n    p.z\t= R*rA*sin(radians(P*th));\n\n    return p;\n  }\n\n  PVector getTangentAt(float th)\n  {\n    float dth = 360.0 / 10000.0f;\n\n    PVector A = this.getPointAt(th);\n    PVector B = this.getPointAt(th+dth);\n    PVector T = new PVector(B.x - A.x, B.y - A.y, B.z - A.z);\n\n    T.normalize();\n\n    return T;\n  }\n\n  float[] getTangentBasis(float th)\n  {\n    float[] b = new float[9];\n    float dth = 360.0/10000.0;\n\n    PVector T  = new PVector();\n    PVector N  = new PVector();\n    PVector B_ = new PVector();\n\n    PVector A = getPointAt(th);\n    PVector B = getPointAt(th+dth);\n\n    T.set(B.x - A.x, B.y - A.y, B.z - A.z);\n    N.set(B.x + A.x, B.y + A.y, B.z + A.z);\n\n    B_ = T.cross(N);\n    N  = B_.cross(T);\n\n    N.normalize();\n    B_.normalize();\n    T.normalize();\n\n    b[0] = N.x ; \n    b[1] = N.y ; \n    b[2] = N.z ; \n\n    b[3] = B_.x ; \n    b[4] = B_.y ; \n    b[5] = B_.z ; \n\n    b[6] = T.x ;\n    b[7] = T.y ;\n    b[8] = T.z ;\n\n    return b;\n  }\n};\n\nclass TorusKnotLine\n{\n  Vec3D A, B;\n\n  TorusKnotLine(Vec3D A_, Vec3D B_)\n  {\n    A = A_;\n    B = B_;\n  }\n}\n"
  },
  {
    "path": "Forms/Turmites/Rules.pde",
    "content": "int[][] TurmiteTurn = \n{\n  // 0 (//)\n  {-1,-1,-1,-1},\n  // 1 (No turn)\n  { 0, 1, 2, 3},\n  // 2  (Right)\n  { 1, 2, 3, 0},\n  // 3  (//)\n  {-1,-1,-1,-1},\n  // 4  (U-turn)\n  { 2, 3, 0, 1},\n  // 5  (//)\n  {-1,-1,-1,-1},\n  // 6  (//)\n  {-1,-1,-1,-1},\n  // 7  (//)\n  {-1,-1,-1,-1},\n  // 8  (Left)\n  { 3, 0, 1, 2}\n};\n\n// I know.\nint[][][][] r  = \n{\n{{{1, 2, 0}, {0, 8, 0}}},  // 1: Langton's ant\n{{{1, 2, 0}, {0, 1, 0}}},  // 2: binary counter\n{{{0, 8, 1}, {1, 2, 1}}, {{1, 1, 0}, {1, 1, 1}}}, // 3: (filled triangle)\n{{{0, 1, 1}, {0, 8, 1}}, {{1, 2, 0}, {0, 1, 1}}}, // 4: spiral in a box\n{{{0, 2, 1}, {0, 8, 0}}, {{1, 8, 1}, {0, 2, 0}}}, // 5: stripe-filled spiral\n{{{0, 2, 1}, {0, 8, 0}}, {{1, 8, 1}, {1, 1, 0}}}, // 6: stepped pyramid\n{{{0, 2, 1}, {0, 1, 1}}, {{1, 2, 1}, {1, 8, 0}}}, // 7: contoured island\n{{{0, 2, 1}, {0, 2, 1}}, {{1, 1, 0}, {0, 2, 1}}}, // 8: woven placemat\n{{{0, 2, 1}, {1, 2, 1}}, {{1, 8, 1}, {1, 8, 0}}}, // 9: snowflake-ish\n{{{1, 8, 0}, {0, 1, 1}}, {{0, 8, 0}, {0, 8, 1}}}, // 10: slow city builder\n{{{1, 8, 0}, {1, 2, 1}}, {{0, 2, 0}, {0, 8, 1}}}, // 11: framed computer art\n{{{1, 8, 0}, {1, 2, 1}}, {{0, 2, 1}, {1, 8, 0}}}, // 12: balloon bursting (makes a spreading highway) \n{{{1, 8, 1}, {0, 8, 0}}, {{1, 1, 0}, {0, 1, 0}}}, // 13: makes a horizontal highway\n{{{1, 8, 1}, {0, 8, 0}}, {{1, 2, 1}, {1, 2, 0}}}, // 14: makes a 45 degree highway\n{{{1, 8, 1}, {0, 8, 1}}, {{1, 2, 1}, {0, 8, 0}}}, // 15: makes a 45 degree highway\n{{{1, 8, 1}, {0, 1, 0}}, {{1, 1, 0}, {1, 2, 0}}}, // 16: spiral in a filled box\n{{{1, 8, 1}, {0, 2, 0}}, {{0, 8, 0}, {0, 8, 0}}}, // 17: glaciers\n{{{1, 8, 1}, {1, 8, 1}}, {{1, 2, 1}, {0, 1, 0}}}, // 18: golden rectangle!\n{{{1, 8, 1}, {1, 2, 0}}, {{0, 8, 0}, {0, 8, 0}}}, // 19: fizzy spill\n{{{1, 8, 1}, {1, 2, 1}}, {{1, 1, 0}, {0, 1, 1}}}, // 20: nested cabinets\n{{{1, 1, 1}, {0, 8, 1}}, {{1, 2, 0}, {1, 1, 1}}}, // 21: (cross)\n{{{1, 1, 1}, {0, 1, 0}}, {{0, 2, 0}, {1, 8, 0}}}, // 22: saw-tipped growth\n{{{1, 1, 1}, {0, 1, 1}}, {{1, 2, 1}, {0, 1, 0}}}, // 23: curves in blocks growth\n{{{1, 1, 1}, {0, 2, 0}}, {{0, 8, 0}, {0, 8, 0}}}, // 24: textured growth\n{{{1, 1, 1}, {0, 2, 1}}, {{1, 8, 0}, {1, 2, 0}}}, // 25: (diamond growth)\n{{{1, 1, 1}, {1, 8, 0}}, {{1, 2, 1}, {0, 1, 0}}}, // 26: coiled rope\n{{{1, 2, 0}, {0, 8, 1}}, {{1, 8, 0}, {0, 1, 1}}}, // 27: (growth)\n{{{1, 2, 0}, {0, 8, 1}}, {{1, 8, 0}, {0, 2, 1}}}, // 28: (square spiral)\n{{{1, 2, 0}, {1, 2, 1}}, {{0, 1, 0}, {0, 1, 1}}}, // 29: loopy growth with holes\n{{{1, 2, 1}, {0, 8, 1}}, {{1, 1, 0}, {0, 1, 0}}}, // 30: Lanton's Ant drawn with squares\n{{{1, 2, 1}, {0, 2, 0}}, {{0, 8, 1}, {1, 8, 0}}}, // 31: growth with curves and blocks\n{{{1, 2, 1}, {0, 2, 0}}, {{0, 1, 0}, {1, 2, 1}}}, // 32: distracted spiral builder\n{{{1, 2, 1}, {0, 2, 1}}, {{1, 1, 0}, {1, 1, 1}}}, // 33: cauliflower stalk (45 deg highway)\n{{{1, 2, 1}, {1, 8, 1}}, {{1, 2, 1}, {0, 2, 0}}}, // 34: worm trails (eventually turns cyclic!)\n{{{1, 2, 1}, {1, 1, 0}}, {{1, 1, 0}, {0, 1, 1}}}, // 35: eventually makes a two-way highway!\n{{{1, 2, 1}, {1, 2, 0}}, {{0, 1, 0}, {0, 1, 0}}}, // 36: almost symmetric mould bloom\n{{{1, 2, 1}, {1, 2, 0}}, {{0, 2, 0}, {1, 1, 1}}}, // 37: makes a 1 in 2 gradient highway\n{{{1, 2, 1}, {1, 2, 1}}, {{1, 8, 1}, {0, 2, 0}}}, // 38: immediately makes a 1 in 3 highway\n{{{0, 2, 1}, {1, 2, 1}}, {{0, 8, 2}, {0, 8, 0}}, {{1, 2, 2}, {1, 8, 0}}}, // 39: squares and diagonals growth\n{{{1, 8, 1}, {0, 1, 0}}, {{0, 2, 2}, {1, 8, 0}}, {{1, 2, 1}, {1, 1, 0}}}, // 40: streak at approx. an 8.1 in 1 gradient\n{{{1, 8, 1}, {0, 1, 2}}, {{0, 2, 2}, {1, 1, 1}}, {{1, 2, 1}, {1, 1, 0}}}, // 41: streak at approx. a 1.14 in 1 gradient\n{{{1, 8, 1}, {1, 8, 1}}, {{1, 1, 0}, {0, 1, 2}}, {{0, 8, 1}, {1, 1, 1}}}, // 42: maze-like growth\n{{{1, 8, 2}, {0, 2, 0}}, {{1, 8, 0}, {0, 2, 0}}, {{0, 8, 0}, {0, 8, 1}}}, // 43: growth by cornices \n{{{1, 2, 0}, {0, 2, 2}}, {{0, 8, 0}, {0, 2, 0}}, {{0, 1, 1}, {1, 8, 0}}}, // 44: makes a 1 in 7 highway\n{{{1, 2, 1}, {0, 8, 0}}, {{1, 2, 2}, {0, 1, 0}}, {{1, 8, 0}, {0, 8, 0}}} // 45: makes a 4 in 1 highway\n};\n"
  },
  {
    "path": "Forms/Turmites/Turmite.pde",
    "content": "class Turmite\n{\n  PImage grid;\n  int offset;\n  int x, y;\n  int state = 0;\n  int direction = 0;\n  int ruleIndex=0;\n  int iteration=0;\n\n  Turmite(PImage grid, int ruleIndex)\n  {\n    this.grid = grid;\n    setRule(ruleIndex);\n    reset();\n  }\n  \n  void reset()\n  {\n    grid.loadPixels();\n    for (int i=0;i<grid.pixels.length;i++) grid.pixels[i] = color(255);\n    grid.updatePixels();\n    \n    this.state = 0;\n    this.x = this.grid.width/2;\n    this.y = this.grid.height/2;\n  }\n  \n  void setRule(int which)\n  {\n    if (which >= r.length) which = 0;\n    this.ruleIndex = which;\n  }\n\n  boolean color0(color c)\n  {\n    return (red(c) == 255);\n  }\n\n  boolean color1(color c)\n  {\n    return (red(c) == 0);\n  }\n  \n  int colorIndex(color pixel)\n  {\n    if (color0(pixel)) return 0;\n    if (color1(pixel)) return 1;\n    return -1;\n  }\n  \n  void colorCell(int colorIndex)\n  {\n    offset = this.x + grid.width*this.y;\n    grid.pixels[offset] = color(colorIndex == 0 ? 255 : 0);  \n  }\n  \n  void turn(int which)\n  {\n    this.direction = TurmiteTurn[which][direction];\n  }\n\n  void state_(int which)\n  {\n    this.state = which;\n  }\n  \n  void move()\n  {\n    switch(direction)\n    {\n    case 0:\n      y = y-1;\n      if (y<0) y=grid.height-1;\n      break;\n    case 1:\n      x = (x+1)%grid.width;\n      break;\n    case 2:\n      y = (y+1)%grid.height;\n      break;\n    case 3:\n      x = x-1;\n      if (x<0) x=grid.width-1;\n      break;\n    }\n\n  }\n\n  void run()\n  {\n    grid.loadPixels(); \n    color pixel = grid.get(x, y);\n\n    // Rule\n    int c = colorIndex(pixel);\n    if (c>=0)\n    {\n      int[] next = r[ruleIndex][state][c];\n      int nextColorIndex = next[0];\n      int nextTurn = next[1];\n      int nextState = next[2];\n\n      // Action\n      colorCell(nextColorIndex);\n      turn(nextTurn);\n      state_(nextState);\n\n      // Move\n      move();\n    \n      // Iteration\n      iteration++;\n    }\n\n    grid.updatePixels();\n  }\n}\n"
  },
  {
    "path": "Forms/Turmites/Turmites.pde",
    "content": "/*\n  Turmites\n\n  —\n  Based on :\n    - http://en.wikipedia.org/wiki/Turmite\n    - can't remember where I grabbed the table in Rules tab though ...\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.9.2)\n\n  —\n  Instructions : \n    - click to generate new turmite.\n      \n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n\n// ------------------------------------------------------------------------------------------------\nPImage grid;\nTurmite turmite;\nint div = 20;\nint ruleIndex = 0;\n\n// ------------------------------------------------------------------------------------------------\nvoid setup()\n{\n  size(800, 800, P2D);\n  grid = createImage(width/div, height/div, RGB);\n  turmite = new Turmite(grid, 0);\n  setWindowTitle();\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid draw()\n{\n  turmite.run();\n\n  background(255);\n  fill(0);\n  grid.loadPixels();\t\n  int i, j, off;\n  int x, y;\n  color c;\n  stroke(0);\n  fill(0);\n  noStroke();\n  rectMode(CENTER);\n\n  for (i=0;i<grid.width;i++)\n  {\n    x = div*i+div/2;\n    for (j=0;j<grid.height;j++)\n    {\n      y = div*j+div/2;\n      if ( red( grid.pixels[i+grid.width*j] ) == 0) {\n        rect(x, y, div, div);\n      }\n    }\n  }\n  grid.updatePixels();\n  filter(INVERT);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid mousePressed()\n{\n  ruleIndex = (ruleIndex+1)%r.length;\n  turmite.reset();\n  turmite.setRule(ruleIndex);\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid keyPressed()\n{\n  if (key == CODED) \n  {\t\n    if (keyCode == RIGHT) { \n      ruleIndex = (ruleIndex+1)%r.length;\n    }\n    if (keyCode == LEFT) { \n      ruleIndex = ruleIndex-1;\n      if (ruleIndex<0) ruleIndex = r.length-1;\n    }\n\n    turmite.reset();\n    turmite.setRule(ruleIndex);\n    setWindowTitle();\n  }\n  else\n  if (key == 's')\n  {\n    saveFrame(\"Turmites.png\");\n  }\n}\n\n// ------------------------------------------------------------------------------------------------\nvoid setWindowTitle()\n{\n  frame.setTitle(\"Turmites - rule \"+ruleIndex);\n}\n"
  },
  {
    "path": "Image/CameraPropagation/CameraPropagation.pde",
    "content": "/*\n  CameraPropagation\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.10.2)\n\n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n// ------------------------------------------------------\nimport processing.video.*;\n\n// ------------------------------------------------------\nCapture camera;\n\n// ------------------------------------------------------\nint nbColumns = 10;\nint nbRows = 10;\n\n// ------------------------------------------------------\nint wImage = 0;\nint hImage = 0;\n\n// ------------------------------------------------------\nPImage[] images;\nint indexImageCurrent = 0;\n\n\n// ------------------------------------------------------\nvoid setup()\n{\n  size(1024, 768);\n  wImage = width / nbColumns;\n  hImage = height / nbRows;\n\n  images = new PImage[nbColumns*nbRows];\n  for (int i=0; i<images.length ; i++)\n  {\n    images[i] = createImage(wImage, hImage, RGB);\n  }\n  \n  camera = new Capture(this, 320, 180, 30); // largeur, hauteur, nombre images par seconde\n  camera.start();\n}\n\n// ------------------------------------------\nvoid draw()\n{\n  if (camera.available() == true)\n  {\n    camera.read();\n    \n    images[indexImageCurrent].copy(camera, 0, 0, 320, 180, 0, 0, wImage, hImage);\n    indexImageCurrent = indexImageCurrent+1; \n    if (indexImageCurrent > images.length-1)\n    {\n      indexImageCurrent=0;\n    }\n  }\n\n  // Dessin de notre grille d'images\n  // (Identique à ce que l'on a fait sur le dessin de «patterns»)\n  for (int j=0; j<nbRows ; j++)\n  {\n    for (int i=0;i<nbColumns; i++)\n    {\n      // dessin de l'image\n      int indexImageLoop = (indexImageCurrent+(i+j*nbColumns))%images.length;\n      image( images[indexImageLoop],  i*wImage, j*hImage, wImage, hImage);\n    }\n  }\n\n}\n\n"
  },
  {
    "path": "Image/CameraSlitScanVertical/CameraSlitScanVertical.pde",
    "content": "/*\n  OmbroCinema\n\n  —\n  Developped and tested on : \n    - Processing 2.1.1 on MacOSX (10.10.2)\n\n  —\n  Julien @v3ga Gachadoat\n  www.v3ga.net\n  www.2roqs.com\n\n*/\n\n// ------------------------------------------------------\nimport processing.video.*;\n\n// ------------------------------------------------------\nCapture camera;\n\n// ------------------------------------------------------\nint wImage = 0;\nint hImage = 0;\n\n// ------------------------------------------------------\nPImage[] images;\n\n// ------------------------------------------------------\nint indexImageCurrent = 0;\n\n// ------------------------------------------------------\nvoid setup()\n{\n  size(320, 180);\n\n  wImage = width;\n  hImage = height;\n\n  images = new PImage[hImage];\n  for (int i=0; i<images.length ; i++)\n  {\n    images[i] = createImage(wImage, hImage, RGB);\n  }\n\n  camera = new Capture(this, wImage, hImage, 30);\n  camera.start();\n}\n\n// ------------------------------------------------------\nvoid draw()\n{\n  if (camera.available() == true)\n  {\n    camera.read();\n\n    images[indexImageCurrent].copy(camera, 0, 0, wImage, hImage, 0, 0, wImage, hImage);\n\n    // Pour chaque ligne, on copie une ligne d'une image sauvegardée ...!\n    int indexImage = indexImageCurrent;\n    for (int y=0;y<hImage;y++)\n    {\n      copy(images[indexImage], 0, y, wImage, 1, 0, y, wImage, 1);     \n      indexImage = (indexImage+1)%hImage;\n    }\n\n\n    indexImageCurrent = (indexImageCurrent+1)%images.length; \n  }\n}\n\n// ------------------------------------------\nvoid mousePressed()\n{\n  saveFrame(\"slitscan.png\");\n}"
  },
  {
    "path": "README.md",
    "content": "Processing\n==========\nA collection of sketches using various libraries I use during courses.  \n\n## Forms\n* **Chladni plate interference surfaces**\n* **L_System**\n* **Turmites** - according to wikipedia, a turmite is a Turing machine which has an orientation as well as a current state and a \"tape\" that consists of an infinite two-dimensional grid of cells.\n* **Sunflower**\n* **Torus** - made with Processing 1.5.1.\n* **RuttEtra**\n* **MazeGenerator** - using recursive backtracker algorithm.\n* **Circles**\n* **HilbertCurve**\n* **Penrose**\n* **Langton ant**\n* **Cellular automaton with rule 30 and 110**\n\n\n![Chladni](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Chandli-250.png)\n![L_System](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/L_system-250.png)\n![Turmites](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Turmites-250.png)\n![Sunflower](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Sunflower-250.png)\n![Torus](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Torus-250.png)\n![RuttEtra](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/RuttEtra-250.png)\n![Maze](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Maze-250.png)\n![Circles recursion](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Circles_recursion-250.png)\n![Hilbert curve](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/HilbertCurve-250.png)\n![Penrose](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Penrose-250.png)\n![LangtonAnt](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/LangtonAntMultiple-250.png)\n![Rule110](http://v3ga.github.io/Images/Processing/Forms/Thumbnails/Rule110-250.png)\n\n## Animation\n* **OmbroCinema**\n![OmbroCinema](http://v3ga.github.io/Images/Processing/Animation/Thumbnails/OmbroCinema-250.png)\n"
  }
]