不规则图形 尖角转圆角
2016-04-26 20:39
716 查看
用于视线效果,不可见区域的阴影美化,将尖锐的阴影边缘柔和成圆角。
![](http://img.blog.csdn.net/20160426204529464)
![](http://img.blog.csdn.net/20160426204544505)
1. 取3个点A,B,C
2. 计算得到射线向量BA, BC
3. 射线BA, BC分别从B点沿射线方向,取若干距离的点作为垂线坐标点
4. 分别以垂点做垂线,并计算垂线的斜率
5. 已知一点与斜率,分别得出二者垂线的方程并计算两条垂线的交点。将交点设为圆心,半径是圆心到垂点的距离。
6. 确定了圆心之后,两个垂点之间的短弧,即是圆角。
7. 判断垂线的角度,取点移动的方向是逆时针。假如A点为逆时针的起始点,则从BA的向量角度递增至BC,逐间隔计算圆上的点
8. 根据圆心,半径,角度,逆时针逐间隔计算圆上的点
9. 将得到的点连接,即为圆角点。
1. 取3个点A,B,C
2. 计算得到射线向量BA, BC
3. 射线BA, BC分别从B点沿射线方向,取若干距离的点作为垂线坐标点
4. 分别以垂点做垂线,并计算垂线的斜率
5. 已知一点与斜率,分别得出二者垂线的方程并计算两条垂线的交点。将交点设为圆心,半径是圆心到垂点的距离。
6. 确定了圆心之后,两个垂点之间的短弧,即是圆角。
7. 判断垂线的角度,取点移动的方向是逆时针。假如A点为逆时针的起始点,则从BA的向量角度递增至BC,逐间隔计算圆上的点
8. 根据圆心,半径,角度,逆时针逐间隔计算圆上的点
9. 将得到的点连接,即为圆角点。
void convertToCircle(std::vector<Vec2>& pointList) { std::vector<Vec2> vecNewPoint; std::vector<Vec2>::iterator itrPt; std::vector<Vec2>::iterator itrPtPre; std::vector<Vec2>::iterator itrPtNext; for (itrPt = pointList.begin(); itrPt != pointList.end(); itrPt++) { //取3个点A,B,C itrPtPre = itrPt - 1; if (itrPt == pointList.begin()) { itrPtPre = pointList.end() - 1; } itrPtNext = itrPt + 1; if (itrPtNext == pointList.end()) { itrPtNext = pointList.begin(); } //计算得到射线向量BA, BC Vec2 line0 = (*itrPtPre) - (*itrPt); Vec2 line1 = (*itrPtNext) - (*itrPt); //以射线BA, BC分别从B点沿射线方向若干距离的点作为垂线坐标点 float incLength = CircleRaido_Inc; float length0 = line0.getLength(); float length1 = line1.getLength(); //计算垂线的斜率 Vec2 plumbPoint0 = getPtByInc((*itrPt), line0, incLength); float k0 = getPlumbK(line0); //垂直线的斜率 Vec2 plumbPoint1 = getPtByInc((*itrPt), line1, incLength); float k1 = getPlumbK(line1); //垂直线的斜率 //得出垂线的方程并计算二者交点,交点设为圆心,半径是圆心到垂点的距离 float crossPtX; float crossPtY; if ( isEqual( k0 ,1.0f)) { crossPtX = plumbPoint0.x; crossPtY = k1*(crossPtX - plumbPoint1.x) + plumbPoint1.y; }else if ( isEqual(k1, 1.0f)) { crossPtX = plumbPoint1.x; crossPtY = k0*(crossPtX - plumbPoint0.x) + plumbPoint0.y; } else { crossPtX = (k0*plumbPoint0.x - k1*plumbPoint1.x + plumbPoint1.y - plumbPoint0.y) / (k0 - k1); crossPtY = k0*(crossPtX - plumbPoint0.x) + plumbPoint0.y; } Vec2 crossPt(crossPtX, crossPtY);//垂线交点, 圆心 float radius = (crossPt - plumbPoint0).getLength();//圆半径 //判断垂线的角度,移动的方向是逆时针。假如A点为逆时针的起始点,则从BA的向量角度递增至BC,逐间隔计算圆上的点 float circleAngle0 = getAngle(plumbPoint0 - crossPt); float circleAngle1 = getAngle(plumbPoint1 - crossPt); float startAngle = circleAngle0; float endAngle = circleAngle1; float angleInc = Radian_Inc; bool isInc = true; if (circleAngle0 > circleAngle1) { angleInc = -Radian_Inc; isInc = false; if (circleAngle0 > 0.0f && circleAngle1 < 0.0f) { if (circleAngle0 > M_PI + circleAngle1) { endAngle = M_2PI + circleAngle1; angleInc = Radian_Inc; isInc = true; } } } else { if (circleAngle0 < 0.0f && circleAngle1 > 0.0f) { if (M_PI + circleAngle0 < circleAngle1) { startAngle = M_2PI + circleAngle0; angleInc = -Radian_Inc; isInc = false; } } } //根据圆心,半径,角度,逆时针逐间隔计算圆上的点 float curAngle = startAngle + angleInc; vecNewPoint.push_back(plumbPoint0); if (isInc) { while (curAngle < endAngle) { vecNewPoint.push_back(crossPt + Vec2(radius*cosf(curAngle), radius*sinf(curAngle))); curAngle += angleInc; } } else { while (curAngle > endAngle) { vecNewPoint.push_back(crossPt + Vec2(radius*cosf(curAngle), radius*sinf(curAngle))); curAngle += angleInc; } } vecNewPoint.push_back(plumbPoint1); } pointList.clear(); pointList.swap(vecNewPoint); }
相关文章推荐
- 安卓 天气预报
- 非常好用的万能BaseAdapter
- 2.替换空格
- JavaScript 对象(1)
- linux常用命令
- mac thinkphp3.2 nginx配置rewrite pathinfo
- 多线程断点续传及下载
- Android学习-进阶之路
- #define和typedef在定义指针类型上的优劣
- 华为p7怎么打开usb调试模式
- LEIJP开船(线段树)
- HDU 5665
- 图片轮播(jquery方式)
- Android Studio 升级之更新包升级版本
- pulltorefreshlistview 和xlistview 中的获取item控件布局时出现的类转换异常的问题:
- 程序集反射 Type 类
- 网络通信 --> Socket、TCP/IP、HTTP、FTP及网络编程
- 关于色温调节的一个 shader
- C经典 输入数组并打印
- C++小细节之static的作用