Files
envi-code/SourceCode/Code2026/tg_shs/shs_siteplan/PlaceTreeCmd.cpp
T
2026-09-28 15:28:50 +08:00

510 lines
10 KiB
C++

#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();
}
}