3d print stl file for circuit
Eduardo Gomez Romero
1,335
Reputation points
Hello
I have an app made in winUI, for making lines on a canvas, but I need some help. I need to be able to save this file in STL formal (for 3d printing)
ViewModel
using System.Linq;
namespace NanoFlow.ViewModels {
public partial class MainViewModel : ObservableObject {
private readonly int gridSpacing = 20; // Spacing between grid lines in pixels
private bool _areGridMarginsAdded = false;
private readonly List<Line> _gridMarginLines = []; // To track grid lines
private readonly List<TextBlock> _gridTextBlocks = [];
private readonly ObservableCollection<PointModel> Points = [];
private readonly ObservableCollection<LineModel> Lines = [];
private readonly List<PointModel> _selectedPoints = [];
private Grid? _rootContainer;
private Canvas? _canvas;
private PointModel? _previousPoint;
public void SetRootContainer(object sender, RoutedEventArgs args) {
_rootContainer = sender as Grid;
}
[RelayCommand]
void CreateNewDesign() {
DrawCanvas();
if(_canvas != null) {
_canvas!.PointerPressed += Canvas_PointerPressed;
_canvas.PointerMoved += Canvas_PointerMoved;
_canvas.PointerReleased += Canvas_PointerReleased;
}
}
[RelayCommand]
async Task GuidedProcessAsync() {
Points.Clear();
DrawCanvas();
var dlg = new ContentDialog {
XamlRoot = _rootContainer?.XamlRoot,
Title = "Select point to draw",
PrimaryButtonText = "Ok"
};
GridView gridView = new() {
Width = 400,
Height = 600
};
for(int i = 0; i < _canvas!.Width; i += gridSpacing) {
for(int j = 0; j < _canvas.Height; j += gridSpacing) {
var point = new PointModel(i, j);
var checkBox = new CheckBox {
Content = $"Point ({point.X / 20},{point.Y / 20})",
IsChecked = false, // Default to unchecked
Tag = point,
};
checkBox.Checked += GuidCheckBox_CheckedChanged;
checkBox.Unchecked += GuidCheckBox_CheckedChanged;
gridView.Items.Add(checkBox);
}
}
dlg.Content = gridView;
var response = await dlg.ShowAsync();
if(response == ContentDialogResult.Primary && _selectedPoints.Count > 1) {
for(int i = 0; i < _selectedPoints.Count - 1; i++) {
var startPoint = new PointModel(_selectedPoints[i].X * gridSpacing, _selectedPoints[i].Y * gridSpacing);
var endPoint = new PointModel(_selectedPoints[i + 1].X * gridSpacing, _selectedPoints[i + 1].Y * gridSpacing);
DrawLine(startPoint, endPoint);
}
}
}
[RelayCommand]
void AddMargin() {
if(_canvas == null) {
return;
}
if(_areGridMarginsAdded) {
RemoveGridMarginsAndTextBlocks();
_areGridMarginsAdded = false;
}
else {
DrawGridMarginsAndTextBlocks();
_areGridMarginsAdded = true;
}
}
private void RemoveGridMarginsAndTextBlocks() {
var allItems = _gridMarginLines.Cast<UIElement>()
.Concat(_gridTextBlocks.Cast<UIElement>())
.ToList();
foreach(var element in allItems) {
_canvas!.Children.Remove(element);
}
// Clear both lists afterward
_gridMarginLines.Clear();
_gridTextBlocks.Clear();
}
private void GuidCheckBox_CheckedChanged(object sender, RoutedEventArgs e) {
if(sender is CheckBox checkBox && checkBox.Tag is PointModel point) {
var correctedPoint = new PointModel(point.X / gridSpacing, point.Y / gridSpacing);
if(checkBox.IsChecked == true) {
_selectedPoints.Add(correctedPoint);
}
else {
_selectedPoints.Remove(correctedPoint);
}
}
}
private void DrawCanvas() {
_canvas = new Canvas {
Background = new SolidColorBrush(Color.FromArgb(255, 0, 128, 0)),
Width = 378,
Height = 378,
};
if(_rootContainer != null) {
_rootContainer.Children.Add(_canvas);
Grid.SetRow(_canvas, 1);
}
}
private void DrawGridMarginsAndTextBlocks() {
for(int i = 0; i < _canvas!.Width; i += gridSpacing) {
for(int j = 0; j < _canvas.Height; j += gridSpacing) {
// Draw vertical and horizontal lines crossing at intersections
if(i == 0) {
var horizontalLine = new Line {
X1 = 0,
Y1 = j,
X2 = _canvas.Width,
Y2 = j,
Stroke = new SolidColorBrush(Colors.Gray),
StrokeThickness = 1
};
_canvas.Children.Add(horizontalLine);
_gridMarginLines.Add(horizontalLine);
}
if(j == 0) {
var verticalLine = new Line {
X1 = i,
Y1 = 0,
X2 = i,
Y2 = _canvas.Height,
Stroke = new SolidColorBrush(Colors.Gray),
StrokeThickness = 1
};
_canvas.Children.Add(verticalLine);
_gridMarginLines.Add(verticalLine);
}
// Add a TextBlock at each intersection
var textBlock = new TextBlock {
Text = $"({i / gridSpacing},{j / gridSpacing})",
Foreground = new SolidColorBrush(Colors.Black),
FontSize = 6
};
Canvas.SetLeft(textBlock, i + 2); // Position slightly offset for visibility
Canvas.SetTop(textBlock, j + 2);
_canvas.Children.Add(textBlock);
_gridTextBlocks.Add(textBlock);
}
}
}
private void DrawLine(PointModel startPoint, PointModel endPoint) {
var line = new Line {
X1 = startPoint.X,
Y1 = startPoint.Y,
X2 = endPoint.X,
Y2 = endPoint.Y,
Stroke = new SolidColorBrush(Colors.White),
StrokeThickness = 2,
};
_canvas!.Children.Add(line);
Lines.Add(new LineModel(startPoint, endPoint));
}
private void Canvas_PointerReleased(object sender, PointerRoutedEventArgs e) {
_previousPoint = null;
}
private void Canvas_PointerMoved(object sender, PointerRoutedEventArgs e) {
if(_previousPoint != null && e.Pointer.IsInContact) {
var position = e.GetCurrentPoint(_canvas).Position;
var currentPoint = new PointModel(position.X, position.Y);
DrawLine(_previousPoint, currentPoint);
_previousPoint = currentPoint;
}
}
private void Canvas_PointerPressed(object sender, PointerRoutedEventArgs e) {
var position = e.GetCurrentPoint(_canvas).Position;
var currentPoint = new PointModel(position.X, position.Y);
_previousPoint = currentPoint;
Points.Add(currentPoint);
var ellipse = new Ellipse {
Width = 4,
Height = 4,
Fill = new SolidColorBrush(Colors.Red)
};
Canvas.SetLeft(ellipse, currentPoint.X - 2);
Canvas.SetTop(ellipse, currentPoint.Y - 2);
_canvas!.Children.Add(ellipse);
// Connect to the previous point with a line if there is one
if(Points.Count > 1) {
var previousPoint = Points[^2];
DrawLine(previousPoint, currentPoint);
}
}
}
}
XAML
<Window
x:Class="NanoFlow.Views.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:NanoFlow.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:ribbon="using:Syncfusion.UI.Xaml.Ribbon"
xmlns:vm="using:NanoFlow.ViewModels"
Title="MainWindow"
mc:Ignorable="d">
<Grid
x:Name="SetRootContainer"
Loaded="{x:Bind ViewModel.SetRootContainer}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ribbon:SfRibbon
ActiveLayoutMode="Simplified"
ShowBackstageMenuButton="False">
<ribbon:SfRibbon.Tabs>
<ribbon:RibbonTab Header="File">
<ribbon:RibbonGroup Header="Desings">
<ribbon:RibbonButton
AllowedSizeModes="Large"
Command="{x:Bind ViewModel.CreateNewDesignCommand}"
Content="New"
ToolTipService.ToolTip="Create new desing">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="Add" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
<ribbon:RibbonButton
AllowedSizeModes="Large"
Content="Open"
ToolTipService.ToolTip="OpenDesign">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="OpenFile" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
<ribbon:RibbonButton
AllowedSizeModes="Large"
Content="save"
ToolTipService.ToolTip="Save design">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="Save" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
<ribbon:RibbonButton
AllowedSizeModes="Large"
Content="Share"
ToolTipService.ToolTip="Save">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="Share" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
</ribbon:RibbonGroup>
<ribbon:RibbonGroup Header="Help">
<ribbon:RibbonButton
AllowedSizeModes="Large"
Command="{x:Bind ViewModel.GuidedProcessCommand}"
Content="Guided Process"
ToolTipService.ToolTip="imput coordinates and the app will create the lines">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="Repair" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
<ribbon:RibbonButton
AllowedSizeModes="Large"
Command="{x:Bind ViewModel.AddMarginCommand}"
Content="Guided Process"
ToolTipService.ToolTip="imput coordinates and the app will create the lines">
<ribbon:RibbonButton.Icon>
<SymbolIcon Symbol="ViewAll" />
</ribbon:RibbonButton.Icon>
</ribbon:RibbonButton>
</ribbon:RibbonGroup>
</ribbon:RibbonTab>
</ribbon:SfRibbon.Tabs>
</ribbon:SfRibbon>
</Grid>
</Window>
To open in a stp app opener like cimco, blender or opening here
Sign in to answer