import processing.opengl.*; import processing.opengl.*; import anar.*; // import geometry.Point3D; import java.util.*; import rad.*; /* * Example for Anar library by Guillaume LaBelle + Julien Nembrini * http://anar.ch */ Obj myObject; Param angle = new Param(0.3f); Param invAngle = new Param( -angle.get()); ArrayList deploy = new ArrayList(); Transform[] sides = new Transform[3]; // ///////////////////////////////// // ///////////////////////////////// // ///////////////////////////////// void setup(){ // size(screen.width,screen.height,OPENGL); size(1000,500,OPENGL); Anar.init(this); Anar.drawAxis(true); simThread = new RadEngine(this,10f); // generate random deployment // must comply with max delta rule newDeploy(); // ///////////////////////////////// // ///////////////////////////////// // PREPARE TRANSFORMS // We limit the set of transforms to three different // It will produce a limited set of different patterns // The elementary operation Translate modulor = new Translate(Anar.PtNull(0,0,3)); // Create 3 subsequent Transform from this one // I use TransformLinear to combine them as a group Transform sideA = new Transform(); sideA.add(modulor); Transform sideB = new Transform(); sideB.add(modulor); sideB.add(modulor); Transform sideC = new Transform(); sideC.add(modulor); sideC.add(modulor); sideC.add(modulor); // Then I have three different transforms from the first one // They have different lengths // Remark, I ends up with only one parameter // Combine them in a table (it will be usefull when randomized) // Here I need to remember that 0 is short, 1 normal and 2 is long sides[0] = sideA; sides[1] = sideB; sides[2] = sideC; // It's good for sides myObject = generatorDeploy(deploy); Face.globalRender = new RenderFaceDoubleSide(new AColor(255,180,180),new AColor(220)); } // ///////////////////////////////// // ///////////////////////////////// // ///////////////////////////////// void draw(){ if(frameCount%2==0) background(255); else background(230); myObject.draw(); // if(frameCount%1000==750) angle.set(0); // if(frameCount%1000==999) angle.set(0.3f); if( !isSimRunning){ myObject = growDeploy(deploy); simThread.simulate(myObject); simThread.runNow(); isSimRunning = true; } } // ///////////////////////////////// // ///////////////////////////////// // ///////////////////////////////// int A, B; float energy; Element(int _A, int _B, float _e){ A = _A; B = _B; energy = _e; } } // start wiht two elements static int nElement = 2; static int maxDelta = 3; static int maxModulor = 3; // create new deployment random void newDeploy(){ deploy.clear(); // Indeed also to track the difference between both (number of times between // modulos) // At the beginning they are both aligns // -1 means that ptsB is from a distance 1 of modulor less than ptsA // 2 means that ptsB is from a distance 2 of modulor more than ptsA int delta = 0; for (int i = 0; imaxDelta); // Here I limit the // maximum sitance // between paths (both // ways) // Update new delta state delta += lengthA-lengthB; deploy.add(new Element(lengthA,lengthB,0f)); } } Obj growDeploy(ArrayList d){ // add an element to the deployment // in order to increase the energy gathered // first compute delta int delta = 0; ListIterator it = d.listIterator(); while (it.hasNext()){ Element e = it.next(); delta += e.A-e.B; } // compute new element according to energy from last element float energieAA = d.get(nElement-2).energy; float energieA = d.get(nElement-1).energy; int lengthA = 0; int lengthB = 0; // if energy is growing increase delta trend if(energieAA0&&delta -maxDelta){ lengthA = 1; lengthB = 2; } else{ lengthA = 1; lengthB = 1; } } // if energy decreases inverse delta trend else{ if(delta>0){ lengthA = 1; lengthB = 2; } else if(delta<0){ lengthA = 2; lengthB = 1; } else{ lengthA = 1; lengthB = 1; } } d.add(new Element(lengthA,lengthB,0f)); nElement++; return generatorDeploy(d); } // ////////////////////////////////// // ////////////////////////////////// // ////////////////////////////////// Obj generatorDeploy(ArrayList d){ // ///////////////////////////////// // ///////////////////////////////// // INIT SOME CONTAINERS Obj outputFmz = new Obj(); // Now let's create a rotation (let's keep it simple with only one rotation) // On the chantier, it correspond to uniforms clips between panels // I need to create a RotateZ as it will be used inside Allingn // Allign will allign an axis to Z coordinate then apply a transform and // Come back to initial state RotateZ myRotation = new RotateZ(0.1f); RotateZ myRotation2 = new RotateZ(0); RotateZ myRotation3 = new RotateZ( -0.1f); // ///////////////////////////////// // ///////////////////////////////// // ASSIGN TRANSFORMS // I1){ axisRotateA = new Transform(previousA,previousB,myRotation); axisRotateB = new Transform(previousA,previousB,myRotation); } else{ axisRotateA = new Transform(previousA,previousB,myRotation3); axisRotateB = new Transform(previousA,previousB,myRotation3); } // Create a Translation alligned with the previous // Remember that we don't know how is oriented the last face Transform orientedTranslationA = new Transform(previousAA,previousA,sides[d.get(i).A]); Transform orientedTranslationB = new Transform(previousBB,previousB,sides[d.get(i).B]); // Apply to rotation to the translation Transform comboA = new Transform(); comboA.add(orientedTranslationA); comboA.add(axisRotateA); // From the beginning Transform comboB = new Transform(); comboB.add(orientedTranslationB); comboB.add(axisRotateB); // From the beginning // Here's where evrything is set together pt with transform newPtA.apply(comboA); newPtB.apply(comboB); // Alternative (if we don't want to apply the rotation // Use this to see only the translation effect on a plane // newPtA.set(sides[lengthA]); // newPtB.set(sides[lengthB]); // Put all that in that containers ptsA.add(newPtA); ptsB.add(newPtB); // Swap Previuos previousAA = previousA; previousBB = previousB; previousA = newPtA; previousB = newPtB; } // ///////////////////////////////// // ///////////////////////////////// // RETURN EVRYTHING // cREATE FACES FROM TWO LINES WITH SAME NUMBERS OF POINTS outputFmz = new SweepTwoPaths(ptsA,ptsB); // Cosmetik print(ptsA); print(ptsB); // print(outputFmz.primitiveToString( -1)); TextIO.write("test.lsp",outputFmz.toAutocad()); ptsA.color(new AColor(0,0,255)); ptsB.color(new AColor(255,150,150)); return outputFmz; } // ///////////////////////////////// // ///////////////////////////////// // ///////////////////////////////// // So Rad boolean isSimRunning = true; RadEngine simThread; @Override void radSimDone() { isSimRunning = false; // SwitchRender // MetaRad.switchToAverageRender(myObject); // here integrate energy results into deployment ListIterator it = myObject.faces.listIterator(); int count = 0; Face dummy = it.next(); while (it.hasNext()){ deploy.get(count).energy = ((RenderRadSim)it.next().render).energyDensityFront; count++; } // myObject = transformatorDeploy(deploy); } void keyPressed(){ switch(key){ case 'q': simThread.simulate(myObject); simThread.runNow(); isSimRunning = true; break; case ' ': // myObject = generatorDeploy(); break; case 'w': // MetaRad.switchRender(myObject); break; case 'e': // MetaRad.switchToAverageRender(myObject); break; case 'p': Scene.autoSeek = false; break; case 'r': angle.set(0); invAngle.set( -angle.get()); break; case 't': angle.set(0.3f); invAngle.set( -angle.get()); break; } } // ///////////////////////////////// // ///////////////////////////////// // /////////////////////////////////