From a0a7feda8902c093c089abdd71230156ccbe5c0d Mon Sep 17 00:00:00 2001 From: Jonathan Westhues Date: Wed, 13 Jan 2010 20:47:17 -0800 Subject: [PATCH] Add G Code export to SolveSpace, similar to SketchFlat. This requires user interface to specify the depth, number of passes, feed, and plunge feed, unfortunately. [git-p4: depot-paths = "//depot/solvespace/": change = 2106] --- confscreen.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++++ export.cpp | 6 ++++- exportvector.cpp | 64 +++++++++++++++++++++++++++++++++++++++++++++ solvespace.cpp | 23 +++++++++++++++++ solvespace.h | 19 ++++++++++++++ ui.h | 67 ++++++++++++++++++++++++++---------------------- wishlist.txt | 3 +++ 7 files changed, 213 insertions(+), 32 deletions(-) diff --git a/confscreen.cpp b/confscreen.cpp index 8de4a719..943db5fa 100644 --- a/confscreen.cpp +++ b/confscreen.cpp @@ -127,6 +127,37 @@ void TextWindow::ScreenChangeCanvasSize(int link, DWORD v) { SS.TW.edit.i = v; } +void TextWindow::ScreenChangeGCodeParameter(int link, DWORD v) { + char buf[1024] = ""; + int row = 95; + switch(link) { + case 'd': + SS.TW.edit.meaning = EDIT_G_CODE_DEPTH; + strcpy(buf, SS.MmToString(SS.gCode.depth)); + row += 0; + break; + + case 's': + SS.TW.edit.meaning = EDIT_G_CODE_PASSES; + sprintf(buf, "%d", SS.gCode.passes); + row += 2; + break; + + case 'F': + SS.TW.edit.meaning = EDIT_G_CODE_FEED; + strcpy(buf, SS.MmToString(SS.gCode.feed)); + row += 4; + break; + + case 'P': + SS.TW.edit.meaning = EDIT_G_CODE_PLUNGE_FEED; + strcpy(buf, SS.MmToString(SS.gCode.plungeFeed)); + row += 6; + break; + } + ShowTextEditControl(row, 14, buf); +} + void TextWindow::ShowConfiguration(void) { int i; Printf(true, "%Ft material color-(r, g, b)"); @@ -259,6 +290,17 @@ void TextWindow::ShowConfiguration(void) { (ccc ? "" : "yes"), (ccc ? "yes" : ""), &ScreenChangeCheckClosedContour, (!ccc ? "" : "no"), (!ccc ? "no" : "")); + + Printf(false, ""); + Printf(false, "%Ft exported g code parameters"); + Printf(false, "%Ba%Ft depth: %Fd%s %Fl%Ld%f[change]%E", + SS.MmToString(SS.gCode.depth), &ScreenChangeGCodeParameter); + Printf(false, "%Bd%Ft passes: %Fd%d %Fl%Ls%f[change]%E", + SS.gCode.passes, &ScreenChangeGCodeParameter); + Printf(false, "%Ba%Ft feed: %Fd%s %Fl%LF%f[change]%E", + SS.MmToString(SS.gCode.feed), &ScreenChangeGCodeParameter); + Printf(false, "%Bd%Ft plunge fd: %Fd%s %Fl%LP%f[change]%E", + SS.MmToString(SS.gCode.plungeFeed), &ScreenChangeGCodeParameter); Printf(false, ""); Printf(false, " %Ftgl vendor %E%s", glGetString(GL_VENDOR)); @@ -359,6 +401,27 @@ bool TextWindow::EditControlDoneForConfiguration(char *s) { } break; } + case EDIT_G_CODE_DEPTH: { + Expr *e = Expr::From(s, true); + if(e) SS.gCode.depth = (float)SS.ExprToMm(e); + break; + } + case EDIT_G_CODE_PASSES: { + Expr *e = Expr::From(s, true); + if(e) SS.gCode.passes = (int)(e->Eval()); + SS.gCode.passes = max(1, min(1000, SS.gCode.passes)); + break; + } + case EDIT_G_CODE_FEED: { + Expr *e = Expr::From(s, true); + if(e) SS.gCode.feed = (float)SS.ExprToMm(e); + break; + } + case EDIT_G_CODE_PLUNGE_FEED: { + Expr *e = Expr::From(s, true); + if(e) SS.gCode.plungeFeed = (float)SS.ExprToMm(e); + break; + } default: return false; } diff --git a/export.cpp b/export.cpp index 383a1376..60349611 100644 --- a/export.cpp +++ b/export.cpp @@ -410,9 +410,13 @@ VectorFileWriter *VectorFileWriter::ForFile(char *filename) { } else if(StringEndsIn(filename, ".step")||StringEndsIn(filename, ".stp")) { static Step2dFileWriter Step2dWriter; ret = &Step2dWriter; + } else if(StringEndsIn(filename, ".txt")) { + static GCodeFileWriter GCodeWriter; + ret = &GCodeWriter; } else { Error("Can't identify output file type from file extension of " - "filename '%s'; try .step, .stp, .dxf, .svg, .plt, .hpgl, .pdf, " + "filename '%s'; try " + ".step, .stp, .dxf, .svg, .plt, .hpgl, .pdf, .txt, " ".eps, or .ps.", filename); return NULL; diff --git a/exportvector.cpp b/exportvector.cpp index 61f8f6c4..a9934f2a 100644 --- a/exportvector.cpp +++ b/exportvector.cpp @@ -612,6 +612,70 @@ void HpglFileWriter::FinishAndCloseFile(void) { fclose(f); } +//----------------------------------------------------------------------------- +// Routines for G Code output. Slightly complicated by our ability to generate +// multiple passes, and to specify the feeds and depth; those parameters get +// set in the configuration screen. +//----------------------------------------------------------------------------- +void GCodeFileWriter::StartFile(void) { + ZERO(&sel); +} +void GCodeFileWriter::StartPath(DWORD strokeRgb, double lineWidth, + bool filled, DWORD fillRgb) +{ +} +void GCodeFileWriter::FinishPath(DWORD strokeRgb, double lineWidth, + bool filled, DWORD fillRgb) +{ +} +void GCodeFileWriter::Triangle(STriangle *tr) { +} + +void GCodeFileWriter::Bezier(SBezier *sb) { + if(sb->deg == 1) { + sel.AddEdge(sb->ctrl[0], sb->ctrl[1]); + } else { + BezierAsPwl(sb); + } +} + +void GCodeFileWriter::FinishAndCloseFile(void) { + SPolygon sp; + ZERO(&sp); + sel.AssemblePolygon(&sp, NULL); + + int i; + for(i = 0; i < SS.gCode.passes; i++) { + double depth = (SS.gCode.depth / SS.gCode.passes)*(i+1); + + SContour *sc; + for(sc = sp.l.First(); sc; sc = sp.l.NextAfter(sc)) { + if(sc->l.n < 2) continue; + + SPoint *pt = sc->l.First(); + fprintf(f, "G00 X%s Y%s\r\n", + SS.MmToString(pt->p.x), SS.MmToString(pt->p.y)); + fprintf(f, "G01 Z%s F%s\r\n", + SS.MmToString(depth), SS.MmToString(SS.gCode.plungeFeed)); + + pt = sc->l.NextAfter(pt); + for(; pt; pt = sc->l.NextAfter(pt)) { + fprintf(f, "G01 X%s Y%s F%s\r\n", + SS.MmToString(pt->p.x), SS.MmToString(pt->p.y), + SS.MmToString(SS.gCode.feed)); + } + // Move up to a clearance plane 5mm above the work. + fprintf(f, "G00 Z%s\r\n", + SS.MmToString(SS.gCode.depth < 0 ? +5 : -5)); + } + } + + sp.Clear(); + sel.Clear(); + fclose(f); +} + + //----------------------------------------------------------------------------- // Routine for STEP output; just a wrapper around the general STEP stuff that // can also be used for surfaces or 3d curves. diff --git a/solvespace.cpp b/solvespace.cpp index b654862c..0167a061 100644 --- a/solvespace.cpp +++ b/solvespace.cpp @@ -94,6 +94,11 @@ void SolveSpace::Init(char *cmdLine) { exportCanvas.height = CnfThawFloat(100.0f, "ExportCanvas_Height"); exportCanvas.dx = CnfThawFloat( 5.0f, "ExportCanvas_Dx"); exportCanvas.dy = CnfThawFloat( 5.0f, "ExportCanvas_Dy"); + // Extra parameters when exporting G code + gCode.depth = CnfThawFloat(10.0f, "GCode_Depth"); + gCode.passes = CnfThawDWORD(1, "GCode_Passes"); + gCode.feed = CnfThawFloat(10.0f, "GCode_Feed"); + gCode.plungeFeed = CnfThawFloat(10.0f, "GCode_PlungeFeed"); // Show toolbar in the graphics window showToolbar = CnfThawDWORD(1, "ShowToolbar"); // Recent files menus @@ -184,6 +189,11 @@ void SolveSpace::Exit(void) { CnfFreezeFloat(exportCanvas.height, "ExportCanvas_Height"); CnfFreezeFloat(exportCanvas.dx, "ExportCanvas_Dx"); CnfFreezeFloat(exportCanvas.dy, "ExportCanvas_Dy"); + // Extra parameters when exporting G code + CnfFreezeFloat(gCode.depth, "GCode_Depth"); + CnfFreezeDWORD(gCode.passes, "GCode_Passes"); + CnfFreezeFloat(gCode.feed, "GCode_Feed"); + CnfFreezeFloat(gCode.plungeFeed, "GCode_PlungeFeed"); // Show toolbar in the graphics window CnfFreezeDWORD(showToolbar, "ShowToolbar"); @@ -421,6 +431,19 @@ void SolveSpace::MenuFile(int id) { case GraphicsWindow::MNU_EXPORT_VIEW: { char exportFile[MAX_PATH] = ""; if(!GetSaveFile(exportFile, VEC_EXT, VEC_PATTERN)) break; + + // If the user is exporting something where it would be + // inappropriate to include the constraints, then warn. + if(SS.GW.showConstraints && + (StringEndsIn(exportFile, ".txt") || + fabs(SS.exportOffset) > LENGTH_EPS)) + { + Message("Constraints are currently shown, and will be exported " + "in the toolpath. This is probably not what you want; " + "hide them by clicking the link at the top of the " + "text window."); + } + SS.ExportViewOrWireframeTo(exportFile, false); break; } diff --git a/solvespace.h b/solvespace.h index c281f323..addfba31 100644 --- a/solvespace.h +++ b/solvespace.h @@ -100,6 +100,7 @@ int SaveFileYesNoCancel(void); "STEP File (*.step;*.stp)\0*.step;*.stp\0" \ "DXF File (*.dxf)\0*.dxf\0" \ "HPGL File (*.plt;*.hpgl)\0*.plt;*.hpgl\0" \ + "G Code (*.txt)\0*.txt\0" \ "All Files (*)\0*\0\0" #define VEC_EXT "pdf" // 3d vector (wireframe lines and curves) format @@ -506,6 +507,18 @@ class Step2dFileWriter : public VectorFileWriter { void StartFile(void); void FinishAndCloseFile(void); }; +class GCodeFileWriter : public VectorFileWriter { +public: + SEdgeList sel; + void StartPath( DWORD strokeRgb, double lineWidth, + bool filled, DWORD fillRgb); + void FinishPath(DWORD strokeRgb, double lineWidth, + bool filled, DWORD fillRgb); + void Triangle(STriangle *tr); + void Bezier(SBezier *sb); + void StartFile(void); + void FinishAndCloseFile(void); +}; #ifdef LIBRARY # define ENTITY EntityBase @@ -600,6 +613,12 @@ public: float dx; float dy; } exportCanvas; + struct { + float depth; + int passes; + float feed; + float plungeFeed; + } gCode; typedef enum { UNIT_MM = 0, diff --git a/ui.h b/ui.h index c57e1bdc..1fff381b 100644 --- a/ui.h +++ b/ui.h @@ -85,43 +85,47 @@ public: static const int EDIT_GROUP_NAME = 2; static const int EDIT_GROUP_SCALE = 3; // For the configuraiton screen - static const int EDIT_LIGHT_DIRECTION = 10; - static const int EDIT_LIGHT_INTENSITY = 11; - static const int EDIT_COLOR = 12; - static const int EDIT_CHORD_TOLERANCE = 13; - static const int EDIT_MAX_SEGMENTS = 14; - static const int EDIT_CAMERA_TANGENT = 15; - static const int EDIT_GRID_SPACING = 16; - static const int EDIT_EXPORT_SCALE = 17; - static const int EDIT_EXPORT_OFFSET = 18; - static const int EDIT_CANVAS_SIZE = 19; + static const int EDIT_LIGHT_DIRECTION = 100; + static const int EDIT_LIGHT_INTENSITY = 101; + static const int EDIT_COLOR = 102; + static const int EDIT_CHORD_TOLERANCE = 103; + static const int EDIT_MAX_SEGMENTS = 104; + static const int EDIT_CAMERA_TANGENT = 105; + static const int EDIT_GRID_SPACING = 106; + static const int EDIT_EXPORT_SCALE = 107; + static const int EDIT_EXPORT_OFFSET = 108; + static const int EDIT_CANVAS_SIZE = 109; + static const int EDIT_G_CODE_DEPTH = 110; + static const int EDIT_G_CODE_PASSES = 111; + static const int EDIT_G_CODE_FEED = 112; + static const int EDIT_G_CODE_PLUNGE_FEED = 113; // For the helical sweep - static const int EDIT_HELIX_TURNS = 20; - static const int EDIT_HELIX_PITCH = 21; - static const int EDIT_HELIX_DRADIUS = 22; + static const int EDIT_HELIX_TURNS = 200; + static const int EDIT_HELIX_PITCH = 201; + static const int EDIT_HELIX_DRADIUS = 202; // For TTF text - static const int EDIT_TTF_TEXT = 30; + static const int EDIT_TTF_TEXT = 300; // For the step dimension screen - static const int EDIT_STEP_DIM_FINISH = 40; - static const int EDIT_STEP_DIM_STEPS = 41; + static const int EDIT_STEP_DIM_FINISH = 400; + static const int EDIT_STEP_DIM_STEPS = 401; // For the styles stuff - static const int EDIT_STYLE_WIDTH = 50; - static const int EDIT_STYLE_TEXT_HEIGHT = 51; - static const int EDIT_STYLE_TEXT_ANGLE = 52; - static const int EDIT_STYLE_COLOR = 53; - static const int EDIT_STYLE_FILL_COLOR = 54; - static const int EDIT_STYLE_NAME = 55; - static const int EDIT_BACKGROUND_COLOR = 56; - static const int EDIT_BACKGROUND_IMG_SCALE = 57; + static const int EDIT_STYLE_WIDTH = 500; + static const int EDIT_STYLE_TEXT_HEIGHT = 501; + static const int EDIT_STYLE_TEXT_ANGLE = 502; + static const int EDIT_STYLE_COLOR = 503; + static const int EDIT_STYLE_FILL_COLOR = 504; + static const int EDIT_STYLE_NAME = 505; + static const int EDIT_BACKGROUND_COLOR = 506; + static const int EDIT_BACKGROUND_IMG_SCALE = 507; // For paste transforming - static const int EDIT_PASTE_TIMES_REPEATED = 60; - static const int EDIT_PASTE_ANGLE = 61; - static const int EDIT_PASTE_SCALE = 62; + static const int EDIT_PASTE_TIMES_REPEATED = 600; + static const int EDIT_PASTE_ANGLE = 601; + static const int EDIT_PASTE_SCALE = 602; // For view - static const int EDIT_VIEW_SCALE = 70; - static const int EDIT_VIEW_ORIGIN = 71; - static const int EDIT_VIEW_PROJ_RIGHT = 72; - static const int EDIT_VIEW_PROJ_UP = 73; + static const int EDIT_VIEW_SCALE = 700; + static const int EDIT_VIEW_ORIGIN = 701; + static const int EDIT_VIEW_PROJ_RIGHT = 702; + static const int EDIT_VIEW_PROJ_UP = 703; struct { bool showAgain; int meaning; @@ -219,6 +223,7 @@ public: static void ScreenChangeGridSpacing(int link, DWORD v); static void ScreenChangeExportScale(int link, DWORD v); static void ScreenChangeExportOffset(int link, DWORD v); + static void ScreenChangeGCodeParameter(int link, DWORD v); static void ScreenChangeStyleName(int link, DWORD v); static void ScreenChangeStyleWidthOrTextHeight(int link, DWORD v); static void ScreenChangeStyleTextAngle(int link, DWORD v); diff --git a/wishlist.txt b/wishlist.txt index 9b8387e0..5467e987 100644 --- a/wishlist.txt +++ b/wishlist.txt @@ -1,3 +1,6 @@ +better Error() and Message() dialog boxes +lock point where dragged constraint +projected and signed distance constraints ----- better level of detail