Common/Exchange/GCodeUtil.h

Go to the documentation of this file.
00001 //-------------------------------------------------------------------
00004 //  Copyright (c) 2007 Celeritive Technologies, Inc.
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License, or (at your option) any later version.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019 //
00020 //-------------------------------------------------------------------
00021 #pragma once
00022 #ifndef VOLUMILL_GCODEUTIL_H
00023 #define VOLUMILL_GCODEUTIL_H
00024 
00025 #include <Geom/Curve.h>
00026 #include <Exchange/ToolpathRecords.h>
00027 #include <fstream>
00028 #include <vector>
00029 
00030 namespace exchange
00031 {
00032    struct GCodeRecordWriter : public boost::static_visitor<void>
00033    {
00034       GCodeRecordWriter (std::ostream& os, int digits, double rapidZ, double zOffset)
00035          : m_os (os), m_feedrate (0.0), m_shouldWriteFeedrate (true),
00036          m_lastPt (-1e30, -1e30, -1e30),
00037          m_rapidZ (rapidZ), m_zOffset (zOffset)
00038       {
00039          sprintf (m_format, "%%#.%d%s", digits, "lf");
00040          m_os.setf (std::ios::showpoint);
00041       }
00042       geom::Point2d getArcCenter (const geom::Point2d& startPt, const geom::Point2d& endPt, double radius)
00043       {
00044          geom::Vec2d dVec (endPt[0]-startPt[0], endPt[1]-startPt[1]);
00045          geom::Point2d midPt (0.5 * (startPt[0] + endPt[0]), 0.5 * (startPt[1] + endPt[1]));
00046          double d = geom::length (dVec);
00047          dVec /= d;
00048          double distToCenterSq = std::max (radius * radius - (d * d) / 4, 0.0);
00049          geom::Point2d center (midPt + sqrt (distToCenterSq) * geom::Vec2d (-dVec[1], dVec[0]));
00050          return center;
00051       }
00052       void operator() (const exchange::RapidMove& rm)
00053       {
00054          m_os << "G0";
00055          writeX (rm.m_endPt[0]);
00056          writeY (rm.m_endPt[1]);
00057          writeZ ((rm.m_endPt[2] - m_rapidZ) > util::pointResolution ? rm.m_endPt[2] - m_zOffset : rm.m_endPt[2]);
00058          m_os << '\n';
00059       }
00060       void operator() (const exchange::LinearMove& lm)
00061       {
00062          m_os << "G1";
00063          writeX (lm.m_endPt[0]);
00064          writeY (lm.m_endPt[1]);
00065          writeZ (lm.m_endPt[2] - m_zOffset);
00066          writeF (m_feedrate);
00067          m_os << '\n';
00068       }
00069       void operator() (const exchange::ArcCW& cwArc)
00070       {
00071          bool writeIJ = fabs (cwArc.m_endPt[2] - m_lastPt[2]) > 1e-5;
00072          if (writeIJ)
00073          {
00074             geom::Point2d center (getArcCenter (
00075                geom::Point2d (cwArc.m_endPt[0], cwArc.m_endPt[1]),
00076                geom::Point2d (m_lastPt[0], m_lastPt[1]),
00077                cwArc.m_radius));
00078             double i = center[0] - m_lastPt[0];
00079             if (fabs (i) < 1e-4)
00080                i = 0;
00081             double j = center[1] - m_lastPt[1];
00082             if (fabs (j) < 1e-4)
00083                j = 0;
00084             m_os << "G2";
00085             writeX (cwArc.m_endPt[0]);
00086             writeY (cwArc.m_endPt[1]);
00087             writeZ (cwArc.m_endPt[2] - m_zOffset);
00088             writeI (i);
00089             writeJ (j);
00090          }
00091          else
00092          {
00093             m_os << "G2";
00094             writeX (cwArc.m_endPt[0]);
00095             writeY (cwArc.m_endPt[1]);
00096             writeZ (cwArc.m_endPt[2] - m_zOffset);
00097             writeR (cwArc.m_radius);
00098          }
00099          writeF (m_feedrate);
00100          m_os << '\n';
00101       }
00102       void operator() (const exchange::ArcCCW& ccwArc)
00103       {
00104          bool writeIJ = fabs (ccwArc.m_endPt[2] - m_lastPt[2]) > 1e-5;
00105          if (writeIJ)
00106          {
00107             geom::Point2d center (getArcCenter (
00108                geom::Point2d (m_lastPt[0], m_lastPt[1]),
00109                geom::Point2d (ccwArc.m_endPt[0], ccwArc.m_endPt[1]),
00110                ccwArc.m_radius));
00111             double i = center[0] - m_lastPt[0];
00112             if (fabs (i) < 1e-4)
00113                i = 0;
00114             double j = center[1] - m_lastPt[1];
00115             if (fabs (j) < 1e-4)
00116                j = 0;
00117             m_os << "G3";
00118             writeX (ccwArc.m_endPt[0]);
00119             writeY (ccwArc.m_endPt[1]);
00120             writeZ (ccwArc.m_endPt[2] - m_zOffset);
00121             writeI (i);
00122             writeJ (j);
00123          }
00124          else
00125          {
00126             m_os << "G3";
00127             writeX (ccwArc.m_endPt[0]);
00128             writeY (ccwArc.m_endPt[1]);
00129             writeZ (ccwArc.m_endPt[2] - m_zOffset);
00130             writeR (ccwArc.m_radius);
00131          }
00132          writeF (m_feedrate);
00133          m_os << '\n';
00134       }
00135       void operator() (const exchange::FeedRate& fr)
00136       {
00137          if (fabs (m_feedrate - fr.m_feedrate) > 1e-5)
00138          {
00139             m_feedrate = fr.m_feedrate;
00140             m_shouldWriteFeedrate = true;
00141          }
00142       }
00143       void operator() (const exchange::Warning& w)
00144       {
00145          m_warningIds.push_back (w.m_warningId);
00146       }
00147       void operator() (const exchange::CustomRecord&)
00148       {
00149       }
00150       void writeDouble (double d)
00151       {
00152          char s[30];
00153          sprintf (s, m_format, d);
00154          // Remove trailing zeros
00155          int last = strlen (s) - 1;
00156          for (; last > 0 && s[last] == '0'; --last)
00157             s[last] = '\0';
00158          m_os << s;
00159       }
00160       void writeX (double x)
00161       {
00162          if (fabs (x - m_lastPt[0]) > 1e-5)
00163          {
00164             if (fabs (x) < 1e-4)
00165                x = 0;
00166             m_os << " X";
00167             writeDouble (x);
00168             m_lastPt[0] = x;
00169          }
00170       }
00171       void writeY (double y)
00172       {
00173          if (fabs (y - m_lastPt[1]) > 1e-5)
00174          {
00175             if (fabs (y) < 1e-4)
00176                y = 0;
00177             m_os << " Y";
00178             writeDouble (y);
00179             m_lastPt[1] = y;
00180          }
00181       }
00182       void writeZ (double z)
00183       {
00184          if (fabs (z - m_lastPt[2]) > 1e-5)
00185          {
00186             if (fabs (z) < 1e-4)
00187                z = 0;
00188             m_os << " Z";
00189             writeDouble (z);
00190             m_lastPt[2] = z;
00191          }
00192       }
00193       void writeI (double i)
00194       {
00195          m_os << " I";
00196          writeDouble (i);
00197       }
00198       void writeJ (double j)
00199       {
00200          m_os << " J";
00201          writeDouble (j);
00202       }
00203       void writeR (double r)
00204       {
00205          m_os << " R";
00206          writeDouble (r);
00207       }
00208       void writeF (double f)
00209       {
00210          if (m_shouldWriteFeedrate)
00211          {
00212             m_os << " F";
00213             writeDouble (f);
00214             m_shouldWriteFeedrate = false;
00215          }
00216       }
00217       geom::Point3d m_lastPt;
00218       bool m_shouldWriteFeedrate;
00219       double m_feedrate;
00220       std::ostream& m_os;
00221       char m_format[10];
00222       double m_rapidZ;
00223       double m_zOffset;
00224       std::vector<int> m_warningIds;
00225    };
00226 
00227 class GCodeWriter
00228 {
00229 public:
00230    GCodeWriter (const exchange::ToolpathRecords& records, int digits) : m_records (records), m_digits (digits) {}
00231    void operator ()(const char* fileName, const std::string& startUp, const std::string& shutDown,
00232       double rapidZ, double deltaZ, int numberOfCuts)
00233    {
00234       std::ofstream os (fileName);
00235       os << startUp;
00236 
00237       for (int ii=0; ii < numberOfCuts; ++ii)
00238       {
00239          GCodeRecordWriter gcrw (os, m_digits, rapidZ, deltaZ * ii);
00240          for (ToolpathRecords::const_iterator it = m_records.begin(); it != m_records.end(); ++it)
00241             it->apply_visitor (gcrw);
00242          if (ii == 0)
00243             m_warningIds = gcrw.m_warningIds;
00244       }
00245 
00246       os << shutDown;
00247    }
00248    const std::vector<int>& getWarningIds() const { return m_warningIds; }
00249 private:
00250    const exchange::ToolpathRecords& m_records;
00251    int m_digits;
00252    std::vector<int> m_warningIds;
00253 };
00254 }
00255 #endif

Generated on Tue Jan 29 21:37:56 2008 for VoluMill Universal Client by  doxygen 1.4.6