Bezier Curve 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 void naive_bezier (const std::vector<cv::Point2f>& points, cv::Mat& window) { auto & p_0 = points[0 ]; auto & p_1 = points[1 ]; auto & p_2 = points[2 ]; auto & p_3 = points[3 ]; for (double t = 0.0 ; t <= 1.0 ; t += 0.001 ) { auto point = std::pow (1 - t, 3 ) * p_0 + 3 * t * std::pow (1 - t, 2 ) * p_1 + 3 * std::pow (t, 2 ) * (1 - t) * p_2 + std::pow (t, 3 ) * p_3; window.at <cv::Vec3b>(point.y, point.x)[2 ] = 255 ; } }
de Casteljau 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 cv::Point2f recursive_bezier (const std::vector<cv::Point2f>& control_points, float t) { int nums = control_points.size (); std::vector<cv::Point2f> points = control_points; for (int i = nums; i >= 2 ; i--) { for (int j = 0 ; j < i-1 ; j++) { points[j] = (1 - t) * points[j] + t * points[j + 1 ]; } } return points[0 ]; } void bezier (const std::vector<cv::Point2f>& control_points, cv::Mat& window) { for (double t = 0.0 ; t <= 1.0 ; t += 0.001 ) { auto point = recursive_bezier (control_points, t); window.at <cv::Vec3b>(point.y, point.x)[1 ] = 255 ; } }
Bilinear point的x,y是float形式,转成int形式才能绘制在屏幕上的某个像素点,由此损失精度
p点处在4个像素点之间,对4个像素点进行绘制可以平滑曲线
离p远的像素点颜色更淡
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void bezier_linear (const std::vector<cv::Point2f>& control_points, cv::Mat& window) { for (double t = 0.0 ; t <= 1.0 ; t += 0.001 ) { cv::Point2f p = recursive_bezier (control_points, t); cv::Point2i p0 (p.x - std::floor(p.x) < 0.5 ? std::floor(p.x) : std::ceil(p.x), p.y - std::floor(p.y) < 0.5 ? std::floor(p.y) : std::ceil(p.y)) ; std::vector<cv::Point2i> ps = { p0, cv::Point2i (p0.x - 1 , p0.y), cv::Point2i (p0.x, p0.y - 1 ), cv::Point2i (p0.x - 1 , p0.y - 1 ), }; float sum_d = 0.f ; std::vector<float > ds = {}; for (int i = 0 ; i < 4 ; i++) { cv::Point2f cp (ps[i].x + 0.5f , ps[i].y + 0.5f ) ; float d = std::sqrt (std::pow (p.x - cp.x, 2 ) + std::pow (p.y - cp.y, 2 )); ds.push_back (d); sum_d += d; }; for (int i = 0 ; i < 4 ; i++) { float k = ds[i] / sum_d; window.at <cv::Vec3b>(ps[i].y, ps[i].x)[1 ] = std::min (255.f , window.at <cv::Vec3b>(ps[i].y, ps[i].x)[1 ] + 255.f * k); }; } }
结果
Bresenham Line 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 void rst::rasterizer::draw_line (Eigen::Vector3f begin, Eigen::Vector3f end){ auto x1 = begin.x (); auto y1 = begin.y (); auto x2 = end.x (); auto y2 = end.y (); Eigen::Vector3f line_color = {255 , 255 , 255 }; int x,y,dx,dy,dx1,dy1,px,py,xe,ye,i; dx=x2-x1; dy=y2-y1; dx1=fabs (dx); dy1=fabs (dy); px=2 *dy1-dx1; py=2 *dx1-dy1; if (dy1<=dx1) { if (dx>=0 ) { x=x1; y=y1; xe=x2; } else { x=x2; y=y2; xe=x1; } Eigen::Vector3f point = Eigen::Vector3f (x, y, 1.0f ); set_pixel (point,line_color); for (i=0 ;x<xe;i++) { x=x+1 ; if (px<0 ) { px=px+2 *dy1; } else { if ((dx<0 && dy<0 ) || (dx>0 && dy>0 )) { y=y+1 ; } else { y=y-1 ; } px=px+2 *(dy1-dx1); } Eigen::Vector3f point = Eigen::Vector3f (x, y, 1.0f ); set_pixel (point,line_color); } } else { if (dy>=0 ) { x=x1; y=y1; ye=y2; } else { x=x2; y=y2; ye=y1; } Eigen::Vector3f point = Eigen::Vector3f (x, y, 1.0f ); set_pixel (point,line_color); for (i=0 ;y<ye;i++) { y=y+1 ; if (py<=0 ) { py=py+2 *dx1; } else { if ((dx<0 && dy<0 ) || (dx>0 && dy>0 )) { x=x+1 ; } else { x=x-1 ; } py=py+2 *(dx1-dy1); } Eigen::Vector3f point = Eigen::Vector3f (x, y, 1.0f ); set_pixel (point,line_color); } } }
结果