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.
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.
With a limited set of primitives, combined in different ways, we achieve different forms generations.
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(); }
For a simple square construction, we have different constructions process enabling different behaviours when edited.
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(); }
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(); }
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.
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(); }
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(); }
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); }
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; }
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(); }