# Implementing a 2d Selection Box

I'm in the process of implementing a selection box for my simulation and am having difficulty with something which appears simple. At the moment, I can draw the selection box and accurately select the items under it, provided the box was dragged from the top-left-hand corner downwards:

If I start dragging the box from any other point the rectangle doesn't correspond to that of the viewport, as demonstrated by the negative width and height.

Here is my code:

// selectionBox is Rectangle

if (mouse.LeftButton == ButtonState.Pressed && prevMouse.LeftButton == ButtonState.Pressed)
{
if (selecting)
{
selectionBox.Width = mouse.X - selectionBox.X;
selectionBox.Height = mouse.Y - selectionBox.Y;
}
else
{
selecting = true;
selectionBox.X = mouse.X;
selectionBox.Y = mouse.Y;
}
}

// Code to handle selection finished omitted

// Drawing code
if (selecting)
{
DrawingHelper.DrawRectangle(selectionBox, Color.Yellow, false);
DrawingHelper.DrawRectangle(new Rectangle(startPoint.X - 4, startPoint.Y - 4, 8, 8), Color.Red, true);
}


How can I adjust the X, Y, Width and Height of my selection box so that X and Y are always the top-left of the selection box no matter where the selection began?

• The width and height just need to be absolute values to get their true values. As for the X, Y, are you wanting that to always correspond to the top left of the selection? Or what's the current problem with it? – MichaelHouse Sep 5 '13 at 13:34
• Yes that's correct I'd like for X and Y to always correspond with the top left of the selection. – aligray Sep 5 '13 at 13:40

For the width and height, you can just get the absolute value of the difference between the mouse and the start of the box.

selectionBox.Width = Math.Abs(mouse.X - selectionBox.X);
selectionBox.Height = Math.Abs(mouse.Y - selectionBox.Y);


As for the X and Y, you'll need to maintain two values if you want them to always correspond to the top left. Something like startPoint.

if (selecting)
{
selectionBox.Width = Math.Abs(mouse.X - startPoint.X);
selectionBox.Height = Math.Abs(mouse.Y - startPoint.Y);
//Set the start point to the top left, which is the minimum X and minimum Y
//Choose between the start point and the current mouse position
selectionBox.X = Math.Min(startPoint.X, mouse.X);
selectionBox.Y = Math.Min(startPoint.Y, mouse.Y);
}
else
{
selecting = true;
startPoint.X = mouse.X;
startPoint.Y = mouse.Y;
selectionBox.X = mouse.X;
selectionBox.Y = mouse.Y;
}


Now when you're done with the box, it'll be as if the user started at the upper left and ended in the bottom right, no matter where they actually started/ended.

• This gives very strange results indeed: imgur.com/Lipm5Fl. Is this the same principle as games such as Command & Conquer use? – aligray Sep 5 '13 at 14:07
• Oops, I believe the X, Y should have been the start point plus the non absolute value of the width/height. Try that edited code. – MichaelHouse Sep 5 '13 at 14:30
• startPoint.X + (mouse.X - startPoint.X) == mouse.X; ... your code could be a lot easier to read and still get the exact same numerical result – MickLH Sep 5 '13 at 14:52
• @MickLH Yep, same result, I thought that version might give more understanding as to what we're actually looking at. But I'll make it easier to read with some explanation. – MichaelHouse Sep 5 '13 at 15:48
• @aligray Typically one would just get the min and max world coordinates of the selection box. Then use those coordinates for a bounding box where you can do your contains checks or whatever you're doing with the selection box. – MichaelHouse Sep 5 '13 at 16:11