我一直试图做这一整天。基本上,我有一条线和一个点。我想让曲线通过那个点,但我不想要一条光滑的曲线。我不能定义曲线中的步数,就像这样(小心粗糙mspaint绘图): 迭代平滑曲线
等等。我尝试了各种各样的东西,比如从初始线的中心取出角度,然后在角度位置处将线分开,但是我的长度有问题。我只是将最初的长度除以我所在的步数,但这并不完全正确。
任何人都知道一种方法来做到这一点?
谢谢。
我一直试图做这一整天。基本上,我有一条线和一个点。我想让曲线通过那个点,但我不想要一条光滑的曲线。我不能定义曲线中的步数,就像这样(小心粗糙mspaint绘图): 迭代平滑曲线
等等。我尝试了各种各样的东西,比如从初始线的中心取出角度,然后在角度位置处将线分开,但是我的长度有问题。我只是将最初的长度除以我所在的步数,但这并不完全正确。
任何人都知道一种方法来做到这一点?
谢谢。
你可能需要自己编码。我认为你可以通过在代码中实现二次贝塞尔曲线函数来实现,可以找到here。你只需要解决一些数值就可以决定你想要的增量。如果你想要一条直线,只求解0和1,并用线连接这些点。如果你想要一个角度的例子,求解0,0.5和1,并按顺序连接点。如果你希望你的第三个例子,解决0,0.25,0.5,0.75,1。它可能是最好把它放在一个循环是这样的:
float stepValue = (float)0.25;
float lastCalculatedValue;
for (float t = 0; t <= 1; t += stepValue)
{
// Solve the quadratic bezier function to get the point at t.
// If this is not the first point, connect it to the previous point with a line.
// Store the new value in lastCalculatedValue.
}
编辑:其实,它看起来像你希望线路通过您的控制点。如果是这种情况,你不想使用二次贝塞尔曲线。相反,你可能需要拉格朗日曲线。这个网站可能会对等式有所帮助:http://www.math.ucla.edu/~baker/java/hoefer/Lagrange.htm。但无论哪种情况,您都可以使用相同类型的循环来控制平滑度。
2nd编辑:这似乎工作。只需将numberOfSteps成员更改为所需线段的总数并适当设置点数组。顺便说一下,你可以使用三点以上。它只会分配线段的总数。但是我初始化了数组,以便结果看起来像你最后一个例子。
第3编辑:我更新了一下代码,所以你可以在表单上点击左键添加点并右键点击删除最后一点。另外,我在底部添加了一个NumericUpDown,以便您可以在运行时更改段的数量。
public class Form1 : Form
{
private int numberOfSegments = 4;
private double[,] multipliers;
private List<Point> points;
private NumericUpDown numberOfSegmentsUpDown;
public Form1()
{
this.numberOfSegmentsUpDown = new NumericUpDown();
this.numberOfSegmentsUpDown.Value = this.numberOfSegments;
this.numberOfSegmentsUpDown.ValueChanged += new System.EventHandler(this.numberOfSegmentsUpDown_ValueChanged);
this.numberOfSegmentsUpDown.Dock = DockStyle.Bottom;
this.Controls.Add(this.numberOfSegmentsUpDown);
this.points = new List<Point> {
new Point(100, 110),
new Point(50, 60),
new Point(100, 10)};
this.PrecomputeMultipliers();
}
public void PrecomputeMultipliers()
{
this.multipliers = new double[this.points.Count, this.numberOfSegments + 1];
double pointCountMinusOne = (double)(this.points.Count - 1);
for (int currentStep = 0; currentStep <= this.numberOfSegments; currentStep++)
{
double t = currentStep/(double)this.numberOfSegments;
for (int pointIndex1 = 0; pointIndex1 < this.points.Count; pointIndex1++)
{
double point1Weight = pointIndex1/pointCountMinusOne;
double currentMultiplier = 1;
for (int pointIndex2 = 0; pointIndex2 < this.points.Count; pointIndex2++)
{
if (pointIndex2 == pointIndex1)
continue;
double point2Weight = pointIndex2/pointCountMinusOne;
currentMultiplier *= (t - point2Weight)/(point1Weight - point2Weight);
}
this.multipliers[pointIndex1, currentStep] = currentMultiplier;
}
}
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Point? previousPoint = null;
for (int currentStep = 0; currentStep <= numberOfSegments; currentStep++)
{
double sumX = 0;
double sumY = 0;
for (int pointIndex = 0; pointIndex < points.Count; pointIndex++)
{
sumX += points[pointIndex].X * multipliers[pointIndex, currentStep];
sumY += points[pointIndex].Y * multipliers[pointIndex, currentStep];
}
Point newPoint = new Point((int)Math.Round(sumX), (int)Math.Round(sumY));
if (previousPoint.HasValue)
e.Graphics.DrawLine(Pens.Black, previousPoint.Value, newPoint);
previousPoint = newPoint;
}
for (int pointIndex = 0; pointIndex < this.points.Count; pointIndex++)
{
Point point = this.points[pointIndex];
e.Graphics.FillRectangle(Brushes.Black, new Rectangle(point.X - 1, point.Y - 1, 2, 2));
}
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
if (e.Button == MouseButtons.Left)
{
this.points.Add(e.Location);
}
else
{
this.points.RemoveAt(this.points.Count - 1);
}
this.PrecomputeMultipliers();
this.Invalidate();
}
private void numberOfSegmentsUpDown_ValueChanged(object sender, EventArgs e)
{
this.numberOfSegments = (int)this.numberOfSegmentsUpDown.Value;
this.PrecomputeMultipliers();
this.Invalidate();
}
}
非常感谢,完美的作品! – 2010-11-15 01:33:00
你可以去周围的其他方法:先找到一个匹配的曲线,然后用积分曲线上画出的线条。例如:
通过以下方式获得该地块:
假设你有三个出发点{x0,0},{X1,Y1},{2,0}
然后,您会发现两条相交于{x1,y1}的抛物线曲线,并具有在该点具有最大值的额外条件(用于平滑过渡)。这些曲线是:
yLeft[x_] := a x^2 + b x + c;
yRight[x_] := d x^2 + e x + f;
如果我们发现(经过一番演算):
{c -> -((-x0^2 y1 + 2 x0 x1 y1)/(x0 - x1)^2),
a -> -(y1/(x0 - x1)^2),
b -> (2 x1 y1)/(-x0 + x1)^2}
和
{f -> -((2 x1 x2 y1 - x2^2 y1)/(x1 - x2)^2),
d -> -(y1/(x1 - x2)^2),
e -> (2 x1 y1)/(x1 - x2)^2}
所以我们有两条曲线。
现在你应该注意到,如果你想要你的点数相等的距离,x1/x2应该是一个有理数。你的步数选择是有限的。您可以从x0开始选择通过x1和x2传递的步骤。 (那些形式为x1 /(n * x2))
而就是这样。现在,根据x1的哪一边,根据点{x,yLeft [x]}或{x,yRight [x]}来形成线条。
注意:您可能选择只绘制一条经过您的三点的抛物线,但在一般情况下会导致高度不对称。
如果点X1是在中间,结果也比较好:
谢谢你的回答! – 2010-11-15 01:33:36
我不能这样做了专题公正,但如果你看看贝塞尔曲线,以及如何你会得到良好的信息以形成它们。你可以按照你的建议进行迭代,但是有更好的方法来计算曲线。 – 2010-11-08 02:46:41
我希望能够控制曲线中的线段数量。 – 2010-11-08 02:54:30
曲线具有无限数量的“分段”。您选择评估并渲染线条的点数仍然取决于您。 – 2010-11-08 03:03:26