Có thể bạn sẽ cần phải tự mình viết mã này. Tôi nghĩ rằng bạn có thể làm điều đó bằng cách thực hiện một hàm đường cong bezier bậc hai trong mã, có thể được tìm thấy here. Bạn quyết định như thế nào tốt bạn muốn gia số bằng cách chỉ giải quyết cho một vài giá trị. Nếu bạn muốn một đường thẳng, chỉ giải quyết cho 0 và 1 và kết nối những điểm đó với các dòng. Nếu bạn muốn ví dụ một góc, hãy giải quyết cho 0, 0.5 và 1 và kết nối các điểm theo thứ tự. Nếu bạn muốn ví dụ thứ ba của bạn, giải quyết cho 0, 0,25, 0,5, 0,75, và 1. Đó có lẽ sẽ là tốt nhất để đặt nó trong một vòng lặp for như thế này:
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.
}
Edit: Trên thực tế, có vẻ như bạn muốn dòng đi qua điểm kiểm soát của bạn. Nếu đúng như vậy, bạn không muốn sử dụng đường cong bezier bậc hai. Thay vào đó, bạn có thể muốn có một đường cong Lagrange. Trang web này có thể giúp với phương trình: http://www.math.ucla.edu/~baker/java/hoefer/Lagrange.htm. Nhưng trong cả hai trường hợp, bạn có thể sử dụng cùng một loại vòng lặp để kiểm soát mức độ êm ái.
Chỉnh sửa lần 2: Điều này dường như hoạt động. Chỉ cần thay đổi thành viên numberOfSteps thành tổng số các đoạn thẳng mà bạn muốn và thiết lập mảng điểm một cách thích hợp. Nhân tiện, bạn có thể sử dụng nhiều hơn ba điểm. Nó sẽ chỉ phân phối tổng số phân đoạn dòng trên chúng. Nhưng tôi đã khởi tạo mảng để kết quả trông giống như ví dụ cuối cùng của bạn.
Chỉnh sửa thứ ba: Tôi đã cập nhật mã một chút để bạn có thể nhấp chuột trái vào biểu mẫu để thêm điểm và nhấp chuột phải để xóa điểm cuối cùng. Ngoài ra, tôi đã thêm một NumericUpDown ở phía dưới để bạn có thể thay đổi số lượng phân đoạn khi chạy.
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();
}
}
Tôi không thể làm công lý chủ đề, nhưng bạn sẽ nhận được thông tin tốt nếu bạn nhìn lên đường cong Bezier và làm thế nào để tạo thành chúng. Bạn có thể lặp lại như bạn đề xuất, nhưng có những phương pháp tốt hơn cho các đường cong tính toán. –
Tôi muốn có thể kiểm soát số lượng phân đoạn trong đường cong. –
Đường cong có số lượng 'phân đoạn' vô hạn. Số điểm bạn đã chọn để đánh giá và sau đó hiển thị các đường giữa vẫn tùy thuộc vào bạn. –