3d print stl file for circuit

Eduardo Gomez Romero 1,335 Reputation points
2025-03-04T22:38:04.7366667+00:00

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

https://imagetostl.com/view-stl-online

Windows App SDK
Windows App SDK
A set of Microsoft open-source libraries, frameworks, components, and tools to be used in apps to access Windows platform functionality on many versions of Windows. Previously known as Project Reunion.
838 questions
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.