Wpf 如何在运行时使椭圆变形
首先我对我的英语感到抱歉,我会尽力解释我想做什么 我需要用wpf画一个椭圆,它代表一个光环,它的“变形”代表其中有问题的区域,简言之,一个椭圆可以在特定点的运行时间内变形 我试图画几个贝塞尔曲线形成一个椭圆,但它不是很难(我不知道如何)使点可以被拖动形成该椭圆的凸区或空心区 我用西班牙式英语说得很清楚?有没有简单的方法Wpf 如何在运行时使椭圆变形,wpf,ellipse,Wpf,Ellipse,首先我对我的英语感到抱歉,我会尽力解释我想做什么 我需要用wpf画一个椭圆,它代表一个光环,它的“变形”代表其中有问题的区域,简言之,一个椭圆可以在特定点的运行时间内变形 我试图画几个贝塞尔曲线形成一个椭圆,但它不是很难(我不知道如何)使点可以被拖动形成该椭圆的凸区或空心区 我用西班牙式英语说得很清楚?有没有简单的方法 提前感谢我不知道您到底想做什么,但我建议您制作一个高分辨率的椭圆版本,并自己跟踪变形。下面是一个示例程序,让您开始学习 对于本演示,XAML非常简单: <Canvas Na
提前感谢我不知道您到底想做什么,但我建议您制作一个高分辨率的椭圆版本,并自己跟踪变形。下面是一个示例程序,让您开始学习 对于本演示,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;
}
}
公共分部类EllipseDemo:窗口
{
常数int分辨率=1000;
常量双大调=150;
常数双小调=100;
常数双xOrigin=200;
双约里金常数=200;
常数双半径=10;
常数双刻度=0.1;
常数双排列=10;
常数双倍震级=10;
路径;
椭圆控制点;
线段[]段;
双[]变形;
双[]微扰;
int控制点索引;
公共EllipseDemo()
{
初始化组件();
线段=新线段[分辨率];
变形=新的双[分辨率];
扰动=新的双[分辨率];
对于(int i=0;i<分辨率;i++)
{
var x=i>=分辨率/2?i-分辨率:i;
扰动[i]=震级*Math.Exp(-Math.Pow(标度*x,2)/spread;
}
路径=新路径();
path.Stroke=新的SolidColorBrush(Colors.Black);
path.StrokeThickness=5;
计算椭圆();
canvas.Children.Add(路径);
控制点=新椭圆();
controlPoint.Stroke=新的SolidColorBrush(Colors.Red);
controlPoint.Fill=新的SolidColorBrush(Colors.Transparent);
控制点。宽度=2*半径;
控制点。高度=2*半径;
移动控制点(0);
canvas.Children.Add(控制点);
canvas.Focus();
}
void CalculateEllipse()
{
对于(int i=0;i<分辨率;i++)
{
双角度=2*Math.PI*i/分辨率;
双x=xOrigin+Math.Cos(角度)*(主要+变形[i]);
双y=约里金+数学正弦(角度)*(微小+变形[i]);
线段[i]=新线段(新点(x,y),真);
}
var figure=新路径图(段[0]。点,段,真);
var figures=新路径figurescollection();
图.增加(图);
var geometry=新路径几何体();
几何。数字=数字;
路径数据=几何体;
}
void MoveControlPoint(int索引)
{
controlPointIndex=索引;
SetLeft(控制点,段[index].Point.X-半径);
SetTop(控制点,段[index].Point.Y-半径);
}
布尔·穆斯敦;
void canvas_MouseDown(对象发送器,MouseButtonEventArgs e)
{
if(Mouse.DirectlyOver!=控制点)
返回;
mouseDown=true;
controlPoint.CaptureMouse();
}
void canvas_MouseMove(对象发送器,MouseEventArgs e)
{
如果(!mouseDown)
返回;
int index=FindNearestIndex(例如GetPosition(canvas));
移动控制点(索引);
}
void canvas_MouseUp(对象发送器,MouseButtonEventArgs e)
{
如果(!mouseDown)
返回;
controlPoint.ReleaseMouseCapture();
mouseDown=false;
}
私有void canvas_KeyDown(对象发送方,KeyEventArgs e)
{
int delta=0;
开关(电子钥匙)
{
case Key.Up:
δ=1;
打破
case Key.Down:
delta=-1;
打破
}
如果(增量==0)
返回;
int index=控制点索引;
对于(int i=0;i<分辨率;i++)
变形[(i+指数)%resolution]+=delta*扰动[i];
计算椭圆();
移动控制点(索引);
}
int FindNearestIndex(点-点)
{
var min=双正不确定性;
var指数=-1;
对于(int i=0;i
这主要适用于由线段表示的路径
,以及作为控制点的椭圆。鼠标可以围绕椭圆移动控制点,然后用箭头键添加或删除一个固定的扰动。一切都是硬编码的,但若你们对数学没问题,那个么它应该可以帮助你们开始
以下是正在实施的计划:
谢谢,很抱歉,我会尝试回答,但我认为这正是我需要的!