在二次贝塞尔曲线路径上寻找点

时间:2015-05-20 02:20:32

标签: c# wpf geometry

我正在尝试创建如下形状:

Spiral

对于螺旋曲线,我正在使用二次贝塞尔曲线段。

    PathGeometry pg1 = new PathGeometry();
    PathFigure pf1 = new PathFigure()
    {
        StartPoint = new Point(Convert.ToDouble(middle) + 500, Convert.ToDouble(middle) + 500)
    };
    PathSegmentCollection psc1= new PathSegmentCollection();
    QuadraticBezierSegment arcs1 = new QuadraticBezierSegment()
    {
        Point1 = new Point(100, 560),
        Point2 = new Point(pf.StartPoint.X - 300, pf.StartPoint.Y + 200)
    };
    psc1.Add(arcs1);
    pf1.Segments = psc1;
    pg1.Figures.Add(pf1);
    Path spiral1 = new Path()
    {
        Data = pg1,
        Stroke = Brushes.White,
        StrokeThickness = 1.5
    };
    MainScrn.Children.Add(spiral1);

为其中一个路径输出适当的曲线: animation path displayed

我确定我标记错了,但是上面的变量在哪里以及如何与贝塞尔曲线相关联。

Quadratic Bezier Curves Points

现在我想要的是曲线上的点。

Path with points on segment

我无法从对象那里收到。我试图收集这些点,以便我可以沿Bezier曲线的路径设置物体的运动动画,让它们停在曲线的不同点。我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:2)

假设您想要计算从pf1.StartPoint(P1)到arcs1.Point2(P3)的三次贝塞尔曲线的五分之一(或任何数量)的控制点{{1 (P2)。

你这样做:

  • 计算从P1到P2的直线的五分之一点,并称之为A
  • 计算从P2到P3的直线的五分之一点,并称之为B
  • 计算从A到B的直线的五分之一点,这就是你的答案。

你可以将它减少到polynomial formula,你可以将值插入并得到你的答案,但这可能更具几何直观性,你可以使用{{内置函数轻松实现它1}} class。

答案 1 :(得分:2)

这是完整的答案。我计算了路径的总长度,在路径上分布了30个点(感谢@samgak)。 我通过将长度除以段的数量来找到平均间隔像素长度,然后将其与每个点之间的递增计算(平均值与下一点)的数组进行比较。

这是输出。

proper curve

这是代码。

            PathGeometry pg1 = new PathGeometry();
            PathFigure pf1 = new PathFigure()
            {
                StartPoint = new Point(Convert.ToDouble(middle) + 500, Convert.ToDouble(middle) + 500)
            };
            PathSegmentCollection psc1= new PathSegmentCollection();
            QuadraticBezierSegment arcs1 = new QuadraticBezierSegment()
            {
                //Point1 = new Point(100, 560),
                Point1 = new Point(150, 480),
                Point2 = new Point(pf.StartPoint.X - 300, pf.StartPoint.Y + 200)
            };
            psc1.Add(arcs1);
            pf1.Segments = psc1;
            pg1.Figures.Add(pf1);
            Path spiral1 = new Path()
            {
                Data = pg1,
                Stroke = Brushes.White,
                StrokeThickness = 1.5
            };
            MainScrn.Children.Add(spiral1);
            Rectangle[] pnt = new Rectangle[30];
            float growth = (float)1 / (float)30;
            float loc = 0;
            MessageBox.Show(growth.ToString());
            double lenOfpath = 0;
            Point pntA = new Point(0, 0);
            int segments = 8; segments++;
            float avgspace = 0;
            for (int length = 0; length < pnt.Count(); length++)
            {
                pnt[length] = new Rectangle();
                pnt[length].Fill = Brushes.Red;
                pnt[length].Width = 10;
                pnt[length].Height = 10;
                double t = loc;
                double left = (1 - t) * (1 - t) * pf.StartPoint.X + 2 * (1 - t) * t * arcs1.Point1.X + t * t * arcs1.Point2.X;
                double top = (1 - t) * (1 - t) * pf.StartPoint.Y + 2 * (1 - t) * t * arcs1.Point1.Y + t * t * arcs1.Point2.Y;
                MainScrn.Children.Add(pnt[length]);
                Canvas.SetLeft(pnt[length], left);
                Canvas.SetTop(pnt[length], top);
                loc = loc + growth;
                if (length > 0)
                {
                    double x10 = Canvas.GetLeft(pnt[length - 1]);
                    double x20 = Canvas.GetLeft(pnt[length]);
                    double y10 = Canvas.GetTop(pnt[length - 1]);
                    double y20 = Canvas.GetTop(pnt[length]);
                    lenOfpath = lenOfpath + Math.Sqrt(Math.Pow(x20 - x10, 2) + Math.Pow(y20 - y10, 2));
                    avgspace = ((float)lenOfpath / (float)segments);
                }
            }
            for (int length = 1; length < pnt.Count(); length++)
            {

                double total = 0;
                double[] smallestpos = new double[pnt.Count()-1];
                for (int digger = length + 1; digger < pnt.Count(); digger++)
                {
                    double x11 = Canvas.GetLeft(pnt[length]);
                    double x22 = Canvas.GetLeft(pnt[digger]);
                    double y11 = Canvas.GetTop(pnt[length]);
                    double y22 = Canvas.GetTop(pnt[digger]);
                    smallestpos[digger-1] = Math.Sqrt(Math.Pow(x22 - x11, 2) + Math.Pow(y22 - y11, 2));
                }
                int takeposition = FindClosest(avgspace, smallestpos);
                double min = smallestpos[takeposition];
                while (length < (takeposition+1))
                {
                    pnt[length].Visibility = System.Windows.Visibility.Hidden;
                    length++;
                }
            }    
        }
        public static int FindClosest(float given_number, double[] listofflts)
        {
            // Start min_delta with first element because it's safer
            int min_index = 0;
            double min_delta = listofflts[0] - given_number;
            // Take absolute value of the min_delta
            if (min_delta < 0)
            {
                min_delta = min_delta * (-1);
            }

            // Iterate through the list of integers to find the minimal delta
            // Skip first element because min_delta is set with first element's
            for (int index = 1; index < listofflts.Count(); index++)
            {
                float cur_delta = (float)listofflts[index] - (float)given_number;
                // Take absolute value of the current delta
                if (cur_delta < 0)
                {
                    cur_delta = cur_delta * (-1);
                }

                // Update the minimum delta and save the index
                if (cur_delta < min_delta)
                {
                    min_delta = cur_delta;
                    min_index = index;
                }
            }
            return min_index;
        }

八角形:

completed.

完成所有方面后:

enter image description here