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 pokerMaster 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_rad = Math.Acos(cos_w); 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); canvas1.Children.Add(r); //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; canvas1.Children.Add(e1); canvas1.Children.Add(e2); }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 pokerMaster 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_rad = Math.Acos(cos_w); 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) { canvas1.Children.Add(r); canvas1.Children.Add(e1); canvas1.Children.Add(e2); } } }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
- Edited by Thorsten GuderaMicrosoft Community Contributor Monday, May 28, 2012 5:39 PM
- Edited by Thorsten GuderaMicrosoft Community Contributor Monday, May 28, 2012 6:00 PM
- Marked As Answer by pokerMaster Tuesday, May 29, 2012 6:08 PM
-
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_rad = Math.Acos(cos_w); 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) { c.Children.Add(r); } }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
- Edited by Thorsten GuderaMicrosoft Community Contributor Monday, May 28, 2012 6:09 PM
- Marked As Answer by pokerMaster Tuesday, May 29, 2012 6:08 PM
-
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_rad = Math.Acos(cos_w); 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) { c.Children.Add(r); } }Regards,
Thorsten
- Proposed As Answer by LeeCampbell Tuesday, May 29, 2012 4:32 PM
- Marked As Answer by pokerMaster Tuesday, May 29, 2012 6:07 PM
-
Monday, May 28, 2012 6:58 PM
Thanks, your comments helps me understand a lot.
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 pokerMaster 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) { c.Children.Add(r); } }call it like:
DrawRect(canvas1, new Rectangle(), new Point(50, 50), new Point(300, 200), new SolidColorBrush(Colors.Red), 2, 0);
Regards,
Thorsten
- Edited by Thorsten GuderaMicrosoft Community Contributor Tuesday, May 29, 2012 5:04 PM
- Marked As Answer by pokerMaster Tuesday, May 29, 2012 6:07 PM

