line draw with snap to grid 2

Upload: melekeen

Post on 04-Apr-2018

212 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/31/2019 Line Draw With Snap to Grid 2

    1/6

    1 using System;2 using System.Collections.Generic;3 using System.ComponentModel;4 using System.Data;5 using System.Drawing;6 using System.Linq;7 using System.Text;8 using System.Windows.Forms;9

    10 namespace howto_line_editor_snapgrid11 {12 public partial class Form1 : Form13 {14 public Form1()15 {16 InitializeComponent();17 }1819 // The grid spacing.20 const int grid_gap = 20;2122 // The "size" of an object for mouse over purposes.23 private const int object_radius = 3;24

    25 // We're over an object if the distance squared26 // between the mouse and the object is less than this.27 private const int over_dist_squared = object_radius * object_radius;2829 // The points that make up the line segments.30 private List Pt1 = new List();31 private List Pt2 = new List();3233 // Points for the new line.34 private bool IsDrawing = false;35 private Point NewPt1, NewPt2;3637 // The mouse is up. See whether we're over an end point or segment.38 private void picCanvas_MouseMove_NotDown(object sender, MouseEventArgs e)39 {

    40 Cursor new_cursor = Cursors.Cross;4142 // See what we're over.43 Point mouse_pt = new Point(e.X, e.Y);44 Point hit_point;45 int segment_number;4647 if (MouseIsOverEndpoint(mouse_pt, out segment_number, out hit_point))48 {49 new_cursor = Cursors.Arrow;50 }51 else if (MouseIsOverSegment(mouse_pt, out segment_number))52 {53 new_cursor = Cursors.Hand;54 }

    5556 // Set the new cursor.57 if (picCanvas.Cursor != new_cursor)58 {59 picCanvas.Cursor = new_cursor;60 }61 }6263 // See what we're over and start doing whatever is appropriate.64 private void picCanvas_MouseDown(object sender, MouseEventArgs e)65 {66 // See what we're over.67 Point mouse_pt = new Point(e.X, e.Y);68 Point hit_point;69 int segment_number;7071 if (MouseIsOverEndpoint(mouse_pt, out segment_number, out hit_point))72 {73 // Start moving this end point.

  • 7/31/2019 Line Draw With Snap to Grid 2

    2/6

    74 picCanvas.MouseMove -= picCanvas_MouseMove_NotDown;75 picCanvas.MouseMove += picCanvas_MouseMove_MovingEndPoint;76 picCanvas.MouseUp += picCanvas_MouseUp_MovingEndPoint;7778 // Remember the segment number.79 MovingSegment = segment_number;8081 // See if we're moving the start end point.82 MovingStartEndPoint = (Pt1[segment_number].Equals(hit_point));

    8384 // Remember the offset from the mouse to the point.85 OffsetX = hit_point.X - e.X;86 OffsetY = hit_point.Y - e.Y;87 }88 else if (MouseIsOverSegment(mouse_pt, out segment_number))89 {90 // Start moving this segment.91 picCanvas.MouseMove -= picCanvas_MouseMove_NotDown;92 picCanvas.MouseMove += picCanvas_MouseMove_MovingSegment;93 picCanvas.MouseUp += picCanvas_MouseUp_MovingSegment;9495 // Remember the segment number.96 MovingSegment = segment_number;97

    98 // Remember the offset from the mouse to the segment's first point.99 OffsetX = Pt1[segment_number].X - e.X;100 OffsetY = Pt1[segment_number].Y - e.Y;101 }102 else103 {104 // Start drawing a new segment.105 picCanvas.MouseMove -= picCanvas_MouseMove_NotDown;106 picCanvas.MouseMove += picCanvas_MouseMove_Drawing;107 picCanvas.MouseUp += picCanvas_MouseUp_Drawing;108109 IsDrawing = true;110111 int x = e.X;112 int y = e.Y;

    113 SnapToGrid(ref x, ref y);114 NewPt1 = new Point(x, y);115 NewPt2 = new Point(x, y);116 }117 }118119 // Snap to the nearest grid point.120 private void SnapToGrid(ref int x, ref int y)121 {122 if (!chkSnapToGrid.Checked) return;123 x = grid_gap * (int)Math.Round((double)x / grid_gap);124 y = grid_gap * (int)Math.Round((double)y / grid_gap);125 }126127 #region "Drawing"

    128129 // We're drawing a new segment.130 private void picCanvas_MouseMove_Drawing(object sender, MouseEventArgs e)131 {132 // Save the new point.133 int x = e.X;134 int y = e.Y;135 SnapToGrid(ref x, ref y);136 NewPt2 = new Point(x, y);137138 // Redraw.139 picCanvas.Invalidate();140 }141142 // Stop drawing.143 private void picCanvas_MouseUp_Drawing(object sender, MouseEventArgs e)144 {145 IsDrawing = false;146

  • 7/31/2019 Line Draw With Snap to Grid 2

    3/6

    147 // Reset the event handlers.148 picCanvas.MouseMove -= picCanvas_MouseMove_Drawing;149 picCanvas.MouseMove += picCanvas_MouseMove_NotDown;150 picCanvas.MouseUp -= picCanvas_MouseUp_Drawing;151152 // Create the new segment.153 Pt1.Add(NewPt1);154 Pt2.Add(NewPt2);155

    156 // Redraw.157 picCanvas.Invalidate();158 }159160 #endregion // Drawing161162 #region "Moving End Point"163164 // The segment we're moving or the segment whose end point we're moving.165 private int MovingSegment = -1;166167 // The end point we're moving.168 private bool MovingStartEndPoint = false;169170 // The offset from the mouse to the object being moved.

    171 private int OffsetX, OffsetY;172173 // We're moving an end point.174 private void picCanvas_MouseMove_MovingEndPoint(object sender, MouseEventArgs e)175 {176 // Move the point to its new location.177 int x = e.X + OffsetX;178 int y = e.Y + OffsetY;179 SnapToGrid(ref x, ref y);180181 if (MovingStartEndPoint)182 {183 Pt1[MovingSegment] = new Point(x, y);184 }185 else

    186 {187 Pt2[MovingSegment] = new Point(x, y);188 }189190 // Redraw.191 picCanvas.Invalidate();192 }193194 // Stop moving the end point.195 private void picCanvas_MouseUp_MovingEndPoint(object sender, MouseEventArgs e)196 {197 // Reset the event handlers.198 picCanvas.MouseMove += picCanvas_MouseMove_NotDown;199 picCanvas.MouseMove -= picCanvas_MouseMove_MovingEndPoint;200 picCanvas.MouseUp -= picCanvas_MouseUp_MovingEndPoint;

    201202 // Redraw.203 picCanvas.Invalidate();204 }205206 #endregion // Moving End Point207208 #region "Moving Segment"209210 // We're moving a segment.211 private void picCanvas_MouseMove_MovingSegment(object sender, MouseEventArgs e)212 {213 // See how far the first point will move.214 int x = e.X + OffsetX;215 int y = e.Y + OffsetY;216 SnapToGrid(ref x, ref y);217218 int dx = x - Pt1[MovingSegment].X;219 int dy = y - Pt1[MovingSegment].Y;

  • 7/31/2019 Line Draw With Snap to Grid 2

    4/6

    220221 if (dx == 0 && dy == 0) return;222223 // Move the segment to its new location.224 Pt1[MovingSegment] = new Point(x, y);225 Pt2[MovingSegment] = new Point(226 Pt2[MovingSegment].X + dx,227 Pt2[MovingSegment].Y + dy);228

    229 // Redraw.230 picCanvas.Invalidate();231 }232233 // Stop moving the segment.234 private void picCanvas_MouseUp_MovingSegment(object sender, MouseEventArgs e)235 {236 // Reset the event handlers.237 picCanvas.MouseMove += picCanvas_MouseMove_NotDown;238 picCanvas.MouseMove -= picCanvas_MouseMove_MovingSegment;239 picCanvas.MouseUp -= picCanvas_MouseUp_MovingSegment;240241 // Redraw.242 picCanvas.Invalidate();243 }

    244245 #endregion // Moving End Point246247 // See if the mouse is over an end point.248 private bool MouseIsOverEndpoint(Point mouse_pt, out int segment_number, out Point hit_pt)249 {250 for (int i = 0; i < Pt1.Count; i++)251 {252 // Check the starting point.253 if (FindDistanceToPointSquared(mouse_pt, Pt1[i]) < over_dist_squared)254 {255 // We're over this point.256 segment_number = i;257 hit_pt = Pt1[i];258 return true;

    259 }260261 // Check the end point.262 if (FindDistanceToPointSquared(mouse_pt, Pt2[i]) < over_dist_squared)263 {264 // We're over this point.265 segment_number = i;266 hit_pt = Pt2[i];267 return true;268 }269 }270271 segment_number = -1;272 hit_pt = new Point(-1, -1);273 return false;

    274 }275276 // See if the mouse is over a line segment.277 private bool MouseIsOverSegment(Point mouse_pt, out int segment_number)278 {279 for (int i = 0; i < Pt1.Count; i++)280 {281 // See if we're over the segment.282 PointF closest;283 if (FindDistanceToSegmentSquared(284 mouse_pt, Pt1[i], Pt2[i], out closest)285 < over_dist_squared)286 {287 // We're over this segment.288 segment_number = i;289 return true;290 }291 }292

  • 7/31/2019 Line Draw With Snap to Grid 2

    5/6

    293 segment_number = -1;294 return false;295 }296297 // Calculate the distance squared between two points.298 private int FindDistanceToPointSquared(Point pt1, Point pt2)299 {300 int dx = pt1.X - pt2.X;301 int dy = pt1.Y - pt2.Y;

    302 return dx * dx + dy * dy;303 }304305 // Calculate the distance squared between306 // point pt and the segment p1 --> p2.307 private double FindDistanceToSegmentSquared(Point pt, Point p1, Point p2, out PointF

    closest)308 {309 float dx = p2.X - p1.X;310 float dy = p2.Y - p1.Y;311 if ((dx == 0) && (dy == 0))312 {313 // It's a point not a line segment.314 closest = p1;315 dx = pt.X - p1.X;

    316 dy = pt.Y - p1.Y;317 return dx * dx + dy * dy;318 }319320 // Calculate the t that minimizes the distance.321 float t = ((pt.X - p1.X) * dx + (pt.Y - p1.Y) * dy) / (dx * dx + dy * dy);322323 // See if this represents one of the segment's324 // end points or a point in the middle.325 if (t < 0)326 {327 closest = new PointF(p1.X, p1.Y);328 dx = pt.X - p1.X;329 dy = pt.Y - p1.Y;330 }

    331 else if (t > 1)332 {333 closest = new PointF(p2.X, p2.Y);334 dx = pt.X - p2.X;335 dy = pt.Y - p2.Y;336 }337 else338 {339 closest = new PointF(p1.X + t * dx, p1.Y + t * dy);340 dx = pt.X - closest.X;341 dy = pt.Y - closest.Y;342 }343344 return dx * dx + dy * dy;345 }

    346347 // Draw the lines.348 private void picCanvas_Paint(object sender, PaintEventArgs e)349 {350 // Draw the segments.351 for (int i = 0; i < Pt1.Count; i++)352 {353 // Draw the segment.354 e.Graphics.DrawLine(Pens.Blue, Pt1[i], Pt2[i]);355 }356357 // Draw the end points.358 foreach (Point pt in Pt1)359 {360 Rectangle rect = new Rectangle(361 pt.X - object_radius, pt.Y - object_radius,362 2 * object_radius + 1, 2 * object_radius + 1);363 e.Graphics.FillEllipse(Brushes.White , rect);364 e.Graphics.DrawEllipse(Pens.Black, rect);

  • 7/31/2019 Line Draw With Snap to Grid 2

    6/6

    365 }366 foreach (Point pt in Pt2)367 {368 Rectangle rect = new Rectangle(369 pt.X - object_radius, pt.Y - object_radius,370 2 * object_radius + 1, 2 * object_radius + 1);371 e.Graphics.FillEllipse(Brushes.White , rect);372 e.Graphics.DrawEllipse(Pens.Black, rect);373 }

    374375 // If there's a new segment under constructions, draw it.376 if (IsDrawing)377 {378 e.Graphics.DrawLine(Pens.Red, NewPt1, NewPt2);379 }380 }381382 // Give the PictureBox a grid background.383 private void picCanvas_Resize(object sender, EventArgs e)384 {385 MakeBackgroundGrid();386 }387 private void chkSnapToGrid_CheckedChanged(object sender, EventArgs e)388 {

    389 MakeBackgroundGrid();390 }391 private void MakeBackgroundGrid()392 {393 if (!chkSnapToGrid.Checked)394 {395 picCanvas.BackgroundImage = null;396 }397 else398 {399 Bitmap bm = new Bitmap(400 picCanvas.ClientSize.Width,401 picCanvas.ClientSize.Height);402 for (int x = 0; x < picCanvas.ClientSize.Width; x += grid_gap)403 {

    404 for (int y = 0; y < picCanvas.ClientSize.Height; y += grid_gap)405 {406 bm.SetPixel(x, y, Color.Black);407 }408 }409410 picCanvas.BackgroundImage = bm;411 }412 }413 }414 }415