void CBCStroke::Draw(CDC* pDC) { BEZIERSTROKE::iterator it; for(it=m_bezStroke.begin();it!=m_bezStroke.end();++it){ DrawBezierCurve(pDC,*it); } }
//******************************************************************************************************** void CBCStroke::Draw(FCObjImage& img,BYTE alpha,float zoompaper,float zoompress) { //m_vb.BeginOneStrokeDraw(img.GetPaper()); BEZIERSTROKE::iterator it; int w=img.Width(); int h=img.Height(); img.Stretch(w*3,h*3); for(it=m_bezStroke.begin();it!=m_bezStroke.end();++it){ DrawBezierCurve(img,*it,alpha,zoompaper*3,zoompress*3); } img.AntiAliased_Zoom(3); //m_vb.EndOneStrokeDraw(img.GetPaper()); }
/* * FitCubic : * Fit a Bezier curve to a (sub)set of digitized points */ static void FitCubic(Point2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error, BezierContour &bezContour) { BezierCurve bezCurve; /*Control points of fitted Bezier curve*/ double *u; /* Parameter values for point */ double *uPrime; /* Improved parameter values */ double maxError; /* Maximum fitting error */ int splitPoint; /* Point to split point set at */ int nPts; /* Number of points in subset */ double iterationError; /*Error below which you try iterating */ int maxIterations = 4; /* Max times to try iterating */ Vector2 tHatCenter; /* Unit tangent vector at splitPoint */ int i; iterationError = error * error; nPts = last - first + 1; /* Use heuristic if region only has two points in it */ if (nPts == 2) { double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0; bezCurve = (Point2 *)malloc(4 * sizeof(Point2)); bezCurve[0] = d[first]; bezCurve[3] = d[last]; V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]); V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]); DrawBezierCurve(3, bezCurve, bezContour); free((void *)bezCurve); return; } /* Parameterize points, and attempt to fit curve */ u = ChordLengthParameterize(d, first, last); bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2); /* Find max deviation of points to fitted curve */ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint); if (maxError < error) { DrawBezierCurve(3, bezCurve, bezContour); free((void *)u); free((void *)bezCurve); return; } /* If error not too large, try some reparameterization */ /* and iteration */ if (maxError < iterationError) { for (i = 0; i < maxIterations; i++) { uPrime = Reparameterize(d, first, last, u, bezCurve); free((void *)bezCurve); bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2); maxError = ComputeMaxError(d, first, last, bezCurve, uPrime, &splitPoint); if (maxError < error) { DrawBezierCurve(3, bezCurve, bezContour); free((void *)u); free((void *)bezCurve); free((void *)uPrime); return; } free((void *)u); u = uPrime; } } /* Fitting failed -- split at max error point and fit recursively */ free((void *)u); free((void *)bezCurve); tHatCenter = ComputeCenterTangent(d, splitPoint); FitCubic(d, first, splitPoint, tHat1, tHatCenter, error, bezContour); V2Negate(&tHatCenter); FitCubic(d, splitPoint, last, tHatCenter, tHat2, error, bezContour); }
void UICurveEditor::DrawBezier( float in_x, float in_y, float in_w, float in_h, const char *Title, r3dBezierGradient* edit_val, float* pVertScale, float in_minVal, float in_maxVal, int x_steps /*= 10*/, int y_steps /*= 10*/, int x_precision /*= 2*/, int y_precision /*= 2*/, bool bUseDesktop ) { if ( bUseDesktop ) { if ( ! Desktop().IsWindowVisible( in_x, in_y, in_x + in_w, in_y + in_h ) ) return; in_x -= Desktop().GetX(); in_y -= Desktop().GetY(); } const int x_dels = x_steps; const int y_dels = y_steps; static const float off_field = 30; static const float off_header = 20; static const r3dColor clr_bg(50, 50, 50); static const r3dColor clr_hdr(80, 120, 80); static const r3dColor clr_fld(30, 30, 30); static const r3dColor clr_line(100, 100, 100); static const r3dColor clr_selline(200, 200, 200); float ui_x = in_x; float ui_y = in_y; float ui_w = in_w; float ui_h = in_h - 8; // field coords fx = ui_x + off_field; fw = ui_w - off_field - off_field; fy = ui_y + off_header; fh = ui_h - off_field - off_header; r3dBezierGradient& grad = *edit_val; if( pVertScale ) { r3d_assert( "Copy me from UICurveEditor::DrawIM!!" ); } else { vertScale = 1.f ; } if(in_minVal > -9999) { minMaxLocked = true; minVal = in_minVal; maxVal = in_maxVal; // apply min/max limits float min = R3D_MIN(minVal, maxVal); float max = R3D_MAX(minVal, maxVal); for(int i=0; i<grad.NumValues; i++) { r3dBezierGradient::val_s& gv = grad.Values[i]; gv.val[0] = R3D_CLAMP(gv.val[0], min, max); } } else { minMaxLocked = false; // unrestricted mode - detect min/max minVal = 9999; maxVal = -9999; for(int i=0; i<grad.NumValues; i++) { r3dBezierGradient::val_s& gv = grad.Values[i]; if(minVal > gv.val[0]) minVal = gv.val[0]; if(maxVal < gv.val[0]) maxVal = gv.val[0]; } minVal -= 1.0f; maxVal += 1.0f; if(imgui_val == edit_val) { // do not change min/val while dragging! minVal = dragSavedMin; maxVal = dragSavedMax; } } // draw backgoround r3dDrawBox2D(ui_x, ui_y, ui_w, in_h, clr_bg); r3dDrawBox2D(fx, fy, fw, fh, clr_fld); r3dDrawBox2D(ui_x, ui_y, ui_w, off_header-2, clr_hdr); MenuFont_Editor->PrintF(ui_x+5, ui_y+2, r3dColor(255,255,255), Title); x_precision = R3D_MIN( R3D_MAX( x_precision, 0 ), 9 ); y_precision = R3D_MIN( R3D_MAX( y_precision, 0 ), 9 ); char num_fmt[] = "%.0f"; const int fmt_precision_pos = 2; // draw x lines - from 0.0 to 1.0 { float x = fx; float y = fy; float dx = fw / x_dels; num_fmt[fmt_precision_pos] = '0' + x_precision; for(int i=0; i<=x_dels; i++) { r3dDrawVLine(x, y, ui_h - off_header, clr_line); MenuFont_Editor->PrintF(x+2, y+fh+2, r3dColor::white, num_fmt, float(i) / x_dels); x += dx; } } // draw y lines - from minVal to maxVal { float x = float(ui_x); float y = fy; float dy = fh / y_dels; float val = maxVal; float vd = (minVal - maxVal) / y_dels; num_fmt[fmt_precision_pos] = '0' + y_precision; for(int i=0; i<=y_dels; i++) { r3dDrawHLine(x, y, ui_w, clr_line); MenuFont_Editor->PrintF(x, y, r3dColor::white, num_fmt, val); y += dy; val += vd; } } DrawBezierCurve(*edit_val ); DrawBezierPoints(*edit_val, imgui_val == NULL); if(imgui_disabled) return; if(imgui_val && imgui_val != edit_val) return; // draw mouseover lines && current coordinate/value if(!g_imgui_InDrag && imgui_mx >= fx && imgui_mx <= fx+fw && imgui_my >= fy && imgui_my <= fy+fh && (imgui_val == NULL || imgui_val == edit_val)) { r3dDrawHLine(fx, imgui_my, fw, clr_selline); r3dDrawVLine(imgui_mx, fy, fh, clr_selline); if(selectedPnt == -1) { float vx, vy; CalcFromCoord(imgui_mx, imgui_my, vx, vy); MenuFont_Editor->PrintF(imgui_mx+2, imgui_my+2, r3dColor::white, "----Time:%.2f Val:%.4f", vx, vy); } } // if we snapped on point - print it's coordinate/value if(selectedPnt != -1) { const r3dBezierGradient::val_s& gv = grad.Values[selectedPnt]; float x, y; CalcFromValue(gv, x, y); MenuFont_Editor->PrintF(x+2, y+2, r3dColor::white, "****Time:%.2f Val:%.4f", gv.time, gv.val[0]); MenuFont_Editor->PrintF(ui_x+0, ui_y-2, r3dColor::white, "[%.2f]:%.4f", gv.time, gv.val[0]); } bool act1 = !g_imgui_InDrag && imgui_lbp && !Keyboard->IsPressed(kbsLeftControl); bool act2 = !g_imgui_InDrag && imgui_lbp && Keyboard->IsPressed(kbsLeftControl); // // point dragging // if(imgui_val == NULL && selectedPnt != -1 && imgui_val != this && act1) { // enable point dragging imgui_val = edit_val; draggingPnt = selectedPnt; dragSavedMin= minVal; dragSavedMax= maxVal; } if(imgui_val == edit_val) { assert(draggingPnt != -1); // update dragging point float vx, vy; CalcFromCoord(imgui_mx, imgui_my, vx, vy); r3dBezierGradient::val_s& gv = grad.Values[draggingPnt]; if(gv.time < 0.001f || gv.time > 0.999f) { // do not edit value for border params gv.val[0] = vy; } else { gv.time = R3D_CLAMP(vx, 0.01f, 0.98f); gv.val[0] = vy; grad.ResortAfterChange(&selectedPnt); } if(imgui_lbr) { imgui_val = NULL; draggingPnt = -1; } return; } // // point adding/removing // if(imgui_mx >= fx && imgui_mx <= fx+fw && imgui_my >= fy && imgui_my <= fy+fh) { assert(imgui_val == NULL); if(selectedPnt != -1 && act2) { // remove selected point (only not border ones) if(selectedPnt != 0 && selectedPnt != grad.NumValues-1) { grad.NumValues--; memmove(&grad.Values[selectedPnt], &grad.Values[selectedPnt+1], sizeof(grad.Values[0]) * (grad.NumValues - selectedPnt)); grad.UpdateControlPoints (); selectedPnt = -1; return; } } if(selectedPnt == -1 && act1) { // add new control point and lock it for dragging float vx, vy; CalcFromCoord(imgui_mx, imgui_my, vx, vy); draggingPnt = grad.AddValue(vx, vy); dragSavedMin= minVal; dragSavedMax= maxVal; imgui_val = edit_val; return; } } return; }