Let the user draw and move line segments snapping their positions to a snap grid in C#

Draw and move line segments snapping to a grid

See the example Draw and move line segments in C# for basic information about the program. This example does the same thing, but lets you snap segments and end points to a grid.

When the drawing PictureBox is resized or when the “Snap To Grid” checkbox is checked or unchecked, the program calls the MakeBackgroundGrid method shown in the following code.

private void MakeBackgroundGrid()
    if (!chkSnapToGrid.Checked)
        picCanvas.BackgroundImage = null;
        Bitmap bm = new Bitmap(
        for (int x = 0; x < picCanvas.ClientSize.Width;
            x += grid_gap)
            for (int y = 0; y < picCanvas.ClientSize.Height;
                y += grid_gap)
                bm.SetPixel(x, y, Color.Black);

        picCanvas.BackgroundImage = bm;

If the checkbox is not checked, this method sets the picCanvas control’s background to null. Otherwise it makes a bitmap to fit the PictureBox, draws dots on it to show the grid, and sets the PictureBox‘s BackgroundImage property to the bitmap.

The other change to the program is how it handles new points. Whenever the program is about to do something with a point, it calls the following SnapToGrid method to snap that point’s coordinates to the grid (if appropriate).

// Snap to the nearest grid point.
private void SnapToGrid(ref int x, ref int y)
    if (!chkSnapToGrid.Checked) return;
    x = grid_gap * (int)Math.Round((double)x / grid_gap);
    y = grid_gap * (int)Math.Round((double)y / grid_gap);

This method rounds its x and y parameters to the nearest multiples of the grid’s size.

The following code shows an example of how the program uses the SnapToGrid method. This event handler executes when the user is moving a segment’s end point.

// We're moving an end point.
private void picCanvas_MouseMove_MovingEndPoint(
    object sender, MouseEventArgs e)
    // Move the point to its new location.
    int x = e.X + OffsetX;
    int y = e.Y + OffsetY;
    SnapToGrid(ref x, ref y);

    if (MovingStartEndPoint)
        Pt1[MovingSegment] = new Point(x, y);
        Pt2[MovingSegment] = new Point(x, y);

    // Redraw.

The code gets the mouse’s X and Y coordinates and calls SnapToGrid to snap to the nearest grid location. It then updates the appropriate segment end point (start point or end point) and redraws the PictureBox.

See the previous example for more details.

Download Example   Follow me on Twitter   RSS feed   Donate

This entry was posted in algorithms, drawing, graphics, mathematics and tagged , , , , , , , , , , , , , , , , , . Bookmark the permalink.

9 Responses to Let the user draw and move line segments snapping their positions to a snap grid in C#

  1. Pingback: Draw and move polygons snapping them to a grid in C# -

  2. rata says:

    Hi and thanks for the example! How can I ctrl+click to select and move multiple lines segments at once (change position, not start/end points of the line)? I’ve tried moving them but I don’t know how to calculate position of the second selected line, it always snaps to the first selected line, since the mouse position starts at the first selected line.

    Thanks a lot!

    • RodStephens says:

      Sorry but this example can’t do that. It’s a bit more complicated. You need to make a list of selected objects. Then you need to provide mouse events to manage the list. For example, Shift+Click adds a point to the list, Ctrl+Click toggles a point, click-and-drag selects multiple points, Shift+click-and-drag adds multiple points, etc.

      Then when the user clicks-and-drags a selected point, the program needs to move them all.

  3. Javier says:

    Thank you for sharing the code. I need to draw a rectangle on a surface with grid lines, and snap the rectangle corners to the nearest points. This is to model a wall with door and window openings. Could you please indicate what would need to be changed in your example? Thank you.

    • RodStephens says:

      It might be as simple as changing the code that draws the lines so it draws a rectangle instead. That wouldn’t be quite perfect because you could still only move two of the rectangle’s corners (the ones that correspond to the line segment’s end points), but it would be relatively easy.

      A more thorough approach would look for mouse events on all four corners and the edges. The following WPF example should give you an idea of what’s involved.

      Let the user move and resize a rectangle in WPF and C#

  4. Bret says:

    Thank you for this example. I have adapted it for my program, however, it isn’t working quite right. Instead of a line endpoint, I am moving a button control. However, it “vibrates” around the mouse cursor until I stop holding the mouse button down. AND, I don’t think it is sticking to a multiple of my grid width.

    I’d like to be able to move the mouse cursor and then have the control “snap” to the next grid square once the mouse has passed the halfway mark. I know I have not let a lot of information, but can you point me towards a resource perhaps or do you perhaps have any ideas?

    Thank you.

    • RodStephens says:

      As you say, that’s not a lot of information. Are you using the button’s mouse events? That could cause problems because, when you move the button, the mouse’s position is moved relative to the button’s upper left corner.

      You might try not moving the button. Instead move a rectangle until the user drops it and then move the button to that position.

  5. Serkan Ozkan says:

    Another not working examples…

    • RodStephens says:

      I hate to be snarky, but obviously the example works. Did you think I used MS Paint or something to draw a fake example? Why on earth would anyone do that? And the comments show that the example works for other people.

      The examples all work. If they don’t work for you, then you did something strange like using the wrong version of Visual Studio or copying and pasting the text without downloading the example program.

      DOWNLOAD THE EXAMPLE PROGRAM. Then if it doesn’t work as you want it to work, let us know what it’s doing wrong.

Comments are closed.