Canvas math problem

Eduardo Gomez Romero 1,255 Reputation points
2025-02-27T15:49:23.9166667+00:00

User's image I have this Canvas that is 100 mm x 100 mm

the problem is that when I draw a line es calculating bad (or I'm the bad one)

if I select 0,0 and 18,18. I shod have

23zyu6u7

but for some reason I get

User's image

this is the code

 private readonly ObservableCollection<PointModel> Points = [];
 private readonly ObservableCollection<LineModel> Lines = [];
 private readonly List<PointModel> _selectedPoints = [];
 private Grid? _rootContainer;
 private Canvas? _canvas;
 private PointModel? _previousPoint;
 private readonly int gridSpacing = 20; // Spacing between grid lines in pixels
 public void SetRootContainer(object sender, RoutedEventArgs args) {
     _rootContainer = sender as Grid;
 }
 [RelayCommand]
 void CreateNewDesign() {
     DrawCanvas();
     _canvas!.PointerPressed += Canvas_PointerPressed;
     _canvas.PointerMoved += Canvas_PointerMoved;
     _canvas.PointerReleased += Canvas_PointerReleased;
 }
 [RelayCommand]
 async Task GuidedProcessAsync() {
     Points.Clear();
     DrawCanvas();
     // Add labels at the intersection points 
     ContentDialog dlg = new() {
         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) {
         if(_selectedPoints.Count > 1) {
             for(int i = 0; i < _selectedPoints.Count - 1; i++) {
                 DrawLine(_selectedPoints[i], _selectedPoints[i + 1]);
             }
         }
     }
 }
 private void GuidCheckBox_CheckedChanged(object sender, RoutedEventArgs e) {
     var checkBox = sender as CheckBox;
     var point = checkBox?.Tag as PointModel;
     if(point != null) {
         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,
     };
     _rootContainer!.Children.Add(_canvas);
     Grid.SetRow(_canvas, 1);
 }
 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);
     }
 }
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,833 questions
{count} votes

1 answer

Sort by: Most helpful
  1. Hongrui Yu-MSFT 4,605 Reputation points Microsoft Vendor
    2025-02-28T02:26:50.55+00:00

    Hi, @Eduardo Gomez Romero. Welcome to Microsoft Q&A. 

    Cause of error: The points in _selectedPoints are divided by gridSpacing in GuidCheckBox_CheckedChanged, and then the lines are drawn using the points in _selectedPoints. However, the actual drawn position should not be divided by gridSpacing.

    Solution: Before drawing, convert to the points required for drawing. Adjust the code at the following position in GuidedProcessAsync

    Picture2 To

                if (response == ContentDialogResult.Primary)
                {
                    if (_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);
                        }
                    }
                }
    

    Of course, if there is no special need, you could also not divide the points in _selectedPoints by gridSpacing in GuidCheckBox_CheckedChanged.

    Test results: Picture1


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    0 comments No comments

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.