WPF draws geometry

Keywords: Windows Attribute

A basic graphic object of WPF Shape

The base class of WPF graphics is Shape, and all WPF graphics classes are inherited from Shape. WPF provides many ready-made Shape Object. All shape objects are derived from Shape Class inheritance. Available shape objects include EllipseLine ,Path,PolygonPolyline and Rectangle.  Shape Objects share the following common properties.

  • Stroke : describes how the shape outline is drawn.

  • StrokeThickness : describes the thickness of the shape contour.

  • Fill : describes how the interior of a shape is drawn.

  • Data attributes used to specify coordinates and vertices, measured in device independent pixels.

Because they are derived from UIElement Shape objects can be used in panels and most controls. The Canvas Panels are a particularly good choice for creating complex graphics because they support the absolute positioning of their children.

The Line Class enables you to draw a line between two points. The following example shows several ways to specify line coordinates and stroke attributes.

<Canvas Height="300" Width="300">

  <!-- Draws a diagonal line from (10,10) to (50,50). -->
  <Line
    X1="10" Y1="10"
    X2="50" Y2="50"
    Stroke="Black"
    StrokeThickness="4" />

  <!-- Draws a diagonal line from (10,10) to (50,50)
       and moves it 100 pixels to the right. -->
  <Line
    X1="10" Y1="10"
    X2="50" Y2="50"
    StrokeThickness="4"
    Canvas.Left="100">
    <Line.Stroke>
      <RadialGradientBrush GradientOrigin="0.5,0.5" Center="0.5,0.5" RadiusX="0.5" RadiusY="0.5">
        <RadialGradientBrush.GradientStops>
          <GradientStop Color="Red" Offset="0" />
          <GradientStop Color="Blue" Offset="0.25" />
        </RadialGradientBrush.GradientStops>
      </RadialGradientBrush>
    </Line.Stroke>
  </Line>

  <!-- Draws a horizontal line from (10,60) to (150,60). -->
  <Line
     X1="10" Y1="60"
     X2="150" Y2="60"
     Stroke="Black"
     StrokeThickness="4"/>

</Canvas>
// Add a Line Element
myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1;
myLine.X2 = 50;
myLine.Y1 = 1;
myLine.Y2 = 50;
myLine.HorizontalAlignment = HorizontalAlignment.Left;
myLine.VerticalAlignment = VerticalAlignment.Center;
myLine.StrokeThickness = 2;
myGrid.Children.Add(myLine);

The following image shows the rendered Line.

although Line Class does provide properties Fill , but setting it does not work, Line Because there is no area.

A straight line is the simplest figure. Use X1 and Y1 to set the starting point coordinate, and X2 and Y2 to set the ending point coordinate. By controlling the coordinates of the starting point and the end point, parallel and staggered effects can be achieved. The data type of the Stroke attribute is Brush.
Let's take another example:

<!--StrokeThickness: The thickness of figure outline; StrokeDashArray: The style of the dotted line gap of the shape outline; StrokeStartLineCap/StrokeEndLineCap: Beginning of straight line/The graphic style of the end. The attribute values are Flat,Round,Square,Triangle-->

        <Line X1="10" Y1="20" X2="500" Y2="20" Stroke="Pink" StrokeThickness="10"/>                            //Stroke is the color and stroke thickness is the width of the line
        <Line X1="10" Y1="50" X2="500" Y2="50" Stroke="Black" StrokeDashArray="3" StrokeThickness="1"/>        //strokeDashArray is a dashed gap
        <Line X1="10" Y1="80" X2="500" Y2="80" Stroke="Pink" StrokeEndLineCap="Flat" StrokeThickness="10"/>
        <Line X1="10" Y1="110" X2="500" Y2="110" Stroke="Pink" StrokeEndLineCap="Round" StrokeThickness="10"/>
        <Line X1="10" Y1="140" X2="500" Y2="140" Stroke="Pink" StrokeEndLineCap="Square" StrokeThickness="10"/>
        <Line X1="10" Y1="170" X2="500" Y2="170" Stroke="Pink" StrokeEndLineCap="Triangle" StrokeThickness="10"/>

The results are as follows:

 

 

Another common shape Ellipse Yes. By definition Ellipse shape Width and Height Property creation. To draw a circle, specify Ellipse his WidthHeight Equal to a value. Rectangle, consisting of Stroke and Fill.

<Ellipse Fill="Yellow" Height="100" Width="200" StrokeThickness="2" Stroke="Black"/>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SDKSample
{
    public partial class SetBackgroundColorOfShapeExample : Page
    {
        public SetBackgroundColorOfShapeExample()
        {
            // Create a StackPanel to contain the shape.
            StackPanel myStackPanel = new StackPanel();

            // Create a red Ellipse.
            Ellipse myEllipse = new Ellipse();

            // Create a SolidColorBrush with a red color to fill the
            // Ellipse with.
            SolidColorBrush mySolidColorBrush = new SolidColorBrush();

            // Describes the brush's color using RGB values.
            // Each value has a range of 0-255.
            mySolidColorBrush.Color = Color.FromArgb(255, 255, 255, 0);
            myEllipse.Fill = mySolidColorBrush;
            myEllipse.StrokeThickness = 2;
            myEllipse.Stroke = Brushes.Black;

            // Set the width and height of the Ellipse.
            myEllipse.Width = 200;
            myEllipse.Height = 100;

            // Add the Ellipse to the StackPanel.
            myStackPanel.Children.Add(myEllipse);

            this.Content = myStackPanel;
        }
    }
}

The following image shows the rendering Ellipse An example of.

Look at the following example, drawing a rectangle into a rounded rectangle

<Rectangle Width="200" Height="200" StrokeDashArray="3" Fill="Transparent" Stroke="Blue" StrokeThickness="15"
StrokeDashCap="Flat" StrokeDashOffset="100" StrokeEndLineCap="Triangle" StrokeMiterLimit="10"
StrokeLineJoin="Round"/>

Dashed lines are also called dash patterns

The StrokeDashArray property contains a group of double type values, which identify the length of the dotted line and the solid line. A number represents the virtual part and real part of the same size, two numbers represent the small size of the virtual part and the real part, and more than one represents the first, second and third paragraph

The RadiusX and RadiusY attributes need to use a combination of angles to represent the angle, which does not work if set separately. RadiusX represents the curvature of the X-axis angle, and RadiusY represents the curvature of the Y-axis angle.

The StrokeDashCap property is used to set the shape of the dashed line. If there is no dashed line, it will not take effect

StrokeDashOffset indicates the starting distance and offset of the dash

StrokeEndLineCap sets the shape at the beginning or end. Closed curves are invalid

The ratio of the stroke length to the miter stroke limit. This value is always a positive number greater than or equal to 1.

Polygon polygon,
Consider the following example:

<Polygon Points="100,150 400,150 140,320 250,50 360,320" StrokeThickness="2" Stroke="Pink"/>

 

The Points attribute represents a collection of polygon Points.

IsClosed specifies whether the last point of the polygon is closed to the first point. To be a polygon. Should be set to true in general

The ArcRoundness property specifies how far from the end of the LineSegment to start the bend, and is usually used with useroundness percentage.

The useroundness percentage property specifies whether the ArcRoundness value is a percentage or a fixed value.

For example, if ArcRoundness is set to 10 and useroundness percentage is set to false, the bend will start at 10 from the end of the line segment. If use roundness percentage is set to true. The curve starts at 10% of the end of the line.

 

Polyline is a multi line type, which is composed of a number of straight lines connecting the head and tail.
Consider the following example:

<Polyline Points="50,200 100,80 200,80 150,120" StrokeThickness="2" Stroke="Pink"/>

be careful:

Polyline draws a broken line at a small angle (such as a few degrees). One of the two lines forming the corner will exceed, and the smaller the angle, the more obvious.

The problem is as follows:

You can use custom shape to solve this problem. When rewriting DefiningGeometry, you can write the following code:

using (StreamGeometryContext context = sg.Open())
{
context.BeginFigure(Points[0], true, false);
foreach (Point p in Points)
{
context.LineTo(p, true, true);
}
}

2. Using paths and geometry

Path path can combine basic elements such as lines, arcs and curves to form more complex graphs. These curves and shapes use Geometry Object. To use Path , create Geometry And use it to set Path Properties of the object Data . WPF provides two classes to describe the path data: one is StreamGeometry and the other is PathFigureCollection. There are many Geometry Objects are available for selection.   RectangleGeometryEllipseGeometry and LineGeometry Class describes relatively simple shapes. To create more complex shapes or create curves, use the PathGeometry.

The most important attribute of Path: Data. See the following example:

<! -- M: move to start point C: cubic Bezier curve -- >

<Path Stroke="Red" StrokeThickness="2" Data="M 240,240 C 160,80 320,80 240,240"/>
<Path x:Name="PathFillColor" Fill="{TemplateBinding Property=Button.Background}">
    <Path.Data>
        <PathGeometry>
            <PathFigure StartPoint="1,24" IsClosed="True">
                <LineSegment Point="35,58"/>
                <ArcSegment Size="55,20" Point="59,48" SweepDirection="Clockwise"/>
                <LineSegment Point="59,1"/>
                <ArcSegment Size="80,80" Point="1,24" SweepDirection="Counterclockwise"/>
            </PathFigure>
        </PathGeometry>
    </Path.Data>
</Path>

WPF provides two classes to describe the path data: one is StreamGeometry and the other is PathFigureCollection.  

<Path Stroke="Black" Data="M 100,240 C 510,300 80,100 300,160 H40 v80" />

Is the XAML code representation of StreamGeometry, which is also the most concise representation.  

<Path Stroke="Black" StrokeThickness="1" Fill="#CCCCFF"> 
  <Path.Data> 
    <PathGeometry Figures="M 10,100 C 10,300 300,-160 300,100" /> 
  </Path.Data> 
</Path> 

This is done using the XAML code representation of the pathfigure collection.  
These two methods can achieve the same display effect. When to use StreamGeometry and pathfigure collection?  
Generally, when you create a path and you no longer need to modify it, you can use the StreamGeometry method. If you need to modify the path value, you can use the PathFigureCollection method (here is PathGeometry).  

The meaning of the string "M 100240 C510300 80100300160 H40 V80" is explained below.  
It can be explained in four cases
1. Move Command (M): M starting point or M starting point
For example, m 100240 or m 100240
When using uppercase m, it means absolute value; when using lowercase m, it indicates the value relative to the previous point, if the previous point is not specified, use (0,0).  

2. Draw command:
We can draw the following shapes:
(1) Line(L)
(2) Horizontal line(H)
(3) Vertical line(V)
(4) Cubic Bezier curve(C)
(5) Quadratic Bezier curve(Q)
(6) Smooth cubic Bezier curve(S)
(7) smooth quadratic Bezier curve(T)
(8) Elliptical arc: elliptical Arc(A)

The English letters in brackets after each of the above shapes are the upper case form of the command abbreviation, but you can also use lower case. The difference between using uppercase and lowercase is that upper case is absolute and lowercase is relative. For example, l 100 and 200 L 300400 represent a straight line from the absolute coordinate point (100200) to another absolute coordinate point (300400). And l 100, 200 L 300400 means a straight line from the coordinate point (100200) calculated from the previous point (0,0 coordinate point by default if not specified) to the coordinate point (300400).  

When we reuse the same type, we can omit the previous command. For example: l 100, 200 L 300 400, abbreviated as l 100, 200, 300, 400.  

<Path Stroke="Black" StrokeThickness="1" Data="M 10,10 100,10 100,40 Z M 10,100 L 100,100 100,50 Z" /> 

Here is a Z command that you haven't seen yet. It is a close Command, which means to close the specified shape, that is, the head and tail points are connected to form a closed area.  
Drawing instruction format syntax:

(1) Line(L)
Format: l end point coordinate or: l end point coordinate.  
For example, l 100100 or l 100 100. Coordinate values can be in the form of x,y (separated by commas in the middle) or x,y (separated by half a space in the middle).  

(2) Horizontal line(H): draws a line from the current point to the specified x coordinate.  
Format: h x value or h x value (x is System.Double Value of type)
For example: H 100 or H 100, or H 100.00 or H 100.00.  

(3) Vertical line(V): draws a line from the current point to the specified y coordinate.  
Format: v y value or v y value (y is System.Double Type)
For example: V 100 or y 100, or V 100.00 or V 100.00.  

(4) Cubic Bezier curve(C): draws a cubic Bezier curve from the current point to the specified end point by specifying two control points.  
Format: c first control point second control point end point or c first control point second control point end point
For example: C 100200 200400 300200 or C 100200 200400 300200
Among them, point (100200) is the first control point, point (200400) is the second control point and point (300200) is the end point.  

(5) Quadratic Bezier curve(Q): draws a quadratic Bezier curve from the current point to the specified end point through a specified control point.  
Format: q control point end point or q control point end point
For example: Q 100200 300200. Among them, point (100200) is the control point and point (300200) is the end point.  

(6) Smooth cubic Bezier curve(S): Smooth cubic Bezier curve(S): controls the Bezier curve from the current point to the specified point "smoothly" through a specified point.  
Format: s control point end point or s control point end point
For example: s 100200 200300

(7) smooth quadratic Bezier curve(T): similar to smooth cubic Bezier curve.  
Format: t control point end point or t control point end point
For example: t 100200 200300

(8) Elliptical arc: elliptical Arc(A): draws an arc between the current point and the specified end point.  
Dimension A arc rotation angle value mark the positive and negative angle of the dominant arc mark the end point
Or:
a dimension arc rotation angle value mark positive and negative angle mark end point of dominant arc
Size: System.Windows.Size Type to specify the radius value in the X and Y directions of the ellipse arc.  
Rotation angle: System.Double Type.  
rotationAngle: the rotation angle value of the elliptical arc.  
Is largearcflag: whether it is a dominant arc. If the angle of the arc is greater than or equal to 180 degrees, it is set to 1; otherwise, it is 0.  
sweepDirectionFlag: set to 1 when drawing in positive direction, otherwise 0.  
End point: System.Windows.Point Type.  

3. Close command: used to connect the first and last points of a graph with a straight line to form a closed area.  
In Z or Z.  

The difference between graphic drawing and geometric drawing:

Graphics objects can exist independently, and can draw specific graphics independently.

Geometry object has no specific shape, it needs to rely on an object element and can not be directly presented on the drawing board
Geometric drawing includes five kinds of objects:

LineGeometry: line geometry
Rectangle geometry: rectangular geometry
Ellipse geometry: ellipse geometry
PathGeometry: path geometry
Geometry group: a group of geometric figures formed by combining several basic geometric figures
Consider the following example:

<Grid Height="469" VerticalAlignment="Bottom">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="239*"/>
            <ColumnDefinition Width="253*"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="100*"/>
            <RowDefinition Height="100*"/>
            <RowDefinition Height="100*"/>
            <RowDefinition Height="169*"/>
        </Grid.RowDefinitions>
        <!--straight line-->
        <Path Stroke="Blue" StrokeThickness="2" Grid.Column="0" Grid.Row="0">
            <Path.Data>
                <LineGeometry StartPoint="20,40" EndPoint="200,60"/>
            </Path.Data>
        </Path>

        <!--Rectangular path-->
        <Path Stroke="Pink" StrokeThickness="2" Grid.Column="1" Grid.Row="0">
            <Path.Data>
              <!--Rect="40,20,60,60" 40,20 The third digit is the width and the fourth digit is the length-->
                <RectangleGeometry Rect="40,20,60,60" RadiusX="10" RadiusY="10"/>
            </Path.Data>
        </Path>
        <!--Ellipse path-->
        <Path Stroke="Yellow" Fill="Orange" Grid.Column="0" Grid.Row="1">
            <Path.Data>
                <EllipseGeometry Center="100,50" RadiusX="60" RadiusY="40"></EllipseGeometry>
            </Path.Data>
        </Path>

        <!—Geometry group-->
     <Path Fill="Pink" Stroke="Red" StrokeThickness="2">
            <Path.Data>
                <GeometryGroup FillRule="EvenOdd">
                    <EllipseGeometry Center="80,80" RadiusX="30" RadiusY="60"/>
                    <LineGeometry StartPoint="20,40" EndPoint="200,60"/>
                    <RectangleGeometry Rect="20,20,60,60" RadiusX="10" RadiusY="10"/>
                </GeometryGroup>
            </Path.Data>
        </Path>
</Grid>

Geometry class (geometric drawing) includes LineGeometry (geometric line), rectangle geometry (geometric rectangle), ellipsegeometry (geometric ellipse), GeometryGroup (geometric combination) and PathGeometry (geometric path). It can describe any 2D shape of geometry.

From the drawing point of view, the Geometry class and Share are similar to drawing 2D graphics, but there are important differences between the two classes. The Geometry class is lighter and more efficient than Share.

2, Geometry and Path

LineGeometry, rectangle Geometry, ellipsegeometry, GeometryGroup and PathGeometry are inherited from Geometry.

 

In fact, path can also be used as a container to allow Geometry of any Geometry shape to be included in the Path.Data Inside.

LineGeometry

The Line object similar to Share is used to generate a Line. The difference is that Line uses X and Y coordinates to generate lines, while LineGeometry uses StartPoint and EndPoint to complete Line drawing.

For example:

<LineGeometry StartPoint="0,0" EndPoint="100,500" />

Rectangle geometry and ellipse geometry are similar to rectangle and ellipses in Share, which are not described here.

GeometryGroup

Sometimes some graphs need to be combined. GeometryGroup has this function, such as the following example:

<StackPanel x:Name="LayoutRoot" Orientation="Horizontal" Background="AliceBlue">
        <Path Fill="Cyan" Stroke="Black" StrokeThickness="3">
            <Path.Data>
                <!--GeometryGroup combination-->
                <GeometryGroup FillRule="EvenOdd">
                    <RectangleGeometry  RadiusX="2" RadiusY="2" Rect="80,50 200,100"></RectangleGeometry>
                    <EllipseGeometry Center="300,100" RadiusX="80" RadiusY="60"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path>
        <Path Fill="Cyan" Stroke="Black" StrokeThickness="3">
            <Path.Data>
                <!--GeometryGroup combination-->
                <GeometryGroup FillRule="Nonzero">
                    <RectangleGeometry  RadiusX="2" RadiusY="2" Rect="80,50 200,100"></RectangleGeometry>
                    <EllipseGeometry Center="300,100" RadiusX="80" RadiusY="60"></EllipseGeometry>
                </GeometryGroup>
            </Path.Data>
        </Path> 
    </StackPanel>

The operation results are as follows:

 

When two figures cross, the FillRule property of Geometry can be used to define the filling rules of combined figures. The FillRule property has two enumeration values (enodd) and (Zonzero)

PathGeometry

PathGeometry is the most flexible of Geometry. It can draw arbitrary 2D Geometry.

 <Path Stroke="Black" StrokeThickness="1">
            <Path.Data>
                <! -- specify Path.Data The fill for is pathgeometry -- >
                <PathGeometry>
                    <! -- define the figure of PathGeometry -- >
                    <PathGeometry.Figures>
                        <PathFigureCollection>
                            <! -- pathfigure represents a sub part of the geometry, a series of separately connected 2D geometric segments.
                            IsClosed: gets or sets a value indicating whether to connect the first and last segments of the drawing. >
                            <PathFigure IsClosed="True" StartPoint="50,100">
                                <PathFigure.Segments>
                                    <BezierSegment Point1="100,0" Point2="200,200" Point3="300,100"/>
                                    <LineSegment Point="400,100" />
                                    <ArcSegment Size="50,50" RotationAngle="45" IsLargeArc="False"  SweepDirection="Clockwise" Point="200,100"/>
                                </PathFigure.Segments>
                            </PathFigure>
                        </PathFigureCollection>
                    </PathGeometry.Figures>
                </PathGeometry>
            </Path.Data>
        </Path>

The above running results provide a path syntax parser to simplify the above XAML and WPF

   <Path Stroke="Black" StrokeThickness="1" 
 
            Data="M 10,100 L 100,100 100,50 Z M 10,10 100,10 100,40 Z" />

LineSegment pair

Using LineSegment object to create line object

<Path Stroke="DarkCyan" StrokeThickness="3">
            <Path.Fill>
                <LinearGradientBrush>
                    <GradientStop Color="Orange"/>
                    <GradientStop Color="White" Offset="1"/>
                </LinearGradientBrush>
            </Path.Fill>
            <Path.Data>
                <PathGeometry>
                    <!-- Indicate closed line and specify start position-->
                    <PathFigure IsClosed="True" StartPoint="50,100">
                        <LineSegment Point="200,200" />
                        <LineSegment Point="200,150" />
                        <LineSegment Point="400,150" />
                        <LineSegment Point="400,50" />
                        <LineSegment Point="200,50" />
                        <LineSegment Point="200,0" />
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

 

Operation result:

 

ArcSegment object

Use ArcSegment object to draw arc elements

 <Path Stroke="DarkCyan" StrokeThickness="3">
            <Path.Data>
                <PathGeometry>
                    <! -- arcsegment specifies the starting point of the arc -- >
                    <PathFigure IsClosed="False" StartPoint="50,50">
                        <! -- arcsegment declares the end point and radian of the first arc -- >
                        <ArcSegment Size="280,280" Point="400,50" />
                        <! -- arcsegment declares the end point and radian of the second arc -- >
                        <ArcSegment Size="90,280" Point="550,150" />
 
                        <ArcSegment Size="50,50" Point="600,50" />
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

Operation result:

 

 

BezierSegment object

 

Bezier curve is drawn by using BeezierSegment object. Bezier curve is generated by complex mathematical formula. It is used to calculate how to determine the contour of a curve between two control points. Here is an example:

  <!--Start drawing Bezier curves-->
        <Path Stroke="DarkCyan" Fill="YellowGreen" StrokeThickness="5">
            <Path.Data>
                <PathGeometry>
                    <!--Declare Bezier curve-->
                    <PathFigure StartPoint="10,10">
                        <BezierSegment Point1="130,30" Point2="40,140" Point3="150,150"/>
                    </PathFigure>
                </PathGeometry>
            </Path.Data>
        </Path>

Operation result:

 

Posted by BrettCarr on Mon, 29 Jun 2020 02:33:35 -0700