draw rectangle at x degrees angle WPF

# draw rectangle at x degrees angle WPF

• Monday, May 28, 2012 4:30 PM

anyone please help me with this newbie WPF drawing problem - i've spend hours googleing at drawing rectangle in wpf but nothing i saw was helpful. so hoping to get a quick easy to understand tutorial / answer here without scarifying much more of my times.

all i want is to be able to draw a rectangle by given two points.

p1(x,y) and p2(x,y)

maybe with the setting width and thickness of the rectangle, too.

now, those p1 and p2 give me a Cartesian angle, and, i want to draw the rectangle at that angle.

an illustrated example is in the pic below.

thanks for any help

• Edited by Monday, May 28, 2012 4:30 PM
•

### All Replies

• Monday, May 28, 2012 4:52 PM

Hi,

if you use a Canvas and the Shapes-Rectangle you could do something like:

Point p1 = new Point(100, 200);
Point p2 = new Point(400, 20);

private void button1_Click(object sender, RoutedEventArgs e)
{
Vector v = p2 - p1;
double width = Math.Sqrt(v.X * v.X + v.Y * v.Y);
double cos_w = v.X / width;
double w = w_rad * 180.0 / Math.PI;

Rectangle r = new Rectangle();
r.Width = width;

//this is set by "hand"; I dont know which value you want to have here
r.Height = 50;
r.SetValue(Canvas.LeftProperty, p1.X);
r.SetValue(Canvas.TopProperty, p1.Y - r.Height / 2.0);

r.Stroke = new SolidColorBrush(Colors.Red);
r.StrokeThickness = 2;
r.RenderTransform = new RotateTransform(-w, 0, r.Height / 2.0);

//draw the two points:
Ellipse e1 = new Ellipse();
e1.Width = 4;
e1.Height = 4;
e1.SetValue(Canvas.LeftProperty, p1.X - 2.0);
e1.SetValue(Canvas.TopProperty, p1.Y - 2.0);

Ellipse e2 = new Ellipse();
e2.Width = 4;
e2.Height = 4;
e2.SetValue(Canvas.LeftProperty, p2.X - 2.0);
e2.SetValue(Canvas.TopProperty, p2.Y - 2.0);

e1.Stroke = e2.Stroke = new SolidColorBrush(Colors.Blue);
e1.StrokeThickness = e2.StrokeThickness = 2;
}

The Xaml (without the Window-Tag):

<Canvas Name="canvas1">
<Button Canvas.Left="384" Canvas.Top="245" Content="Button" Height="23" Name="button1" Width="75" Click="button1_Click" />
</Canvas>

Regards,

Thorsten

• Marked As Answer by Tuesday, May 29, 2012 6:08 PM
•
• Monday, May 28, 2012 5:00 PM

Hi Thorsten,

I see the code you give works in buttonClick event. can this be done in a non-event way?

I mean, I just want a DrawRecFunction();

• Monday, May 28, 2012 5:36 PM

Hi,

public partial class MainWindow : Window
{
Point p1 = new Point(100, 200);
Point p2 = new Point(400, 20);
Rectangle r = new Rectangle();
Ellipse e1 = new Ellipse();
Ellipse e2 = new Ellipse();

public MainWindow()
{
InitializeComponent();
}

private void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
p1 = e.GetPosition(canvas1);
DrawRect();
}

private void Canvas_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
{
p2 = e.GetPosition(canvas1);
DrawRect();
}

private void DrawRect()
{
Vector v = p2 - p1;
double width = Math.Sqrt(v.X * v.X + v.Y * v.Y);
double cos_w = v.X / width;
double w = w_rad * 180.0 / Math.PI;

if (p2.Y < p1.Y)
w = -w;

r.Width = width;

//this is set by "hand"; I dont know which value you want to have here
r.Height = 50;
r.SetValue(Canvas.LeftProperty, p1.X);
r.SetValue(Canvas.TopProperty, p1.Y - r.Height / 2.0);

r.Stroke = new SolidColorBrush(Colors.Red);
r.StrokeThickness = 2;
r.RenderTransform = new RotateTransform(w, 0, r.Height / 2.0);

//draw the two points:
e1.Width = 4;
e1.Height = 4;
e1.SetValue(Canvas.LeftProperty, p1.X - 2.0);
e1.SetValue(Canvas.TopProperty, p1.Y - 2.0);

e2.Width = 4;
e2.Height = 4;
e2.SetValue(Canvas.LeftProperty, p2.X - 2.0);
e2.SetValue(Canvas.TopProperty, p2.Y - 2.0);

e1.Stroke = e2.Stroke = new SolidColorBrush(Colors.Blue);
e1.StrokeThickness = e2.StrokeThickness = 2;

if (canvas1.Children.Contains(r) == false)
{
}
}
}

and the Xaml:

<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas MouseLeftButtonDown="Canvas_MouseLeftButtonDown" MouseRightButtonDown="Canvas_MouseRightButtonDown" Name="canvas1"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Aqua">

</Canvas>
</Window>

This will add a rectangle (if it doesnt exist as canvas child) and the two points when clicking. So you can call the method to adjust the rectangle whenever needed...

A different way was to create your own drawing surface (maybe derviving from canvas) and add/remove visual childs to that.

Regards,

Thorsten

• Monday, May 28, 2012 5:53 PM

Hi Thorsten,

Thank you for your effort trying helping me here.

but, that is not what i really want to have for my project; though, i am sure someone else would find the code helpful to them.

what I need is to be able to draw a rectangle from the p1 and p2. also, i am going to draw a lot of rectangles on my Canvas. So, that was what i meant in my previous comment. What I need is a generic function that does the drawing rectangle by having me giving the p1 and p2. and, once I hit the run button in VS, I want to see the rectangle display there, with no mouse click.

I might be a heck here, but don't get me wrong. I am very appreciate your help.

• Monday, May 28, 2012 6:07 PM

... so maybe make a method aout of the code like:

//the height is used as in your picture, so, that the points are
//in the middle of the short sides...
private void DrawRect(Canvas c, Rectangle r, Point p1, Point p2, double height)
{
Vector v = p2 - p1;
double width = Math.Sqrt(v.X * v.X + v.Y * v.Y);
double cos_w = v.X / width;
double w = w_rad * 180.0 / Math.PI;

if (p2.Y < p1.Y)
w = -w;

r.Width = width;

//this is set by "hand"; I dont know which value you want to have here
r.Height = height;
r.SetValue(Canvas.LeftProperty, p1.X);
r.SetValue(Canvas.TopProperty, p1.Y - r.Height / 2.0);

r.Stroke = new SolidColorBrush(Colors.Red);
r.StrokeThickness = 2;
r.RenderTransform = new RotateTransform(w, 0, r.Height / 2.0);

//maybe remove this
if (c.Children.Contains(r) == false)
{
}
}

and call it whenever needed...

DrawRect(canvas1, new Rectangle(), p1, p2, 50);

But think of making your own design-surface here (as I mentioned above). If you really will have a lot (thousands of) rectangles, the way using drawingVisuals instead of Shape-Controls will be more performant. And you can handle all visuals in one class, so the code will stay somewhat more tidy.

Regards,

Thorsten

• Monday, May 28, 2012 6:31 PM

Thank you Thorsten, that is exactly what I was looking for!!

Though, if you can help me understanding your code would be helpful to me, and to other. can you comment the lines in your code?

• Monday, May 28, 2012 6:43 PM

Hi,

//the height is used as in your picture, so, that the points are
//in the middle of the short sides...
private void DrawRect(Canvas c, Rectangle r, Point p1, Point p2, double height)
{
//get distances
Vector v = p2 - p1;
double width = Math.Sqrt(v.X * v.X + v.Y * v.Y);

//get the angle (relation of triangle sides will give the cosine in radians)
double cos_w = v.X / width;
double w = w_rad * 180.0 / Math.PI;

// clockwisw / non clockwise
if (p2.Y < p1.Y)
w = -w;

//set the width
r.Width = width;

//the height
//this is set by "hand"; I dont know which value you want to have here
r.Height = height;

//set the Location of the Rectangle relative to the containing Canvas
r.SetValue(Canvas.LeftProperty, p1.X);
r.SetValue(Canvas.TopProperty, p1.Y - r.Height / 2.0);

//Stroke-Color and Thickness
r.Stroke = new SolidColorBrush(Colors.Red);
r.StrokeThickness = 2;

//now do the rotation with a RenderTransform (pass the angle and the location of the point p1
//as parameters, angle is straightforward, the location is the point at which the rotation will have its origin,
//so the rectangle will be rotated around that point)
r.RenderTransform = new RotateTransform(w, 0, r.Height / 2.0);

//maybe remove this
if (c.Children.Contains(r) == false)
{
}
}

Regards,

Thorsten

• Proposed As Answer by Tuesday, May 29, 2012 4:32 PM
• Marked As Answer by Tuesday, May 29, 2012 6:07 PM
•
• Monday, May 28, 2012 6:58 PM

also, when the rectangle got render into the main display, it is pretty tiny, is there a way i can set it so that it can "fit to screen" or to 25% of screen at bottom half, ..etc?

this is my XAML...

<Window x:Class="wpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Border>
<Canvas HorizontalAlignment="Center" VerticalAlignment="Center" Name="myCanvas"
Width="0" Height="0"
RenderTransform="1 0 0 -1 0 0">
</Canvas>
</Border>
</Grid>
</Window>

• Edited by Monday, May 28, 2012 6:59 PM
•
• Tuesday, May 29, 2012 12:50 AM

the width is set by the distance of the points x-distance, the height of the rectangle passed as parameter... so to make it smaller or bigger, change these values.

Btw: This is a rather unusual way to construct a rectangle, I just followed your picture in your first post. Usually to create a rectangle from two points, one point specifies the upper-left-corner and the other the lower-right one (so both width and height could be computed from the relation of the two points).

Regards,

Thorsten

• Tuesday, May 29, 2012 2:43 PM

Hi Thorsten,

I am also very interested in know how to draw a rectangle with "one point specifies the upper-left-corner and the other the lower-right one (so both width and height could be computed from the relation of the two points)."

Can you give an example?

• Tuesday, May 29, 2012 4:47 PM

Hi,

//p1 is the topLeft corner of the rectangle, p2 the bottomright corner - so a unrotated rectangle is constructed from the points
private void DrawRect(Canvas c, Rectangle r, Point p1, Point p2, Brush stroke, double strokeThickness, double angle)
{
//get distances
Vector v = p2 - p1;

r.Width = v.X;
r.Height = v.Y;

//set the Location of the Rectangle relative to the containing Canvas
r.SetValue(Canvas.LeftProperty, p1.X);
r.SetValue(Canvas.TopProperty, p1.Y);

//Stroke-Color and Thickness
r.Stroke = stroke;
r.StrokeThickness = strokeThickness;

//now do the rotation with a RenderTransform (pass the angle and the location of the point p1
//as parameters, angle is straightforward, the location is the point at which the rotation will have its origin,
//so the rectangle will be rotated around that point)
RotateTransform rot = r.RenderTransform as RotateTransform;

if (rot != null)
rot.Angle = angle;
else
r.RenderTransform = new RotateTransform(angle, 0, 0);

//maybe remove this
if (c.Children.Contains(r) == false)
{