{"id":72,"date":"2015-11-20T19:38:26","date_gmt":"2015-11-20T19:38:26","guid":{"rendered":"http:\/\/joseecarrier.ca\/en\/?post_type=jetpack-portfolio&#038;p=72"},"modified":"2015-11-30T16:07:48","modified_gmt":"2015-11-30T16:07:48","slug":"succulents","status":"publish","type":"jetpack-portfolio","link":"https:\/\/joseecarrier.ca\/en\/portfolio\/succulents\/","title":{"rendered":"Succulents"},"content":{"rendered":"<!DOCTYPE html PUBLIC \"-\/\/W3C\/\/DTD HTML 4.0 Transitional\/\/EN\" \"http:\/\/www.w3.org\/TR\/REC-html40\/loose.dtd\">\n<html><body><p>I love how mathematics can be used to represent phenomenons that we can observe in nature. And when you combined this with programming you can create beautiful patterns. For this project, I was inspired by succulents and the arrangements that the leaves form when they grow, this is referred as <a href=\"https:\/\/en.wikipedia.org\/wiki\/Phyllotaxis\" target=\"_blank\">phyllotaxis<\/a>. This pattern can be represented using a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Logarithmic_spiral\" target=\"_blank\">spiral<\/a> and the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Golden_angle\" target=\"_blank\">golden angle<\/a>. I made a <a href=\"http:\/\/processing.org\/\" target=\"_blank\">Processing<\/a>&nbsp;script (<a href=\"http:\/\/p5js.org\/\" target=\"_blank\">p5js<\/a>) based on this. Multiples succulents are generated by the script. Their layout and size are computed&nbsp;using an algorithm used to randomly fill space (based on the work by <a href=\"http:\/\/paulbourke.net\/texture_colour\/randomtile\/\" target=\"_blank\">Paul Bourke<\/a> and <a href=\"http:\/\/john-art.com\/\" target=\"_blank\">John Shier<\/a>).<\/p>\n<p>Here is one example of the&nbsp;images generated.<br>\n<img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-75\" src=\"http:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/succulents.png\" alt=\"succulents\" width=\"880\" height=\"660\" srcset=\"https:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/succulents.png 880w, https:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/succulents-300x225.png 300w, https:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/succulents-840x630.png 840w, https:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/succulents-480x360.png 480w\" sizes=\"auto, (max-width: 880px) 100vw, 880px\" \/><\/p>\n<p style=\"text-align: left;\">And here is a sketch with which you can interact: move your mouse over it and the succulents will grow!<\/p>\n<p style=\"text-align: center;\"><a style=\"display:none\" class=\"p5_sketch_link\" href=\"http:\/\/joseecarrier.ca\/en\/wp-content\/uploads\/sites\/3\/2015\/11\/sketch.js\" data-height=\"660\" data-width=\"880\" data-nocode=\"true\">sketch<\/a><iframe loading=\"lazy\" src=\"https:\/\/joseecarrier.ca\/en\/wp-content\/plugins\/p5-embedder\/p5_iframe.html\" class=\"p5_exampleFrame\" width=\"880\" height=\"660\"><\/iframe><pre class=\"language-javascript\" style=\"display:none\"><code class=\"p5_editor language-javascript\">var sketch = function (p) {\r\n\r\n  \/\/ parameters for the function used to locate all succulents\r\n  var circles = [];\r\n  var maxRadius = 125;\r\n  var minRadius = 35.0;\r\n  var gap = 0;\r\n  var c = 1.15; \/\/ must be larger than 1\r\n  var n = 12;\r\n  var a0;\r\n  var numIter;\r\n\r\n  spirals = [];\r\n\r\n  \/\/ parameters for the spirals (succulents)\r\n  var petals = 0; \/\/ 0: convexe, 1: concave\r\n  var z = 1.015;\r\n  \/\/ stroke weight: initial and stroke factor\r\n  var s0 = 0.1;\r\n  var sf = 0.02;\r\n  \/\/ stroke color the radius is a ratio of final radiux\r\n  var rcol1 = 0.2;\r\n  var rcol2 = 0.8;\r\n  var init = 0;\r\n\r\n\r\n\r\n\r\n  p.setup = function () {\r\n    p.createCanvas(880, 660);\r\n\r\n    p.background('#ffffff');\r\n\r\n\r\n    \/\/ parameters for the function used to locate all succulents\r\n    \/\/ initial area to have a1 have maxRadius,  a1= a0*pow(n+1,-c)\r\n    a0 = p.PI*p.sq(maxRadius)\/p.pow(n+1,-c);\r\n\r\n    \/\/ compute the location of all succulents\r\n    \/\/ num of iterations to have last circles radius minRadius\r\n    \/\/ reference: Paul Bourke: http:\/\/paulbourke.net\/texture_colour\/randomtile\/\r\n    numIter = parseInt(p.pow(a0\/(p.PI*p.sq(minRadius)), 1\/c))-n;\r\n    for (var i = 1; i &lt;= numIter; i++) {\r\n      var an = a0*p.pow(n+i,-c);\r\n      var prad = p.sqrt(an\/p.PI);\r\n      var px = 0;\r\n      var py = 0;\r\n\r\n\r\n      var tries = 0;\r\n      var found = false;\r\n      while (!found & tries < 1000 ) {\r\n        px = p.random(p.width);\r\n        py = p.random(p.height);\r\n        \/\/ check that it is not overlapping previous circle\r\n        if (!Overlapping(px, py, prad)) {\r\n          found = true;     \r\n        }\r\n        tries++;\r\n      }\r\n      if (found) {\r\n        circles.push(new HCircle(px, py, prad));\r\n      }\r\n    }\r\n\r\n\r\n    \/\/ for all the locations, calculate the parameters of the spiral for the succulents\r\n    for (var i=0; i&lt;circles.length; i++) {\r\n      spirals.push(new HSpiral(circles[i]));\r\n    }\r\n\r\n  }\r\n\r\n  p.draw = function () {\r\n\r\n    for (var i=0; i&lt;circles.length; i++) {\r\n      var s = spirals[i];\r\n      s.draw();\r\n    }\r\n    init = 1;\r\n  }\r\n\r\n  p.mouseMoved = function () {\r\n    if (init==1) {\r\n      \/\/ find if mouse on a succulent, if so make it grow\r\n      for (var i=0; i&lt;circles.length; i++) {\r\n        var c = circles[i];\r\n        if (Overlap(c.x, c.y, c.rad, p.mouseX, p.mouseY, 0.0)) {\r\n\r\n          spirals[i].grow();\r\n          \r\n          \/\/ can only be overlapping one circle\r\n          break;\r\n        }\r\n      }\r\n    }\r\n  }\r\n\r\n  \/\/ Separated(), from Paul Bourke: http:\/\/paulbourke.net\/texture_colour\/randomtile\/\r\n  function Overlapping(px, py, prad)\r\n  {\r\n    for (var i=0; i&lt;circles.length; i++) {\r\n      var c = circles[i];\r\n       if (Overlap(c.x, c.y, c.rad, px, py, prad)) {\r\n        return true;    \r\n       }\r\n    }\r\n    return false;\r\n  }\r\n\r\n  function Overlap(c1x, c1y, c1rad, c2x, c2y, c2rad) {\r\n    var dx,dy;\r\n\r\n    dx = c1x - c2x;\r\n    dy = c1y - c2y;\r\n    \r\n     \/\/ adding a gap so they don't touch each other\r\n    var radiusSum =  c1rad + c2rad + gap;\r\n    var centreDistanceSquared = dx*dx + dy*dy;\r\n\r\n     \/\/ circles overlapping if  distance between center less than sum of the two radii\r\n     if (centreDistanceSquared &lt; radiusSum*radiusSum) {\r\n      return true;    \r\n     }\r\n\r\n     return false;\r\n  }\r\n\r\n\r\n\r\n\r\n  function HCircle(x, y, rad) {\r\n    this.x = x;\r\n    this.y = y;\r\n    this.rad = rad;\r\n  }\r\n\r\n  function HSpiral(circle) {\r\n    this.r0 = p.random(5, 10);\r\n    this.cx = circle.x;\r\n    this.cy = circle.y;\r\n    this.radius = circle.rad;\r\n    \r\n    this.nvertex = parseInt(p.log(this.radius\/this.r0)\/p.log(z));\r\n    var min_nvertex = parseInt(p.log(minRadius\/this.r0)\/p.log(z));\r\n\r\n    this.ncurrent = 0;\r\n    this.nstep = parseInt(p.random(20,50));\r\n    if (this.nstep &lt; min_nvertex) {\r\n      this.nstep = min_nvertex;\r\n    } else if (this.nstep &gt; this.nvertex) {\r\n      this.nstep = this.nvertex;\r\n    }\r\n\r\n\r\n    var golden_angle = p.PI*(3- p.sqrt(5));         \/\/ golden angle\r\n    var theta = p.radians(p.random(0, 45));   \/\/random rotation of the succulent\r\n\r\n    this.xn = [];\r\n    this.yn = [];\r\n    this.rn = [];\r\n\r\n    for (var i = 0; i &lt; this.nvertex; i++) {\r\n      var angle = (i*golden_angle + theta)%p.TWO_PI;\r\n      this.rn[i] = this.r0*p.pow(z,i); \/\/ spiral lattice\r\n      this.xn[i] = this.cx + p.cos(angle) * this.rn[i];\r\n      this.yn[i] = this.cy + p.sin(angle) * this.rn[i];\r\n    }\r\n\r\n  }\r\n\r\n  HSpiral.prototype.draw = function() {\r\n\r\n    for (var i = this.ncurrent; i &lt; this.nstep; i++) {\r\n      p.noFill();\r\n      p.strokeWeight(sf*this.rn[i] + s0);\r\n      var s_col;\r\n      p.colorMode(p.RGB);\r\n      var col1 = p.color(182,219,25); \/\/#B6DB19\r\n      var col2 = p.color(58,9,24); \/\/#3A0918\r\n\r\n      var rad_ratio = this.rn[i]\/this.radius;\r\n      if (rad_ratio &lt; rcol1) {\r\n        s_col = col1;     \r\n      } else if (rad_ratio &gt; rcol2) {\r\n        s_col = col2;\r\n      } else {\r\n        var amt =(rad_ratio - rcol1)\/(rcol2-rcol1);\r\n        s_col = p.lerpColor(col1, col2, amt);\r\n      }\r\n      p.stroke(s_col);\r\n\r\n      if (petals == 0) {\r\n        p.curveTightness(-0.0);\r\n        p.beginShape();\r\n        var f = 0.25;\r\n        if (i&gt;=8) {\r\n          p.curveVertex(this.xn[i-8]+f*(this.cx-this.xn[i-8]), this.yn[i-8]+f*(this.cy-this.yn[i-8]));\r\n          p.curveVertex(this.xn[i-8], this.yn[i-8]);\r\n        } else {\r\n          p.curveVertex(this.cx, this.cy);\r\n          p.curveVertex(this.cx, this.cy);\r\n        }\r\n        p.curveVertex(this.xn[i], this.yn[i]);\r\n        if (i&gt;=5) {\r\n          p.curveVertex(this.xn[i-5], this.yn[i-5]);\r\n          p.curveVertex(this.xn[i-5]+f*(this.cx-this.xn[i-5]), this.yn[i-5]+f*(this.cy-this.yn[i-5]));\r\n        } else {\r\n          p.curveVertex(this.cx, this.cy);\r\n          p.curveVertex(this.cx, this.cy);\r\n        }\r\n        p.endShape();\r\n      } else {\r\n        p.curveTightness(0.5);\r\n        p.beginShape();\r\n        p.curveVertex(this.cx, this.cy);\r\n        if (i&gt;=8) {\r\n          p.curveVertex(this.xn[i-8], this.yn[i-8]);\r\n        } else {\r\n          p.curveVertex(this.cx, this.cy);\r\n        }\r\n        p.curveVertex(this.xn[i], this.yn[i]);\r\n        p.curveVertex(this.xn[i]+0.5*(this.xn[i]-this.cx), this.yn[i]+0.5*(this.yn[i]-this.cy));\r\n        p.endShape();\r\n        p.beginShape();\r\n        p.curveVertex(this.xn[i]+0.5*(this.xn[i]-this.cx), this.yn[i]+0.5*(this.yn[i]-this.cy));\r\n        p.curveVertex(this.xn[i], this.yn[i]);\r\n        if (i&gt;=5) {\r\n          p.curveVertex(this.xn[i-5], this.yn[i-5]);\r\n        } else {\r\n          p.curveVertex(this.cx, this.cy);\r\n        }\r\n        p.curveVertex(this.cx, this.cy);\r\n        p.endShape();\r\n      }\r\n    }\r\n    this.ncurrent = this.nstep;\r\n  }\r\n\r\n  HSpiral.prototype.grow = function() {\r\n    if (this.ncurrent &lt; this.nvertex) {\r\n      this.nstep = this.ncurrent + 1;\r\n      this.draw();\r\n    }\r\n  }\r\n\r\n};\r\n\r\n\r\nnew p5(sketch);<\/code><\/pre><\/p>\n<p>If your interested by patterns in nature, here is a fun series of videos by Vi Hart: <a href=\"https:\/\/www.youtube.com\/watch?v=ahXIMUkSXX0&amp;feature=youtube_gdata_player\" target=\"_blank\">Doodling in Math: Spirals, Fibonacci, and Being a Plant<\/a>.<\/p>\n<\/body><\/html>\n","protected":false},"excerpt":{"rendered":"<p>I love how mathematics can be used to represent phenomenons that we can observe in nature. And when you combined this with programming you can create beautiful patterns. For this project, I was inspired by succulents and the arrangements that the leaves form when they grow, this is referred as phyllotaxis. This pattern can be [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":75,"comment_status":"closed","ping_status":"closed","template":"","format":"standard","meta":{"footnotes":""},"jetpack-portfolio-type":[5],"jetpack-portfolio-tag":[23,11,12],"class_list":["post-72","jetpack-portfolio","type-jetpack-portfolio","status-publish","format-standard","has-post-thumbnail","hentry","jetpack-portfolio-type-generative-design","jetpack-portfolio-tag-p5js","jetpack-portfolio-tag-pattern","jetpack-portfolio-tag-processing","jetpack-portfolio-succulents"],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio\/72","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio"}],"about":[{"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/types\/jetpack-portfolio"}],"author":[{"embeddable":true,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/comments?post=72"}],"version-history":[{"count":1,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio\/72\/revisions"}],"predecessor-version":[{"id":76,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio\/72\/revisions\/76"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/media\/75"}],"wp:attachment":[{"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/media?parent=72"}],"wp:term":[{"taxonomy":"jetpack-portfolio-type","embeddable":true,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio-type?post=72"},{"taxonomy":"jetpack-portfolio-tag","embeddable":true,"href":"https:\/\/joseecarrier.ca\/en\/wp-json\/wp\/v2\/jetpack-portfolio-tag?post=72"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}