// emit gcode for an extrude move protected virtual void emit_extrude(QueuedExtrude p) { double write_x = p.toPos.x + PositionShift.x; double write_y = p.toPos.y + PositionShift.y; Builder.BeginGLine(1, p.comment). AppendF("X", write_x).AppendF("Y", write_y); if (OmitDuplicateZ == false || MathUtil.EpsilonEqual(p.toPos.z, currentPos.z, MoveEpsilon) == false) { Builder.AppendF("Z", p.toPos.z); } if (OmitDuplicateF == false || MathUtil.EpsilonEqual(p.feedRate, currentFeed, MoveEpsilon) == false) { Builder.AppendF("F", p.feedRate); } if (OmitDuplicateE == false || MathUtil.EpsilonEqual(p.extruderA, extruderA, MoveEpsilon) == false) { Builder.AppendF(p.extrudeChar.ToString(), p.extruderA); } currentPos = p.toPos; currentFeed = p.feedRate; extruderA = p.extruderA; }
// push point onto queue and update accumulated length protected virtual void append_to_queue(QueuedExtrude p) { double dt = (next_queue_index == 0) ? currentPos.xy.Distance(p.toPos.xy) : extrude_queue[next_queue_index - 1].toPos.xy.Distance(p.toPos.xy); extrude_queue_len += dt; extrude_queue[next_queue_index] = p; next_queue_index = Math.Min(next_queue_index + 1, extrude_queue.Length - 1);; }
static public QueuedExtrude lerp(ref QueuedExtrude a, ref QueuedExtrude b, double t) { QueuedExtrude newp = new QueuedExtrude(); newp.toPos = Vector3d.Lerp(a.toPos, b.toPos, t); newp.feedRate = Math.Max(a.feedRate, b.feedRate); newp.extruderA = MathUtil.Lerp(a.extruderA, b.extruderA, t); newp.comment = (a.comment == null) ? a.comment : b.comment; return(newp); }
// emit static retraction move (no xyz movement) protected virtual void emit_retract(QueuedExtrude p) { Builder.BeginGLine(1, p.comment); BuildFeedrateParameter(p.feedRate); BuildExtrudeParameter(p.extruderA); currentPos = p.toPos; currentFeed = p.feedRate; extruderA = p.extruderA; }
// push an extrude move onto queue protected virtual void queue_extrude(Vector3d toPos, double feedRate, double e, string comment, bool bIsRetract) { Util.gDevAssert(InExtrude || bIsRetract); if (EnableBoundsChecking && PositionBounds.Contains(toPos.xy) == false) { throw new Exception("BaseDepositionAssembler.queue_extrude: tried to move outside of bounds!"); } lastPos = toPos; QueuedExtrude p = new QueuedExtrude() { toPos = toPos, feedRate = feedRate, extruderA = e, comment = comment }; // we cannot queue a retract, so flush queue and emit the retract/unretract if (bIsRetract) { flush_extrude_queue(); emit_retract(p); return; } else if (toPos.z != NozzlePosition.z) { flush_extrude_queue(); emit_extrude(p); return; } // push this point onto queue. this will also update the extrude_queue_len double prev_len = extrude_queue_len; append_to_queue(p); // if we haven't moved far enough to emit a point, we wait if (extrude_queue_len < MinExtrudeStepDistance) { return; } // ok we moved far enough from last point to emit // if queue has one point, just emit it int last_i = next_queue_index - 1; if (last_i == 0) { flush_extrude_queue(); return; } // otherwise we lerp between last two points so that we emit at // point where accumulated linear arclength is exactly MinExtrudeStepDistance. double a = prev_len, b = extrude_queue_len; double t = (MinExtrudeStepDistance - a) / (b - a); Util.gDevAssert(t > -0.0001 && t < 1.0001); t = MathUtil.Clamp(t, 0, 1); QueuedExtrude last_p = extrude_queue[next_queue_index - 1]; QueuedExtrude emit_p = QueuedExtrude.lerp(ref extrude_queue[next_queue_index - 2], ref last_p, t); // emit and clear queue emit_extrude(emit_p); next_queue_index = 0; extrude_queue_len = 0; // now we re-submit last point. This pushes the remaining bit of the last segment // back onto the queue. (should we skip this if t > nearly-one?) queue_extrude(last_p.toPos, last_p.feedRate, last_p.extruderA, last_p.comment, false); }