Design with Ratios

ANAR+ is a scenegraph providing basic geometric operations. Each object have his own set of properties like colors, ways to be rendered, Parameters.

The second most important feature in ANAR+ is the Transmigration Operations, similar to what you usually find in parametric modeling softwares (like Generative Component, Catia, SolidWorks, ProEngineer). The Transmigration Operations are a way to describe intrinsic properties of a form. The philosophy of ANAR+ is to provide ways to better describe relationship between parts of a construction. Since each constructions represent a different way to think to world, there is no good or bad ways to describe part relationships, they are just a different point of view and they have different meaning for each designers.

Transformation and Parametric

anar.ch_img_studio.01_01.jpg

For an equivalent geometrical result, different geometrical constructions could be described. Those different process have different meanings and represent a particular point of view of the form's logic.

Primitives

With a limited set of primitives, combined in different ways, we achieve different forms generations.

anar.ch_img_studio.01_primitives.jpg

Parameters

import anar.*;
import processing.opengl.*;
 
Sliders mySliders;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
 
  //Create some parametric values
  Param a = new Param(50);
  Param b = new Param(50);
 
  //Param --> Value, Minimum, Maximum
  Param c = new Param(255,0,255);
 
  //Create a new Sliders List
  mySliders = new Sliders();
  mySliders.add(a);
  mySliders.add(b);
  mySliders.add(c);
}
 
void draw() {
  //Use the value to change the background color
  background(mySliders.get(0).toFloat(),mySliders.get(1).toFloat(),mySliders.get(2).toFloat());
  mySliders.draw();
}

Geometric Construction

anar.ch_img_studio.01_image1.jpg

For a simple square construction, we have different constructions process enabling different behaviours when edited.

Square.00

First, a square described with absolute coordinates.

import anar.*;
import processing.opengl.*;
 
Face mySquare;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
 
  initForm();
}
 
void initForm() {
 
  //Create few points with absolute coordinates
  Pt a = Anar.Pt(-60, -60);
  Pt b = Anar.Pt(60, -60);
  Pt c = Anar.Pt(60, 60);
  Pt d = Anar.Pt(-60, 60);
 
  //Create a new Face
  mySquare = new Face();
 
  //Store the points inside our Face
  mySquare.add(a);
  mySquare.add(b);
  mySquare.add(c);	
  mySquare.add(d);
 
  //Create Sliders based on an object
  Anar.sliders(mySquare);	
}
 
void draw() {
  background(150);
  mySquare.draw();
}

anar.ch_img_studio.01_00564.jpg

anar.ch_img_studio.01_00565.jpg anar.ch_img_studio.01_p5pdesquareoog01csquare00dot.jpg

Square.01

Second Square is defined from a set of Translation

import anar.*;
import processing.opengl.*;
 
Face mySquare;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  //Create a first point with absolute coordinates    
  Pt a = Anar.Pt(-60, -60);
 
  //Create two transformations
  Translate t1 = new TranslateX(120);
  Translate t2 = new TranslateY(120);
 
  //Create point b from point a with the translation t1
  Pt b = a.copy().apply(t1);
 
  //Create a first line  
  Pts myLine1 = new Pts(a,b);
 
  //Copy and move the first line
  Pts myLine2 = myLine1.copy().apply(t2);
 
  //Create a new Face
  mySquare = new Face();
 
  //Store the points inside our Face
  myLine2.reverse();  //We want to pair points
  mySquare.add(myLine1);
  mySquare.add(myLine2);
 
  //Create Sliders based on an object
  Anar.sliders(b);  
}
 
void draw() {
  background(150);
  mySquare.draw();
}

anar.ch_img_studio.01_00566.jpg

anar.ch_img_studio.01_00567.jpg anar.ch_img_studio.01_p5pdesquareoog01csquare01d.jpg

A different example, with a different construction. In this case, the modification behavior is slightly different: it creates parallelograms.

Note that there is no better solution, it depends on the designer intention to define a specific family of possible forms. Some further developments would absolutely need right angles and opt for the previous solution, others would benefit from the added freedom in form exploration.

import anar.*;
import processing.opengl.*;
 
Face mySquare;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  //Create a first point with absolute coordinates    
  Pt a = Anar.Pt(-60, -60);
  Pt b = Anar.Pt(60,-60);
 
  //Create a Translation
  Translate t1 = new TranslateY(120);
 
  //Create point b from point a with the translation t1
  Pt c = a.copy().apply(t1);   
 
  //Create a first line
  Pts myLine1 = new Pts(a,b); 
 
  //Create point b from point a with the translation t1
  Pt d = b.copy().apply(t1); 
 
  //Create a new Face
  mySquare = new Face(a,b,d,c);
 
  //Create Sliders based on an object
  Anar.sliders(mySquare);  
}
 
void draw() {
  background(150);
  mySquare.draw();
}

This code might be simplified. Some parts might be written differently, they are considered equivalent.

Pt c = a.copy().apply(t1);
Pt c = new Pt(a).apply(t1);
Pt c = a.copy().translateY(120);

But if you say this:

Pt c = a.translateY(120);

Then a will be changed as c. copy() is required to create a different instance of a.

Square.02

For the last construction, we use the rotations and translation.

import anar.*;
import processing.opengl.*;
 
Face mySquare;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  //Definition of shape parameters	
  int numOfSides = 4;	
  float theta = 2*PI/numOfSides;
 
  //Create a first point with absolute coordinates    
  Pt a = Anar.Pt(-60, -60);
 
  // rotation
  RotateZ r = new RotateZ(theta);
 
  //Create a new Face
  mySquare = new Face();
 
  for (int i=0; i<numOfSides; i++) {
    //Create a point from a previous
    Pt newPt = a.copy().apply(r);
    mySquare.add(newPt);
    a = newPt;
  }
 
  //Create Sliders based on an object
  Anar.sliders(mySquare);  
}
 
void draw() {
  background(153);
  mySquare.draw();
}

anar.ch_img_studio.01_00568.jpg

anar.ch_img_studio.01_00569.jpg anar.ch_img_studio.01_p5pdesquareoog01csquare02dot.jpg anar.ch_img_studio.01_00570.jpg anar.ch_img_studio.01_p5pdesquareoog01csquare02xt.jpg

Star

With a set of two transformations

import anar.*;
import processing.opengl.*;
 
Face myStar;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  int numOfSides = 5;
  float theta = 2*PI/(numOfSides*2);
 
  Param p = new Param(100,0,100,3);
 
  // starting point
  Pt a = Anar.Pt(100,0);
  Pt b = Anar.Pt(50,0);
 
  // rotation
  RotateZ rot = new RotateZ(theta);
  b.apply(rot);
 
  //Create a new Face
  myStar = new Face();
 
  //Store the points inside our Face
  for (int i=0; i<numOfSides; i++) {
    a = a.copy();
    b = b.copy();
 
    a.apply(rot);
    a.apply(rot);
 
    b.apply(rot);
    b.apply(rot);
 
    myStar.add(a,b);
  }
 
  //Create Sliders based on an object
  Anar.sliders(myStar); 
}
 
public void draw() {
  background(153);
  myStar.draw();
}

anar.ch_img_studio.01_00578.jpg

Spiral

Here the line is stored in an Obj which can contain Faces, Pts and Pt (e.g. faces, lines and points).

import anar.*;
import processing.opengl.*;
 
Obj myObj;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  //Create a new Object to store our shape
  myObj = new Obj();  
 
  int numOfSides = 25;
  int numOfLoops = 5;
  float theta = 2*PI/(numOfSides*2);
 
  // starting point
  Pt a = Anar.Pt(50,0);
  Pt b = Anar.Pt(45,0);
 
  // rotation
  RotateZ rot = new RotateZ(theta);
  b.apply(rot);
 
  Translate t = new TranslateZ(1);
 
  //Create a new Line
  Pts myLine = new Pts();
 
  for (int i=0; i<numOfSides*numOfLoops; i++) {
    a = a.copy();
    b = b.copy();
 
    a.apply(rot);
    a.apply(rot);
    a.apply(t);
 
    b.apply(rot);
    b.apply(rot);
    b.apply(t);
 
    myLine.add(a);
    myLine.add(b);
  }
 
  //Store myLine in our object
  myObj.add(myLine);
 
  //Create Sliders based on an object
  Anar.sliders(myObj); 
}
 
void draw() {
  background(153);
  myObj.draw();
  Anar.camTarget(myObj);
}

anar.ch_img_studio.01_00579.jpg

Star Grid

an example with a set of different modules

import processing.opengl.*;
import anar.*;
 
Obj myObj = new Obj();
 
void setup(){
    size(800,400,OPENGL);
  frameRate(200);
 
    //this.hint(ENABLE_OPENGL_2X_SMOOTH);
 
  Anar.init(this);
  Anar.drawAxis(true);
 
  initForm();
}
 
void initForm(){
 
  myObj = new Obj();
 
  int nGridX = 6;
  int nGridY = 6;
 
  Param h = new Param(30,0,300);
  Param r = new Param(1,-PI*4,PI*4);
  Param L = new Param(50,0,100);
  Param s = new Param(20,0,100);
 
  Anar.slidersReset();
  Anar.sliders(h);
  Anar.sliders(r);
  Anar.sliders(L);
  Anar.sliders(s);
 
  for(int i=0; i<nGridX; i++)
    for(int j=0; j<nGridY; j++){       
      Param x = s.multiply(nGridX*(i-nGridX/2f));
      Param y = s.multiply(nGridY*(j-nGridY/2f));
 
      Obj tmpModule = createModule(x,y,h,random(90)+10,L,(int)random(10)+3,r);
 
      myObj.add(tmpModule);
    }
 
  myObj.fill(255,100);
}
 
Obj createModule(Param x, Param y,Param h,float lengthA, Param lenghtB, int numOfSides, Param rotation){
  Obj myModule = new Obj();    
 
  Face star = new Star(new Param(lengthA),lenghtB,new Param(numOfSides));
  star.translate(x,y);
 
  Obj pyr = new Pyramid(star,h);
  myModule.add(pyr);
 
  Transform allign = new Transform(star.pt((int)random(star.numOfPts())),star.pt((int)random(star.numOfPts())));
  allign.rotateZ(rotation);
 
  Face starRefelx = new Face(star,allign);
 
  myModule.add(starRefelx);
 
  return myModule;
}
 
void draw(){
  background(155);
  myObj.draw();
}

the same example with individual parameters

import processing.opengl.*;
import anar.*;
 
Obj myObj = new Obj();
 
Sliders hauteurs = new Sliders();
Sliders rotationz = new Sliders();
 
Obj[][] griOfPyr = new Obj[6][6];
 
void setup(){
  size(800,400,OPENGL);
  frameRate(200);
 
  //this.hint(ENABLE_OPENGL_2X_SMOOTH);
 
  Anar.init(this);
  Anar.drawAxis(true);
 
  initForm();
 
  actualDisplayedSet = hauteurs;
}
 
void initForm(){
 
  myObj = new Obj();
 
  int nGridX = 6;
  int nGridY = 6;
 
  Param h = new Param(30,0,300);
  Param r = new Param(1,-PI*4,PI*4);
  Param L = new Param(50,0,100);
  Param s = new Param(20,0,100);
 
  /*
  Anar.slidersReset();
   Anar.sliders(h);
   Anar.sliders(r);
   Anar.sliders(L);
   Anar.sliders(s);
   */
 
  for(int i=0; i<nGridX; i++)
    for(int j=0; j<nGridY; j++){       
      Param x = s.multiply(nGridX*(i-nGridX/2f));
      Param y = s.multiply(nGridY*(j-nGridY/2f));
 
      Obj tmpModule = createModule(x,y,h,random(90)+10,L,(int)random(10)+3,r);
 
      myObj.add(tmpModule);
 
      griOfPyr[i][j] =  tmpModule;
    }
 
  myObj.fill(255,100);
}
 
Obj createModule(Param x, Param y,Param h,float lengthA, Param lenghtB, int numOfSides, Param rotation){
  Obj myModule = new Obj();    
 
  Face star = new Star(new Param(lengthA),lenghtB,new Param(numOfSides));
  star.translate(x,y);
 
  Param hh = new Param(.5f); 
  hauteurs.add(hh);
 
  Param rr = new Param(.5f); 
  rotationz.add(rr);
 
  Obj pyr = new Pyramid(star,hh);
  myModule.add(pyr);
 
  Transform allign = new Transform(star.pt((int)random(star.numOfPts())),star.pt((int)random(star.numOfPts())));
  allign.rotateZ(rr);
 
  Face starRefelx = new Face(star,allign);
 
  myModule.add(starRefelx);
 
  return myModule;
}
 
Sliders actualDisplayedSet;
 
void draw(){
  background(155);
  myObj.draw();
  actualDisplayedSet.draw();
 
 
}
 
void keyPressed(){
  if(actualDisplayedSet == hauteurs)
    actualDisplayedSet = rotationz;
  else 
    actualDisplayedSet = hauteurs;
}

Tower Array

anar.ch_img_studio.01_00574.jpg

An exemple with a single module but with independent rotations.

import anar.*;
import processing.opengl.*;
 
Obj myObj;
Sliders myParams;
 
Pts ref;
 
void setup() {
  size(800, 400, OPENGL);
  Anar.init(this);
  initForm();
}
 
void initForm() {
  //Create a new Object to store our shape
  myObj = new Obj();  
 
  //Create a vertical translation defining the height of tower floors
  Transform t = new Translate(0,0,10);
 
  //Create parameter array to store individual rotations values
  myParams = new Sliders();
 
  Obj module = createModule();
 
  for (int i=0; i<25; i++) {
    //Create individual rotations parameters randomly
    Param p = new Param(random(.4f), -3.14f, 3.14f);
 
    //Create transformation that include a translation 
    // and a new rotation on the axis Z created from p
    Transform tt = new Transform();
    tt.add(t);
    tt.rotateZ(p);
 
    myParams.add(p);
 
    //Create a copy of module
    //Apply the transformation
    Obj myCopy = module.copy().apply(tt);
 
    //Add the copy to myObj
    myObj.add(myCopy);
 
    //copy is now the base module
    module = myCopy;
  }
 
  Anar.camTarget(myObj);
}
 
Obj createModule() {
  int edge = 40;
  int h = 9;
 
  //Create the base face (here a square)
  Face f = new Face();
  f.add(Anar.Pt(-edge/2, -edge/2));
  f.add(Anar.Pt(edge/2,-edge/2));
  f.add(Anar.Pt(edge/2, edge/2));
  f.add(Anar.Pt(-edge/2,edge/2));
 
  //Extrude mySquare along the translation t
  return new Extrude(f, Anar.Pt(0,0,h));  
}  
 
void draw() {
  background(150);
  myObj.draw();
  myParams.draw();
}