510 lines
10 KiB
C++
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();
|
|
}
|
|
}
|
|
|