// PlaceTreeStyle.cpp: implementation of the CPlaceTreeStyle class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "PlaceTreeStyle.h" #include "SinglePlaceTreeDlg.h" #include "TPlaceTreePreviewJig.h" #include "dbregion.h" #include "GlwPlaceTreeDataManage.h" #include "GlwGlobalVariable.h" #include "dbRay.h" // add by xly on 110324 引入随机函数 extern double GetRandNumber(double dMin, double dMax); //调整多线段内画树的个数 int GetTreeNum(XPoly2D &ploy2D, double dRad) { double dArea; int nTreeNum; dArea = ploy2D.Area(); nTreeNum = fabs(dArea) / (4 * dRad * dRad); if(nTreeNum > 0 && nTreeNum < 50) { double dprob; dprob = GetRandNumber(0.7, 0.8); nTreeNum = dprob * nTreeNum; } else if(nTreeNum >= 50 && nTreeNum < 100) { double dprob; dprob = GetRandNumber(0.6, 0.7); nTreeNum = dprob * nTreeNum; } else if (nTreeNum >= 100 && nTreeNum < 500) { double dprob; dprob = GetRandNumber(0.5, 0.6); nTreeNum = dprob * nTreeNum; } else if (nTreeNum >= 500 && nTreeNum < 1500) { double dprob; dprob = GetRandNumber(0.4, 0.5); nTreeNum = dprob * nTreeNum; } else if(nTreeNum >= 1500 && nTreeNum < 7500) { double dprob; dprob = GetRandNumber(0.2, 0.4); nTreeNum = dprob * nTreeNum; } else if (nTreeNum > 7500) { double dprob; dprob = GetRandNumber(0.1, 0.2); nTreeNum = dprob * nTreeNum; } return nTreeNum; } //获取形心中心 BOOL GetPolyLineCenterPoint(const AcDbPolyline &poly, AcGePoint3d &ptCenter) { unsigned iCount = 0; AcDbVoidPtrArray curveSegments, regions; AcGePoint3d LinePt0, LinePt1; AcGePoint3d origin; AcGeVector3d xAxis, yAxis; double perimeter, area, prodInertia; double momInertia[2], prinMoments[2], radiiGyration[2]; AcGePoint2d centroid; AcGeVector2d prinAxes[2]; AcGePoint2d extentsLow, extentsHigh; curveSegments.append((AcDbCurve *) &poly); if (AcDbRegion::createFromCurves(curveSegments, regions) != Acad::eOk){ return FALSE; } AcDbRegion * pRegion; if ((iCount = regions.length()) == 0){ return FALSE; } pRegion = (AcDbRegion *) regions.at(0); origin.set(0,0,0); xAxis.set(1,0,0); yAxis.set(0,1,0); if (pRegion->getAreaProp( origin, xAxis, yAxis, perimeter, area, centroid, momInertia, prodInertia, prinMoments, prinAxes, radiiGyration, extentsLow, extentsHigh) != Acad::eOk ){ pRegion->close(); delete pRegion; return FALSE; } pRegion->close(); delete pRegion; ptCenter.x = centroid.x; ptCenter.y = centroid.y; return TRUE; } enum ERandomPtState { eFirst = 0, eContinu = 1, eToBeEnd = 2, }; int GetRandIntNum(int nMin, int nMax) { int nRand = 0; nRand = rand() % (nMax - nMin) + nMin; return nRand; } BOOL IsCircle(XPoly2D &xPoly2D) { BOOL bRet = FALSE; TGGeCurveSegment cv; int nSegNum = 0; nSegNum = xPoly2D.TotalSegments(); if (2 == nSegNum && 2 == xPoly2D.Length()) { TGGeCurveSegment cv1, cv2; xPoly2D.Nth(0, cv1); xPoly2D.Nth(0, cv2); if ((fabs(cv1.GetBulge() - PI) < 1E-6) && (fabs(cv2.GetBulge() - PI) < 1E-6)) { bRet = TRUE; } } return bRet; } //随机获取多线段切割线上一点 void GetRandPtOnLine(XPoly2D &xPoly2D, TDPtrList &ptList, AcGePoint3d &ptStart, const AcGePoint3d &ptCenter) { if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dRad = pDataManage->GetTreeRad(TRUE); int nNum = GetTreeNum(xPoly2D, dRad); AcGePoint3d ptEnd; int nPtNum, nTotleNum, nSelFrst, nSelSecond; double dAngle = 0, dLength = 0, dTransLength = 0; nPtNum = xPoly2D.Length(); nTotleNum = nPtNum + ptList.Length(); if (nNum < 1500) { int nRandNum = rand() % 3; if (!nRandNum) { nSelFrst = GetRandIntNum(0, nPtNum); } else { nSelFrst = GetRandIntNum(nPtNum, nTotleNum); } if (nSelFrst > nPtNum - 1) ptStart = ptList.GetAt(nSelFrst - nPtNum)->AsAcGePoint3d(); else ptStart = xPoly2D.GetPointListAt(nSelFrst)->AsAcGePoint3d(); dLength = GetRandNumber(0, ptCenter.distanceTo(ptStart)); AcGeVector3d vecStToend(ptStart - ptCenter); nRandNum = rand() % 4; if (!nRandNum) { ptStart = -dLength * vecStToend / vecStToend.length() + ptStart; } else { ptStart= dLength * vecStToend / vecStToend.length() + ptCenter; } } else { int nRandNum = rand() % 2; if (!nRandNum) nSelFrst= GetRandIntNum(nPtNum , nTotleNum); else nSelFrst = GetRandIntNum(0, nPtNum); if (nSelFrst > nPtNum) ptStart = (*ptList.GetAt(nSelFrst - nPtNum - 1)).AsAcGePoint3d(); else if (nSelFrst == nPtNum) ptStart = ptCenter; else ptStart = (*xPoly2D.GetPointListAt(nSelFrst)).AsAcGePoint3d(); while (true) { nRandNum = rand() % 2; if (!nRandNum) nSelSecond= GetRandIntNum(nPtNum, nTotleNum); else nSelSecond = GetRandIntNum(0, nPtNum); if (nSelFrst < nPtNum && (nSelSecond == nSelFrst + 1 || nSelSecond == nSelFrst - 1) ) { continue; } if (nSelSecond != nSelFrst) { break; } } if (nSelSecond > nPtNum) ptEnd = (*ptList.GetAt(nSelSecond - nPtNum - 1)).AsAcGePoint3d(); else if (nSelSecond == nPtNum) ptEnd = ptCenter; else ptEnd = *xPoly2D.GetPointListAt(nSelSecond); dLength = GetRandNumber(0, ptStart.distanceTo(ptEnd)); AcGeVector3d vecStToend(ptEnd - ptStart); if (rand() % 2) ptStart = dLength * vecStToend / vecStToend.length() + ptStart; else ptStart = -dLength * vecStToend / vecStToend.length() + ptEnd; } } //随机获取圆切割线上一点 void GetRandPtOnLineForCircle(XPoly2D &xPoly2D, TDPtrList &ptList, AcGePoint3d &ptStart, const AcGePoint3d &ptCenter) { AcGePoint3d ptOnPoly; TADSGePoint3d tgPoint; int nPtNum, nSelPt, nTotleNum; double dLength = 0; nPtNum = xPoly2D.Length(); nTotleNum = nPtNum + ptList.Length(); nSelPt = GetRandNumber(0, nTotleNum); if (nSelPt > nPtNum - 1) ptOnPoly = ptList.GetAt(nSelPt - nPtNum)->AsAcGePoint3d(); else ptOnPoly = xPoly2D.GetPointListAt(nSelPt)->AsAcGePoint3d(); dLength = GetRandNumber(0, ptCenter.distanceTo(ptOnPoly)); AcGeVector3d vecStToend(ptOnPoly - ptCenter); int nRandNum = rand() % 10; if (!nRandNum) { ptStart = dLength * vecStToend / vecStToend.length() + ptCenter; } else { if (nRandNum % 2) ptStart= -dLength * vecStToend / vecStToend.length() + ptOnPoly; else ptStart= -0.75 * dLength * vecStToend / vecStToend.length() + ptOnPoly; } } void GetPtOnInterLine(XPoly2D &xPoly2D, AcGePoint3d& ptStart, AcGePoint3d& ptOnInterLine) { AcGePoint3d ptTemp; TGGePoly tgPloy; int nSelPt; double dAngle = 0, dLength = 0, dTransLength = 0; xPoly2D.MapToPolygon(tgPloy); dAngle = GetRandNumber(0, 2*PI); AcGeVector2d vecStart = AcGeVector2d::kXAxis; vecStart = vecStart.rotateBy(dAngle); dLength = xPoly2D.GetLength(); ptTemp = dLength * vecStart / vecStart.length() + ptStart; XLine* pXlineSt = new XLine(); pXlineSt->SetStartPoint(ptStart); pXlineSt->SetEndPoint(ptTemp); TPointList ptlstStart(ptStart, ptTemp); int nCrossPt = 0; nCrossPt = pXlineSt->Intersection(&tgPloy, ptlstStart); if(nCrossPt < 1) return; if (nCrossPt > 1) { if (nCrossPt % 2) { nSelPt = rand() % nCrossPt; if (!nSelPt) { ptOnInterLine = ptlstStart.GetAt(1)->AsAcGePoint3d(); } else { if (nSelPt % 2) { ptOnInterLine = ptlstStart.GetAt(nSelPt + 2)->AsAcGePoint3d(); ptStart = ptlstStart.GetAt(nSelPt + 1)->AsAcGePoint3d(); } else { ptStart = ptlstStart.GetAt(nSelPt)->AsAcGePoint3d(); ptOnInterLine = ptlstStart.GetAt(nSelPt + 1)->AsAcGePoint3d(); } } } else { nSelPt = rand() % nCrossPt; if (nSelPt % 2) { ptStart = ptlstStart.GetAt(nSelPt)->AsAcGePoint3d(); ptOnInterLine = ptlstStart.GetAt(nSelPt + 1)->AsAcGePoint3d(); } else { ptStart = ptlstStart.GetAt(nSelPt + 1)->AsAcGePoint3d(); ptOnInterLine = ptlstStart.GetAt(nSelPt + 2)->AsAcGePoint3d(); } } } else ptOnInterLine = ptlstStart.GetAt(1)->AsAcGePoint3d(); dTransLength = GetRandNumber(0, ptOnInterLine.distanceTo(ptStart)); if(rand() % 2) ptOnInterLine = (dTransLength) * vecStart / vecStart.length() + ptStart; else ptOnInterLine = -(dTransLength) * vecStart / vecStart.length() + ptOnInterLine; ptlstStart.Reset(); } //获取多线段内随机点 BOOL GetRandomPtByPloy(XPoly2D &xPoly2D, AcGePoint3d &ptRand, ERandomPtState &eRandomState) { static TDPtrList ptList; static AcGePoint3d ptCenter; static BOOL bIsCircle = FALSE; TGGeCurveSegment cv; int nSegNum = 0; if (eFirst == eRandomState) { AcDbPolyline polyLine; PolyConvert(xPoly2D, polyLine); GetPolyLineCenterPoint(polyLine, ptCenter); nSegNum = xPoly2D.TotalSegments(); bIsCircle = IsCircle(xPoly2D); if (bIsCircle) { double dRadius = ptCenter.distanceTo(xPoly2D.GetPointListAt(0)->AsAcGePoint3d()); for(int num = 0; num < nSegNum; ++num) { TADSGePoint3d ptOnCircle = *xPoly2D.GetPointListAt(num); AcGeVector3d vecRand = ptOnCircle.AsAcGePoint3d() - ptCenter; for (int i = 0; i < 9; i++) { TADSGePoint3d* tgres = new TADSGePoint3d(ptCenter); vecRand = vecRand.rotateBy(0.1 * (i + 1) * PI, AcGeVector3d::kZAxis); *tgres = *tgres + dRadius * vecRand / vecRand.length(); ptList.Append(tgres); } } } else { for(int num = 0; num < nSegNum; ++num) { TADSGePoint3d* tgres = new TADSGePoint3d; xPoly2D.Nth(num, cv); if(cv.ProjectToMe(ptCenter, *tgres) == RTNORM) ptList.Append(tgres); else delete tgres; } } eRandomState = eContinu; } AcGePoint3d ptOnInterLine, ptStart; TGGePoly tgPloy; int nSelPt; double dAngle = 0, dLength = 0, dTransLength = 0; xPoly2D.MapToPolygon(tgPloy); if (bIsCircle) GetRandPtOnLineForCircle(xPoly2D, ptList, ptStart, ptCenter); else GetRandPtOnLine(xPoly2D, ptList, ptStart, ptCenter); GetPtOnInterLine(xPoly2D, ptStart, ptOnInterLine); GetPtOnInterLine(xPoly2D, ptOnInterLine, ptRand); if(xPoly2D.HitTestOnCurve((TADSGePoint3d)ptRand)) return FALSE; if (eToBeEnd == eRandomState) { ptList.Reset(); bIsCircle = FALSE; } return TRUE; } BOOL ptInPoly(AcGePoint3d & pt, AcDbPolyline &poly) { poly.setClosed(Adesk::kTrue); AcDbRay ray; ray.setBasePoint(AcGePoint3d(pt.x, pt.y, 0.0)); ray.setUnitDir(AcGeVector3d(0.0, -1.0, 0.0)); AcGePoint3dArray points; poly.intersectWith(&ray, AcDb::kOnBothOperands, points); if (points.length() % 2) return TRUE; else return FALSE; } //与ch_utility\EdJigEx.cpp类里int DragInputPoly2d(XPoint ptStart, XPoly2D &poly2dRet)区别是否连续绘制弧段 BOOL DragPolyLine(AcDbPolyline *pLine, XPoint ptStart) { if (NULL == pLine) return FALSE; pLine->addVertexAt(0, ptStart); TPolyEdJig jig(pLine); jig.SetPrompt(_T("\n直段下一点或 [弧段(A)/回退(U)]<结束>: ")); jig.SetOperCode(TPolyEdTreeJig::kLinePoint);//设置直线 jig.SetKeyword(_T("A U")); while(1) { int nKeyIndex=0; int nRetCode=jig.DoIt(&nKeyIndex); if(nRetCode==RTNORM) {//左键 pLine->addVertexAt(pLine->numVerts(), (AcGePoint2d &)jig.GetPickPoint()); if(jig.GetOperCode()==TPolyEdJig::kArcPoint) //如果是弧段 { CString strPrompt = _T(""); TPolyEdJig jig1(pLine); jig1.SetOperCode(TPolyEdJig::kArcMidPoint);//取弧上一点 jig1.SetPrompt(_T("\n点取弧上一点:")); //jig1.SetKeyword(_T("R")); int nKeyIdx; int nRetCode1=jig1.DoIt(&nKeyIdx); if(nRetCode1==RTKWORD) { static double dRadius=6000.0; TPolyEdTreeJig jigTree(pLine); dRadius = _AS_SYS_UNIT(dRadius); if (DocGetMeterUnitDraw()) { strPrompt.Format(_T("\n输入半径<%.3f>"), dRadius); } else { strPrompt.Format(_T("\n输入半径<%.0f>"), dRadius); } jigTree.SetOperCode(TPolyEdJig::kArcRadius);//取弧上半径,遗留问题??问题原因: jigTree.SetRadius(dRadius); jigTree.SetPrompt(strPrompt); jigTree.DoIt(); dRadius = jigTree.GetRadius(); if (DocGetMeterUnitDraw()) { dRadius = _AS_MM(dRadius); } } } else //如果是直线段 { jig.SetPrompt(_T("\n直段下一点或 [弧段(A)/回退(U)]<结束>: ")); jig.SetOperCode(TPolyEdJig::kLinePoint); jig.SetKeyword(_T("A U")); } } //输入关键字 else if(nRetCode==RTKWORD) { if(jig.GetOperCode()==TPolyEdJig::kLinePoint) { if(nKeyIndex==0) {//弧线绘制 jig.SetOperCode(TPolyEdJig::kArcPoint); jig.SetPrompt(_T("\n弧段下一点或 [直段(L)/回退(U)]<结束>: ")); jig.SetKeyword(_T("L U")); } else if(nKeyIndex==1) {//回退 int numVert=pLine->numVerts(); if(numVert>1) { pLine->removeVertexAt(numVert-1); pLine->setBulgeAt(numVert-2, 0.0); } } } else if(jig.GetOperCode()==TPolyEdJig::kArcPoint) { if(nKeyIndex==0) {//直线绘制 jig.SetOperCode(TPolyEdJig::kLinePoint); jig.SetPrompt(_T("\n直段下一点或 [弧段(A)/回退(U)]<结束>: ")); jig.SetKeyword(_T("A U")); } else if(nKeyIndex==1) {//回退 int numVert=pLine->numVerts(); if(numVert>1) { pLine->removeVertexAt(numVert-1); pLine->setBulgeAt(numVert-2, 0.0); } } } } //右键或者空格,跳出循环 else if(nRetCode==RTNONE) { break; } //取消,直接返回 else if(nRetCode==RTCAN) { return RTERROR; } } int numVert=pLine->numVerts(); if(numVert<2) //继续当前命令 return FALSE; //继续当前命令 return TRUE; } CPlaceTreeStyle::CPlaceTreeStyle() { } CPlaceTreeStyle::~CPlaceTreeStyle() { } bool CPlaceTreeStyle::MakeBlockReference(AcGePoint3d ptInsert) { //实时获取数据 if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dRad = pDataManage->GetTreeRad(TRUE); BOOL bIsRotation = pDataManage->GetIsSetRotation(); AcDbObjectId idBlk = pDataManage->GetTreeId(); AcDbBlockReference *pRef = new AcDbBlockReference(ptInsert, idBlk); if (pRef == NULL) { return false; } AcDbExtents extents; AcGePoint3d ptLow,ptUp; // 获得块的包围盒 pRef->getGeomExtents(extents); // 计算块的大小 ptLow = extents.minPoint(); ptUp = extents.maxPoint(); double dSize = (ptUp.x-ptLow.x)/2; // 比例变化矩阵 AcGeMatrix3d xform; // 设置块比例 xform.setToScaling(dRad / dSize, ptInsert); pRef->transformBy(xform); // add by xly on 110324 设置随机旋转 if (bIsRotation) { xform.setToRotation((double)GetRandNumber(0, PI * 2), AcGeVector3d::kZAxis, ptInsert); pRef->transformBy(xform); } // add by xly on 110327 设置任意布树的图层 AcDbObjectId idLayer = InitLayer(LAY_TREE); pRef->setLayer(idLayer); AcDbObjectId idRef = AddToModelSpace(pRef, Adesk::kTrue); // 添加到数据库 return true; } // 自由插入 bool CPlaceTreeStyle::FreedomPlaceTree() { bool bOk = true; // 标记插入点是否满足“树间距” int nRet(0), nLength(0), i(0); AcGePoint3d ptInsert; AcGePoint3dArray arPts; while(1) { nRet = acedGetPoint(NULL, _T("\n请点取插入点<退出>:"), asDblArray(ptInsert)); if (nRet != RTNORM) { return false; } ptInsert = Ucs2Wcs(ptInsert);// add by xly on 110328 支持用户坐标系 if (!MakeBlockReference(ptInsert)) // 造块 { return false; } arPts.append(ptInsert); } return true; } // 拖动绘制树 bool CPlaceTreeStyle::DragPlaceTreeExtend() { AcDbPolyline polyLine; XPoint ptStart; int nRet = acedGetPoint(NULL, _T("\n请输入起始点<退出>:"), ptStart); if (nRet != RTNORM) { return false; } ptStart = Ucs2Wcs(ptStart);//add tyj 20160926:解决用户坐标系下起点位置错误的问题 DragPolyLine(&polyLine, ptStart); //根据偏移量判断是否需要偏移路径,偏移时点击右键或者空白,退出 if (!GetPolyLineByOffsetPreviewJig(polyLine)) return false; if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dDis = pDataManage->GetTreeDis(); BOOL bIsSetDis = pDataManage->GetIsSetDis(); AcGePoint3dArray arPts; PolyLineStyle(&polyLine, dDis, arPts, bIsSetDis); int nLen = arPts.length(); for (int n = 0; n:"),asDblArray(ptInsert)); if (nRet != RTNORM) { return false; } int i(0), iTreeNums(0); double dUcsAngle = 0.0, dLength(0); AcGeVector3d vtCur(cos(dUcsAngle), sin(dUcsAngle), 0), vet; AcGePoint3dArray arPts;// 保存用户插入点 // add by xly on 110328 支持用户坐标系 //arPts.append(ptInsert); arPts.append(Ucs2Wcs(ptInsert)); PickSet ss(SS_FREE); AcGeIntArray nAryTreeNums;// 保存最后一次添加树的数量 if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dDis = pDataManage->GetTreeDis(); while (1) { INITGET_BEG(NULL, _T("U")); nRet = acedGetPoint(asDblArray(ptInsert), _T("\n输入下一点或[回退(U)]<结束>:"), asDblArray(ptNext)); INITGET_END(); if (nRet == RTKWORD) // 关键字,回退 { // 已经退到第一个点 int nAryLen = arPts.length(); if (nAryLen<2) { continue; } // 删除最新一个点 arPts.removeLast(); // 鼠标回退到倒数第二个点 ptInsert = arPts.last(); // add by xly on 110328 支持用户坐标系 ptInsert = Wcs2Ucs(ptInsert); // 树的总数 long nLen = ss.Length(); int nTemp = nAryTreeNums.last(); nAryTreeNums.removeLast(); // 将最后一次添加的树移除 PickSet ssDel(SS_FREE); for (long n = nLen-nTemp-1; n:"), ssLine, rbMask); if (nRet != RTNORM) { return false; } long ni = 0, nSsLen = ssLine.Length(); // 打开选择集中的实体 for(ni = 0; niisKindOf(AcDbLine::desc())) // 直线 { AcDbLine* pLine = AcDbLine::cast(pEnt); AsPolyline(*pLine, polyLine); } else if (pEnt->isKindOf(AcDbArc::desc()))// 圆弧 { AcDbArc *pArc = AcDbArc::cast(pEnt); AsPolyline(*pArc, polyLine); } else if (pEnt->isKindOf(AcDbPolyline::desc()))// 多段线,起点位置 { AcDbPolyline *pPoly= AcDbPolyline::cast(pEnt); polyLine.copyFrom(pPoly->clone()); //polyLine = *((AcDbPolyline*)pPoly->clone()); } OPENOBJ_END(); //根据偏移量判断是否需要偏移路径 if (!GetPolyLineByOffsetPreviewJig(polyLine)) continue; //根据路径绘制块 if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dDis = pDataManage->GetTreeDis(); BOOL bIsSetDis = pDataManage->GetIsSetDis();//修改 tyj 20160831:函数用错了,修正任意布树时路径匹配模式下间距一直是自动调整的错误 AcGePoint3dArray arPts;// 保存插入点 PolyLineStyle(&polyLine, dDis, arPts, bIsSetDis); int nLen = arPts.length(); for (int n = 0; n:"), ent, rbFilter, kword, chRet); int vn = hookmsg.GetValue(); switch (iRetCode) { case RTNORM: { //选择多段线 TGGePoly2D poly2dTemp(ent); poly2d = poly2dTemp; poly2d.SetClosed(); return 1; } break; case RTKWORD: { //绘制边界线 nSelectMode = kDraw; return 0; } break; default: { if(vn == 0 && GetFocus() == acedGetAcadDwgView()->GetSafeHwnd())//当前焦点在CAD上,并且没有选中 { acutPrintf(_T("\n选择无效,请重新选择!")); return 0; } else return -1; } } } int CPlaceTreeStyle::DrawPolyLine(TGGePoly2D &poly2d, int &nSelectMode) { XPoint ptStart; int nRet = 0; INITGET_BEG(0, _T("Q")); nRet = acedGetPoint(NULL, _T("\n请输入起始点或[选择多段线(Q)]:"), ptStart); INITGET_END(); ptStart = Ucs2Wcs(ptStart);//add tyj 20160927:修正用户坐标系下起点错误的问题 if (nRet == RTKWORD) { nSelectMode = kSelect; return 0; } else if (nRet != RTNORM) { //直接退出命令 return -1; } AcDbPolyline polyLine; PolyConvert(poly2d, polyLine); if (!DragPolyLine(&polyLine, ptStart)) { return 0; } polyLine.setClosed(TRUE); PolyConvert(polyLine, poly2d); return 1; } //获取多段线 int CPlaceTreeStyle::GetPolyLine(TGGePoly2D &poly2d, int &nSelectMode) { if (nSelectMode == kSelect) { return SelectPolyLine(poly2d, nSelectMode); } else if (nSelectMode == kDraw) { return DrawPolyLine(poly2d, nSelectMode); } return -1; } // 区域内随机分布树 bool CPlaceTreeStyle::RegPlaceTree() { int nSelectMode = kSelect; while (1) { TGGePoly2D poly2d; //获取多段线 int nRet = GetPolyLine(poly2d, nSelectMode); AcDbPolyline pline; PolyConvert(poly2d, pline); if (-1 == nRet) return false; else if (0 == nRet) continue; //闭合多断线 //多段线不需要闭合 // if (!poly2d.IsClosed()) // poly2d.SetClosed(); //多段线面积 if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dRad = pDataManage->GetTreeRad(TRUE); if (abs(dRad) <= 0.0000006) return false; int nNum = GetTreeNum(poly2d, dRad); ERandomPtState eRandomState = eFirst; for (int i=0; istartPoint(); ptEnd = pLine->endPoint(); // add by xly on 110324 清空数组 ptAryInsert.setLogicalLength(0); ptAryInsert.append(ptSt); // 计算直线的长度 double dLenth = ptSt.distanceTo(ptEnd); AcGeVector3d ver = ptEnd - ptSt; // 当前的坐标系 double dUcsAngle = 0.0; AcGeVector3d vtCur(cos(dUcsAngle), sin(dUcsAngle), 0); dUcsAngle = ver.angleTo(vtCur, AcGeVector3d::kZAxis); // 生成树的数量 int iNumTrees = 0; if(bIsSetDis)// 间距自调 { iNumTrees = (int)(dLenth / dTreeDis); dTreeDis = dLenth / iNumTrees; } else// 间距不自调 { iNumTrees = (int)(dLenth / dTreeDis); } AcGePoint3d ptInsertNew; for(int i = 0; i < iNumTrees; i++) { // 计算新的插入点 acutPolar(asDblArray(ptSt), -dUcsAngle, dTreeDis+dTreeDis * i, asDblArray(ptInsertNew)); ptAryInsert.append(ptInsertNew); } } // 圆弧样式生成树 void CPlaceTreeStyle::ArcStyle(AcDbArc *pArc, double dTreeDis, AcGePoint3dArray &ptAryInsert, BOOL bIsSetDis, double dBugle) { AcGePoint3d ptSt,ptCentre; // 获得圆弧的参数 pArc->getStartPoint(ptSt); ptCentre = pArc->center(); // add by xly on 110324 清空数组 ptAryInsert.setLogicalLength(0); ptAryInsert.append(ptSt); // 获得圆弧的半径 double dArcRad = pArc->radius(); // 计算弧长 double dLenth = (pArc->endAngle() - pArc->startAngle()) * dArcRad; if (dLenth<0+_DIST_SNAP)// 优弧 { dLenth = 2 * PI * dArcRad + dLenth; } // 当前的坐标系 double dUcsAngle; // 生成树的数量 int iNumTrees = 0; if (bIsSetDis)// 间距自调 { iNumTrees = (int)(dLenth / dTreeDis); dTreeDis = dLenth / iNumTrees; // 根据弧长计算角度 dUcsAngle = dTreeDis / dArcRad; } else { // 根据弧长计算角度 dUcsAngle = dTreeDis / dArcRad; // 计算插入树的数量 iNumTrees = (int)(dLenth / (dUcsAngle*dArcRad)); } AcGeVector3d verSt, verEnd; verSt = ptSt- ptCentre; // 绘制树 AcGePoint3d ptInsertNew; for(int i = 0; i-1E-6) { verEnd = verSt.rotateBy(dUcsAngle, AcGeVector3d::kZAxis); } else { verEnd = verSt.rotateBy(-dUcsAngle, AcGeVector3d::kZAxis); } ptInsertNew = verEnd + ptCentre; ptAryInsert.append(ptInsertNew); } } // 多段线样式生成树 void CPlaceTreeStyle::PolyLineStyle(AcDbPolyline *pPolyLine, double dTreeDis, AcGePoint3dArray &ptAryInsert, BOOL bIsSetDis) { // 获得多段线的起点 AcGePoint3d ptSt, ptEnd; pPolyLine->getStartPoint(ptSt); pPolyLine->getEndPoint(ptEnd); // 获得多段线的所有顶点 //int iNumVerts = pPolyLine->numVerts(); XPoly2D poly2d; BOOL bIsClose = TRUE; PolyConvert(*pPolyLine, poly2d); int iNumVerts = poly2d.TotalSegments(); bIsClose = poly2d.IsClosed(); double dBulge = 0.0; AcGeCircArc3d arc; AcGeLineSeg3d line; AcGePoint3dArray aryTemp; // 遍历多段线的顶点,除了最后一点 for (int i = 0; igetBulgeAt(i,dBulge); if (dBulge != 0)// 圆弧 { pPolyLine->getArcSegAt(i,arc); // 获得几何图形的参数 AcGePoint3d ptCenter = arc.center(); AcGeVector3d normal = arc.normal(); AcGeVector3d refVec = arc.refVec(); AcGePlane plane = AcGePlane(ptCenter,normal); double dAng = refVec.angleOnPlane(plane); // 构造数据库的实体 AcDbArc *pArc = new AcDbArc(ptCenter,normal,arc.radius(),arc.startAng()+dAng, arc.endAng()+dAng); ArcStyle(pArc,dTreeDis,aryTemp,bIsSetDis,dBulge); if (i != 0) aryTemp.removeFirst(); if ((i == (iNumVerts - 1)) && bIsClose) aryTemp.removeLast(); } else// 直线 { pPolyLine->getLineSegAt(i,line); AcDbLine *pLine = new AcDbLine(line.startPoint(),line.endPoint()); LineStyle(pLine,dTreeDis,aryTemp,bIsSetDis); if (i != 0) aryTemp.removeFirst(); if ((i == (iNumVerts - 1)) && bIsClose) aryTemp.removeLast(); } ptAryInsert.append(aryTemp); } } //判断是否有偏移量,有偏移量进行预览,得到预览后的polyLine bool CPlaceTreeStyle::GetPolyLineByOffsetPreviewJig(AcDbPolyline &polyLine) { //如果有偏移量要进行偏移预览 if(!GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage)) SET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage, new GlwPlaceTreeDataManage); GlwPlaceTreeDataManage *pDataManage = GET_GLOBAL_VARIABLE(GlwPlaceTreeDataManage); double dOffsetDis = pDataManage->GetTreeOffset(); //判断是否需要偏移 if (abs(dOffsetDis) > 0.0000001) { TPlaceTreePreviewJig jigPreView(&polyLine); jigPreView.SetPrompt(_T("\n请点取偏移方向:")); int nRet = jigPreView.doIt(); if(nRet !=RTNORM) { return false; } //polyLine = *jigPreView.CloneCurrentSelectPoly(); polyLine.copyFrom(jigPreView.CloneCurrentSelectPoly()); } return true; }