package org.reprap.pcb;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.PrintStream;
import java.io.FileReader;
import java.io.File;
import java.util.Date;
import java.text.SimpleDateFormat;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import org.reprap.Extruder;
import org.reprap.Attributes;
import org.reprap.Preferences;
import org.reprap.geometry.polygons.*;
import org.reprap.utilities.RrGraphics;
import org.reprap.utilities.Debug;
import org.reprap.comms.GCodeReaderAndWriter;
class PCBOffsets extends JPanel {
private static final long serialVersionUID = 1L;
private static JDialog dialog;
private static JTextField xo;
private static JTextField yo;
private static double xoff = 10;
private static double yoff = 10;
private PCBOffsets(Rectangle rec)
{
super(new BorderLayout());
JPanel radioPanel;
radioPanel = new JPanel(new GridLayout(0, 1));
radioPanel.setSize(300,200);
JLabel jLabel2 = new JLabel();
radioPanel.add(jLabel2);
jLabel2.setText(" PCB dimensions: " + org.reprap.machines.GCodeRepRap.round(rec.ne().x() - rec.sw().x(), 1) +
"(X) x " + org.reprap.machines.GCodeRepRap.round(rec.ne().y() - rec.sw().y(), 1) + "(Y) mm");
jLabel2.setHorizontalAlignment(SwingConstants.CENTER);
JLabel jLabel3 = new JLabel();
radioPanel.add(jLabel3);
jLabel3.setText(" Offsets (X and Y) in mm:");
jLabel3.setHorizontalAlignment(SwingConstants.CENTER);
xo = new JTextField("10");
radioPanel.add(xo);
xo.setHorizontalAlignment(SwingConstants.CENTER);
yo = new JTextField("10");
radioPanel.add(yo);
yo.setHorizontalAlignment(SwingConstants.CENTER);
try
{
JButton okButton = new JButton();
radioPanel.add(okButton);
okButton.setText("OK");
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
OKHandler();
}
});
add(radioPanel, BorderLayout.LINE_START);
setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
} catch (Exception ex)
{
Debug.e(ex.toString());
ex.printStackTrace();
}
}
public static void OKHandler()
{
xoff = Double.parseDouble(xo.getText().trim());
yoff = Double.parseDouble(yo.getText().trim());
dialog.dispose();
}
public static void pcbo(Rectangle rec)
{
//Create and set up the window.
JFrame f = new JFrame();
dialog = new JDialog(f, "PCB Offsets");
dialog.setLocation(500, 400);
dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
//Create and set up the content pane.
JComponent newContentPane = new PCBOffsets(rec);
newContentPane.setOpaque(true); //content panes must be opaque
dialog.setContentPane(newContentPane);
//Display the window.
dialog.pack();
dialog.setModalityType(JDialog.DEFAULT_MODALITY_TYPE);
dialog.setVisible(true);
}
public static double getXoff()
{
return xoff;
}
public static double getYoff()
{
return yoff;
}
}
public class PCB {
GerberGCode gerberGcode;
String[] splitline;
Rectangle bigBox;
BufferedReader in;
String line;
String formatX = "23", formatY="23";
double scale = 1;
double penWidth = 0.7;
double zFeedRate = 50;
double zDown = 0;
static final double centreWidth = 0.9;
static double offsetX=0;
static double offsetY=0;
File inputTracksAndPads;
File inputDrill;
File outputGCodes;
Extruder pcbPen;
PolygonList penPaths;
GCodeReaderAndWriter gcode;
/**
* @param args
*/
public void pcb(File itp, File id, File og, Extruder pp)
{
inputTracksAndPads = itp;
inputDrill = id;
outputGCodes = og;
pcbPen = pp;
penWidth = pcbPen.getExtrusionSize();
Debug.d("Gerber RS274X to GCoder Converter for RepRap\n");
Debug.d("Input: " + inputTracksAndPads.getName());
Debug.d("Output: " + outputGCodes.getName()+"\n");
Debug.d("Pen Width: " + penWidth + " mm");
createBitmap();
penPaths = gerberGcode.getPolygons();
penPaths = penPaths.nearEnds(new Point2D(0, 0), true, 1.5*penWidth);
if(Preferences.simulate() && penPaths.size() > 0)
{
RrGraphics simulationPlot2 = new RrGraphics("PCB pen plotlines");
// if(currentPolygon != null)
// thePattern.add(new RrPolygon(currentPolygon));
simulationPlot2.init(penPaths.getBox(), false, "0");
simulationPlot2.add(penPaths);
}
writeGCodes();
Debug.d("GCode file generated succesfully !");
}
private void raisePen()
{
double zf = org.reprap.machines.GCodeRepRap.round(zFeedRate, 1);
double zu = org.reprap.machines.GCodeRepRap.round(pcbPen.getLift(), 1);
double xyf = org.reprap.machines.GCodeRepRap.round(pcbPen.getSlowXYFeedrate(), 1);
try {
gcode.queue("G1 F" + zf + "; Z feedrate");
gcode.queue("G1 Z" + zu + "; Z clearance height");
gcode.queue("G1 F" + xyf + "; XY feedrate");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void lowerPen()
{
double zf = org.reprap.machines.GCodeRepRap.round(zFeedRate, 1);
double zd = org.reprap.machines.GCodeRepRap.round(zDown, 1);
double xyf = org.reprap.machines.GCodeRepRap.round(pcbPen.getSlowXYFeedrate(), 1);
try {
gcode.queue("G1 F" + zf + "; Z feedrate");
gcode.queue("G1 Z" + zd + "; Z drawing height");
gcode.queue("G1 F" + xyf + "; XY feedrate");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void PCBHeader()
{
gcode.startRun();
try
{
gcode.queue("; PCB GCode generated by RepRap Java Host Software");
Date myDate = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd:HH-mm-ss");
String myDateString = sdf.format(myDate);
gcode.queue("; Created: " + myDateString);
gcode.queue("; Gerber tracks and pads file: " + inputTracksAndPads.getName());
gcode.queue("; Drill file: " + inputDrill.getName());
gcode.queue(";#!RECTANGLE: " + bigBox);
gcode.queue(";#!LAYER: 1/1");
gcode.queue("G21 ;metric");
gcode.queue("G90 ;absolute positioning");
gcode.queue("M140 S0.0 ;set bed temperature and return");
gcode.queue("T" + pcbPen.getPhysicalExtruderNumber() + "; select new extruder");
//gcode.queue("M113; set extruder to use pot for PWM");
gcode.queue("G28; go home");
gcode.queue("G92 E0 ;zero the extruded length");
raisePen();
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void PCBFooter()
{
try
{
gcode.queue("M0 ; stop RepRap");
} catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void polygonPlot(Polygon p)
{
if(p.size() <= 0)
return;
double x, y;
try
{
x = org.reprap.machines.GCodeRepRap.round(p.point(0).x(), 1);
y = org.reprap.machines.GCodeRepRap.round(p.point(0).y(), 1);
gcode.queue("G1 X" + x + " Y" + y + "; move to polygon start");
lowerPen();
for(int i = 1; i < p.size(); i++)
{
x = org.reprap.machines.GCodeRepRap.round(p.point(i).x(), 1);
y = org.reprap.machines.GCodeRepRap.round(p.point(i).y(), 1);
gcode.queue("G1 X" + x + " Y" + y + "; draw line");
}
x = org.reprap.machines.GCodeRepRap.round(p.point(0).x(), 1);
y = org.reprap.machines.GCodeRepRap.round(p.point(0).y(), 1);
gcode.queue("G1 X" + x + " Y" + y + "; draw back to polygon start");
} catch (Exception e) {
e.printStackTrace();
return;
}
raisePen();
}
private void writeGCodes()
{
try {
gcode = new GCodeReaderAndWriter(new PrintStream(outputGCodes));
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
PCBHeader();
for(int i = 0; i < penPaths.size(); i++)
polygonPlot(penPaths.polygon(i));
PCBFooter();
}
private void createBitmap()
{
gerberGcode = new GerberGCode(pcbPen, null, true);
bigBox = new Rectangle();
Rectangle r;
// processing Gerber file
try {
in = new BufferedReader(new FileReader(inputTracksAndPads));
while((line = in.readLine()) != null)
{
r = processLine(line, false);
if(r != null)
bigBox = Rectangle.union(bigBox, r);
}
in.close();
PCBOffsets.pcbo(bigBox);
offsetX = PCBOffsets.getXoff() - bigBox.sw().x();
offsetY = PCBOffsets.getYoff() - bigBox.sw().y();
bigBox = bigBox.translate(new Point2D(offsetX, offsetY));
in = new BufferedReader(new FileReader(inputTracksAndPads));
BooleanGrid pattern = new BooleanGrid(CSG2D.nothing(), bigBox, new Attributes(null, null, null, pcbPen.getAppearance()));
gerberGcode = new GerberGCode(pcbPen, pattern, true);
while((line = in.readLine()) != null)
{
processLine(line, false);
}
if(inputDrill != null)
{
in = new BufferedReader(new FileReader(inputDrill));
gerberGcode = new GerberGCode(pcbPen, pattern, false);
gerberGcode.addCircleAperture(-1, centreWidth); // Just mark drill centres with a disc
while((line = in.readLine()) != null)
{
processLine(line, true);
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private Rectangle processLine(String line, boolean drill)
{
Debug.d(line);
boolean drillDef = false;
Rectangle result = null;
if(drill)
{
formatX = "24";
formatY = "24";
}
if(line.startsWith("%FSLA"))
{
formatX = line.substring(6, 8);
formatY = line.substring(9, 11);
Debug.d("Format X: " + formatX + " Format Y: " + formatY);
}
else
if(line.startsWith("%ADD"))
{
String apertureNum, apertureType, apertureSize;
line = line.substring(4, line.length()-2);
apertureNum = line.substring(0, 2);
line = line.substring(2);
splitline = line.split(",");
apertureType = splitline[0];
apertureSize = splitline[1];
Debug.d("\n\nAparture: " + apertureNum);
Debug.d("Type: " + apertureType);
if(apertureType.equals("C"))
{
double s = scale*Double.parseDouble(apertureSize);
gerberGcode.addCircleAperture(Integer.parseInt(apertureNum), s);
Debug.d("Size: " + s + " mm");
}
else
if(apertureType.equals("R"))
{
String rectSides[] = apertureSize.split("X");
double x = scale*Double.parseDouble(rectSides[0]);
double y = scale*Double.parseDouble(rectSides[1]);
gerberGcode.addRectangleAperture(Integer.parseInt(apertureNum), x, y);
Debug.d("Size: " + x + "x" + y + "mm x mm");
}
else
if(apertureType.equals("OC8"))
{
gerberGcode.addCircleAperture(Integer.parseInt(apertureNum), scale*Double.parseDouble(apertureSize));
}
else
{
Debug.e(" [-] aparture type: " + apertureType + " not supported [" + line+"]\n");
//System.exit(-1);
}
} else
if(line.startsWith("T") && drill && line.length() > 3)
{
if(line.charAt(3) == 'C')
{
String apertureNum, apertureSize;
line = line.substring(1, line.length());
splitline = line.split("C");
apertureNum = splitline[0];
apertureSize = splitline[1];
Debug.d("\n\nDrill: " + apertureNum);
drillDef = true;
double s = scale*Double.parseDouble(apertureSize);
gerberGcode.addCircleAperture(Integer.parseInt(apertureNum), s);
Debug.d("Size: " + s + " mm");
}
}
else
if(line.startsWith("G90"))
{
gerberGcode.enableAbsolute();
Debug.d("Absolute coordinates");
}
else
if(line.startsWith("G91"))
{
gerberGcode.enableRelative();
Debug.d("Relative coordinates");
}
else
if(line.startsWith("G70") || (drill && line.startsWith("M72")))
{
scale = 25.4;
Debug.d("Inches");
}
else
if(line.startsWith("G71")|| (drill && line.startsWith("M71")))
{
scale = 1;
Debug.d("Metric");
}
else
if(line.startsWith("G54"))
{
if(drill)
{
gerberGcode.selectAperture(-1);
Debug.d("Drill centre selected.");
} else
{
int aperture;
aperture = Integer.valueOf(line.substring(4, line.length()-1).trim());
gerberGcode.selectAperture(aperture);
Debug.d("Apature: " + aperture + " selected.");
}
}
else
if(line.startsWith("X"))
{
double x, y;
int d;
if(drill)
{
d = 3;
line = line.substring(1);
splitline = line.split("Y");
while(splitline[0].length() < 6)
splitline[0] = "0" + splitline[0];
while(splitline[1].length() < 6)
splitline[1] = "0" + splitline[1];
} else
{
splitline[0] = line.substring(1, line.indexOf("Y"));
splitline[1] = line.substring(line.indexOf("Y")+1, line.indexOf("D"));
d = Integer.valueOf(line.substring(line.indexOf("D")+1, line.indexOf("D")+3));
}
int divFactorX = (int)Math.pow(10.0,Integer.parseInt(formatX.substring(1)));
int divFactorY = (int)Math.pow(10.0,Integer.parseInt(formatY.substring(1)));
x = scale*Double.valueOf(splitline[0])/divFactorX;
y = scale*Double.valueOf(splitline[1])/divFactorY;
x += offsetX;
y += offsetY;
Debug.d(" X: "+x+" Y:"+y+" D:"+d);
if(d==1)
{
result = gerberGcode.drawLine(new Point2D(x, y));
}
else
if(d==2)
{
gerberGcode.goTo(new Point2D(x, y));
}
else
if(d==3)
{
result = gerberGcode.exposePoint(new Point2D(x, y));
}
}
else
if(line.startsWith("D") || (line.startsWith("T") && drill && !drillDef))
{
if(drill)
{
gerberGcode.selectAperture(-1);
Debug.d("Drill centre selected.");
} else
{
int aperture;
aperture = Integer.valueOf(line.substring(1, 3));
gerberGcode.selectAperture(aperture);
Debug.d("Apature: " + aperture + " selected.");
}
}
return result;
}
}