/******************************************************************************* * This is part of SketchChair, an open-source tool for designing your own furniture. * www.sketchchair.cc * * Copyright (C) 2012, Diatom Studio ltd. Contact: hello@diatom.cc * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. ******************************************************************************/ package ShapePacking; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import nu.xom.Attribute; import nu.xom.Document; import nu.xom.Element; import nu.xom.Serializer; import cc.sketchchair.core.GLOBAL; import cc.sketchchair.core.LOGGER; import cc.sketchchair.core.SETTINGS; import cc.sketchchair.functions.functions; import cc.sketchchair.sketch.Sketch; import ToolPathWriter.CraftRoboWriter; import ToolPathWriter.DXFWriter; import processing.core.PApplet; import processing.core.PConstants; import processing.core.PFont; import processing.core.PGraphics; import processing.pdf.PGraphicsPDF; /** * Main class responsible for backing spOutlines on a page. * @author gregsaul * */ public class spShapePack { spShapes shapes = new spShapes(); public spPages pages = new spPages(); public float pdf_pixels_per_mm = 2.834658423659949f; public float dxf_pixels_per_mm = 1; public float plotter_pixels_per_mm = 20; float shape_scale = 1; float zoom = 1; float offsetX = 0; float offsetY = 0; boolean firstRender = true; // is this the first time we have rendered to the screen. public float materialWidth = 210;//mm public float materialHeight = 297;//mm float shapeGap = 2.5f; public float scale = 1; public float pdfScale = 1; private OutputStream out = null; private InputStream in = null; public float CAM_OFFSET_X = -500; public float CAM_OFFSET_Y = -500; public float ZOOM = 1; public float content_scale = 100; public boolean seperate_slots = false; public boolean addDogbones = false; public boolean add_guide_divets = false; public float inner_corner_radius = 5; private float textSize = 3.5f; public boolean autoPackPieces = false; public boolean addLabels = true; float minZoom = 0.1f; float maxZoom = 10.0f; float maxCamX = 10000; float minCamX = -10000; float maxCamY = 10000; float minCamY = -10000; public void add(spShape shape) { shape.shapePack = this; this.shapes.add(shape); } void addShape(spShape shape) { shape.shapePack = this; this.shapes.add(shape); } public void build() { this.pages.shapePack = this; if(this.autoPackPieces) this.pages.packShapesSmart(this.shapes); else this.pages.packShapesTile(this.shapes); } //This return the total height of the cutting sheet public float getHeight(){ return this.pages.getHeight(); } public void empty() { this.shapes.empty(); this.pages.empty(); } public ByteArrayOutputStream getDXFBuffered(PApplet a) { PGraphicsPDF pdf = (PGraphicsPDF) a.createGraphics( (int) (this.materialWidth), (int) (this.materialHeight), a.PDF); ByteArrayOutputStream out = new ByteArrayOutputStream(); pdf.setOutput(out); pdf.beginDraw(); //pdf.scale(pdf_pixels_per_mm ); pdf.strokeWeight(.0001f); pdf.stroke(255, 0, 0); //PFont font = a.createFont("Arial", 8); //pdf.textFont(font); this.pages.renderPDF(pdf, pdf_pixels_per_mm); pdf.dispose(); pdf.endDraw(); return out; } public ByteArrayOutputStream getPDFBuffered(PApplet a) { PGraphicsPDF pdf = (PGraphicsPDF) a.createGraphics( (int) (this.materialWidth), (int) (this.materialHeight), a.PDF); ByteArrayOutputStream out = new ByteArrayOutputStream(); pdf.setOutput(out); // pdf.textSize(this.textSize); pdf.beginDraw(); //pdf.scale(pdf_pixels_per_mm ); pdf.strokeWeight(.0001f); pdf.stroke(255, 0, 0); this.pages.renderPDF(pdf, pdf_pixels_per_mm); pdf.dispose(); pdf.endDraw(); return out; } public void makeDXF(PApplet a, String dxfSaveLocation) { a.textSize(this.textSize); DXFWriter dxf = new DXFWriter(dxfSaveLocation); //d.beginRaw(a.DXF, dxfSaveLocation); dxf.scale(dxf_pixels_per_mm); this.pages.renderToPlotter(dxf); dxf.close(); //dxf.endDraw(); } public void makePDF(PApplet a) { PGraphicsPDF pdf = (PGraphicsPDF) a.createGraphics( (int) (this.materialWidth), (int) (this.materialHeight), a.PDF, "C:\\MyMedia\\sketchChair\\pdfOutput\\output" + functions.getFileName() + ".pdf"); PFont font = a.createFont("Arial", this.textSize); pdf.textFont(font); pdf.textSize(this.textSize); pdf.beginDraw(); //pdf.scale(pdf_pixels_per_mm ); pdf.strokeWeight(.0001f); pdf.stroke(255, 0, 0); this.pages.renderPDF(pdf, pdf_pixels_per_mm); pdf.dispose(); pdf.endDraw(); } public void makePDF(PApplet a, String pdfSaveLocation) { PGraphicsPDF pdf = (PGraphicsPDF) a.createGraphics( (int) (this.materialWidth * pdf_pixels_per_mm), (int) (this.materialHeight * pdf_pixels_per_mm), PConstants.PDF, pdfSaveLocation); LOGGER.info("sending PDF to " + pdfSaveLocation); pdf.beginDraw(); //pdf.scale(pdf_pixels_per_mm); pdf.strokeWeight(.0001f); pdf.stroke(255, 0, 0); //PFont font = a.createFont("Arial", this.textSize); //pdf.textFont(font); pdf.textSize(this.textSize); this.pages.renderPDF(pdf, pdf_pixels_per_mm); pdf.dispose(); pdf.endDraw(); } public void makeSVG(PApplet a, String svgSaveLocation){ try { Element root = getSVG(a); Document doc = new Document(root); OutputStream outXML = new FileOutputStream(svgSaveLocation); outXML = new BufferedOutputStream(outXML); Serializer serializer = new Serializer(outXML, "ISO-8859-1"); serializer.write(doc); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } public Element getSVG(PApplet a){ Element patternInfo = new Element("skchptrn","http://www.sketchchair.cc/formats/skchptrn"); patternInfo.addAttribute(new Attribute("version","0.9")); patternInfo.addAttribute(new Attribute("width",materialWidth+"px")); patternInfo.addAttribute(new Attribute("height",materialHeight+"px")); patternInfo.addAttribute(new Attribute("scale",this.scale+"")); patternInfo.addAttribute(new Attribute("mm_px","1")); patternInfo.addAttribute(new Attribute("designID","0")); patternInfo.addAttribute(new Attribute("notes","")); patternInfo.addAttribute(new Attribute("materialWidth","")); patternInfo.addAttribute(new Attribute("dogbonesAdded","")); patternInfo.addAttribute(new Attribute("user","")); Element root = new Element("svg","http://www.w3.org/2000/svg"); root.appendChild(patternInfo); root.addAttribute(new Attribute("version","1.1")); root.addAttribute(new Attribute("width",materialWidth+"px")); root.addAttribute(new Attribute("height",materialHeight+"px")); root.addAttribute(new Attribute("style","fill:rgb(0,0,0)")); root.appendChild(this.pages.toXML()); return root; } public void printToCraftRobo() { String currentDir = new File(".").getAbsolutePath(); currentDir = currentDir.substring(0, currentDir.length() - 1); LOGGER.info("saving plt file to: " + currentDir + "temp.plt"); CraftRoboWriter craftRoboWriter = new CraftRoboWriter(currentDir + "temp.plt"); craftRoboWriter.setupDefault(); craftRoboWriter.setPenForce(30); craftRoboWriter.scale(plotter_pixels_per_mm); this.pages.renderToPlotter(craftRoboWriter); craftRoboWriter.close(); try { Runtime rt = Runtime.getRuntime(); Process p; String craftRoboPath = ""; String osName = System.getProperty("os.name"); if (osName.startsWith("Mac OS X")){ String[] cmd = {"/usr/bin/open", "-a" , "Cutting Master 2 for CraftROBO.app", "/Applications/Cutting Master 2 CraftROBO 1.86/Release/"}; p = rt.exec(cmd); }else{ craftRoboPath = "C:/Program Files/Cutting Master 2 for CraftROBO 1.60/Program/App2.exe"; p = rt.exec(craftRoboPath); } LOGGER.info("Running: " + craftRoboPath); // in = p.getInputStream(); if (in.available() > 0) System.out.println(in.toString()); out = p.getOutputStream(); InputStream err = p.getErrorStream(); //p.destroy() ; } catch (Exception exc) {/*handle exception*/ } } public void setupFirstRender(PGraphics g){ ZOOM = ( (float)g.height/this.materialHeight); this.CAM_OFFSET_X = (int) -(this.materialWidth/2.0f); this.CAM_OFFSET_Y = (int) -(this.materialHeight/2.0f); } public void render(PGraphics g) { if(firstRender) setupFirstRender(g);//if this is the first time we have rendered then setup the correct postion on the screen if(ZOOM < minZoom) ZOOM = minZoom; if(ZOOM > maxZoom) ZOOM = maxZoom; if(CAM_OFFSET_X > maxCamX) CAM_OFFSET_X = maxCamX; if(CAM_OFFSET_X < minCamX) CAM_OFFSET_X = minCamX; if(CAM_OFFSET_Y > maxCamY) CAM_OFFSET_Y = maxCamY; if(CAM_OFFSET_Y < minCamY) CAM_OFFSET_Y = minCamY; firstRender = false; g.textSize(this.textSize); g.fill(0); g.noStroke(); g.pushMatrix(); g.translate(g.width/2, g.height/2); g.scale(this.ZOOM); g.translate(this.CAM_OFFSET_X, this.CAM_OFFSET_Y); this.pages.render(g); g.popMatrix(); } public void renderPickBuffer(PGraphics pickBuffer) { firstRender = false; pickBuffer.noFill(); pickBuffer.stroke(0); pickBuffer.pushMatrix(); pickBuffer.scale(this.ZOOM); pickBuffer.translate(this.CAM_OFFSET_X, this.CAM_OFFSET_Y); this.pages.renderPickBuffer(pickBuffer); pickBuffer.popMatrix(); } public void renderList(PGraphics g) { g.textSize(this.textSize); g.noFill(); g.stroke(0); g.pushMatrix(); this.pages.renderList(g); g.popMatrix(); } public void scaleAll(float scale) { this.shapes.scale(scale); } public void renderPickBufferList(PGraphics pickBuffer) { this.pages.renderPickBufferList(pickBuffer); } public void zoomView(float _zoomDelta, float _mouseX, float _mouseY){ float deltaMouseXBefore = (float) (((GLOBAL.applet.width/2)-_mouseX)/this.ZOOM); float deltaMouseYBefore = (float) (((GLOBAL.applet.height/2)-_mouseY)/this.ZOOM); this.ZOOM -= _zoomDelta; if( (_zoomDelta > 0 && this.ZOOM < SETTINGS.MIN_ZOOM)){ // this.ZOOM = SETTINGS.MIN_ZOOM; } if(_zoomDelta < 0 && this.ZOOM > SETTINGS.MAX_ZOOM){ // this.ZOOM = SETTINGS.MAX_ZOOM; } float deltaMouseXAfter = (float) (((GLOBAL.applet.width/2)-_mouseX)/this.ZOOM); float deltaMouseYAfter = (float) (((GLOBAL.applet.height/2)-_mouseY)/this.ZOOM); float deltaMouseX = deltaMouseXAfter - deltaMouseXBefore; float deltaMouseY = deltaMouseYAfter - deltaMouseYBefore; moveView(-deltaMouseX,-deltaMouseY); } void moveView(float _deltaX, float _deltaY){ this.CAM_OFFSET_X += _deltaX; this.CAM_OFFSET_Y += _deltaY; float leftEdge = (float) (this.CAM_OFFSET_X - ((GLOBAL.applet.width/2)/this.ZOOM)); //if(leftEdge < SETTINGS.MIN_CAM_X_OFFSET) // this.CAM_OFFSET_X = SETTINGS.MIN_CAM_X_OFFSET + ((GLOBAL.applet.width/2)/this.ZOOM); float rightEdge = (float) (this.CAM_OFFSET_X + ((GLOBAL.applet.width/2)/this.ZOOM)); //if(rightEdge > SETTINGS.MAX_CAM_X_OFFSET) //this.CAM_OFFSET_X = SETTINGS.MAX_CAM_X_OFFSET - ((GLOBAL.applet.width/2)/this.ZOOM); double topEdge = (double) this.CAM_OFFSET_Y + ((GLOBAL.applet.height/2)/this.ZOOM); //if(topEdge > SETTINGS.MAX_CAM_Y_OFFSET) //this.CAM_OFFSET_Y = SETTINGS.MAX_CAM_Y_OFFSET - ((GLOBAL.applet.height/2)/this.ZOOM); float bottomEdge = (float) (GLOBAL.CAM_OFFSET_Y - ((GLOBAL.applet.height/2)/this.ZOOM)); //if(bottomEdge < SETTINGS.MIN_CAM_Y_OFFSET) //this.CAM_OFFSET_Y = SETTINGS.MIN_CAM_Y_OFFSET + ((GLOBAL.applet.height/2)/this.ZOOM); } }