Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

726 lines
17 KiB
C++

#include "StdAfx.h"
#include "globalFunc.h"
#include "Dbwell.h"
#include "Dbpipe.h"
#include "AecDbText.h"
#include "PickEntSet.h"
/*************************************************躲避更新*************************************************/
// 设置井编号位置
void ModifyWellSerivalPos(Entity &entWell, XPoint &ptDim)
{
AcDbObjectId idWell;
acdbGetObjectId(idWell, entWell);
AcDbEntity *pEnt = NULL;
acdbOpenAcDbEntity(pEnt, idWell, AcDb::kForWrite);
if (pEnt == NULL)
{
return;
}
AecXDbWell *pWell = (AecXDbWell *)pEnt;
if (pWell == NULL)
{
pEnt->close();
return;
}
pWell->SetLabelLocation(ptDim);
pWell->close();
pEnt->close();
}
// 获得井编号距离,插入点, 标注点, 井半径
void GetWellInfo(Entity &ent, double &dTextDist, XPoint &ptLoc, XPoint &ptDim, double &dRadius)
{
AcDbObjectId idWell;
acdbGetObjectId(idWell, ent);
AcDbEntity *pEnt = NULL;
acdbOpenAcDbEntity(pEnt, idWell, AcDb::kForRead);
if (pEnt == NULL)
{
return;
}
AecXDbWell *pWell = (AecXDbWell *)pEnt;
if (pWell == NULL)
{
pEnt->close();
return;
}
dRadius = pWell->GetScale() * pWell->GetPScale() / 2;
ptDim = pWell->GetLabelLocation();
ptLoc = pWell->GetLocation();
dTextDist = ptDim.Distance2d(ptLoc);
pWell->close();
pEnt->close();
}
//根据点阵构造闭合外包框
void MakeClosedPline(AcDbExtents &ext, AcDbPolyline *&pPolyLine, double &dLen)
{
XPoint ptMax, ptMin;
ptMax = ext.maxPoint();
ptMin = ext.minPoint();
ptMax[2] = 0;
ptMin[2] = 0;
XPoint ptMaxLeft(ptMin[0], ptMax[1], 0);
XPoint ptMinRight(ptMax[0], ptMin[1], 0);
dLen = ptMin.Distance2d(ptMax);//zxl 2011.12.08 add
pPolyLine->addVertexAt(0, ptMin);
pPolyLine->addVertexAt(1, ptMinRight);
pPolyLine->addVertexAt(2, ptMax);
pPolyLine->addVertexAt(3, ptMaxLeft);
pPolyLine->setClosed(Adesk::kTrue);
}
// 获得井编号的外包框
void GetWellSerivalExtents(Entity &ent, AcDbPolyline &poly, double &dLen)
{
AcDbObjectId id;
acdbGetObjectId(id, ent);
AcDbEntity *pEnt = NULL;
acdbOpenAcDbEntity(pEnt, id, AcDb::kForRead);
if (pEnt == NULL)
{
return;
}
AcDbVoidPtrArray entArry;
pEnt->explode(entArry);
pEnt->close();
AecXDbText *pText = NULL;
AcDbEntity *pEntOther = NULL;
for (int j = 0; j < entArry.length(); j++)
{
pEntOther = NULL;
pEntOther = (AcDbEntity *)entArry[j];
if (pEntOther == NULL)
{
continue;
}
pText = NULL;
if (pEntOther->isKindOf(AecXDbText::desc()))
{
pText = (AecXDbText *)pEntOther;
break;
}
}
if (pText == NULL)
{
return;
}
AcDbExtents ext;
double dAngle = pText->GetRotation();
pText->SetRotation(GlobalFunc::Wcs2Ucs(0.0));
pText->getGeomExtents(ext);
AcDbPolyline *pPLine = &poly;
MakeClosedPline(ext, pPLine, dLen);
AcGeMatrix3d mat;
mat.setToRotation(dAngle - GlobalFunc::Wcs2Ucs(0.0), AcGeVector3d::kZAxis, pText->GetLocation());
poly.transformBy(mat);
GlobalFunc::ReleaseEntSet(entArry);
}
// 躲避位置(以pt为圆心dRadius为半径做圆,将圆每45度取一点作为躲避点)
void GetEvadePostion(XPoint &pt, double dRadius, std::vector<XPoint> &vecPts, XPoint &ptDim)
{
pt = GlobalFunc::Wcs2Ucs(pt);
ptDim = GlobalFunc::Wcs2Ucs(ptDim);
pt[2] = 0;
ptDim[2] = 0;
AcGeVector3d vec = ptDim - pt;
vec.normalize();
XPoint ptResult;
double dAngle = PI / 4;
for (int i = 0; i < 8; i++)
{
vec.rotateBy(dAngle, AcGeVector3d::kZAxis);
ptResult = pt + vec * dRadius;
ptResult = GlobalFunc::Ucs2Wcs(ptResult);
ptResult[2] = 0;
vecPts.push_back(ptResult);
}
pt = GlobalFunc::Ucs2Wcs(pt);
ptDim = GlobalFunc::Ucs2Wcs(ptDim);
}
// 获得躲避实体的直线和外包框
// 可以通过炸开实体的方式获得直线和文字,文字需获取外包框
void GetLineExtent(const PickSet &ss, PtrList<AcDbPolyline> &lstPline)
{
AcDbEntity *pEnt = NULL;
AcDbObjectId id;
AcDbVoidPtrArray entitySet;
AcDbEntity * pEntSmall = NULL;
AcDbText *pText = NULL;
AecXDbText *pText2 = NULL;
AcDbLine *pLine = NULL;
AcDbPolyline *pPLine = NULL;
AcDbPolyline *pPolyLine = NULL;
for (long i = 0; i < ss.Length(); i++)
{
acdbGetObjectId(id, ss[i]);
acdbOpenAcDbEntity(pEnt, id, AcDb::kForRead);
if (pEnt != NULL)
{
entitySet.setLogicalLength(0);
pEnt->explode(entitySet);
pEnt->close();
for (int j = 0; j < entitySet.length(); ++j)
{
pEntSmall = NULL;
pEntSmall = (AcDbEntity *)entitySet[j];
pText = NULL;
pText = AcDbText::cast(pEntSmall);
pText2 = NULL;
pText2 = AecXDbText::cast(pEntSmall);
pLine = NULL;
pLine = AcDbLine::cast(pEntSmall);
pPLine = NULL;
pPLine = AcDbPolyline::cast(pEntSmall);
pPolyLine = NULL;
pPolyLine = new AcDbPolyline;
if (pLine != NULL) // 直线直接构造pline
{
XPoint ptStart, ptEnd;
pLine->getStartPoint(ptStart);
pLine->getEndPoint(ptEnd);
pPolyLine->addVertexAt(0, ptStart);
pPolyLine->addVertexAt(1, ptEnd);
lstPline.Append(pPolyLine);
}
else if (pText2 != NULL) // 上华单行文字,通过外包框构造pline
{
AcDbExtents ext;
double dTextAngle = pText2->GetRotation();
XPoint ptLoc = pText2->GetLocation();
ptLoc[2] = 0;
pText2->SetRotation(GlobalFunc::Wcs2Ucs(0.0));
XPoint pt1, pt2;
pText2->GetExtents2d(pt1, pt2);
ext.set(pt1, pt2);
double dLen = 0.0;
MakeClosedPline(ext, pPolyLine, dLen);
AcGeMatrix3d mat;
mat.setToRotation(dTextAngle - GlobalFunc::Wcs2Ucs(0.0), AcGeVector3d::kZAxis, ptLoc);
pPolyLine->transformBy(mat);
lstPline.Append(pPolyLine);
}
else if (pText != NULL) // cad单行文字,通过外包框构造pline
{
AcDbExtents ext;
double dLength = 0.0;
pText->getGeomExtents(ext);
MakeClosedPline(ext, pPolyLine, dLength);
lstPline.Append(pPolyLine);
}
else if (pPLine != NULL)// PLine线,通过宽度构造闭合pline
{
AcGePoint3d ptOnPLine1, ptOnPLine2;
pPLine->getPointAt(0, ptOnPLine1);
pPLine->getPointAt(1, ptOnPLine2);
double dStartWidth = 0.0, dEndWidth = 0.0;
pPLine->getWidthsAt(0, dStartWidth, dEndWidth);
AcGeVector3d vec = ptOnPLine2 - ptOnPLine1;
vec.normalize();
vec.rotateBy(PI / 2, AcGeVector3d::kZAxis);
XPoint ptLD, ptRD, ptRU, ptLU;
ptLD = ptOnPLine1 - vec * dStartWidth / 2;
ptRD = ptOnPLine1 + vec * dStartWidth / 2;
ptLU = ptOnPLine2 - vec * dEndWidth / 2;
ptRU = ptOnPLine2 + vec * dEndWidth / 2;
pPolyLine->addVertexAt(0, ptLD);
pPolyLine->addVertexAt(1, ptRD);
pPolyLine->addVertexAt(2, ptRU);
pPolyLine->addVertexAt(3, ptLU);
pPolyLine->setClosed(Adesk::kTrue);
lstPline.Append(pPolyLine);
}
}
GlobalFunc::ReleaseEntSet(entitySet);
}
}
}
//判断两条不相交的闭合polyline线是否包含
bool CheckPolyLines(AcDbPolyline &pline1, AcDbPolyline &pline2)
{
double dArea1 = 0.0;
double dArea2 = 0.0;
pline1.getArea(dArea1);
pline2.getArea(dArea2);
AcDbPolyline *pPLine1 = &pline1;
AcDbPolyline *pPLine2 = &pline2;
if (dArea1 > dArea2)
{
pPLine1 = &pline2;
pPLine2 = &pline1;
}
AcDbLine line;
AcGePoint3d ptOnPLine1, ptOnPLine2;
pPLine1->getPointAt(0, ptOnPLine1);
pPLine1->getPointAt(1, ptOnPLine2);
line.setStartPoint(ptOnPLine1);
line.setEndPoint(ptOnPLine2);
AcGePoint3dArray arrInterPt;
line.intersectWith(pPLine2, AcDb::kExtendThis, arrInterPt);//延长面积小的polyline线的第一根线和第二根polyline线求交点
if (arrInterPt.length() < 2)
{
return false;
}
int j = 0;
double dDist = 0.0;
AcGePoint3d pt;
AcGePoint3d ptOnPline;
for (int i = 0; i < arrInterPt.length(); i++)
{
pt = arrInterPt[i];
pPLine2->getClosestPointTo(pt, ptOnPline);
dDist = pt.distanceTo(ptOnPline);
if (dDist < 0.0001)
{
arrInterPt[j] = pt;
j++;
}
}
AcGeVector3d vec1 = ptOnPLine1 - arrInterPt[0];
AcGeVector3d vec2 = ptOnPLine1 - arrInterPt[1];
vec1.normalize();
vec2.normalize();
if (vec1 == vec2)
{
return false;
}
else
{
return true;
}
}
// 检查外包框与躲避实体是否有交点(与实体求交时,直线直接求交,文字取外包框求交)
bool CheckCurPos(AcDbPolyline &poly, PickSet &ss)
{
if (ss.Length() == 0)
{
return false;
}
// 获得躲避实体的直线或外包框
PtrList<AcDbPolyline> listPolyLine;
GetLineExtent(ss, listPolyLine);
// 通过求交判断是否需要躲避
AcGePoint3dArray arrPt;
AcDbPolyline *pPolyLine = NULL;
for (int i = 0; i < listPolyLine.Length(); i++)
{
arrPt.setLogicalLength(0);
pPolyLine = NULL;
pPolyLine = listPolyLine[i];
poly.intersectWith(pPolyLine, AcDb::kOnBothOperands, arrPt);
if (arrPt.length() > 0)
{
return true;
}
if (pPolyLine->isClosed())
{
if (!CheckPolyLines(poly, *pPolyLine))
{
continue;
}
else
{
return true;
}
}
}
return false;
}
//检查外包框是否与井相交
bool CheckWell(AcDbPolyline &poly, std::vector<AcDbCircle *> &vecCircle)
{
AcDbCircle *pCircle = NULL;
AcGePoint3dArray arrPt;
std::vector<AcDbCircle *>::iterator it = vecCircle.begin();
for (; it != vecCircle.end(); it++)
{
pCircle = NULL;
arrPt.setLogicalLength(0);
pCircle = *it;
poly.intersectWith(pCircle, AcDb::kOnBothOperands, arrPt);
if (arrPt.length() > 0)
{
return true;
}
}
return false;
}
//获取井标注 zxl 2011.11.02 add
void GetWellDim(AcDbObjectId &idWell, PickSet &ss)
{
//获取井标注
AecXDbWell *pWell = NULL;
acdbOpenObject(pWell, idWell, AcDb::kForRead);
const double dDist = 10.0;
if (pWell == NULL)
{
return;
}
AcGePoint3d pt = pWell->GetLocation();
pWell->close();
AcGePoint3d ptGeLB, ptGeLT, ptGeRB, ptGeRT;
AcGeVector3d vtX = AcGeVector3d::kXAxis;
AcGeVector3d vtY = AcGeVector3d::kYAxis;
pt = GlobalFunc::Wcs2Ucs(pt);
ptGeLB = pt - vtX * dDist / 2;
ptGeLB = ptGeLB - vtY * dDist / 2;
ptGeLT = ptGeLB + vtY * dDist;
ptGeRB = ptGeLB + vtX * dDist;
ptGeRT = ptGeRB + vtY * dDist;
PickSet ssWellDim(SS_FREE);
RBList rbFilter(RTDXF0, _T("AEC_ZT_WELLDIM"), NULL);
RBList rbPt = acutBuildList(RTPOINT, &ptGeLB, RTPOINT, &ptGeLT, RTPOINT, &ptGeRT, RTPOINT, &ptGeRB, NULL);
acedSSGet(_T("CP"), rbPt, NULL, rbFilter, ssWellDim);
ss += ssWellDim;
}
// 由井获取躲避实体(与井相关的标注,管线)
void GetEvadeEnts(Entity &entWell, PickSet &ss)
{
AcDbObjectId idWell = NULL;
acdbGetObjectId(idWell, entWell);
AcDbEntity *pEnt = NULL;
acdbOpenAcDbEntity(pEnt, idWell, AcDb::kForRead);
if (pEnt == NULL)
{
return;
}
AecXDbWell *pWell = (AecXDbWell *)pEnt;
if (pWell == NULL)
{
pEnt->close();
return;
}
//获取和井关联的管道
for (int i = 0; i < pWell->GetInterfaceNum(); i++)
{
CPipeInterface face;
pWell->GetInterface(i, face);
AcDbObjectId id = face.m_idPipe;
//获取连井管线另一端的井 zxl 2011.11.02 add
CDbPipe *pPipe = NULL;
double dLength = 0.0;
double dDist = 0.0;
acdbOpenObject(pPipe, id, AcDb::kForRead);
if (pPipe != NULL)
{
AcDbObjectId idNode = pPipe->GetNode(0);
if (idNode == idWell)
{
idNode = pPipe->GetNode(1);
}
ads_name sWeLLName;
acdbGetAdsName(sWeLLName, idNode);
Entity ent = sWeLLName;
dLength = pPipe->GetLength();
dDist = pWell->GetScale() * pWell->GetPScale() * 5;
if (dLength < dDist) //管道长度小于5倍的井直径 zxl 2011.11.03 add
{
ss += ent;
}
pPipe->close();
}
ads_name sName;
acdbGetAdsName(sName, id);
Entity entPipe = sName;
ss += entPipe;
}
pWell->close();
//获取井标注
GetWellDim(idWell, ss);
}
// cet 2011.10.13 add 检查井是否显示井编号
bool IsShowWellSerial(Entity &ent)
{
AcDbObjectId idWell;
acdbGetObjectId(idWell, ent);
bool bShowDim = false;
AecXDbWell *pWell = NULL;
acdbOpenObject(pWell, idWell, AcDb::kForRead);
if (pWell != NULL)
{
if (pWell->IsDrawLabel())
{
bShowDim = true;
}
pWell->close();
}
return bShowDim;
}
void FreeVec(std::vector<AcDbCircle *> &vecCir)
{
std::vector<AcDbCircle *>::iterator it = vecCir.begin();
for (; it != vecCir.end(); it++)
{
delete *it;
*it = NULL;
}
}
//获取连井管线另一端的所有井 zxl 2011.11.02 modify
void GetNearWells(PickSet &ss, std::vector<AcDbCircle *> &vecCirle)
{
AcDbObjectId id = NULL;
AcDbEntity *pEnt = NULL;
AecXDbWell *pWell = NULL;
AcDbCircle *pCirOther = NULL;
AcGePoint3d ptCenter;
for (long i = 0; i < ss.Length(); i++)
{
id = NULL;
acdbGetObjectId(id, ss[i]);
pEnt = NULL;
acdbOpenAcDbEntity(pEnt, id, AcDb::kForRead);
if (pEnt != NULL)
{
pWell = NULL;
pWell = AecXDbWell::cast(pEnt);
if (pWell != NULL)
{
GetWellDim(id, ss);
pCirOther = NULL;
pCirOther = new AcDbCircle;
pCirOther->setRadius(pWell->GetScale() * pWell->GetPScale() / 2);
ptCenter = pWell->GetLocation();
ptCenter[2] = 0;
pCirOther->setCenter(ptCenter);
vecCirle.push_back(pCirOther);
pWell->close();
}
pEnt->close();
}
}
}
//井编号和井自身有交点时,调整井编号位置 zxl 2011.12.08 add
bool GetNewWellDimPos(AcDbCircle *&pCir, XPoint &ptDim, AcDbPolyline &poly, double &dWellTextDist, double &dLen, XPoint &ptNewDim)
{
XPoint ptCenter = pCir->center();
double dWellRadius = pCir->radius();
ptDim[2] = 0;
if (ptDim.Distance2d(ptCenter) - 0.0 < 0.001)//井编号插入点和井本身插入点重合
{
return false;
}
ptDim = GlobalFunc::Wcs2Ucs(ptDim);
ptCenter = GlobalFunc::Wcs2Ucs(ptCenter);
AcGeVector3d vt = ptDim - ptCenter;
vt.normalize();
dWellTextDist = dLen / 2 + dWellRadius;
ptNewDim = ptCenter + vt * dWellTextDist;
ptNewDim = GlobalFunc::Ucs2Wcs(ptNewDim);
ptDim = GlobalFunc::Ucs2Wcs(ptDim);
ptCenter = GlobalFunc::Ucs2Wcs(ptCenter);
AcGeMatrix3d matNew;
matNew.setToTranslation(ptNewDim - ptDim);
ptDim = ptNewDim;
poly.transformBy(matNew);
AcGePoint3d ptClosest;
poly.getClosestPointTo(ptCenter, ptClosest);
if (ptCenter.Distance2d(ptClosest) - dWellRadius * 1.2 > 0.0)
{
double dDistLen = ptNewDim.Distance2d(ptClosest);
ptNewDim = ptCenter + vt * (dWellRadius * 1.2 + dDistLen);
dWellTextDist = dWellRadius * 1.2 + dDistLen;
matNew.setToTranslation(ptNewDim - ptDim);
ptDim = ptNewDim;
poly.transformBy(matNew);
}
return true;
}
// 对实体进行躲避,返回值判断躲避情况(失败:-1,躲避成功且位置改变:1 ,躲避成功且位置未动:0)
int EvadeUpdating(Entity &ent)
{
// 检查井是否有标注
if (!IsShowWellSerial(ent))
{
return -1;
}
// 获得井上躲避实体
PickSet ss(SS_FREE); // 保存躲避实体
GetEvadeEnts(ent, ss);
// 获得井信息
XPoint ptWell, ptDim; // 井插入点, 井编号位置点
double dWellTextDist = 0.0; // 井编号距井距离
double dWellRadius = 0.0; //井半径
GetWellInfo(ent, dWellTextDist, ptWell, ptDim, dWellRadius);
// 获取井编号的外包框
AcDbPolyline poly; // 井编号外包框构成的闭合pline
double dLen = 0.0;
GetWellSerivalExtents(ent, poly, dLen);
std::vector<AcDbCircle *> vecCirle;
AcDbCircle *pCir = new AcDbCircle;
pCir->setRadius(dWellRadius);
XPoint ptCenter = ptWell;
ptCenter[2] = 0;
pCir->setCenter(ptCenter);
vecCirle.push_back(pCir);
//井编号是否压井
bool bIsModified = false;
//井编号和井自身有交点时,调整井编号位置 zxl 2011.12.08 add
double dDist = ptCenter.Distance2d(ptDim);
XPoint ptNewDim;
if (dDist - dWellRadius < 0.0 || CheckWell(poly, vecCirle))
{
if (!GetNewWellDimPos(pCir, ptDim, poly, dWellTextDist, dLen, ptNewDim))
{
FreeVec(vecCirle);
return 0;
}
ModifyWellSerivalPos(ent, ptDim);
bIsModified = true;
}
//获取连井管线另一端的所有井 zxl 2011.11.02 add
GetNearWells(ss, vecCirle);
// 检查井编号当前位置是否需要躲避
if (!CheckCurPos(poly, ss))
{
if (!CheckWell(poly, vecCirle))
{
FreeVec(vecCirle);
if (bIsModified)
{
return 1;
}
return 0;
}
}
// 获得躲避位置
std::vector<XPoint> vecPt; // 躲避点
GetEvadePostion(ptWell, dWellTextDist, vecPt, ptDim);
if (bIsModified)//编号压井时增加1.2倍的判定距离
{
GetEvadePostion(ptWell, dWellTextDist * 1.2, vecPt, ptDim);
}
GetEvadePostion(ptWell, dWellTextDist * 1.5, vecPt, ptDim);
GetEvadePostion(ptWell, dWellTextDist * 2.0, vecPt, ptDim);
// 检查在躲避位置是否满足躲避要求
std::vector<XPoint>::iterator it;
AcGeMatrix3d mat;
for (it = vecPt.begin(); it != vecPt.end(); it++)
{
ptDim[2] = 0;
mat.setToTranslation(*it - ptDim);
ptDim = *it;
poly.transformBy(mat);
// 检查当前位置是否满足躲避要求
if (!CheckCurPos(poly, ss))
{
if (!CheckWell(poly, vecCirle))
{
// 修改井编号位置
ModifyWellSerivalPos(ent, ptDim);
FreeVec(vecCirle);
return 1;
}
}
}
FreeVec(vecCirle);
return -1;
}
// 对实体进行躲避操作,返回修改实体个数
int EvadeUpdating(PickSet &ss)
{
if (ss.Length() == 0)
{
return 0;
}
int nNum = 0;
acedSetStatusBarProgressMeter(_T("计算中..."), 0, ss.Length());
Entity ent;
for (long i = 0; i < ss.Length(); i++)
{
ent = ss[i];
acedSetStatusBarProgressMeterPos(i + 1);
if (EvadeUpdating(ent) == 1)
{
++nNum;
}
}
acedRestoreStatusBar();
return nNum;
}
// 主函数
void EvadeUpdating()
{
// 选择井
RBList rbMask(RTDXF0, _T("AEC_ZT_WELL"), NULL);
PickSet ss(SS_FREE);
if (GlobalFunc::SelectEntities(_T("\n请选择要修改的井:<退出>"), ss, rbMask) != RTNORM)
{
return;
}
int nNum = EvadeUpdating(ss);
CString sNote = _T("");
sNote.Format(_T("共修改%d个井编号."), nNum);
acutPrintf(sNote);
}