objectarx 填充的分割

主要思路:找到填充邊界集合: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;      }

判斷邊界是否在左邊邊界內部

完整程式碼見附件: