#include "stdafx.h" #include "dbxutil.h" #include "dbregion.h" #include "MultPlaceTreeDlg.h" #include "SinglePlaceTreeDlg.h" #include "PlaceTreeStyle.h" // 在制定范围内获取随机数 // 在 dMin——dMax范围内获取随机数 double GetRandNumber(double dMin, double dMax) { double dRand = 0; dRand = (((double) rand() / (double) RAND_MAX) * (dMax - dMin) + dMin); return dRand; } // 生成面域 void TransToRegions(AcDbVoidPtrArray& arEnts, AcDbObjectIdArray& arIds) { AcDbObjectId idRegion; AcDbVoidPtrArray arRegions; // 创建面域 AcDbRegion region; region.createFromCurves(arEnts, arRegions); if (arRegions.length() == 1) // 面域中有一个实体 { AcDbRegion *pRegion = (AcDbRegion*)arRegions.first(); if (pRegion != NULL) { // 面域添加到模型空间 idRegion = AddToModelSpace(pRegion, TRUE); // 保存面域的Id arIds.append(idRegion); } } else if (arRegions.length() == 2) // 面域中有两个实体 { AcDbRegion *pRegion = (AcDbRegion*)arRegions.first(); AcDbRegion *pUnit = (AcDbRegion*)arRegions.last(); if (pRegion != NULL && pUnit != NULL) { double dArea1 = 0.0; double dArea2 = 0.0; pRegion->getArea(dArea1); pUnit->getArea(dArea2); if (dArea1 > dArea2) { // 布尔运算取出交集 pRegion->booleanOper(AcDb::kBoolSubtract, pUnit); idRegion = AddToModelSpace(pRegion, TRUE); } else { pUnit->booleanOper(AcDb::kBoolSubtract, pRegion); idRegion = AddToModelSpace(pUnit, TRUE); } arIds.append(idRegion); } } } // 布树 BOOL MultPlaceTreeT(CMultPlaceTreeDlg &dlg, AcGePoint3dArray &arPts, AcDbObjectId idBlk, AcDbObjectIdArray &arIds, double &dScaleRad) { int nRet = 0; AcGePoint3d ptInsert; AcDbVoidPtrArray arEnts; AcDbBlockReference* pRef = NULL; AcGeMatrix3d xform; struct resbuf result; int nType = 0; BOOL bKW = FALSE; while (TRUE) { // 等待0.01秒绘制 Sleep(10); nType = 0; // 获得用户的设备输入 nRet = acedGrRead(13, &nType, &result); if (nType >= 11) { break; } else if (nType == 3) // 点坐标 { break; } else if (nType == 2) // 输入字码 { if (result.resval.rint == 83 || result.resval.rint == 115) { bKW = TRUE; break; } } if (nRet == RTNORM) // 用户的没有中断 { // 保存鼠标扫过的点 AcGePoint3d ptNew; ads_point_set(result.resval.rpoint, asDblArray(ptNew)); // 将鼠标扫过的点转化为世界坐标系的点 acdbUcs2Wcs(asDblArray(ptNew), asDblArray(ptInsert), false); bool bContinue = false; if (dlg.m_bSameDis) // 间距固定 { for (int i = 0; i < arPts.length(); i++) { if (ptInsert.distanceTo(arPts.at(i)) < dlg.GetDisMin()) { bContinue = true; break; } } } else // 间距不固定 { // 随机获取最大值和最小值中的一个 double dRandDis = GetRandNumber(dlg.GetDisMin(), dlg.GetDisMax()); for (int i = 0; i < arPts.length(); i++) { if (ptInsert.distanceTo(arPts.at(i)) < dRandDis) { bContinue = true; break; } } } if (bContinue) continue; arEnts.setLogicalLength(0); // 初始化块参照 pRef = new AcDbBlockReference(ptInsert, idBlk); if (dlg.m_bSameRad) // 半径固定 { xform.setToScaling(dScaleRad*dlg.GetRadMin(), ptInsert); } else // 半径不固定 { xform.setToScaling((double)GetRandNumber(dlg.GetRadMin(), dlg.GetRadMax()), ptInsert); } pRef->transformBy(xform); xform.setToRotation((double)GetRandNumber(0, PI * 2), AcGeVector3d::kZAxis, ptInsert); pRef->transformBy(xform); // 将对应的树形块炸 Acad::ErrorStatus es = pRef->explode(arEnts); if (es != Acad::eOk) return FALSE; delete pRef; // 实体转化为面域 TransToRegions(arEnts, arIds); arPts.append(ptInsert); } else { break; } } return !bKW; } // 插入块函数 AcDbObjectId InsertBlock(CString &csBlkName, int &iTreeType) { // 获得块表 AcDbBlockTable *pBlockTab = NULL; if (acdbCurDwg()->getSymbolTable(pBlockTab, AcDb::kForRead) != Acad::eOk) return NULL; // 检查块是否存在 AcDbObjectId blockId; Acad::ErrorStatus es = pBlockTab->getAt(csBlkName, blockId, false); if (es == Acad::eOk) { pBlockTab->close(); return blockId; } pBlockTab->close(); // 保存树形文件名 const TCHAR *szFileName = _T(""); switch(iTreeType) // 树形不同用到的图纸不同 { case 0: // 树形1 szFileName = _T("_Tree1.dwg"); break; case 1: // 树形2 szFileName = _T("_Tree2.dwg"); break; case 2: // 树形3 szFileName = _T("_Tree3.dwg"); break; case 3: // 树形4 szFileName = _T("_Tree4.dwg"); break; default: return NULL; } // 找到sys路径下的dwg文件 CString szFullPath = g_sDwbPath; szFullPath = szFullPath.Left(szFullPath.GetLength() - 5) + _T("\\sys\\") + szFileName; // 打开树形文件 AcDbDatabase *pXrefDb = new AcDbDatabase(false); es = pXrefDb->readDwgFile(szFullPath); if (es != Acad::eOk) { delete pXrefDb; return NULL; } // 将树形文件以块的形式插入数据库 es = acdbCurDwg()->insert(blockId, csBlkName, pXrefDb, true); if (es != Acad::eOk) { delete pXrefDb; return NULL; } delete pXrefDb; return blockId; } // 合并面域 void UninRegions(AcDbObjectIdArray& arIds) { // 设置图层 AcDbObjectId idLayer = InitLayer(LAY_TREE); AcDbRegion *pRegion = NULL; AcDbRegion *pOper = NULL; AcDbEntity *pEnt = NULL; AcDbEntity *pEnt1 = NULL; // 打开第一个的实体 if (acdbOpenAcDbEntity(pEnt, arIds.first(), AcDb::kForWrite) != Acad::eOk) return; // 转化为面域 pRegion = AcDbRegion::cast(pEnt); if (pRegion == NULL) return; // 打开第2到最后一个实体 for (int i = 1; i < arIds.length(); i++) { if (acdbOpenAcDbEntity(pEnt1, arIds.at(i), AcDb::kForWrite) != Acad::eOk) return; pOper = AcDbRegion::cast(pEnt1); if (pOper != NULL) { // 面域之间做布尔元素按求并集 pRegion->booleanOper(AcDb::kBoolUnite, pOper); } pEnt1->erase();//add tyj 20161107:删除不需要的实体,修正成片布树,会额外生成面积为0的面域 pEnt1->close(); } pEnt->setLayer(idLayer); pEnt->close(); } // 单点绘制函数的实现 void PointPlaceTree(CMultPlaceTreeDlg& dlg, AcDbObjectId idBlk, AcDbObjectIdArray& arIds, AcGePoint3d ptInsert,double& dRadScale ) { static AcGePoint3dArray arPts; bool bContinue = false; if (dlg.m_bSameDis) // 间距固定 { for (int i = 0; i < arPts.length(); i++) { if (ptInsert.distanceTo(arPts.at(i)) < dlg.GetDisMin()) { bContinue = true; break; } } if (bContinue) return; } AcDbVoidPtrArray arEnts; AcGeMatrix3d xform; AcDbBlockReference *pRef = new AcDbBlockReference(ptInsert, idBlk); if (dlg.m_bSameRad) // 半径固定 { xform.setToScaling(dRadScale*dlg.GetRadMin(), ptInsert); } else // 半径不固定 { xform.setToScaling((double)GetRandNumber(dlg.GetRadMin(), dlg.GetRadMax()), ptInsert); } pRef->transformBy(xform); xform.setToRotation((double)GetRandNumber(0, PI * 2), AcGeVector3d::kZAxis, ptInsert); pRef->transformBy(xform); pRef->explode(arEnts); delete pRef; TransToRegions(arEnts, arIds); // 转化为面域 arPts.append(ptInsert); } ////////////////////////////////////////////////////////////// // // 命令函数:成片布树 // ////////////////////////////////////////////////////////////// // 布树函数 void MultPlaceTree() { CMultPlaceTreeDlg dlgTree; // 判断对话框的状态 CAcModuleResourceOverride vTemp; INT_PTR nRet = dlgTree.DoModal(); if (nRet == IDCANCEL || nRet == IDCLOSE) { return; } // 块半径大小换算 double dRad = dlgTree.m_bSameRad, dScaleRad = 0.0; // 不同的树形对应不同的块 CString csTree; switch(dlgTree.m_iTreeType) { case 0: // 树形1 csTree = _T("TREE1"); dScaleRad = dRad; break; case 1: // 树形2 csTree = _T("TREE2"); dScaleRad = dRad / 1.07; break; case 2: // 树形3 csTree = _T("TREE3"); dScaleRad = dRad / 1.03; break; case 3: // 树形4 csTree = _T("TREE4"); dScaleRad = dRad / 1.08; break; default: return; } // 创建csTree名称的图块 AcDbObjectId BlockId = InsertBlock(csTree, dlgTree.m_iTreeType); if (!BlockId.isValid()) { return; } static bool s_bIsMutiTree = true; // 命令状态控制 srand((unsigned)time(NULL)); int iRet(0); CString csPrompt; AcGePoint3d ptInsert; AcGePoint3dArray arPts; AcDbObjectIdArray arIds; while (true) { csPrompt = s_bIsMutiTree ? _T("\n请点击鼠标左键开始或[单点绘制(Q)]<退出>:") : _T("\n请点取插入点或[连续绘制(Q)]<退出>:"); INITGET_BEG(NULL, _T("Q")); iRet = acedGetPoint(NULL, csPrompt, asDblArray(ptInsert)); INITGET_END(); if (iRet == RTKWORD) // 出现关键字 { s_bIsMutiTree = !s_bIsMutiTree; continue; } if (iRet != RTNORM) // 退出 { break; } if (s_bIsMutiTree) // 连续绘制 { acutPrintf(_T("\n 点击鼠标左键或右键结束绘制!")); if (MultPlaceTreeT(dlgTree, arPts, BlockId, arIds,dScaleRad)) { break; } } else // 单点绘制 { PointPlaceTree(dlgTree, BlockId, arIds, ptInsert, dScaleRad); continue; } } if (arIds.length() > 0) { UninRegions(arIds); // 合并面域 } } ////////////////////////////////////////////////////////////// // // 命令函数:任意布树 // ////////////////////////////////////////////////////////////// void SinglePlaceTree() { CSinglePlaceTreeDlg dlg(acedGetAcadFrame()); { CAcModuleResourceOverride vTemp; dlg.Create(dlg.IDD, acedGetAcadFrame()); } dlg.ShowWindow(SW_SHOW); acedGetAcadDwgView()->SetFocus(); CPlaceTreeStyle placeStyle; // 根据树的布置方式,进行对应的用户交互,并布置树 int nDrawStyle(0); // 接收绘制类型 bool bRet = false; // 接收绘制结果,是否成功 // add by xly on 110327 增加选择集记录添加到数据库中的树 PickSet ssAllTrees(SS_FREE); ssAllTrees.IncludeBegin(); while(1) { // 标记是否使用了ESC退出 dlg.m_bUseEsc = true; nDrawStyle = dlg.GetDrawType(); switch(nDrawStyle) // 绘制方式 { case 0: bRet = placeStyle.FreedomPlaceTree(); // 任意点取 break; case 1: bRet = placeStyle.DragPlaceTreeExtend();// 拖动绘制 ssAllTrees.IncludeEnd(); ssAllTrees.MakeUnnamedGroup(); break; case 2: bRet = placeStyle.PathPlaceTree(); // 路径匹配 ssAllTrees.IncludeEnd(); ssAllTrees.MakeUnnamedGroup(); break; case 3: bRet = placeStyle.RegPlaceTree(); //区域绘制 default: break; } if (!bRet && dlg.m_bUseEsc) // != RTNORM,并且没有切换绘制方式,命令真正结束 { break; } } ssAllTrees.IncludeEnd(); // modify by xly on 110327 销毁对话框 //if (dlg.DestroyWindow()) //{ // dlg.SetDefaultId(); //} if (IsWindow(dlg.m_hWnd)) { dlg.DestroyWindow(); } }