Vase generator with Processing for 3D printing (Part 2)

In the previous tutorial we have written a simple class for creating a vase generator with Processing. Now we will continue our work by adding a GUI to it, so that it will be much easier to experiment with different shapes, before choosing what we want to print.

 

Adding a GUI

First, download, import and initialize the library controlP5, the one we will use to create our GUI.

//...

import controlP5.*;

ControlP5 cp5; // Control P5 for GUI

//...

void setup() {
  size(800, 600, P3D);

  //...

  // Initialize Control P5
  cp5 = new ControlP5(this);
  cp5.setAutoDraw(false);

  //...
}

I suggest now to create a new tab in your Processing sketch and call it “GUI”.

We will now create a new class that will make the code for our GUI more tidy and easier to maintain. Let’s call this class Builder.

class Builder {
  Printer printer = new Printer();
  Settings settings = new Settings();
  Processor processor = new Processor();

  Drawer drawer;
  GcodeGenerator gcodeGenerator;

  Vase vase;

  Builder() {
    addCreator();
    update();
  }

  void addCreator() {
    vase = new Vase(printer, settings, printer.x_center_table, printer.y_center_table);
  }

  void update() {
    vase.generate();

    processor = new Processor();

    processor.addObject(vase);

    processor.sortPaths();

    drawer = new Drawer(processor, printer);

    gcodeGenerator = new GcodeGenerator(printer, settings, processor);
  }

  void visualize() {
    drawer.displayPrinterChamber();
    drawer.displayPaths(color(0, 150));
  }

  void exportGcode() {
    gcodeGenerator = new GcodeGenerator(printer, settings, processor);
    gcodeGenerator.generate().export();
  }
}

As you can see, Builder packs together everything that was previously written in the main tab of the sketch. Let’s see how this looks now:

import java.util.Collections;
import java.util.Comparator; 

import peasy.*;
import peasy.org.apache.commons.math.*;
import peasy.org.apache.commons.math.geometry.*;

PeasyCam cam; // Peasy cam for 3d views

import controlP5.*;

ControlP5 cp5; // Control P5 for GUI

Builder builder;

void setup() {
  size(800, 600, P3D);

  cam = new PeasyCam(this, 100);

  builder = new Builder();

  // Initialize Control P5
  cp5 = new ControlP5(this);
  cp5.setAutoDraw(false);
  setGui();
}

void draw() {
  background(255);

  builder.visualize();

  gui();
}

As you notice, there are two functions which we have not covered yet: setGui() and gui().

gui() allows us to use controlP5 together with PeasyCam, making sure that the two libraries don’t interfere with each other:

// ENABLE CONTOLP5 WITH PEASYCAM
void gui() {
  hint(DISABLE_DEPTH_TEST);
  cam.beginHUD();
  if (cp5.isMouseOver()) {
    cam.setActive(false);
  } else {
    cam.setActive(true);
  }
  cp5.draw();
  cam.endHUD();
  hint(ENABLE_DEPTH_TEST);
}

setGui() adds the different controllers that we want to our interface, in these case several sliders and a button. Refer to the controlP5 documentation and examples to find out how they exactly work and what else you can do with the library.  Associated with setGui() there is a ControlEvent() function:

void setGui() {
  cp5.setAutoDraw(false);

  float start_X = 10;
  float inc_X = 10;
  float start_Y = 10;
  float inc_Y = 10;

  cp5.addSlider("sides").setPosition(start_X, start_Y+=2*inc_Y).setRange(3, 100).setNumberOfTickMarks(98).setCaptionLabel("sides number").setColorCaptionLabel(100).setValue(4);

  cp5.addSlider("width_vase").setPosition(start_X, start_Y+=2*inc_Y).setRange(0, builder.printer.width_table/2).setCaptionLabel("Width X (mm)").setColorCaptionLabel(100).setValue(10);
  cp5.addSlider("length_vase").setPosition(start_X, start_Y+=inc_Y).setRange(0, builder.printer.length_table/2).setCaptionLabel("Length X (mm)").setColorCaptionLabel(100).setValue(10);
  cp5.addSlider("height_vase").setPosition(start_X, start_Y+=inc_Y).setRange(0, builder.printer.height_printer).setCaptionLabel("Height X (mm)").setColorCaptionLabel(100).setValue(10);

  cp5.addSlider("rotation").setPosition(start_X, start_Y+=2*inc_Y).setRange(0, QUARTER_PI/15).setCaptionLabel("Rotation (rad)").setColorCaptionLabel(100).setValue(0);

  cp5.addSlider("amount_oscillation_XY").setPosition(start_X, start_Y+=2*inc_Y).setRange(0, 50).setCaptionLabel("amount oscillation XY (mm)").setColorCaptionLabel(100).setValue(0);
  cp5.addSlider("increment_oscillation_XY").setPosition(start_X, start_Y+=inc_Y).setRange(0, PI).setCaptionLabel("increment oscillation XY (rad)").setColorCaptionLabel(100).setValue(0);

  cp5.addSlider("amount_oscillation_Z").setPosition(start_X, start_Y+=2*inc_Y).setRange(0, 50).setCaptionLabel("amount oscillation Z (mm)").setColorCaptionLabel(100).setValue(0);
  cp5.addSlider("increment_oscillation_Z").setPosition(start_X, start_Y+=inc_Y).setRange(0, QUARTER_PI/15).setCaptionLabel("increment oscillation Z (rad)").setColorCaptionLabel(100).setValue(0);

  cp5.addButton("Export GCODE").setPosition(10, height-50).setHeight(40).setWidth(int(0.2*width)-10).setColorLabel(10).setColorBackground(color(0, 200, 0));
}

void controlEvent(ControlEvent theEvent) {
  if (theEvent.isController()) { 
    if (theEvent.getController().getName()=="sides") {
      builder.vase.setSides((int)cp5.getController("sides").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="width_vase") {
      builder.vase.setWidth(cp5.getController("width_vase").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="length_vase") {
      builder.vase.setLength(cp5.getController("length_vase").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="height_vase") {
      builder.vase.setHeight(cp5.getController("height_vase").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="rotation") {
      builder.vase.setRotation(cp5.getController("rotation").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="amount_oscillation_XY") {
      builder.vase.setOscillationXYAmount(cp5.getController("amount_oscillation_XY").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="increment_oscillation_XY") {
      builder.vase.setOscillationXY(cp5.getController("increment_oscillation_XY").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="amount_oscillation_Z") {
      builder.vase.setOscillationZAmount(cp5.getController("amount_oscillation_Z").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="increment_oscillation_Z") {
      builder.vase.setOscillationZ(cp5.getController("increment_oscillation_Z").getValue());
      builder.update();
    } else if (theEvent.getController().getName()=="Export GCODE") {
      builder.exportGcode();
    }
  }
}

And here we have out GUI for our vase generator:

processing_screenshot_3

As we said in the previous tutorial, this is only a little example: try to expand this vase generator and see what you can achieve!

processing_screenshot_4

Vase generator

Vase generator Vase generator

Vase generator

Vase generator

 

2 comments

Leave a Reply