00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
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