Commit of the code

This commit is contained in:
larsbrubaker 2014-01-29 19:09:30 -08:00
parent 33cee93974
commit f4c1b0b85c
356 changed files with 175795 additions and 0 deletions

View file

@ -0,0 +1,250 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.ImageProcessing;
using MatterHackers.Agg.VertexSource;
using MatterHackers.MarchingSquares;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.VectorMath;
using ClipperLib;
namespace MatterHackers.MatterControl
{
using Polygon = List<IntPoint>;
using Polygons = List<List<IntPoint>>;
public static class CreateDiscreteMeshes
{
public static Mesh[] SplitIntoMeshes(Mesh meshToSplit, Vector3 buildVolume, BackgroundWorker backgroundWorker, int startPercent, int endPercent)
{
int lengthPercent = endPercent-startPercent;
// check if the part is bigger than the build plate (if it is we need to use that as our size)
AxisAlignedBoundingBox partBounds = meshToSplit.GetAxisAlignedBoundingBox();
buildVolume.x = Math.Max(buildVolume.x, partBounds.XSize + 2);
buildVolume.y = Math.Max(buildVolume.y, partBounds.YSize + 2);
buildVolume.z = Math.Max(buildVolume.z, partBounds.ZSize + 2);
// Find all the separate objects that are on the plate
// Create a 2D image the size of the printer bed at some scale with the parts draw on it top down
double scaleFactor = 5;
ImageBuffer partPlate = new ImageBuffer((int)(buildVolume.x * scaleFactor), (int)(buildVolume.y * scaleFactor), 32, new BlenderBGRA());
Vector2 renderOffset = new Vector2(buildVolume.x / 2, buildVolume.y / 2) - new Vector2(partBounds.Center.x, partBounds.Center.y);
PolygonMesh.Processors.OrthographicZProjection.DrawTo(partPlate.NewGraphics2D(), meshToSplit, renderOffset, scaleFactor, RGBA_Bytes.White);
if (backgroundWorker != null)
{
backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent * .2));
}
//ImageBMPIO.SaveImageData("test part plate 0.png", partPlate);
// expand the bounds a bit so that we can collect all the vertices and polygons within each bound
Dilate.DoDilate3x3Binary(partPlate, 1);
//ImageBMPIO.SaveImageData("test part plate 1.png", partPlate);
// trace all the bounds of the objects on the plate
PolyTree polyTreeForPlate = FindDistictObjectBounds(partPlate);
if (polyTreeForPlate == null)
{
Mesh[] singleMesh = new Mesh[1];
singleMesh[0] = meshToSplit;
return singleMesh;
}
// get all the discrete areas that are polygons so we can search them
Polygons discreteAreas = new Polygons();
GetAreasRecursive(polyTreeForPlate, discreteAreas);
if (discreteAreas.Count == 0)
{
return null;
}
else if (discreteAreas.Count == 1)
{
Mesh[] singleMesh = new Mesh[1];
singleMesh[0] = meshToSplit;
return singleMesh;
}
Graphics2D graphics2D = partPlate.NewGraphics2D();
graphics2D.Clear(RGBA_Bytes.Black);
Random rand = new Random();
foreach (Polygon polygon in discreteAreas)
{
graphics2D.Render(PlatingHelper.PolygonToPathStorage(polygon), new RGBA_Bytes(rand.Next(128, 255), rand.Next(128, 255), rand.Next(128, 255)));
}
if (backgroundWorker != null)
{
backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent * .50));
}
//ImageBMPIO.SaveImageData("test part plate 2.png", partPlate);
// add each of the separate bounds polygons to new meshes
Mesh[] discreteMeshes = new Mesh[discreteAreas.Count];
for (int i = 0; i < discreteAreas.Count; i++)
{
discreteMeshes[i] = new Mesh();
}
foreach (Face face in meshToSplit.Faces)
{
bool faceDone = false;
// figure out which area one or more of the vertices are in add the face to the right new mesh
foreach (FaceEdge faceEdge in face.FaceEdgeIterator())
{
Vector2 position = new Vector2(faceEdge.vertex.Position.x, faceEdge.vertex.Position.y);
position += renderOffset;
position *= scaleFactor;
for (int areaIndex = discreteAreas.Count-1; areaIndex >= 0; areaIndex--)
{
if (PointInPolygon(discreteAreas[areaIndex], new IntPoint((int)position.x, (int)position.y)))
{
List<Vertex> faceVertices = new List<Vertex>();
foreach (FaceEdge faceEdgeToAdd in face.FaceEdgeIterator())
{
Vertex newVertex = discreteMeshes[areaIndex].CreateVertex(faceEdgeToAdd.vertex.Position);
faceVertices.Add(newVertex);
}
discreteMeshes[areaIndex].CreateFace(faceVertices.ToArray());
faceDone = true;
break;
}
}
if (faceDone)
{
break;
}
}
}
if (backgroundWorker != null)
{
backgroundWorker.ReportProgress(startPercent + (int)(lengthPercent));
}
for (int i = 0; i < discreteMeshes.Count(); i++)
{
Mesh mesh = discreteMeshes[i];
}
return discreteMeshes;
}
public static bool PointInPolygon(Polygon polygon, IntPoint testPosition)
{
int numPoints = polygon.Count;
bool result = false;
for (int i = 0; i < numPoints; i++)
{
int prevIndex = i - 1;
if(prevIndex < 0)
{
prevIndex += numPoints;
}
if ((((polygon[i].Y <= testPosition.Y) && (testPosition.Y < polygon[prevIndex].Y))
|| ((polygon[prevIndex].Y <= testPosition.Y) && (testPosition.Y < polygon[i].Y)))
&& (testPosition.X - polygon[i].X < (polygon[prevIndex].X - polygon[i].X) * (testPosition.Y - polygon[i].Y) / (polygon[prevIndex].Y - polygon[i].Y)))
{
result = !result;
}
}
return result;
}
static private void GetAreasRecursive(PolyNode polyTreeForPlate, Polygons discreteAreas)
{
if (!polyTreeForPlate.IsHole)
{
discreteAreas.Add(polyTreeForPlate.Contour);
}
foreach (PolyNode child in polyTreeForPlate.Childs)
{
GetAreasRecursive(child, discreteAreas);
}
}
static public PolyTree FindDistictObjectBounds(ImageBuffer image)
{
MarchingSquaresByte marchingSquaresData = new MarchingSquaresByte(image, 5, 0);
marchingSquaresData.CreateLineSegments();
Polygons lineLoops = marchingSquaresData.CreateLineLoops(1);
if (lineLoops.Count == 1)
{
return null;
}
// create a bounding polygon to clip against
IntPoint min = new IntPoint(long.MaxValue, long.MaxValue);
IntPoint max = new IntPoint(long.MinValue, long.MinValue);
foreach (Polygon polygon in lineLoops)
{
foreach (IntPoint point in polygon)
{
min.X = Math.Min(point.X - 10, min.X);
min.Y = Math.Min(point.Y - 10, min.Y);
max.X = Math.Max(point.X + 10, max.X);
max.Y = Math.Max(point.Y + 10, max.Y);
}
}
Polygon boundingPoly = new Polygon();
boundingPoly.Add(min);
boundingPoly.Add(new IntPoint(min.X, max.Y));
boundingPoly.Add(max);
boundingPoly.Add(new IntPoint(max.X, min.Y));
// now clip the polygons to get the inside and outside polys
Clipper clipper = new Clipper();
clipper.AddPolygons(lineLoops, PolyType.ptSubject);
clipper.AddPolygon(boundingPoly, PolyType.ptClip);
PolyTree polyTreeForPlate = new PolyTree();
clipper.Execute(ClipType.ctIntersection, polyTreeForPlate);
return polyTreeForPlate;
}
}
}

View file

@ -0,0 +1,704 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.ComponentModel;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.OpenGlGui;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using MatterHackers.GCodeVisualizer;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl;
using MatterHackers.MatterControl.PrintQueue;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class GcodeViewBasic : PartPreviewBaseWidget
{
public Slider selectLayerSlider;
TextWidget gcodeProcessingStateInfoText;
GCodeViewWidget gcodeViewWidget;
PrintItemWrapper printItem;
Button closeButton;
bool startedSliceFromGenerateButton = false;
Button generateGCodeButton;
FlowLayoutWidget buttonBottomPanel;
FlowLayoutWidget layerSelectionButtonsPannel;
FlowLayoutWidget buttonRightPanel;
FlowLayoutWidget modelOptionsContainer;
FlowLayoutWidget layerOptionsContainer;
FlowLayoutWidget displayOptionsContainer;
CheckBox expandModelOptions;
CheckBox expandLayerOptions;
CheckBox expandDisplayOptions;
GuiWidget gcodeDispalyWidget;
GetSizeFunction bedSizeFunction;
GetSizeFunction bedCenterFunction;
public delegate Vector2 GetSizeFunction();
public GcodeViewBasic(PrintItemWrapper printItem, GetSizeFunction bedSizeFunction, GetSizeFunction bedCenterFunction)
{
this.printItem = printItem;
this.bedSizeFunction = bedSizeFunction;
this.bedCenterFunction = bedCenterFunction;
CreateAndAddChildren(null);
}
void CreateAndAddChildren(object state)
{
RemoveAllChildren();
FlowLayoutWidget mainContainerTopToBottom = new FlowLayoutWidget(FlowDirection.TopToBottom);
mainContainerTopToBottom.HAnchor = Agg.UI.HAnchor.Max_FitToChildren_ParentWidth;
mainContainerTopToBottom.VAnchor = Agg.UI.VAnchor.Max_FitToChildren_ParentHeight;
buttonBottomPanel = new FlowLayoutWidget(FlowDirection.LeftToRight);
buttonBottomPanel.HAnchor = HAnchor.ParentLeftRight;
buttonBottomPanel.Padding = new BorderDouble(3, 3);
buttonBottomPanel.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
generateGCodeButton = textImageButtonFactory.Generate("Generate");
generateGCodeButton.Click += new ButtonBase.ButtonEventHandler(generateButton_Click);
buttonBottomPanel.AddChild(generateGCodeButton);
layerSelectionButtonsPannel = new FlowLayoutWidget(FlowDirection.RightToLeft);
layerSelectionButtonsPannel.HAnchor = HAnchor.ParentLeftRight;
layerSelectionButtonsPannel.Padding = new BorderDouble(0);
closeButton = textImageButtonFactory.Generate("Close");
layerSelectionButtonsPannel.AddChild(closeButton);
FlowLayoutWidget centerPartPreviewAndControls = new FlowLayoutWidget(FlowDirection.LeftToRight);
centerPartPreviewAndControls.AnchorAll();
gcodeDispalyWidget = new GuiWidget(HAnchor.ParentLeftRight, Agg.UI.VAnchor.ParentBottomTop);
string startingMessage = "Loading GCode...";
if (Path.GetExtension(printItem.FileLocation).ToUpper() == ".GCODE")
{
gcodeDispalyWidget.AddChild(CreateGCodeViewWidget(printItem.FileLocation));
}
else
{
string gcodePathAndFileName = printItem.GCodePathAndFileName;
bool gcodeFileIsComplete = printItem.IsGCodeFileComplete(gcodePathAndFileName);
if (gcodeProcessingStateInfoText != null && gcodeProcessingStateInfoText.Text == "Slicing Error")
{
startingMessage = "Slicing Error. Please review your slice settings.";
}
else
{
startingMessage = "Press 'generate' to view layers";
}
if (File.Exists(gcodePathAndFileName) && gcodeFileIsComplete)
{
gcodeDispalyWidget.AddChild(CreateGCodeViewWidget(gcodePathAndFileName));
}
// we only hook these up to make sure we can regenerate the gcode when we want
printItem.SlicingOutputMessage += sliceItem_SlicingOutputMessage;
printItem.Done += new EventHandler(sliceItem_Done);
}
centerPartPreviewAndControls.AddChild(gcodeDispalyWidget);
buttonRightPanel = CreateRightButtonPannel();
centerPartPreviewAndControls.AddChild(buttonRightPanel);
// add in a spacer
layerSelectionButtonsPannel.AddChild(new GuiWidget(HAnchor.ParentLeftRight));
buttonBottomPanel.AddChild(layerSelectionButtonsPannel);
mainContainerTopToBottom.AddChild(centerPartPreviewAndControls);
mainContainerTopToBottom.AddChild(buttonBottomPanel);
this.AddChild(mainContainerTopToBottom);
AddProcessingMessage(startingMessage);
AddViewControls();
AddHandlers();
}
void AddViewControls()
{
TextImageButtonFactory iconTextImageButtonFactory = new TextImageButtonFactory();
FlowLayoutWidget transformTypeSelector = new FlowLayoutWidget();
transformTypeSelector.BackgroundColor = new RGBA_Bytes(0, 0, 0, 120);
iconTextImageButtonFactory.FixedHeight = 20;
iconTextImageButtonFactory.FixedWidth = 20;
string translateIconPath = Path.Combine("Icons", "ViewTransformControls", "translate.png");
RadioButton translateButton = iconTextImageButtonFactory.GenerateRadioButton("", translateIconPath);
translateButton.Margin = new BorderDouble(3);
transformTypeSelector.AddChild(translateButton);
translateButton.Click += (sender, e) =>
{
gcodeViewWidget.TransformState = GCodeViewWidget.ETransformState.Move;
};
string scaleIconPath = Path.Combine("Icons", "ViewTransformControls", "scale.png");
RadioButton scaleButton = iconTextImageButtonFactory.GenerateRadioButton("", scaleIconPath);
scaleButton.Margin = new BorderDouble(3);
transformTypeSelector.AddChild(scaleButton);
scaleButton.Click += (sender, e) =>
{
gcodeViewWidget.TransformState = GCodeViewWidget.ETransformState.Scale;
};
transformTypeSelector.Margin = new BorderDouble(5);
transformTypeSelector.HAnchor |= Agg.UI.HAnchor.ParentLeft;
transformTypeSelector.VAnchor = Agg.UI.VAnchor.ParentTop;
AddChild(transformTypeSelector);
translateButton.Checked = true;
}
private FlowLayoutWidget CreateRightButtonPannel()
{
FlowLayoutWidget buttonRightPanel = new FlowLayoutWidget(FlowDirection.TopToBottom);
buttonRightPanel.Width = 200;
{
BorderDouble buttonMargin = new BorderDouble(top: 3);
expandModelOptions = expandMenuOptionFactory.GenerateCheckBoxButton("Model", "icon_arrow_right_no_border_32x32.png", "icon_arrow_down_no_border_32x32.png");
expandModelOptions.Margin = new BorderDouble(bottom: 2);
buttonRightPanel.AddChild(expandModelOptions);
expandModelOptions.Checked = true;
modelOptionsContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
modelOptionsContainer.HAnchor = HAnchor.ParentLeftRight;
//modelOptionsContainer.Visible = false;
buttonRightPanel.AddChild(modelOptionsContainer);
expandLayerOptions = expandMenuOptionFactory.GenerateCheckBoxButton("Layer", "icon_arrow_right_no_border_32x32.png", "icon_arrow_down_no_border_32x32.png");
expandLayerOptions.Margin = new BorderDouble(bottom: 2);
//buttonRightPanel.AddChild(expandLayerOptions);
layerOptionsContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
layerOptionsContainer.HAnchor = HAnchor.ParentLeftRight;
layerOptionsContainer.Visible = false;
buttonRightPanel.AddChild(layerOptionsContainer);
expandDisplayOptions = expandMenuOptionFactory.GenerateCheckBoxButton("Display", "icon_arrow_right_no_border_32x32.png", "icon_arrow_down_no_border_32x32.png");
expandDisplayOptions.Margin = new BorderDouble(bottom: 2);
buttonRightPanel.AddChild(expandDisplayOptions);
expandDisplayOptions.Checked = true;
displayOptionsContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
displayOptionsContainer.HAnchor = HAnchor.ParentLeftRight;
//displayOptionsContainer.Visible = false;
buttonRightPanel.AddChild(displayOptionsContainer);
GuiWidget verticalSpacer = new GuiWidget();
verticalSpacer.VAnchor = VAnchor.ParentBottomTop;
buttonRightPanel.AddChild(verticalSpacer);
}
buttonRightPanel.Padding = new BorderDouble(6, 6);
buttonRightPanel.Margin = new BorderDouble(0, 1);
buttonRightPanel.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
buttonRightPanel.VAnchor = VAnchor.ParentBottomTop;
return buttonRightPanel;
}
private void CreateOptionsContent()
{
AddModelInfo(modelOptionsContainer);
//AddLayerInfo(layerOptionsContainer);
AddDisplayControls(displayOptionsContainer);
}
private void AddModelInfo(FlowLayoutWidget buttonPanel)
{
textImageButtonFactory.FixedWidth = 44;
FlowLayoutWidget modelInfoContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
modelInfoContainer.HAnchor = HAnchor.ParentLeftRight;
modelInfoContainer.Padding = new BorderDouble(5);
// put in the print time
modelInfoContainer.AddChild(new TextWidget("Print Time:", textColor: RGBA_Bytes.White));
{
string timeRemainingText = "---";
if (gcodeViewWidget != null && gcodeViewWidget.LoadedGCode != null)
{
int secondsRemaining = (int)gcodeViewWidget.LoadedGCode.GCodeCommandQueue[0].secondsToEndFromHere;
int hoursRemaining = (int)(secondsRemaining / (60 * 60));
int minutesRemaining = (int)((secondsRemaining + 30) / 60 - hoursRemaining * 60); // +30 for rounding
secondsRemaining = secondsRemaining % 60;
if (hoursRemaining > 0)
{
timeRemainingText = string.Format("{0} h, {1} min", hoursRemaining, minutesRemaining);
}
else
{
timeRemainingText = string.Format("{0} min", minutesRemaining);
}
}
GuiWidget estimatedPrintTime = new TextWidget(string.Format("{0}", timeRemainingText), textColor: RGBA_Bytes.White, pointSize: 10);
estimatedPrintTime.HAnchor = Agg.UI.HAnchor.ParentLeft;
estimatedPrintTime.Margin = new BorderDouble(3, 0, 0, 3);
modelInfoContainer.AddChild(estimatedPrintTime);
}
//modelInfoContainer.AddChild(new TextWidget("Size:", textColor: RGBA_Bytes.White));
// show the filament used
modelInfoContainer.AddChild(new TextWidget("Filament Length:", textColor: RGBA_Bytes.White));
{
double filamentUsed = gcodeViewWidget.LoadedGCode.GetFilamentUsedMm(ActiveSliceSettings.Instance.NozzleDiameter);
GuiWidget estimatedPrintTime = new TextWidget(string.Format("{0:0.0} mm", filamentUsed), textColor: RGBA_Bytes.White, pointSize: 10);
estimatedPrintTime.HAnchor = Agg.UI.HAnchor.ParentLeft;
estimatedPrintTime.Margin = new BorderDouble(3, 0, 0, 3);
modelInfoContainer.AddChild(estimatedPrintTime);
}
modelInfoContainer.AddChild(new TextWidget("Filament Volume:", textColor: RGBA_Bytes.White));
{
var density = 1.0;
string filamentType = "PLA";
if(filamentType == "ABS")
{
density = 1.04;
}
else if(filamentType == "PLA")
{
density = 1.24;
}
double filamentMm3 = gcodeViewWidget.LoadedGCode.GetFilamentCubicMm(ActiveSliceSettings.Instance.FillamentDiameter);
GuiWidget estimatedPrintTime = new TextWidget(string.Format("{0:0.00} cm3", filamentMm3/1000), textColor: RGBA_Bytes.White, pointSize: 10);
estimatedPrintTime.HAnchor = Agg.UI.HAnchor.ParentLeft;
estimatedPrintTime.Margin = new BorderDouble(3, 0, 0, 3);
modelInfoContainer.AddChild(estimatedPrintTime);
}
modelInfoContainer.AddChild(new TextWidget("Weight:", textColor: RGBA_Bytes.White));
{
var density = 1.0;
string filamentType = "PLA";
if (filamentType == "ABS")
{
density = 1.04;
}
else if (filamentType == "PLA")
{
density = 1.24;
}
double filamentWeightGrams = gcodeViewWidget.LoadedGCode.GetFilamentWeightGrams(ActiveSliceSettings.Instance.FillamentDiameter, density);
GuiWidget estimatedPrintTime = new TextWidget(string.Format("{0:0.00} g", filamentWeightGrams), textColor: RGBA_Bytes.White, pointSize: 10);
estimatedPrintTime.HAnchor = Agg.UI.HAnchor.ParentLeft;
estimatedPrintTime.Margin = new BorderDouble(3, 0, 0, 3);
modelInfoContainer.AddChild(estimatedPrintTime);
}
//modelInfoContainer.AddChild(new TextWidget("Layer Count:", textColor: RGBA_Bytes.White));
buttonPanel.AddChild(modelInfoContainer);
textImageButtonFactory.FixedWidth = 0;
}
private void AddLayerInfo(FlowLayoutWidget buttonPanel)
{
textImageButtonFactory.FixedWidth = 44;
FlowLayoutWidget layerInfoContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
layerInfoContainer.HAnchor = HAnchor.ParentLeftRight;
layerInfoContainer.Padding = new BorderDouble(5);
layerInfoContainer.AddChild(new TextWidget("Layer Number:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Layer Height:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Num GCodes:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Filament Used:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Weight:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Print Time:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Extrude Speeds:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Move Speeds:", textColor: RGBA_Bytes.White));
layerInfoContainer.AddChild(new TextWidget("Retract Speeds:", textColor: RGBA_Bytes.White));
buttonPanel.AddChild(layerInfoContainer);
textImageButtonFactory.FixedWidth = 0;
}
private void AddDisplayControls(FlowLayoutWidget buttonPanel)
{
textImageButtonFactory.FixedWidth = 44;
FlowLayoutWidget layerInfoContainer = new FlowLayoutWidget(FlowDirection.TopToBottom);
layerInfoContainer.HAnchor = HAnchor.ParentLeftRight;
layerInfoContainer.Padding = new BorderDouble(5);
// put in a show grid check box
CheckBox showGrid = new CheckBox("Show Grid", textColor: RGBA_Bytes.White);
showGrid.Checked = gcodeViewWidget.RenderGrid;
showGrid.CheckedStateChanged += (sender, e) =>
{
gcodeViewWidget.RenderGrid = showGrid.Checked;
};
layerInfoContainer.AddChild(showGrid);
// put in a show moves checkbox
CheckBox showMoves = new CheckBox("Show Moves", textColor: RGBA_Bytes.White);
showMoves.Checked = gcodeViewWidget.RenderMoves;
showMoves.CheckedStateChanged += (sender, e) =>
{
gcodeViewWidget.RenderMoves = showMoves.Checked;
};
layerInfoContainer.AddChild(showMoves);
//layerInfoContainer.AddChild(new CheckBox("Show Retractions", textColor: RGBA_Bytes.White));
buttonPanel.AddChild(layerInfoContainer);
textImageButtonFactory.FixedWidth = 0;
}
public override void OnParentChanged(EventArgs e)
{
base.OnParentChanged(e);
}
string partToStartLoadingOnFirstDraw = null;
private GuiWidget CreateGCodeViewWidget(string pathAndFileName)
{
gcodeViewWidget = new GCodeViewWidget(bedSizeFunction(), bedCenterFunction());
gcodeViewWidget.DoneLoading += DoneLoadingGCode;
gcodeViewWidget.LoadingProgressChanged += LoadingProgressChanged;
partToStartLoadingOnFirstDraw = pathAndFileName;
return gcodeViewWidget;
}
bool hookedParentKeyDown = false;
public override void OnDraw(Graphics2D graphics2D)
{
if (!hookedParentKeyDown)
{
Parent.Parent.Parent.KeyDown += new KeyEventHandler(Parent_KeyDown);
hookedParentKeyDown = true;
}
if (partToStartLoadingOnFirstDraw != null)
{
gcodeViewWidget.Load(partToStartLoadingOnFirstDraw);
partToStartLoadingOnFirstDraw = null;
}
base.OnDraw(graphics2D);
}
void Parent_KeyDown(object sender, KeyEventArgs keyEvent)
{
if (keyEvent.KeyCode == Keys.Up)
{
gcodeViewWidget.ActiveLayerIndex = (gcodeViewWidget.ActiveLayerIndex + 1);
}
else if (keyEvent.KeyCode == Keys.Down)
{
gcodeViewWidget.ActiveLayerIndex = (gcodeViewWidget.ActiveLayerIndex - 1);
}
}
private void AddProcessingMessage(string message)
{
gcodeProcessingStateInfoText = new TextWidget(message);
gcodeProcessingStateInfoText.HAnchor = HAnchor.ParentCenter;
gcodeProcessingStateInfoText.VAnchor = VAnchor.ParentCenter;
gcodeProcessingStateInfoText.AutoExpandBoundsToText = true;
GuiWidget labelContainer = new GuiWidget();
labelContainer.AnchorAll();
labelContainer.AddChild(gcodeProcessingStateInfoText);
labelContainer.Selectable = false;
gcodeDispalyWidget.AddChild(labelContainer);
}
void LoadingProgressChanged(object sender, ProgressChangedEventArgs e)
{
gcodeProcessingStateInfoText.Text = string.Format("Loading GCode {0}%...", e.ProgressPercentage);
}
void DoneLoadingGCode(object sender, EventArgs e)
{
gcodeProcessingStateInfoText.Text = "";
if (gcodeViewWidget != null
&& gcodeViewWidget.LoadedGCode != null
&& gcodeViewWidget.LoadedGCode.GCodeCommandQueue.Count > 0
&& gcodeViewWidget.LoadedGCode.GCodeCommandQueue[0].secondsToEndFromHere > 0)
{
CreateOptionsContent();
SetLayerWidget setLayerWidget = new SetLayerWidget(gcodeViewWidget);
setLayerWidget.VAnchor = Agg.UI.VAnchor.ParentTop;
layerSelectionButtonsPannel.AddChild(setLayerWidget);
LayerNavigationWidget navigationWidget = new LayerNavigationWidget(gcodeViewWidget);
navigationWidget.Margin = new BorderDouble(0, 0, 20, 0);
layerSelectionButtonsPannel.AddChild(navigationWidget);
selectLayerSlider = new Slider(new Vector2(), 10, 0, gcodeViewWidget.gCodeView.NumLayers - 1, Orientation.Vertical);
selectLayerSlider.ValueChanged += new EventHandler(selectLayerSlider_ValueChanged);
gcodeViewWidget.ActiveLayerChanged += new EventHandler(gcodeViewWidget_ActiveLayerChanged);
AddChild(selectLayerSlider);
SetSliderSize();
BoundsChanged += new EventHandler(PartPreviewGCode_BoundsChanged);
}
}
void gcodeViewWidget_ActiveLayerChanged(object sender, EventArgs e)
{
if (gcodeViewWidget.ActiveLayerIndex != (int)(selectLayerSlider.Value + .5))
{
selectLayerSlider.Value = gcodeViewWidget.ActiveLayerIndex;
}
}
void selectLayerSlider_ValueChanged(object sender, EventArgs e)
{
gcodeViewWidget.ActiveLayerIndex = (int)(selectLayerSlider.Value + .5);
}
void PartPreviewGCode_BoundsChanged(object sender, EventArgs e)
{
SetSliderSize();
}
void SetSliderSize()
{
selectLayerSlider.OriginRelativeParent = new Vector2(gcodeDispalyWidget.Width - 20, 80);
selectLayerSlider.TotalWidthInPixels = gcodeDispalyWidget.Height - 80;
}
private void AddHandlers()
{
closeButton.Click += onCloseButton_Click;
expandModelOptions.CheckedStateChanged += new CheckBox.CheckedStateChangedEventHandler(expandModelOptions_CheckedStateChanged);
expandLayerOptions.CheckedStateChanged += new CheckBox.CheckedStateChangedEventHandler(expandScaleOptions_CheckedStateChanged);
expandDisplayOptions.CheckedStateChanged += new CheckBox.CheckedStateChangedEventHandler(expandMirrorOptions_CheckedStateChanged);
}
void expandModelOptions_CheckedStateChanged(object sender, EventArgs e)
{
modelOptionsContainer.Visible = expandModelOptions.Checked;
}
void expandMirrorOptions_CheckedStateChanged(object sender, EventArgs e)
{
displayOptionsContainer.Visible = expandDisplayOptions.Checked;
}
void expandScaleOptions_CheckedStateChanged(object sender, EventArgs e)
{
layerOptionsContainer.Visible = expandLayerOptions.Checked;
}
private void onCloseButton_Click(object sender, EventArgs e)
{
UiThread.RunOnIdle(CloseOnIdle);
}
void CloseOnIdle(object state)
{
Close();
}
public override void OnClosed(EventArgs e)
{
printItem.SlicingOutputMessage -= sliceItem_SlicingOutputMessage;
printItem.Done -= new EventHandler(sliceItem_Done);
if (startedSliceFromGenerateButton && printItem.CurrentlySlicing)
{
SlicingQueue.Instance.CancelCurrentSlicing();
}
base.OnClosed(e);
}
void generateButton_Click(object sender, MouseEventArgs mouseEvent)
{
if (ActiveSliceSettings.Instance.IsValid())
{
((Button)sender).Visible = false;
SlicingQueue.Instance.QueuePartForSlicing(printItem);
startedSliceFromGenerateButton = true;
}
}
void sliceItem_SlicingOutputMessage(object sender, EventArgs e)
{
StringEventArgs message = e as StringEventArgs;
if (message != null && message.Data != null)
{
gcodeProcessingStateInfoText.Text = message.Data;
}
else
{
gcodeProcessingStateInfoText.Text = "";
}
}
void sliceItem_Done(object sender, EventArgs e)
{
UiThread.RunOnIdle(CreateAndAddChildren);
startedSliceFromGenerateButton = false;
}
}
public class SetLayerWidget : FlowLayoutWidget
{
NumberEdit editCurrentLayerIndex;
Button setLayerButton;
GCodeViewWidget gcodeViewWidget;
TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
public SetLayerWidget(GCodeViewWidget gcodeViewWidget)
:base(FlowDirection.LeftToRight)
{
this.gcodeViewWidget = gcodeViewWidget;
textImageButtonFactory.normalTextColor = RGBA_Bytes.White;
textImageButtonFactory.hoverTextColor = RGBA_Bytes.White;
textImageButtonFactory.disabledTextColor = RGBA_Bytes.White;
textImageButtonFactory.pressedTextColor = RGBA_Bytes.White;
editCurrentLayerIndex = new NumberEdit(1, pixelWidth: 40);
editCurrentLayerIndex.VAnchor = VAnchor.ParentCenter;
editCurrentLayerIndex.Margin = new BorderDouble(5, 0);
editCurrentLayerIndex.EditComplete += new EventHandler(editCurrentLayerIndex_EditComplete);
this.AddChild(editCurrentLayerIndex);
gcodeViewWidget.ActiveLayerChanged += new EventHandler(gcodeViewWidget_ActiveLayerChanged);
setLayerButton = textImageButtonFactory.Generate("Go");
setLayerButton.VAnchor = Agg.UI.VAnchor.ParentCenter;
setLayerButton.Click += new Button.ButtonEventHandler(layerCountTextWidget_EditComplete);
this.AddChild(setLayerButton);
}
void gcodeViewWidget_ActiveLayerChanged(object sender, EventArgs e)
{
editCurrentLayerIndex.Value = gcodeViewWidget.ActiveLayerIndex + 1;
}
void editCurrentLayerIndex_EditComplete(object sender, EventArgs e)
{
gcodeViewWidget.ActiveLayerIndex = ((int)editCurrentLayerIndex.Value - 1);
editCurrentLayerIndex.Value = gcodeViewWidget.ActiveLayerIndex + 1;
}
void layerCountTextWidget_EditComplete(object sender, MouseEventArgs e)
{
gcodeViewWidget.ActiveLayerIndex = ((int)editCurrentLayerIndex.Value - 1);
}
}
public class LayerNavigationWidget : FlowLayoutWidget
{
Button prevLayerButton;
Button nextLayerButton;
TextWidget layerCountTextWidget;
GCodeViewWidget gcodeViewWidget;
TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
public LayerNavigationWidget(GCodeViewWidget gcodeViewWidget)
:base(FlowDirection.LeftToRight)
{
this.gcodeViewWidget = gcodeViewWidget;
textImageButtonFactory.normalTextColor = RGBA_Bytes.White;
textImageButtonFactory.hoverTextColor = RGBA_Bytes.White;
textImageButtonFactory.disabledTextColor = RGBA_Bytes.White;
textImageButtonFactory.pressedTextColor = RGBA_Bytes.White;
prevLayerButton = textImageButtonFactory.Generate("<<");
prevLayerButton.Click += new Button.ButtonEventHandler(prevLayer_ButtonClick);
this.AddChild(prevLayerButton);
layerCountTextWidget = new TextWidget("/1____", 12);
layerCountTextWidget.TextColor = ActiveTheme.Instance.PrimaryTextColor;
layerCountTextWidget.VAnchor = VAnchor.ParentCenter;
layerCountTextWidget.AutoExpandBoundsToText = true;
layerCountTextWidget.Margin = new BorderDouble(5, 0);
this.AddChild(layerCountTextWidget);
nextLayerButton = textImageButtonFactory.Generate(">>");
nextLayerButton.Click += new Button.ButtonEventHandler(nextLayer_ButtonClick);
this.AddChild(nextLayerButton);
}
void nextLayer_ButtonClick(object sender, MouseEventArgs mouseEvent)
{
gcodeViewWidget.ActiveLayerIndex = (gcodeViewWidget.ActiveLayerIndex + 1);
}
void prevLayer_ButtonClick(object sender, MouseEventArgs mouseEvent)
{
gcodeViewWidget.ActiveLayerIndex = (gcodeViewWidget.ActiveLayerIndex - 1);
}
public override void OnDraw(Graphics2D graphics2D)
{
if (gcodeViewWidget.LoadedGCode != null)
{
layerCountTextWidget.Text = string.Format("{0} / {1}", gcodeViewWidget.ActiveLayerIndex + 1, gcodeViewWidget.gCodeView.NumLayers.ToString());
}
base.OnDraw(graphics2D);
}
}
}

View file

@ -0,0 +1,97 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.OpenGlGui;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class PartPreviewBaseWidget : GuiWidget
{
protected TextImageButtonFactory textImageButtonFactory = new TextImageButtonFactory();
protected TextImageButtonFactory checkboxButtonFactory = new TextImageButtonFactory();
protected TextImageButtonFactory expandMenuOptionFactory = new TextImageButtonFactory();
protected TextImageButtonFactory whiteButtonFactory = new TextImageButtonFactory();
public PartPreviewBaseWidget()
{
textImageButtonFactory.normalTextColor = RGBA_Bytes.White;
textImageButtonFactory.hoverTextColor = RGBA_Bytes.White;
textImageButtonFactory.disabledTextColor = RGBA_Bytes.White;
textImageButtonFactory.pressedTextColor = RGBA_Bytes.White;
whiteButtonFactory.FixedWidth = 138;
whiteButtonFactory.normalFillColor = RGBA_Bytes.White;
whiteButtonFactory.normalTextColor = RGBA_Bytes.Black;
whiteButtonFactory.hoverTextColor = RGBA_Bytes.Black;
whiteButtonFactory.hoverFillColor = new RGBA_Bytes(255, 255, 255, 200);
expandMenuOptionFactory.FixedWidth = 138;
expandMenuOptionFactory.normalTextColor = RGBA_Bytes.White;
expandMenuOptionFactory.hoverTextColor = RGBA_Bytes.White;
expandMenuOptionFactory.disabledTextColor = RGBA_Bytes.White;
expandMenuOptionFactory.pressedTextColor = RGBA_Bytes.White;
expandMenuOptionFactory.hoverFillColor = new RGBA_Bytes(255, 255, 255, 50);
expandMenuOptionFactory.pressedFillColor = new RGBA_Bytes(255, 255, 255, 50);
expandMenuOptionFactory.disabledFillColor = new RGBA_Bytes(255, 255, 255, 50);
checkboxButtonFactory.fontSize = 11;
checkboxButtonFactory.FixedWidth = 138;
checkboxButtonFactory.borderWidth = 3;
checkboxButtonFactory.normalTextColor = RGBA_Bytes.White;
checkboxButtonFactory.normalBorderColor = new RGBA_Bytes(0, 0, 0, 0);
checkboxButtonFactory.normalFillColor = ActiveTheme.Instance.PrimaryBackgroundColor;
checkboxButtonFactory.hoverTextColor = RGBA_Bytes.White;
checkboxButtonFactory.hoverBorderColor = new RGBA_Bytes(0, 0, 0, 50);
checkboxButtonFactory.hoverFillColor = new RGBA_Bytes(0, 0, 0, 50);
checkboxButtonFactory.pressedTextColor = RGBA_Bytes.White;
checkboxButtonFactory.pressedBorderColor = new RGBA_Bytes(0, 0, 0, 50);
checkboxButtonFactory.disabledTextColor = RGBA_Bytes.White;
BackgroundColor = RGBA_Bytes.White;
}
}
}

View file

@ -0,0 +1,150 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.OpenGlGui;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.Localizations;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class PartPreviewMainWindow : SystemWindow
{
View3DTransformPart part3DView;
GcodeViewBasic partGcodeView;
//PartPreview3DGcode part3DGcodeView;
public PartPreviewMainWindow(PrintItemWrapper printItem)
: base(690, 340)
{
Title = "MatterControl: " + Path.GetFileName(printItem.Name);
BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
TabControl tabControl = new TabControl();
tabControl.TabBar.BorderColor = new RGBA_Bytes(0, 0, 0, 0);
tabControl.TabBar.BackgroundColor = ActiveTheme.Instance.PrimaryBackgroundColor;
double buildHeight = ActiveSliceSettings.Instance.BuildHeight;
string part3DViewLblBeg = ("3D");
string part3DViewLblEnd = new LocalizedString ("View").Translated;
string part3DViewLblFull = string.Format("{0} {1} ", part3DViewLblBeg, part3DViewLblEnd);
part3DView = new View3DTransformPart(printItem, new Vector3(ActiveSliceSettings.Instance.BedSize, buildHeight));
TabPage partPreview3DView = new TabPage(part3DView, part3DViewLblFull);
partGcodeView = new GcodeViewBasic(printItem, ActiveSliceSettings.Instance.GetBedSize, ActiveSliceSettings.Instance.GetBedCenter);
TabPage layerView = new TabPage(partGcodeView, new LocalizedString("Layer View").Translated);
//part3DGcodeView = new PartPreview3DGcode(printItem.FileLocation, bedXSize, bedYSize);
tabControl.AddTab(new SimpleTextTabWidget(partPreview3DView , 16,
ActiveTheme.Instance.TabLabelSelected, new RGBA_Bytes(), ActiveTheme.Instance.TabLabelUnselected, new RGBA_Bytes()));
tabControl.AddTab(new SimpleTextTabWidget(layerView, 16,
ActiveTheme.Instance.TabLabelSelected, new RGBA_Bytes(), ActiveTheme.Instance.TabLabelUnselected, new RGBA_Bytes()));
if (Path.GetExtension(printItem.FileLocation).ToUpper() == ".GCODE")
{
tabControl.TabBar.SwitchToPage(layerView);
}
this.AddChild(tabControl);
this.AnchorAll();
AddHandlers();
Width = 640;
Height = 480;
ShowAsSystemWindow();
MinimumSize = new Vector2(400, 300);
}
PerformanceFeedbackWindow timingWindow = null;
Stopwatch totalDrawTime = new Stopwatch();
static NamedExecutionTimer partPreviewDraw = new NamedExecutionTimer("PartPreview Draw");
public override void OnDraw(Graphics2D graphics2D)
{
ExecutionTimer.Instance.Reset();
totalDrawTime.Restart();
partPreviewDraw.Start();
base.OnDraw(graphics2D);
partPreviewDraw.Stop();
totalDrawTime.Stop();
#if true //DEBUG
#if false
if (timingWindow == null)
{
timingWindow = new PerformanceFeedbackWindow();
}
{
timingWindow.ShowResults(totalDrawTime.Elapsed.TotalSeconds);
}
#endif
#endif
}
event EventHandler unregisterEvents;
private void AddHandlers()
{
ActiveTheme.Instance.ThemeChanged.RegisterEvent(Instance_ThemeChanged, ref unregisterEvents);
part3DView.Closed += (sender, e) => { Close(); };
partGcodeView.Closed += (sender, e) => { Close(); };
}
public override void OnClosed(EventArgs e)
{
if (unregisterEvents != null)
{
unregisterEvents(this, null);
}
base.OnClosed(e);
}
void Instance_ThemeChanged(object sender, EventArgs e)
{
Invalidate();
}
}
}

View file

@ -0,0 +1,300 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using ClipperLib;
using MatterHackers.Agg;
using MatterHackers.Agg.VertexSource;
using MatterHackers.PolygonMesh;
using MatterHackers.PolygonMesh.Csg;
using MatterHackers.RayTracer;
using MatterHackers.VectorMath;
namespace MatterHackers.MatterControl
{
using Polygon = List<IntPoint>;
using Polygons = List<List<IntPoint>>;
public class PlatingMeshData
{
public double currentScale = 1;
public double xSpacing;
public IRayTraceable traceableData;
}
public static class PlatingHelper
{
public static Mesh DoMerge(List<Mesh> meshesToMerge, BackgroundWorker backgroundWorker, int startPercent, int endPercent, bool doCSGMerge = false)
{
int lengthPercent = endPercent - startPercent;
Mesh allPolygons = new Mesh();
if (doCSGMerge)
{
for (int i = 0; i < meshesToMerge.Count; i++)
{
Mesh mesh = meshesToMerge[i];
allPolygons = CsgOperations.PerformOperation(allPolygons, mesh, CsgNode.Union);
}
}
else
{
for (int i = 0; i < meshesToMerge.Count; i++)
{
Mesh mesh = meshesToMerge[i];
foreach (Face face in mesh.Faces)
{
List<Vertex> faceVertices = new List<Vertex>();
foreach (FaceEdge faceEdgeToAdd in face.FaceEdgeIterator())
{
// we allow duplicates (the true) to make sure we are not changing the loaded models acuracy.
Vertex newVertex = allPolygons.CreateVertex(faceEdgeToAdd.vertex.Position, true);
faceVertices.Add(newVertex);
}
// we allow duplicates (the true) to make sure we are not changing the loaded models acuracy.
allPolygons.CreateFace(faceVertices.ToArray(), true);
}
int nextPercent = startPercent + (i + 1) * lengthPercent / meshesToMerge.Count;
backgroundWorker.ReportProgress(nextPercent);
}
}
return allPolygons;
}
public static PathStorage PolygonToPathStorage(Polygon polygon)
{
PathStorage output = new PathStorage();
bool first = true;
foreach (IntPoint point in polygon)
{
if (first)
{
output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandMoveTo);
first = false;
}
else
{
output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandLineTo);
}
}
output.ClosePolygon();
output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop);
return output;
}
public static PathStorage PolygonToPathStorage(Polygons polygons)
{
PathStorage output = new PathStorage();
foreach (Polygon polygon in polygons)
{
bool first = true;
foreach (IntPoint point in polygon)
{
if (first)
{
output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandMoveTo);
first = false;
}
else
{
output.Add(point.X, point.Y, ShapePath.FlagsAndCommand.CommandLineTo);
}
}
output.ClosePolygon();
}
output.Add(0, 0, ShapePath.FlagsAndCommand.CommandStop);
return output;
}
public static void PlaceMeshOnBed(List<Mesh> meshesList, List<Matrix4X4> meshTransforms, int index, bool alsoCenterXY = true)
{
AxisAlignedBoundingBox bounds = meshesList[index].GetAxisAlignedBoundingBox(meshTransforms[index]);
Vector3 boundsCenter = (bounds.maxXYZ + bounds.minXYZ) / 2;
if (alsoCenterXY)
{
meshTransforms[index] *= Matrix4X4.CreateTranslation(-boundsCenter + new Vector3(0, 0, bounds.ZSize / 2));
}
else
{
meshTransforms[index] *= Matrix4X4.CreateTranslation(new Vector3(0, 0, -boundsCenter.z + bounds.ZSize / 2));
}
}
public static void PlaceAllMeshesOnBed(List<Mesh> meshesList, List<Matrix4X4> meshTransforms)
{
for (int i = 0; i < meshesList.Count; i++)
{
PlaceMeshOnBed(meshesList, meshTransforms, i);
}
}
public static void CenterMeshesXY(List<Mesh> meshesList, List<Matrix4X4> meshTransforms)
{
bool first = true;
AxisAlignedBoundingBox totalBounds = new AxisAlignedBoundingBox(new Vector3(), new Vector3());
for(int index= 0; index<meshesList.Count; index++)
{
if(first)
{
totalBounds = meshesList[index].GetAxisAlignedBoundingBox(meshTransforms[index]);
first = false;
}
else
{
AxisAlignedBoundingBox bounds = meshesList[index].GetAxisAlignedBoundingBox(meshTransforms[index]);
totalBounds = AxisAlignedBoundingBox.Union(totalBounds, bounds);
}
}
Vector3 boundsCenter = (totalBounds.maxXYZ + totalBounds.minXYZ) / 2;
boundsCenter.z = 0;
for (int index = 0; index < meshesList.Count; index++)
{
meshTransforms[index] *= Matrix4X4.CreateTranslation(-boundsCenter);
}
}
public static void FindPositionForPartAndAddToPlate(Mesh meshToAdd, Matrix4X4 meshTransform, List<PlatingMeshData> perMeshInfo, List<Mesh> meshesToAvoid, List<Matrix4X4> meshTransforms)
{
if (meshToAdd == null || meshToAdd.Vertices.Count < 3)
{
return;
}
meshesToAvoid.Add(meshToAdd);
PlatingMeshData newMeshInfo = new PlatingMeshData();
perMeshInfo.Add(newMeshInfo);
meshTransforms.Add(meshTransform);
int index = meshesToAvoid.Count-1;
MoveMeshToOpenPosition(index, perMeshInfo, meshesToAvoid, meshTransforms);
PlaceMeshOnBed(meshesToAvoid, meshTransforms, index, false);
}
public static void MoveMeshToOpenPosition(int meshToMoveIndex, List<PlatingMeshData> perMeshInfo, List<Mesh> allMeshes, List<Matrix4X4> meshTransforms)
{
Mesh meshToMove = allMeshes[meshToMoveIndex];
// find a place to put it that doesn't hit anything
AxisAlignedBoundingBox meshToMoveBounds = meshToMove.GetAxisAlignedBoundingBox(meshTransforms[meshToMoveIndex]);
// add in a few mm so that it will not be touching
meshToMoveBounds.minXYZ -= new Vector3(2, 2, 0);
meshToMoveBounds.maxXYZ += new Vector3(2, 2, 0);
double ringDist = Math.Min(meshToMoveBounds.XSize, meshToMoveBounds.YSize);
double currentDist = 0;
double angle = 0;
double angleIncrement = MathHelper.Tau / 64;
Matrix4X4 transform;
while (true)
{
Matrix4X4 positionTransform = Matrix4X4.CreateTranslation(currentDist, 0, 0);
positionTransform *= Matrix4X4.CreateRotationZ(angle);
Vector3 newPosition = Vector3.Transform(Vector3.Zero, positionTransform);
transform = Matrix4X4.CreateTranslation(newPosition);
AxisAlignedBoundingBox testBounds = meshToMoveBounds.NewTransformed(transform);
bool foundHit = false;
for(int i=0; i<allMeshes.Count; i++)
{
Mesh meshToTest = allMeshes[i];
if (meshToTest != meshToMove)
{
AxisAlignedBoundingBox existingMeshBounds = meshToTest.GetAxisAlignedBoundingBox(meshTransforms[i]);
AxisAlignedBoundingBox intersection = AxisAlignedBoundingBox.Intersection(testBounds, existingMeshBounds);
if (intersection.XSize > 0 && intersection.YSize > 0)
{
foundHit = true;
break;
}
}
}
if (!foundHit)
{
break;
}
angle += angleIncrement;
if (angle >= MathHelper.Tau)
{
angle = 0;
currentDist += ringDist;
}
}
meshTransforms[meshToMoveIndex] *= transform;
}
public static void CreateITraceableForMesh(List<PlatingMeshData> perMeshInfo, List<Mesh> meshes, int i)
{
if (meshes[i] != null)
{
List<IRayTraceable> allPolys = new List<IRayTraceable>();
List<Vector3> positions = new List<Vector3>();
foreach (Face face in meshes[i].Faces)
{
positions.Clear();
foreach (Vertex vertex in face.VertexIterator())
{
positions.Add(vertex.Position);
}
// We should use the teselator for this if it is greater than 3.
Vector3 next = positions[1];
for (int positionIndex = 2; positionIndex < positions.Count; positionIndex++)
{
TriangleShape triangel = new TriangleShape(positions[0], next, positions[positionIndex], null);
allPolys.Add(triangel);
next = positions[positionIndex];
}
}
perMeshInfo[i].traceableData = BoundingVolumeHierarchy.CreateNewHierachy(allPolys);
}
}
}
}

View file

@ -0,0 +1,93 @@
/*
Copyright (c) 2013, Lars Brubaker
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 System.Collections.Generic;
using System.Linq;
using System.Text;
using MatterHackers.Agg;
using MatterHackers.Agg.Image;
using MatterHackers.Agg.UI;
using MatterHackers.Agg.OpenGlGui;
using MatterHackers.PolygonMesh;
using MatterHackers.RenderOpenGl;
using MatterHackers.VectorMath;
using MatterHackers.MeshVisualizer;
using MatterHackers.PolygonMesh.Processors;
using MatterHackers.PolygonMesh.Csg;
using MatterHackers.MarchingSquares;
using MatterHackers.MatterControl.DataStorage;
using MatterHackers.Agg.ImageProcessing;
using MatterHackers.Agg.VertexSource;
using MatterHackers.MatterControl.PrintQueue;
using MatterHackers.RayTracer;
using MatterHackers.RayTracer.Traceable;
namespace MatterHackers.MatterControl.PartPreviewWindow
{
public class ProgressControl : FlowLayoutWidget
{
GuiWidget bar;
public TextWidget textWidget;
int percentComplete;
public int PercentComplete
{
get { return percentComplete; }
set
{
if (value != percentComplete)
{
percentComplete = value;
Invalidate();
}
}
}
public ProgressControl(string message)
{
textWidget = new TextWidget(message, textColor: RGBA_Bytes.White);
textWidget.AutoExpandBoundsToText = true;
textWidget.Margin = new BorderDouble(5, 0);
AddChild(textWidget);
bar = new GuiWidget(80, 15);
bar.VAnchor = Agg.UI.VAnchor.ParentCenter;
AddChild(bar);
}
public override void OnDraw(Graphics2D graphics2D)
{
RectangleDouble barBounds = bar.BoundsRelativeToParent;
graphics2D.FillRectangle(barBounds.Left, barBounds.Bottom, barBounds.Left + barBounds.Width * PercentComplete / 100.0, barBounds.Top, ActiveTheme.Instance.PrimaryAccentColor);
graphics2D.Rectangle(barBounds, RGBA_Bytes.Black);
base.OnDraw(graphics2D);
}
}
}

File diff suppressed because it is too large Load diff