最近很忙,忙的连写日记的功夫都没有了。
有个项目的需求是需要把多个圆环的区域合并。得到包络线和内部空洞的线。
查了查google。类似的实现比较少见。简单的说说我的实现方法。
基本想法就是通过判断一段圆弧和圆环组的关系,来判断这段圆弧是否是属于合并后的包络线的一部分
如图,左边的圆盒右边的圆相交。则这两个圆就被分成了两段。
对外包络线,如上图。将所有圆环的外圆(粗线)相交。把每个圆都切成一段段的圆弧,如左边的黑色圆,则切成了黑色段和黑色+红色的两段。对每一段,我们测试这一段弧是否在其它圆环的大圆内部,如果这段圆弧不在其它的环的大圆内部(不包括内部小圆),则这段圆弧属于外包络线的一部分。否则不是。
内部透空的小圆的合并稍微麻烦一些。因为透空的部分,不光是小圆的弧,还会有大圆弧的参与。
考察小圆的圆弧,同样的,我们将小圆 和其它圆环的求交点,把小圆切成一段段的弧线(注意小圆和其它环求交的时候,就要跟这个环的大小圆都交一遍,而不光是小圆和小圆了)。如果这一段弧线不在这组圆环内(指的是环的内部,而不是大圆的内部),则表示这段弧是属于内包络线的一部分。
考察大圆的弧,大圆产生内包络线的原因主要是大圆会抵消一部分小圆的透空作用。所以同样的我们将大圆 和其它圆环的求交点,把小圆切成一段段的弧线--跟外包络不同,这次求交的时候,该大圆要和其它圆环的大小圆都求交,而不光是大圆对大圆。 对每一段圆弧,如果弧线不在环的内部,而且该段弧应该还需要位于某个环的小圆内部(看图就明白为什么了)。则该大圆弧也是内包络的一部分。
这里求圆弧在环的内部还是在大小圆内,有一个偷懒的方法。因为我们已经保证这段圆弧除了两个端点以外不和其它任何弧相交,所以只要用这段弧的中点来代替弧来作判断就好了。使得复杂性大大降低了。
以上是效果图,三个环合并成一个区域。
以下是主要代码
class CRingGroup
{
public:
bool load(const wchar_t* _ringGroupsFile)
{
xXmlDocument doc;
if(doc.load(_ringGroupsFile) == false )
return false;
xXmlNode::XmlNodes ringNodes;
doc.findAllNode(L"ring" , ringNodes);
if(ringNodes.size() == 0)
return false;
for(size_t i = 0 ; i < ringNodes.size() ; i ++)
{
xXmlNode* pNode = ringNodes[i];
xRing _ring;
_ring.m_InnerR = pNode->float_value(L"r1");
_ring.m_OutR = pNode->float_value(L"r2");
_ring.m_Center = pNode->get_value<float2>(L"center");
m_vRings.push_back(_ring);
}
}
void toSplineDrawer(CSplineDraw& drawer)
{
drawer.m_vArcs.clear();
for(int i = 0 ; i < m_vRings.size() ; i ++)
{
std::vector<float> CutPoints;
xRing& ring = m_vRings[i];
ring.toArcs(CutPoints , true , drawer.m_vArcs);
}
for(int i = 0 ; i < m_vRings.size() ; i ++)
{
std::vector<float> CutPoints;
xRing& ring = m_vRings[i];
ring.toArcs(CutPoints , false , drawer.m_vArcs);
}
}
void toInnerLine(std::vector<xArc>& vOut)
{
for(int i = 0 ; i < m_vRings.size() ; i ++)
{
std::vector<float> vCutPoints;
std::vector<xArc> vArcs;
//先来切内圆
xRing& _ring = m_vRings[i];
for(int j = 0 ; j < m_vRings.size() ; j ++)
{
if(j == i) continue;
xRing& _ring2 = m_vRings[j];
_ring.CutByCircle(_ring2.m_Center , _ring2.m_OutR , vCutPoints , false );
_ring.CutByCircle(_ring2.m_Center , _ring2.m_InnerR , vCutPoints , false);
}
_ring.toArcs(vCutPoints , false , vArcs);
//内圆的弧,必须在所有的外圆的外部。
for(int iArc = 0 ; iArc < vArcs.size() ; iArc ++)
{
xArc& _arc = vArcs[iArc];
bool bInRing = false;
for(int k = 0 ; k < m_vRings.size() ; k ++)
{
if( k == i ) continue;
xRing& _ring2 = m_vRings[k];
if( true == _ring2.IsInRing( _arc ) )
{
bInRing = true;
}
}
//////////////////////////////////////////////////////////////////////////
if(bInRing == false)
{
vOut.push_back(_arc);
}
}
//内圆切完了。来切外圆套在其它内圆中的部分。
vCutPoints.clear();
vArcs.clear();
for(int j = 0 ; j < m_vRings.size() ; j ++)
{
if(j == i) continue;
xRing& _ring2 = m_vRings[j];
_ring.CutByCircle(_ring2.m_Center , _ring2.m_OutR , vCutPoints , true );
_ring.CutByCircle(_ring2.m_Center , _ring2.m_InnerR , vCutPoints , true);
}
_ring.toArcs(vCutPoints , true , vArcs);
//内圆的弧,必须在所有的外圆的外部。
for(int iArc = 0 ; iArc < vArcs.size() ; iArc ++)
{
xArc& _arc = vArcs[iArc];
bool bInRing = false;
bool bInSmallRing = false;
for(int k = 0 ; k < m_vRings.size() ; k ++)
{
if( k == i ) continue;
xRing& _ring2 = m_vRings[k];
if( true == _ring2.IsInRing( _arc ) )
{
bInRing = true;
}
if( true == _ring2.IsInSmallRing( _arc) )
{
bInSmallRing = true;
}
}
//////////////////////////////////////////////////////////////////////////
if(bInRing == false && bInSmallRing == true)
{
vOut.push_back(_arc);
}
}
}
return ;
}
void toOutLine(std::vector<xArc>& vOut)
{
//return ;
for(int i = 0 ; i < m_vRings.size() ; i ++)
{
std::vector<float> vCutPoints;
xRing& _ring = m_vRings[i];
for(int j = 0 ; j < m_vRings.size() ; j ++)
{
if(j == i) continue;
xRing& _ring2 = m_vRings[j];
_ring.CutByCircle(_ring2.m_Center , _ring2.m_OutR , vCutPoints , true);
}
std::vector<xArc> vArcs;
_ring.toArcs(vCutPoints , true , vArcs);
//判断生成的圆弧是不是在内部。
for(int iArc = 0 ; iArc < vArcs.size() ; iArc ++)
{
xArc& _arc = vArcs[iArc];
bool bInRing = false;
for(int k = 0 ; k < m_vRings.size() ; k ++)
{
if( k == i ) continue;
xRing& _ring2 = m_vRings[k];
if( true == _ring2.IsInOutRing(_arc ) )
{
bInRing = true;
}
}
//////////////////////////////////////////////////////////////////////////
if(bInRing == false)
{
vOut.push_back(_arc);
}
}
}
return ;
}
public:
std::vector<xRing> m_vRings;
};
分享到:
相关推荐
求区域的平均值getmean求圆环区域平均值原创
Qt编写三色圆环仪表盘
变形多分类圆环图
iphone上的一个圆环动画效果
halcon找取圆环。首先阈值,通过拟合圆去与圆环拟合,找出内外圆环最佳拟合的两个圆,形成圆环,由红线标出,并求得圆心及半径参数。
一个渐变旋转的圆环
EXCEL报表圆环图-4-圆环图(变形多分类).xlsx
自己定制的一个多彩圆环和一个可以设置内外双环以及里面的文字,可以自己设置圆环的颜色,字体颜色,字体大小等等。如果不满足你的需求也可以自己在进行扩展。
三个圆环重叠切换是一款三个层重叠,鼠标点击任何一个圆可进行滑动切换,效果非常棒。
EXCEL报表圆环饼图-2-多数据圆环与饼图组合.xlsx
基于matlab的图像处理中圆环提取的代码,该代码经过适当的修改后可以适用于图像中圆的提取,在图像的剪切中应用广泛
Excel模板11-多分类圆环图(直角).zip
一个采用MUILIB界面库配置出来的圆环界面,里面有8个环形按钮,主要的特色在于鼠标只有点击到有效区域才激活按钮 全界面采用XML配置,无需代码就可以实现。 下载资源包后通过MUIEditor或者MUIPlayer打开里面的mui...
android 自定义旋转圆环button,录音时使用,点击变为停止按钮同时有圆环在旋转
圆环形进度条 可以设置圆环宽度 进度背景色 圆环中间的图片可以随意更换
自定义圆环,通过设置时长,圆环自动进行播放,可以用来播放
圆环错觉 java 程序 源代码 绘图程序
1、使用halcon绘制圆环roi;2、圆环roi使用比较冷僻;3、圆环的定义主要有5个参数;4、圆环的交互绘制和圆环的显示,共封装了两个函数;
纯CSS3多层圆环加载动画特效是一款圆环loading加载动画特效。
多分类圆环图.zip