I would like to dynamically add a Triangle to my canvas. I can do this but only in one very specific way that does not work for my application. What I would like to do is supply a point and a size and get back a triangle.
var poly = shape as Polygon;
Polygon p = new Polygon
{
//Width = size,
//Height = size,
Fill = new SolidColorBrush(Colors.Red),
ManipulationMode = ManipulationModes.All,
RenderTransform = new CompositeTransform()
};
int w = 200;
int h = 200;
Point start = new Point(400, 200);
var right = new Point(start.X + w, start.Y);
var top = new Point(start.X + (w / 2), start.Y - (h));
poly.Points.Add(point);
poly.Points.Add(right);
poly.Points.Add(top);
poly.Points.Add(point);
Then I add the shape to my canvas child controls and and set the X Y on the shapes RenderTransform. Nothing appears. If however I just do this:
Polygon p = new Polygon
{
//Width = size,
//Height = size,
Fill = new SolidColorBrush(Colors.Red),
ManipulationMode = ManipulationModes.All,
RenderTransform = new CompositeTransform()
};
p.Points.Add(new Point(300, 200));
p.Points.Add(new Point(400, 125));
p.Points.Add(new Point(400, 275));
p.Points.Add(new Point(300, 200));
It renders a Triangle just fine. However if you supply a width and height to the above code it will stop rendering.
Can I just create a triangle of a certain size, without having to set actual points on the canvas at first, much like you do an Ellipse or a Rectangle?
Related
I would like add a Grid in a Canvas and put inside a Rectangle.
Here my code
Grid gridForModules = new Grid();
Canvas.SetLeft(gridForModules, 600);
Canvas.SetTop(gridForModules, 80);
AddRowsOfGrid(gridForModules, 5);
AddColumnsOfGrid(gridForModules, 8);
gridForModules.ShowGridLines = true;
m_grid.RegisterName("ModulesGRID", gridForModules);
m_canvas.Children.Add(gridForModules);
Rectangle rect = new Rectangle();
Grid.SetColumn(rect, 2);
Grid.SetRow(rect, 2);
Grid.SetRowSpan(rect, 2);
Grid.SetColumnSpan(rect, 2);
rect.Fill = new SolidColorBrush(Colors.Coral);
rect.Name = "ModuloEsempio";
gridForModules.Children.Add(rect);
m_grid.RegisterName(rect.Name, rect);
Thanks
You specify that the columns/rows of the Grid should be equally wide/high by setting new GridLength(1.0, GridUnitType.Star) on both. So if you have 5 rows then the height of each row should be the height of the Grid divided by 5.
The problem in your code is that the Grid doesn't have a height or width because the Canvas is just a drawing board that doesn't size its contents.
To solve your problem you either have to set the size on the Grid using
gridForModules.Width = 300;
gridForModules.Height = 200;
or you have to set it in the Column/RowDefinitions
col.Width = new GridLength(30);
row.Height = new GridLength(30);
After that you should see your Grid and your Rectangle (if you look a bit far to the right).
Ok so i have created a triangle but I cant for the life of me work out the coordinates to create a simple hexagon,
Point[] shape = new Point[3];
shape[0] = new Point(200, 100);
shape[1] = new Point(300, 200);
shape[2] = new Point(100, 200);
This makes a triangle but I cant figure out the x and y values for a hexagon, sounds like a simple question but my brain just isn't working correctly today, Below is the array for the hexagon I just can't figure out the values.
Point[] shape = new Point[6];
shape[0] = new Point(0, 0);
shape[1] = new Point(0, 0);
shape[2] = new Point(0, 0);
shape[3] = new Point(0, 0);
shape[4] = new Point(0, 0);
shape[5] = new Point(0, 0);
Any help would be great thanks!
Since I've already written a comment, I guess I should demonstrate that in some real code.
I created a WinForms application with a Panel object on which I can draw. Then I've overridden the Paint event on that to draw me a hexagon.
private void panel1_Paint(object sender, PaintEventArgs e)
{
var graphics = e.Graphics;
//Get the middle of the panel
var x_0 = panel1.Width / 2;
var y_0 = panel1.Height / 2;
var shape = new PointF[6];
var r = 70; //70 px radius
//Create 6 points
for(int a=0; a < 6; a++)
{
shape[a] = new PointF(
x_0 + r * (float)Math.Cos(a * 60 * Math.PI / 180f),
y_0 + r * (float)Math.Sin(a * 60 * Math.PI / 180f));
}
graphics.DrawPolygon(Pens.Red, shape);
}
This then draws
As I said, the key is to view the hexagon as a "discrete" circle. The points are all computed as being on the outer part of a perfect circle, which are then connected with a straight line. You can create all regular n-Point shapes with this technique (a pentagon e.g. as a 5-regular shape ;))
So, you just "inscribe" the 6 points in the circle to get your hexagon, as shown in this diagram with a regular 5-point shape:
Then remember that you can compute the (x,y) coordinates of a point given its polar coordinates (r, phi) as
To which you can also add an offset , which is in my case the center of the frame I'm drawing in.
Basically I have a form and am trying to "dim" areas of it to draw focus to a certain part of the form. To do this I'm using a Form with no border and 50% opacity, aligned with the actual form. The area I am trying to mask is the dark gray area, roughly, as pictured:
To get the "U"-shaped form, I'm using a GraphicsPath with AddPolygon, calculating the points of each vertex:
var p = new GraphicsPath();
var origin = new Point(Top, Left);
var maxExtentPt = new Point(origin.X + Width, origin.Y + Height);
Point[] points = {
origin,
new Point(origin.X + leftPanel.Width, origin.Y),
new Point(origin.X + leftPanel.Width, maxExtentPt.Y - bottomPanel.Height),
new Point(maxExtentPt.X - rightPanel.Width, maxExtentPt.Y- bottomPanel.Height),
new Point(maxExtentPt.X - rightPanel.Width, origin.Y),
new Point(maxExtentPt.X, origin.Y),
maxExtentPt,
new Point(origin.X, maxExtentPt.Y),
origin
};
p.AddPolygon(points);
overlayForm.Region = new Region(p);
overlayForm.Location = PointToScreen(Point.Empty);
The three panels in the code are what I am masking, so I am using their dimensions to calculate the points. Instead of getting my expected result, the mask looks like this, with its size changing as I resize the main form (I recalculate the region on Move and Resize):
Is there some limitation of GraphicsPath.AddPolygon that I'm not aware of? I double-checked (quadruple-checked, really) the results of my calculations, including taking the coordinates for each point and plugging them into Ipe to see if the shape was actually correct... It was. But not in my program!
Edit: Here are the values of each point, when I hit a breakpoint at p.AddPolygon(points); I'm starting in the upper left-hand corner and going around clockwise:
Looks like your points are wrong after all.
Everything ought to be in the coordinates of the ClientRectangle, so
Origin should not be new Point(Top, Left) which is the Location of the Form. It should be Point.Empty or (0,0). Or you could use the leftPanel.Location.
And
maxExtentPt = new Point(origin.X + Width, origin.Y + Height);
should read:
var maxExtentPt = new Point(origin.X + ClientSize.Width, origin.Y + ClientSize.Height);
(The difference is the size of border+title..)
Let me know if that works better!
You could also try doing it this way, basing everything off the Panels:
Form overlayForm = new Form();
overlayForm.Opacity = .5;
overlayForm.BackColor = Color.DarkGray;
overlayForm.StartPosition = FormStartPosition.Manual;
overlayForm.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
var p = new GraphicsPath();
var origin = new Point(0, 0);
var maxExtentPt = new Point(this.Width, this.Height);
Point[] points = {
origin,
new Point(leftPanel.Right, origin.Y),
new Point(leftPanel.Right, bottomPanel.Top),
new Point(rightPanel.Left, bottomPanel.Top),
new Point(rightPanel.Left, origin.Y),
new Point(rightPanel.Right, origin.Y),
maxExtentPt,
new Point(origin.X, maxExtentPt.Y),
origin
};
p.AddPolygon(points);
overlayForm.Region = new Region(p);
overlayForm.Location = this.PointToScreen(new Point(0, 0));
overlayForm.Show();
How to draw a bezier with two colors? like the picture below?
I already have drawn the bezier, I can fill it with any color, however I cant the gradient working.
this is what im doing, im using a Path to create the bezier by the way.
private void test()
{
System.Windows.Media.GradientStop GradientStop1 = new System.Windows.Media.GradientStop();
System.Windows.Media.GradientStop GradientStop2 = new System.Windows.Media.GradientStop();
System.Windows.Media.LinearGradientBrush p_Fill; p_Fill = new System.Windows.Media.LinearGradientBrush(Colors.Blue, Colors.Red, new Point(0, 0.5), new Point(1, 0.5));
p_Fill.GradientStops.Add(GradientStop1);
p_Fill.GradientStops.Add(GradientStop2);
Bez.Fill = p_Fill;
}
This is how it should be
This is what I get
If you need a sharp cut between the 2 colored halves, you have to need more GradientStops:
var grad3 = new System.Windows.Media.GradientStop()
{Offset = 0.5, Color=Colors.Blue};
var grad4 = new System.Windows.Media.GradientStop()
{Offset = 0.5, Color=Colors.Red};
GradientStop2.Offset = 1;
p_Fill.GradientStops.Add(GradientStop1);
p_Fill.GradientStops.Add(grad3);
p_Fill.GradientStops.Add(grad4);
p_Fill.GradientStops.Add(GradientStop2);
Addtionally, you have to set the Brush for the Stroke, not the Fill. The StrokeThickness determines the thickness of the curve:
Bez.Stroke = p_Fill;
Bez.StrokeThickness = new Thickness(10);
Am using the below code to create polygon. i just want to fill this polygon surface with black dots, how i can do that, then i want to convert this polygon to bitmap or in memory stream, how to do this??
// Create a blue and a black Brush
SolidColorBrush yellowBrush = new SolidColorBrush();
yellowBrush.Color = Colors.Transparent;
SolidColorBrush blackBrush = new SolidColorBrush();
blackBrush.Color = Colors.Black;
// Create a Polygon
Polygon yellowPolygon = new Polygon();
yellowPolygon.Stroke = blackBrush;
yellowPolygon.Fill = yellowBrush;
yellowPolygon.StrokeThickness = 4;
// Create a collection of points for a polygon
System.Windows.Point Point1 = new System.Windows.Point(50, 100);
System.Windows.Point Point2 = new System.Windows.Point(200, 100);
System.Windows.Point Point3 = new System.Windows.Point(200, 200);
System.Windows.Point Point4 = new System.Windows.Point(300, 30);
PointCollection polygonPoints = new PointCollection();
polygonPoints.Add(Point1);
polygonPoints.Add(Point2);
polygonPoints.Add(Point3);
polygonPoints.Add(Point4);
// Set Polygon.Points properties
yellowPolygon.Points = polygonPoints;
// Add Polygon to the page
mygrid.Children.Add(yellowPolygon);
Do the dots have to be positioned in a particular order or do you just want to have a dotted pattern in your polygon without specific order?
If you don't need a special order you could use a Brush, a DrawingBrush for instance. Check out this link: http://msdn.microsoft.com/en-us/library/aa970904.aspx
You can then set this Brush as the Fill-Property of your Polygon instead of the SolidColorBrush.
This is the DrawingBrush example from the msdn link, but modified to display dots:
// Create a DrawingBrush and use it to
// paint the rectangle.
DrawingBrush myBrush = new DrawingBrush();
GeometryDrawing backgroundSquare =
new GeometryDrawing(
Brushes.Yellow,
null,
new RectangleGeometry(new Rect(0, 0, 100, 100)));
GeometryGroup aGeometryGroup = new GeometryGroup();
aGeometryGroup.Children.Add(new EllipseGeometry(new Rect(0, 0, 20, 20)));
SolidColorBrush checkerBrush = new SolidColorBrush(Colors.Black);
GeometryDrawing checkers = new GeometryDrawing(checkerBrush, null, aGeometryGroup);
DrawingGroup checkersDrawingGroup = new DrawingGroup();
checkersDrawingGroup.Children.Add(backgroundSquare);
checkersDrawingGroup.Children.Add(checkers);
myBrush.Drawing = checkersDrawingGroup;
myBrush.Viewport = new Rect(0, 0, 0.05, 0.05);
myBrush.TileMode = TileMode.Tile;
yellowPolygon.Fill = myBrush;