您的位置:首页 > 其它

不规则图形 尖角转圆角

2016-04-26 20:39 716 查看
用于视线效果,不可见区域的阴影美化,将尖锐的阴影边缘柔和成圆角。





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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: