PathGeometry позволяет создавать более сложные по характеру геометрии. PathGeometry содержит один или несколько компонентов PathFigure. Объект PathFigure в свою очередь формируется из сегментов. Все сегменты наследуются от класса PathSegment и бывают нескольких видов:
LineSegment задает отрезок прямой линии между двумя точками
ArcSegment задает дугу
BezierSegment задает кривую Безье
QuadraticBezierSegment задает квадратичную кривую Безье
PolyLineSegment задает сегмент из нескольких линий
PolyBezierSegment задает сегмент из нескольких кривых Безье
PolyQuadraticBezierSegment задает сегмент из нескольких квадратичных кривых Безье
Эти сегменты составляют свойство Segment объекта PathFigure. Кроме того, PathFigure имеет еще несколько важных свойств:
StartPoint - точка начала первой фигуры
IsClosed - если значение равно true, то первая и последняя точки (если они не совпадают) соединяются
IsFilled - если значение равно true, то площадь внутри пути окрашивается кистью, заданной свойством Fill у объекта Path
Создание линий с помощью PathGeometry:
<Grid> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Path Fill="LightPink" Stroke="Blue"> <Path.Data> <PathGeometry> <PathFigure IsClosed="True" StartPoint="10,100"> <LineSegment Point="100,100" /> <LineSegment Point="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> <Path Grid.Column="1" Fill="LightPink" Stroke="Blue"> <Path.Data> <PathGeometry> <PathFigure IsClosed="False" StartPoint="10,100"> <LineSegment Point="100,100" /> <LineSegment Point="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> <Path Grid.Row="1" Stroke="Blue"> <Path.Data> <PathGeometry> <PathFigure IsClosed="True" StartPoint="10,100"> <LineSegment Point="100,100" /> <LineSegment Point="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> <Path Grid.Row="1" Grid.Column="1" Fill="LightPink"> <Path.Data> <PathGeometry> <PathFigure StartPoint="10,100"> <LineSegment Point="100,100" /> <LineSegment Point="100,50" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Grid>
Управляя свойством IsClosed
мы можем получить как замкнутый, так и незамкнутый контур. А при применении свойства Fill
в элементе Path содержимое
контура заполняется цветом. Таким образом, мы можем получить не просто линию, а целостные фигуры, заполненные цветом.
<Grid> <Path Stroke="Blue"> <Path.Data> <PathGeometry> <PathFigure IsClosed="True" StartPoint="10,10"> <ArcSegment Point="250,50" Size="150,200" /> </PathFigure> </PathGeometry> </Path.Data> </Path> <Path Stroke="Red"> <Path.Data> <PathGeometry> <PathFigure IsClosed="False" StartPoint="10,110"> <ArcSegment Point="250,150" Size="150,200" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Grid>
Для создания дуги у ArcSegment задается свойство Point
, которое указывает на конечную точку дуги (начальная точка задается через свойство StartPoint элемента PathFigure),
а свойство Size
устанавливает размер окружностей, по которым строится дуга.
Кривые Безье представляют линии, для построения которых применяются сложные математические преобразования. В WPF кривые Безье представлены различными типами: простые и квадратичные кривые. Для построения кривых Безье используются начальная и конечная точки, а также ряд промежуточных точек:
<Grid> <Path Stroke="Blue"> <Path.Data> <PathGeometry> <PathFigure StartPoint="60,10"> <BezierSegment Point1="180,30" Point2="100,140" Point3="210,150" /> </PathFigure> </PathGeometry> </Path.Data> </Path> <Path Stroke="Red"> <Path.Data> <PathGeometry> <PathFigure IsClosed="False" StartPoint="10,110"> <QuadraticBezierSegment Point1="130,130" Point2="40,240" /> </PathFigure> </PathGeometry> </Path.Data> </Path> </Grid>
Начальная точка кривых устанавливается с помощью свойства StartPoint
элемента PathFigure. Для простой кривой Безье свойства Point1 и Point2 задают промежуточные точки, а Point3 является
конечной точкой. Для квадратичной кривой Point2 - конечная точка, а Point1 - промежуточная.
Также принят упрощенный вариант записи фигур. Например, следующее описание фигуры
<Path Stroke="Red"> <Path.Data> <PathGeometry> <PathFigure StartPoint="20,170"> <LineSegment Point="50,170" /> </PathFigure> </PathGeometry> </Path.Data> </Path>
можно написать следующим образом
<Path Data="M 20,170 L 50,170 Z" Stroke="Red" />
или
<Path Stroke="Red"> <Path.Data> <PathGeometry Figures="M 20,170 L 50,170 Z" /> </Path.Data> </Path>
Что в данном случае означате сокращенная запись?
M x,y | Создает новый объект PathFigure и указывает на его начальную точку |
Z | Завершает фигуру и устанавливает свойство IsClosed в true. Если же не требуется завершать фигуру, то вместо Z употребляется буква M |
L x,y | Создает объект LineSegment до указанной точки |
A raduisX, radiusY, degrees, isLargArc, IaClockwize, x,y | Создает новый объект ArcSegment с соответствующими параметрами |
С x1,y1,x2,y2,x,y | Создает новый объект BezierSegment по указанным точкам |
Q x1,y1, x,y | Создает новый объект QuadraticBezierSegment по указанным точкам |
S x1,y1, x,y | Создает новый объект BezierSegment по указанным точкам |
Создадим программно координатную плоскость с использованием объекта PathGeometry:
PathGeometry pathGeom =new PathGeometry(); Path p =new Path(); LineSegment vertLS =new LineSegment(); PathFigure vertPF =new PathFigure(); vertPF.StartPoint = new Point(10, 150); vertLS.Point = new Point(10, 10); vertPF.Segments.Add(vertLS); pathGeom.Figures.Add(vertPF); LineSegment horLS =new LineSegment(); PathFigure horPF =new PathFigure(); horPF.StartPoint = new Point(10, 150); horLS.Point = new Point(150, 150); horPF.Segments.Add(horLS); pathGeom.Figures.Add(horPF); for(byte i = 2;i< 14;i++) { PathFigure pf = new PathFigure(); pf.StartPoint = new Point(i * 10, 155); LineSegment a = new LineSegment(); a.Point = new Point(i * 10, 145); pf.Segments.Add(a); pathGeom.Figures.Add(pf); } for(byte i = 3;i< 15;i++) { PathFigure pf =new PathFigure(); pf.StartPoint = new Point(5, i * 10); LineSegment a =new LineSegment(); a.Point = new Point(15, i * 10); pf.Segments.Add(a); pathGeom.Figures.Add(pf); } PolyLineSegment vertArr =new PolyLineSegment(); vertArr.Points = new PointCollection(); vertArr.Points.Add(new Point(10, 10)); vertArr.Points.Add(new Point(15, 15)); PathFigure vertArrF =new PathFigure(); vertArrF.StartPoint = new Point(5, 15); vertArrF.Segments.Add(vertArr); pathGeom.Figures.Add(vertArrF); PolyLineSegment horArr = new PolyLineSegment(); horArr.Points = new PointCollection(); horArr.Points.Add(new Point(150, 150)); horArr.Points.Add(new Point(145, 155)); PathFigure horArrF = new PathFigure(); horArrF.StartPoint = new Point(145, 145); horArrF.Segments.Add(horArr); pathGeom.Figures.Add(horArrF); p.Data = pathGeom; p.Stroke = Brushes.Black; grid1.Children.Add(p);