#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 &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 &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 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 &vecCircle) { AcDbCircle *pCircle = NULL; AcGePoint3dArray arrPt; std::vector::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 &vecCir) { std::vector::iterator it = vecCir.begin(); for (; it != vecCir.end(); it++) { delete *it; *it = NULL; } } //获取连井管线另一端的所有井 zxl 2011.11.02 modify void GetNearWells(PickSet &ss, std::vector &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 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 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::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); }