diff --git a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs index cac5fe132..8a3db5368 100644 --- a/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs +++ b/MatterControl.OpenGL/GCodeRenderer/GCodeRenderer.cs @@ -177,6 +177,22 @@ namespace MatterHackers.GCodeVisualizer return renderFeatures[layerToCountFeaturesOn].Count; } + public RenderFeatureBase this[int layerIndex, int featureIndex] + { + get + { + try + { + return renderFeatures[layerIndex][featureIndex - 1]; + } + catch + { + // Lazy guard for invalid indexes - callers should test for non-null values + return null; + } + } + } + public void Render(Graphics2D graphics2D, GCodeRenderInfo renderInfo) { if (renderFeatures.Count > 0) diff --git a/MatterControlLib/PartPreviewWindow/GCodeDetails/GCodeDebugView.cs b/MatterControlLib/PartPreviewWindow/GCodeDetails/GCodeDebugView.cs new file mode 100644 index 000000000..467994188 --- /dev/null +++ b/MatterControlLib/PartPreviewWindow/GCodeDetails/GCodeDebugView.cs @@ -0,0 +1,114 @@ +/* +Copyright (c) 2019, Lars Brubaker, John Lewin +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +The views and conclusions contained in the software and documentation are those +of the authors and should not be interpreted as representing official policies, +either expressed or implied, of the FreeBSD Project. +*/ + +using System; +using MatterControl.Printing; +using MatterHackers.Agg.UI; +using MatterHackers.GCodeVisualizer; +using MatterHackers.Localizations; +using MatterHackers.VectorMath; + +namespace MatterHackers.MatterControl.PartPreviewWindow +{ + public class GCodeDebugView : GCodeDetailsPanel + { + private PrinterTabPage printerTabPage; + private ISceneContext sceneContext; + private TextWidget startPointWidget; + private TextWidget endPointWidget; + private TextWidget slopeWidget; + private TextWidget lengthWidget; + private TextWidget yInterceptWidget; + private TextWidget xInterceptWidget; + + public GCodeDebugView(PrinterTabPage printerTabPage, GCodeFile gCodeMemoryFile, ISceneContext sceneContext, ThemeConfig theme) + : base(theme) + { + this.printerTabPage = printerTabPage; + this.sceneContext = sceneContext; + + startPointWidget = this.AddSetting("Start".Localize(), ""); + endPointWidget = this.AddSetting("End".Localize(), ""); + lengthWidget = this.AddSetting("Length".Localize(), ""); + slopeWidget = this.AddSetting("Slope".Localize(), ""); + yInterceptWidget = this.AddSetting("Y Intercept".Localize(), ""); + xInterceptWidget = this.AddSetting("X Intercept".Localize(), ""); + + // Register listeners + printerTabPage.LayerFeaturesScrollbar.SecondValueChanged += this.LayerFeaturesScrollbar_SecondValueChanged; + } + + public override void OnClosed(EventArgs e) + { + // Unregister listeners + printerTabPage.LayerFeaturesScrollbar.SecondValueChanged -= this.LayerFeaturesScrollbar_SecondValueChanged; + + base.OnClosed(e); + } + + private void LayerFeaturesScrollbar_SecondValueChanged(object sender, EventArgs e) + { + var renderInfo = sceneContext.RenderInfo; + int layerIndex = renderInfo.EndLayerIndex - 1; + int featuresOnLayer = sceneContext.GCodeRenderer.GetNumFeatures(layerIndex); + int featureIndex = (int)(featuresOnLayer * renderInfo.FeatureToEndOnRatio0To1 + .5); + + int activeFeatureIndex = Math.Max(0, Math.Min(featureIndex, featuresOnLayer)); + + if (sceneContext.GCodeRenderer[layerIndex, activeFeatureIndex] is RenderFeatureTravel line) + { + var start = line.Start; + var end = line.End; + + startPointWidget.Text = $"{start}"; + endPointWidget.Text = $"{end}"; + + var length = new Vector2(start).Distance(new Vector2(end)); + lengthWidget.Text = $"{length}"; + + // Slope + // m = (y_2 - y_1) / (x_2 - x_1) + + // Y-Intercept + // n = -x_1 * (y_2 - y_1) / (x_2 - x_1) + y_1 + + var slope = (end.Y - start.Y) / (end.X - start.X); + slopeWidget.Text = $"{slope}"; + + // -x_1 * (y_2 - y_1) / (x_2 - x_1) + y_1 + var yIntercept = -start.X * slope + start.Y; + yInterceptWidget.Text = $"{yIntercept}"; + + // x_1 - y_1*(x_2-x_1)/(y_2-y_1) + var xIntercept = start.X - start.Y * (end.X - start.X) / (end.Y - start.Y); + xInterceptWidget.Text = $"{xIntercept}"; + } + } + } +} diff --git a/MatterControlLib/PartPreviewWindow/GCodePanel.cs b/MatterControlLib/PartPreviewWindow/GCodePanel.cs index aa8f1ff87..13c24e21a 100644 --- a/MatterControlLib/PartPreviewWindow/GCodePanel.cs +++ b/MatterControlLib/PartPreviewWindow/GCodePanel.cs @@ -43,15 +43,17 @@ namespace MatterHackers.MatterControl.PartPreviewWindow private ISceneContext sceneContext; private ThemeConfig theme; private PrinterConfig printer; + private PrinterTabPage printerTabPage; private SectionWidget speedsWidget; private GuiWidget loadedGCodeSection; - public GCodePanel(PrinterConfig printer, ISceneContext sceneContext, ThemeConfig theme) + public GCodePanel(PrinterTabPage printerTabPage, PrinterConfig printer, ISceneContext sceneContext, ThemeConfig theme) : base (FlowDirection.TopToBottom) { this.sceneContext = sceneContext; this.theme = theme; this.printer = printer; + this.printerTabPage = printerTabPage; SectionWidget sectionWidget; @@ -151,6 +153,22 @@ namespace MatterHackers.MatterControl.PartPreviewWindow HAnchor = HAnchor.Stretch, VAnchor = VAnchor.Fit }); +#if DEBUG + loadedGCodeSection.AddChild( + new SectionWidget( + "Debug".Localize(), + new GCodeDebugView(printerTabPage, printer.Bed.LoadedGCode, sceneContext, theme) + { + HAnchor = HAnchor.Stretch, + Margin = new BorderDouble(bottom: 3), + Padding = new BorderDouble(15, 4) + }, + theme) + { + HAnchor = HAnchor.Stretch, + VAnchor = VAnchor.Fit + }); +#endif } // Enforce panel padding in sidebar diff --git a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs index 0d9f685c8..8ee17f8c9 100644 --- a/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs +++ b/MatterControlLib/PartPreviewWindow/PrinterTabPage.cs @@ -48,8 +48,9 @@ namespace MatterHackers.MatterControl.PartPreviewWindow internal GCode2DWidget gcode2DWidget; private View3DConfig gcodeOptions; + private DoubleSolidSlider layerRenderRatioSlider; - public SliceLayerSelector LayerScrollbar { get; private set; } + private GCodePanel gcodePanel; internal VerticalResizeContainer gcodeContainer; internal PrinterActionsBar printerActionsBar; @@ -148,7 +149,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow var position = view3DWidget.InteractionLayer.Children.IndexOf(trackball); - gcodePanel = new GCodePanel(printer, sceneContext, theme) + gcodePanel = new GCodePanel(this, printer, sceneContext, theme) { Name = "GCode3DWidget", HAnchor = HAnchor.Stretch, @@ -229,6 +230,10 @@ namespace MatterHackers.MatterControl.PartPreviewWindow sceneContext.LoadedGCodeChanged += BedPlate_LoadedGCodeChanged; } + public SliceLayerSelector LayerScrollbar { get; private set; } + + public DoubleSolidSlider LayerFeaturesScrollbar => layerRenderRatioSlider; + public int LayerFeaturesIndex { get