@ -1050,6 +1050,7 @@ void ImDrawList::PathArcTo(const ImVec2& center, float radius, float a_min, floa
}
}
// Cubic bezier
ImVec2 ImBezierCalc ( const ImVec2 & p1 , const ImVec2 & p2 , const ImVec2 & p3 , const ImVec2 & p4 , float t )
{
float u = 1.0f - t ;
@ -1060,13 +1061,14 @@ ImVec2 ImBezierCalc(const ImVec2& p1, const ImVec2& p2, const ImVec2& p3, const
return ImVec2 ( w1 * p1 . x + w2 * p2 . x + w3 * p3 . x + w4 * p4 . x , w1 * p1 . y + w2 * p2 . y + w3 * p3 . y + w4 * p4 . y ) ;
}
// Cubic bezier
// Closely mimics BezierClosestPointCasteljauStep() in imgui.cpp
static void PathBezierToCasteljau ( ImVector < ImVec2 > * path , float x1 , float y1 , float x2 , float y2 , float x3 , float y3 , float x4 , float y4 , float tess_tol , int level )
{
float dx = x4 - x1 ;
float dy = y4 - y1 ;
float d2 = ( ( x2 - x4 ) * dy - ( y2 - y4 ) * dx ) ;
float d3 = ( ( x3 - x4 ) * dy - ( y3 - y4 ) * dx ) ;
float d2 = ( x2 - x4 ) * dy - ( y2 - y4 ) * dx ;
float d3 = ( x3 - x4 ) * dy - ( y3 - y4 ) * dx ;
d2 = ( d2 > = 0 ) ? d2 : - d2 ;
d3 = ( d3 > = 0 ) ? d3 : - d3 ;
if ( ( d2 + d3 ) * ( d2 + d3 ) < tess_tol * ( dx * dx + dy * dy ) )
@ -1075,17 +1077,18 @@ static void PathBezierToCasteljau(ImVector<ImVec2>* path, float x1, float y1, fl
}
else if ( level < 10 )
{
float x12 = ( x1 + x2 ) * 0.5f , y12 = ( y1 + y2 ) * 0.5f ;
float x23 = ( x2 + x3 ) * 0.5f , y23 = ( y2 + y3 ) * 0.5f ;
float x34 = ( x3 + x4 ) * 0.5f , y34 = ( y3 + y4 ) * 0.5f ;
float x123 = ( x12 + x23 ) * 0.5f , y123 = ( y12 + y23 ) * 0.5f ;
float x234 = ( x23 + x34 ) * 0.5f , y234 = ( y23 + y34 ) * 0.5f ;
float x1234 = ( x123 + x234 ) * 0.5f , y1234 = ( y123 + y234 ) * 0.5f ;
PathBezierToCasteljau ( path , x1 , y1 , x12 , y12 , x123 , y123 , x1234 , y1234 , tess_tol , level + 1 ) ;
PathBezierToCasteljau ( path , x1234 , y1234 , x234 , y234 , x34 , y34 , x4 , y4 , tess_tol , level + 1 ) ;
float x12 = ( x1 + x2 ) * 0.5f , y12 = ( y1 + y2 ) * 0.5f ;
float x23 = ( x2 + x3 ) * 0.5f , y23 = ( y2 + y3 ) * 0.5f ;
float x34 = ( x3 + x4 ) * 0.5f , y34 = ( y3 + y4 ) * 0.5f ;
float x123 = ( x12 + x23 ) * 0.5f , y123 = ( y12 + y23 ) * 0.5f ;
float x234 = ( x23 + x34 ) * 0.5f , y234 = ( y23 + y34 ) * 0.5f ;
float x1234 = ( x123 + x234 ) * 0.5f , y1234 = ( y123 + y234 ) * 0.5f ;
PathBezierToCasteljau ( path , x1 , y1 , x12 , y12 , x123 , y123 , x1234 , y1234 , tess_tol , level + 1 ) ;
PathBezierToCasteljau ( path , x1234 , y1234 , x234 , y234 , x34 , y34 , x4 , y4 , tess_tol , level + 1 ) ;
}
}
// Cubic bezier
void ImDrawList : : PathBezierCurveTo ( const ImVec2 & p2 , const ImVec2 & p3 , const ImVec2 & p4 , int num_segments )
{
ImVec2 p1 = _Path . back ( ) ;
@ -1101,6 +1104,51 @@ void ImDrawList::PathBezierCurveTo(const ImVec2& p2, const ImVec2& p3, const ImV
}
}
// Quadratic bezier
ImVec2 ImQuadBezierCalc ( const ImVec2 & p1 , const ImVec2 & p2 , const ImVec2 & p3 , float t )
{
float u = 1.0f - t ;
float w1 = u * u ;
float w2 = 2 * u * t ;
float w3 = t * t ;
return ImVec2 ( w1 * p1 . x + w2 * p2 . x + w3 * p3 . x , w1 * p1 . y + w2 * p2 . y + w3 * p3 . y ) ;
}
// Quadratic bezier
static void PathQuadBezierToCasteljau ( ImVector < ImVec2 > * path , float x1 , float y1 , float x2 , float y2 , float x3 , float y3 , float tess_tol , int level )
{
float dx = x3 - x1 , dy = y3 - y1 ;
float det = ( x2 - x3 ) * dy - ( y2 - y3 ) * dx ;
if ( det * det * 4.0f < tess_tol * ( dx * dx + dy * dy ) )
{
path - > push_back ( ImVec2 ( x3 , y3 ) ) ;
}
else if ( level < 10 )
{
float x12 = ( x1 + x2 ) * 0.5f , y12 = ( y1 + y2 ) * 0.5f ;
float x23 = ( x2 + x3 ) * 0.5f , y23 = ( y2 + y3 ) * 0.5f ;
float x123 = ( x12 + x23 ) * 0.5f , y123 = ( y12 + y23 ) * 0.5f ;
PathQuadBezierToCasteljau ( path , x1 , y1 , x12 , y12 , x123 , y123 , tess_tol , level + 1 ) ;
PathQuadBezierToCasteljau ( path , x123 , y123 , x23 , y23 , x3 , y3 , tess_tol , level + 1 ) ;
}
}
// Quadratic bezier
void ImDrawList : : PathQuadBezierCurveTo ( const ImVec2 & p2 , const ImVec2 & p3 , int num_segments )
{
ImVec2 p1 = _Path . back ( ) ;
if ( num_segments = = 0 )
{
PathQuadBezierToCasteljau ( & _Path , p1 . x , p1 . y , p2 . x , p2 . y , p3 . x , p3 . y , _Data - > CurveTessellationTol , 0 ) ; // Auto-tessellated
}
else
{
float t_step = 1.0f / ( float ) num_segments ;
for ( int i_step = 1 ; i_step < = num_segments ; i_step + + )
_Path . push_back ( ImQuadBezierCalc ( p1 , p2 , p3 , t_step * i_step ) ) ;
}
}
void ImDrawList : : PathRect ( const ImVec2 & a , const ImVec2 & b , float rounding , ImDrawCornerFlags rounding_corners )
{
rounding = ImMin ( rounding , ImFabs ( b . x - a . x ) * ( ( ( rounding_corners & ImDrawCornerFlags_Top ) = = ImDrawCornerFlags_Top ) | | ( ( rounding_corners & ImDrawCornerFlags_Bot ) = = ImDrawCornerFlags_Bot ) ? 0.5f : 1.0f ) - 1.0f ) ;
@ -1310,6 +1358,17 @@ void ImDrawList::AddNgonFilled(const ImVec2& center, float radius, ImU32 col, in
PathFillConvex ( col ) ;
}
// Quad Bezier takes 3 controls points
void ImDrawList : : AddQuadBezierCurve ( const ImVec2 & p1 , const ImVec2 & p2 , const ImVec2 & p3 , ImU32 col , float thickness , int num_segments )
{
if ( ( col & IM_COL32_A_MASK ) = = 0 )
return ;
PathLineTo ( p1 ) ;
PathQuadBezierCurveTo ( p2 , p3 , num_segments ) ;
PathStroke ( col , false , thickness ) ;
}
// Cubic Bezier takes 4 controls points
void ImDrawList : : AddBezierCurve ( const ImVec2 & p1 , const ImVec2 & p2 , const ImVec2 & p3 , const ImVec2 & p4 , ImU32 col , float thickness , int num_segments )
{