前一篇文章:无向图:计算亏格(环的孔洞)
首先,判断图中是否存在环。方法,找到联通子图,循环删除度为1的节点,同时删除边。直到不存在度为1的边,则联通子图只剩下环或者复杂环。
在不需要遍历出环的算法里面,可以通过欧拉公式直接计算亏格。孔洞的个数。
公式: nGenus = l-p+1; l为边的个数,p为点的个数。
过程:对于所有联通的集合,循环删除度数为1的顶点,同时删除边;计算亏格。
然而,上述过程出现了问题。主要是平面图中若严格按照直线边进行拓扑,出现了复杂图,即立体图。
如图:
改进方法:
使用多边形并差计算,以此寻找孔洞,以此来应对复杂图的特殊情况。
代码段:
import seisw.util.geom.Clip;
import seisw.util.geom.Poly;
import seisw.util.geom.PolyDefault;
// 适应情况,一个房间多个家具,只有一次孔洞,不会有岛屿!
private static int findPolyGenus( List<NewPoint> walls, List<List<NewPoint>> furniturePolygons, double wallwidth,
double width) {
// 1.根据分区得到房间剩下的多个多边形,要求生成的多个多边形不能有空洞
int genus = 0;
// 默认房间为逆时针多边形,分区需保证为顺时针
Poly diffPoly = new PolyDefault();
for (NewPoint p : walls) {
diffPoly.add(p.m_x, p.m_y);
}
// 确保逆时针
for (int k = 0; k < furniturePolygons.size(); ++k) {
List<NewPoint> f = furniturePolygons.get(k);
ArrayList<NewPoint> fEx = extendPoly(furniturePolygons.get(k), 15+ width + wallwidth);//width );//
furniturePolygons.set(k, fEx);
Poly subPoly = new PolyDefault();
for (NewPoint p : fEx) {
subPoly.add(p.m_x, p.m_y);
}
diffPoly = (PolyDefault) Clip.difference(diffPoly, subPoly);
}
// 获取所有孔洞
genus = diffPoly.getNumInnerPoly();
for ( int i = 0; i < diffPoly.getNumInnerPoly(); ++i) {
boolean isHole = diffPoly.getInnerPoly(i).isHole();
if( isHole ){
genus = genus - 1;
}
}
return genus;
最后,可以得到正确结果。