objectarx 填充的分割
- 2020 年 3 月 7 日
- 筆記
主要思路:找到填充邊界集合:vecBo,然後把面積最大的邊界找出來:bo1,用分割曲線和bo1通過boundary命令構成兩個新的最大封閉邊界,左邊的記為 boLeft(紅色部分),右邊的記為boRight(綠色部分),在vecBo邊界集合分開為:boLeft內部的邊界,和boRight內部的邊界。這樣在分別填充的時候,就能有正確的填充邊界集合。
下面放出程式碼:
通過選擇填充求得填充邊界集合:

static void GetHatchBo(AcDbHatch *pHatch,vector<AcDbEntity*>&vecBo) { Acad::ErrorStatus es; Adesk::Int32 LoopType; AcGeVoidPointerArray edgeptrAry; AcGeIntArray edgeTypesAry; AcGePoint2dArray vertices; AcGeDoubleArray bulges; //獲得填充邊界的數目 int LoopNum = pHatch->numLoops(); for (int i = 0; i < LoopNum; i++) { //獲取邊界類型 LoopType = pHatch->loopTypeAt(i); //如果邊界是多義線 if (LoopType & AcDbHatch::kPolyline) { //取得邊界定義數據(polyline)的頂點數組和凸度數組,它們是一一對應的 es = pHatch->getLoopAt(i, LoopType, vertices, bulges); acutPrintf(L"n多段線"); //是不是根據這些頂點數組和凸度數組構造一條AcDb多義線取決於你 AcDbPolyline *pl = new AcDbPolyline(); GetPolyline(vertices, bulges, pl); vecBo.push_back(pl); } else { //幾乎可以取得除polyline外的所有邊界定義數據 //第三個參數返回值是無值指針數組 //第四個參數返回值是組成邊界的每一條邊的類型 //它們也是一一對應的關係 es = pHatch->getLoopAt(i, LoopType, edgeptrAry, edgeTypesAry); //遍歷,因為每一條邊界又可能由多種AcGe曲線構成 for (int j = 0; j < edgeTypesAry.length(); j++) { if (edgeTypesAry[j] == AcDbHatch::kLine)//直線 { AcGeLineSeg2d *LnSeg = (AcGeLineSeg2d *)edgeptrAry[j]; acutPrintf(L"n直線"); AcGePoint2d pt1 = LnSeg->startPoint(); AcGePoint2d pt2 = LnSeg->endPoint(); AcDbLine *line = new AcDbLine(AcGePoint3d(pt1.x,pt1.y,0), AcGePoint3d(pt2.x, pt2.y, 0)); vecBo.push_back(line); } //圓弧 else if (edgeTypesAry[j] == AcDbHatch::kCirArc) { AcGeCircArc2d *cirArc = (AcGeCircArc2d *)edgeptrAry[j]; acutPrintf(L"n圓弧"); //可以根據數學圓弧構造相應的AcDb圓弧,取決於你(以下同) AcGePoint2d center = cirArc->center(); double ra = cirArc->radius(); double angle1 = cirArc->startAng(); double angle2 = cirArc->endAng(); AcDbCircle *cir = new AcDbCircle(AcGePoint3d(center.x, center.y, 0), AcGeVector3d::kZAxis, ra); vecBo.push_back(cir); } else if (edgeTypesAry[j] == AcDbHatch::kEllArc)//橢圓弧 { AcGeEllipArc2d *ellArc = (AcGeEllipArc2d *)edgeptrAry[j]; acutPrintf(L"n橢圓弧"); AcGePoint2d center = ellArc->center(); AcGeVector2d majorVec = ellArc->majorAxis(); double angle1 = ellArc->startAng(); double angle2 = ellArc->endAng(); double rad = ellArc->majorRadius(); double rad2 = ellArc->minorRadius(); AcDbEllipse *ell = new AcDbEllipse(AcGePoint3d(center.x, center.y, 0), AcGeVector3d::kZAxis, AcGeVector3d(majorVec.x,majorVec.y,0), rad / rad2, angle1, angle2); vecBo.push_back(ell); } else if (edgeTypesAry[j] == AcDbHatch::kSpline)//NURBS曲線 { AcGeNurbCurve2d *spline = (AcGeNurbCurve2d *)edgeptrAry[j]; acutPrintf(L"nNURBS曲線"); AcDbSpline * spl = NULL; createSpline(*spline, spl, 0); vecBo.push_back(spl); } } } vertices.removeAll(); bulges.removeAll(); edgeptrAry.removeAll(); edgeTypesAry.removeAll(); } }
獲得填充邊界集合
分割曲線構造新多段線:

if (pEnt2->isA() == AcDbPolyline::desc()) { AcDbPolyline * plTemp = AcDbPolyline::cast(pEnt2); AcGeDoubleArray dbArr; AcGePoint2dArray pt2dArr; int indexS = 0, indexE = 0; GetCollOfPl(plTemp, dbArr, pt2dArr); //獲得兩個交點的索引用來構造新的多段線 GetIndexOfPl(plTemp, pt2dArr, ptArr, indexS, indexE); AcDbPolyline *newPl = new AcDbPolyline(); newPl->addVertexAt(newPl->numVerts(), AcGePoint2d(ptArr[0].x, ptArr[0].y), 0, 0, 0); for (int i=indexS;i<=indexE;i++) { newPl->addVertexAt(newPl->numVerts(), pt2dArr[i], dbArr[i], 0, 0); } newPl->addVertexAt(newPl->numVerts(), AcGePoint2d(ptArr[1].x, ptArr[1].y), 0, 0, 0); newPl->setColorIndex(4); PostToModelSpace(newPl); newPl->close(); }
截取分隔曲線
構造左右邊界:紅色部分最大邊界和綠色部分最大邊界

static bool GetBoundary(const AcGePoint3d & seedPoint, AcDbVoidPtrArray& ptrArr) { ErrorStatus es = acedTraceBoundary(seedPoint, false, ptrArr); if (es != Acad::eOk) { acutPrintf(L"nboundary=%d", es); return false; } return true; }
View Code
判斷vecBo邊界集合的邊界是否在左右邊界內部:
主要是獲得內部圖形的點集,然後把左邊邊界內部的一點分別與這個點集中的點構成直線,如果直線和左邊邊界相交時有1個以上交點,就說明這個邊界不在左邊界內部。

static bool JudgeXj(CONST AcGePoint3dArray & ptArr, AcDbEntity *pEnt,const AcGePoint3d &innerPt) { AcDbLine * l = new AcDbLine(); l->setStartPoint(innerPt); AcGePoint3dArray ptTemp; for (int i = 0; i < ptArr.length(); i++) { l->setEndPoint(ptArr[i]); l->intersectWith(pEnt, AcDb::kOnBothOperands, ptTemp); if (ptTemp.length() >= 1) { delete l; l = NULL; return true; } } return false; }
判斷邊界是否在左邊邊界內部
完整程式碼見附件: