无向图:计算亏格(环的孔洞)
前一篇文章:无向图:计算亏格(环的孔洞)
首先,判断图中是否存在环。方法,找到联通子图,循环删除度为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;
最后,可以得到正确结果。