├── .gitignore ├── GCodeFile.cs ├── GCodeLine.cs ├── LICENSE ├── Properties └── AssemblyInfo.cs ├── README.md ├── assemblers ├── AssemblerUtil.cs ├── BaseDepositionAssembler.cs ├── BaseMillingAssembler.cs ├── ExtrusionMath.cs ├── GenericMillingAssembler.cs ├── MakerbotAssembler.cs └── RepRapAssembler.cs ├── builders ├── GCodeBuilder.cs ├── GCodeFileAccumulator.cs └── IGCodeAccumulator.cs ├── gsGCode.asmdef ├── gsGCode.csproj ├── interpreters ├── BiesseInterpreter.cs ├── GCodeInterpreter.cs ├── GCodeToPlanarComplex.cs ├── MakerbotInterpreter.cs └── ThreeAxisCNCInterpreter.cs ├── parsers ├── GCodeUtil.cs └── GenericGCodeParser.cs ├── settings ├── AdditiveSettings.cs ├── FlashforgeSettings.cs ├── GenericPrinterSettings.cs ├── MakerbotSettings.cs ├── MonopriceSettings.cs ├── PrintrbotSettings.cs ├── PrusaSettings.cs ├── RepRapSettings.cs └── manufacturers.txt └── writers ├── BaseGCodeWriter.cs └── StandardGCodeWriter.cs /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | gsGCode/bin 31 | gsGCode/obj 32 | gsGCode.csproj.user 33 | bin 34 | obj 35 | *.meta 36 | -------------------------------------------------------------------------------- /GCodeFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace gs 7 | { 8 | 9 | 10 | public class GCodeFile 11 | { 12 | 13 | List lines; 14 | 15 | 16 | 17 | public GCodeFile() 18 | { 19 | lines = new List(); 20 | } 21 | 22 | 23 | public void AppendLine(GCodeLine l) 24 | { 25 | lines.Add(l); 26 | } 27 | 28 | 29 | public int LineCount { 30 | get { return lines.Count; } 31 | } 32 | 33 | 34 | public IEnumerable AllLines() 35 | { 36 | int N = lines.Count; 37 | for (int i = 0; i < N; ++i) { 38 | yield return lines[i]; 39 | } 40 | } 41 | 42 | 43 | public IEnumerable AllLinesOfType(GCodeLine.LType eType) 44 | { 45 | int N = lines.Count; 46 | for (int i = 0; i < N; ++i) { 47 | if ( lines[i].type == eType ) 48 | yield return lines[i]; 49 | } 50 | } 51 | 52 | 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /GCodeLine.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | 10 | 11 | 12 | public struct GCodeParam 13 | { 14 | public enum PType 15 | { 16 | Code, 17 | DoubleValue, 18 | IntegerValue, 19 | TextValue, 20 | NoValue, 21 | Unknown 22 | } 23 | 24 | public PType type; 25 | public string identifier; 26 | 27 | public double doubleValue; 28 | public int intValue { 29 | get { return (int)doubleValue; } // we can store [-2^54, 2^54] precisely in a double 30 | set { doubleValue = value; } 31 | } 32 | public string textValue; 33 | } 34 | 35 | 36 | 37 | 38 | // ugh..class...dangerous!! 39 | public class GCodeLine 40 | { 41 | public enum LType 42 | { 43 | GCode, 44 | MCode, 45 | UnknownCode, 46 | 47 | Comment, 48 | UnknownString, 49 | Blank, 50 | 51 | If, 52 | EndIf, 53 | Else, 54 | UnknownControl 55 | } 56 | 57 | 58 | 59 | public int lineNumber; 60 | 61 | public LType type; 62 | public string orig_string; 63 | 64 | public int N; // N number of line 65 | public int code; // G or M code 66 | public GCodeParam[] parameters; // arguments/parameters 67 | 68 | public string comment; 69 | 70 | public GCodeLine(int num, LType type) 71 | { 72 | lineNumber = num; 73 | this.type = type; 74 | 75 | orig_string = null; 76 | N = code = -1; 77 | parameters = null; 78 | comment = null; 79 | } 80 | 81 | public GCodeLine(int lineNum, LType type, string comment) { 82 | lineNumber = lineNum; 83 | this.type = type; 84 | if ( type == LType.UnknownString ) { 85 | this.orig_string = comment; 86 | } else { 87 | this.comment = comment; 88 | } 89 | } 90 | 91 | 92 | public virtual GCodeLine Clone() { 93 | GCodeLine clone = new GCodeLine(this.lineNumber, this.type); 94 | clone.orig_string = this.orig_string; 95 | clone.N = this.N; 96 | clone.code = this.code; 97 | if ( this.parameters != null ) { 98 | clone.parameters = new GCodeParam[this.parameters.Length]; 99 | for (int i = 0; i < this.parameters.Length; ++i ) 100 | clone.parameters[i] = this.parameters[i]; 101 | } 102 | clone.comment = this.comment; 103 | return clone; 104 | } 105 | 106 | } 107 | 108 | 109 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 gradientspace 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | #if !G3_USING_UNITY 2 | 3 | using System.Reflection; 4 | using System.Runtime.CompilerServices; 5 | using System.Runtime.InteropServices; 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("gsGCode")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("gradientspae")] 14 | [assembly: AssemblyProduct("gsGCode")] 15 | [assembly: AssemblyCopyright("Copyright © ryan schmidt 2017")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("25de77c9-14a4-4562-9a24-0bf1e612d9a9")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Build and Revision Numbers 35 | // by using the '*' as shown below: 36 | // [assembly: AssemblyVersion("1.0.*")] 37 | [assembly: AssemblyVersion("1.0.0.0")] 38 | [assembly: AssemblyFileVersion("1.0.0.0")] 39 | 40 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gsGCode 2 | 3 | GCode parsing / manipulation / generation library. 4 | 5 | C#, MIT License. Copyright 2017 ryan schmidt / gradientspace 6 | 7 | Dependencies: [geometry3Sharp](https://github.com/gradientspace/geometry3Sharp) (Boost license) 8 | 9 | questions? get in touch on twitter: [@rms80](http://www.twitter.com/rms80) or [@gradientspace](http://www.twitter.com/gradientspace), 10 | or email [rms@gradientspace.com](mailto:rms@gradientspace.com?subject=gsGCode). 11 | 12 | # What Is This? 13 | 14 | gsGCode is a library for working with GCode. Not just generating GCode, but also reading and manipulating existing GCode files. 15 | 16 | What? Edit a GCode file? that's crazy, right? CAD people used to think the same thing about STL mesh files too. 17 | STL was something you wrote out to communicate with a CNC machine. You might "repair" it, but you didn't edit it. 18 | But then a guy wrote [OpenSCAD](http://www.openscad.org/), and I wrote [Meshmixer](http://www.meshmixer.com), and now STL 19 | files are something that thousands of people open and edit every day. 20 | 21 | The purpose of this library is to make the same thing possible for GCode. GCode is just 3D lines, curves, and 22 | control commands. There is no reason you can't open a GCode file, change one of the paths, and write it back out. 23 | You can easily do that with this library. 24 | 25 | # Can It Write GCode Too? 26 | 27 | Yes! I'm developing gsGCode to support the gradientspace Slicer, which is not released yet. But the low-level GCode generation 28 | infrastructure is all here. You can either use **GCodeBuilder** to construct a **GCodeFile** line-by-line, or an Assembler 29 | (currently only **MakerbotAssembler**) which provides a higher-level turtle-graphics-like API. 30 | 31 | # How? 32 | 33 | See [the wiki](https://github.com/gradientspace/gsGCode/wiki) for what minimal documentation exists right now. 34 | Some sample code will come in time. 35 | -------------------------------------------------------------------------------- /assemblers/AssemblerUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using g3; 3 | 4 | namespace gs 5 | { 6 | /// 7 | /// Utility functions for gcode assemblers 8 | /// 9 | public static class AssemblerUtil 10 | { 11 | 12 | /// 13 | /// Calculate distance of filament to extrude to draw path of 14 | /// given length/width/height, for given filament diameter. 15 | /// 16 | public static double CalculateExtrudedFilament( 17 | double pathWidth, double pathHeight, double pathLen, 18 | double filamentDiam ) 19 | { 20 | // [RMS] this is just formula form gsSlicer.CalculateExtrusion 21 | double section_area = pathWidth * pathHeight; 22 | double linear_vol = pathLen * section_area; 23 | double fil_rad = filamentDiam / 2; 24 | double fil_area = Math.PI * fil_rad * fil_rad; 25 | double fil_len = linear_vol / fil_area; 26 | return fil_len; 27 | } 28 | 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /assemblers/BaseDepositionAssembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | using gs; 7 | 8 | namespace gs 9 | { 10 | 11 | public interface IGCodeAssembler 12 | { 13 | } 14 | 15 | public interface IDepositionAssembler : IGCodeAssembler 16 | { 17 | } 18 | 19 | 20 | public delegate BaseDepositionAssembler AssemblerFactoryF(GCodeBuilder builder, SingleMaterialFFFSettings settings); 21 | 22 | 23 | /// 24 | /// Assembler translates high-level commands from Compiler (eg MoveTo, ExtrudeTo, BeginRetract, etc) 25 | /// into GCode instructions, which it passes to GCodeBuilder instance. 26 | /// 27 | /// To do this, Assembler maintains state machine for things like current nozzle position, 28 | /// extruder position, etc. 29 | /// 30 | /// TODO: 31 | /// - need to reset accumulated extrusion distance to 0 once in a while, 32 | /// to avoid precision issues. 33 | /// - support relative mode for position and extruder 34 | /// 35 | /// 36 | /// 37 | public abstract class BaseDepositionAssembler : IDepositionAssembler 38 | { 39 | public GCodeBuilder Builder; 40 | 41 | public enum ExtrudeParamType { 42 | ExtrudeParamA, ExtrudeParamE 43 | } 44 | 45 | /// 46 | /// Different machines use A or E for the extrude parameter 47 | /// 48 | public ExtrudeParamType ExtrudeParam = ExtrudeParamType.ExtrudeParamE; 49 | 50 | /// 51 | /// To keep things simple, we use the absolute coordinates of the slice polygons 52 | /// at the higher levels. However the printer often operates in some other coordinate 53 | /// system, for example relative to front-left corner. PositionShift is added to all x/y 54 | /// coordinates before they are passed to the GCodeBuilder. 55 | /// 56 | public Vector2d PositionShift = Vector2d.Zero; 57 | 58 | 59 | /// 60 | /// check that all points lie within bounds 61 | /// 62 | public bool EnableBoundsChecking = true; 63 | 64 | /// 65 | /// if EnableBoundsChecking=true, will assert if we try to move outside these bounds 66 | /// 67 | public AxisAlignedBox2d PositionBounds = AxisAlignedBox2d.Infinite; 68 | 69 | 70 | /// 71 | /// Generally, deposition-style 3D printers cannot handle large numbers of very small GCode steps. 72 | /// The result will be very chunky. 73 | /// So, we will cluster sequences of tiny steps into something that can actually be printed. 74 | /// 75 | public double MinExtrudeStepDistance = 0.0f; // is set to FFFMachineInfo.MinPointSpacingMM in constructor below!! 76 | 77 | 78 | // Makerbot uses G1 for travel as well as extrude, so need to be able to override this 79 | public int TravelGCode = 0; 80 | 81 | public bool OmitDuplicateZ = false; 82 | public bool OmitDuplicateF = false; 83 | public bool OmitDuplicateE = false; 84 | 85 | // threshold for omitting "duplicate" Z/F/E parameters 86 | public double MoveEpsilon = 0.00001; 87 | 88 | 89 | public BaseDepositionAssembler(GCodeBuilder useBuilder, FFFMachineInfo machineInfo) 90 | { 91 | Builder = useBuilder; 92 | currentPos = Vector3d.Zero; 93 | lastPos = Vector3d.Zero; 94 | extruderA = 0; 95 | currentFeed = 0; 96 | 97 | Vector2d originRepositioning = new Vector2d(machineInfo.BedOriginFactorX, machineInfo.BedOriginFactorY); 98 | Vector2d bedSize = new Vector2d(machineInfo.BedSizeXMM, machineInfo.BedSizeYMM); 99 | PositionShift = originRepositioning*bedSize; 100 | 101 | MinExtrudeStepDistance = machineInfo.MinPointSpacingMM; 102 | } 103 | 104 | 105 | /* 106 | * Subclasses must implement these 107 | */ 108 | 109 | public abstract void AppendHeader(); 110 | public abstract void AppendFooter(); 111 | public abstract void EnableFan(); 112 | public abstract void DisableFan(); 113 | public abstract void UpdateProgress(int i); 114 | public abstract void ShowMessage(string s); 115 | 116 | /* 117 | * These seem standard enough that we will provide a default implementation 118 | */ 119 | public virtual void SetExtruderTargetTemp(int temp, string comment = "set extruder temp C") 120 | { 121 | Builder.BeginMLine(104, comment).AppendI("S", temp); 122 | } 123 | public virtual void SetExtruderTargetTempAndWait(int temp, string comment = "set extruder temp C, and wait") 124 | { 125 | Builder.BeginMLine(109, comment).AppendI("S", temp); 126 | } 127 | 128 | public virtual void SetBedTargetTemp(int temp, string comment = "set bed temp C") 129 | { 130 | Builder.BeginMLine(140, comment).AppendI("S", temp); 131 | } 132 | public virtual void SetBedTargetTempAndWait(int temp, string comment = "set bed temp C, and wait") 133 | { 134 | Builder.BeginMLine(190, comment).AppendI("S", temp); 135 | } 136 | 137 | 138 | /* 139 | * Position commands 140 | */ 141 | 142 | protected Vector3d currentPos; 143 | protected Vector3d lastPos; 144 | public Vector3d NozzlePosition 145 | { 146 | get { 147 | return lastPos; 148 | } 149 | } 150 | 151 | protected double currentFeed; 152 | public double FeedRate 153 | { 154 | get { return currentFeed; } 155 | } 156 | 157 | protected double extruderA; 158 | public double ExtruderA 159 | { 160 | get { return extruderA; } 161 | } 162 | 163 | protected bool in_retract; 164 | protected double retractA; 165 | public bool InRetract 166 | { 167 | get { return in_retract; } 168 | } 169 | 170 | protected bool in_travel; 171 | public bool InTravel 172 | { 173 | get { return in_travel; } 174 | } 175 | 176 | public bool InExtrude { 177 | get { return InTravel == false; } 178 | } 179 | 180 | 181 | 182 | 183 | /* 184 | * Code below is all to support MinExtrudeStepDistance > 0 185 | * In that case, we want to only emit the next gcode extrusion point once we have travelled 186 | * at least MinExtrudeStepDistance distance. To do that, we will skip points 187 | * until we have moved far enough, then emit one. 188 | * 189 | * Currently we are saving all the skipped points in a queue, although we only use 190 | * the last two to emit. Current strategy is to lerp along the last line segment, 191 | * so that the emitted point is exactly at linear-arc-length MinExtrudeStepDistance. 192 | * The remainder of the last line goes back on the queue. 193 | * 194 | * This does end up clipping sharp corners if they are made of multiple closely-spaced 195 | * points. However the scale of the clipping should be on the order of the filament 196 | * width, so it probably doesn't make a visual difference. And (anecdotally) it may 197 | * actually produce cleaner results in the corners... 198 | * 199 | * [TODO] This is actually speed-dependent. We could modulate the clipping step size 200 | * by the movement speed. Or, we could slow down to hit the higher precision? 201 | * Might be preferable to just be consistent per layer, though... 202 | */ 203 | 204 | 205 | 206 | // stores info we need to emit an extrude gcode point 207 | protected struct QueuedExtrude 208 | { 209 | public Vector3d toPos; 210 | public double feedRate; 211 | public double extruderA; 212 | public char extrudeChar; 213 | public string comment; 214 | 215 | static public QueuedExtrude lerp(ref QueuedExtrude a, ref QueuedExtrude b, double t) 216 | { 217 | QueuedExtrude newp = new QueuedExtrude(); 218 | newp.toPos = Vector3d.Lerp(a.toPos, b.toPos, t); 219 | newp.feedRate = Math.Max(a.feedRate, b.feedRate); 220 | newp.extruderA = MathUtil.Lerp(a.extruderA, b.extruderA, t); 221 | newp.extrudeChar = a.extrudeChar; 222 | newp.comment = (a.comment == null) ? a.comment : b.comment; 223 | return newp; 224 | } 225 | } 226 | 227 | 228 | protected QueuedExtrude[] extrude_queue = new QueuedExtrude[1024]; 229 | protected double extrude_queue_len = 0; 230 | int next_queue_index = 0; 231 | 232 | 233 | // we do not actually queue travel moves, but we might need to flush extrude queue 234 | protected virtual void queue_travel(Vector3d toPos, double feedRate, string comment) 235 | { 236 | Util.gDevAssert(InExtrude == false); 237 | if (EnableBoundsChecking && PositionBounds.Contains(toPos.xy) == false) 238 | throw new Exception("BaseDepositionAssembler.queue_move: tried to move outside of bounds!"); 239 | 240 | lastPos = toPos; 241 | 242 | // flush any pending extrude 243 | flush_extrude_queue(); 244 | 245 | emit_travel(toPos, feedRate, comment); 246 | } 247 | 248 | // actually emit travel move gcode 249 | protected virtual void emit_travel(Vector3d toPos, double feedRate, string comment) 250 | { 251 | double write_x = toPos.x + PositionShift.x; 252 | double write_y = toPos.y + PositionShift.y; 253 | 254 | Builder.BeginGLine(TravelGCode, comment). 255 | AppendF("X", write_x).AppendF("Y", write_y); 256 | 257 | if (OmitDuplicateZ == false || MathUtil.EpsilonEqual(currentPos.z, toPos.z, MoveEpsilon) == false) { 258 | Builder.AppendF("Z", toPos.z); 259 | } 260 | if (OmitDuplicateF == false || MathUtil.EpsilonEqual(currentFeed, feedRate, MoveEpsilon) == false) { 261 | Builder.AppendF("F", feedRate); 262 | } 263 | 264 | currentPos = toPos; 265 | currentFeed = feedRate; 266 | } 267 | 268 | 269 | // push an extrude move onto queue 270 | protected virtual void queue_extrude(Vector3d toPos, double feedRate, double e, char extrudeChar, string comment, bool bIsRetract) 271 | { 272 | Util.gDevAssert(InExtrude || bIsRetract); 273 | if (EnableBoundsChecking && PositionBounds.Contains(toPos.xy) == false) 274 | throw new Exception("BaseDepositionAssembler.queue_extrude: tried to move outside of bounds!"); 275 | 276 | lastPos = toPos; 277 | 278 | QueuedExtrude p = new QueuedExtrude() { 279 | toPos = toPos, feedRate = feedRate, extruderA = e, extrudeChar = extrudeChar, comment = comment 280 | }; 281 | 282 | // we cannot queue a retract, so flush queue and emit the retract/unretract 283 | bool bForceEmit = (bIsRetract) || (toPos.z != NozzlePosition.z); 284 | if (bForceEmit) { 285 | flush_extrude_queue(); 286 | emit_extrude(p); 287 | return; 288 | } 289 | 290 | // push this point onto queue. this will also update the extrude_queue_len 291 | double prev_len = extrude_queue_len; 292 | append_to_queue(p); 293 | 294 | // if we haven't moved far enough to emit a point, we wait 295 | if (extrude_queue_len < MinExtrudeStepDistance) { 296 | return; 297 | } 298 | // ok we moved far enough from last point to emit 299 | 300 | // if queue has one point, just emit it 301 | int last_i = next_queue_index-1; 302 | if (last_i == 0) { 303 | flush_extrude_queue(); 304 | return; 305 | } 306 | 307 | // otherwise we lerp between last two points so that we emit at 308 | // point where accumulated linear arclength is exactly MinExtrudeStepDistance. 309 | double a = prev_len, b = extrude_queue_len; 310 | double t = (MinExtrudeStepDistance-a) / (b-a); 311 | Util.gDevAssert(t > -0.0001 && t < 1.0001); 312 | t = MathUtil.Clamp(t, 0, 1); 313 | QueuedExtrude last_p = extrude_queue[next_queue_index - 1]; 314 | QueuedExtrude emit_p = QueuedExtrude.lerp(ref extrude_queue[next_queue_index-2], ref last_p, t); 315 | 316 | // emit and clear queue 317 | emit_extrude(emit_p); 318 | next_queue_index = 0; 319 | extrude_queue_len = 0; 320 | 321 | // now we re-submit last point. This pushes the remaining bit of the last segment 322 | // back onto the queue. (should we skip this if t > nearly-one?) 323 | queue_extrude(last_p.toPos, last_p.feedRate, last_p.extruderA, last_p.extrudeChar, last_p.comment, false); 324 | } 325 | protected virtual void queue_extrude_to(Vector3d toPos, double feedRate, double extrudeDist, string comment, bool bIsRetract) 326 | { 327 | if (ExtrudeParam == ExtrudeParamType.ExtrudeParamA) 328 | queue_extrude(toPos, feedRate, extrudeDist, 'A', comment, bIsRetract); 329 | else 330 | queue_extrude(toPos, feedRate, extrudeDist, 'E', comment, bIsRetract); 331 | } 332 | 333 | // emit gcode for an extrude move 334 | protected virtual void emit_extrude(QueuedExtrude p) 335 | { 336 | double write_x = p.toPos.x + PositionShift.x; 337 | double write_y = p.toPos.y + PositionShift.y; 338 | Builder.BeginGLine(1, p.comment). 339 | AppendF("X", write_x).AppendF("Y", write_y); 340 | 341 | if (OmitDuplicateZ == false || MathUtil.EpsilonEqual(p.toPos.z, currentPos.z, MoveEpsilon) == false) { 342 | Builder.AppendF("Z", p.toPos.z); 343 | } 344 | if (OmitDuplicateF == false || MathUtil.EpsilonEqual(p.feedRate, currentFeed, MoveEpsilon) == false) { 345 | Builder.AppendF("F", p.feedRate); 346 | } 347 | if (OmitDuplicateE == false || MathUtil.EpsilonEqual(p.extruderA, extruderA, MoveEpsilon) == false) { 348 | Builder.AppendF(p.extrudeChar.ToString(), p.extruderA); 349 | } 350 | 351 | currentPos = p.toPos; 352 | currentFeed = p.feedRate; 353 | extruderA = p.extruderA; 354 | } 355 | 356 | // push point onto queue and update accumulated length 357 | protected virtual void append_to_queue(QueuedExtrude p) 358 | { 359 | double dt = (next_queue_index == 0) ? 360 | currentPos.xy.Distance(p.toPos.xy) : extrude_queue[next_queue_index-1].toPos.xy.Distance(p.toPos.xy); 361 | extrude_queue_len += dt; 362 | 363 | extrude_queue[next_queue_index] = p; 364 | next_queue_index = Math.Min(next_queue_index + 1, extrude_queue.Length - 1); ; 365 | } 366 | 367 | // emit point at end of queue and clear it 368 | protected virtual void flush_extrude_queue() 369 | { 370 | if (next_queue_index > 0) { 371 | emit_extrude(extrude_queue[next_queue_index - 1]); 372 | next_queue_index = 0; 373 | } 374 | extrude_queue_len = 0; 375 | } 376 | 377 | 378 | 379 | /* 380 | * Assembler API that Compiler uses 381 | */ 382 | 383 | 384 | public virtual void AppendMoveTo(double x, double y, double z, double f, string comment = null) 385 | { 386 | queue_travel(new Vector3d(x, y, z), f, comment); 387 | } 388 | public virtual void AppendMoveTo(Vector3d pos, double f, string comment = null) 389 | { 390 | AppendMoveTo(pos.x, pos.y, pos.z, f, comment); 391 | } 392 | 393 | 394 | 395 | public virtual void AppendExtrudeTo(Vector3d pos, double feedRate, double extrudeDist, string comment = null) 396 | { 397 | if (ExtrudeParam == ExtrudeParamType.ExtrudeParamA) 398 | AppendMoveToA(pos, feedRate, extrudeDist, comment); 399 | else 400 | AppendMoveToE(pos, feedRate, extrudeDist, comment); 401 | } 402 | 403 | 404 | protected virtual void AppendMoveToE(double x, double y, double z, double f, double e, string comment = null) 405 | { 406 | queue_extrude(new Vector3d(x, y, z), f, e, 'E', comment, false); 407 | } 408 | protected virtual void AppendMoveToE(Vector3d pos, double f, double e, string comment = null) 409 | { 410 | AppendMoveToE(pos.x, pos.y, pos.z, f, e, comment); 411 | } 412 | 413 | 414 | protected virtual void AppendMoveToA(double x, double y, double z, double f, double a, string comment = null) 415 | { 416 | queue_extrude(new Vector3d(x, y, z), f, a, 'A', comment, false); 417 | } 418 | protected virtual void AppendMoveToA(Vector3d pos, double f, double a, string comment = null) 419 | { 420 | AppendMoveToA(pos.x, pos.y, pos.z, f, a, comment); 421 | } 422 | 423 | 424 | 425 | public virtual void BeginRetractRelativeDist(Vector3d pos, double feedRate, double extrudeDelta, string comment = null) 426 | { 427 | BeginRetract(pos, feedRate, ExtruderA + extrudeDelta, comment); 428 | } 429 | public virtual void BeginRetract(Vector3d pos, double feedRate, double extrudeDist, string comment = null) { 430 | if (in_retract) 431 | throw new Exception("BaseDepositionAssembler.BeginRetract: already in retract!"); 432 | if (extrudeDist > extruderA) 433 | throw new Exception("BaseDepositionAssembler.BeginRetract: retract extrudeA is forward motion!"); 434 | 435 | // need to flush any pending extrudes here, so that extruderA is at actual last extrude value 436 | flush_extrude_queue(); 437 | retractA = extruderA; 438 | queue_extrude_to(pos, feedRate, extrudeDist, (comment == null) ? "Retract" : comment, true); 439 | in_retract = true; 440 | } 441 | 442 | 443 | public virtual void EndRetract(Vector3d pos, double feedRate, double extrudeDist = -9999, string comment = null) { 444 | if (! in_retract) 445 | throw new Exception("BaseDepositionAssembler.EndRetract: already in retract!"); 446 | if (extrudeDist != -9999 && MathUtil.EpsilonEqual(extrudeDist, retractA, 0.0001) == false ) 447 | throw new Exception("BaseDepositionAssembler.EndRetract: restart position is not same as start of retract!"); 448 | if (extrudeDist == -9999) 449 | extrudeDist = retractA; 450 | queue_extrude_to(pos, feedRate, extrudeDist, (comment == null) ? "End Retract" : comment, true); 451 | in_retract = false; 452 | } 453 | 454 | 455 | public virtual void BeginTravel() { 456 | if (in_travel) 457 | throw new Exception("BaseDepositionAssembler.BeginTravel: already in travel!"); 458 | in_travel = true; 459 | } 460 | 461 | 462 | public virtual void EndTravel() 463 | { 464 | if (in_travel == false) 465 | throw new Exception("BaseDepositionAssembler.EndTravel: not in travel!"); 466 | in_travel = false; 467 | } 468 | 469 | 470 | public virtual void AppendTravelTo(double x, double y, double z, double f) 471 | { 472 | throw new NotImplementedException("BaseDepositionAssembler.AppendTravelTo"); 473 | } 474 | 475 | 476 | public virtual void AppendComment(string comment) 477 | { 478 | Builder.AddCommentLine(comment); 479 | } 480 | 481 | 482 | public virtual void AppendDwell(int milliseconds, string comment = null) 483 | { 484 | flush_extrude_queue(); 485 | 486 | Builder.BeginGLine(4, (comment != null) ? comment : "dwell" ) 487 | .AppendI("P", milliseconds); 488 | } 489 | 490 | 491 | public virtual void AppendResetExtrudedLength() 492 | { 493 | if (in_retract) 494 | throw new Exception("BaseDepositionAssembler.AppendResetExtrudedLength: cannot reset during retract!"); 495 | flush_extrude_queue(); 496 | Builder.BeginGLine(92, "reset extruded length").AppendI("E", 0); 497 | extruderA = 0; 498 | } 499 | 500 | 501 | /// 502 | /// Assembler may internally queue up a series of points, to optimize gcode emission. 503 | /// Call this to ensure that everything is written out to GCodeBuilder 504 | /// 505 | public virtual void FlushQueues() 506 | { 507 | flush_extrude_queue(); 508 | } 509 | 510 | 511 | 512 | 513 | protected virtual void AddStandardHeader(SingleMaterialFFFSettings Settings) 514 | { 515 | Builder.AddCommentLine("; Generated on " + DateTime.Now.ToLongDateString() + " by Gradientspace gsSlicer"); 516 | Builder.AddCommentLine(string.Format("; Printer: {0} {1}", Settings.Machine.ManufacturerName, Settings.Machine.ModelIdentifier)); 517 | Builder.AddCommentLine("; Print Settings"); 518 | Builder.AddCommentLine("; Layer Height: " + Settings.LayerHeightMM); 519 | Builder.AddCommentLine("; Nozzle Diameter: " + Settings.Machine.NozzleDiamMM + " Filament Diameter: " + Settings.Machine.FilamentDiamMM); 520 | Builder.AddCommentLine("; Extruder Temp: " + Settings.ExtruderTempC); 521 | Builder.AddCommentLine(string.Format("; Speeds Extrude: {0} Travel: {1} Z: {2}", Settings.RapidExtrudeSpeed, Settings.RapidTravelSpeed, Settings.ZTravelSpeed)); 522 | Builder.AddCommentLine(string.Format("; Retract Distance: {0} Speed: {1}", Settings.RetractDistanceMM, Settings.RetractSpeed)); 523 | Builder.AddCommentLine(string.Format("; Shells: {0} InteriorShells: {1}", Settings.Shells, Settings.InteriorSolidRegionShells)); 524 | Builder.AddCommentLine(string.Format("; RoofLayers: {0} FloorLayers: {1}", Settings.RoofLayers, Settings.FloorLayers)); 525 | Builder.AddCommentLine(string.Format("; InfillX: {0}", Settings.SparseLinearInfillStepX)); 526 | Builder.AddCommentLine(string.Format("; Support: {0} Angle {1} SpacingX: {2} Shell: {3} Gap: {4} VolScale: {5}", 527 | Settings.GenerateSupport, Settings.SupportOverhangAngleDeg, Settings.SupportSpacingStepX, Settings.EnableSupportShell, Settings.SupportSolidSpace, Settings.SupportVolumeScale)); 528 | Builder.AddCommentLine(string.Format("; ClipOverlaps: {0} Tolerance: {1}", Settings.ClipSelfOverlaps, Settings.SelfOverlapToleranceX)); 529 | Builder.AddCommentLine(string.Format("; LayerRange: {0}-{1}", Settings.LayerRangeFilter.a, Settings.LayerRangeFilter.b)); 530 | } 531 | 532 | 533 | 534 | 535 | 536 | 537 | protected virtual void AddPrimeLine(SingleMaterialFFFSettings Settings) 538 | { 539 | Builder.AddCommentLine("---begin prime type=line"); 540 | 541 | // extruder prime by drawing line across front of bed 542 | double PrimeHeight = Settings.Machine.MaxLayerHeightMM; 543 | double PrimeWidth = 2 * Settings.Machine.NozzleDiamMM; 544 | 545 | // assumes origin is at center of bed... 546 | Vector3d frontRight = new Vector3d(Settings.Machine.BedSizeXMM / 2, -Settings.Machine.BedSizeYMM / 2, PrimeHeight); 547 | frontRight.x -= 10; 548 | frontRight.y += 5; 549 | Vector3d frontLeft = frontRight; frontLeft.x = -frontRight.x; 550 | 551 | double primeLen = frontRight.Distance(frontLeft); 552 | 553 | double PrimeFeedRate = 1800; 554 | double prime_feed_len = AssemblerUtil.CalculateExtrudedFilament( 555 | PrimeWidth, PrimeHeight, primeLen, Settings.Machine.FilamentDiamMM); 556 | 557 | Builder.BeginGLine(92, "reset extruded length").AppendI("E", 0); 558 | BeginTravel(); 559 | AppendMoveTo(frontRight, 9000, "start prime"); 560 | EndTravel(); 561 | AppendExtrudeTo(frontLeft, PrimeFeedRate, prime_feed_len, "extrude prime"); 562 | 563 | AppendResetExtrudedLength(); 564 | 565 | Builder.AddCommentLine("---end prime"); 566 | } 567 | 568 | 569 | 570 | 571 | } 572 | 573 | 574 | } -------------------------------------------------------------------------------- /assemblers/BaseMillingAssembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | using gs; 7 | 8 | namespace gs 9 | { 10 | 11 | public interface IMillingAssembler : IGCodeAssembler 12 | { 13 | } 14 | 15 | 16 | public delegate BaseMillingAssembler MillingAssemblerFactoryF(GCodeBuilder builder, SingleMaterialFFFSettings settings); 17 | 18 | 19 | /// 20 | /// Assembler translates high-level commands from Compiler (eg MoveTo, BeginRetract, etc) 21 | /// into GCode instructions, which it passes to GCodeBuilder instance. 22 | /// 23 | /// To do this, Assembler maintains state machine for things like current tool position 24 | /// 25 | /// TODO: 26 | /// - support relative mode 27 | /// 28 | /// 29 | public abstract class BaseMillingAssembler : IMillingAssembler 30 | { 31 | public GCodeBuilder Builder; 32 | 33 | /// 34 | /// To keep things simple, we use the absolute coordinates of the slice polygons 35 | /// at the higher levels. However the printer often operates in some other coordinate 36 | /// system, for example relative to front-left corner. PositionShift is added to all x/y 37 | /// coordinates before they are passed to the GCodeBuilder. 38 | /// 39 | public Vector2d PositionShift = Vector2d.Zero; 40 | 41 | 42 | /// 43 | /// check that all points lie within bounds 44 | /// 45 | public bool EnableBoundsChecking = true; 46 | 47 | /// 48 | /// if EnableBoundsChecking=true, will assert if we try to move outside these bounds 49 | /// 50 | public AxisAlignedBox2d PositionBounds = AxisAlignedBox2d.Infinite; 51 | 52 | public bool OmitDuplicateZ = false; 53 | public bool OmitDuplicateF = false; 54 | 55 | // threshold for omitting "duplicate" Z/F parameters 56 | public double MoveEpsilon = 0.00001; 57 | 58 | public BaseMillingAssembler(GCodeBuilder useBuilder, FFFMachineInfo machineInfo) 59 | { 60 | Builder = useBuilder; 61 | currentPos = Vector3d.Zero; 62 | currentFeed = 0; 63 | } 64 | 65 | 66 | /* 67 | * Subclasses must implement these 68 | */ 69 | 70 | public abstract void AppendHeader(); 71 | public abstract void AppendFooter(); 72 | public abstract void UpdateProgress(int i); 73 | public abstract void ShowMessage(string s); 74 | 75 | 76 | /* 77 | * Position commands 78 | */ 79 | 80 | protected Vector3d currentPos; 81 | public Vector3d ToolPosition { 82 | get { return currentPos; } 83 | } 84 | 85 | protected double currentFeed; 86 | public double FeedRate { 87 | get { return currentFeed; } 88 | } 89 | 90 | 91 | protected bool in_retract; 92 | public bool InRetract { 93 | get { return in_retract; } 94 | } 95 | 96 | protected bool in_travel; 97 | public bool InTravel { 98 | get { return in_travel; } 99 | } 100 | 101 | public bool InCut { 102 | get { return InTravel == false; } 103 | } 104 | 105 | 106 | 107 | 108 | // actually emit travel move gcode 109 | protected virtual void emit_travel(Vector3d toPos, double feedRate, string comment) 110 | { 111 | double write_x = toPos.x + PositionShift.x; 112 | double write_y = toPos.y + PositionShift.y; 113 | 114 | Builder.BeginGLine(0, comment). 115 | AppendF("X", write_x).AppendF("Y", write_y); 116 | 117 | if (OmitDuplicateZ == false || MathUtil.EpsilonEqual(currentPos.z, toPos.z, MoveEpsilon) == false) { 118 | Builder.AppendF("Z", toPos.z); 119 | } 120 | if (OmitDuplicateF == false || MathUtil.EpsilonEqual(currentFeed, feedRate, MoveEpsilon) == false) { 121 | Builder.AppendF("F", feedRate); 122 | } 123 | 124 | currentPos = toPos; 125 | currentFeed = feedRate; 126 | } 127 | 128 | 129 | // emit gcode for an cut move 130 | protected virtual void emit_cut(Vector3d toPos, double feedRate, string comment = null) 131 | { 132 | double write_x = toPos.x + PositionShift.x; 133 | double write_y = toPos.y + PositionShift.y; 134 | Builder.BeginGLine(1, comment). 135 | AppendF("X", write_x).AppendF("Y", write_y); 136 | 137 | if (OmitDuplicateZ == false || MathUtil.EpsilonEqual(toPos.z, currentPos.z, MoveEpsilon) == false) { 138 | Builder.AppendF("Z", toPos.z); 139 | } 140 | if (OmitDuplicateF == false || MathUtil.EpsilonEqual(feedRate, currentFeed, MoveEpsilon) == false) { 141 | Builder.AppendF("F", feedRate); 142 | } 143 | 144 | currentPos = toPos; 145 | currentFeed = feedRate; 146 | } 147 | 148 | 149 | 150 | 151 | /* 152 | * Assembler API that Compiler uses 153 | */ 154 | 155 | 156 | public virtual void AppendMoveTo(Vector3d pos, double f, string comment = null) 157 | { 158 | if (in_retract) { 159 | last_retract_z = pos.z; 160 | pos.z = currentPos.z; 161 | } 162 | 163 | emit_travel(pos, f, comment); 164 | } 165 | 166 | 167 | 168 | public virtual void AppendCutTo(Vector3d pos, double feedRate, string comment = null) 169 | { 170 | if (InRetract) 171 | throw new Exception("BaseMillingAssembler.AppendMoveTo: in retract!"); 172 | 173 | emit_cut(pos, feedRate, comment); 174 | } 175 | 176 | 177 | 178 | 179 | double last_retract_z = 0; 180 | 181 | 182 | public virtual void BeginRetract(double retractHeight, double feedRate, string comment = null) 183 | { 184 | if (in_retract) 185 | throw new Exception("BaseMillingAssembler.BeginRetract: already in retract!"); 186 | 187 | last_retract_z = currentPos.z; 188 | Vector3d pos = currentPos; 189 | pos.z = retractHeight; 190 | 191 | emit_travel(pos, feedRate, comment); 192 | 193 | in_retract = true; 194 | } 195 | 196 | 197 | public virtual void EndRetract(double feedRate, string comment = null) 198 | { 199 | if (!in_retract) 200 | throw new Exception("BaseMillingAssembler.EndRetract: already in retract!"); 201 | 202 | Vector3d pos = currentPos; 203 | pos.z = last_retract_z; 204 | emit_travel(pos, feedRate, comment); 205 | 206 | in_retract = false; 207 | } 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | public virtual void BeginTravel() { 217 | if (in_travel) 218 | throw new Exception("BaseMillingAssembler.BeginTravel: already in travel!"); 219 | in_travel = true; 220 | } 221 | 222 | 223 | public virtual void EndTravel() 224 | { 225 | if (in_travel == false) 226 | throw new Exception("BaseMillingAssembler.EndTravel: not in travel!"); 227 | in_travel = false; 228 | } 229 | 230 | 231 | public virtual void AppendTravelTo(double x, double y, double z, double f) 232 | { 233 | throw new NotImplementedException("BaseMillingAssembler.AppendTravelTo"); 234 | } 235 | 236 | 237 | public virtual void AppendComment(string comment) 238 | { 239 | Builder.AddCommentLine(comment); 240 | } 241 | 242 | 243 | public virtual void AppendDwell(int milliseconds, string comment = null) 244 | { 245 | Builder.BeginGLine(4, (comment != null) ? comment : "dwell" ) 246 | .AppendI("P", milliseconds); 247 | } 248 | 249 | 250 | 251 | 252 | protected virtual void AddStandardHeader(SingleMaterialFFFSettings Settings) 253 | { 254 | Builder.AddCommentLine(" Generated on " + DateTime.Now.ToLongDateString() + " by Gradientspace gsSlicer"); 255 | Builder.AddCommentLine(string.Format(" Printer: {0} {1}", Settings.Machine.ManufacturerName, Settings.Machine.ModelIdentifier)); 256 | Builder.AddCommentLine(" Print Settings"); 257 | Builder.AddCommentLine(" Layer Height: " + Settings.LayerHeightMM); 258 | Builder.AddCommentLine(" Nozzle Diameter: " + Settings.Machine.NozzleDiamMM + " Filament Diameter: " + Settings.Machine.FilamentDiamMM); 259 | Builder.AddCommentLine(" Extruder Temp: " + Settings.ExtruderTempC); 260 | Builder.AddCommentLine(string.Format(" Speeds Extrude: {0} Travel: {1} Z: {2}", Settings.RapidExtrudeSpeed, Settings.RapidTravelSpeed, Settings.ZTravelSpeed)); 261 | Builder.AddCommentLine(string.Format(" Retract Distance: {0} Speed: {1}", Settings.RetractDistanceMM, Settings.RetractSpeed)); 262 | Builder.AddCommentLine(string.Format(" Shells: {0} InteriorShells: {1}", Settings.Shells, Settings.InteriorSolidRegionShells)); 263 | Builder.AddCommentLine(string.Format(" InfillX: {0}", Settings.SparseLinearInfillStepX)); 264 | Builder.AddCommentLine(string.Format(" LayerRange: {0}-{1}", Settings.LayerRangeFilter.a, Settings.LayerRangeFilter.b)); 265 | } 266 | 267 | 268 | 269 | 270 | } 271 | 272 | 273 | } -------------------------------------------------------------------------------- /assemblers/ExtrusionMath.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using g3; 3 | 4 | namespace gs 5 | { 6 | /// 7 | /// Utility class for filament extrusion calculations 8 | /// 9 | public static class ExtrusionMath 10 | { 11 | 12 | /// 13 | /// This function computes the amount of filament to extrude (ie how 14 | /// much to turn extruder stepper) along pathLen distance. 15 | /// volumeScale allows for local tuning of this. 16 | /// 17 | public static double PathLengthToFilamentLength( 18 | double layerHeight, double nozzleDiam, double filamentDiam, 19 | double pathLen, 20 | double volumeScale = 1.0) 21 | { 22 | double section_area = nozzleDiam * layerHeight; 23 | double linear_volume = pathLen * section_area; 24 | linear_volume *= volumeScale; 25 | 26 | double filamentRadius = filamentDiam * 0.5; 27 | double filament_section_area = Math.PI * filamentRadius * filamentRadius; 28 | double filament_len = linear_volume / filament_section_area; 29 | 30 | return filament_len; 31 | } 32 | 33 | 34 | 35 | public static double PathLengthToVolume( 36 | double layerHeight, double nozzleDiam, 37 | double pathLen) 38 | { 39 | double section_area = nozzleDiam * layerHeight; 40 | double linear_volume = pathLen * section_area; 41 | return linear_volume; 42 | } 43 | 44 | 45 | public static double WidthFromTargetVolume( 46 | double layerHeight, double pathLen, double targetVolume) 47 | { 48 | return targetVolume / (pathLen * layerHeight); 49 | } 50 | 51 | 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /assemblers/GenericMillingAssembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | using gs; 7 | 8 | namespace gs 9 | { 10 | 11 | public class GenericMillingAssembler : BaseMillingAssembler 12 | { 13 | public static BaseMillingAssembler Factory(GCodeBuilder builder, SingleMaterialFFFSettings settings) { 14 | return new GenericMillingAssembler(builder, settings); 15 | } 16 | 17 | 18 | public SingleMaterialFFFSettings Settings; 19 | 20 | 21 | public GenericMillingAssembler(GCodeBuilder useBuilder, SingleMaterialFFFSettings settings) : base(useBuilder, settings.Machine) 22 | { 23 | Settings = settings; 24 | 25 | OmitDuplicateZ = true; 26 | OmitDuplicateF = true; 27 | 28 | HomeSequenceF = StandardHomeSequence; 29 | } 30 | 31 | 32 | public override void UpdateProgress(int i) { 33 | // not supported on reprap? 34 | //Builder.BeginMLine(73).AppendI("P",i); 35 | } 36 | 37 | public override void ShowMessage(string s) 38 | { 39 | Builder.AddCommentLine(s); 40 | } 41 | 42 | 43 | /// 44 | /// Replace this to run your own home sequence 45 | /// 46 | public Action HomeSequenceF; 47 | 48 | 49 | public enum HeaderState 50 | { 51 | AfterComments, 52 | BeforeHome 53 | }; 54 | public Action HeaderCustomizerF = (state, builder) => { }; 55 | 56 | 57 | 58 | 59 | public override void AppendHeader() { 60 | AppendHeader_StandardRepRap(); 61 | } 62 | void AppendHeader_StandardRepRap() { 63 | 64 | base.AddStandardHeader(Settings); 65 | 66 | HeaderCustomizerF(HeaderState.AfterComments, Builder); 67 | 68 | Builder.BeginGLine(21, "units=mm"); 69 | Builder.BeginGLine(90, "absolute positions"); 70 | 71 | HeaderCustomizerF(HeaderState.BeforeHome, Builder); 72 | 73 | HomeSequenceF(Builder); 74 | 75 | // retract to retract height 76 | //Builder.BeginGLine(0, "retract to top").AppendI("X", 0).AppendI("Y", 0).AppendF("Z", Settings.RetractDistanceMM); 77 | 78 | //PositionShift = 0.5 * new Vector2d(Settings.Machine.BedSizeXMM, Settings.Machine.BedSizeYMM); 79 | //PositionShift = Vector2d.Zero; 80 | currentPos = Vector3d.Zero; 81 | 82 | ShowMessage("Cut Started"); 83 | 84 | in_travel = false; 85 | 86 | UpdateProgress(0); 87 | } 88 | 89 | 90 | 91 | 92 | public override void AppendFooter() { 93 | AppendFooter_StandardRepRap(); 94 | } 95 | void AppendFooter_StandardRepRap() { 96 | 97 | UpdateProgress(100); 98 | 99 | Builder.AddCommentLine("End of print"); 100 | ShowMessage("Done!"); 101 | 102 | Builder.BeginMLine(30, "end program"); 103 | 104 | Builder.EndLine(); // need to force this 105 | } 106 | 107 | 108 | 109 | 110 | public virtual void StandardHomeSequence(GCodeBuilder builder) 111 | { 112 | //Builder.BeginGLine(0, "home x/y/z").AppendI("X", 0).AppendI("Y", 0).AppendI("Z", 0); 113 | } 114 | 115 | 116 | } 117 | 118 | 119 | } -------------------------------------------------------------------------------- /assemblers/MakerbotAssembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | 10 | public class MakerbotAssembler : BaseDepositionAssembler 11 | { 12 | public static BaseDepositionAssembler Factory(GCodeBuilder builder, SingleMaterialFFFSettings settings) { 13 | return new MakerbotAssembler(builder, settings); 14 | } 15 | 16 | 17 | public SingleMaterialFFFSettings Settings; 18 | 19 | 20 | public MakerbotAssembler(GCodeBuilder useBuilder, SingleMaterialFFFSettings settings) : base(useBuilder, settings.Machine) 21 | { 22 | Settings = settings as SingleMaterialFFFSettings; 23 | 24 | PositionBounds = new AxisAlignedBox2d(settings.Machine.BedSizeXMM, settings.Machine.BedSizeYMM); 25 | PositionBounds.Translate(-PositionBounds.Center); 26 | 27 | // [RMS] currently bed dimensions are hardcoded in header setup, and this trips bounds-checker. 28 | // So, disable this checking for now. 29 | EnableBoundsChecking = false; 30 | 31 | TravelGCode = 1; 32 | } 33 | 34 | 35 | public override void BeginRetract(Vector3d pos, double feedRate, double extrudeDist, string comment = null) { 36 | // [TODO] makerbot gcode disables fan here 37 | // disable fan for every tiny travel? seems pointless... 38 | 39 | base.BeginRetract(pos, feedRate, extrudeDist, comment); 40 | 41 | // [RMS] makerbot does this...but does it do anything?? 42 | base.BeginTravel(); 43 | AppendMoveTo(pos, 3000, "Retract 2?"); 44 | base.EndTravel(); 45 | } 46 | 47 | public override void EndRetract(Vector3d pos, double feedRate, double extrudeDist = -9999, string comment = null) { 48 | base.EndRetract(pos, feedRate, extrudeDist, comment); 49 | 50 | // [TODO] re-enable fan here 51 | } 52 | 53 | 54 | 55 | 56 | public override void UpdateProgress(int i) { 57 | Builder.BeginMLine(73).AppendI("P",i); 58 | } 59 | 60 | 61 | public override void EnableFan() { 62 | // makerbot-style firmware does not support fan speed? 63 | Builder.BeginMLine(126).AppendI("T",0); 64 | } 65 | public override void DisableFan() { 66 | Builder.BeginMLine(127).AppendI("T",0); 67 | } 68 | 69 | public override void ShowMessage(string s) { 70 | // do nothing (not available) 71 | } 72 | 73 | 74 | 75 | 76 | public override void AppendHeader() { 77 | AppendHeader_Replicator2(); 78 | } 79 | void AppendHeader_Replicator2() { 80 | 81 | base.AddStandardHeader(Settings); 82 | 83 | Vector3d frontRight = new Vector3d(Settings.Machine.BedSizeXMM / 2, -Settings.Machine.BedSizeYMM / 2, 0); 84 | frontRight.x -= 10; 85 | frontRight.y += 5; 86 | Vector3d FrontLeft = frontRight; FrontLeft.x = -frontRight.x; 87 | //Vector3d BackRight = frontRight; BackRight.y = -frontRight.y; 88 | 89 | Builder.BeginMLine(136, "(enable build)"); 90 | 91 | // reset build percentage 92 | UpdateProgress(0); 93 | 94 | // set target temperature. Do this before home because it will happen faster then. 95 | Builder.BeginMLine(135, "select tool 0") 96 | .AppendI("T", 0); 97 | Builder.BeginMLine(104, "set target tool temperature") 98 | .AppendI("S", Settings.ExtruderTempC).AppendI("T", 0); 99 | if (Settings.Machine.HasHeatedBed) { 100 | Builder.BeginMLine(140, "set heated bed temperature") 101 | .AppendI("S", Settings.HeatedBedTempC).AppendI("T", 0); 102 | } 103 | 104 | // homing 105 | 106 | Builder.BeginGLine(162, "(home XY axes maximum)") 107 | .AppendL("X").AppendL("Y").AppendI("F", 2000); 108 | 109 | Builder.BeginGLine(161, "(home Z axis minimum)") 110 | .AppendL("Z").AppendI("F", 900); 111 | 112 | Builder.BeginGLine(92, "(set Z to -5)"). 113 | AppendI("X",0).AppendI("Y",0).AppendI("Z",-5).AppendI("A",0).AppendI("B",0); 114 | currentPos = new Vector3d(0, 0, -5); 115 | extruderA = 0; 116 | 117 | Builder.BeginGLine(1, "(move Z to '0')") 118 | .AppendI("Z", 0).AppendI("F", 900); 119 | currentPos.z = 0; 120 | 121 | Builder.BeginGLine(161, "(home Z axis minimum)") 122 | .AppendL("Z").AppendI("F", 100); 123 | 124 | Builder.BeginMLine(132, "(Recall stored home offsets for XYZAB axis)"). 125 | AppendL("X").AppendL("Y").AppendL("Z").AppendL("A").AppendL("B"); 126 | 127 | // [RMS] this line is not necessary 128 | //Builder.BeginGLine(92). 129 | // AppendF("X",BackRight.x).AppendF("Y",BackRight.y).AppendI("Z",0).AppendI("A",0).AppendI("B",0); 130 | //currentPos = new Vector3d(BackRight.x, BackRight.y, 0); 131 | //extruderA = 0; 132 | 133 | Builder.BeginGLine(1, "(move to waiting position)"). 134 | AppendF("X",FrontLeft.x).AppendF("Y",FrontLeft.y).AppendI("Z",40).AppendI("F",3300); 135 | currentPos = new Vector3d(FrontLeft.x, FrontLeft.y, 40); 136 | 137 | Builder.BeginGLine(130, "(Lower stepper Vrefs while heating)"). 138 | AppendI("X",20).AppendI("Y",20).AppendI("A",20).AppendI("B",20); 139 | 140 | if ( Settings.Machine.HasHeatedBed ) { 141 | Builder.BeginMLine(134, "wait for bed to heat") 142 | .AppendI("T", 0); 143 | } 144 | 145 | // wait to heat 146 | Builder.BeginMLine(133, "wait for tool to heat") 147 | .AppendI("T",0); 148 | 149 | Builder.BeginGLine(130, "(Set Stepper motor Vref to defaults)"). 150 | AppendI("X",127).AppendI("Y",127).AppendI("A",127).AppendI("B",127); 151 | 152 | // prime 153 | base.AddPrimeLine(Settings); 154 | 155 | // this isn't necessary anymore... 156 | Builder.BeginGLine(92, "(Reset after prime)").AppendI("A", 0).AppendI("B", 0); 157 | 158 | // move to z=0 159 | Builder.BeginGLine(1).AppendI("Z",0).AppendI("F",1000); 160 | currentPos.z = 0; 161 | 162 | // move to front-left corner 163 | AppendMoveToE(FrontLeft.x, FrontLeft.y, 0, 1000, 0); 164 | 165 | in_retract = false; 166 | in_travel = false; 167 | 168 | EnableFan(); 169 | UpdateProgress(0); 170 | } 171 | 172 | 173 | 174 | 175 | 176 | public override void AppendFooter() { 177 | AppendFooter_Replicator2(); 178 | } 179 | void AppendFooter_Replicator2() { 180 | double MaxHeight = 155; 181 | 182 | Builder.AddCommentLine("End of print"); 183 | 184 | // final retract 185 | if (InRetract == false) { 186 | BeginRetract(NozzlePosition, Settings.RetractSpeed, 187 | ExtruderA - Settings.RetractDistanceMM, "Final Retract"); 188 | } 189 | 190 | //G1 X-9.119 Y10.721 Z0.200 F1500 A61.36007; Retract 191 | 192 | Builder.BeginMLine(127, "(Fan Off)").AppendI("T",0); 193 | Builder.BeginMLine(18, "(Turn off A and B Steppers)").AppendL("A").AppendL("B"); 194 | 195 | // move bed to max height 196 | Builder.BeginGLine(1).AppendF("Z",MaxHeight).AppendI("F",900); 197 | 198 | // home steppers and turn off 199 | Builder.BeginGLine(162).AppendL("X").AppendL("Y").AppendI("F", 2000); 200 | Builder.BeginMLine(18,"(Turn off steppers)").AppendL("X").AppendL("Y").AppendL("Z"); 201 | 202 | // set temp to 0 203 | Builder.BeginMLine(104, "set target tool temperature").AppendI("S",0).AppendI("T",0); 204 | 205 | if ( Settings.Machine.HasHeatedBed ) { 206 | Builder.BeginMLine(140, "set heated bed temperature") 207 | .AppendI("S", 0).AppendI("T", 0); 208 | } 209 | 210 | // set built-in status message 211 | Builder.BeginMLine(70, "// Cotangent //").AppendI("P",5); 212 | 213 | // skip song 214 | //Builder.BeginMLine(72).AppendI("P",1); 215 | 216 | UpdateProgress(100); 217 | 218 | Builder.BeginMLine(137,"(build end notification)"); 219 | 220 | Builder.EndLine(); // need to force this 221 | } 222 | 223 | } 224 | 225 | 226 | } -------------------------------------------------------------------------------- /assemblers/RepRapAssembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | using gs; 7 | 8 | namespace gs 9 | { 10 | 11 | public class RepRapAssembler : BaseDepositionAssembler 12 | { 13 | public static BaseDepositionAssembler Factory(GCodeBuilder builder, SingleMaterialFFFSettings settings) { 14 | return new RepRapAssembler(builder, settings); 15 | } 16 | 17 | 18 | public SingleMaterialFFFSettings Settings; 19 | 20 | 21 | public RepRapAssembler(GCodeBuilder useBuilder, SingleMaterialFFFSettings settings) : base(useBuilder, settings.Machine) 22 | { 23 | Settings = settings; 24 | 25 | OmitDuplicateZ = true; 26 | OmitDuplicateF = true; 27 | OmitDuplicateE = true; 28 | 29 | HomeSequenceF = StandardHomeSequence; 30 | } 31 | 32 | 33 | //public override void BeginRetract(Vector3d pos, double feedRate, double extrudeDist, string comment = null) { 34 | // base.BeginRetract(pos, feedRate, extrudeDist, comment); 35 | //} 36 | 37 | //public override void EndRetract(Vector3d pos, double feedRate, double extrudeDist = -9999, string comment = null) { 38 | // base.EndRetract(pos, feedRate, extrudeDist, comment); 39 | //} 40 | 41 | 42 | public override void UpdateProgress(int i) { 43 | // not supported on reprap? 44 | //Builder.BeginMLine(73).AppendI("P",i); 45 | } 46 | 47 | public override void ShowMessage(string s) 48 | { 49 | Builder.BeginMLine(117).AppendL(s); 50 | } 51 | 52 | public override void EnableFan() { 53 | int fan_speed = (int)(Settings.FanSpeedX * 255.0); 54 | Builder.BeginMLine(106, "fan on").AppendI("S", fan_speed); 55 | } 56 | public override void DisableFan() { 57 | Builder.BeginMLine(107, "fan off"); 58 | } 59 | 60 | 61 | /// 62 | /// Replace this to run your own home sequence 63 | /// 64 | public Action HomeSequenceF; 65 | 66 | 67 | public enum HeaderState 68 | { 69 | AfterComments, 70 | AfterTemperature, 71 | BeforeHome, 72 | BeforePrime 73 | }; 74 | public Action HeaderCustomizerF = (state, builder) => { }; 75 | 76 | 77 | 78 | 79 | public override void AppendHeader() { 80 | AppendHeader_StandardRepRap(); 81 | } 82 | void AppendHeader_StandardRepRap() { 83 | 84 | base.AddStandardHeader(Settings); 85 | 86 | DisableFan(); 87 | 88 | HeaderCustomizerF(HeaderState.AfterComments, Builder); 89 | 90 | /* 91 | * Configure temperatures 92 | */ 93 | 94 | // do this first so it happens while bed heats 95 | SetExtruderTargetTemp(Settings.ExtruderTempC); 96 | 97 | // M190 98 | if (Settings.Machine.HasHeatedBed) { 99 | if (Settings.HeatedBedTempC > 0) 100 | SetBedTargetTempAndWait(Settings.HeatedBedTempC); 101 | else 102 | SetBedTargetTemp(0, "disable heated bed"); 103 | } 104 | 105 | // M109 106 | SetExtruderTargetTempAndWait(Settings.ExtruderTempC); 107 | 108 | 109 | HeaderCustomizerF(HeaderState.AfterTemperature, Builder); 110 | 111 | Builder.BeginGLine(21, "units=mm"); 112 | Builder.BeginGLine(90, "absolute positions"); 113 | Builder.BeginMLine(82, "absolute extruder position"); 114 | 115 | HeaderCustomizerF(HeaderState.BeforeHome, Builder); 116 | 117 | HomeSequenceF(Builder); 118 | 119 | currentPos = Vector3d.Zero; 120 | 121 | HeaderCustomizerF(HeaderState.BeforePrime, Builder); 122 | 123 | base.AddPrimeLine(Settings); 124 | 125 | // [RMS] this does not extrude very much and does not seem to work? 126 | //Builder.BeginGLine(1, "move platform down").AppendF("Z", 15).AppendI("F", 9000); 127 | //currentPos.z = 15; 128 | //Builder.BeginGLine(92, "reset extruded length").AppendI("E", 0); 129 | //extruderA = 0; 130 | //Builder.BeginGLine(1, "extrude blob").AppendI("F", 200).AppendI("E", 3); 131 | //Builder.BeginGLine(92, "reset extruded length again").AppendI("E", 0); 132 | //extruderA = 0; 133 | //Builder.BeginGLine(1, "reset speed").AppendI("F", 9000); 134 | 135 | // move to z=0 136 | BeginTravel(); 137 | AppendMoveTo(new Vector3d(NozzlePosition.x,NozzlePosition.y,0), Settings.ZTravelSpeed, "reset z"); 138 | EndTravel(); 139 | 140 | ShowMessage("Print Started"); 141 | 142 | in_retract = false; 143 | in_travel = false; 144 | 145 | EnableFan(); 146 | UpdateProgress(0); 147 | } 148 | 149 | 150 | 151 | 152 | public override void AppendFooter() { 153 | AppendFooter_StandardRepRap(); 154 | } 155 | void AppendFooter_StandardRepRap() { 156 | 157 | UpdateProgress(100); 158 | 159 | Builder.AddCommentLine("End of print"); 160 | ShowMessage("Done!"); 161 | 162 | DisableFan(); 163 | SetExtruderTargetTemp(0, "extruder off"); 164 | SetBedTargetTemp(0, "bed off"); 165 | 166 | BeginRetractRelativeDist(currentPos, 300, -1, "final retract"); 167 | 168 | Vector3d zup = currentPos; 169 | zup.z = Math.Min(Settings.Machine.MaxHeightMM, zup.z + 50); 170 | AppendMoveToE(zup, 9000, ExtruderA - 5.0, "move up and retract"); 171 | 172 | Builder.BeginGLine(28, "home x/y").AppendI("X", 0).AppendI("Y", 0); 173 | currentPos.x = currentPos.y = 0; 174 | 175 | Builder.BeginMLine(84, "turn off steppers"); 176 | 177 | Builder.EndLine(); // need to force this 178 | } 179 | 180 | 181 | 182 | 183 | public virtual void StandardHomeSequence(GCodeBuilder builder) 184 | { 185 | Builder.BeginGLine(28, "home x/y").AppendI("X", 0).AppendI("Y", 0); 186 | Builder.BeginGLine(28, "home z").AppendI("Z", 0); 187 | } 188 | 189 | 190 | } 191 | 192 | 193 | } -------------------------------------------------------------------------------- /builders/GCodeBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace gs 7 | { 8 | public class GCodeBuilder 9 | { 10 | public IGCodeAccumulator Target; 11 | 12 | public GCodeBuilder(IGCodeAccumulator target) { 13 | Target = target; 14 | } 15 | 16 | public virtual GCodeBuilder AddLine(GCodeLine line, bool bClone = true) { 17 | close_current_line(); 18 | if ( bClone ) { 19 | GCodeLine clone = line.Clone(); 20 | clone.lineNumber = next_line_number(); 21 | Target.AddLine(clone); 22 | } else { 23 | line.lineNumber = next_line_number(); 24 | Target.AddLine(line); 25 | } 26 | return this; 27 | } 28 | 29 | 30 | /// 31 | /// Add a comment to output. Will add necessary comment prefix if not provided. 32 | /// 33 | public virtual GCodeBuilder AddCommentLine(string comment) { 34 | //if ( comment[0] != ';' && comment[0] != '(' ) 35 | // comment = ";" + comment; 36 | AddLine( 37 | new GCodeLine(next_line_number(), GCodeLine.LType.Comment, comment) ); 38 | return this; 39 | } 40 | 41 | 42 | /// 43 | /// Add this exact string to output. not a good idea. 44 | /// 45 | public virtual GCodeBuilder AddExplicitLine(string line) { 46 | AddLine( 47 | new GCodeLine(next_line_number(), GCodeLine.LType.UnknownString, line) ); 48 | return this; 49 | } 50 | 51 | 52 | 53 | /// 54 | /// Open a G code line. Use AppendXParameter to add more info 55 | /// 56 | public virtual GCodeBuilder BeginGLine(int Gcode, string comment = null) { 57 | begin_new_line(GCodeLine.LType.GCode); 58 | next_line.code = Gcode; 59 | if ( comment != null ) 60 | next_line.comment = comment; 61 | return this; 62 | } 63 | 64 | /// 65 | /// Open a M code line. Use AppendXParameter to add more info 66 | /// 67 | public virtual GCodeBuilder BeginMLine(int Mcode, string comment = null) { 68 | begin_new_line(GCodeLine.LType.MCode); 69 | next_line.code = Mcode; 70 | if ( comment != null ) 71 | next_line.comment = comment; 72 | return this; 73 | } 74 | 75 | /// 76 | /// close and append current line. In most cases this does not have to be explicitly called. 77 | /// 78 | public virtual GCodeBuilder EndLine() { 79 | close_current_line(); 80 | return this; 81 | } 82 | 83 | 84 | 85 | public virtual GCodeBuilder AppendComment(string comment) { 86 | if ( next_line == null ) 87 | throw new Exception("GCodeBuilder.AppendComment: next_line was null!?"); 88 | next_line.comment = comment; 89 | return this; 90 | } 91 | 92 | 93 | /// 94 | /// Add an integer-value parameter to the current line 95 | /// 96 | public virtual GCodeBuilder AppendI(string identifier, int value) { 97 | GCodeParam p = new GCodeParam() { 98 | type = GCodeParam.PType.IntegerValue, identifier = identifier, intValue = value }; 99 | next_params.Add(p); 100 | return this; 101 | } 102 | 103 | /// 104 | /// Add a float-value parameter to the current line 105 | /// 106 | public virtual GCodeBuilder AppendF(string identifier, double value) { 107 | GCodeParam p = new GCodeParam() { 108 | type = GCodeParam.PType.DoubleValue, identifier = identifier, doubleValue = value }; 109 | next_params.Add(p); 110 | return this; 111 | } 112 | 113 | /// 114 | /// Add a text-value parameter to the current line 115 | /// (these are used in Biesse gcode...can also use this to string-format values yourself) 116 | /// 117 | public virtual GCodeBuilder AppendS(string identifier, string value) { 118 | GCodeParam p = new GCodeParam() { 119 | type = GCodeParam.PType.TextValue, identifier = identifier, textValue = value }; 120 | next_params.Add(p); 121 | return this; 122 | } 123 | 124 | /// 125 | /// Append a label-only parameter to the current line (eg like G162 X Y) 126 | /// 127 | /// Identifier. 128 | public virtual GCodeBuilder AppendL(string identifier) { 129 | GCodeParam p = new GCodeParam() { 130 | type = GCodeParam.PType.NoValue, identifier = identifier }; 131 | next_params.Add(p); 132 | return this; 133 | } 134 | 135 | 136 | 137 | 138 | int line_number = 0; 139 | protected virtual int next_line_number() { 140 | return line_number++; 141 | } 142 | 143 | GCodeLine next_line; 144 | List next_params; 145 | 146 | protected virtual void close_current_line() { 147 | if ( next_line != null ) { 148 | if ( next_params.Count > 0 ) 149 | next_line.parameters = next_params.ToArray(); 150 | Target.AddLine(next_line); 151 | next_line = null; 152 | } 153 | } 154 | 155 | protected virtual void begin_new_line(GCodeLine.LType type) { 156 | if ( next_line != null ) 157 | close_current_line(); 158 | 159 | next_line = new GCodeLine(next_line_number(), type); 160 | if (next_params == null || next_params.Count > 0 ) 161 | next_params = new List(); 162 | } 163 | 164 | } 165 | 166 | 167 | } 168 | -------------------------------------------------------------------------------- /builders/GCodeFileAccumulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace gs 7 | { 8 | 9 | public class GCodeFileAccumulator : IGCodeAccumulator 10 | { 11 | public GCodeFile File; 12 | 13 | public GCodeFileAccumulator(GCodeFile useFile = null) 14 | { 15 | File = (useFile != null) ? useFile : new GCodeFile(); 16 | } 17 | 18 | public virtual void AddLine(GCodeLine line) { 19 | File.AppendLine(line); 20 | } 21 | 22 | 23 | } 24 | 25 | 26 | } -------------------------------------------------------------------------------- /builders/IGCodeAccumulator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace gs 7 | { 8 | 9 | public interface IGCodeAccumulator 10 | { 11 | void AddLine(GCodeLine line); 12 | } 13 | 14 | 15 | } -------------------------------------------------------------------------------- /gsGCode.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gsGCode", 3 | "references": [ 4 | "geometry3Sharp" 5 | ], 6 | "optionalUnityReferences": [], 7 | "includePlatforms": [], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false 10 | } -------------------------------------------------------------------------------- /gsGCode.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {25DE77C9-14A4-4562-9A24-0BF1E612D9A9} 8 | Library 9 | Properties 10 | gs 11 | gsGCode 12 | v4.6 13 | 512 14 | 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | AnyCPU 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | AnyCPU 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | {0c518dda-28fe-44ca-9ab0-f9773974f13a} 79 | geometry3Sharp 80 | 81 | 82 | 83 | 90 | -------------------------------------------------------------------------------- /interpreters/BiesseInterpreter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Diagnostics; 6 | using g3; 7 | 8 | namespace gs 9 | { 10 | public class BiesseInterpreter : IGCodeInterpreter 11 | { 12 | IGCodeListener listener = null; 13 | Dictionary> GCodeMap = new Dictionary>(); 14 | 15 | 16 | public BiesseInterpreter() 17 | { 18 | build_maps(); 19 | } 20 | 21 | 22 | 23 | public virtual void AddListener(IGCodeListener listener) { 24 | if (this.listener != null) 25 | throw new Exception("Only one listener supported!"); 26 | this.listener = listener; 27 | } 28 | 29 | public virtual void Interpret(GCodeFile file, InterpretArgs args) 30 | { 31 | IEnumerable lines_enum = 32 | (args.HasTypeFilter) ? file.AllLines() : file.AllLinesOfType(args.eTypeFilter); 33 | 34 | listener.Begin(); 35 | 36 | foreach(GCodeLine line in lines_enum) { 37 | 38 | if ( line.type == GCodeLine.LType.GCode ) { 39 | Action parseF; 40 | if (GCodeMap.TryGetValue(line.code, out parseF)) 41 | parseF(line); 42 | } 43 | 44 | } 45 | 46 | listener.End(); 47 | } 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | void emit_linear(GCodeLine line) 57 | { 58 | Debug.Assert(line.code == 1); 59 | 60 | double dx = 0, dy = 0; 61 | bool brelx = GCodeUtil.TryFindParamNum(line.parameters, "XI", ref dx); 62 | bool brely = GCodeUtil.TryFindParamNum(line.parameters, "YI", ref dy); 63 | 64 | LinearMoveData move = new LinearMoveData(new Vector2d(dx,dy)); 65 | 66 | if (brelx || brely) { 67 | listener.LinearMoveToRelative2d(move); 68 | return; 69 | } 70 | 71 | double x = 0, y = 0; 72 | bool absx = GCodeUtil.TryFindParamNum(line.parameters, "X", ref x); 73 | bool absy = GCodeUtil.TryFindParamNum(line.parameters, "Y", ref y); 74 | if ( absx && absy ) { 75 | listener.LinearMoveToAbsolute2d(move); 76 | return; 77 | } 78 | 79 | // [RMS] can we have this?? 80 | if (absx || absy) 81 | System.Diagnostics.Debug.Assert(false); 82 | } 83 | 84 | 85 | 86 | void emit_cw_arc(GCodeLine line) { 87 | emit_arc(line, true); 88 | } 89 | void emit_ccw_arc(GCodeLine line) { 90 | emit_arc(line, false); 91 | } 92 | 93 | void emit_arc(GCodeLine line, bool clockwise) { 94 | 95 | double dx = 0, dy = 0; 96 | 97 | // either of these might be missing... 98 | bool brelx = GCodeUtil.TryFindParamNum(line.parameters, "XI", ref dx); 99 | bool brely = GCodeUtil.TryFindParamNum(line.parameters, "YI", ref dy); 100 | Debug.Assert(brelx == true && brely == true); 101 | 102 | double r = 0; 103 | bool br = GCodeUtil.TryFindParamNum(line.parameters, "R", ref r); 104 | Debug.Assert(br == true); 105 | 106 | // [RMS] seems like G5 always has negative radius and G4 positive ?? 107 | // (this will tell us) 108 | Debug.Assert((clockwise && r < 0) || (clockwise == false && r > 0)); 109 | r = Math.Abs(r); 110 | 111 | listener.ArcToRelative2d( new Vector2d(dx,dy), r, clockwise ); 112 | } 113 | 114 | 115 | void build_maps() 116 | { 117 | 118 | // G1 = linear move 119 | GCodeMap[1] = emit_linear; 120 | 121 | // G4 = CCW circular 122 | GCodeMap[4] = emit_ccw_arc; 123 | GCodeMap[5] = emit_cw_arc; 124 | } 125 | 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /interpreters/GCodeInterpreter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | 10 | public struct InterpretArgs 11 | { 12 | public GCodeLine.LType eTypeFilter; 13 | 14 | 15 | public bool HasTypeFilter { get { return eTypeFilter != GCodeLine.LType.Blank; } } 16 | 17 | public static readonly InterpretArgs Default = new InterpretArgs() { 18 | eTypeFilter = GCodeLine.LType.Blank 19 | }; 20 | } 21 | 22 | 23 | public interface IGCodeInterpreter 24 | { 25 | void AddListener(IGCodeListener listener); 26 | void Interpret(GCodeFile file, InterpretArgs args); 27 | } 28 | 29 | 30 | /// 31 | /// GCodeInterpreter passes this to GCodeListener for each G1 line 32 | /// 33 | public struct LinearMoveData { 34 | 35 | public Vector3d position; 36 | public double rate; 37 | public Vector3d extrude; 38 | public GCodeLine source; 39 | 40 | public LinearMoveData(Vector2d pos, 41 | double rateIn = GCodeUtil.UnspecifiedValue ) { 42 | position = new Vector3d(pos.x, pos.y, GCodeUtil.UnspecifiedValue); 43 | rate = rateIn; 44 | extrude = GCodeUtil.UnspecifiedPosition; 45 | source = null; 46 | } 47 | public LinearMoveData(Vector3d pos, double rateIn = GCodeUtil.UnspecifiedValue) { 48 | position = pos; 49 | rate = rateIn; 50 | extrude = GCodeUtil.UnspecifiedPosition; 51 | source = null; 52 | } 53 | public LinearMoveData(Vector3d pos, double rateIn, Vector3d extrudeIn) { 54 | position = pos; 55 | rate = rateIn; 56 | extrude = extrudeIn; 57 | source = null; 58 | } 59 | } 60 | 61 | 62 | // codes to pass to IGCodeListener.CustomCommand 63 | // this is basically just slightly better than complete hacks 64 | public enum CustomListenerCommands 65 | { 66 | ResetPosition = 0, // object should be Vector3d 67 | ResetExtruder = 1 // object should be Vector3d 68 | 69 | } 70 | 71 | 72 | public interface IGCodeListener 73 | { 74 | void Begin(); 75 | void End(); 76 | 77 | void BeginTravel(); 78 | void BeginDeposition(); 79 | void BeginCut(); 80 | 81 | // for hacks 82 | void CustomCommand(int code, object o); 83 | 84 | void LinearMoveToAbsolute2d(LinearMoveData move); 85 | void LinearMoveToRelative2d(LinearMoveData move); 86 | void ArcToRelative2d(Vector2d pos, double radius, bool clockwise, double rate = 0); 87 | 88 | void LinearMoveToAbsolute3d(LinearMoveData move); 89 | void LinearMoveToRelative3d(LinearMoveData move); 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /interpreters/GCodeToPlanarComplex.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Diagnostics; 6 | using g3; 7 | 8 | namespace gs 9 | { 10 | public class GCodeToPlanarComplex : IGCodeListener 11 | { 12 | public PlanarComplex Complex = new PlanarComplex(); 13 | 14 | Vector2d P; 15 | 16 | 17 | public void Begin() 18 | { 19 | P = Vector2d.Zero; 20 | } 21 | public void End() 22 | { 23 | } 24 | 25 | // not sure what to do with these... 26 | public void BeginTravel() { 27 | } 28 | public void BeginDeposition() { 29 | } 30 | public void BeginCut() 31 | { 32 | } 33 | 34 | public void LinearMoveToAbsolute2d(LinearMoveData move) 35 | { 36 | Vector2d P2 = move.position.xy; 37 | Complex.Add(new Segment2d(P, P2)); 38 | P = P2; 39 | } 40 | 41 | public void LinearMoveToRelative2d(LinearMoveData move) 42 | { 43 | Vector2d P2 = P + move.position.xy; 44 | Complex.Add(new Segment2d(P, P2)); 45 | P = P2; 46 | } 47 | 48 | 49 | public void LinearMoveToAbsolute3d(LinearMoveData move) 50 | { 51 | throw new NotSupportedException(); 52 | } 53 | 54 | public void LinearMoveToRelative3d(LinearMoveData move) 55 | { 56 | throw new NotSupportedException(); 57 | } 58 | 59 | 60 | int find_arc_centers(Vector2d p1, Vector2d p2, double radius, out Vector2d c0, out Vector2d c1) 61 | { 62 | c0 = c1 = Vector2d.Zero; 63 | 64 | double dist2 = p1.DistanceSquared(p2); 65 | double diam2 = 4 * radius * radius; 66 | Debug.Assert(diam2 > dist2); // otherwise solution is impossible 67 | 68 | Vector2d midpoint = 0.5 * (p1 + p2); 69 | if ( MathUtil.EpsilonEqual(dist2, diam2, MathUtil.ZeroTolerance) ) { 70 | c0 = midpoint; 71 | return 1; 72 | } 73 | 74 | double d = Math.Sqrt(radius * radius - dist2 / 4); 75 | double distance = Math.Sqrt(dist2); 76 | double ox = d * (p2.x - p1.x) / distance; 77 | double oy = d * (p2.y - p1.y) / distance; 78 | c0 = new Vector2d(midpoint.x - oy, midpoint.y + ox); 79 | c1 = new Vector2d(midpoint.x + oy, midpoint.y - ox); 80 | return 2; 81 | } 82 | 83 | 84 | double arc_angle_deg(Vector2d p, Vector2d c) { 85 | Vector2d v = p - c; 86 | v.Normalize(); 87 | double angle = Math.Atan2(v.y, v.x); 88 | return angle * MathUtil.Rad2Deg; 89 | } 90 | 91 | 92 | bool arc_is_cw( Vector2d p1, Vector2d p2, Vector2d c ) { 93 | return false; 94 | } 95 | 96 | 97 | public void ArcToRelative2d(Vector2d v, double radius, bool clockwise, double rate = 0) 98 | { 99 | Vector2d P2 = P + v; 100 | 101 | Vector2d c0,c1; 102 | int nCenters = find_arc_centers(P, P2, radius, out c0, out c1); 103 | 104 | //bool b0Left = MathUtil.IsLeft(P, P2, c0) > 0; 105 | //bool b1Left = MathUtil.IsLeft(P, P2, c1) > 0; 106 | 107 | Vector2d c = c0; 108 | if (nCenters == 2 && clockwise == false ) 109 | c = c1; 110 | 111 | // [RMS] what does negative radius mean ?? 112 | //bool reverse = false; 113 | //if (radius < 0) 114 | // reverse = true; 115 | radius = Math.Abs(radius); 116 | 117 | double start_angle = arc_angle_deg(P, c); 118 | double end_angle = arc_angle_deg(P2, c); 119 | if ( clockwise == false ) { 120 | double tmp = start_angle; start_angle = end_angle; end_angle = tmp; 121 | } 122 | 123 | 124 | Arc2d arc = new Arc2d(c, radius, start_angle, end_angle); 125 | //if (reverse) 126 | // arc.Reverse(); 127 | Complex.Add(arc); 128 | 129 | P = P2; 130 | } 131 | 132 | 133 | public void CustomCommand(int code, object o) { 134 | // ignore all for now 135 | } 136 | 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /interpreters/MakerbotInterpreter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | // useful documents: 10 | // https://github.com/makerbot/s3g/blob/master/doc/GCodeProtocol.md 11 | 12 | 13 | /// 14 | /// Makerbot GCode interpreter. 15 | /// 16 | public class MakerbotInterpreter : IGCodeInterpreter 17 | { 18 | IGCodeListener listener = null; 19 | 20 | Dictionary> GCodeMap = new Dictionary>(); 21 | Dictionary> MCodeMap = new Dictionary>(); 22 | 23 | 24 | bool UseRelativePosition = false; 25 | bool UseRelativeExtruder = false; 26 | 27 | 28 | Vector3d CurPosition = Vector3d.Zero; 29 | 30 | double ExtrusionA = 0; 31 | double LastRetractA = 0; 32 | bool in_retract = false; 33 | bool in_travel = false; 34 | bool in_extrude = false; 35 | 36 | public MakerbotInterpreter() { 37 | build_maps(); 38 | } 39 | 40 | public virtual void AddListener(IGCodeListener listener) 41 | { 42 | if (this.listener != null) 43 | throw new Exception("Only one listener supported!"); 44 | this.listener = listener; 45 | } 46 | 47 | 48 | public virtual void Interpret(GCodeFile file, InterpretArgs args) 49 | { 50 | IEnumerable lines_enum = 51 | (args.HasTypeFilter) ? file.AllLines() : file.AllLinesOfType(args.eTypeFilter); 52 | 53 | listener.Begin(); 54 | 55 | ExtrusionA = 0; 56 | CurPosition = Vector3d.Zero; 57 | 58 | foreach(GCodeLine line in lines_enum) { 59 | Action parseF; 60 | if (line.type == GCodeLine.LType.GCode) { 61 | if (GCodeMap.TryGetValue(line.code, out parseF)) 62 | parseF(line); 63 | } else if (line.type == GCodeLine.LType.MCode) { 64 | if (MCodeMap.TryGetValue(line.code, out parseF)) 65 | parseF(line); 66 | } 67 | } 68 | 69 | listener.End(); 70 | } 71 | 72 | 73 | 74 | 75 | public virtual IEnumerable InterpretInteractive(GCodeFile file, InterpretArgs args) 76 | { 77 | IEnumerable lines_enum = 78 | (args.HasTypeFilter) ? file.AllLinesOfType(args.eTypeFilter) : file.AllLines(); 79 | 80 | listener.Begin(); 81 | 82 | ExtrusionA = 0; 83 | CurPosition = Vector3d.Zero; 84 | 85 | foreach (GCodeLine line in lines_enum) { 86 | if (line.type == GCodeLine.LType.GCode) { 87 | Action parseF; 88 | if (GCodeMap.TryGetValue(line.code, out parseF)) { 89 | parseF(line); 90 | yield return true; 91 | } 92 | } 93 | } 94 | 95 | listener.End(); 96 | 97 | yield return false; 98 | } 99 | 100 | 101 | 102 | void emit_linear(GCodeLine line) 103 | { 104 | Debug.Assert(line.code == 0 || line.code == 1); 105 | 106 | double x = GCodeUtil.UnspecifiedValue, 107 | y = GCodeUtil.UnspecifiedValue, 108 | z = GCodeUtil.UnspecifiedValue; 109 | bool found_x = GCodeUtil.TryFindParamNum(line.parameters, "X", ref x); 110 | bool found_y = GCodeUtil.TryFindParamNum(line.parameters, "Y", ref y); 111 | bool found_z = GCodeUtil.TryFindParamNum(line.parameters, "Z", ref z); 112 | Vector3d newPos = (UseRelativePosition) ? Vector3d.Zero : CurPosition; 113 | if ( found_x ) 114 | newPos.x = x; 115 | if ( found_y ) 116 | newPos.y = y; 117 | if ( found_z ) 118 | newPos.z = z; 119 | if (UseRelativePosition) 120 | CurPosition += newPos; 121 | else 122 | CurPosition = newPos; 123 | 124 | // F is feed rate (this changes?) 125 | double f = 0; 126 | bool haveF = GCodeUtil.TryFindParamNum(line.parameters, "F", ref f); 127 | 128 | // A is extrusion stepper. E is also "current" stepper. 129 | double a = 0; 130 | bool haveA = GCodeUtil.TryFindParamNum(line.parameters, "A", ref a); 131 | if ( haveA == false ) { 132 | haveA = GCodeUtil.TryFindParamNum(line.parameters, "E", ref a); 133 | } 134 | if (UseRelativeExtruder) 135 | a = ExtrusionA + a; 136 | 137 | LinearMoveData move = new LinearMoveData( 138 | newPos, 139 | (haveF) ? f : GCodeUtil.UnspecifiedValue, 140 | (haveA) ? GCodeUtil.Extrude(a) : GCodeUtil.UnspecifiedPosition ); 141 | 142 | if ( haveA == false ) { 143 | // if we do not have extrusion, this is a travel move 144 | if (in_travel == false) { 145 | listener.BeginTravel(); 146 | in_travel = true; 147 | in_extrude = false; 148 | } 149 | 150 | } else if (in_retract) { 151 | // if we are in retract, we stay in until we see forward movement 152 | 153 | Debug.Assert(in_travel); 154 | Debug.Assert(a <= LastRetractA+0.001); 155 | if ( MathUtil.EpsilonEqual(a, LastRetractA, 0.00001) ) { 156 | in_retract = false; 157 | listener.BeginDeposition(); 158 | in_extrude = true; 159 | in_travel = false; 160 | ExtrusionA = a; 161 | } 162 | 163 | } else if ( a < ExtrusionA ) { 164 | // if extrusion moved backwards, we need to enter travel 165 | 166 | in_retract = true; 167 | LastRetractA = ExtrusionA; 168 | ExtrusionA = a; 169 | if (in_travel == false) { 170 | listener.BeginTravel(); 171 | in_travel = true; 172 | in_extrude = false; 173 | } 174 | } else { 175 | // if we are in travel, we need to begin extruding 176 | if (in_travel) { 177 | listener.BeginDeposition(); 178 | in_travel = false; 179 | in_extrude = true; 180 | } 181 | if (in_extrude == false) { // handle initialization cases 182 | listener.BeginDeposition(); 183 | in_extrude = true; 184 | } 185 | ExtrusionA = a; 186 | } 187 | 188 | move.source = line; 189 | Debug.Assert(in_travel || in_extrude); 190 | listener.LinearMoveToAbsolute3d(move); 191 | } 192 | 193 | 194 | 195 | // G92 - Position register: Set the specified axes positions to the given position 196 | // Sets the position of the state machine and the bot. NB: There are two methods of forming the G92 command: 197 | void set_position(GCodeLine line) 198 | { 199 | double x = 0, y = 0, z = 0, a = 0; 200 | if ( GCodeUtil.TryFindParamNum(line.parameters, "X", ref x ) ) { 201 | CurPosition.x = x; 202 | } 203 | if ( GCodeUtil.TryFindParamNum(line.parameters, "Y", ref y ) ) { 204 | CurPosition.y = y; 205 | } 206 | if ( GCodeUtil.TryFindParamNum(line.parameters, "Z", ref z ) ) { 207 | CurPosition.z = z; 208 | } 209 | if ( GCodeUtil.TryFindParamNum(line.parameters, "A", ref a ) ) { 210 | ExtrusionA = a; 211 | listener.CustomCommand( 212 | (int)CustomListenerCommands.ResetExtruder, GCodeUtil.Extrude(a) ); 213 | // reset our state 214 | in_travel = in_extrude = in_retract = false; 215 | } 216 | 217 | // E is "current" stepper (A for single extruder) 218 | double e = 0; 219 | if ( GCodeUtil.TryFindParamNum(line.parameters, "E", ref e ) ) { 220 | ExtrusionA = e; 221 | listener.CustomCommand( 222 | (int)CustomListenerCommands.ResetExtruder, GCodeUtil.Extrude(e) ); 223 | // reset our state 224 | in_travel = in_extrude = in_retract = false; 225 | } 226 | } 227 | 228 | 229 | // G90 230 | void set_absolute_positioning(GCodeLine line) { 231 | UseRelativePosition = false; 232 | } 233 | // G91 234 | void set_relative_positioning(GCodeLine line) { 235 | UseRelativePosition = true; 236 | 237 | // [RMS] according to http://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning, 238 | // this should only happen on some firmware... 239 | UseRelativeExtruder = true; 240 | } 241 | 242 | 243 | // M82 244 | void set_absolute_extruder(GCodeLine line) { 245 | UseRelativeExtruder = false; 246 | } 247 | // M83 248 | void set_relative_extruder(GCodeLine line) { 249 | UseRelativeExtruder = true; 250 | } 251 | 252 | 253 | 254 | void build_maps() 255 | { 256 | // G0 = rapid move 257 | GCodeMap[0] = emit_linear; 258 | 259 | // G1 = linear move 260 | GCodeMap[1] = emit_linear; 261 | 262 | // G4 = CCW circular 263 | //GCodeMap[4] = emit_ccw_arc; 264 | //GCodeMap[5] = emit_cw_arc; 265 | 266 | GCodeMap[90] = set_absolute_positioning; // http://reprap.org/wiki/G-code#G90:_Set_to_Absolute_Positioning 267 | GCodeMap[91] = set_relative_positioning; // http://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning 268 | GCodeMap[92] = set_position; // http://reprap.org/wiki/G-code#G92:_Set_Position 269 | 270 | 271 | MCodeMap[82] = set_absolute_extruder; // http://reprap.org/wiki/G-code#M83:_Set_extruder_to_relative_mode 272 | MCodeMap[83] = set_relative_extruder; // http://reprap.org/wiki/G-code#M83:_Set_extruder_to_relative_mode 273 | } 274 | 275 | 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /interpreters/ThreeAxisCNCInterpreter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | /// 10 | /// Basic 3-axis CNC interpreter 11 | /// 12 | public class ThreeAxisCNCInterpreter : IGCodeInterpreter 13 | { 14 | IGCodeListener listener = null; 15 | 16 | Dictionary> GCodeMap = new Dictionary>(); 17 | Dictionary> MCodeMap = new Dictionary>(); 18 | 19 | bool UseRelativePosition = false; 20 | 21 | 22 | Vector3d CurPosition = Vector3d.Zero; 23 | 24 | bool in_travel = false; 25 | bool in_cut = false; 26 | 27 | public ThreeAxisCNCInterpreter() { 28 | build_maps(); 29 | } 30 | 31 | public virtual void AddListener(IGCodeListener listener) 32 | { 33 | if (this.listener != null) 34 | throw new Exception("Only one listener supported!"); 35 | this.listener = listener; 36 | } 37 | 38 | 39 | public virtual void Interpret(GCodeFile file, InterpretArgs args) 40 | { 41 | IEnumerable lines_enum = 42 | (args.HasTypeFilter) ? file.AllLines() : file.AllLinesOfType(args.eTypeFilter); 43 | 44 | listener.Begin(); 45 | 46 | CurPosition = Vector3d.Zero; 47 | 48 | foreach(GCodeLine line in lines_enum) { 49 | Action parseF; 50 | if (line.type == GCodeLine.LType.GCode) { 51 | if (GCodeMap.TryGetValue(line.code, out parseF)) 52 | parseF(line); 53 | } else if (line.type == GCodeLine.LType.MCode) { 54 | if (MCodeMap.TryGetValue(line.code, out parseF)) 55 | parseF(line); 56 | } 57 | } 58 | 59 | listener.End(); 60 | } 61 | 62 | 63 | 64 | 65 | public virtual IEnumerable InterpretInteractive(GCodeFile file, InterpretArgs args) 66 | { 67 | IEnumerable lines_enum = 68 | (args.HasTypeFilter) ? file.AllLinesOfType(args.eTypeFilter) : file.AllLines(); 69 | 70 | listener.Begin(); 71 | 72 | CurPosition = Vector3d.Zero; 73 | 74 | foreach (GCodeLine line in lines_enum) { 75 | if (line.type == GCodeLine.LType.GCode) { 76 | Action parseF; 77 | if (GCodeMap.TryGetValue(line.code, out parseF)) { 78 | parseF(line); 79 | yield return true; 80 | } 81 | } 82 | } 83 | 84 | listener.End(); 85 | 86 | yield return false; 87 | } 88 | 89 | 90 | 91 | void emit_linear(GCodeLine line) 92 | { 93 | Debug.Assert(line.code == 0 || line.code == 1); 94 | 95 | double x = GCodeUtil.UnspecifiedValue, 96 | y = GCodeUtil.UnspecifiedValue, 97 | z = GCodeUtil.UnspecifiedValue; 98 | bool found_x = GCodeUtil.TryFindParamNum(line.parameters, "X", ref x); 99 | bool found_y = GCodeUtil.TryFindParamNum(line.parameters, "Y", ref y); 100 | bool found_z = GCodeUtil.TryFindParamNum(line.parameters, "Z", ref z); 101 | Vector3d newPos = (UseRelativePosition) ? Vector3d.Zero : CurPosition; 102 | if ( found_x ) 103 | newPos.x = x; 104 | if ( found_y ) 105 | newPos.y = y; 106 | if ( found_z ) 107 | newPos.z = z; 108 | if (UseRelativePosition) 109 | CurPosition += newPos; 110 | else 111 | CurPosition = newPos; 112 | 113 | // F is feed rate (this changes?) 114 | double f = 0; 115 | bool haveF = GCodeUtil.TryFindParamNum(line.parameters, "F", ref f); 116 | 117 | LinearMoveData move = new LinearMoveData( 118 | newPos, 119 | (haveF) ? f : GCodeUtil.UnspecifiedValue ); 120 | 121 | bool is_travel = (line.code == 0); 122 | 123 | if (is_travel) { 124 | if (in_travel == false) { 125 | listener.BeginTravel(); 126 | in_travel = true; 127 | in_cut = false; 128 | } 129 | } else { 130 | if ( in_cut == false) { 131 | listener.BeginCut(); 132 | in_travel = false; 133 | in_cut = true; 134 | } 135 | } 136 | 137 | move.source = line; 138 | Debug.Assert(in_travel || in_cut); 139 | listener.LinearMoveToAbsolute3d(move); 140 | } 141 | 142 | 143 | 144 | // G92 - Position register: Set the specified axes positions to the given position 145 | // Sets the position of the state machine and the bot. NB: There are two methods of forming the G92 command: 146 | void set_position(GCodeLine line) 147 | { 148 | double x = 0, y = 0, z = 0; 149 | if ( GCodeUtil.TryFindParamNum(line.parameters, "X", ref x ) ) { 150 | CurPosition.x = x; 151 | } 152 | if ( GCodeUtil.TryFindParamNum(line.parameters, "Y", ref y ) ) { 153 | CurPosition.y = y; 154 | } 155 | if ( GCodeUtil.TryFindParamNum(line.parameters, "Z", ref z ) ) { 156 | CurPosition.z = z; 157 | } 158 | } 159 | 160 | 161 | // G90 162 | void set_absolute_positioning(GCodeLine line) { 163 | UseRelativePosition = false; 164 | } 165 | // G91 166 | void set_relative_positioning(GCodeLine line) { 167 | UseRelativePosition = true; 168 | } 169 | 170 | 171 | 172 | 173 | void build_maps() 174 | { 175 | // G0 = rapid move 176 | GCodeMap[0] = emit_linear; 177 | 178 | // G1 = linear move 179 | GCodeMap[1] = emit_linear; 180 | 181 | // G4 = CCW circular 182 | //GCodeMap[4] = emit_ccw_arc; 183 | //GCodeMap[5] = emit_cw_arc; 184 | 185 | GCodeMap[90] = set_absolute_positioning; // http://reprap.org/wiki/G-code#G90:_Set_to_Absolute_Positioning 186 | GCodeMap[91] = set_relative_positioning; // http://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning 187 | GCodeMap[92] = set_position; // http://reprap.org/wiki/G-code#G92:_Set_Position 188 | } 189 | 190 | 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /parsers/GCodeUtil.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | static public class GCodeUtil 10 | { 11 | public const double UnspecifiedValue = double.MaxValue; 12 | public static readonly Vector3d UnspecifiedPosition = Vector3d.MaxValue; 13 | public static readonly Vector2d UnspecifiedDimensions = Vector2d.MaxValue; 14 | 15 | public static Vector3d Extrude(double a) { 16 | return new Vector3d(a, UnspecifiedValue, UnspecifiedValue); 17 | } 18 | 19 | 20 | // returns index of param, or -1 21 | static public int TryFindParam(GCodeParam[] paramList, string identifier ) 22 | { 23 | for (int i = 0; i < paramList.Length; ++i) 24 | if (paramList[i].identifier == identifier) 25 | return i; 26 | return -1; 27 | } 28 | 29 | static public bool TryFindParamNum(GCodeParam[] paramList, string identifier, ref double d) 30 | { 31 | if (paramList == null ) 32 | return false; 33 | for (int i = 0; i < paramList.Length; ++i) { 34 | if (paramList[i].identifier == identifier) { 35 | if (paramList[i].type == GCodeParam.PType.DoubleValue) { 36 | d = paramList[i].doubleValue; 37 | return true; 38 | } else if (paramList[i].type == GCodeParam.PType.IntegerValue) { 39 | d = paramList[i].intValue; 40 | return true; 41 | } else 42 | return false; 43 | } 44 | } 45 | return false; 46 | } 47 | 48 | 49 | 50 | public enum NumberType 51 | { 52 | Integer, Decimal, NotANumber 53 | } 54 | 55 | // doesn't handle e^ numbers 56 | // doesn't allow commas 57 | static public NumberType GetNumberType(string s) 58 | { 59 | int N = s.Length; 60 | 61 | bool saw_digit = false; 62 | bool saw_dot = false; 63 | bool saw_sign = false; 64 | for (int i = 0; i < N; ++i) { 65 | char c = s[i]; 66 | if ( c == '-' ) { 67 | if (saw_digit || saw_dot || saw_sign) 68 | return NumberType.NotANumber; 69 | saw_sign = true; 70 | } else if ( c == '.' ) { 71 | if (saw_dot) 72 | return NumberType.NotANumber; 73 | saw_dot = true; 74 | } else if (Char.IsDigit(c)) { 75 | saw_digit = true; 76 | } else { 77 | return NumberType.NotANumber; 78 | } 79 | } 80 | if (!saw_digit) 81 | return NumberType.NotANumber; 82 | return (saw_dot) ? NumberType.Decimal : NumberType.Integer; 83 | } 84 | 85 | 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /parsers/GenericGCodeParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace gs 8 | { 9 | public class GenericGCodeParser 10 | { 11 | 12 | public GCodeFile Parse(TextReader input) 13 | { 14 | GCodeFile file = new GCodeFile(); 15 | 16 | int lines = 0; 17 | while ( input.Peek() >= 0 ) { 18 | string line = input.ReadLine(); 19 | int nLineNum = lines++; 20 | 21 | GCodeLine l = ParseLine(line, nLineNum); 22 | file.AppendLine(l); 23 | } 24 | 25 | return file; 26 | } 27 | 28 | 29 | 30 | virtual protected GCodeLine ParseLine(string line, int nLineNum) 31 | { 32 | if (line.Length == 0) 33 | return make_blank(nLineNum); 34 | if (line[0] == ';') 35 | return make_comment(line, nLineNum); 36 | 37 | // strip off trailing comment 38 | string comment = null; 39 | int ci = line.IndexOf(';'); 40 | if ( ci < 0 ) { 41 | int bo = line.IndexOf('('); 42 | int bc = line.IndexOf(')'); 43 | if ( bo >= 0 && bc > 0 ) 44 | ci = bo; 45 | } 46 | if ( ci >= 1 ) { 47 | comment = line.Substring(ci); 48 | line = line.Substring(0, ci); 49 | } 50 | 51 | 52 | string[] tokens = line.Split( (char[])null , StringSplitOptions.RemoveEmptyEntries); 53 | 54 | // handle extra spaces at start...? 55 | if (tokens.Length == 0) 56 | return make_blank(nLineNum); 57 | 58 | GCodeLine gcode = null; 59 | switch ( tokens[0][0]) { 60 | case ';': 61 | gcode = make_comment(line, nLineNum); 62 | break; 63 | case 'N': 64 | gcode = make_N_code_line(line, tokens, nLineNum); 65 | break; 66 | case 'G': 67 | case 'M': 68 | gcode = make_GM_code_line(line, tokens, nLineNum); 69 | break; 70 | case ':': 71 | gcode = make_control_line(line, tokens, nLineNum); 72 | break; 73 | default: 74 | gcode = make_string_line(line, nLineNum); 75 | break; 76 | } 77 | 78 | if ( comment != null ) 79 | gcode.comment = comment; 80 | 81 | return gcode; 82 | } 83 | 84 | 85 | 86 | 87 | // G### and M### code lines 88 | virtual protected GCodeLine make_GM_code_line(string line, string[] tokens, int nLineNum) 89 | { 90 | GCodeLine.LType eType = GCodeLine.LType.UnknownCode; 91 | if (tokens[0][0] == 'G') 92 | eType = GCodeLine.LType.GCode; 93 | else if (tokens[0][0] == 'M') 94 | eType = GCodeLine.LType.MCode; 95 | 96 | GCodeLine l = new GCodeLine(nLineNum, eType); 97 | l.orig_string = line; 98 | 99 | l.N = int.Parse(tokens[0].Substring(1)); 100 | 101 | // [TODO] comments 102 | 103 | if (eType == GCodeLine.LType.UnknownCode) { 104 | if (tokens.Length > 1) 105 | l.parameters = parse_parameters(tokens, 1); 106 | } else { 107 | l.code = int.Parse(tokens[0].Substring(1)); 108 | if (tokens.Length > 1) 109 | l.parameters = parse_parameters(tokens, 1); 110 | } 111 | 112 | return l; 113 | } 114 | 115 | 116 | 117 | // N### lines 118 | virtual protected GCodeLine make_N_code_line(string line, string[] tokens, int nLineNum) 119 | { 120 | GCodeLine.LType eType = GCodeLine.LType.UnknownCode; 121 | if (tokens[1][0] == 'G') 122 | eType = GCodeLine.LType.GCode; 123 | else if (tokens[1][0] == 'M') 124 | eType = GCodeLine.LType.MCode; 125 | 126 | GCodeLine l = new GCodeLine(nLineNum, eType); 127 | l.orig_string = line; 128 | 129 | l.N = int.Parse(tokens[0].Substring(1)); 130 | 131 | // [TODO] comments 132 | 133 | if (eType == GCodeLine.LType.UnknownCode) { 134 | if (tokens.Length > 1) 135 | l.parameters = parse_parameters(tokens, 1); 136 | } else { 137 | l.code = int.Parse(tokens[1].Substring(1)); 138 | if (tokens.Length > 2) 139 | l.parameters = parse_parameters(tokens, 2); 140 | } 141 | 142 | return l; 143 | } 144 | 145 | 146 | 147 | 148 | 149 | 150 | // any line we can't understand 151 | virtual protected GCodeLine make_string_line(string line, int nLineNum) 152 | { 153 | GCodeLine l = new GCodeLine(nLineNum, GCodeLine.LType.UnknownString); 154 | l.orig_string = line; 155 | return l; 156 | } 157 | 158 | 159 | 160 | // :IF, :ENDIF, :ELSE 161 | virtual protected GCodeLine make_control_line(string line, string[] tokens, int nLineNum) 162 | { 163 | // figure out command type 164 | string command = tokens[0].Substring(1); 165 | GCodeLine.LType eType = GCodeLine.LType.UnknownControl; 166 | if (command.Equals("if", StringComparison.OrdinalIgnoreCase)) 167 | eType = GCodeLine.LType.If; 168 | else if (command.Equals("else", StringComparison.OrdinalIgnoreCase)) 169 | eType = GCodeLine.LType.Else; 170 | else if (command.Equals("endif", StringComparison.OrdinalIgnoreCase)) 171 | eType = GCodeLine.LType.EndIf; 172 | 173 | GCodeLine l = new GCodeLine(nLineNum, eType); 174 | l.orig_string = line; 175 | 176 | if (tokens.Length > 1) 177 | l.parameters = parse_parameters(tokens, 1); 178 | 179 | return l; 180 | } 181 | 182 | 183 | 184 | // line starting with ; 185 | virtual protected GCodeLine make_comment(string line, int nLineNum) 186 | { 187 | GCodeLine l = new GCodeLine(nLineNum, GCodeLine.LType.Comment); 188 | 189 | l.orig_string = line; 190 | int iStart = line.IndexOf(';'); 191 | l.comment = line.Substring(iStart); 192 | return l; 193 | } 194 | 195 | 196 | // line with no text at all 197 | virtual protected GCodeLine make_blank(int nLineNum) 198 | { 199 | return new GCodeLine(nLineNum, GCodeLine.LType.Blank); 200 | } 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | virtual protected GCodeParam[] parse_parameters(string[] tokens, int iStart, int iEnd = -1) 209 | { 210 | if (iEnd == -1) 211 | iEnd = tokens.Length; 212 | 213 | int N = iEnd - iStart; 214 | GCodeParam[] paramList = new GCodeParam[N]; 215 | 216 | for ( int ti = iStart; ti < iEnd; ++ti ) { 217 | int pi = ti - iStart; 218 | 219 | bool bHandled = false; 220 | if ( tokens[ti].Contains('=') ) { 221 | parse_equals_parameter(tokens[ti], ref paramList[pi]); 222 | bHandled = true; 223 | 224 | } else if ( tokens[ti][0] == 'G' || tokens[ti][0] == 'M' ) { 225 | parse_code_parameter(tokens[ti], ref paramList[pi]); 226 | bHandled = true; 227 | 228 | } else if ( is_num_parameter(tokens[ti]) > 0 ) { 229 | parse_noequals_num_parameter( tokens[ti], ref paramList[pi] ); 230 | bHandled = true; 231 | 232 | } else if ( tokens[ti].Length == 1 ) { 233 | paramList[pi].type = GCodeParam.PType.NoValue; 234 | paramList[pi].identifier = tokens[ti]; 235 | bHandled = true; 236 | } 237 | 238 | if (!bHandled) { 239 | paramList[pi].type = GCodeParam.PType.TextValue; 240 | paramList[pi].textValue = tokens[ti]; 241 | } 242 | } 243 | 244 | return paramList; 245 | } 246 | 247 | 248 | 249 | 250 | virtual protected bool parse_code_parameter(string token, ref GCodeParam param) 251 | { 252 | param.type = GCodeParam.PType.Code; 253 | param.identifier = token.Substring(0,1); 254 | 255 | string value = token.Substring(1); 256 | GCodeUtil.NumberType numType = GCodeUtil.GetNumberType(value); 257 | if (numType == GCodeUtil.NumberType.Integer) 258 | param.intValue = int.Parse(value); 259 | 260 | return true; 261 | } 262 | 263 | 264 | virtual protected int is_num_parameter(string token) 265 | { 266 | int N = token.Length; 267 | 268 | bool contains_number = false; 269 | for (int i = 0; i < N && contains_number == false; ++i) { 270 | if (Char.IsDigit(token[i])) 271 | contains_number = true; 272 | } 273 | if (!contains_number) 274 | return -1; 275 | 276 | for ( int i = 1; i < N; ++i ) { 277 | string sub = token.Substring(i); 278 | GCodeUtil.NumberType numtype = GCodeUtil.GetNumberType(sub); 279 | if (numtype != GCodeUtil.NumberType.NotANumber) { 280 | return i; 281 | } 282 | } 283 | return -1; 284 | } 285 | 286 | 287 | virtual protected bool parse_noequals_num_parameter(string token, ref GCodeParam param) 288 | { 289 | int i = is_num_parameter(token); 290 | if ( i >= 0 ) 291 | return parse_value_param(token, i, 0, ref param); 292 | return false; 293 | } 294 | 295 | 296 | 297 | virtual protected bool parse_equals_parameter(string token, ref GCodeParam param) 298 | { 299 | int i = token.IndexOf('='); 300 | return parse_value_param(token, i, 1, ref param); 301 | } 302 | 303 | 304 | 305 | virtual protected bool parse_value_param(string token, int split, int skip, ref GCodeParam param) 306 | { 307 | param.identifier = token.Substring(0, split); 308 | 309 | string value = token.Substring(split + skip, token.Length - (split+skip)); 310 | 311 | try { 312 | GCodeUtil.NumberType numType = GCodeUtil.GetNumberType(value); 313 | if (numType == GCodeUtil.NumberType.Decimal) { 314 | param.type = GCodeParam.PType.DoubleValue; 315 | param.doubleValue = double.Parse(value); 316 | return true; 317 | } else if (numType == GCodeUtil.NumberType.Integer) { 318 | param.type = GCodeParam.PType.IntegerValue; 319 | param.intValue = int.Parse(value); 320 | return true; 321 | } 322 | } catch { 323 | // just continue on and do generic string param 324 | } 325 | 326 | param.type = GCodeParam.PType.TextValue; 327 | param.textValue = value; 328 | return true; 329 | } 330 | 331 | 332 | } 333 | } 334 | -------------------------------------------------------------------------------- /settings/AdditiveSettings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using g3; 3 | 4 | namespace gs 5 | { 6 | public enum MachineClass 7 | { 8 | Unknown, 9 | PlasticFFFPrinter, 10 | MetalSLSPrinter 11 | } 12 | 13 | 14 | public abstract class MachineInfo 15 | { 16 | protected static string UnknownUUID = "00000000-0000-0000-0000-000000000000"; 17 | 18 | public string ManufacturerName = "Unknown"; 19 | public string ManufacturerUUID = UnknownUUID; 20 | public string ModelIdentifier = "Machine"; 21 | public string ModelUUID = UnknownUUID; 22 | public MachineClass Class = MachineClass.Unknown; 23 | 24 | public double BedSizeXMM = 100; 25 | public double BedSizeYMM = 100; 26 | public double MaxHeightMM = 100; 27 | 28 | // These factors define the output coordinate system 29 | 30 | // BedOriginFactorX: 31 | // 0 : the origin is at the left of the build plate 32 | // 0.5 : the origin is at the middle of the build plate 33 | // 1 : the origin is at the right of the build plate 34 | 35 | // BedOriginFactorY: 36 | // 0 : the origin is at the front of the build plate 37 | // 0.5 : the origin is at the middle of the build plate 38 | // 1 : the origin is at the back of the build plate 39 | 40 | public double BedOriginFactorX = 0; 41 | public double BedOriginFactorY = 0; 42 | 43 | public abstract T CloneAs() where T : class; 44 | protected virtual void CopyFieldsTo(MachineInfo to) 45 | { 46 | to.ManufacturerName = this.ManufacturerName; 47 | to.ManufacturerUUID = this.ManufacturerUUID; 48 | to.ModelIdentifier = this.ModelIdentifier; 49 | to.ModelUUID = this.ModelUUID; 50 | to.Class = this.Class; 51 | to.BedSizeXMM = this.BedSizeXMM; 52 | to.BedSizeYMM = this.BedSizeYMM; 53 | to.MaxHeightMM = this.MaxHeightMM; 54 | } 55 | } 56 | 57 | 58 | 59 | public class FFFMachineInfo : MachineInfo 60 | { 61 | /* 62 | * printer mechanics 63 | */ 64 | public double NozzleDiamMM = 0.4; 65 | public double FilamentDiamMM = 1.75; 66 | 67 | public double MinLayerHeightMM = 0.2; 68 | public double MaxLayerHeightMM = 0.2; 69 | 70 | /* 71 | * Temperatures 72 | */ 73 | 74 | public int MinExtruderTempC = 20; 75 | public int MaxExtruderTempC = 230; 76 | 77 | public bool HasHeatedBed = false; 78 | public int MinBedTempC = 0; 79 | public int MaxBedTempC = 0; 80 | 81 | /* 82 | * All units are mm/min = (mm/s * 60) 83 | */ 84 | public int MaxExtrudeSpeedMMM = 50 * 60; 85 | public int MaxTravelSpeedMMM = 100 * 60; 86 | public int MaxZTravelSpeedMMM = 20 * 60; 87 | public int MaxRetractSpeedMMM = 20 * 60; 88 | 89 | 90 | /* 91 | * bed levelling 92 | */ 93 | public bool HasAutoBedLeveling = false; 94 | public bool EnableAutoBedLeveling = false; 95 | 96 | 97 | /* 98 | * Hacks? 99 | */ 100 | 101 | public double MinPointSpacingMM = 0.1; // Avoid emitting gcode extrusion points closer than this spacing. 102 | // This is a workaround for the fact that many printers do not gracefully 103 | // handle very tiny sequential extrusion steps. This setting could be 104 | // configured using CalibrationModelGenerator.MakePrintStepSizeTest() with 105 | // all other cleanup steps disabled. 106 | // [TODO] this is actually speed-dependent... 107 | 108 | public override T CloneAs() 109 | { 110 | FFFMachineInfo fi = new FFFMachineInfo(); 111 | this.CopyFieldsTo(fi); 112 | return fi as T; 113 | } 114 | protected virtual void CopyFieldsTo(FFFMachineInfo to) 115 | { 116 | base.CopyFieldsTo(to); 117 | 118 | to.NozzleDiamMM = this.NozzleDiamMM; 119 | to.FilamentDiamMM = this.FilamentDiamMM; 120 | to.MinLayerHeightMM = this.MinLayerHeightMM; 121 | to.MaxHeightMM = this.MaxHeightMM; 122 | to.MinExtruderTempC = this.MaxExtruderTempC; 123 | to.HasHeatedBed = this.HasHeatedBed; 124 | to.MinBedTempC = this.MinBedTempC; 125 | to.MaxBedTempC = this.MaxBedTempC; 126 | to.MaxExtrudeSpeedMMM = this.MaxExtrudeSpeedMMM; 127 | to.MaxTravelSpeedMMM = this.MaxTravelSpeedMMM; 128 | to.MaxZTravelSpeedMMM = this.MaxZTravelSpeedMMM; 129 | to.MaxRetractSpeedMMM = this.MaxRetractSpeedMMM; 130 | to.MinPointSpacingMM = this.MinPointSpacingMM; 131 | 132 | to.EnableAutoBedLeveling = this.EnableAutoBedLeveling; 133 | to.HasAutoBedLeveling = this.HasAutoBedLeveling; 134 | 135 | to.ManufacturerName = this.ManufacturerName; 136 | to.ManufacturerUUID = this.ManufacturerUUID; 137 | to.ModelIdentifier = this.ModelIdentifier; 138 | to.ModelUUID = this.ModelUUID; 139 | to.Class = this.Class; 140 | to.BedSizeXMM = this.BedSizeXMM; 141 | to.BedSizeYMM = this.BedSizeYMM; 142 | to.MaxHeightMM = this.MaxHeightMM; 143 | to.BedOriginFactorX = this.BedOriginFactorX; 144 | to.BedOriginFactorY = this.BedOriginFactorY; 145 | } 146 | } 147 | 148 | 149 | 150 | public abstract class PlanarAdditiveSettings 151 | { 152 | /// 153 | /// This is the "name" of this settings (eg user identifier) 154 | /// 155 | public string Identifier = "Defaults"; 156 | 157 | public double LayerHeightMM = 0.2; 158 | 159 | 160 | public string ClassTypeName { 161 | get { return GetType().ToString(); } 162 | } 163 | 164 | 165 | public abstract MachineInfo BaseMachine { get; set; } 166 | 167 | public abstract T CloneAs() where T : class; 168 | protected virtual void CopyFieldsTo(PlanarAdditiveSettings to) 169 | { 170 | to.Identifier = this.Identifier; 171 | to.LayerHeightMM = this.LayerHeightMM; 172 | } 173 | } 174 | 175 | 176 | 177 | public class SingleMaterialFFFSettings : PlanarAdditiveSettings 178 | { 179 | // This is a bit of an odd place for this, but settings are where we actually 180 | // know what assembler we should be using... 181 | public virtual AssemblerFactoryF AssemblerType() { 182 | throw new NotImplementedException("Settings.AssemblerType() not provided"); 183 | } 184 | 185 | 186 | protected FFFMachineInfo machineInfo; 187 | public FFFMachineInfo Machine { 188 | get { if (machineInfo == null) machineInfo = new FFFMachineInfo(); return machineInfo; } 189 | set { machineInfo = value; } 190 | } 191 | 192 | 193 | public override MachineInfo BaseMachine { 194 | get { return Machine; } 195 | set { if (value is FFFMachineInfo) 196 | machineInfo = value as FFFMachineInfo; 197 | else 198 | throw new Exception("SingleMaterialFFFSettings.Machine.set: type is not FFFMachineInfo!"); 199 | } 200 | } 201 | 202 | /* 203 | * Temperatures 204 | */ 205 | 206 | public int ExtruderTempC = 210; 207 | public int HeatedBedTempC = 0; 208 | 209 | /* 210 | * Distances. 211 | * All units are mm 212 | */ 213 | 214 | public bool EnableRetraction = true; 215 | public double RetractDistanceMM = 1.3; 216 | public double MinRetractTravelLength = 2.5; // don't retract if we are travelling less than this distance 217 | 218 | 219 | /* 220 | * Speeds. 221 | * All units are mm/min = (mm/s * 60) 222 | */ 223 | 224 | // these are all in units of millimeters/minute 225 | public double RetractSpeed = 25 * 60; // 1500 226 | 227 | public double ZTravelSpeed = 23 * 60; // 1380 228 | 229 | public double RapidTravelSpeed = 150 * 60; // 9000 230 | 231 | public double CarefulExtrudeSpeed = 30 * 60; // 1800 232 | public double RapidExtrudeSpeed = 90 * 60; // 5400 233 | public double MinExtrudeSpeed = 20 * 60; // 600 234 | 235 | public double OuterPerimeterSpeedX = 0.5; 236 | 237 | public double FanSpeedX = 1.0; // default fan speed, fraction of max speed (generally unknown) 238 | 239 | 240 | // Settings for z-lift on rapid travel moves 241 | public bool TravelLiftEnabled { get; set; } = true; 242 | public double TravelLiftHeight { get; set; } = 0.2; 243 | public double TravelLiftDistanceThreshold { get; set; } = 5d; 244 | 245 | /* 246 | * Shells 247 | */ 248 | public int Shells = 2; 249 | public int InteriorSolidRegionShells = 0; // how many shells to add around interior solid regions (eg roof/floor) 250 | public bool OuterShellLast = false; // do outer shell last (better quality but worse precision) 251 | 252 | /* 253 | * Roof/Floors 254 | */ 255 | public int RoofLayers = 2; 256 | public int FloorLayers = 2; 257 | 258 | /* 259 | * Solid fill settings 260 | */ 261 | public double ShellsFillNozzleDiamStepX = 1.0; // multipler on Machine.NozzleDiamMM, defines spacing between adjacent 262 | // nested shells/perimeters. If < 1, they overlap. 263 | public double SolidFillNozzleDiamStepX = 1.0; // multipler on Machine.NozzleDiamMM, defines spacing between adjacent 264 | // solid fill parallel lines. If < 1, they overlap. 265 | public double SolidFillBorderOverlapX = 0.25f; // this is a multiplier on Machine.NozzleDiamMM, defines how far we 266 | // overlap solid fill onto border shells (if 0, no overlap) 267 | 268 | /* 269 | * Sparse infill settings 270 | */ 271 | public double SparseLinearInfillStepX = 5.0; // this is a multiplier on FillPathSpacingMM 272 | 273 | public double SparseFillBorderOverlapX = 0.25f; // this is a multiplier on Machine.NozzleDiamMM, defines how far we 274 | // overlap solid fill onto border shells (if 0, no overlap) 275 | 276 | /* 277 | * Start layer controls 278 | */ 279 | public int StartLayers = 0; // number of start layers, special handling 280 | public double StartLayerHeightMM = 0; // height of start layers. If 0, same as regular layers 281 | 282 | 283 | /* 284 | * Support settings 285 | */ 286 | public bool GenerateSupport = true; // should we auto-generate support 287 | public double SupportOverhangAngleDeg = 35; // standard "support angle" 288 | public double SupportSpacingStepX = 5.0; // usage depends on support technique? 289 | public double SupportVolumeScale = 1.0; // multiplier on extrusion volume 290 | public bool EnableSupportShell = true; // should we print a shell around support areas 291 | public double SupportAreaOffsetX = -0.5; // 2D inset/outset added to support regions. Multiplier on Machine.NozzleDiamMM. 292 | public double SupportSolidSpace = 0.35f; // how much space to leave between model and support 293 | public double SupportRegionJoinTolX = 2.0; // support regions within this distance will be merged via topological dilation. Multiplier on NozzleDiamMM. 294 | public bool EnableSupportReleaseOpt = true; // should we use support release optimization 295 | public double SupportReleaseGap = 0.2f; // how much space do we leave 296 | public double SupportMinDimension = 1.5; // minimal size of support polygons 297 | public bool SupportMinZTips = true; // turn on/off detection of support 'tip' regions, ie tiny islands. 298 | public double SupportPointDiam = 2.5f; // width of per-layer support "points" (keep larger than SupportMinDimension!) 299 | public int SupportPointSides = 4; // number of vertices for support-point polygons (circles) 300 | 301 | 302 | /* 303 | * Bridging settings 304 | */ 305 | public bool EnableBridging = true; 306 | public double MaxBridgeWidthMM = 10.0; 307 | public double BridgeFillNozzleDiamStepX = 0.85; // multiplier on FillPathSpacingMM 308 | public double BridgeVolumeScale = 1.0; // multiplier on extrusion volume 309 | public double BridgeExtrudeSpeedX = 0.5; // multiplier on CarefulExtrudeSpeed 310 | 311 | 312 | /* 313 | * Toolpath filtering options 314 | */ 315 | public double MinLayerTime = 5.0; // minimum layer time in seconds 316 | public bool ClipSelfOverlaps = false; // if true, try to remove portions of toolpaths that will self-overlap 317 | public double SelfOverlapToleranceX = 0.75; // what counts as 'self-overlap'. this is a multiplier on NozzleDiamMM 318 | 319 | /* 320 | * Debug/Utility options 321 | */ 322 | 323 | public Interval1i LayerRangeFilter = new Interval1i(0, 999999999); // only compute slices in this range 324 | 325 | 326 | 327 | 328 | /* 329 | * functions that calculate derived values 330 | * NOTE: these cannot be properties because then they will be json-serialized! 331 | */ 332 | public double ShellsFillPathSpacingMM() { 333 | return Machine.NozzleDiamMM * ShellsFillNozzleDiamStepX; 334 | } 335 | public double SolidFillPathSpacingMM() { 336 | return Machine.NozzleDiamMM * SolidFillNozzleDiamStepX; 337 | } 338 | public double BridgeFillPathSpacingMM() { 339 | return Machine.NozzleDiamMM * BridgeFillNozzleDiamStepX; 340 | } 341 | 342 | 343 | public override T CloneAs() 344 | { 345 | SingleMaterialFFFSettings copy = new SingleMaterialFFFSettings(); 346 | this.CopyFieldsTo(copy); 347 | return copy as T; 348 | } 349 | protected virtual void CopyFieldsTo(SingleMaterialFFFSettings to) 350 | { 351 | base.CopyFieldsTo(to); 352 | to.machineInfo = this.machineInfo.CloneAs(); 353 | 354 | to.ExtruderTempC = this.ExtruderTempC; 355 | to.HeatedBedTempC = this.HeatedBedTempC; 356 | to.EnableRetraction = this.EnableRetraction; 357 | to.RetractDistanceMM = this.RetractDistanceMM; 358 | to.MinRetractTravelLength = this.MinRetractTravelLength; 359 | 360 | to.RetractSpeed = this.RetractSpeed; 361 | to.ZTravelSpeed = this.ZTravelSpeed; 362 | to.RapidTravelSpeed = this.RapidTravelSpeed; 363 | to.CarefulExtrudeSpeed = this.CarefulExtrudeSpeed; 364 | to.RapidExtrudeSpeed = this.RapidExtrudeSpeed; 365 | to.MinExtrudeSpeed = this.MinExtrudeSpeed; 366 | to.OuterPerimeterSpeedX = this.OuterPerimeterSpeedX; 367 | to.FanSpeedX = this.FanSpeedX; 368 | 369 | to.TravelLiftEnabled = this.TravelLiftEnabled; 370 | to.TravelLiftHeight = this.TravelLiftHeight; 371 | to.TravelLiftDistanceThreshold = this.TravelLiftDistanceThreshold; 372 | 373 | to.Shells = this.Shells; 374 | to.InteriorSolidRegionShells = this.InteriorSolidRegionShells; 375 | to.OuterShellLast = this.OuterShellLast; 376 | to.RoofLayers = this.RoofLayers; 377 | to.FloorLayers = this.FloorLayers; 378 | 379 | to.ShellsFillNozzleDiamStepX = this.ShellsFillNozzleDiamStepX; 380 | to.SolidFillNozzleDiamStepX = this.SolidFillNozzleDiamStepX; 381 | to.SolidFillBorderOverlapX = this.SolidFillBorderOverlapX; 382 | 383 | to.SparseLinearInfillStepX = this.SparseLinearInfillStepX; 384 | to.SparseFillBorderOverlapX = this.SparseFillBorderOverlapX; 385 | 386 | to.StartLayers = this.StartLayers; 387 | to.StartLayerHeightMM = this.StartLayerHeightMM; 388 | 389 | to.GenerateSupport = this.GenerateSupport; 390 | to.SupportOverhangAngleDeg = this.SupportOverhangAngleDeg; 391 | to.SupportSpacingStepX = this.SupportSpacingStepX; 392 | to.SupportVolumeScale = this.SupportVolumeScale; 393 | to.EnableSupportShell = this.EnableSupportShell; 394 | to.SupportAreaOffsetX = this.SupportAreaOffsetX; 395 | to.SupportSolidSpace = this.SupportSolidSpace; 396 | to.SupportRegionJoinTolX = this.SupportRegionJoinTolX; 397 | to.EnableSupportReleaseOpt = this.EnableSupportReleaseOpt; 398 | to.SupportReleaseGap = this.SupportReleaseGap; 399 | to.SupportMinDimension = this.SupportMinDimension; 400 | to.SupportMinZTips = this.SupportMinZTips; 401 | to.SupportPointDiam = this.SupportPointDiam; 402 | to.SupportPointSides = this.SupportPointSides; 403 | 404 | to.EnableBridging = this.EnableBridging; 405 | to.MaxBridgeWidthMM = this.MaxBridgeWidthMM; 406 | to.BridgeFillNozzleDiamStepX = this.BridgeFillNozzleDiamStepX; 407 | to.BridgeVolumeScale = this.BridgeVolumeScale; 408 | to.BridgeExtrudeSpeedX = this.BridgeExtrudeSpeedX; 409 | 410 | 411 | to.MinLayerTime = this.MinLayerTime; 412 | to.ClipSelfOverlaps = this.ClipSelfOverlaps; 413 | to.SelfOverlapToleranceX = this.SelfOverlapToleranceX; 414 | 415 | to.LayerRangeFilter = this.LayerRangeFilter; 416 | } 417 | 418 | } 419 | 420 | 421 | 422 | 423 | // just for naming... 424 | public class GenericRepRapSettings : SingleMaterialFFFSettings 425 | { 426 | public override AssemblerFactoryF AssemblerType() { 427 | return RepRapAssembler.Factory; 428 | } 429 | 430 | 431 | public override T CloneAs() 432 | { 433 | GenericRepRapSettings copy = new GenericRepRapSettings(); 434 | this.CopyFieldsTo(copy); 435 | return copy as T; 436 | } 437 | 438 | 439 | } 440 | 441 | } -------------------------------------------------------------------------------- /settings/FlashforgeSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class Flashforge 9 | { 10 | public const string UUID = "5974064e-8751-4048-a700-73a023add74f"; 11 | 12 | public enum Models { 13 | Unknown, 14 | CreatorPro 15 | }; 16 | 17 | public const string UUID_Unknown = "f387a3d4-ba39-4a60-9e68-93ce7af4d92a"; 18 | public const string UUID_CreatorPro = "0dd884e1-9b19-436e-9558-e4cb5fb27f7d"; 19 | } 20 | 21 | 22 | public class FlashforgeSettings : SingleMaterialFFFSettings, ISailfishSettings 23 | { 24 | public Flashforge.Models ModelEnum; 25 | 26 | public override AssemblerFactoryF AssemblerType() { 27 | return MakerbotAssembler.Factory; 28 | } 29 | 30 | public FlashforgeSettings(Flashforge.Models model = Flashforge.Models.CreatorPro) { 31 | ModelEnum = model; 32 | 33 | if (model == Flashforge.Models.CreatorPro) 34 | configure_CreatorPro(); 35 | else 36 | configure_unknown(); 37 | 38 | } 39 | 40 | 41 | public override T CloneAs() { 42 | FlashforgeSettings copy = new FlashforgeSettings(this.ModelEnum); 43 | this.CopyFieldsTo(copy); 44 | return copy as T; 45 | } 46 | 47 | 48 | public static IEnumerable EnumerateDefaults() 49 | { 50 | yield return new FlashforgeSettings(Flashforge.Models.CreatorPro); 51 | yield return new FlashforgeSettings(Flashforge.Models.Unknown); 52 | } 53 | 54 | 55 | public string GPXModelFlag { 56 | get { 57 | if (ModelEnum == Flashforge.Models.CreatorPro) 58 | return "-m fcp"; 59 | else 60 | return ""; 61 | } 62 | } 63 | 64 | 65 | void configure_CreatorPro() 66 | { 67 | Machine.ManufacturerName = "Flashforge"; 68 | Machine.ManufacturerUUID = Flashforge.UUID; 69 | Machine.ModelIdentifier = "Creator Pro"; 70 | Machine.ModelUUID = Flashforge.UUID_CreatorPro; 71 | Machine.Class = MachineClass.PlasticFFFPrinter; 72 | Machine.BedSizeXMM = 227; 73 | Machine.BedSizeYMM = 148; 74 | Machine.MaxHeightMM = 150; 75 | Machine.NozzleDiamMM = 0.4; 76 | Machine.FilamentDiamMM = 1.75; 77 | 78 | Machine.MaxExtruderTempC = 230; 79 | Machine.HasHeatedBed = true; 80 | Machine.MaxBedTempC = 105; 81 | 82 | Machine.MaxExtrudeSpeedMMM = 60 * 60; 83 | Machine.MaxTravelSpeedMMM = 80 * 60; 84 | Machine.MaxZTravelSpeedMMM = 23 * 60; 85 | Machine.MaxRetractSpeedMMM = 20 * 60; 86 | Machine.MinLayerHeightMM = 0.1; 87 | Machine.MaxLayerHeightMM = 0.3; 88 | 89 | LayerHeightMM = 0.2; 90 | 91 | ExtruderTempC = 230; 92 | HeatedBedTempC = 25; 93 | 94 | SolidFillNozzleDiamStepX = 1.0; 95 | RetractDistanceMM = 1.3; 96 | 97 | RetractSpeed = Machine.MaxRetractSpeedMMM; 98 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 99 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 100 | CarefulExtrudeSpeed = 30 * 60; 101 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 102 | OuterPerimeterSpeedX = 0.5; 103 | } 104 | 105 | 106 | void configure_unknown() 107 | { 108 | Machine.ManufacturerName = "Flashforge"; 109 | Machine.ManufacturerUUID = Flashforge.UUID; 110 | Machine.ModelIdentifier = "(Unknown)"; 111 | Machine.ModelUUID = Flashforge.UUID_Unknown; 112 | Machine.Class = MachineClass.PlasticFFFPrinter; 113 | 114 | Machine.BedSizeXMM = 100; 115 | Machine.BedSizeYMM = 100; 116 | Machine.MaxHeightMM = 130; 117 | Machine.NozzleDiamMM = 0.4; 118 | Machine.FilamentDiamMM = 1.75; 119 | 120 | Machine.MaxExtruderTempC = 230; 121 | Machine.HasHeatedBed = false; 122 | Machine.MaxBedTempC = 0; 123 | 124 | Machine.MaxExtrudeSpeedMMM = 60 * 60; 125 | Machine.MaxTravelSpeedMMM = 80 * 60; 126 | Machine.MaxZTravelSpeedMMM = 23 * 60; 127 | Machine.MaxRetractSpeedMMM = 20 * 60; 128 | Machine.MinLayerHeightMM = 0.1; 129 | Machine.MaxLayerHeightMM = 0.3; 130 | 131 | LayerHeightMM = 0.2; 132 | 133 | ExtruderTempC = 230; 134 | HeatedBedTempC = 0; 135 | 136 | SolidFillNozzleDiamStepX = 1.0; 137 | RetractDistanceMM = 1.3; 138 | 139 | RetractSpeed = Machine.MaxRetractSpeedMMM; 140 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 141 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 142 | CarefulExtrudeSpeed = 30 * 60; 143 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 144 | OuterPerimeterSpeedX = 0.5; 145 | } 146 | 147 | } 148 | 149 | } -------------------------------------------------------------------------------- /settings/GenericPrinterSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public class GenericPrinterSettings : GenericRepRapSettings 9 | { 10 | public override AssemblerFactoryF AssemblerType() { 11 | return RepRapAssembler.Factory; 12 | } 13 | 14 | public string ManufacturerName; 15 | public string ManufacturerUUID; 16 | public string DefaultMachineUUID; 17 | 18 | public GenericPrinterSettings(string mfgName, string mfgUUID, string defaultMachineUUID) { 19 | ManufacturerName = mfgName; 20 | ManufacturerUUID = mfgUUID; 21 | DefaultMachineUUID = defaultMachineUUID; 22 | 23 | configure_unknown(); 24 | } 25 | 26 | 27 | public override T CloneAs() { 28 | GenericPrinterSettings copy = new GenericPrinterSettings(ManufacturerName, ManufacturerUUID, DefaultMachineUUID); 29 | this.CopyFieldsTo(copy); 30 | return copy as T; 31 | } 32 | 33 | 34 | void configure_unknown() 35 | { 36 | Machine.ManufacturerName = ManufacturerName; 37 | Machine.ManufacturerUUID = ManufacturerUUID; 38 | Machine.ModelIdentifier = "Unknown"; 39 | Machine.ModelUUID = DefaultMachineUUID; 40 | Machine.Class = MachineClass.PlasticFFFPrinter; 41 | Machine.BedSizeXMM = 80; 42 | Machine.BedSizeYMM = 80; 43 | Machine.MaxHeightMM = 55; 44 | Machine.NozzleDiamMM = 0.4; 45 | Machine.FilamentDiamMM = 1.75; 46 | 47 | Machine.MaxExtruderTempC = 230; 48 | Machine.HasHeatedBed = false; 49 | Machine.MaxBedTempC = 60; 50 | 51 | Machine.MaxExtrudeSpeedMMM = 50 * 60; 52 | Machine.MaxTravelSpeedMMM = 150 * 60; 53 | Machine.MaxZTravelSpeedMMM = 100 * 60; 54 | Machine.MaxRetractSpeedMMM = 40 * 60; 55 | Machine.MinLayerHeightMM = 0.1; 56 | Machine.MaxLayerHeightMM = 0.3; 57 | 58 | LayerHeightMM = 0.2; 59 | 60 | ExtruderTempC = 200; 61 | HeatedBedTempC = 0; 62 | 63 | SolidFillNozzleDiamStepX = 1.0; 64 | RetractDistanceMM = 4.5; 65 | 66 | RetractSpeed = Machine.MaxRetractSpeedMMM; 67 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 68 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 69 | CarefulExtrudeSpeed = 20 * 60; 70 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 71 | OuterPerimeterSpeedX = 0.5; 72 | } 73 | 74 | 75 | } 76 | 77 | } -------------------------------------------------------------------------------- /settings/MakerbotSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class Makerbot 9 | { 10 | public const string UUID = "77b7ed08-dcc8-4c2e-a189-18aa549bf94b"; 11 | 12 | public enum Models { 13 | Unknown, 14 | Replicator2 15 | }; 16 | 17 | public const string UUID_Unknown = "625aa5dc-8e9d-4240-86ff-8bc369cd5124"; 18 | public const string UUID_Replicator2 = "a1c13f61-1ae6-4b1a-9c8c-18b2170e82b1"; 19 | } 20 | 21 | 22 | 23 | 24 | public interface ISailfishSettings 25 | { 26 | string GPXModelFlag { get; } 27 | } 28 | 29 | 30 | 31 | public class MakerbotSettings : SingleMaterialFFFSettings, ISailfishSettings 32 | { 33 | public Makerbot.Models ModelEnum; 34 | 35 | public override AssemblerFactoryF AssemblerType() { 36 | return MakerbotAssembler.Factory; 37 | } 38 | 39 | public MakerbotSettings(Makerbot.Models model = Makerbot.Models.Replicator2) { 40 | ModelEnum = model; 41 | 42 | if (model == Makerbot.Models.Replicator2) 43 | configure_Replicator_2(); 44 | else 45 | configure_unknown(); 46 | 47 | } 48 | 49 | 50 | public override T CloneAs() { 51 | MakerbotSettings copy = new MakerbotSettings(this.ModelEnum); 52 | this.CopyFieldsTo(copy); 53 | return copy as T; 54 | } 55 | 56 | 57 | public static IEnumerable EnumerateDefaults() 58 | { 59 | yield return new MakerbotSettings(Makerbot.Models.Replicator2); 60 | yield return new MakerbotSettings(Makerbot.Models.Unknown); 61 | } 62 | 63 | 64 | 65 | public string GPXModelFlag { 66 | get { 67 | if (ModelEnum == Makerbot.Models.Replicator2) 68 | return "-m r2"; 69 | else 70 | return ""; 71 | } 72 | } 73 | 74 | 75 | 76 | void configure_Replicator_2() 77 | { 78 | Machine.ManufacturerName = "Makerbot"; 79 | Machine.ManufacturerUUID = Makerbot.UUID; 80 | Machine.ModelIdentifier = "Replicator 2"; 81 | Machine.ModelUUID = Makerbot.UUID_Replicator2; 82 | Machine.Class = MachineClass.PlasticFFFPrinter; 83 | Machine.BedSizeXMM = 285; 84 | Machine.BedSizeYMM = 153; 85 | Machine.MaxHeightMM = 155; 86 | Machine.NozzleDiamMM = 0.4; 87 | Machine.FilamentDiamMM = 1.75; 88 | 89 | Machine.MaxExtruderTempC = 230; 90 | Machine.HasHeatedBed = false; 91 | Machine.MaxBedTempC = 0; 92 | 93 | Machine.MaxExtrudeSpeedMMM = 90 * 60; 94 | Machine.MaxTravelSpeedMMM = 150 * 60; 95 | Machine.MaxZTravelSpeedMMM = 23 * 60; 96 | Machine.MaxRetractSpeedMMM = 25 * 60; 97 | Machine.MinLayerHeightMM = 0.1; 98 | Machine.MaxLayerHeightMM = 0.3; 99 | 100 | 101 | LayerHeightMM = 0.2; 102 | 103 | ExtruderTempC = 230; 104 | HeatedBedTempC = 0; 105 | 106 | SolidFillNozzleDiamStepX = 1.0; 107 | RetractDistanceMM = 1.3; 108 | 109 | RetractSpeed = Machine.MaxRetractSpeedMMM; 110 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 111 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 112 | CarefulExtrudeSpeed = 30 * 60; 113 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 114 | OuterPerimeterSpeedX = 0.5; 115 | } 116 | 117 | 118 | void configure_unknown() 119 | { 120 | Machine.ManufacturerName = "Makerbot"; 121 | Machine.ManufacturerUUID = Makerbot.UUID; 122 | Machine.ModelIdentifier = "(Unknown)"; 123 | Machine.ModelUUID = Makerbot.UUID_Unknown; 124 | Machine.Class = MachineClass.PlasticFFFPrinter; 125 | 126 | Machine.BedSizeXMM = 100; 127 | Machine.BedSizeYMM = 100; 128 | Machine.MaxHeightMM = 130; 129 | Machine.NozzleDiamMM = 0.4; 130 | Machine.FilamentDiamMM = 1.75; 131 | 132 | Machine.MaxExtruderTempC = 230; 133 | Machine.HasHeatedBed = false; 134 | Machine.MaxBedTempC = 0; 135 | Machine.MaxExtrudeSpeedMMM = 90 * 60; 136 | Machine.MaxTravelSpeedMMM = 150 * 60; 137 | Machine.MaxZTravelSpeedMMM = 23 * 60; 138 | Machine.MaxRetractSpeedMMM = 25 * 60; 139 | Machine.MinLayerHeightMM = 0.1; 140 | Machine.MaxLayerHeightMM = 0.3; 141 | 142 | 143 | LayerHeightMM = 0.2; 144 | 145 | ExtruderTempC = 230; 146 | HeatedBedTempC = 0; 147 | 148 | SolidFillNozzleDiamStepX = 1.0; 149 | RetractDistanceMM = 1.3; 150 | 151 | RetractSpeed = Machine.MaxRetractSpeedMMM; 152 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 153 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 154 | CarefulExtrudeSpeed = 30 * 60; 155 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 156 | OuterPerimeterSpeedX = 0.5; 157 | } 158 | 159 | } 160 | 161 | } -------------------------------------------------------------------------------- /settings/MonopriceSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class Monoprice 9 | { 10 | public const string UUID = "860432eb-dec6-4b20-8f97-3643a50daf1d"; 11 | 12 | public enum Models { 13 | Unknown = 0, 14 | MP_Select_Mini_V2 = 1 15 | }; 16 | 17 | public const string UUID_Unknown = "409e843b-c1d0-45fc-82d1-d7cc5635b8ee"; 18 | public const string UUID_MP_Select_Mini_V2 = "4a498843-9080-4c97-aa82-b587f415ab1f"; 19 | } 20 | 21 | 22 | public class MonopriceSettings : GenericRepRapSettings 23 | { 24 | public Monoprice.Models ModelEnum; 25 | 26 | public override AssemblerFactoryF AssemblerType() { 27 | return RepRapAssembler.Factory; 28 | } 29 | 30 | 31 | public MonopriceSettings(Monoprice.Models model) { 32 | ModelEnum = model; 33 | 34 | if (model == Monoprice.Models.MP_Select_Mini_V2) 35 | configure_MP_Select_Mini_V2(); 36 | else 37 | configure_unknown(); 38 | } 39 | 40 | public override T CloneAs() { 41 | MonopriceSettings copy = new MonopriceSettings(this.ModelEnum); 42 | this.CopyFieldsTo(copy); 43 | return copy as T; 44 | } 45 | 46 | public static IEnumerable EnumerateDefaults() 47 | { 48 | yield return new MonopriceSettings(Monoprice.Models.MP_Select_Mini_V2); 49 | yield return new MonopriceSettings(Monoprice.Models.Unknown); 50 | } 51 | 52 | 53 | 54 | void configure_MP_Select_Mini_V2() 55 | { 56 | Machine.ManufacturerName = "Monoprice"; 57 | Machine.ManufacturerUUID = Monoprice.UUID; 58 | Machine.ModelIdentifier = "MP Select Mini V2"; 59 | Machine.ModelUUID = Monoprice.UUID_MP_Select_Mini_V2; 60 | Machine.Class = MachineClass.PlasticFFFPrinter; 61 | Machine.BedSizeXMM = 120; 62 | Machine.BedSizeYMM = 120; 63 | Machine.MaxHeightMM = 120; 64 | Machine.NozzleDiamMM = 0.4; 65 | Machine.FilamentDiamMM = 1.75; 66 | 67 | Machine.MaxExtruderTempC = 250; 68 | Machine.HasHeatedBed = true; 69 | Machine.MaxBedTempC = 60; 70 | 71 | Machine.MaxExtrudeSpeedMMM = 55 * 60; 72 | Machine.MaxTravelSpeedMMM = 150 * 60; 73 | Machine.MaxZTravelSpeedMMM = 100 * 60; 74 | Machine.MaxRetractSpeedMMM = 100 * 60; 75 | Machine.MinLayerHeightMM = 0.1; 76 | Machine.MaxLayerHeightMM = 0.3; 77 | 78 | 79 | LayerHeightMM = 0.2; 80 | 81 | ExtruderTempC = 200; 82 | HeatedBedTempC = 0; 83 | 84 | SolidFillNozzleDiamStepX = 1.0; 85 | RetractDistanceMM = 4.5; 86 | 87 | RetractSpeed = Machine.MaxRetractSpeedMMM; 88 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 89 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 90 | CarefulExtrudeSpeed = 20 * 60; 91 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 92 | OuterPerimeterSpeedX = 0.5; 93 | } 94 | 95 | 96 | 97 | 98 | void configure_unknown() 99 | { 100 | Machine.ManufacturerName = "Monoprice"; 101 | Machine.ManufacturerUUID = Monoprice.UUID; 102 | Machine.ModelIdentifier = "(Unknown)"; 103 | Machine.ModelUUID = Monoprice.UUID_Unknown; 104 | Machine.Class = MachineClass.PlasticFFFPrinter; 105 | Machine.BedSizeXMM = 100; 106 | Machine.BedSizeYMM = 100; 107 | Machine.MaxHeightMM = 100; 108 | Machine.NozzleDiamMM = 0.4; 109 | Machine.FilamentDiamMM = 1.75; 110 | 111 | Machine.MaxExtruderTempC = 230; 112 | Machine.HasHeatedBed = false; 113 | Machine.MaxBedTempC = 0; 114 | 115 | Machine.HasAutoBedLeveling = false; 116 | Machine.EnableAutoBedLeveling = false; 117 | 118 | Machine.MaxExtrudeSpeedMMM = 60 * 60; 119 | Machine.MaxTravelSpeedMMM = 80 * 60; 120 | Machine.MaxZTravelSpeedMMM = 23 * 60; 121 | Machine.MaxRetractSpeedMMM = 20 * 60; 122 | Machine.MinLayerHeightMM = 0.1; 123 | Machine.MaxLayerHeightMM = 0.3; 124 | 125 | LayerHeightMM = 0.2; 126 | 127 | ExtruderTempC = 200; 128 | HeatedBedTempC = 0; 129 | 130 | SolidFillNozzleDiamStepX = 1.0; 131 | RetractDistanceMM = 1.0; 132 | 133 | RetractSpeed = Machine.MaxRetractSpeedMMM; 134 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 135 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 136 | CarefulExtrudeSpeed = 20 * 60; 137 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 138 | OuterPerimeterSpeedX = 0.5; 139 | } 140 | 141 | 142 | } 143 | 144 | } -------------------------------------------------------------------------------- /settings/PrintrbotSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class Printrbot 9 | { 10 | public const string UUID = "10dd0db9-df41-4b3e-8b73-d345c408b5ff"; 11 | 12 | public enum Models { 13 | Unknown = 0, 14 | Plus = 1 15 | }; 16 | 17 | public const string UUID_Unknown = "9a4cc498-376a-4780-956c-d0e145751868"; 18 | public const string UUID_Plus = "1c868178-5aa2-47c3-9a8c-6f86ef1d1ff6"; 19 | } 20 | 21 | 22 | public class PrintrbotSettings : GenericRepRapSettings 23 | { 24 | public Printrbot.Models ModelEnum; 25 | 26 | public override AssemblerFactoryF AssemblerType() { 27 | return MakePrintrbotAssembler; 28 | } 29 | 30 | 31 | public PrintrbotSettings(Printrbot.Models model) { 32 | ModelEnum = model; 33 | 34 | if (model == Printrbot.Models.Plus) 35 | configure_Plus(); 36 | else 37 | configure_unknown(); 38 | } 39 | 40 | public override T CloneAs() { 41 | PrintrbotSettings copy = new PrintrbotSettings(this.ModelEnum); 42 | this.CopyFieldsTo(copy); 43 | return copy as T; 44 | } 45 | 46 | 47 | public static IEnumerable EnumerateDefaults() 48 | { 49 | yield return new PrintrbotSettings(Printrbot.Models.Plus); 50 | yield return new PrintrbotSettings(Printrbot.Models.Unknown); 51 | } 52 | 53 | 54 | 55 | void configure_Plus() 56 | { 57 | Machine.ManufacturerName = "Printrbot"; 58 | Machine.ManufacturerUUID = Printrbot.UUID; 59 | Machine.ModelIdentifier = "Plus"; 60 | Machine.ModelUUID = Printrbot.UUID_Plus; 61 | Machine.Class = MachineClass.PlasticFFFPrinter; 62 | Machine.BedSizeXMM = 250; 63 | Machine.BedSizeYMM = 250; 64 | Machine.MaxHeightMM = 250; 65 | Machine.NozzleDiamMM = 0.4; 66 | Machine.FilamentDiamMM = 1.75; 67 | 68 | Machine.MaxExtruderTempC = 250; 69 | Machine.HasHeatedBed = true; 70 | Machine.MaxBedTempC = 80; 71 | 72 | Machine.MaxExtrudeSpeedMMM = 80 * 60; 73 | Machine.MaxTravelSpeedMMM = 120 * 60; 74 | Machine.MaxZTravelSpeedMMM = 100 * 60; 75 | Machine.MaxRetractSpeedMMM = 45 * 60; 76 | Machine.MinLayerHeightMM = 0.05; 77 | Machine.MaxLayerHeightMM = 0.3; 78 | 79 | 80 | LayerHeightMM = 0.2; 81 | 82 | ExtruderTempC = 200; 83 | HeatedBedTempC = 0; 84 | 85 | SolidFillNozzleDiamStepX = 1.0; 86 | RetractDistanceMM = 0.7; 87 | 88 | RetractSpeed = Machine.MaxRetractSpeedMMM; 89 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 90 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 91 | CarefulExtrudeSpeed = 20 * 60; 92 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 93 | OuterPerimeterSpeedX = 0.5; 94 | 95 | // specific to printrbot 96 | Machine.HasAutoBedLeveling = true; 97 | Machine.EnableAutoBedLeveling = true; 98 | } 99 | 100 | 101 | 102 | 103 | void configure_unknown() 104 | { 105 | Machine.ManufacturerName = "Printrbot"; 106 | Machine.ManufacturerUUID = Printrbot.UUID; 107 | Machine.ModelIdentifier = "(Unknown)"; 108 | Machine.ModelUUID = Printrbot.UUID_Unknown; 109 | Machine.Class = MachineClass.PlasticFFFPrinter; 110 | Machine.BedSizeXMM = 100; 111 | Machine.BedSizeYMM = 100; 112 | Machine.MaxHeightMM = 100; 113 | Machine.NozzleDiamMM = 0.4; 114 | Machine.FilamentDiamMM = 1.75; 115 | 116 | Machine.MaxExtruderTempC = 230; 117 | Machine.HasHeatedBed = false; 118 | Machine.MaxBedTempC = 0; 119 | 120 | Machine.HasAutoBedLeveling = false; 121 | Machine.EnableAutoBedLeveling = false; 122 | 123 | Machine.MaxExtrudeSpeedMMM = 60 * 60; 124 | Machine.MaxTravelSpeedMMM = 80 * 60; 125 | Machine.MaxZTravelSpeedMMM = 23 * 60; 126 | Machine.MaxRetractSpeedMMM = 20 * 60; 127 | Machine.MinLayerHeightMM = 0.1; 128 | Machine.MaxLayerHeightMM = 0.3; 129 | 130 | LayerHeightMM = 0.2; 131 | 132 | ExtruderTempC = 200; 133 | HeatedBedTempC = 0; 134 | 135 | SolidFillNozzleDiamStepX = 1.0; 136 | RetractDistanceMM = 1.0; 137 | 138 | RetractSpeed = Machine.MaxRetractSpeedMMM; 139 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 140 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 141 | CarefulExtrudeSpeed = 20 * 60; 142 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 143 | OuterPerimeterSpeedX = 0.5; 144 | } 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | public BaseDepositionAssembler MakePrintrbotAssembler( 153 | GCodeBuilder builder, SingleMaterialFFFSettings settings) 154 | { 155 | var asm = new RepRapAssembler(builder, settings); 156 | asm.HeaderCustomizerF = HeaderCustomF; 157 | return asm; 158 | } 159 | 160 | protected void HeaderCustomF(RepRapAssembler.HeaderState state, GCodeBuilder Builder) 161 | { 162 | if (state == RepRapAssembler.HeaderState.BeforePrime) { 163 | if ( Machine.HasAutoBedLeveling && Machine.EnableAutoBedLeveling ) 164 | Builder.BeginGLine(29, "auto-level bed"); 165 | } 166 | } 167 | 168 | } 169 | 170 | } -------------------------------------------------------------------------------- /settings/PrusaSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class Prusa 9 | { 10 | public const string UUID = "4530287d-cd23-416c-b74b-4876c385750a"; 11 | 12 | public enum Models { 13 | Unknown = 0, 14 | i3_MK3 = 1 15 | }; 16 | 17 | public const string UUID_Unknown = "b7498970-b847-4a24-8e5c-2e7c0c4d417f"; 18 | public const string UUID_I3_MK3 = "fc09f99c-aee0-45e9-bca3-3e088ccb0b55"; 19 | } 20 | 21 | 22 | public class PrusaSettings : GenericRepRapSettings 23 | { 24 | public Prusa.Models ModelEnum; 25 | 26 | public override AssemblerFactoryF AssemblerType() { 27 | return MakePrusaAssembler; 28 | } 29 | 30 | 31 | public PrusaSettings(Prusa.Models model) { 32 | ModelEnum = model; 33 | 34 | if (model == Prusa.Models.i3_MK3) 35 | configure_i3_MK3(); 36 | else 37 | configure_unknown(); 38 | } 39 | 40 | public override T CloneAs() { 41 | PrusaSettings copy = new PrusaSettings(this.ModelEnum); 42 | this.CopyFieldsTo(copy); 43 | return copy as T; 44 | } 45 | 46 | 47 | public static IEnumerable EnumerateDefaults() 48 | { 49 | yield return new PrusaSettings(Prusa.Models.i3_MK3); 50 | yield return new PrusaSettings(Prusa.Models.Unknown); 51 | } 52 | 53 | 54 | void configure_i3_MK3() 55 | { 56 | Machine.ManufacturerName = "Prusa"; 57 | Machine.ManufacturerUUID = Prusa.UUID; 58 | Machine.ModelIdentifier = "i3 MK3"; 59 | Machine.ModelUUID = Prusa.UUID_I3_MK3; 60 | Machine.Class = MachineClass.PlasticFFFPrinter; 61 | Machine.BedSizeXMM = 250; 62 | Machine.BedSizeYMM = 210; 63 | Machine.MaxHeightMM = 200; 64 | Machine.NozzleDiamMM = 0.4; 65 | Machine.FilamentDiamMM = 1.75; 66 | 67 | Machine.MaxExtruderTempC = 300; 68 | Machine.HasHeatedBed = true; 69 | Machine.MaxBedTempC = 120; 70 | 71 | Machine.HasAutoBedLeveling = true; 72 | Machine.EnableAutoBedLeveling = true; 73 | 74 | Machine.MaxExtrudeSpeedMMM = 80 * 60; 75 | Machine.MaxTravelSpeedMMM = 120 * 60; 76 | Machine.MaxZTravelSpeedMMM = 250 * 60; 77 | Machine.MaxRetractSpeedMMM = 35 * 60; 78 | Machine.MinLayerHeightMM = 0.05; 79 | Machine.MaxLayerHeightMM = 0.35; 80 | 81 | LayerHeightMM = 0.2; 82 | 83 | ExtruderTempC = 200; 84 | HeatedBedTempC = 60; 85 | 86 | SolidFillNozzleDiamStepX = 1.0; 87 | RetractDistanceMM = 0.7; 88 | 89 | RetractSpeed = Machine.MaxRetractSpeedMMM; 90 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 91 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 92 | CarefulExtrudeSpeed = 20 * 60; 93 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 94 | OuterPerimeterSpeedX = 0.5; 95 | } 96 | 97 | 98 | 99 | 100 | void configure_unknown() 101 | { 102 | Machine.ManufacturerName = "Prusa"; 103 | Machine.ManufacturerUUID = Prusa.UUID; 104 | Machine.ModelIdentifier = "(Unknown)"; 105 | Machine.ModelUUID = Prusa.UUID_Unknown; 106 | Machine.Class = MachineClass.PlasticFFFPrinter; 107 | Machine.BedSizeXMM = 100; 108 | Machine.BedSizeYMM = 100; 109 | Machine.MaxHeightMM = 100; 110 | Machine.NozzleDiamMM = 0.4; 111 | Machine.FilamentDiamMM = 1.75; 112 | 113 | Machine.MaxExtruderTempC = 230; 114 | Machine.HasHeatedBed = false; 115 | Machine.MaxBedTempC = 0; 116 | 117 | Machine.HasAutoBedLeveling = false; 118 | Machine.EnableAutoBedLeveling = false; 119 | 120 | Machine.MaxExtrudeSpeedMMM = 60 * 60; 121 | Machine.MaxTravelSpeedMMM = 80 * 60; 122 | Machine.MaxZTravelSpeedMMM = 23 * 60; 123 | Machine.MaxRetractSpeedMMM = 20 * 60; 124 | Machine.MinLayerHeightMM = 0.1; 125 | Machine.MaxLayerHeightMM = 0.3; 126 | 127 | LayerHeightMM = 0.2; 128 | 129 | ExtruderTempC = 200; 130 | HeatedBedTempC = 0; 131 | 132 | SolidFillNozzleDiamStepX = 1.0; 133 | RetractDistanceMM = 1.0; 134 | 135 | RetractSpeed = Machine.MaxRetractSpeedMMM; 136 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 137 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 138 | CarefulExtrudeSpeed = 20 * 60; 139 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 140 | OuterPerimeterSpeedX = 0.5; 141 | } 142 | 143 | 144 | 145 | 146 | 147 | public BaseDepositionAssembler MakePrusaAssembler( 148 | GCodeBuilder builder, SingleMaterialFFFSettings settings) 149 | { 150 | var asm = new RepRapAssembler(builder, settings); 151 | asm.HomeSequenceF = this.HomeSequence; 152 | asm.HeaderCustomizerF = HeaderCustomF; 153 | asm.TravelGCode = 1; 154 | return asm; 155 | } 156 | 157 | 158 | protected virtual void HomeSequence(GCodeBuilder builder) 159 | { 160 | if (Machine.HasAutoBedLeveling && Machine.EnableAutoBedLeveling) { 161 | builder.BeginGLine(28).AppendL("W").AppendComment("home all without bed level"); 162 | builder.BeginGLine(80, "auto-level bed"); 163 | } else { 164 | // standard home sequenece 165 | builder.BeginGLine(28, "home x/y").AppendI("X", 0).AppendI("Y", 0); 166 | builder.BeginGLine(28, "home z").AppendI("Z", 0); 167 | } 168 | 169 | } 170 | 171 | 172 | protected virtual void HeaderCustomF(RepRapAssembler.HeaderState state, GCodeBuilder Builder) 173 | { 174 | if (state == RepRapAssembler.HeaderState.AfterComments ) { 175 | 176 | if ( ModelEnum == Prusa.Models.i3_MK3 ) { 177 | Builder.BeginMLine(201) 178 | .AppendI("X",1000).AppendI("Y",1000).AppendI("Z",200).AppendI("E",5000) 179 | .AppendComment("Set maximum accelleration in mm/sec^2"); 180 | Builder.BeginMLine(203) 181 | .AppendI("X", 200).AppendI("Y", 200).AppendI("Z", 12).AppendI("E", 120) 182 | .AppendComment("Set maximum feedrates in mm/sec"); 183 | Builder.BeginMLine(204) 184 | .AppendI("S", 1250).AppendI("T", 1250) 185 | .AppendComment("Set acceleration for moves (S) and retract (T)"); 186 | Builder.BeginMLine(205) 187 | .AppendF("X", 10).AppendF("Y", 10).AppendF("Z", 0.4).AppendF("E", 2.5) 188 | .AppendComment("Set jerk limits in mm/sec"); 189 | Builder.BeginMLine(205) 190 | .AppendI("S", 0).AppendI("T", 0) 191 | .AppendComment("Set minimum extrude and travel feed rate in mm/sec"); 192 | } 193 | 194 | 195 | } 196 | } 197 | 198 | } 199 | 200 | } -------------------------------------------------------------------------------- /settings/RepRapSettings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | using g3; 5 | 6 | namespace gs.info 7 | { 8 | public static class RepRap 9 | { 10 | public const string UUID = "e95dcaaa-4315-412f-bd80-5049fb74f384"; 11 | 12 | public enum Models { 13 | Unknown = 0 14 | }; 15 | 16 | public const string UUID_Unknown = "bb097486-bb07-4a95-950f-1a1de992e782"; 17 | } 18 | 19 | 20 | public class RepRapSettings : GenericRepRapSettings 21 | { 22 | public RepRap.Models ModelEnum; 23 | 24 | public override AssemblerFactoryF AssemblerType() { 25 | return RepRapAssembler.Factory; 26 | } 27 | 28 | 29 | public RepRapSettings(RepRap.Models model) { 30 | ModelEnum = model; 31 | 32 | if (model == RepRap.Models.Unknown) 33 | configure_unknown(); 34 | } 35 | 36 | public override T CloneAs() { 37 | RepRapSettings copy = new RepRapSettings(this.ModelEnum); 38 | this.CopyFieldsTo(copy); 39 | return copy as T; 40 | } 41 | 42 | public static IEnumerable EnumerateDefaults() 43 | { 44 | yield return new RepRapSettings(RepRap.Models.Unknown); 45 | } 46 | 47 | 48 | void configure_unknown() 49 | { 50 | Machine.ManufacturerName = "RepRap"; 51 | Machine.ManufacturerUUID = RepRap.UUID; 52 | Machine.ModelIdentifier = "Unknown"; 53 | Machine.ModelUUID = RepRap.UUID_Unknown; 54 | Machine.Class = MachineClass.PlasticFFFPrinter; 55 | Machine.BedSizeXMM = 80; 56 | Machine.BedSizeYMM = 80; 57 | Machine.BedOriginFactorX = 0.5; 58 | Machine.BedOriginFactorY = 0.5; 59 | 60 | Machine.MaxHeightMM = 55; 61 | Machine.NozzleDiamMM = 0.4; 62 | Machine.FilamentDiamMM = 1.75; 63 | 64 | Machine.MaxExtruderTempC = 230; 65 | Machine.HasHeatedBed = false; 66 | Machine.MaxBedTempC = 60; 67 | 68 | Machine.MaxExtrudeSpeedMMM = 50 * 60; 69 | Machine.MaxTravelSpeedMMM = 150 * 60; 70 | Machine.MaxZTravelSpeedMMM = 100 * 60; 71 | Machine.MaxRetractSpeedMMM = 40 * 60; 72 | Machine.MinLayerHeightMM = 0.1; 73 | Machine.MaxLayerHeightMM = 0.3; 74 | 75 | LayerHeightMM = 0.2; 76 | 77 | ExtruderTempC = 200; 78 | HeatedBedTempC = 0; 79 | 80 | SolidFillNozzleDiamStepX = 1.0; 81 | RetractDistanceMM = 4.5; 82 | 83 | RetractSpeed = Machine.MaxRetractSpeedMMM; 84 | ZTravelSpeed = Machine.MaxZTravelSpeedMMM; 85 | RapidTravelSpeed = Machine.MaxTravelSpeedMMM; 86 | CarefulExtrudeSpeed = 20 * 60; 87 | RapidExtrudeSpeed = Machine.MaxExtrudeSpeedMMM; 88 | OuterPerimeterSpeedX = 0.5; 89 | } 90 | 91 | 92 | } 93 | 94 | } -------------------------------------------------------------------------------- /settings/manufacturers.txt: -------------------------------------------------------------------------------- 1 | 3D Systems,94b7a2ac-ccac-4a71-b21d-cb88e2a07378,7f898fc4-1e2a-4bb0-b1c9-b5d8e140a31d 2 | Airwolf 3D,79b0ce85-e8c0-437b-b6a8-6fca0d799f27,276dc7d0-f03e-4b11-b20b-0f0ed13d9d30 3 | Afinia,d25ef920-9e97-4204-8ee8-c6af5ca91a34,50e1edfa-d021-4db2-a032-132d54be5d69 4 | AON 3D,81935c8d-352d-4cc6-9491-e235912a6f58,bcd3120c-818f-4d58-9c08-91c4c70a0bea 5 | Arcam,d4464797-8ac0-4de8-8929-aea175caf74d,9f6b12a3-986c-424f-9765-7d870d3acfd1 6 | Autodesk,5bb78a3d-1f53-43a2-8cac-fbce92a410c1,01c3ccad-18d2-49ce-aa96-7dabb6a871c5 7 | B9 Creations,3c695645-2bc9-4683-8d2b-f3d50383b6fd,be4d0871-406c-41a9-bec1-2d4723abdc59 8 | BCN3D,a5dcc576-2bb5-4855-bbe9-46a9285966ed,d0a133ea-355a-49df-a0e2-d43750cc3fae 9 | BEEVERYCREATIVE,c6801cdc-9ad9-4a93-9244-ea36c2d1aee0,73b4fda0-d83d-42a7-a394-b2b7cfcdcaae 10 | BigRep,737eef0a-2648-434b-b3e2-fc9ef3b2af79,65f1b193-7260-4b97-8896-e5f100bc51fa 11 | BQ,37d83f7f-ffc4-41d4-ba51-babe7b58ab28,b3d1fb5f-b73b-456e-a070-8394d7a0aff1 12 | Carbon,60d0408c-01d9-4d58-8aee-39992c7c9ff8,9ff8fcc7-f395-49d7-8834-47efb37f81c0 13 | CEL,70bf21b6-9cca-455d-ab5c-689e89d917f4,4660bb09-197b-4fa5-b6cf-f6a0ebb0bdb6 14 | Cetus3D,ba6588df-3efe-4718-a820-f37f07c4273c,023eaad7-94ac-4393-8212-708ca8ff4fc6 15 | ConceptLaser,b327511b-5e1f-4e3f-af04-da4604a8d898,e4b2bba5-1147-451a-a124-d67927ce80f7 16 | CraftUnique,b5277ab8-0804-4a42-ad46-625b4e939879,59105b59-1751-4242-97e2-dfa9882d9d70 17 | Creality,d31a921f-0c3e-40fb-8d6d-19bce9767a47,e99dad60-60db-409b-9cec-ef4a40bc3f12 18 | Dremel,98084da7-82e1-4d38-9954-d9016e49e767,0d37a5e8-0d27-475c-8d02-80fbfefaf905 19 | EnvisionTEC,dc35e446-67c5-4171-a9d4-85bca099b6af,73e5a4a3-91a1-43a8-a7f5-095fc1518a2c 20 | EOS,9e66dc8e-b524-46fc-9725-a745cd16c6ea,4dc95818-1f68-4975-99a0-770e42891508 21 | ExOne,f8826e0e-28b1-4220-8185-442afda7fab1,9dac5954-16bd-4256-bf59-7e3e3186bcc6 22 | FlashForge,5974064e-8751-4048-a700-73a023add74f,f387a3d4-ba39-4a60-9e68-93ce7af4d92a 23 | Formlabs,aad64234-0bdd-43b9-97a2-89b5d801754c,7634cb5d-6c0b-4eef-bdd4-1ed0886181c2 24 | HICTOP,52983236-3d5c-4875-bf7d-825608e6f7dd,5418c66a-9b67-461f-88b4-afec771c300e 25 | HP,f08420a3-98fd-4d8c-b6b1-410395837087,f456f367-25e2-485a-9b68-201db722fa04 26 | Hyvision,b0765b0c-d40a-4b74-bef7-d702db3b3269,67cf37bd-d10d-4933-9d78-0e10e6eda4cb 27 | Leapfrog,66a66dcb-b4ca-48c6-99d4-8e6119c60af9,ee82152f-bc97-4b1d-9cc2-4bfaeb89da87 28 | Lulzbot,2b2419af-5ae8-4b08-9434-cb619c0e7b13,839770e8-654b-427f-ad0c-296b4c79acb2 29 | M3D,8ba4493a-90bd-4ae5-b777-22f26b0f2ef8,1796376e-54e1-4bfc-88a5-156cae9bb6cf 30 | Markforged,70377286-8692-415d-9449-04af1712b939,5d94c2d3-2b38-4503-8ffb-c9e11b0d4f91 31 | Makerbot,77b7ed08-dcc8-4c2e-a189-18aa549bf94b,625aa5dc-8e9d-4240-86ff-8bc369cd5124 32 | Makergear,d7763933-bf59-4c7d-ad80-0f7ecd3bd925,54f9de24-2c3d-48c6-8d35-3a55e016f8c6 33 | Mcor,1918a2f0-543d-49c8-af29-b3e3983a35f4,3c693662-fe56-4531-b7f8-f3bc9b0fcecf 34 | Monoprice,860432eb-dec6-4b20-8f97-3643a50daf1d,409e843b-c1d0-45fc-82d1-d7cc5635b8ee 35 | New Matter,fa938c28-612b-4efb-99e6-bc64bdf2ed7e,44bcfd43-f041-46e9-a40b-8c96618abbe0 36 | Printrbot,10dd0db9-df41-4b3e-8b73-d345c408b5ff,9a4cc498-376a-4780-956c-d0e145751868 37 | Prusa Research,4530287d-cd23-416c-b74b-4876c385750a,fc09f99c-aee0-45e9-bca3-3e088ccb0b55 38 | Sharebot,af512da8-3dab-4e14-88b1-fdce4508fc99,0dc584bb-de1a-479b-97bf-70d32ab66a5e 39 | SeeMeCNC,7964ea72-74b0-46b0-951e-6f7ba9aff565,5284e874-6cfc-470a-9530-7fc927b894eb 40 | Solidoodle,291a28dd-92a2-46c0-92eb-c1d786830000,1b38daf5-edd9-4839-ade0-d80c4de47059 41 | Raise3D,7c28bf29-6876-4eea-b703-2d63f08198e9,1f1199d1-4667-4981-99b8-23e3d246fd8a 42 | Renishaw,95b96935-14ed-44dd-a3c5-b9a4acb18725,a3317353-e781-4c4f-afe2-a4242fe2e7cb 43 | RepRap,e95dcaaa-4315-412f-bd80-5049fb74f384,bb097486-bb07-4a95-950f-1a1de992e782 44 | Robo3D,178bff03-c02d-4c6a-b255-9c914937d18e,10636e51-c1ad-430a-9ca1-1fdeba23f536 45 | Stratasys,34a02b0d-b5c0-4282-bba5-0c455ece5bf4,749235cd-3c10-450d-bf33-bfb8b1c16beb 46 | Tevo,b05970de-a552-4d24-b938-a48638d0d967,9e0bee29-54cb-419a-bb5f-5375d470ffb8 47 | Tinkerines,1e3fdd02-d907-4990-b4eb-b1e72ea20bfa,d5a44850-ac45-4180-b491-edb0358244ba 48 | Type A,66a0f1f1-e5da-4af4-88e0-c2945f7499bc,477a9bca-fe98-4c2a-94bb-3b1ebba83171 49 | Ultimaker,4d34d642-f1a1-4009-8ee0-60f7d1bdeb28,017f7ea4-ce20-4686-b1b5-410870db41a2 50 | UP3D,0dd0b76c-2014-40ac-843f-e8a70dc91b77,09d7ab84-89cd-4f0a-af5b-be434ab43a3c 51 | Velleman,d47e667a-e496-4626-8c98-a96725071b8e,ef2dc71a-a72f-4049-bf14-4b8172fd738c 52 | Voxeljet,239aa7e7-6a3a-4e5d-8688-acafe5bea792,0b3ca452-4988-4bdf-b9d2-19565c62d46e 53 | WASP,590ea63b-52b4-4f81-a5dd-c1332918ac07,595799cc-e543-4e80-a1fe-a895c6bb304c 54 | Wanhao,17c056dd-0df5-47ff-b7a1-abf90df1fbe2,6de7f6ce-2392-4d16-9a47-bc06cf502607 55 | XYZprinting,4176871a-d65c-48dc-a813-02e464209277,7ecd4430-1ef2-4262-b472-4a7b33a352a9 56 | Zortrax,f66c38a2-869c-4a91-969f-831544181477,cb678fe8-ebc3-4924-ba24-df4321a0bf44 57 | ZMorph,e2d0a401-61b7-4c6d-9a8e-f956e52eaa59,3bb41c49-7ebe-4eab-8ac7-bb5bcd686903 -------------------------------------------------------------------------------- /writers/BaseGCodeWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Threading; 4 | using System.Globalization; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | public abstract class BaseGCodeWriter 10 | { 11 | /// 12 | /// If the mesh format we are writing is text, then the OS will write in the number style 13 | /// of the current language. So in Germany, numbers are written 1,00 instead of 1.00, for example. 14 | /// If this flag is true, we override this to always write in a consistent way. 15 | /// 16 | public bool WriteInvariantCulture = true; 17 | 18 | 19 | public virtual IOWriteResult WriteFile(GCodeFile file, StreamWriter outStream) 20 | { 21 | // save current culture 22 | var current_culture = Thread.CurrentThread.CurrentCulture; 23 | 24 | try { 25 | if (WriteInvariantCulture) 26 | Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; 27 | 28 | foreach ( var line in file.AllLines() ) 29 | WriteLine(line, outStream); 30 | 31 | // restore culture 32 | if (WriteInvariantCulture) 33 | Thread.CurrentThread.CurrentCulture = current_culture; 34 | 35 | return IOWriteResult.Ok; 36 | 37 | } catch (Exception e) { 38 | // restore culture 39 | if (WriteInvariantCulture) 40 | Thread.CurrentThread.CurrentCulture = current_culture; 41 | return new IOWriteResult(IOCode.WriterError, "Unknown error : exception : " + e.Message); 42 | } 43 | } 44 | 45 | 46 | public abstract void WriteLine(GCodeLine line, StreamWriter outStream); 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /writers/StandardGCodeWriter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Text; 4 | using System.IO; 5 | using g3; 6 | 7 | namespace gs 8 | { 9 | public class StandardGCodeWriter : BaseGCodeWriter 10 | { 11 | int float_precision = 5; 12 | string float_format = "{0:0.#####}"; 13 | public int FloatPrecision { 14 | get { return float_precision; } 15 | set { float_precision = value; 16 | float_format = "{0:0." + new String('#',float_precision) + "}"; 17 | } 18 | } 19 | 20 | 21 | public enum CommentStyles 22 | { 23 | Semicolon = 0, 24 | Bracket = 1 25 | } 26 | public CommentStyles CommentStyle = CommentStyles.Semicolon; 27 | 28 | 29 | 30 | public override void WriteLine(GCodeLine line, StreamWriter outStream) 31 | { 32 | if ( line.type == GCodeLine.LType.Comment ) { 33 | if (CommentStyle == CommentStyles.Semicolon) { 34 | if (line.comment[0] != ';') 35 | outStream.Write(";"); 36 | outStream.WriteLine(line.comment); 37 | } else { 38 | outStream.Write("("); 39 | outStream.Write(line.comment); 40 | outStream.WriteLine(")"); 41 | } 42 | return; 43 | } else if ( line.type == GCodeLine.LType.UnknownString ) { 44 | outStream.WriteLine(line.orig_string); 45 | return; 46 | } else if ( line.type == GCodeLine.LType.Blank ) { 47 | return; 48 | } 49 | 50 | StringBuilder b = new StringBuilder(); 51 | if ( line.type == GCodeLine.LType.MCode ) { 52 | b.Append('M'); 53 | } else if (line.type == GCodeLine.LType.GCode ) { 54 | b.Append('G'); 55 | } else { 56 | throw new Exception("StandardGCodeWriter.WriteLine: unsupported line type"); 57 | } 58 | 59 | b.Append(line.code); 60 | b.Append(' '); 61 | 62 | if ( line.parameters != null ) { 63 | foreach ( GCodeParam p in line.parameters ) { 64 | if ( p.type == GCodeParam.PType.Code ) { 65 | // 66 | } else if ( p.type == GCodeParam.PType.IntegerValue ) { 67 | b.Append(p.identifier); 68 | b.Append(p.intValue); 69 | b.Append(' '); 70 | } else if ( p.type == GCodeParam.PType.DoubleValue ) { 71 | b.Append(p.identifier); 72 | b.AppendFormat(float_format, p.doubleValue); 73 | b.Append(' '); 74 | } else if ( p.type == GCodeParam.PType.TextValue) { 75 | b.Append(p.identifier); 76 | b.Append(p.textValue); 77 | b.Append(' '); 78 | } else if ( p.type == GCodeParam.PType.NoValue) { 79 | b.Append(p.identifier); 80 | b.Append(' '); 81 | } else { 82 | throw new Exception("StandardGCodeWriter.WriteLine: unsupported parameter type"); 83 | } 84 | } 85 | } 86 | 87 | 88 | if ( line.comment != null && line.comment.Length > 0 ) { 89 | if (CommentStyle == CommentStyles.Semicolon) { 90 | if (line.comment[0] != '(' && line.comment[0] != ';') 91 | b.Append(';'); 92 | b.Append(line.comment); 93 | } else { 94 | b.Append("("); 95 | b.Append(line.comment); 96 | b.Append(")"); 97 | } 98 | } 99 | 100 | outStream.WriteLine(b.ToString()); 101 | } 102 | 103 | } 104 | } 105 | --------------------------------------------------------------------------------