Вращение фигур в WPF

415
27 февраля 2017, 10:38

Есть у меня пятиконечная звезда.

<ed:RegularPolygon x:Name="regularPolygon" Fill="{StaticResource RatingButtonNormalFill}" InnerRadius="0.55" PointCount="5" Stroke="Black" 
                       StrokeThickness="0.5" RenderTransformOrigin="0.5,0.5" Width="{TemplateBinding ActualWidth}" Height="{TemplateBinding ActualHeight}">

Есть с ней проблема. На форме она маленькая (20х20) и она при клике вращается. Так вот при вращении она как бы сдвигается немного.

Я полагаю, что это из-за того, что когда звезда вращается, размеры описывающего ее ректа меняются (ведь контейнер не вращается вместе с ней) и она на ходу подгоняет свои размеры. Пока не знаю, что с этим делать. Может, причина и не в этом.

UPD

С причиной я угадал. Звезда не вписывается в квадрат. Вот, я покажу на примере правильного пятиугольника и квадрата что происходит. Вот изображение без поворота.

А вот я повернул пятиугольник на 72 градуса (то есть чтобы наверху оказалась следующая его вершина).

Пока не знаю что делать с этим.

UPD2

Короче геометрическое решение нашел... надо только как то в xaml это перенести. Суть в том, что квадрат, в котором у меня находится звезда, должен описывать круг, в который вписана звезда. Как это перенести в xaml я не знаю :(

UPD3

Нужно перенести центр вращения в центр круга, описывающего звезду. Самого круга конечно же нет. Надо изменить свойство RenderTransformOrigin="0.5,0.5", но я пока не знаю на что

Answer 1

Класс RegularPolygon, к сожалению, никуда не годится: он не центрирует фигуру вокруг геометрического центра, а наоборот растягивает свою высоту и ширину, так что получается вовсе не правильный многоугольник!

Чтобы было правильно, проще всего посчитать самому. У меня работает такой код:

<Grid Background="#D08435">
    <Path Data="M -1,-1
                M 0,-1
                L 0.95105651629515357211643933337938,-0.30901699437494742410229341718282
                L 0.58778525229247312916870595463907,0.80901699437494742410229341718282
                L -0.58778525229247312916870595463907,0.80901699437494742410229341718282
                L -0.95105651629515357211643933337938,-0.30901699437494742410229341718282
                L 0,-1
                M 1,1"
          Stretch="Uniform" 
          Fill="#7093D0"
          RenderTransformOrigin="0.5,0.5"/>
</Grid>

(Коэффициенты при L — синусы и косинусы углов, кратных 72°.)

Я добавил вращение к Path, получилось вот что:

Если нужен переменный внутренний радиус, проще, наверное, сделать через конвертер.

class StarGeometryConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter,
                          CultureInfo culture)
    {
        return CreateStarGeometry((int)parameter, (double)value);
    }
    Geometry CreateStarGeometry(int numberOfVertices, double innerRadius)
    {
        var edge1 = new PathFigure() { StartPoint = new Point(-1, -1) };
        var edge2 = new PathFigure() { StartPoint = new Point(1, 1) };
        var segments = new List<PathSegment>();
        var step = Math.PI * 2 / numberOfVertices;
        foreach (var angle in Enumerable.Range(0, numberOfVertices).Select(n => n * step))
        {
            segments.Add(new LineSegment(
                             new Point(Math.Sin(angle),
                                       -Math.Cos(angle)),
                             isStroked: true));
            segments.Add(new LineSegment(
                             new Point(innerRadius * Math.Sin(angle + step / 2),
                                       -innerRadius * Math.Cos(angle + step / 2)),
                             isStroked: true));
        }
        var figure = new PathFigure(new Point(0, -1), segments, closed: true);
        return new PathGeometry(new[] { edge1, figure, edge2 });
    }
    public object ConvertBack(object value, Type targetType, object parameter,
                              CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

С ним получаем такой XAML:

<Window.Resources>
    <sys:Int32 x:Key="NumberOfVertices">5</sys:Int32>
    <sys:Double x:Key="InnerRadius">0.6</sys:Double>
    <local:StarGeometryConverter x:Key="StarConverter"/>
</Window.Resources>
<Grid Background="#D08435">
    <Path Data="{Binding Source={StaticResource InnerRadius},
                         Converter={StaticResource StarConverter},
                         ConverterParameter={StaticResource NumberOfVertices}}"
          Stretch="Uniform" 
          Fill="#7093D0"
          RenderTransformOrigin="0.5,0.5"/>
</Grid>

Результат:

READ ALSO
Гексагональная сетка

Гексагональная сетка

ВопросКак можно реализовать визуализацию гексагональной сетки на WPF, при том что каждая клеточка этой сетки является отдельным объектом,...

333
C# Наследование

C# Наследование

Решал задачу по наследованию на: http://skillsitvdn

294
Many To Many laravel отношения

Many To Many laravel отношения

Имеются 2 таблицыproducts и regions с таким содержимым

297
Как настроить отношения User Model в Laravel 5.4?

Как настроить отношения User Model в Laravel 5.4?

Имеется две моделиUser (получена в результате make:auth) и Ad

286