黄色的线是天正建筑2014画出来的墙炸开后的样子,炸开后全是AcDbLine。可以看到这个黄色的线在拐弯处,交叉处会出现多余的小线段,并且是不连续的,或者是超出了缺口,想要把它转变成梁就需要考虑这些因素。
我的思路是这样的,第一步 过滤小于等于墙厚度的直线,这样多余的直线就会消失,之后保存剩下的线段到一个vector集合中。
for (int i = 0; i < ids.length(); i++) { AcDbLine * l = NULL; if (acdbOpenObject(l, ids[i], AcDb::kForWrite) == Acad::eOk) { double len = 0; l->getDistAtPoint(l->endPoint(), len) //根据要求有三种数值的墙厚度 if (len <queKou||len<queKou2||len<quekou3) { l->erase(); l->close(); l = NULL; } else { vecLines.push_back(l); } } }
第二步,把所有缺口封闭起来形成类似“#”这样的缺口,我采用的办法是,遍历直线集合,两两相交,如果有交点就延长至交点处,这里有个限制,那就是从线的端点到延长到交点的长度不超过1.5*quekou值并且交点确实是在延长线上而不是在直线的两个端点之间。
for (int ww = 0; ww < (int)vecLines.size(); ww++) { AcDbLine * l1 = vecLines[ww]; for (int j = ww + 1; j < (int)vecLines.size(); j++) { AcDbLine *l2 = vecLines[j]; l1->intersectWith(l2, AcDb::kOnBothOperands, temp1, 0, 0); if (1 == temp1.length()) { temp1.removeAll(); } else { l1->intersectWith(l2, AcDb::kExtendBoth, temp2, 0, 0); if (temp2.length() > 0) { ExtendLine(l1, temp2[0]); ExtendLine(l2, temp2[0]); temp2.removeAll(); } } } }
static void ExtendLine(AcDbLine * l1, const AcGePoint3d & pt) { AcGePoint3d pt11 = l1->startPoint(); AcGePoint3d pt12 = l1->endPoint(); double disO = pt11.distanceTo(pt12); double dis1 = pt11.distanceTo(pt); double dis2 = pt12.distanceTo(pt); double max = (dis2 > dis1 ? dis2 : dis1); if (max > disO + 1.5*(queKou + queKou2 + quekou3) / 3 || max < disO) { return; } else { if (max==dis2) { l1->setStartPoint(pt); } else { l1->setEndPoint(pt); } } }
第三步削减类似“#”的口子,让它们变成类似互通的路口,我采取的方法是遍历两两相交,判断交点是否在线的两个端点之间,如果是,则进行消减,改变端点。
//削减 for (int ww = 0; ww < (int)vecLines.size(); ww++) { AcDbLine * l1 = vecLines[ww]; for (int j = ww + 1; j < (int)vecLines.size(); j++) { AcDbLine *l2 = vecLines[j]; //l1->intersectWith(l2, AcDb::kExtendBoth, temp2, 0, 0); l1->intersectWith(l2, AcDb::kOnBothOperands, temp1, 0, 0); if (1 == temp1.length()) { CutLine(l1, temp1[0]); CutLine(l2, temp1[0]); temp1.removeAll(); } } }
static void CutLine(AcDbLine * l1, const AcGePoint3d & pt) { AcGePoint3d pt11 = l1->startPoint(); AcGePoint3d pt12 = l1->endPoint(); double disO = pt11.distanceTo(pt12); double dis1 = pt11.distanceTo(pt); double dis2 = pt12.distanceTo(pt); if (disO > dis1&&disO > dis2) { if (dis1 <= (queKou + queKou2 + quekou3)/3&&dis2 <= (queKou + queKou2 + quekou3) / 3) { return; } else { if (dis1 < dis2) { l1->setStartPoint(pt); } else { l1->setEndPoint(pt); } } } }
第四步,在第三步的时候会把边界的路口的线也给删了,所以就要补充边界缺口。这时剩下的缺口有个特点,那就是缺口对应的两条线是不会有交点的,利用这个特点就能解决问题。我是在交点处画一个圆,与圆相交的线构成集合,然后把这个集合中部任何线相交的直线找出来,进行延长相交,补充缺口。
//補充 temp1.removeAll(); temp2.removeAll(); AcGePoint3dArray ptArrAll; ptArrAll.append(AcGePoint3d::kOrigin); ptArrAll.removeAll(); for (int i = 0; i < (int)vecLines.size(); i++) { AcDbLine * l1 = vecLines[i]; ptArrAll.append(l1->startPoint()); ptArrAll.append(l1->endPoint()); } //acutPrintf(L"prePt=%d", ptArrAll.length()); double r = (queKou + queKou2 + quekou3) / 3*2; for (int i=0;i<ptArrAll.length();i++) { AcGePoint3d ptCenter=ptArrAll[i]; AcDbCircle *cir = new AcDbCircle(ptCenter, AcGeVector3d::kZAxis, r); for (int j = i+1; j < ptArrAll.length(); j++) { AcGePoint3d pt2 = ptArrAll[j]; double dis = pt2.distanceTo(ptCenter); if (dis <= r) { ptArrAll.removeAt(j); } } delete cir; cir = NULL; } //acutPrintf(L"afterPt=%d", ptArrAll.length()); for (int i = 0; i < ptArrAll.length(); i++) { AcGePoint3d ptCenter = ptArrAll[i]; AcDbCircle *cir = new AcDbCircle(ptCenter, AcGeVector3d::kZAxis, r); vector<AcDbLine*>vecLL; for (int ww = 0; ww < (int)vecLines.size(); ww++) { AcDbLine * l1 = vecLines[ww]; l1->intersectWith(cir, AcDb::kOnBothOperands, temp1, 0, 0); if (temp1.length() > 0) { vecLL.push_back(l1); temp1.removeAll(); } } delete cir; cir = NULL; AcGeIntArray intArr; for (int m = 0; m < (int)vecLL.size(); m++) { AcDbLine * lT1 = vecLL[m]; for (int s = 0; s < (int)vecLL.size(); s++) { AcDbLine * lT2 = vecLL[s]; lT1->intersectWith(lT2, AcDb::kOnBothOperands, temp2, 0, 0); if (temp2.length() > 0) { intArr.append(m); intArr.append(s); temp2.removeAll(); } } } for (int m = 0; m < (int)vecLL.size(); m++) { if (intArr.contains(m)) { continue; } AcDbLine * lT1 = vecLL[m]; for (int s = 0; s < (int)vecLL.size() ; s++) { if (intArr.contains(s)) { continue; } AcDbLine * lT2 = vecLL[s]; lT1->intersectWith(lT2, AcDb::kExtendBoth, temp2, 0, 0); //ptNJdAll.append(temp2[0]); if (temp2.length() > 0) { AcGePoint3d pt11 = lT1->startPoint(); AcGePoint3d pt12 = lT1->endPoint(); double disO = pt11.distanceTo(pt12); double dis1 = pt11.distanceTo(temp2[0]); double dis2 = pt12.distanceTo(temp2[0]); double max1 = (dis2 > dis1 ? dis2 : dis1); AcGePoint3d pt21 = lT2->startPoint(); AcGePoint3d pt22 = lT2->endPoint(); double disO2 = pt21.distanceTo(pt22); double dis21 = pt21.distanceTo(temp2[0]); double dis22 = pt22.distanceTo(temp2[0]); double max21 = (dis22 > dis21 ? dis22 : dis21); if (max1 < disO + 0.5*(queKou + queKou2 + quekou3)) { if (max1 == dis2) { lT1->setStartPoint(temp2[0]); } else { lT1->setEndPoint(temp2[0]); } } if (max21 < disO2 + 0.5*(queKou + queKou2 + quekou3)) { if (max21 == dis22) { lT2->setStartPoint(temp2[0]); } else { lT2->setEndPoint(temp2[0]); } } temp2.removeAll(); } } } intArr.removeAll(); vecLL.clear(); }
最后在关闭实体
for (int i = 0; i < (int)vecLines.size(); i++) { vecLines[i]->setColorIndex(1); vecLines[i]->close(); }