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

1160 lines
28 KiB
C++

// 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<TADSGePoint3d> &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<TADSGePoint3d> &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<TADSGePoint3d> 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<nLen; n++)
{
if (!MakeBlockReference(arPts[n])) // 造块
{
return false;
}
}
return true;
}
// 拖动绘制树
bool CPlaceTreeStyle::DragPlaceTree()
{
AcGePoint3d ptInsert, ptNext, ptInsertNew;
int nRet = acedGetPoint(NULL, _T("\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<nLen; n++)
{
ssDel += ss[n];
}
ss -= ssDel;
ssDel.Erase();
}
else if (nRet == RTNORM)
{
// 保存插入图面中的树,回退的时候用
ss.IncludeBegin();
// add by xly on 110328 支持用户坐标系
ptInsert = Ucs2Wcs(ptInsert);
ptNext = Ucs2Wcs(ptNext);
if (!MakeBlockReference(ptInsert)) // 在第一点插入块
{
return false;
}
// 根据拖动长度,计算绘制树的个数
dLength = ptInsert.distanceTo(ptNext);
iTreeNums = int(dLength / dDis);
vet = ptNext - ptInsert;
dUcsAngle = vet.angleTo(vtCur, AcGeVector3d::kZAxis);
for (i = 0; i<iTreeNums; i++)
{
acutPolar(asDblArray(ptInsert), -dUcsAngle, dDis+dDis*i, asDblArray(ptInsertNew));
// add by xly on 110328 支持用户坐标系
//ptInsertNew = Ucs2Wcs(ptInsertNew);
if (!MakeBlockReference(ptInsertNew)) // 造块
{
return false;
}
}
ptInsert = ptNext;
// 保存用户输入点
arPts.append(ptNext);
// 保存用户绘制树的颗数
nAryTreeNums.append(iTreeNums);
ptInsert = Wcs2Ucs(ptInsert);
ss.IncludeEnd();
}
else // 结束
{
return false;
}
}
return true;
}
// 路径匹配
bool CPlaceTreeStyle::PathPlaceTree()
{
//选择路径
PickSet ssLine(SS_FREE);
RBList rbMask(RTDXF0, _T("LINE,ARC,POLYLINE,LWPOLYLINE"), NULL);
int nRet = SelectEntities(_T("\n请选择作为路径的曲线(直线、圆弧、多段线)<退出>:"), ssLine, rbMask);
if (nRet != RTNORM)
{
return false;
}
long ni = 0,
nSsLen = ssLine.Length();
// 打开选择集中的实体
for(ni = 0; ni<nSsLen; ni++)
{
AcDbPolyline polyLine;
OPENOBJ_BEGIN(ssLine[ni], AcDb::kForRead, AcDbEntity, pEnt);
if (pEnt->isKindOf(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<nLen; n++)// 将块插入到图纸中
{
if (!MakeBlockReference(arPts[n])) // 造块
{
return false;
}
}
}
return true;
}
//选择多断线
int CPlaceTreeStyle::SelectPolyLine(TGGePoly2D &poly2d, int &nSelectMode)
{
TEntitySet ent;
TRBList rbFilter(acutBuildList(RTDXF0, _T("CIRCLE,POLYLINE,LWPOLYLINE"), NULL));
TCHAR chRet;
const TCHAR *kword=_T("Q ");
THookMsg hookmsg;
int iRetCode = SelectEntity(_T("\n请选择多线段或[绘制边界线(Q)]:<返回>:"), 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; i<nNum; ++i)
{
AcGePoint3d ptRandomPoint;
/*if (!GetRandomPtByPloy(poly2d, ptRandomPoint, eRandomState))
{
continue;
}*/
int nCycleCount = 10;
while (nCycleCount)
{
if (GetRandomPtByPloy(poly2d, ptRandomPoint, eRandomState))
{
break;
}
--nCycleCount;
}
//eRandomState = eContinu;
if (i == nNum - 2)
{
eRandomState = eToBeEnd;
}
if (!nCycleCount)
{
continue;
}
//ptRandomPoint = Ucs2Wcs(ptRandomPoint);//del tyj 20160926
//判断当前点是否在区域内
if (TRUE == ptInPoly(ptRandomPoint, pline))
{
if (!MakeBlockReference(ptRandomPoint)) // 造块
{
return false;
}
}
}
}
return true;
}
// 直线样式生成树
void CPlaceTreeStyle::LineStyle(AcDbLine *pLine, double dTreeDis, AcGePoint3dArray &ptAryInsert, BOOL bIsSetDis)
{
// 获得直线的起点和终点
AcGePoint3d ptSt,ptEnd;
ptSt = pLine->startPoint();
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<iNumTrees; i++ )
{
if (dBugle>-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; i<iNumVerts; i++)
{
// 获得顶点处的弧度值
pPolyLine->getBulgeAt(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;
}