{"id":368,"date":"2011-12-02T12:23:14","date_gmt":"2011-12-02T20:23:14","guid":{"rendered":"http:\/\/new.joyofprocessing.com\/blog\/?p=368"},"modified":"2011-12-02T12:23:14","modified_gmt":"2011-12-02T20:23:14","slug":"stipple-cat","status":"publish","type":"post","link":"https:\/\/joyofprocessing.com\/blog\/2011\/12\/stipple-cat\/","title":{"rendered":"Stipple Cat"},"content":{"rendered":"<p><script type=\"application\/processing\">\/\/ Stipple Cat  Jim Bumgardner\n\/\/\n\/\/   @pjs preload=\"\/assets\/cats2_0.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_1.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_2.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_3.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_4.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_5.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_6.png\";\n\/\/   @pjs preload=\"\/assets\/cats2_7.png\";\n\n\n\/\/ Play with these...\nfloat imageScale;\nfloat dotDensity = .24; \/\/ higher ratios = more dots\n\n\n\/\/ Probably don't need to play with these as much...\nfloat  damping = 0.7;\nfloat  kRadiusFactor = 0.5;\nfloat  kSpeed = 3.0;\nfloat  minDistFactor = 2.5; \/\/ area of influence - smaller numbers make rendering go faster\nint  nbrParticles = 2200;\n\nint catSpeed = 2;\n\n\nPImage reference; \/\/ for dithering initialilzation...\nint nbrCatFrames = 8;\n\nPImage[] cats = new PImage[nbrCatFrames];\n\nclass Particle\n{\n  float  x, y, vx, vy, rad;\n  float  fx, fy, wt;\n\n  Particle(float _x, float _y)\n  {\n    vx = 0;\n    vy = 0;\n    x = _x;\n    y = _y;\n    rad = 1;\n  }\n}\n\nParticle[] particles;\n\nfloat minRadius, maxRadius, medRadius;\n\nvoid setup()\n{\n  size(500,214);\n\n  for (int i = 0; i < nbrCatFrames; ++i) {\n    cats[i] = loadImage(\"\/assets\/cats2_\" + i + \".png\");\n  }\n  reference = cats[0];\n\n  int dwidth = 136;\n  int dheight = 68;\n  imageScale = width\/(float) dwidth;\n\n  particles = new Particle[nbrParticles];\n\n  for (int i = 0; i < nbrParticles; ++i) {\n    particles[i] = new Particle(random(width), random(height));\n  }\n\n  frameRate(24);\n  \/\/ noLoop();\n  smooth();\n  noStroke();\n\n  float medArea = (width*height)\/nbrParticles;\n  medRadius = sqrt(medArea\/PI);\n  minRadius = medRadius;\n  maxRadius = medRadius*medRadius*1;\n  \/\/ println(\"nbrParticles = \" + nbrParticles);\n  \/\/ println(\"medrad = \" + medRadius);\n  \/\/ println(\"min-max = \" + minRadius + \" --> \" + maxRadius);\n  background(255);\n}\n\nvoid doPhysics()\n{\n  if (frameCount % catSpeed == 0) {\n    int frameCtr = (frameCount\/catSpeed % nbrCatFrames);\n    reference = cats[frameCtr];\n  }\n\n  for (int i = 0; i < nbrParticles; ++i) {\n    int px = (int) (particles[i].x \/ imageScale);\n    int py = (int) (particles[i].y \/ imageScale);\n    if (px >= 0 && px < reference.width && py >= 0 && py < reference.height) {\n      int v = (int) red(reference.pixels[ py*reference.width + px ]);\n      particles[i].rad = map(v\/255.0, 0, 1, minRadius, maxRadius);\n    }\n  }\n\n\n  for (int i = 0; i < nbrParticles; ++i) {\n    Particle p = particles[i];\n    p.fx = p.fy = p.wt = 0;\n\n    p.vx *= damping;\n    p.vy *= damping;\n  }\n\n  \/\/ Particle -> particle interactions\n  for (int i = 0; i < nbrParticles-1; ++i) {\n    Particle p = particles[i];\n    for (int j = i+1; j < nbrParticles; ++j) {\n      Particle pj = particles[j];\n      if (i== j || Math.abs(pj.x - p.x) > p.rad*minDistFactor ||\n        Math.abs(pj.y - p.y) > p.rad*minDistFactor)\n        continue;\n\n      double  dx = p.x - pj.x;\n      double  dy = p.y - pj.y;\n      double  distance = Math.sqrt(dx*dx+dy*dy);\n\n      double  maxDist = (p.rad + pj.rad);\n      double  diff = maxDist - distance;\n      if (diff > 0) {\n        double scle = diff\/maxDist;\n        scle = scle*scle;\n        p.wt += scle;\n        pj.wt += scle;\n        scle = scle*kSpeed\/distance;\n        p.fx += dx*scle;\n        p.fy += dy*scle;\n        pj.fx -= dx*scle;\n        pj.fy -= dy*scle;\n      }\n    }\n  }\n\n  for (int i = 0; i < nbrParticles; ++i) {\n    Particle p = particles[i];\n\n    \/\/ keep within edges\n    double dx, dy, distance, scle, diff;\n    double maxDist = p.rad;\n    \/\/ left edge  \n    distance = dx = p.x - 0;    \n    dy = 0;\n    diff = maxDist - distance;\n    if (diff > 0) {\n      scle = diff\/maxDist;\n      scle = scle*scle;\n      p.wt += scle;\n      scle = scle*kSpeed\/distance;\n      p.fx += dx*scle;\n      p.fy += dy*scle;\n    }\n    \/\/ right edge  \n    dx = p.x - width;    \n    dy = 0;\n    distance = -dx;\n    diff = maxDist - distance;\n    if (diff > 0) {\n      scle = diff\/maxDist;\n      scle = scle*scle;\n      p.wt += scle;\n      scle = scle*kSpeed\/distance;\n      p.fx += dx*scle;\n      p.fy += dy*scle;\n    }\n    \/\/ top edge\n    distance = dy = p.y - 0;    \n    dx = 0;\n    diff = maxDist - distance;\n    if (diff > 0) {\n      scle = diff\/maxDist;\n      scle = scle*scle;\n      p.wt += scle;\n      scle = scle*kSpeed\/distance;\n      p.fx += dx*scle;\n      p.fy += dy*scle;\n    }\n    \/\/ bot edge  \n    dy = p.y - height;    \n    dx = 0;\n    distance = -dy;\n    diff = maxDist - distance;\n    if (diff > 0) {\n      scle = diff\/maxDist;\n      scle = scle*scle;\n      p.wt += scle;\n      scle = scle*kSpeed\/distance;\n      p.fx += dx*scle;\n      p.fy += dy*scle;\n    }\n    if (p.wt > 0) {\n      p.vx += p.fx\/p.wt;\n      p.vy += p.fy\/p.wt;\n    }\n    p.x += p.vx;\n    p.y += p.vy;\n  }\n}\n\nvoid draw()\n{\n  doPhysics();\n  fill(255, 72);\n  rect(0, 0, width, height);\n  stroke(0);\n  strokeWeight(medRadius*1.1);\n  for (int i = 0; i < nbrParticles; ++i) {\n    point(particles[i].x, particles[i].y);\n  }\n  \/\/ if (frameCount % 60 == 0)\n  \/\/  println(\"fps = \" + frameRate);\n}\n\n<\/script><\/p>\n<div class=\"ps_cap\"><a href=\"\/showexample.php?ex=stipple_cat\">source<\/a><\/div>\n<p>A variation of my <a href=\"http:\/\/new.joyofprocessing.com\/blog\/2011\/11\/stipple-cam\/\">stipple cam<\/a> sketch from a few days ago, designed to work with Processing.js.  Here, instead of using a webcam, I&#8217;m using a classic motion study by Edweard Muybridge.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>source A variation of my stipple cam sketch from a few days ago, designed to work with Processing.js. Here, instead of using a webcam, I&#8217;m using a classic motion study by Edweard Muybridge.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-368","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/posts\/368","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/comments?post=368"}],"version-history":[{"count":3,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/posts\/368\/revisions"}],"predecessor-version":[{"id":371,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/posts\/368\/revisions\/371"}],"wp:attachment":[{"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/media?parent=368"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/categories?post=368"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/joyofprocessing.com\/blog\/wp-json\/wp\/v2\/tags?post=368"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}