package org.reprap.geometry;
import javax.media.j3d.*;
import javax.swing.JCheckBoxMenuItem;
import org.reprap.Preferences;
import org.reprap.Printer;
import org.reprap.geometry.polygons.*;
import org.reprap.gui.PreviewPanel;
import org.reprap.gui.RepRapBuild;
import org.reprap.machines.MachineFactory;
import org.reprap.machines.NullCartesianMachine;
import org.reprap.utilities.Debug;
import org.reprap.devices.pseudo.LinePrinter;
public class Producer {
/**
* The machine doing the making
*/
protected Printer reprap;
/**
* Line parallel to which odd-numbered layers will be hatched
*/
protected RrHalfPlane oddHatchDirection;
/**
* Line parallel to which even-numbered layers will be hatched
*/
protected RrHalfPlane evenHatchDirection;
/**
* The list of objects to be built
*/
protected RepRapBuild bld;
/**
* @param preview
* @param builder
* @throws Exception
*/
public Producer(PreviewPanel preview, RepRapBuild builder) throws Exception {
reprap = MachineFactory.create();
reprap.setPreviewer(preview);
if(preview != null)
preview.setMachine(reprap);
bld = builder;
// Original hatch vectors
oddHatchDirection = new RrHalfPlane(new Rr2Point(0.0, 0.0), new Rr2Point(1.0, 1.0));
evenHatchDirection = new RrHalfPlane(new Rr2Point(0.0, 1.0), new Rr2Point(1.0, 0.0));
// // Vertical hatch vector
// oddHatchDirection = new RrHalfPlane(new Rr2Point(0.0, 0.0), new Rr2Point(0.0, 1.0));
// evenHatchDirection = new RrHalfPlane(new Rr2Point(0.0, 1.0), new Rr2Point(0.0, 0.0));
// // Horizontal hatch vector
// oddHatchDirection = new RrHalfPlane(new Rr2Point(0.0, 0.0), new Rr2Point(1.0, 0.0));
// evenHatchDirection = new RrHalfPlane(new Rr2Point(1.0, 0.0), new Rr2Point(0.0, 0.0));
}
/**
* Set the source checkbox used to determine if there should
* be a pause between segments.
*
* @param segmentPause The source checkbox used to determine
* if there should be a pause. This is a checkbox rather than
* a boolean so it can be changed on the fly.
*/
public void setSegmentPause(JCheckBoxMenuItem segmentPause) {
reprap.setSegmentPause(segmentPause);
}
/**
* Set the source checkbox used to determine if there should
* be a pause between layers.
*
* @param layerPause The source checkbox used to determine
* if there should be a pause. This is a checkbox rather than
* a boolean so it can be changed on the fly.
*/
public void setLayerPause(JCheckBoxMenuItem layerPause) {
reprap.setLayerPause(layerPause);
}
public void setCancelled(boolean c)
{
reprap.setCancelled(c);
}
/**
* @throws Exception
*/
public void produce() throws Exception
{
int movementSpeedZ;
boolean subtractive;
boolean interLayerCooling;
try {
subtractive = Preferences.loadGlobalBool("Subtractive");
movementSpeedZ = Preferences.loadGlobalInt("MovementSpeedZ(0..255)");
} catch (Exception ex) {
movementSpeedZ = 212;
subtractive = false;
System.err.println("Warning: could not load Z MovementSpeed and/or subtractive flag, using default");
}
try {
interLayerCooling = Preferences.loadGlobalBool("InterLayerCooling");
} catch (Exception ex) {
interLayerCooling = true;
System.err.println("Warning: could not load InterLayerCooling flag, using default");
}
reprap.setSpeedZ(movementSpeedZ);
Debug.d("Intialising reprap");
reprap.initialise();
Debug.d("Selecting material 0");
reprap.selectExtruder(0);
Debug.d("Setting temperature");
reprap.getExtruder().heatOn();
// A "warmup" segment to get things in working order
if (!subtractive)
{
reprap.setSpeed(reprap.getExtruder().getXYSpeed());
reprap.moveTo(1, 1, 0, false, false);
// Workaround to get the thing to start heating up
reprap.printTo(1, 1, 0, true);
if(reprap.getExtruder().getNozzleClearTime() <= 0)
{
Debug.d("Printing warmup segments, moving to (1,1)");
// Take it slow and easy.
Debug.d("Printing warmup segments, printing to (1,60)");
reprap.moveTo(1, 25, 0, false, false);
reprap.setSpeed(LinePrinter.speedFix(reprap.getExtruder().getXYSpeed(),
reprap.getExtruder().getOutlineSpeed()));
reprap.printTo(1, 60, 0, false);
Debug.d("Printing warmup segments, printing to (3,60)");
reprap.printTo(3, 60, 0, false);
Debug.d("Printing warmup segments, printing to (3,25)");
reprap.printTo(3, 25, 0, true);
Debug.d("Warmup complete");
}
reprap.setSpeed(reprap.getFastSpeed());
}
// This should now split off layers one at a time
// and pass them to the LayerProducer.
boolean isEvenLayer = true;
STLSlice stlc;
double zMax;
bld.mouseToWorld();
stlc = new STLSlice(bld.getSTLs());
zMax = stlc.maxZ();
double startZ;
double endZ;
double stepZ;
if (subtractive)
{
// Subtractive construction works from the top, downwards
startZ = zMax;
endZ = 0;
stepZ = -reprap.getExtruder().getExtrusionHeight();
reprap.setZManual(startZ);
} else
{
// Normal constructive fabrication, start at the bottom and work up.
startZ = 0;
endZ = zMax;
stepZ = reprap.getExtruder().getExtrusionHeight();
}
int layerNumber = 0;
for(double z = startZ; subtractive ? z > endZ : z < endZ; z += stepZ) {
if (reprap.isCancelled())
break;
Debug.d("Commencing layer at " + z);
// Change Z height
reprap.moveTo(reprap.getX(), reprap.getY(), z, false, false);
if (reprap.isCancelled())
break;
// Pretend we've just finished a layer first time;
// All other times we really will have.
if (layerNumber == 0 || interLayerCooling) {
reprap.finishedLayer(layerNumber);
reprap.betweenLayers(layerNumber);
}
RrCSGPolygonList slice = stlc.slice(z+reprap.getExtruder().getExtrusionHeight()*0.5);
BranchGroup lowerShell = stlc.getBelow();
LayerProducer layer = null;
if(slice.size() > 0)
layer = new LayerProducer(reprap, z, slice, lowerShell,
isEvenLayer?evenHatchDirection:oddHatchDirection,
layerNumber, endZ);
if (layerNumber == 0 || interLayerCooling) {
reprap.startingLayer(layerNumber);
}
if (reprap.isCancelled())
break;
if(layer != null)
{
layer.plot();
layer.destroy();
}
layer = null;
slice.destroy();
stlc.destroyLayer();
isEvenLayer = !isEvenLayer;
layerNumber++;
}
if (subtractive)
reprap.moveTo(0, 0, startZ, true, true);
else
reprap.moveTo(0, 0, reprap.getZ(), true, true);
reprap.terminate();
}
/**
* The total distance moved is the total distance extruded plus
* plus additional movements of the extruder when no materials
* was deposited
*
* @return total distance the extruder has moved
*/
public double getTotalDistanceMoved() {
return reprap.getTotalDistanceMoved();
}
/**
* @return total distance that has been extruded in millimeters
*/
public double getTotalDistanceExtruded() {
return reprap.getTotalDistanceExtruded();
}
/**
* TODO: This figure needs to get added up as we go along to allow for different extruders
* @return total volume that has been extruded
*/
public double getTotalVolumeExtruded() {
return reprap.getTotalDistanceExtruded() * reprap.getExtruder().getExtrusionHeight() *
reprap.getExtruder().getExtrusionSize();
}
/**
*
*/
public void dispose() {
reprap.dispose();
}
/**
* @return total elapsed time in seconds between start and end of building the 3D object
*/
public double getTotalElapsedTime() {
return reprap.getTotalElapsedTime();
}
}