robocut-1.0.8/0000755000175000017500000000000011621557774012602 5ustar markusmarkusrobocut-1.0.8/images/0000755000175000017500000000000011621557774014047 5ustar markusmarkusrobocut-1.0.8/images/cap-pen.png0000644000175000017500000000135711621557774016106 0ustar markusmarkusPNG  IHDR@@iqsRGBbKGD pHYs  tIME >:tEXtCommentThis drawing is: Copyright 2010 Markus Schulz and is licensed under the GPL version 3wIDATx9,DADK\jPjB\5vN\$JGei^?V76ےWx1p \<?q/i^owrm~Ϻm<``m{;Pe:~ /Nf4|> ,`%bx0@B2Vf_*~T1͢Rio{?$qk_ߔfQh?K̆P"iI7@4x@ Hw+(1J,1VoPb<`F݈* v5ශBidK̜P' ^埮Ʋ>_W sI_/^C%jx\(EpU_Xb2aHƟ&#bXZІHa M%Ǫ#K:6`tpVLˤ n6xIENDB`robocut-1.0.8/images/cap-red.png0000644000175000017500000000121011621557774016062 0ustar markusmarkusPNG  IHDR@@iqsRGBbKGD pHYs  tIME ;tEXtCommentThis drawing is: Copyright 2010 Markus Schulz and is licensed under the GPL version 3w}IDATxX10XExGAI#((yD@S(ie+"Rw1#ȓ]ݳk`G`.΃^sJr9OK8--b T)}[@TAAS Y`~nP[Y~~y 4 CP’Ò_d,60*)@m4XK,@]-,@' LV+pN'`n_ #-;bˑ,1ҍȲ@AV@4R=xO1 8RX0 O焾ﻏW@CrYje}ꍘ&Të`0 )soIENDB`robocut-1.0.8/images/robocut.xcf0000644000175000017500000000175311621557774016234 0ustar markusmarkusgimp xcf file BBgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches)   New Layer     1 E U    J       x x x x x xHJ       x x x x x xHR    eeee eeee  x x x x x xH%@robocut-1.0.8/images/cap.xcf0000644000175000017500000000546011621557774015321 0ustar markusmarkusgimp xcf file@@BB gimp-commentyThis drawing is: Copyright © 2010 Markus Schulz and is licensed under the GPL version 3gimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) @@ New Layer#2      X@@@@ 2 2 2 2 2 2 2 @@ New Layer     M@@@@F Ж$ љ$ ԛ$ ՝$ ֞$ ٟ$ ١$ ۣ$ ݤ$ ߦ$ ਈ$ ᩈ$ 㪈$ 䭈$ 殈$R И И љ ԛ ՝ ֞ ٟ ١ ۣ ݤ ߦ ਈ ᩈ 㪈 䭈 殈bЌ*ҍ*Ց*֓*ٔ*ڗ*ܘ*ߛ**➈*䡈*ޕ19:;<=>F Ж$ љ$ ԛ$ ՝$ ֞$ ؟$ ڡ$ ۣ$ ܤ$ ߦ$ ৈ$ ᩈ$ 䪈$ 嬈$ 歈$R И И љ ԛ ՝ ֞ ؟ ڡ ۣ ܤ ߦ ৈ ᩈ 䪈 嬈 歈bЌ*ҍ*Ց*֓*ؔ*ۗ*ܘ*ߛ**㞈*塈*ߕ19:;<=>F і$ ҙ$ ӛ$ ՜$ ֝$ ؠ$ ١$ ܣ$ ܥ$ ަ$ ਈ$ ᩈ$ 㪈$ 䬈$ 殈$R ј ј ҙ ӛ ՜ ֝ ؠ ١ ܣ ܥ ަ ਈ ᩈ 㪈 䬈 殈bь*ҍ*Ԑ*֒*ؕ*ږ*ܙ*ޛ**➈*䠈*鰈19:;<=>F3 3 3 3 3 3 3 3 3 3 3 3 3 3 3R$$$$$$$$$$$$$$$$b***********19:;<=>robocut-1.0.8/images/cap-blue.png0000644000175000017500000000130411621557774016243 0ustar markusmarkusPNG  IHDR@@iqsRGBbKGD pHYs  tIME  ʔqtEXtCommentThis drawing is: Copyright 2010 Markus Schulz and is licensed under the GPL version 3wIDATxX1N@φPTTQPP"$~BI("Q La[NŖG3( `d~88<8?;`C/ٷj`eV `s@YUkG TbCp!h0Tt= `ۏAz LW}6ڦ+^g~p LeIPR(K˒$PX@lP( AeI={YB s.Kh,,![,٥B'l*LKa vs@c z@ߓHD#R堀a7p P_j\h|Z 瀲J\.8S wj29{QwBUU+ G" r QObn BP( yrFbIENDB`robocut-1.0.8/images/robocut.xpm0000644000175000017500000000245511621557774016260 0ustar markusmarkus/* XPM */ static char * robocut_xpm[] = { "32 32 8 1", " c None", ". c #FF0000", "+ c #0004FF", "@ c #F7FF00", "# c #000000", "$ c #FFFFFF", "% c #FFA165", "& c #787878", " ", " ", " ", " ", " ..... +++++ @@@@@ # ", " ... +++ @@@ # ", " . + @ # ", " # ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " $$$$$$$$$$$$$$$$$$$$$$######## ", " $$$$$$$$$$$$$$$$$$$$$$######## ", " $$$$$$$$$$$$$$$$$$$$$$######## ", " $$$$$$$$$$$$$$$$$$$$$$######## ", " $$$$$$$%$$%$%$%$$$$$$$######## ", " $$$$$$%$%$$%$$%$$$$$$$######## ", " $$$$$$$$$$$$$$$$$$$$$$######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " &&&&&&&&&&&&&&&&&&&&&&######## ", " ", " "}; robocut-1.0.8/images/icon.png0000644000175000017500000000042511621557774015506 0ustar markusmarkusPNG  IHDR szzsRGBbKGD pHYs  tIME 56IDATX 0g}<azhL̡B~v Ktsu"Hrq/,ؤ^!"D&LīJTMT%2n/͈ORL ̏r}5~>[ -l H)u 'Y[IENDB`robocut-1.0.8/images/cap-yellow.png0000644000175000017500000000116311621557774016632 0ustar markusmarkusPNG  IHDR@@iqsRGBbKGD pHYs  tIME *AtEXtCommentThis drawing is: Copyright 2010 Markus Schulz and is licensed under the GPL version 3whIDATxX1N0[ExGAy=G<EYDrBNnv$WQy2 to^{ٳo=-+(S?-KyYYYEU7 de t (z 6-PT-{@׼t]V {yL-sBeÒ4 `VVXR_EaImP [Z j^ L_{#S[uakg%FQcƟ HrdEPȑUjQŀԞa؜O7C.0 }FVp;@ /a{m&IENDB`robocut-1.0.8/images/pen.xcf0000644000175000017500000000220011621557774015325 0ustar markusmarkusgimp xcf file@@BBG gimp-commentCreated with GIMPgimp-image-grid(style solid) (fgcolor (color-rgba 0.000000 0.000000 0.000000 1.000000)) (bgcolor (color-rgba 1.000000 1.000000 1.000000 1.000000)) (xspacing 10.000000) (yspacing 10.000000) (spacing-unit inches) (xoffset 0.000000) (yoffset 0.000000) (offset-unit inches) @@ New Layer     \@@p@@ ;:J8;5%3e1 c/< #- +)WH&$0#sJ! !Io",!$"dS!!<}"9!!Va!!!/"rF!!Ho"-!#"cT!!;~"s9#<%b'"')G**p+.,- T. /G0:{robocut-1.0.8/MainWindow.cpp0000644000175000017500000002454111621557774015370 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "MainWindow.h" #include "ui_MainWindow.h" #include "PathPaintPage.h" #include "Plotter.h" #include "ProgramOptions.h" #include "CuttingDialog.h" #include "PathSorter.h" #include #include #include #include #include #include #include #include #include #include #include #include using namespace std; const double InitialZoom = 2.0; MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); scene = new QGraphicsScene(this); ui->graphicsView->setScene(scene); ui->graphicsView->scale(InitialZoom, InitialZoom); ui->graphicsView->viewport()->installEventFilter(this); cutDialog = NULL; animationTimer = new QTimer(this); connect(animationTimer, SIGNAL(timeout()), SLOT(animate())); cutMarker = NULL; // Alternative zoom shortcuts QShortcut* zoom_in = new QShortcut(QKeySequence("X"), this); connect(zoom_in, SIGNAL(activated()), SLOT(on_actionZoom_In_triggered())); QShortcut* zoom_out = new QShortcut(QKeySequence("Z"), this); connect(zoom_out, SIGNAL(activated()), SLOT(on_actionZoom_Out_triggered())); //default options if not specified on command line this->show(); filename = ProgramOptions::Instance().getFileName(); if(QFile::exists(filename)) loadFile(); if(ProgramOptions::Instance().getStartCut() == true) on_actionCut_triggered(); sortFlag = ProgramOptions::Instance().getSortPath(); cout << ProgramOptions::Instance().getVersion().toStdString() << endl; } MainWindow::~MainWindow() { delete ui; } void MainWindow::on_actionOpen_triggered() { if (lastOpenDir.isEmpty()) lastOpenDir = QDir::homePath(); filename = QFileDialog::getOpenFileName(this, tr("Open File"), lastOpenDir, tr("SVG Files (*.svg)")); if (filename.isEmpty()) return; lastOpenDir = QFileInfo(filename).absoluteDir().path(); loadFile(); } void MainWindow::loadFile() { if (filename.isEmpty()) return; qDebug() << "Reading file: " << filename; QSvgRenderer rend; if (!rend.load(filename)) { QMessageBox::critical(this, "Error loading file.", "Couldn't open the file for reading."); qDebug() << "Error loading svg."; return; } qDebug() << "SVG default size: " << rend.defaultSize() << endl; qDebug() << "SVG view box: " << rend.viewBoxF() << endl; // Geqt size from SVG. TODO: Sanity check. // Also TODO: This won't handle offset viewboxes... need to get the offset and subtract it from // all the objects. mediaSize = rend.viewBoxF().size() * 25.4 / 90.0; double ppm = 90.0/25.4; // Pixels per mm. qDebug() << "Page size (mm): " << mediaSize << endl; PathPaintDevice pg(mediaSize.width(), mediaSize.height(), ppm); QPainter p(&pg); rend.render(&p); PathSorter pathsort(pg.paths(), mediaSize.height()); paths = pathsort.UnSort(); //paths = pathsort.Sort(); //paths = pathsort.TspSort(); //paths = pathsort.GroupTSP(); if(!ProgramOptions::Instance().getSortPath() == true)paths = pathsort.BestSort(); if(ProgramOptions::Instance().getTspSortPath() == true)paths = pathsort.BbSort(paths); scene->clear(); scene->setBackgroundBrush(QBrush(Qt::lightGray)); // The page. scene->addRect(0.0, 0.0, mediaSize.width(), mediaSize.height(), QPen(), QBrush(Qt::white)); QPen pen; pen.setWidthF(0.0); for (int i = 0, ii = 50, iii=0; i < paths.size(); ++i,ii+=10) { switch (iii) { case 0: pen.setColor(QColor(ii, ii, ii)); break; case 1: pen.setColor(QColor(ii, 0, 0)); break; case 2: pen.setColor(QColor(0, ii, 0)); break; case 3: pen.setColor(QColor(0, 0, ii)); break; case 4: pen.setColor(QColor(ii, ii, 0)); break; case 5: pen.setColor(QColor(ii, 0, ii)); break; case 6: pen.setColor(QColor(0, ii, ii)); break; } QPainterPath path; path.addPolygon(paths[i]); scene->addPath(path, pen); if(ii >= 200) { ii = 50; iii++; if(iii >=7)iii=0; } } // Handle the animation. I.e. stop it. // The old one was deleted when we cleared the scene. cutMarker = scene->addEllipse(-1.0, -1.0, 2.0, 2.0, QPen(Qt::black), QBrush(Qt::red)); cutMarker->hide(); ui->actionAnimate->setChecked(false); // Reset the viewport. on_actionReset_triggered(); // Redraw. Probably not necessary. update(); if (pg.clipped()) QMessageBox::warning(this, "Paths clipped", "BIG FAT WARNING!

Some paths lay outside the 210×297 mm A4 area. These have been squeezed back onto the page in a most ugly fashion, so cutting will almost certainly not do what you want."); // Change window title and enable menu items. setFileLoaded(filename); } void MainWindow::on_actionAbout_triggered() { QString message = "" + ProgramOptions::Instance().getVersion() + "

By Tim Hutt, © 2010

Parts of the source by Markus Schulz, © 2010

This software allows you to read a vector image in SVG format, and send it to a Graphtec Craft Robo 2 (or possibly 3) for cutting. It is designed to work with SVGs produced by the excellent free vector graphics editor Inkscape. It may work with other software but this has not been tested.

See the online manual for instructions."; QMessageBox::information(this, "About", message); } void MainWindow::on_actionExit_triggered() { close(); } void MainWindow::on_actionCut_triggered() { if (!cutDialog) cutDialog = new CutDialog(this); if (cutDialog->exec() != QDialog::Accepted) return; // Create a new dialog and run the actual cutting in a different thread. CuttingDialog* cuttingDlg = new CuttingDialog(this); cuttingDlg->startCut(paths, mediaSize.width(), mediaSize.height(), cutDialog->media(), cutDialog->speed(), cutDialog->pressure(), cutDialog->trackEnhancing(), cutDialog->regMark(), cutDialog->regSearch(), cutDialog->regWidth(), cutDialog->regHeight()); cuttingDlg->show(); } void MainWindow::on_actionManual_triggered() { QMessageBox::information(this, "Manual", "An online manual is available at

http://concentriclivers.com/"); } void MainWindow::on_actionAnimate_toggled(bool animate) { if (animate) { animationTimer->start(30); if (cutMarker) { cutMarker->setPos(0, 0); cutMarker->show(); } cutMarkerPath = 0; cutMarkerLine = 0; cutMarkerDistance = 0.0; } else { animationTimer->stop(); if (cutMarker) cutMarker->hide(); } } void MainWindow::on_actionReset_triggered() { ui->graphicsView->resetTransform(); ui->graphicsView->scale(InitialZoom, InitialZoom); } void MainWindow::on_actionZoom_In_triggered() { ui->graphicsView->scale(1.2, 1.2); } void MainWindow::on_actionZoom_Out_triggered() { ui->graphicsView->scale(1.0/1.2, 1.0/1.2); } void MainWindow::animate() { if (!cutMarker) return; // Make sure the current position is sane. if (cutMarkerPath >= paths.size() || cutMarkerLine >= paths[cutMarkerPath].size()) { // If not, reset it. cutMarkerPath = 0; cutMarkerLine = 0; cutMarkerDistance = 0.0; return; } // Get the ends of the segment/edge we are currently on. QPointF a = paths[cutMarkerPath][cutMarkerLine]; QPointF b; if (cutMarkerLine == paths[cutMarkerPath].size()-1) { // We are moving between paths, and not cutting. b = paths[(cutMarkerPath+1) % paths.size()][0]; cutMarker->setOpacity(0.2); } else { // We are cutting on a path. b = paths[cutMarkerPath][cutMarkerLine+1]; cutMarker->setOpacity(1.0); } QPointF r = b-a; double h = hypot(r.x(), r.y()); if (h > 0.0) r /= h; // The current position of the marker. QPointF p = a + r * cutMarkerDistance; cutMarker->setPos(p); // Advance the position of the marker for the next time this function is called. cutMarkerDistance += 2.0; if (cutMarkerDistance > h) { cutMarkerDistance = 0.0; if (++cutMarkerLine >= paths[cutMarkerPath].size()) { cutMarkerLine = 0; if (++cutMarkerPath >= paths.size()) { cutMarkerPath = 0; // Also stop the animation... ui->actionAnimate->setChecked(false); } } } } void MainWindow::setFileLoaded(QString filename) { bool e = !filename.isEmpty(); if (e) setWindowTitle("Robocut - " + filename); else setWindowTitle("Robocut"); ui->actionAnimate->setEnabled(e); ui->actionReset->setEnabled(e); ui->actionZoom_In->setEnabled(e); ui->actionZoom_Out->setEnabled(e); ui->actionCut->setEnabled(e); } bool MainWindow::eventFilter(QObject *o, QEvent *e) { if (o == ui->graphicsView->viewport()) { if (e->type() == QEvent::Wheel) { QWheelEvent *w = dynamic_cast(e); if(w->delta() <= 0) on_actionZoom_In_triggered(); else on_actionZoom_Out_triggered(); return true; } } return false; } robocut-1.0.8/manfile.txt0000644000175000017500000000037011621557774014756 0ustar markusmarkus[ENVIRONMENT] QT SVG only supports the SVG 1.2 Tiny standard and this has a limited SVG support. For example multiline text is something that is no supported by Robocut, however you can export your text to a path or just create each line separate. robocut-1.0.8/CuttingThread.h0000644000175000017500000000535111621557774015524 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once #include #include // A thread to send the cutting stuff to the plotter. // To use: // // 1. Create. // 2. Connect success() and error() to your class. Only one is called. // 3. Call setParams(...) with the parameters you want. // 4. Call start(). // 5. Wait for success() or error(). class CuttingThread : public QThread { Q_OBJECT public: explicit CuttingThread(QObject *parent = 0); // Set the parameters to use for the cut. void setParams(QList cuts, double mediawidth, double mediaheight, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, float regwidth, float reglength); signals: // Emitted if the cutting was (as far as we can tell) successful. void success(); // Emitted if the cutting failed. void error(QString message); public slots: protected: // This reads the params, then tries to send the data to the cutter. // When it is done, it runs exec() to send the success() or error() signal. void run(); private: QList _cuts; double _mediawidth; double _mediaheight; int _media; int _speed; int _pressure; bool _trackenhancing; bool _regmark; bool _regsearch; double _regwidth; double _reglength; }; robocut-1.0.8/PathPaintPage.h0000644000175000017500000000526711621557774015452 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once // TODO: Rename this file to PathPaintDevice.h #include #include #include #include class PathPaintEngine; // Needed for QSet. Simply concatenates all the coordinates in a QByteArray and hashes that. uint qHash(const QPolygonF& key); class PathPaintDevice : public QPaintDevice { public: PathPaintDevice(double widthInMm, double heightInMm, double pixelsPerMm = 90.0/25.4); ~PathPaintDevice(); // Adds a path to the device. // Also automatically ignores duplicate paths, which QSvgPainter creates (I guess for the fill and stroke). // Paths are clipped (horribly) to the page. And if any are clipped, clipped() returns true. void addPath(const QPolygonF& path); // Get a list of paths. QList paths(); // Returns true if any paths had to be clipped. bool clipped() const; QPaintEngine* paintEngine() const; protected: int metric(PaintDeviceMetric metric) const; private: mutable PathPaintEngine* engine; // The paths added. QList pagePaths; // Set of paths, so we can detect duplicates. QSet pagePathSet; bool pathsClipped; double width; double height; double ppm; }; robocut-1.0.8/PathPaintEngine.cpp0000644000175000017500000001327111621557774016330 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PathPaintEngine.h" #include #include PathPaintEngine::PathPaintEngine(QPaintDevice* pdev) : QPaintEngine(AllFeatures) { dev = dynamic_cast(pdev); if (!dev) qWarning("PathPaintEngine: unsupported target device."); } bool PathPaintEngine::begin(QPaintDevice* pdev) { dev = dynamic_cast(pdev); if (!dev) qWarning("PathPaintEngine: unsupported target device."); // TODO: setActive? return true; } bool approximatelyEqual(qreal a, qreal b, qreal epsilon) { return fabs(a - b) <= ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool essentiallyEqual(qreal a, qreal b, qreal epsilon) { return fabs(a - b) <= ( (fabs(a) > fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool definitelyGreaterThan(qreal a, qreal b, qreal epsilon) { return (a - b) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } bool definitelyLessThan(qreal a, qreal b, qreal epsilon) { return (b - a) > ( (fabs(a) < fabs(b) ? fabs(b) : fabs(a)) * epsilon); } void PathPaintEngine::drawPath(const QPainterPath& path) { if (!dev) return; if(!isCosmetic) { QList polys = path.toSubpathPolygons(); for (int i = 0; i < polys.size(); ++i) { if(dashPattern.empty()) dev->addPath(transform.map(polys[i])); else { QPolygonF polytemp = transform.map(polys[i]), newpoly; int dashtoggle = 1, dashi=0, j = 0; qreal actualdashsize = dashPattern[dashi]; QPointF origin = QPointF(polytemp[j]), testp; j++; do { newpoly = QPolygonF(); newpoly.append(origin); do { testp = polytemp[j]; origin = QPointF(getPointAtLenght(QPointF(origin), polytemp[j], actualdashsize)); if (essentiallyEqual(origin.x(), polytemp[j].x(), 0.01 ) && approximatelyEqual(origin.y(), polytemp[j].y(),0.01) && j+1 < polytemp.size()) { origin = polytemp[j]; int tempz = polytemp.size(); j++; testp = polytemp[j]; } newpoly.append(origin); }while(definitelyGreaterThan(actualdashsize,0.0,0.1) && testp!=origin); if(dashtoggle == 1) { dev->addPath(newpoly); } dashtoggle = dashtoggle * -1; dashi++; if(dashi >= dashPattern.size()) dashi=0; actualdashsize = dashPattern[dashi]; }while(!essentiallyEqual(origin.x(), polytemp[j].x(), 0.001 ) || !essentiallyEqual(origin.y(), polytemp[j].y(),0.001)); } } } } void PathPaintEngine::drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr) { // Nop. } void PathPaintEngine::drawPolygon(const QPointF* points, int pointCount, PolygonDrawMode mode) { if (!dev) return; QPolygonF p; for (int i = 0; i < pointCount; ++i) p.append(points[i]); dev->addPath(transform.map(p)); } bool PathPaintEngine::end() { if (!dev) return false; return true; } QPaintEngine::Type PathPaintEngine::type() const { return QPaintEngine::User; } void PathPaintEngine::updateState(const QPaintEngineState& state) { if (state.state() & DirtyTransform) transform = state.transform(); dashPattern = state.pen().dashPattern(); isCosmetic = state.pen().isCosmetic(); } qreal PathPaintEngine::getDistance(const QPointF &p1, const QPointF &p2) { qreal testx1 = p1.x(); qreal testy1 = p1.y(); qreal testx2 = p2.x(); qreal testy2 = p2.y(); qreal a = 0.0; qreal b = 0.0; double c = 0.0; if(testx1 >= testx2) a = testx1 - testx2; else a = testx2 - testx1; if(testy1 >= testy2) b = testy1 - testy2; else b = testy2 - testy1; c = sqrt((double)(a*a+b*b)); return (qreal) c; } QPointF PathPaintEngine::getPointAtLenght(const QPointF &p1, const QPointF &p2, qreal &l1) { qreal testx1 = p1.x(); qreal testy1 = p1.y(); qreal testx2 = p2.x(); qreal testy2 = p2.y(); qreal lenghtp1p2 = getDistance(p1,p2); qreal lenghtdash = l1; l1 = lenghtp1p2 - lenghtdash; if (definitelyLessThan(lenghtp1p2, lenghtdash, 0.01)) { l1 = lenghtdash - lenghtp1p2; return p2; } if (definitelyGreaterThan(lenghtdash, lenghtp1p2, 0.01)) { l1 = lenghtdash - lenghtp1p2; return p1; } l1 = 0; qreal factor = lenghtp1p2/lenghtdash; qreal a = testx1-testx2; qreal b = testy1-testy2; qreal aa = a/factor; qreal bb = b/factor; QPointF ret = QPointF(testx1-aa,testy1-bb); return ret; } robocut-1.0.8/main.cpp0000644000175000017500000000423311621557774014234 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include #include "MainWindow.h" #include "ProgramOptions.h" #include #include using namespace std; int main(int argc, char *argv[]) { ProgramOptions::Instance().setVersion("Robocut V1.0.8"); // would be nice if this could be imported from qmake ProgramOptions::Instance().GetOpt(argc, argv); int err = libusb_init(NULL); if (err != LIBUSB_SUCCESS) { cerr << "Error initialising usb library." << endl; return 1; } int ret = 0; // Code block to ensure usb devices are closed. Maybe. { QApplication a(argc, argv); MainWindow w; ret = a.exec(); } libusb_exit(NULL); return ret; } robocut-1.0.8/PathPaintEngine.h0000644000175000017500000000467011621557774016000 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once #include #include #include #include "PathPaintPage.h" // This is a simple paint engine that records all the paths painted. // It is used with QSvgPainter to record the paths in an SVG. // The only device it can draw to is PathPaintDevice class PathPaintEngine : public QPaintEngine { public: PathPaintEngine(QPaintDevice* pdev); bool begin(QPaintDevice* pdev); void drawPath(const QPainterPath& path); void drawPixmap(const QRectF& r, const QPixmap& pm, const QRectF& sr); void drawPolygon(const QPointF* points, int pointCount, PolygonDrawMode mode); bool end(); Type type() const; void updateState(const QPaintEngineState& state); private: PathPaintDevice* dev; QTransform transform; QVector dashPattern; bool isCosmetic; qreal getDistance(const QPointF &p1, const QPointF &p2); QPointF getPointAtLenght(const QPointF &p1, const QPointF &p2, qreal &l1); }; robocut-1.0.8/PathSorter.h0000644000175000017500000000530711621557774015053 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PATHSORTER_H #define PATHSORTER_H #include class PathSorter { public: PathSorter( ); PathSorter(const QList inpaths, qreal mediaheight); virtual ~PathSorter( ); void getQList (const QList inpaths); QList Sort (const QList inpaths); QList Sort () {return Sort(pathToSort);}; QList UnSort (const QList inpaths); QList UnSort () {return UnSort(pathToSort);}; QList BestSort (const QList inpaths); QList BestSort () {return BestSort(pathToSort);}; QList GroupTSP(const QList inpaths1, int groups = 3); QList GroupTSP(int groups = 3) {return GroupTSP(pathToSort, groups);}; QList BbSort (const QList inpaths); QList BbSort () {return BbSort(pathToSort);}; void setMediaHeight(qreal mediaheight); private: QList pathToSort; qreal mediaHeight; protected: private: QList MyFakeTSP(const QList inpaths); qreal getDistance(const QPolygonF &p1, const QPolygonF &p2); qreal getTotalDistance(const QList inpaths, int maxdepth = 0); static bool MyLessThan(const QPolygonF &p1, const QPolygonF &p2); }; #endif // PATHSORTER_H robocut-1.0.8/Plotter.h0000755000175000017500000000500311621557774014405 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once #include #include #include "Common.h" using namespace std; // Perform the cut. Returns error state. Note that this just sends the data, it has no way of knowing whether it really // worked and there is no easy way to cancel it. // // media: The type of media. I'm not sure what this effects, see CuttingDialog.cpp/ui for values. 300 is "custom". // The value is not fully checked for sanity. // speed: Cutting speed: 1-10 inclusive. // pressure: Cutting pressure: 1-33 inclusive. // trackenhancing: Supposed to feed/unfeed the media a few times to create tracks. // regmark: Whether to use registration marks for calibration. // regsearch: ? // regwidth/height: Distance between the registration marks. // // TODO: Apparently you can change the number of registration marks? Error Cut(QList cuts, double mediawidth, double mediaheight, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, double regwidth, double reglength); robocut-1.0.8/NoCopy.h0000755000175000017500000000315211621557774014166 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once class NoCopy { public: NoCopy() { } ~NoCopy() { } private: NoCopy(const NoCopy&); const NoCopy& operator=(const NoCopy&); }; #define NOCOPY NoCopy nocopyvar robocut-1.0.8/Common.h0000755000175000017500000000636011621557774014213 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once /// Result Class #include #include #include #include #include using std::vector; using std::string; typedef string::size_type stringpos; /// Error Handling class Error { public: explicit Error(bool S) : s(S) { } explicit Error(const char* C) : s(false), m(C) { } Error(const string& msg) : s(false), m(msg) { } operator bool() { return s; } // TODO: Use bool hack from boost so int i = Error(); doesn't work. string message() { if (m.empty()) return "Unspecified Error"; return m; } private: bool s; string m; }; const Error Success(true); const Error Failure(false); /** Integer to string. */ inline string ItoS(int I) { std::stringstream S; S << I; return S.str(); } /** Unsigned integer to string. */ inline string UItoS(unsigned int I) { std::stringstream S; S << I; return S.str(); } /** Unsigned long long to string. */ inline string ULLtoS(unsigned long long I) { char out[128]; sprintf(out, "%lld", I); return out; } /** String to integer, returns Fail on fail. */ inline int StoI(const string& S, int Fail = 0) { char* EP; const char* P = S.c_str(); int R = strtol(P, &EP, 0); if (EP == P) return Fail; return R; } /** String to unsigned integer, returns Fail on fail. */ inline unsigned int StoUI(const string& S, unsigned int Fail = 0) { char* EP; const char* P = S.c_str(); int R = strtoul(P, &EP, 0); if (EP == P) return Fail; return R; } /** String to unsigned integer, returns Fail on fail. */ inline unsigned int StoULL(const string& S, unsigned long long Fail = 0) { char* EP; const char* P = S.c_str(); int R = strtoull(P, &EP, 0); if (EP == P) return Fail; return R; } /** Get an environmental variable. */ inline string GetEnv(const string& Var) { char* V = getenv(Var.c_str()); if (!V) return ""; return V; } robocut-1.0.8/Common.cpp0000644000175000017500000000271511621557774014543 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Common.h" robocut-1.0.8/CutDialog.ui0000644000175000017500000004202211621557774015014 0ustar markusmarkus CutDialog 0 0 482 340 Cut Robocut Media: Card without Craft Paper Backing :/images/cap-yellow.png:/images/cap-yellow.png Card with Craft Paper Backing :/images/cap-yellow.png:/images/cap-yellow.png Vinyl Sticker :/images/cap-blue.png:/images/cap-blue.png Film Labels :/images/cap-blue.png:/images/cap-blue.png Thick Media :/images/cap-yellow.png:/images/cap-yellow.png Thin Media :/images/cap-blue.png:/images/cap-blue.png Pen :/images/cap-pen.png:/images/cap-pen.png Bond Paper 13-28 lbs :/images/cap-blue.png:/images/cap-blue.png Bristol Paper 57-67 lbs :/images/cap-yellow.png:/images/cap-yellow.png Cardstock 40-60 lbs :/images/cap-yellow.png:/images/cap-yellow.png Cover 40-60 lbs :/images/cap-yellow.png:/images/cap-yellow.png Film, Double Matte Translucent :/images/cap-blue.png:/images/cap-blue.png Film, Vinyl With Adhesive Back :/images/cap-blue.png:/images/cap-blue.png Film, Window With Kling Adhesive :/images/cap-blue.png:/images/cap-blue.png Index 90 lbs :/images/cap-red.png:/images/cap-red.png Inkjet Photo Paper 28-44 lbs :/images/cap-yellow.png:/images/cap-yellow.png Inkjet Photo Paper 45-75 lbs :/images/cap-red.png:/images/cap-red.png Magnetic Sheet :/images/cap-red.png:/images/cap-red.png Offset 24-60 lbs :/images/cap-blue.png:/images/cap-blue.png Print Paper Light Weight :/images/cap-blue.png:/images/cap-blue.png Print Paper Medium Weight :/images/cap-yellow.png:/images/cap-yellow.png Sticker Sheet :/images/cap-blue.png:/images/cap-blue.png Tag 100 lbs :/images/cap-red.png:/images/cap-red.png Text Paper 24-70 lbs :/images/cap-blue.png:/images/cap-blue.png Vellum Bristol 57-67 lbs :/images/cap-yellow.png:/images/cap-yellow.png Writing Paper 24-70 lbs :/images/cap-blue.png:/images/cap-blue.png Speed: 1 10 2 Qt::Horizontal Pressure: 1 33 2 Qt::Horizontal Track Enhancing 1 10 1 33 Registration Marks (Experimental!) true false Search Registration Marks true Dimensions (width × height): 0 0 188 0 mm 300.000000000000000 180.000000000000000 × 0 0 188 0 mm 1000.000000000000000 240.000000000000000 Qt::Vertical 20 0 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok buttonBox accepted() CutDialog accept() 257 156 157 274 buttonBox rejected() CutDialog reject() 325 156 286 274 mediaCombo currentIndexChanged(int) CutDialog onMediaChanged(int) 123 29 44 105 speedSlider valueChanged(int) speedSpinBox setValue(int) 246 81 434 81 speedSpinBox valueChanged(int) speedSlider setValue(int) 434 81 246 81 pressureSlider valueChanged(int) pressureSpinBox setValue(int) 246 116 434 116 pressureSpinBox valueChanged(int) pressureSlider setValue(int) 434 116 246 116 onMediaChanged(int) robocut-1.0.8/install.txt0000644000175000017500000000132711621557774015014 0ustar markusmarkusINSTALLATION ^^^^^^^^^^^^ sudo apt-get install libqt4-dev libusb-1.0-0-dev git-core # Go to home directory (or wherever you want to install it) cd ~ # Get the latest source code (if you don't already have it) git clone git://gitorious.org/robocut/robocut.git # Go into the source code directory. cd robocut # Build the project. qmake make # At this point the executable is built, and you can just link to it if you like, or you can install it # system-wide like this: sudo cp Robocut /usr/local/bin # Then create a link in your menu to /usr/local/bin/Robocut (not capital R) # Finally remember to make sure you are in the lp group: adduser lp # You will probably have to log out and log in again after that. robocut-1.0.8/CutDialog.cpp0000644000175000017500000000765511621557774015176 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "CutDialog.h" #include "ui_CutDialog.h" #include "ProgramOptions.h" CutDialog::CutDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CutDialog) { ui->setupUi(this); ui->mediaCombo->setCurrentIndex(ProgramOptions::Instance().getMedia()); ui->speedSlider->setValue(ProgramOptions::Instance().getSpeed()); ui->pressureSlider->setValue(ProgramOptions::Instance().getPressure()); ui->trackEnhancingCheckbox->setChecked(ProgramOptions::Instance().getTrackEnhancing()); if(ProgramOptions::Instance().getRegMark()) { ui->regMarksGroup->setChecked(true); ui->regSearchCheckbox->setChecked(false); } if(ProgramOptions::Instance().getRegMarkAuto()) { ui->regMarksGroup->setChecked(true); ui->regSearchCheckbox->setChecked(true); } ui->regWidthSpinner->setValue(ProgramOptions::Instance().getRegDimensionWidthMM()); ui->regHeightSpinner->setValue(ProgramOptions::Instance().getRegDimensionHeightMM()); } CutDialog::~CutDialog() { delete ui; } void CutDialog::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } int CutDialog::media() const { int idx = ui->mediaCombo->currentIndex(); // Media code for each entry. int medias[] = { 100, 101, 102, 106, 111, 112, 113, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138 }; if (idx < 0 || idx >= 26) idx = 0; return medias[idx]; } int CutDialog::speed() const { return ui->speedSlider->value(); } int CutDialog::pressure() const { return ui->pressureSlider->value(); } bool CutDialog::trackEnhancing() const { return ui->trackEnhancingCheckbox->isChecked(); } bool CutDialog::regMark() const { return ui->regMarksGroup->isChecked(); } bool CutDialog::regSearch() const { return ui->regSearchCheckbox->isChecked(); } double CutDialog::regWidth() const { return ui->regWidthSpinner->value(); } double CutDialog::regHeight() const { return ui->regHeightSpinner->value(); } void CutDialog::onMediaChanged(int idx) { if (idx < 0 || idx >= 26) idx = 0; // Pressure for each entry. int pressures[] = { 27, 27, 10, 14, 27, 2, 10, 30, 30, 30, 30, 1, 1, 1, 30, 20, 27, 30, 30, 5, 25, 20, 20, 30, 30, 30 }; // Default speed is max except for magnetic sheet. int newspeed = idx == 17 ? 3 : 10; int newpressure = pressures[idx]; ui->speedSlider->setValue(newspeed); ui->pressureSlider->setValue(newpressure); } robocut-1.0.8/CuttingThread.cpp0000644000175000017500000000513411621557774016056 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "CuttingThread.h" #include "Plotter.h" CuttingThread::CuttingThread(QObject *parent) : QThread(parent) { _media = 300; _speed = 10; _pressure = 10; _trackenhancing = false; _regmark = false; _regsearch = false; _regwidth = 0.0; _reglength = 0.0; } void CuttingThread::setParams(QList cuts, double mediawidth, double mediaheight, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, float regwidth, float reglength) { // TODO: Move all this into a structure. _cuts = cuts; _media = media; _speed = speed; _pressure = pressure; _trackenhancing = trackenhancing; _regmark = regmark; _regsearch = regsearch; _regwidth = regwidth; _reglength = reglength; _mediawidth = mediawidth; _mediaheight = mediaheight; } void CuttingThread::run() { Error e = Cut(_cuts, _mediawidth, _mediaheight, _media, _speed, _pressure, _trackenhancing, _regmark, _regsearch, _regwidth, _reglength); if (e) emit success(); else emit error(e.message().c_str()); exec(); } robocut-1.0.8/Robocut.pro0000644000175000017500000000374511621557774014752 0ustar markusmarkus# ------------------------------------------------- # Project created by QtCreator 2010-10-03T18:21:30 # ------------------------------------------------- TARGET = robocut VERSION = 1.0.8 TEMPLATE = app INSTALLS += icon \ target target.path = /usr/bin icon.files += ./images/robocut.xpm icon.path = /usr/share/pixmaps/ QMAKE_EXTRA_TARGETS += release tarball SOURCES += main.cpp \ MainWindow.cpp \ Plotter.cpp \ Common.cpp \ PathPaintEngine.cpp \ CutDialog.cpp \ CuttingDialog.cpp \ CuttingThread.cpp \ PathPaintPage.cpp \ PathSorter.cpp \ ProgramOptions.cpp HEADERS += MainWindow.h \ Plotter.h \ NoCopy.h \ Common.h \ PathPaintEngine.h \ CutDialog.h \ CuttingDialog.h \ CuttingThread.h \ PathPaintPage.h \ PathSorter.h \ ProgramOptions.h FORMS += MainWindow.ui \ CutDialog.ui \ CuttingDialog.ui LIBS += -lusb-1.0 QT += svg RESOURCES += \ resources.qrc release.depends = tarball tarball.target = $${TARGET}-$${VERSION}.tar.gz tarball.commands = \ $(DEL_FILE) -r $${TARGET}-$${VERSION} ; \ $(MKDIR) $${TARGET}-$${VERSION} ; \ $(COPY_DIR) * $${TARGET}-$${VERSION}/ ; \ $(DEL_FILE) $${TARGET}-$${VERSION}/*.pro.user \ $${TARGET}-$${VERSION}/$${TARGET}-$${VERSION}.tar.gz \ $(DEL_FILE) -r $${TARGET}-$${VERSION}/$${TARGET}-$${VERSION} \ $${TARGET}-$${VERSION}/autodist.sh ; \ $(DEL_FILE) -r $${TARGET}-$${VERSION}/$${TARGET}-$${VERSION} \ $${TARGET}-$${VERSION}/umbrello_stuff.xmi ; \ $(DEL_FILE) -r $${TARGET}-$${VERSION}/$${TARGET}-$${VERSION} \ $${TARGET}-$${VERSION}/robocut ; \ $(DEL_FILE) -r $${TARGET}-$${VERSION}/$${TARGET}-$${VERSION} \ $${TARGET}-$${VERSION}/Makefile ; \ tar -cz --exclude=.svn --exclude=*.tar.gz -f $$tarball.target $${TARGET}-$${VERSION} ; \ $(DEL_FILE) -r $${TARGET}-$${VERSION} robocut-1.0.8/ProgramOptions.h0000644000175000017500000000764211621557774015747 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef PROGRAMOPTIONS_H #define PROGRAMOPTIONS_H #include class ProgramOptions { private: ProgramOptions ( ); ProgramOptions(const ProgramOptions &); ProgramOptions & operator=(const ProgramOptions &); virtual ~ProgramOptions ( ); public: // Singleton static ProgramOptions& Instance(); private: int sortPath; int startCut; QString fileName; int tspSortPath; int media; int speed; int pressure; int regMarkAuto; int regMark; double regDimensionWidth; double regDimensionHeight; double regOriginWidth; double regOriginHeight; QString version; int vendorUSB_ID; int productUSB_ID; double marginTop; double marginRight; int trackEnhancing; public: void setSortPath ( int new_var ); int getSortPath ( ); void setStartCut ( int new_var ); int getStartCut ( ); void setFileName ( QString new_var ); QString getFileName ( ); void setTspSortPath ( int new_var ); int getTspSortPath ( ); void setMedia ( int new_var ); int getMedia ( ); void setSpeed ( int new_var ); int getSpeed ( ); void setPressure ( int new_var ); int getPressure ( ); void setRegMarkAuto ( int new_var ); int getRegMarkAuto ( ); void setRegMark ( int new_var ); int getRegMark ( ); void setRegDimensionWidth ( int new_var ); int getRegDimensionWidth ( ); void setRegDimensionHeight ( int new_var ); int getRegDimensionHeight ( ); void setRegOriginWidth ( int new_var ); int getRegOriginWidth ( ); void setRegOriginHeight ( int new_var ); int getRegOriginHeight ( ); void setRegDimensionWidthMM ( double new_var ); double getRegDimensionWidthMM ( ); void setRegDimensionHeightMM ( double new_var ); double getRegDimensionHeightMM ( ); void setRegOriginWidthMM ( double new_var ); double getRegOriginWidthMM ( ); void setRegOriginHeightMM ( double new_var ); double getRegOriginHeightMM ( ); void setVersion ( QString new_var ); QString getVersion ( ); void setVendorUSB_ID ( int new_var ); int getVendorUSB_ID ( ); void setProductUSB_ID ( int new_var ); int getProductUSB_ID ( ); void setMarginTop ( int new_var ); int getMarginTop ( ); void setMarginRight ( int new_var ); int getMarginRight ( ); void setMarginTopMM ( double new_var ); double getMarginTopMM ( ); void setMarginRightMM ( double new_var ); double getMarginRightMM ( ); void setTrackEnhancing ( int new_var ); int getTrackEnhancing ( ); private: void showHelp ( ); void showVersion ( ); void showShow ( ); void initAttributes ( ) ; public: int GetOpt (int argc, char *argv[] ); }; #endif // PROGRAMOPTIONS_H robocut-1.0.8/PathPaintPage.cpp0000644000175000017500000000723011621557774015775 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PathPaintPage.h" #include "PathPaintEngine.h" #include uint qHash(const QPolygonF& key) { QByteArray repr; for (int i = 0; i < key.size(); ++i) { double x = key[i].x(); double y = key[i].y(); repr.append(reinterpret_cast(&x), sizeof(x)); repr.append(reinterpret_cast(&y), sizeof(y)); } return qHash(repr); } PathPaintDevice::PathPaintDevice(double widthInMm, double heightInMm, double pixelsPerMm) { engine = NULL; width = widthInMm; height = heightInMm; pathsClipped = false; ppm = pixelsPerMm; if (ppm == 0.0) ppm = 1.0; } PathPaintDevice::~PathPaintDevice() { if (engine) delete engine; } void PathPaintDevice::addPath(const QPolygonF& path) { if (pagePathSet.contains(path)) return; pagePathSet.insert(path); pagePaths.append(path); // Clip the path. for (int j = 0; j < pagePaths.back().size(); ++j) { // pagePaths are in mm, so convert from pixels to mm. pagePaths.back()[j] /= ppm; if (pagePaths.back()[j].x() < 0.0) { pathsClipped = true; pagePaths.back()[j].setX(0.0); } if (pagePaths.back()[j].y() < 0.0) { pathsClipped = true; pagePaths.back()[j].setY(0.0); } if (pagePaths.back()[j].x() > width) { pathsClipped = true; pagePaths.back()[j].setX(width); } if (pagePaths.back()[j].y() > height) { pathsClipped = true; pagePaths.back()[j].setY(height); } } } QPaintEngine* PathPaintDevice::paintEngine() const { if (!engine) engine = new PathPaintEngine(const_cast(this)); return engine; } QList PathPaintDevice::paths() { return pagePaths; } int PathPaintDevice::metric(PaintDeviceMetric metric) const { switch (metric) { // Width in pixels. case PdmWidth: return width * ppm; case PdmHeight: return height * ppm; case PdmWidthMM: return width; case PdmHeightMM: return height; case PdmNumColors: return 2; case PdmDepth: return 1; case PdmDpiX: return 25.4 * ppm; // Convert to inches. case PdmDpiY: return 25.4 * ppm; case PdmPhysicalDpiX: return 25.4 * ppm; case PdmPhysicalDpiY: return 25.4 * ppm; } return 0; } bool PathPaintDevice::clipped() const { return pathsClipped; } robocut-1.0.8/readme.txt0000644000175000017500000000175311621557774014606 0ustar markusmarkusROBOCUT ^^^^^^^ Robocut is a simple graphical program to allow you to cut graphics with a Graphtec Craft Robo 2 Vinyl Cutter model CC220-20 and Sihouette SD. It can read SVG files produced by Inkscape, but it should also work with other SVG files. Unlike the official programs, Robocut can run on Linux and probably Mac OS X with a tiny bit of work. It may work with the newer CC330-20 model if the USB IDs are changed, but I don’t have one to test with. AUTHORS ^^^^^^^ Tim Hutt, Markus Schulz INSTALLATION ^^^^^^^^^^^^ See install.txt INSTRUCTIONS ^^^^^^^^^^^^ Basic instructions are: 1. Create a new A4 portrait drawing in Inkscape. (For the registration mark feature you can use the supplied public domain letter_reg-marks.svg file) 2. Make sure in the options, the default export DPI is 90.0 3. Paste your stuff into the drawing. 4. Export as Plain SVG. 5. Open the SVG with Robocut. 6. Make sure it will cut correctly with the View->Animate option. 7. File->Cut. ---------- 31/10/2010 robocut-1.0.8/MainWindow.h0000644000175000017500000000622011621557774015027 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include "CutDialog.h" namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); ~MainWindow(); private: Ui::MainWindow *ui; // The cutting paths that were loaded from the SVG. QList paths; // For displaying the cuts. QGraphicsScene* scene; // The dialog that asks what settings to use. We keep this around and reuse it as necessary. CutDialog* cutDialog; // The directory that the last file was opened from. QString lastOpenDir; // Timer for the cutting animation. QTimer* animationTimer; // The circle that marks where the cutter blade is. QGraphicsItem* cutMarker; // Cut marker progress. int cutMarkerPath; // Current path. int cutMarkerLine; // Current line in path double cutMarkerDistance; // Current distance along edge. QSizeF mediaSize; QString filename; public: int sortFlag; int tspFlag; int cutFlag; char *fileValue; private slots: void on_actionZoom_Out_triggered(); void on_actionZoom_In_triggered(); void on_actionReset_triggered(); void on_actionAnimate_toggled(bool animate); void on_actionManual_triggered(); void on_actionCut_triggered(); void on_actionExit_triggered(); void on_actionAbout_triggered(); void on_actionOpen_triggered(); // Advance the cutting animation frame. void animate(); private: // Use empty string to indicate no file is loaded. void setFileLoaded(QString filename); bool eventFilter(QObject *o, QEvent *e); void loadFile(); }; #endif // MAINWINDOW_H robocut-1.0.8/CutDialog.h0000644000175000017500000000457411621557774014640 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #ifndef CUTDIALOG_H #define CUTDIALOG_H #include namespace Ui { class CutDialog; } // This dialog asks the user what settings to use for cutting. class CutDialog : public QDialog { Q_OBJECT public: explicit CutDialog(QWidget *parent = 0); ~CutDialog(); // The media code. See CutDialog.ui for a list. int media() const; // The speed (1-10). int speed() const; // The cutting pressure (1-33). int pressure() const; // Track enhancing. bool trackEnhancing() const; // Whether to search bool regMark() const; bool regSearch() const; // Positions of the registration marks. double regWidth() const; double regHeight() const; protected: void changeEvent(QEvent *e); private slots: // When they change the media, update the default speed and pressure. void onMediaChanged(int idx); private: Ui::CutDialog *ui; }; #endif // CUTDIALOG_H robocut-1.0.8/resources.qrc0000644000175000017500000000040211621557774015317 0ustar markusmarkus images/cap-blue.png images/cap-pen.png images/cap-red.png images/cap-yellow.png images/icon.png robocut-1.0.8/CuttingDialog.cpp0000644000175000017500000000721711621557774016052 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "CuttingDialog.h" #include "ui_CuttingDialog.h" #include #include #include #include CuttingDialog::CuttingDialog(QWidget *parent) : QDialog(parent), ui(new Ui::CuttingDialog) { ui->setupUi(this); thread = NULL; } CuttingDialog::~CuttingDialog() { delete ui; if (thread) { thread->exit(); thread->wait(1000); } } void CuttingDialog::changeEvent(QEvent *e) { QDialog::changeEvent(e); switch (e->type()) { case QEvent::LanguageChange: ui->retranslateUi(this); break; default: break; } } void CuttingDialog::startCut(QList cuts, double mediawidth, double mediaheight, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, double regwidth, double reglength) { if (thread) { qDebug() << "Internal error: startCut() called twice."; return; } thread = new CuttingThread(this); connect(thread, SIGNAL(success()), SLOT(onSuccess())); connect(thread, SIGNAL(error(QString)), SLOT(onError(QString))); thread->setParams(cuts, mediawidth, mediaheight, media, speed, pressure, trackenhancing, regmark, regsearch, regwidth, reglength); thread->start(); } void CuttingDialog::onSuccess() { ui->status->setText("Finished"); ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Close"); thread->exit(); thread->wait(1000); delete thread; thread = NULL; } void CuttingDialog::onError(QString message) { ui->status->setText("Error: " + message); ui->buttonBox->button(QDialogButtonBox::Cancel)->setText("Close"); thread->exit(); thread->wait(1000); delete thread; thread = NULL; } void CuttingDialog::closeEvent(QCloseEvent* e) { if (thread) { if (QMessageBox::question(this, "Kill cutting process?", "Are you sure you wish to stop the cutting process? " "This may result in bad stuff. It might be better just to turn the plotter off and on again.", QMessageBox::Yes, QMessageBox::No) == QMessageBox::No) { e->ignore(); return; } thread->terminate(); thread->wait(5000); delete thread; thread = NULL; } return QDialog::closeEvent(e); } robocut-1.0.8/MainWindow.ui0000644000175000017500000001012511621557774015214 0ustar markusmarkus MainWindow 0 0 823 753 Robocut :/images/icon.png:/images/icon.png QPainter::Antialiasing|QPainter::TextAntialiasing QGraphicsView::ScrollHandDrag QGraphicsView::AnchorUnderMouse 0 0 823 23 File Help View About Manual (Online) F1 Open Ctrl+O false Cut Ctrl+P Exit Ctrl+Q true false Animate Ctrl+A false Reset Ctrl+R false Zoom In + false Zoom Out - robocut-1.0.8/Plotter.cpp0000644000175000017500000003450511621557774014746 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "Plotter.h" #include "ProgramOptions.h" #include int VENDOR_ID = ProgramOptions::Instance().getVendorUSB_ID(); const int VENDOR_ID_GRAPHTEC = 0x0b4d; int PRODUCT_ID = ProgramOptions::Instance().getProductUSB_ID(); const int PRODUCT_ID_CC200_20 = 0x110a; const int PRODUCT_ID_SILHOUETTE_SD_1 = 0x111c; const int PRODUCT_ID_SILHOUETTE_SD_2 = 0x111d; #include #include string UsbError(int e) { switch (e) { case LIBUSB_SUCCESS: return "Success (internal error)"; case LIBUSB_ERROR_IO: return "I/O error"; case LIBUSB_ERROR_INVALID_PARAM: return "Invalid parameter"; case LIBUSB_ERROR_ACCESS: return "Access denied"; case LIBUSB_ERROR_NO_DEVICE: return "No device"; case LIBUSB_ERROR_NOT_FOUND: return "Entity not found"; case LIBUSB_ERROR_BUSY: return "Resource busy"; case LIBUSB_ERROR_TIMEOUT: return "Timeout"; case LIBUSB_ERROR_OVERFLOW: return "Overflow"; case LIBUSB_ERROR_PIPE: return "Pipe error"; case LIBUSB_ERROR_INTERRUPTED: return "Syscall interrupted"; case LIBUSB_ERROR_NO_MEM: return "Insufficient memory"; case LIBUSB_ERROR_NOT_SUPPORTED: return "Operation not supported"; case LIBUSB_ERROR_OTHER: return "Other error"; } return "Unknown error"; } // Send some data to the USB device. Error UsbSend(libusb_device_handle* handle, const string& s, int timeout = 0) { // Send in 4096 byte chunks. Not sure where I got this from, I'm not sure it is actually necessary. for (unsigned int i = 0; i < s.length(); i += 4096) { string data = s.substr(i, 4096); int transferred; unsigned char endpoint = '\x01'; int ret = libusb_bulk_transfer(handle, endpoint, reinterpret_cast(const_cast(data.c_str())), data.length(), &transferred, timeout); if (ret != 0) { cerr << "Error writing to device: " << UsbError(ret) << endl; return Error("Error writing to device: " + UsbError(ret)); } if (transferred != data.length()) { cerr << "Warning, some data not transferred correctly." << endl; return Error("Some data not transfered. Attempted: " + ItoS(data.length()) + " Transferred: " + ItoS(transferred)); } } return Success; } // Receive some data up to the maximum packet size of 64. Because we use the packet size // there can never be overflows, and 64 is ok because none of the craft robo responses are // anywhere near that long. Error UsbReceive(libusb_device_handle* handle, string& s, int timeout = 0) { s.clear(); // A buffer that is one packet long. const int PacketSize = 64; unsigned char buffer[PacketSize]; int transferred = 0; unsigned char endpoint = '\x82'; int ret = libusb_bulk_transfer(handle, endpoint, buffer, PacketSize, &transferred, timeout); if (ret != 0) // But it could be a timout. { cerr << "Error reading from device: " << UsbError(ret) << endl; return Error("Error reading from device: " + UsbError(ret)); } s = string(reinterpret_cast(buffer), transferred); return Success; } // Send a control message //Error UsbControl(libusb_device_handle* handle, ...) //{ // libusb_control_transfer(handle, // uint8_t request_type, uint8_t request, uint16_t value, uint16_t index, // unsigned char *data, uint16_t length, unsigned int timeout); //} Error Cut(QList cuts, double mediawidth, double mediaheight, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, double regwidth, double reglength) { VENDOR_ID = ProgramOptions::Instance().getVendorUSB_ID(); PRODUCT_ID = ProgramOptions::Instance().getProductUSB_ID(); cout << "Cutting... VENDOR_ID : " << VENDOR_ID << " PRODUCT_ID: " << PRODUCT_ID << " mediawidth: " << mediawidth << " mediaheight: " << mediaheight << "media: " << media << " speed: " << speed << " pressure: " << pressure << " trackenhancing: " << trackenhancing << " regmark: " << regmark << " regsearch:" << regsearch <<" regwidth:" << regwidth << " reglength: " << reglength << endl; if (media < 100 || media > 300) media = 300; if (speed < 1) speed = 1; if (speed > 10) speed = 10; if (pressure < 1) pressure = 1; if (pressure > 33) pressure = 33; libusb_device** list; ssize_t cnt = libusb_get_device_list(NULL, &list); if (cnt < 1) return Error("Couldn't get usb device list."); int err = 0; libusb_device* found = NULL; for (ssize_t i = 0; i < cnt; ++i) { libusb_device* device = list[i]; libusb_device_descriptor desc; libusb_get_device_descriptor(device, &desc); // I don't want to be more specific than this really. if ((desc.idVendor == VENDOR_ID || desc.idVendor == VENDOR_ID_GRAPHTEC) && (desc.idProduct == PRODUCT_ID || desc.idProduct == PRODUCT_ID_CC200_20 || desc.idProduct == PRODUCT_ID_SILHOUETTE_SD_1 || desc.idProduct == PRODUCT_ID_SILHOUETTE_SD_2)) { // Just use the first one. Who has two?! found = device; break; } } if (!found) { libusb_free_device_list(list, 1); return Error("Couldn't find Craft Robo 2 (USB device with Vendor ID with USB VendorID 0b4d and ProductID 110a). Is it connected to the system and powered on?"); } libusb_device_handle* handle; err = libusb_open(found, &handle); if (err != 0) { libusb_free_device_list(list, 1); return Error("Error accessing Craft Robo 2: " + UsbError(err) + ". Do you have permission (on Linux make sure you are in the group 'lp')."); } libusb_free_device_list(list, 1); // Now do stuff with the handle. int r = 0; if (libusb_kernel_driver_active(handle, 0) == 1) { r = libusb_detach_kernel_driver(handle, 0); if (r != 0) { libusb_close(handle); return Error("Error detaching kernel USB driver: " + UsbError(r)); } } r = libusb_reset_device(handle); if (r != 0) { libusb_close(handle); return Error("Error resetting device: " + UsbError(r)); } cout << "Selecting configuration." << endl; r = libusb_set_configuration(handle, 1); if (r < 0) { libusb_close(handle); return Error("Error setting USB configuration: " + UsbError(r)); } cout << "Claiming main control interface." << endl; r = libusb_claim_interface(handle, 0); if (r < 0) { libusb_close(handle); return Error("Error claiming USB interface: " + UsbError(r)); } cout << "Setting alt interface." << endl; r = libusb_set_interface_alt_setting(handle, 0, 0); // Probably not really necessary. if (r < 0) { return Error("Error setting alternate USB interface: " + UsbError(r)); } cout << "Initialisation successful." << endl; // TODO: Use exceptions. Error e = Success; string resp; // Initialise plotter. e = UsbSend(handle, "\x1b\x04"); if (!e) goto error; // Status request. e = UsbSend(handle, "\x1b\x05"); if (!e) goto error; e = UsbReceive(handle, resp, 5000); if (!e) goto error; if (resp != "0\x03") // 0 = Ready. 1 = Moving. " " = ?? { e = Error("Invalid response from plotter: " + resp); goto error; } // Home the cutter. e = UsbSend(handle, "TT\x03"); if (!e) goto error; // Query version. e = UsbSend(handle, "FG\x03"); if (!e) goto error; // Receive the firmware version. e = UsbReceive(handle, resp, 10000); // Large timeout because the plotter moves. if (!e) goto error; // Don't really care about this. // if (resp.length() != 10) // { // e = Error("Version error: " + version); // goto error; // } e = UsbSend(handle, "FW" + ItoS(media) + "\x03"); if (!e) goto error; e = UsbSend(handle, "!" + ItoS(speed) + "\x03"); if (!e) goto error; e = UsbSend(handle, "FX" + ItoS(pressure) + "\x03"); if (!e) goto error; // I think this sets the distance from the position of the plotter // head to the actual cutting point, maybe in 0.1 mms (todo: Measure blade). // It is 0 for the pen, 18 for cutting. // C possible stands for curvature. Not that any of the other letters make sense... e = UsbSend(handle, "FC" + ItoS(media == 113 ? 0 : 18) + "\x03"); if (!e) goto error; e = UsbSend(handle, "FY" + ItoS(trackenhancing ? 0 : 1) + "\x03"); if (!e) goto error; // Set to portrait. FN1 does landscape but it's easier just to rotate the image. e = UsbSend(handle, "FN0\x03"); if (!e) goto error; e = UsbSend(handle, "FE0\x03"); // No idea what this does. if (!e) goto error; e = UsbSend(handle, "TB71\x03"); // Again, no idea. Maybe something to do with registration marks? if (!e) goto error; e = UsbReceive(handle, resp, 10000); // Allow 10s. Seems reasonable. if (!e) goto error; if (resp != " 0, 0\x03") { e = Error("Invalid response from plotter."); goto error; } // Begin page definition. e = UsbSend(handle, "FA\x03"); if (!e) goto error; // Block for all the "jump to error crosses initialization" errors. Really need to use exceptions! { // Page size: height,width in 20ths of a mm minus a margin. This is for A4. TODO: Find maximum and use that. stringstream page; int width = lroundl(mediawidth * 20.0); int height = lroundl(mediaheight * 20.0); int margintop = ProgramOptions::Instance().getMarginTop(); int marginright = ProgramOptions::Instance().getMarginRight(); e = UsbSend(handle, "FU" + ItoS(height - margintop) + "," + ItoS(width - marginright) + "\x03"); if (!e) goto error; e = UsbSend(handle, "FM1\x03"); // ? if (!e) goto error; if (regmark) { stringstream regmarkstr; regmarkstr.precision(0); string searchregchar = "23,"; int regw = lroundl(regwidth * 20.0); int regl = lroundl(reglength * 20.0); e = UsbSend(handle, "TB50,381\x03"); //only with registration (it was TB50,1) ??? if (!e) goto error; if (regsearch) searchregchar ="123,"; regmarkstr << "TB99\x03TB55,1\x03TB" + searchregchar + ItoS(regw) + "," + ItoS(regl) + "\x03"; cout << "Registration mark string: " << regmarkstr.str() << endl; e = UsbSend(handle, regmarkstr.str()); //registration mark test /1-2: 180.0mm / 1-3: 230.0mm (origin 15mmx20mm) if (!e) goto error; e = UsbSend(handle, "FQ5\x03"); // only with registration ??? if (!e) goto error; e = UsbReceive(handle, resp, 40000); // Allow 20s for reply... if (!e) goto error; if (resp != " 0, 0\x03") { cout << resp << endl; e = Error("Couldn't find registration marks."); goto error; } // Looks like if the reg marks work it gets 3 messages back (if it fails it times out because it only gets the first message) e = UsbReceive(handle, resp, 40000); // Allow 20s for reply... if (!e) goto error; if (resp != " 0\x03") { cout << resp << endl; e = Error("Couldn't find registration marks."); goto error; } e = UsbReceive(handle, resp, 40000); // Allow 20s for reply... if (!e) goto error; if (resp != " 1\x03") { cout << resp << endl; e = Error("Couldn't find registration marks."); goto error; } } else { e = UsbSend(handle, "TB50,1\x03"); // ??? if (!e) goto error; } if (!e) goto error; // I think this is the feed command. Sometimes it is 5588 - maybe a maximum? e = UsbSend(handle, "FO" + ItoS(height - margintop) + "\x03"); if (!e) goto error; page.flags(ios::fixed); page.precision(0); page << "&100,100,100,\\0,0,Z" << ItoS(width) << "," << ItoS(height) << ",L0"; for (int i = 0; i < cuts.size(); ++i) { if (cuts[i].size() < 2) continue; double x = cuts[i][0].x()*20.0; double y = cuts[i][0].y()*20.0; double xorigin = ProgramOptions::Instance().getRegOriginWidthMM(); double yorigin = ProgramOptions::Instance().getRegOriginHeightMM(); if (regmark) { x = x - (xorigin*20.0); y = y + (yorigin*20.0); } // TODO: Also do this in the UI and warn the user about it. if (x < 0.0) x = 0.0; if (x > width) x = width; if (y < 0.0) y = 0.0; if (y > height) y = height; page << ",M" << x << "," << height-y; for (int j = 1; j < cuts[i].size(); ++j) { x = cuts[i][j].x()*20.0; y = cuts[i][j].y()*20.0; if (regmark) { x = x - (xorigin*20.0); y = y + (yorigin*20.0); } bool draw = true; if (x <= 0.0) { x = 0.0; draw = false; } if (x >= width) { x = width; draw = false; } if (y <= 0.0) { y = 0.0; draw = false; } if (y >= height) { y = height; draw = false; } if (draw) page << ",D" << x << "," << height-y; else page << ",M" << x << "," << height-y; // if outside the range just move } } page << "&1,1,1,TB50,0\x03"; // TB maybe .. ah I dunno. Need to experiment. No idea what &1,1,1 does either. cout << page.str() << endl; e = UsbSend(handle, page.str()); if (!e) goto error; } // Feed the page out. e = UsbSend(handle, "FO0\x03"); if (!e) goto error; // Halt? e = UsbSend(handle, "H,"); if (!e) goto error; // Don't really care about the results of these! libusb_release_interface(handle, 0); libusb_close(handle); return Success; error: // Hey, this is basically C and I can't be bothered to properly C++-ify it. TODO: Use exceptions. libusb_release_interface(handle, 0); libusb_close(handle); return e; } robocut-1.0.8/changelog0000644000175000017500000000252111621557774014454 0ustar markusmarkus1.0.8 * changes in Robocut.pro for qmake so no QT files are shipped (Debian requirement) 1.0.7 * Add USB ID 111C as another default. 1.0.6 * Tim fixed drawing bug * changed from float to int for output to plotter, fixes crash of 2nd gen plotter model * changed display pen size to 0 * Tim fixed track enhancing option was inverted. 1.0.5 * adding all the changes needed for Debian * fixed watch file * make binary lower case * removed redundant copyright form the copyright file * recreated all the images so we have the copyright * added vcs information to control file * merged mentor in to master 1.0.4 * add .desktop file for Ubuntu * default needs to be 10 for pressure * get menu working * better sample reg file 1.0.3 * manpage * command line interface * mouse wheel zoom * change the draw command to move command if the cut is on the outer edge, kind of clipping (but not in preview) * dash pattern from path * sort the different paths to cut faster * bounding box option to cut inside path first (good for letters) * registration mark support 1.0.2 * Initial Release on Ubuntu. Master * Some brief documentation * Initial registration mark support * Load page size from file * Small UI improvements Version 0.2 - a3b13ad - Oct 24th 2010 * Initial working version. robocut-1.0.8/PathSorter.cpp0000644000175000017500000001763011621557774015410 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "PathSorter.h" #include #include #include using namespace std; PathSorter::PathSorter ( ) {} PathSorter::PathSorter (const QList inpaths, qreal mediaheight ) { getQList(inpaths); mediaHeight = mediaheight; } PathSorter::~PathSorter ( ) { } void PathSorter::getQList (const QList inpaths) { pathToSort = QList(inpaths); } void PathSorter::setMediaHeight(qreal mediaheight) { mediaHeight = mediaheight; } QList PathSorter::UnSort (const QList inpaths) { QList outpaths = QList(inpaths); return outpaths; } bool PathSorter::MyLessThan(const QPolygonF &p1, const QPolygonF &p2) { qreal testx1 = p1[0].x(); qreal testx2 = p2[0].x(); qreal testy1 = p1[0].y(); qreal testy2 = p2[0].y(); if(testy1 == testy2) return testx1 > testx2; else return testy1 > testy2; } QList PathSorter::Sort (const QList inpaths) { QList outpaths = QList(inpaths); qSort(outpaths.begin(), outpaths.end(), MyLessThan); return outpaths; } QList PathSorter::BestSort (const QList inpaths) { qreal inpath = getTotalDistance(inpaths); qreal sortpath = inpath; qreal tsppath = inpath, temppath; qreal tsppath2 = inpath; cout<<"in path: "<< inpath << endl; QList outpathSort = Sort(QList(inpaths)); sortpath = getTotalDistance(outpathSort); cout<<"Sort outpath: "<< sortpath << endl; int bestpath=1; for (int i = 1; i < inpaths.size()/2; i++) { QList outpathTSP = GroupTSP(QList(inpaths),i); temppath = getTotalDistance(outpathTSP); //cout<<"xTSPSort outpaths: "<< temppath << " Groups " << i < outpathTSP = GroupTSP(QList(inpaths),bestpath); tsppath = getTotalDistance(outpathTSP); cout<<"TSPSort outpaths: "<< tsppath << " Groups " << bestpath < outpathTSP2 = GroupTSP(QList(outpathSort),i); temppath = getTotalDistance(outpathTSP2); //cout<<"xxTSPSort outpaths: "<< temppath << " Groups " << i < outpathTSP2 = GroupTSP(QList(outpathSort),bestpath2); tsppath2 = getTotalDistance(outpathTSP2); cout<<"TSPSort outpath sort: "<< tsppath2 << " Groups " << bestpath2 < PathSorter::BbSort (const QList inpaths) { QList outpaths = QList(inpaths); for (int i = 0; i < (outpaths.size()-1); i++) { for (int j = (i+1); j < outpaths.size(); j++) { if (outpaths[i].boundingRect().intersects(outpaths[j].boundingRect())) { if (outpaths[i].boundingRect().width() > outpaths[j].boundingRect().width() || outpaths[i].boundingRect().height() > outpaths[j].boundingRect().height()) { outpaths.swap(i,j); break; } } } } cout<<"BbSort outpaths: "<< getTotalDistance(outpaths) << endl; return outpaths; } QList PathSorter::GroupTSP(const QList inpaths, int groups) { if (groups > inpaths.size()) groups = (int)((double) inpaths.size()-((double)inpaths.size()*0.2)); if (groups < 1) groups = 1; QList > listlistpath; QList temppaths; int inps = inpaths.size(); int inpsparts = inps / groups; for (int i = 0; i < inps; i++) { if(i>=inpsparts) { listlistpath.append(temppaths); inpsparts += inps / groups; temppaths = QList() ; } temppaths.append(inpaths[i]); } listlistpath.append(temppaths); for (int i = 0; i < listlistpath.size(); i++) { listlistpath[i] = MyFakeTSP(listlistpath[i]); } QList outpaths; for (int i = 0; i < listlistpath.size(); i++) { for (int j = 0; j < listlistpath[i].size(); j++) { outpaths.append(listlistpath[i][j]); } } //cout<<"xTSPSort outpaths: "<< getTotalDistance(outpaths) << " Groups " << groups <= testx2) a = testx1 - testx2; else a = testx2 - testx1; if(testy1 >= testy2) b = testy1 - testy2; else b = testy2 - testy1; c = sqrt((double)(a*a+b*b)); return (qreal) c; } qreal PathSorter::getTotalDistance(const QList inpaths, int maxdepth) { if (maxdepth >= inpaths.size()-1) maxdepth = inpaths.size()-1; if (maxdepth <= 0) maxdepth = inpaths.size()-1; QPolygonF zero = QPolygonF(QRectF(0.0,mediaHeight,0.0,0.0)); // able to change the start point qreal dist = getDistance(zero,inpaths[0]); for (int i = 0; i < maxdepth; ++i) { dist = dist + getDistance(inpaths[i],inpaths[(i+1)]); } return dist; } QList PathSorter::MyFakeTSP(const QList inpaths) { QPolygonF zero = QPolygonF(QRectF(0.0,mediaHeight,0.0,0.0)); // able to change the start point QList outpaths = QList(inpaths); // find the shortest path for (int i = 0; i < (outpaths.size()-1); ++i) { if(i == 0) // find good start { qreal dist=10000.0; int bestindex=i; for (int j = (i+1); j < outpaths.size(); ++j) { if (getDistance(zero,outpaths[j]) < dist) { dist = getDistance(zero,outpaths[j]); bestindex = j; } } if (dist != 0) outpaths.swap(0,bestindex); } qreal dist=10000.0; int bestindex=i; for (int j = (i+1); j < outpaths.size(); ++j) { if (getDistance(outpaths[i],outpaths[j]) < dist) { dist = getDistance(outpaths[i],outpaths[j]); bestindex = j; } } if (dist != 0) outpaths.swap((i+1),bestindex); } return outpaths; } robocut-1.0.8/ProgramOptions.cpp0000644000175000017500000003617011621557774016300 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "ProgramOptions.h" #include #include #include #include #include using namespace std; ProgramOptions::ProgramOptions ( ) { initAttributes(); } ProgramOptions::~ProgramOptions ( ) { } ProgramOptions& ProgramOptions::Instance() { static ProgramOptions instance; return instance; } void ProgramOptions::setSortPath ( int new_var ) { sortPath = new_var; } int ProgramOptions::getSortPath ( ) { return sortPath; } void ProgramOptions::setStartCut ( int new_var ) { startCut = new_var; } int ProgramOptions::getStartCut ( ) { return startCut; } void ProgramOptions::setFileName ( QString new_var ) { fileName = new_var; } QString ProgramOptions::getFileName ( ) { return fileName; } void ProgramOptions::setTspSortPath ( int new_var ) { tspSortPath = new_var; } int ProgramOptions::getTspSortPath ( ) { return tspSortPath; } void ProgramOptions::setMedia ( int new_var ) { if (new_var<0) new_var = 0; if (new_var>25) new_var = 25; media = new_var; } int ProgramOptions::getMedia ( ) { return media; } void ProgramOptions::setSpeed ( int new_var ) { speed = new_var; } int ProgramOptions::getSpeed ( ) { return speed; } void ProgramOptions::setPressure ( int new_var ) { pressure = new_var; } int ProgramOptions::getPressure ( ) { return pressure; } void ProgramOptions::setRegMarkAuto ( int new_var ) { regMarkAuto = new_var; } int ProgramOptions::getRegMarkAuto ( ) { return regMarkAuto; } void ProgramOptions::setRegMark ( int new_var ) { regMark = new_var; } int ProgramOptions::getRegMark ( ) { return regMark; } void ProgramOptions::setRegDimensionWidth ( int new_var ) { regDimensionWidth = new_var; } int ProgramOptions::getRegDimensionWidth ( ) { return lroundl(regDimensionWidth); } void ProgramOptions::setRegDimensionHeight ( int new_var ) { regDimensionHeight = new_var; } int ProgramOptions::getRegDimensionHeight ( ) { return lroundl(regDimensionHeight); } void ProgramOptions::setRegOriginWidth ( int new_var ) { regOriginWidth = new_var; } int ProgramOptions::getRegOriginWidth ( ) { return lroundl(regOriginWidth); } void ProgramOptions::setRegOriginHeight ( int new_var ) { regOriginHeight = new_var; } int ProgramOptions::getRegOriginHeight ( ) { return lroundl(regOriginHeight); } void ProgramOptions::setRegDimensionWidthMM ( double new_var ) { regDimensionWidth = new_var*20; } double ProgramOptions::getRegDimensionWidthMM ( ) { return regDimensionWidth/20; } void ProgramOptions::setRegDimensionHeightMM ( double new_var ) { regDimensionHeight = new_var*20; } double ProgramOptions::getRegDimensionHeightMM ( ) { return regDimensionHeight/20; } void ProgramOptions::setRegOriginWidthMM ( double new_var ) { regOriginWidth = new_var*20; } double ProgramOptions::getRegOriginWidthMM ( ) { return regOriginWidth/20; } void ProgramOptions::setRegOriginHeightMM ( double new_var ) { regOriginHeight = new_var*20; } double ProgramOptions::getRegOriginHeightMM ( ) { return regOriginHeight/20; } void ProgramOptions::setVersion ( QString new_var ) { version = new_var; } QString ProgramOptions::getVersion ( ) { return version; } void ProgramOptions::setVendorUSB_ID ( int new_var ) { vendorUSB_ID = new_var; } int ProgramOptions::getVendorUSB_ID ( ) { return vendorUSB_ID; } void ProgramOptions::setProductUSB_ID ( int new_var ) { productUSB_ID = new_var; } int ProgramOptions::getProductUSB_ID ( ) { return productUSB_ID; } void ProgramOptions::setMarginTop ( int new_var ) { marginTop = new_var; } int ProgramOptions::getMarginTop ( ) { return lroundl(marginTop); } void ProgramOptions::setMarginRight ( int new_var ) { marginRight = new_var; } int ProgramOptions::getMarginRight ( ) { return lroundl(marginRight); } void ProgramOptions::setMarginTopMM ( double new_var ) { marginTop = new_var*20; } double ProgramOptions::getMarginTopMM ( ) { return marginTop/20; } void ProgramOptions::setMarginRightMM ( double new_var ) { marginRight = new_var*20; } double ProgramOptions::getMarginRightMM ( ) { return marginRight/20; } void ProgramOptions::setTrackEnhancing ( int new_var ) { trackEnhancing = new_var; } int ProgramOptions::getTrackEnhancing ( ) { return trackEnhancing; } int ProgramOptions::GetOpt (int argc, char *argv[] ) { static int version_flag = 0, help_flag = 0, show_flag = 0; int index, option_index = 0; int c = 0; const char shortopts[] = "stg:p:ra:b:c:d:"; static struct option longopts[] = { {"help", no_argument, &help_flag, 1}, {"version", no_argument, &version_flag, 1}, {"show", no_argument, &show_flag, 1}, {"no-sort", no_argument, 0, 's'}, {"bb-sort", no_argument, 0, 't'}, {"cut", no_argument, 0, 'l'}, {"media", required_argument, 0, 'm'}, {"speed", required_argument, 0, 'g'}, {"pressure", required_argument, 0, 'p'}, {"track-enhancing", no_argument, 0, 'n'}, {"margin-top", required_argument, 0, 'o'}, {"margin-right", required_argument, 0, 'q'}, {"reg-mark-auto", no_argument, 0, 'r'}, {"reg-mark", no_argument, 0, 'h'}, {"reg-dimension-width", required_argument, 0, 'a'}, {"reg-dimension-height", required_argument, 0, 'b'}, {"reg-origin-width", required_argument, 0, 'c'}, {"reg-origin-height", required_argument, 0, 'd'}, {"usb-vendor-id", required_argument, 0, 'e'}, {"usb-product-id", required_argument, 0, 'f'}, {0, 0, 0, 0} }; opterr = 0; while ((c = getopt_long(argc, argv, shortopts, longopts, &option_index)) != -1) { switch (c) { case 0: /* If this option set a flag, do nothing else now. */ if (longopts[option_index].flag != 0) break; //cout << longopts[option_index].name << endl; break; case 's': setSortPath(true); break; case 't': setTspSortPath(true); break; case 'l': setStartCut(true); break; case 'm': setMedia(atoi(optarg)); break; case 'g': setSpeed(atoi(optarg)); break; case 'p': setPressure(atoi(optarg)); break; case 'n': setTrackEnhancing(true); break; case 'o': setMarginTopMM(atof(optarg)); break; case 'q': setMarginRightMM(atof(optarg)); break; case 'r': setRegMarkAuto(true); break; case 'h': setRegMark(true); break; case 'a': setRegDimensionWidthMM(atof(optarg)); break; case 'b': setRegDimensionHeightMM(atof(optarg)); break; case 'c': setRegOriginWidthMM(atof(optarg)); break; case 'd': setRegOriginHeightMM(atof(optarg)); break; case 'e': setVendorUSB_ID(atoi(optarg)); break; case 'f': setProductUSB_ID(atoi(optarg)); break; case '?': if (optopt == 'f') cerr << "Option -"<< optopt <<" requires an argument." << endl; else if (isprint (optopt)) cerr << "Unknown option `-"<< (char)optopt <<"'." << endl; else cerr << "Unknown option character ASCII code "<< optopt <<"." << endl; exit(0); default: abort(); } } for (index = optind; index < argc; index++) { //cout << "Non-option argument " << argv[index] <<"'." << endl; fileName = argv[optind]; // take the first non arg as file continue; } if(show_flag) { showShow(); exit(0); } if(help_flag) { showHelp(); exit(0); } if(version_flag) { showVersion(); exit(0); } return 0; } void ProgramOptions::showHelp ( ) { // "<------------------------------------------------------------------------------>" cout << "The `Robocut' program plots or cuts SVG files on a Craft Robo or Silhouette SD" << endl; cout << "or most likely any other customer grade Graphtec cutting plotter." << endl << endl; cout << "Usage:" << endl; cout << " robocut [OPTIONS...] [File]" << endl << endl; // "<------------------------------------------------------------------------------>" cout << "Help Options:" << endl; cout << " --help Show summary of options." << endl; cout << " --version Show version information and copyright details." << endl; cout << " --show Show all the parameters entered and the defaults." << endl << endl; // "<------------------------------------------------------------------------------>" cout << "Application Options:" << endl; cout << " -s, --no-sort Stop sort the objects from the SVG before plotting." << endl; cout << " -t, --bb-sort Sort the objects by bounding box, good for letters." << endl; cout << " This will cut out the inside first and than the" << endl; cout << " outside." << endl; cout << " --cut Shows the cutting dialogue after start." << endl; cout << " --media INT Select the media. See drop down box." << endl; cout << " -g, --speed INT The speed between 1 and 33." << endl; cout << " -p, --pressure INT The pressure between 1 and 10." << endl; cout << " --track-enhancing Move three times back and forward to create a" << endl; cout << " track." << endl; cout << " --margin-top DOUBLE Define the margin on top in mm." << endl; cout << " --margin-right DOUBLE Define the margin right in mm." << endl << endl; // "<------------------------------------------------------------------------------>" cout << "Registration Mark Options:" << endl; cout << " -r, --reg-mark-auto Use registration marks and find the marks" << endl; cout << " automatically." << endl; cout << " --reg-mark Use registration marks but set the knife manually" << endl; cout << " on top the round mark." << endl; cout << " -a, --reg-dimension-width DOUBLE" << endl; cout << " Specify the length in mm between the the two" << endl; cout << " horizontal marks." << endl; cout << " -b, --reg-dimension-height DOUBLE" << endl; cout << " Specify the length in mm between the the two" << endl; cout << " vertical marks." << endl; cout << " -c, --reg-origin-width DOUBLE" << endl; cout << " Specify the length in mm between the the edge of" << endl; cout << " the paper and the first horizontal mark." << endl; cout << " -d, --reg-origin-height DOUBLE" << endl; cout << " Specify the length in mm between the the edge of" << endl; cout << " the paper and the first vertical mark." << endl << endl; // "<------------------------------------------------------------------------------>" cout << "Device Options:" << endl; cout << " --usb-vendor-id INT Try this program with other usb hardware on" << endl; cout << " your own risk. You need to convert hex to dec." << endl; cout << " --usb-product-id INT May also work with other hardware, try" << endl; cout << " usb-devices program to scan your computer." << endl; cout << "Report bugs to https://bugs.launchpad.net/robocut/+filebug." << endl; // "<------------------------------------------------------------------------------>" } void ProgramOptions::showVersion ( ) { cout << (version.toStdString()); // see main.cpp cout << "\n\nCopyright (C) 2010\n"; cout << "This is free software; see the source for copying conditions. There is NO\n"; cout << "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n"; cout << "Written by Tim Hutt and Markus Schulz \n"; } void ProgramOptions::showShow ( ) { cout << "Application Options:\n"; cout << " -s, --no-sort "<< getSortPath() << endl; cout << " -t, --bb-sort "<< getTspSortPath() << endl; cout << " --cut "<< getStartCut() << endl; cout << " --media "<< getMedia() << endl; cout << " -g, --speed "<< getSpeed() << endl; cout << " -p, --pressure "<< getPressure() << endl; cout << " --track-enhancing "<< getTrackEnhancing() << endl; cout << " --margin-top "<< getMarginTopMM() << " / " << getMarginTop() << endl; cout << " --margin-right "<< getMarginRightMM() << " / " << getMarginRight() << endl; cout << " -r, --reg-mark-auto "<< getRegMarkAuto() << endl; cout << " --reg-mark "<< getRegMark() << endl; cout << " -a, --reg-dimension-width "<< getRegDimensionWidthMM() << " / " << getRegDimensionWidth() << endl; cout << " -b, --reg-dimension-height "<< getRegDimensionHeightMM() << " / " << getRegDimensionHeight() << endl; cout << " -c, --reg-origin-width "<< getRegOriginWidthMM() << " / " << getRegOriginWidth() << endl; cout << " -d, --reg-origin-height "<< getRegOriginHeightMM() << " / " << getRegOriginHeight() << endl; cout << " --usb-vendor-id "<< getVendorUSB_ID() << endl; cout << " --usb-product-id "<< getProductUSB_ID() << endl; cout << "[File] "<< getFileName().toStdString() << endl; } void ProgramOptions::initAttributes ( ) { sortPath = false; tspSortPath = false; // used for BBox startCut = false; fileName = ""; media = 2; speed = 10; pressure = 10; regMarkAuto = false; regMark = false; setRegDimensionWidthMM(180.0); setRegDimensionHeightMM(240.0); setRegOriginWidthMM(15.0); setRegOriginHeightMM(10.0); vendorUSB_ID = 0x0b4d; productUSB_ID = 0x111d; setMarginTop(500); setMarginRight(320); trackEnhancing = false; } robocut-1.0.8/examples/0000755000175000017500000000000011621557774014420 5ustar markusmarkusrobocut-1.0.8/examples/legal_reg-marks_h310.svg0000644000175000017500000002002511621557774020727 0ustar markusmarkus image/svg+xml Markus Schulz robocut-1.0.8/examples/a4_reg-marks_h260.svg0000644000175000017500000002005211621557774020153 0ustar markusmarkus image/svg+xml Markus Schulz robocut-1.0.8/examples/letter_reg-marks.svg0000644000175000017500000001772511621557774020424 0ustar markusmarkus image/svg+xml Markus Schulz robocut-1.0.8/CuttingDialog.h0000644000175000017500000000522311621557774015512 0ustar markusmarkus/*************************************************************************** * This file is part of Robocut. * * Copyright (C) 2010 Tim Hutt * * Copyright (C) 2010 Markus Schulz * * * * 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, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #pragma once #include #include "CuttingThread.h" namespace Ui { class CuttingDialog; } // This is the dialog that shows while the cut is progressing. The thread that does the cutting // is also owned by the dialog, in a slightly bad design. class CuttingDialog : public QDialog { Q_OBJECT public: explicit CuttingDialog(QWidget *parent = 0); ~CuttingDialog(); // Start the cutting thread. Call this only once, before the dialog is shown. // It creates the thread, passes it the cutting details, and runs it. void startCut(QList cuts, double mediawidth, double mediaheigt, int media, int speed, int pressure, bool trackenhancing, bool regmark, bool regsearch, double regwidth, double reglength); protected: void changeEvent(QEvent *e); void closeEvent(QCloseEvent* e); private: Ui::CuttingDialog *ui; // The cutting thread. It is pretty basic - just one long run() routine and then it calls onSuccess() or // onError(). CuttingThread* thread; private slots: // These are called from the thread when it has finished. Only one is called. void onSuccess(); void onError(QString message); }; robocut-1.0.8/CuttingDialog.ui0000644000175000017500000000303511621557774015677 0ustar markusmarkus CuttingDialog 0 0 295 68 Cutting... Cutting Qt::Horizontal QDialogButtonBox::Cancel buttonBox accepted() CuttingDialog accept() 248 254 157 274 buttonBox rejected() CuttingDialog reject() 316 260 286 274