2

Дан круг радиуса R (радиус задается пользователем). Также задается градус, число от 0 до 360. Надо нарисовать дугу вот этого заданного угла. 360 полный круг, 180 половина, это понятно.
Делал через CombinedGeometry (GeometryCombineMode: Intersect) - делал PathFigure из LineSegment, ArcSegment, LineSegment в такой последовательности. С использованием Transform, крутил линии и между ними рисовался этот ArcSegment.
Извините код, который написал не могу привести здесь, под рукой нет. Обобщенно выглядит так - надо нарисовать дугу заданного угла, т.е. дан круг, дуга будет представлять часть круга. Вот думаю, без всех этих CombinedGeometry, используя в основном один ArcSegment можно будет реализовать аккуратно. Может кто сталкивался с такой задачкой.

ghost rider
  • 1,580
  • 11
  • 22

2 Answers2

5

Можно сделать проще, без поворотов, только придётся немного вспомнить тригонометрию.

Вот вам пример, с углами в 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>

Получаются такие дуги:
две дуги по 60 градусов

VladD
  • 206,799
0

Решил добавить, вдруг кому пригодится: ниже представлен код, который я делал с поворотами и трансформациями. Это часть кода из редактора, поэтому не смущайтесь по поводу координат и прочего, но думаю основной смысл будет понятен.

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 подставляем все необходимое. Как-то так.

ghost rider
  • 1,580
  • 11
  • 22