как деформировать эллипс во время выполнения - PullRequest
0 голосов
/ 08 января 2011

я сначала извиняюсь за мой английский, я попытаюсь объяснить, что я хочу сделать, мне нужно нарисовать эллипс с wpf, который представляет ауру, и это "деформации", представляющие проблемные зоны в ней, короче говоря, эллипскоторые могут быть деформированы во время выполнения в определенных точках

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

¿я ясно выразился в своем языке?¿Есть ли простой способ сделать это?

Заранее спасибо

1 Ответ

0 голосов
/ 10 января 2011

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

Для этой демонстрации XAML прост:

<Canvas Name="canvas" Focusable="True" KeyDown="canvas_KeyDown" MouseDown="canvas_MouseDown" MouseMove="canvas_MouseMove" MouseUp="canvas_MouseUp"/>

и код:

public partial class EllipseDemo : Window
{
    const int resolution = 1000;
    const double major = 150;
    const double minor = 100;
    const double xOrigin = 200;
    const double yOrigin = 200;
    const double radius = 10;
    const double scale = 0.1;
    const double spread = 10;
    const double magnitude = 10;

    Path path;
    Ellipse controlPoint;
    LineSegment[] segments;
    double[] deformation;
    double[] perturbation;
    int controlPointIndex;

    public EllipseDemo()
    {
        InitializeComponent();

        segments = new LineSegment[resolution];
        deformation = new double[resolution];
        perturbation = new double[resolution];
        for (int i = 0; i < resolution; i++)
        {
            var x = i >= resolution / 2 ? i - resolution : i;
            perturbation[i] = magnitude * Math.Exp(-Math.Pow(scale * x, 2) / spread);
        }
        path = new Path();
        path.Stroke = new SolidColorBrush(Colors.Black);
        path.StrokeThickness = 5;
        CalculateEllipse();
        canvas.Children.Add(path);

        controlPoint = new Ellipse();
        controlPoint.Stroke = new SolidColorBrush(Colors.Red);
        controlPoint.Fill = new SolidColorBrush(Colors.Transparent);
        controlPoint.Width = 2 * radius;
        controlPoint.Height = 2 * radius;
        MoveControlPoint(0);
        canvas.Children.Add(controlPoint);

        canvas.Focus();
    }

    void CalculateEllipse()
    {
        for (int i = 0; i < resolution; i++)
        {
            double angle = 2 * Math.PI * i / resolution;
            double x = xOrigin + Math.Cos(angle) * (major + deformation[i]);
            double y = yOrigin + Math.Sin(angle) * (minor + deformation[i]);
            segments[i] = new LineSegment(new Point(x, y), true);
        }
        var figure = new PathFigure(segments[0].Point, segments, true);
        var figures = new PathFigureCollection();
        figures.Add(figure);
        var geometry = new PathGeometry();
        geometry.Figures = figures;
        path.Data = geometry;
    }

    void MoveControlPoint(int index)
    {
        controlPointIndex = index;
        Canvas.SetLeft(controlPoint, segments[index].Point.X - radius);
        Canvas.SetTop(controlPoint, segments[index].Point.Y - radius);
    }

    bool mouseDown;

    void canvas_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (Mouse.DirectlyOver != controlPoint)
            return;
        mouseDown = true;
        controlPoint.CaptureMouse();
    }

    void canvas_MouseMove(object sender, MouseEventArgs e)
    {
        if (!mouseDown)
            return;
        int index = FindNearestIndex(e.GetPosition(canvas));
        MoveControlPoint(index);
    }

    void canvas_MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!mouseDown)
            return;
        controlPoint.ReleaseMouseCapture();
        mouseDown = false;
    }

    private void canvas_KeyDown(object sender, KeyEventArgs e)
    {
        int delta = 0;
        switch (e.Key)
        {
            case Key.Up:
                delta = 1;
                break;
            case Key.Down:
                delta = -1;
                break;
        }
        if (delta == 0)
            return;
        int index = controlPointIndex;
        for (int i = 0; i < resolution; i++)
            deformation[(i + index) % resolution] += delta * perturbation[i];
        CalculateEllipse();
        MoveControlPoint(index);
    }

    int FindNearestIndex(Point point)
    {
        var min = double.PositiveInfinity;
        var index = -1;
        for (int i = 0; i < segments.Length; i++)
        {
            var vector = point - segments[i].Point;
            var distance = vector.LengthSquared;
            if (distance < min)
            {
                index = i;
                min = distance;
            }
        }
        return index;
    }
}

Этоработает в основном с Path, представленным отрезками и Ellipse в качестве контрольной точки.Мышь может перемещать контрольную точку вокруг эллипса, а затем клавиши со стрелками добавляют или удаляют постоянное возмущение.Все жестко запрограммировано, но если с математикой у вас все в порядке, она должна помочь вам начать работу.

Вот программа в действии:

Ellipse Demo

...