ICM Week 4

This week, I combined the homework from my ICM and Visual Language classes. I had to create my own colour palette and make some compositions with those colours on them for the Visual Language class. I wanted to draw a pattern, and also thought it would be great if I could easily apply various palettes and dimensions. Actually, the programme that generates repetitive design seemed suitable to be programmed with objects and functions which were the main requirements of this week’s ICM homework. At the end, these ideas led those two different assignments to the union.

The full story about designing the pattern is introduced in this posting: Personal Colour Palette

The shapes used for drawing the pattern were rather simple: ellipse and arc. Though the challenging part was allowing their sizes and positions variable depending on the user input. A little bit of math was required for this:

I developed it one by one testing each unit. I started drawing a single flower and a leaf without colour. I implemented the UI part separately at the last and then integreted all of them later, and it was less confusing by doing so.

It was tricky to develop the UI part only with my hand-drawing, so made a clear wireframe on Sketch before implementing. It was very helpful to grasp the layout and each component’s position and size:

The flower and leaf shapes were the obvious subject for being objects as they are drawn repeatedly. Besides, I had the increase/decrease buttons and the palette buttons on the UI panel to be objects.

// a flower
function Flower(l) {
  this.pHig = (l/2) / (cos(14));
  this.pWid = this.pHig/3*2;
  this.stamenL = this.pHig/10;
  
  this.display = function() {
    // outer petals		
    fill(palette[paletteMode][0]);	
    for(let angle=0; angle<360; angle+=72) {
      push();
    	rotate(angle);
      translate(0, -(this.pHig/2));
      ellipse(0, 0, this.pWid, this.pHig);
      pop();
    }
    // inner petals and stamens
    for(let a=0; a<360; a+=72) {
      push();
      rotate(a);
      translate(0, -(this.pHig/2));
      fill(palette[paletteMode][1]);	// inner petals
      arc(0, 0, this.pWid, this.pHig, 7, 90, OPEN);
      arc(0, 0, this.pWid, this.pHig, 90, 173, OPEN);
      fill(palette[paletteMode][2]);	// stamens
      ellipse(0, 0, this.stamenL, this.stamenL);
      pop();
    }
  }
  
  this.changeSize = function(newL) {
    	this.pHig = (newL/2) / (cos(14));
      this.pWid = this.pHig/3*2;
      this.stamenL = this.pHig/10;
  }
  
}
// a leaf
function Leaf(l) {
  this.circleRad = l*2;
  this.circle1X = l/2;
  this.circle1Y = l/2;
  this.circle2X = -l/2;
  this.circle2Y = -l/2;
  
  this.display = function() { 
  	push();
 	 	translate(this.circle1X, this.circle1Y);
  	fill(palette[paletteMode][3]);	// upper leaf
  	arc(0, 0, this.circleRad, this.circleRad, 180, 270, OPEN);
  	pop();
  
  	push();
  	translate(this.circle2X, this.circle2Y);
  	fill(palette[paletteMode][4]);	// lower leaf
  	arc(0, 0, this.circleRad, this.circleRad, 0, 90, OPEN);
    pop();
  }
  
  this.changeSize = function(newL) {
    this.circleRad = newL*2;
  	this.circle1X = newL/2;
  	this.circle1Y = newL/2;
  	this.circle2X = -newL/2;
  	this.circle2Y = -newL/2;
  }
}
// a button for increasing/decreasing the dimension of the pattern
function UpDownButton(c1, c2) {
  
  this.normalColour = c1;
  this.hoverColour = c2;
  
  // draw this button
  // rollover effect is included
  this.display = function(x, y, h) {
    
  // set object variables
  this.gap = h*0.09;
  this.triHeight = (h/2)-(this.gap/2);
  this.triWidth = this.triHeight;
  this.x1 = x + (this.triWidth/2);
  this.y1 = y;
  this.x2 = x;
  this.y2 = y + this.triHeight;
  this.x3 = x + this.triWidth;
  this.y3 = y + this.triHeight;
  
  this.x4 = this.x2;
  this.y4 = this.y2 + this.gap;
  this.x5 = this.x3;
  this.y5 = this.y3 + this.gap;
  this.x6 = this.x1;
  this.y6 = y + h;
  
    // increase button
    // rollover::button
    if(mouseX >= (this.x2+panelX) && mouseX <= (this.x3+panelX) && mouseY >= this.y1 && mouseY <= this.y2) 
      fill(this.hoverColour);
    else	fill(this.normalColour);	// normal
    triangle(this.x1, this.y1, this.x2, this.y2, this.x3, this.y3);

    // decrease button
    if(mouseX >= (this.x4+panelX) && mouseX <= (this.x5+panelX) && mouseY >= this.y4 && mouseY <= this.y6)
    	fill(this.hoverColour);
    else	fill(this.normalColour);
    triangle(this.x4, this.y4, this.x5, this.y5, this.x6, this.y6);
  }
  
}
function PaletteButton() {
  
  this.display = function(palBtnX, palBtnY, cellWidth, c) {
    
    this.x = palBtnX;
    this.y = palBtnY;
    this.cellSize = cellWidth;
    this.c = c;
    
    let cellX = this.x;
    let cellY = this.y;
    
    for(i=0; i<6; i++) {
      fill(this.c[i]);
      rect(cellX, cellY, this.cellSize, this.cellSize);
      cellX += this.cellSize;
    }
    
    if(mouseX >= (this.x+panelX) && mouseX <= (this.x+(this.cellSize*6)+panelX) && mouseY >= this.y && mouseY <= (this.y+this.cellSize)) {
      noFill();
      stroke(255,255,0);
      strokeWeight(2);
      rect(this.x, this.y, this.cellSize*6, this.cellSize);
      noStroke();
    } 
  }
}

I actually made the colour palettes an array of objects at first, but changed them into a 2 by 2 matrix at the end of the day, because it was much handier to access the data with the matrix’s index number. I can’t deny that object is a wonderful and intuitive data structure to group many variables and functions, though the palette object that I created was only used for saving data, and moreover, inconvenient when I wanted to access them by index numbers in a for loop, for example.

// Yuchae blossom
let temp=[color(249,250,254), 	// outer petals
          color(221,226,5),			// inner petals
          color(252,246,70),		// stamen
          color(180,206,118),		// upper leaf
          color(147,189,64),		// lower leaf
          color(190,207,254)];	// background 
palette.push(temp);
// inner petals and stamens
for(let a=0; a<360; a+=72) {
  push();
      rotate(a);
      translate(0, -(this.pHig/2));
            fill(palette[paletteMode][1]);	// inner petals
      arc(0, 0, this.pWid, this.pHig, 7, 90, OPEN);
      arc(0, 0, this.pWid, this.pHig, 90, 173, OPEN);
           fill(palette[paletteMode][2]);	// stamens
           ellipse(0, 0, this.stamenL, this.stamenL);
  pop();
}

It was also possible to keep the setup() and draw() function simply as below using functions:

function setup() { 
  initEnvironment();
  initVarialbes();

} 

function draw() { 
  pattern();	 		// draw the pattern
  displayUI();		// draw the UI panel
}

Following is the final sketch. The UI panel disappears when the mouse cursor isn’t on it and shows up again when the cursor approaches the upper edge of the canvas. You can change the dimension by clicking the up/down triangle buttons or apply a different colour palette by hitting desired one. While the minimum dimension is 2*2, there isn’t a limitation of increasing it, though your browser would get slow if it goes over 20 * 20 or something similar.

The full code is available here: http://alpha.editor.p5js.org/yeony102/sketches/Hym9J93oZ

 

Posted in ICM

Leave a Reply

Your email address will not be published. Required fields are marked *