http://www.wanxiangshu.com

基于PCB 板的边倒圆角实现方案解析

当 PCB 外形是直角时, 通常工程制作外形 (锣带) 时, 会将直角或尖角的地方倒成圆角, 主要是为了防止板边容易划伤板且容易扎伤人

所以当客户没有特殊要求时, PCB 外形是直角一般会默认倒角 0.5mm 圆角(如下图所示)

pIYBAGA91eKANWkRAAF-ci7W500238.png

一。 PCB 板边倒圆角点分析

原 PCB 外形 如下图图示: 看了这个 PCB 外形, 产生有 2 个问题点。

1. 外形中哪些点需倒圆角?

2. 如何怎么倒圆角?

pIYBAGA91fGAZBAQAAChj93QJCs229.png

1. 外形中哪些点需倒圆角?

看下图: PCB 外形倒圆角的点, 刚好就是我们凸包需求出的点, 接下来我们将玩转凸包了, 只要求出凸包, 那么就可以实现 PCB 板边倒圆角啦。

o4YBAGA91gWACJvRAAGXiayC13M609.png

求凸包的算法: 我们可以借鉴算法导论中的查找凸包的算法(加以改进得到新的求凸包方法, 详见[方法一] 与[方法二] )

pIYBAGA91heAIHmvAATiKNwTzCg372.png

2. 如何怎么倒圆角?

在下面有说明倒角方法。

二。 求凸点

方法一求凸点:[采用多轮遍历, 一遍一遍将凹点踢除, 剩于的即是凸点]

150633dbb4hwluqbhyxd3d.gif

方法一求凸点: 代码

/// 《summary》

/// 求最大多边形最大凸包 1 [采用多轮遍历将凹点踢除, 剩于的即是凸点]

/// 《/summary》

/// 《param name=“gSur_Point_list”》《/param》

/// 《returns》《/returns》

public List《gSur_Point》 s_convex_polyon1(List《gSur_Point》 gSur_Point_list)

{

add addCOM = new add();

bool isOK = true;

List《gSur_Point》 PointList = new List《gSur_Point》();

var isCCW = s_isCCW(gSur_Point_list);

int sum = gSur_Point_list.Count() - 1;

int n = gSur_Point_list.Count();

for (int i = 0; i 《n; i++)

{

int IndexPre = (i - 1) % sum;

if (IndexPre == -1) IndexPre = sum - 1;

int IndexCurrent = i % sum;

int IndexNext = (i + 1) % sum;

if (gSur_Point_list[IndexPre].type_point》 0) continue;

if (gSur_Point_list[IndexCurrent].type_point》 0) continue;

var multiVal = multi(gSur_Point_list[IndexPre].p, gSur_Point_list[IndexCurrent].p, gSur_Point_list[IndexNext].p);

if ((isCCW && multiVal》 0) || (!isCCW && multiVal 《0))

PointList.Add(gSur_Point_list[IndexCurrent]);

else

isOK = false;

}

List《gSur_Point》 Point2List = new List《gSur_Point》(PointList);

while (!isOK)

{

isOK = true;

PointList.Clear();

PointList.AddRange(Point2List);

Point2List.Clear();

sum = PointList.Count() - 1;

n = PointList.Count();

for (int i = 0; i 《n; i++)

{

int IndexPre = (i - 1) % sum;

if (IndexPre == -1) IndexPre = sum - 1;

int IndexCurrent = i % sum;

int IndexNext = (i + 1) % sum;

var multiVal = multi(PointList[IndexPre].p, PointList[IndexCurrent].p, PointList[IndexNext].p);

if ((isCCW && multiVal》 0) || (!isCCW && multiVal 《0))

Point2List.Add(PointList[IndexCurrent]);

else

isOK = false;

}

}

return Point2List;

}

方法二求凸包:[采用一边遍历找出凸点并加入队列, 并同时将队列中的凸点队列中找出凹点踢除]

150633buf40f2ulnunqu41.gif

方法二求凸包代码:

/// 《summary》

/// 求最大多边形最大凸包 2 [采用一边遍历找出凸点并加入队列, 并同时将队列中的凸点队列中找出凹点踢除]

/// 《/summary》

/// 《param name=“gSur_Point_list”》《/param》

/// 《returns》《/returns》

public List《gSur_Point》 s_convex_polyon2(List《gSur_Point》 gSur_Point_list)

{

Stack《gSur_Point》 StackPoint = new Stack《gSur_Point》();

var isCCW = s_isCCW(gSur_Point_list);

int sum = gSur_Point_list.Count() - 1;

int n = gSur_Point_list.Count();

for (int i = 0; i 《n; i++)

{

int IndexPre = (i - 1) % sum;

if (IndexPre == -1) IndexPre = sum - 1;

int IndexCurrent = i % sum;

int IndexNext = (i + 1) % sum;

if (gSur_Point_list[IndexPre].type_point》 0) continue;

if (gSur_Point_list[IndexCurrent].type_point》 0) continue;

var multiVal = multi(gSur_Point_list[IndexPre].p, gSur_Point_list[IndexCurrent].p, gSur_Point_list[IndexNext].p);

if ((isCCW && multiVal》 0) || (!isCCW && multiVal 《0))

{

L1:

if (StackPoint.Count》 1)

{

var Top1Point = StackPoint.Pop();

var Top2Point = StackPoint.Peek();

multiVal = multi(Top2Point.p, Top1Point.p, gSur_Point_list[IndexCurrent].p);

if ((isCCW && multiVal》 0) || (!isCCW && multiVal 《0))

StackPoint.Push(Top1Point);

else

goto L1;

}

StackPoint.Push(gSur_Point_list[IndexCurrent]);

}

}

return StackPoint.Reverse().ToList();

}

方法三求凸包:[按算法导论 Graham 扫描法 各节点按方位角 + 距离 逆时针排序 依次检查, 当不属凸点于则弹出]

150633scxss7n93cug3cgn.gif

方法三求凸包代码

/// 《summary》

/// 求最大多边形最大凸包 5 [按算法导论 Graham 扫描法 各节点按方位角 + 距离 逆时针排序 依次检查, 当不属凸点于则弹出]

/// 由于把各点的排列顺序重新排序了, 只支持折线节点(当存在弧节点时会出异常 !!!)

/// 《/summary》

/// 《param name=“gSur_Point_list”》《/param》

/// 《returns》《/returns》

public List《gSur_Point》 s_convex_polyon3(List《gSur_Point》 gSur_Point_list)

{

var LeftBottomPoint = gSur_Point_list.OrderBy(tt =》 tt.p.y).ThenBy(tt =》 tt.p.x).FirstOrDefault();

gSur_Point_list.RemoveAt(gSur_Point_list.Count - 1);

gSur_Point_list.ForEach(tt =》

{

tt.Value = p2p_di(LeftBottomPoint.p, tt.p);

tt.Angle = p_ang(LeftBottomPoint.p, tt.p);

}

);

gSur_Point_list = gSur_Point_list.OrderBy(tt =》 tt.Angle).ThenBy(tt =》 tt.Value).ToList();

gSur_Point_list.Add(gSur_Point_list[0]);

Stack《gSur_Point》 StackPoint = new Stack《gSur_Point》();

var isCCW = true;

int sum = gSur_Point_list.Count() - 1;

int n = gSur_Point_list.Count();

for (int i = 0; i 《n; i++)

{

int IndexPre = (i - 1) % sum;

if (IndexPre == -1) IndexPre = sum - 1;

int IndexCurrent = i % sum;

int IndexNext = (i + 1) % sum;

var multiVal = multi(gSur_Point_list[IndexPre].p, gSur_Point_list[IndexCurrent].p, gSur_Point_list[IndexNext].p);

if (isCCW && multiVal》 0)

{

L1:

if (StackPoint.Count》 1)

{

var Top1Point = StackPoint.Pop();

var Top2Point = StackPoint.Peek();

multiVal = multi(Top2Point.p, Top1Point.p, gSur_Point_list[IndexCurrent].p);

if (isCCW && multiVal》 0)

StackPoint.Push(Top1Point);

else

goto L1;

}

StackPoint.Push(gSur_Point_list[IndexCurrent]);

}

}

return StackPoint.Reverse().ToList();

}

公共方法与数据结构

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。