New tool Quadratic Bézier curve.

Issue #449 on hold
Roman Telezhynskyi repo owner created an issue

Add new tool Quadratic Bézier curve.

Possible code implementation:

//------------------------------------------------------------------------
   void curve3_div::init(double x1, double y1, 
                  double x2, double y2, 
                  double x3, double y3)
   {
      m_points.remove_all();
      m_distance_tolerance = 0.5 / m_approximation_scale;
      m_distance_tolerance *= m_distance_tolerance;
      bezier(x1, y1, x2, y2, x3, y3);
      m_count = 0;
   }


   //------------------------------------------------------------------------
   void curve3_div::recursive_bezier(double x1, double y1, 
                          double x2, double y2, 
                          double x3, double y3, 
                          unsigned level)
   {
      if(level > curve_recursion_limit) 
      {
        return;
      }

      // Вычислить все средние точки отрезков
      //----------------------
      double x12  = (x1 + x2) / 2;           
      double y12  = (y1 + y2) / 2;
      double x23  = (x2 + x3) / 2;
      double y23  = (y2 + y3) / 2;
      double x123  = (x12 + x23) / 2;
      double y123  = (y12 + y23) / 2;

      double dx = x3-x1;
      double dy = y3-y1;
      double d = fabs(((x2 - x3) * dy - (y2 - y3) * dx));

      if(d > curve_collinearity_epsilon)
      { 
        // Обыкновенный случай
        //-----------------
        if(d * d <= m_distance_tolerance * (dx*dx + dy*dy))
        {
           // Если “кривизна” не превышает значение distance_tolerance, 
           // то имеется тенденция завершить деление.
           //----------------------
           if(m_angle_tolerance < curve_angle_tolerance_epsilon)
           {
              m_points.add(point_type(x123, y123));
              return;
           }

           // Критерии угла и точки перегиба
           //----------------------
           double da = fabs(atan2(y3 - y2, x3 - x2)  
                      atan2(y2 - y1, x2 - x1));
           if(da >= pi) da = 2*pi - da;

           if(da < m_angle_tolerance)
           {
              // Наконец, можно остановить рекурсию
              //----------------------
              m_points.add(point_type(x123, y123));
              return;            
           }
        }
      }
      else
      {
        // Полностью коллинеарный случай
        //-----------------
        dx = x123 - (x1 + x3) / 2;
        dy = y123 - (y1 + y3) / 2;
        if(dx*dx + dy*dy <= m_distance_tolerance)
        {
           m_points.add(point_type(x123, y123));
           return;
        }
      }

      // Продолжить деление
      //----------------------
      recursive_bezier(x1, y1, x12, y12, x123, y123, level + 1); 
      recursive_bezier(x123, y123, x23, y23, x3, y3, level + 1); 
   }

   //------------------------------------------------------------------------
   void curve3_div::bezier(double x1, double y1, 
                   double x2, double y2, 
                   double x3, double y3)
  {
    m_points.add(point_type(x1, y1));
    recursive_bezier(x1, y1, x2, y2, x3, y3, 0);
    m_points.add(point_type(x3, y3));
  }

Comments (7)

  1. Barbara Weberkind

    In maths terms, 'quadratic bezier curve', in tailor's/textile designers terms, 'rounding out a corner' .. yes?

  2. naryl

    Not exactly. You can connect any two points with a quadratic bezier curve, there's no need for a third "corner" point between them.

  3. Log in to comment