Дан круг радиуса R (радиус задается пользователем). Также задается градус, число от 0 до 360. Надо нарисовать дугу вот этого заданного угла. 360 полный круг, 180 половина, это понятно.
Делал через CombinedGeometry (GeometryCombineMode: Intersect) - делал PathFigure из LineSegment, ArcSegment, LineSegment в такой последовательности. С использованием Transform, крутил линии и между ними рисовался этот ArcSegment.
Извините код, который написал не могу привести здесь, под рукой нет. Обобщенно выглядит так - надо нарисовать дугу заданного угла, т.е. дан круг, дуга будет представлять часть круга. Вот думаю, без всех этих CombinedGeometry, используя в основном один ArcSegment можно будет реализовать аккуратно. Может кто сталкивался с такой задачкой.
- 1,580
- 11
- 22
2 Answers
Можно сделать проще, без поворотов, только придётся немного вспомнить тригонометрию.
Вот вам пример, с углами в 60 градусов:
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<Path Stroke="Red" StrokeThickness="2">
<Path.Data>
<PathGeometry
Figures="M 100 100 l 100 0 a 100 100 60 0 1 -50 86.6 z"/>
</Path.Data>
</Path>
<Path Stroke="Red" StrokeThickness="2">
<Path.Data>
<PathGeometry>
<PathGeometry.Figures>
<PathFigure StartPoint="100,100" IsClosed="True">
<LineSegment Point="200,100"/>
<ArcSegment Point="150,186.6" RotationAngle="60"
Size="100,100" IsLargeArc="False"
SweepDirection="Clockwise"/>
</PathFigure>
</PathGeometry.Figures>
</PathGeometry>
</Path.Data>
</Path>
</StackPanel>
</Page>
Получаются такие дуги:

- 206,799
Решил добавить, вдруг кому пригодится: ниже представлен код, который я делал с поворотами и трансформациями. Это часть кода из редактора, поэтому не смущайтесь по поводу координат и прочего, но думаю основной смысл будет понятен.
RotateTransform transformStart;
RotateTransform transformEnd;
rx = 0.5 * radius;
// Расчитываем угол поворота и определяем параметры нашим "трансформаторам"
double angle = ((valSegment - minimalValue) / (maximalValue - minimalValue)) * sizeSegment;
transStart.Angle = 360 - (sizeSegment / 2);
transStart.CenterX = origin.X + rx;
transStart.CenterY = origin.Y + rx;
transEnd.Angle = sizeSegment;
transEnd.CenterX = origin.X + rx;
transEnd.CenterY = origin.Y + rx;
Pen penContur = new Pen(ColorCountur, thiknessContour);
DrawingContext dc = Drawing.Open();
EllipseGeometry ell = new EllipseGeometry();
ell.Center = new Point((origin.X + rx +rx)-rx, origin.Y + rx);
ell.RadiusX = rx;
ell.RadiusY = rx;
LineGeometry lineGem = new LineGeometry();
lineGem.StartPoint = new Point(origin.X + rx, origin.Y + rx);
lineGem.EndPoint = new Point(origin.X + rx, origin.Y + (-rx));
dc.PushTransform(transStart);
Point transPoint = transEnd.Transform(lineGem.EndPoint);
Point start = new Point(lineGem.EndPoint.X, lineGem.EndPoint.Y);
ArcSegment arcs = new ArcSegment(new Point(transPoint.X, transPoint.Y), new Size(radius, radius), 0, true, SweepDirection.Clockwise, true);
start = new Point(origin.X + rx, origin.Y + rx);
LineSegment segLine1 = new LineSegment(new Point(lineGem.EndPoint.X, lineGem.EndPoint.Y), false);
LineSegment segLine2 = new LineSegment(new Point(transPoint.X, transPoint.Y), false);
PathFigure figure = new PathFigure(start, new PathSegment[] { segLine1, arcs, segLine2 }, false);
PathGeometry geo = new PathGeometry(new PathFigure[] { figure });
CombinedGeometry comb = new CombinedGeometry(GeometryCombineMode.Intersect, ell, geo);
dc.DrawGeometry(Brushes.White, penContur, comb);
Теперь благодаря VladD, без трасформаций и комбинаций, делаю так:
// вычисляем новые координаты
public Point GetCoordinate(double angle, double radius)
{
double newAngle = (Math.PI / 180.0) * (angle - 90);
double rx = radius * Math.Cos(newAngle);
double ry = radius * Math.Sin(newAngle);
return new Point(rx, ry);
}
затем просто в ArcSegment подставляем все необходимое. Как-то так.
- 1,580
- 11
- 22
-
Мсье знает толк в извращениях) – AlexeyM Feb 20 '13 at 13:12