Files
envi-code/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp
T
2026-09-28 15:28:50 +08:00

2773 lines
68 KiB
C++

#include "stdafx.h"
#include "AcGiViewDraw.h"
#include "AecDbCamera.h"
#include "dbgrip.h"
#include "MFCDbDwgFiler.h"
#include "CoreTools.h"
#include "HlrCutOption.h"
#include "aecdbewpipebase.h"
#include "compare_double.h"
#include "simpleproperty.h"
#include "hlrcommands.h"
IMP_XDATA_KEY(AecDbXCamera, _ptEye_);
IMP_XDATA_KEY(AecDbXCamera, _vtEye_);
IMP_XDATA_KEY(AecDbXCamera, _width_);
IMP_XDATA_KEY(AecDbXCamera, _height_);
IMP_XDATA_KEY(AecDbXCamera, _ptOutput_);
IMP_XDATA_KEY(AecDbXCamera, _horiztop_);
IMP_XDATA_KEY(AecDbXCamera, _horizbottom_);
IMP_XDATA_KEY(AecDbXCamera, _usagemode_);
typedef AecDbXCamera::AcDbEntityArray AcDbEntityArray;
typedef AecDbXCamera::IDMapEntities IDMapEntities;
typedef AecDbXCamera::EntMapEntities EntMapEntities;
namespace
{
// 从母实体上拷贝属性
void copyProperty(AcDbEntity *pSrc, AcDbEntity *pDes)
{
pDes->setLayer(pSrc->layerId());
pDes->setLinetype(pSrc->linetypeId());
pDes->setColorIndex(pSrc->colorIndex());
AecDbObjXDataMap xdata;
if (xdata.Read(pSrc, BIMDATA_APP))
xdata.Write(pDes, BIMDATA_APP);
AcDbPolyline *pPlSrc(AcDbPolyline::cast(pSrc)), *pPlDes(AcDbPolyline::cast(pDes));
if (pPlSrc && pPlDes)
{
double dW;
if (pPlSrc->getConstantWidth(dW) == Acad::eOk)
pPlDes->setConstantWidth(dW);
}
}
// 辅助函数:使用射线法判断一个点是否在闭合曲线上
bool IsPointInsideBoundary(AcDbCurve *pBoundary, const AcGePoint3d &testPt)
{
if (pBoundary == NULL)
{
return false;
}
// 1. 优先判定:点是否在边界曲线上
AcGePoint3d closestPt;
if (pBoundary->getClosestPointTo(testPt, closestPt) == Acad::eOk)
{
// 如果测试点到边界最近点的距离小于容差,认为点在边界上
if (testPt.distanceTo(closestPt) < 1e-6)
{
return true; // 视为在内部,予以保留
}
}
// 2. 获取边界的外包围盒,用于快速排除并构建射线长度
AcDbExtents extents;
if (pBoundary->getGeomExtents(extents) != Acad::eOk)
{
return false;
}
// 粗略判断:如果点在外包围盒之外,肯定在外部
if (testPt.x < extents.minPoint().x || testPt.x > extents.maxPoint().x ||
testPt.y < extents.minPoint().y || testPt.y > extents.maxPoint().y)
{
return false;
}
// 3. 构造一条射线,从测试点射向包围盒外的一个极远点
// 使用非标准角度的向量,尽量避免穿过顶点或与边重合
AcGeVector3d rayDir(1.0, 0.314159, 0.0);
double dist = extents.maxPoint().distanceTo(extents.minPoint()) * 2.0;
AcGePoint3d farPt = testPt + rayDir * dist;
AcDbLine rayLine(testPt, farPt);
AcGePoint3dArray intPts;
// 4. 求交
if (pBoundary->intersectWith(&rayLine, AcDb::kOnBothOperands, intPts) != Acad::eOk)
{
return false;
}
// 5. 过滤重复交点 (容差处理,防止同一个交点被重复计算)
int validIntersectionCount = 0;
for (int i = 0; i < intPts.length(); ++i)
{
bool isDuplicate = false;
for (int j = 0; j < i; ++j)
{
if (intPts[i].distanceTo(intPts[j]) < 1e-6)
{
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
validIntersectionCount++;
}
}
// 6. 射线法核心:交点个数为奇数则在内部,偶数则在外部
return (validIntersectionCount % 2) != 0;
}
// 辅助函数 2:曲线内外判定
bool IsCurveInsideBoundary(AcDbCurve *pBoundary, AcDbCurve *pCurve)
{
if (!pBoundary || !pCurve) return false;
double startParam(.0), endParam(.0);
AcGePoint3d midPt;
if (pCurve->getStartParam(startParam) == Acad::eOk &&
pCurve->getEndParam(endParam) == Acad::eOk &&
pCurve->getPointAtParam((startParam + endParam) * 0.5, midPt) == Acad::eOk)
{
return IsPointInsideBoundary(pBoundary, midPt);
}
return false;
}
// 辅助函数 3:按需克隆
void CloneIfInside(AcDbCurve *pBoundary, AcDbCurve *pTarget, AcDbEntityArray &output)
{
if (IsCurveInsideBoundary(pBoundary, pTarget))
{
AcDbEntity *pClone = static_cast<AcDbEntity *>(pTarget->clone());
if (pClone)
{
copyProperty(pTarget, pClone);
output.append(pClone);
}
}
}
// 主控裁剪函数
void ClipCurvesByBoundary(AcDbCurve *pBoundary, const AcDbEntityArray &ptrs, AcDbEntityArray &output)
{
if (!pBoundary) return;
if (ptrs.isEmpty()) return;
double param(.0);
AcGePoint3d projPt(AcGePoint3d::kOrigin);
AcGePoint3dArray intPts;
AcGeDoubleArray splitParams;
std::vector<double> vecParams;
AcDbVoidPtrArray curveFragments;
for (int i = 0; i < ptrs.length(); ++i)
{
AcDbCurve *pTargetCurve = AcDbCurve::cast(ptrs[i]);
if (!pTargetCurve) continue;
intPts.removeAll();
// 1. 获取交点
if (pTargetCurve->intersectWith(pBoundary, AcDb::kOnBothOperands, intPts) != Acad::eOk) continue;
// 2. 无交点处理
if (intPts.length() < 1)
{
CloneIfInside(pBoundary, pTargetCurve, output);
continue;
}
splitParams.removeAll();
vecParams.clear();
// 3. 交点转参数
for (int j = 0; j < intPts.length(); ++j)
{
if (pTargetCurve->getClosestPointTo(intPts[j], projPt) != Acad::eOk) continue;
if (pTargetCurve->getParamAtPoint(projPt, param) != Acad::eOk) continue;
vecParams.push_back(param);
}
// 4. 参数排序去重与容错
if (vecParams.empty())
{
CloneIfInside(pBoundary, pTargetCurve, output);
continue;
}
std::sort(vecParams.begin(), vecParams.end());
vecParams.erase(std::unique(vecParams.begin(), vecParams.end()), vecParams.end());
for (size_t k = 0; k < vecParams.size(); ++k)
{
splitParams.append(vecParams[k]);
}
// 5. 打断曲线与容错
curveFragments.removeAll();
if (pTargetCurve->getSplitCurves(splitParams, curveFragments) != Acad::eOk)
{
CloneIfInside(pBoundary, pTargetCurve, output);
continue;
}
// 6. 遍历碎片(经过重构,这里现在犹如散文般清晰)
for (int f = 0; f < curveFragments.length(); ++f)
{
AcDbCurve *pFragment = AcDbCurve::cast((AcDbEntity *)curveFragments[f]);
if (!pFragment) continue;
// 直接复用逻辑判定
if (IsCurveInsideBoundary(pBoundary, pFragment))
{
// 内部保留,转移控制权
copyProperty(pTargetCurve, pFragment);
output.append(pFragment);
}
else
{
// 外部剔除,或底层参数异常,统一就地销毁
delete pFragment;
}
}
}
}
void clipResultBySection(IDMapEntities &result, EntMapEntities &result2, AcDbCurve *pSection)
{
if (!pSection) return;
AcDbEntityArray output;
IDMapEntities::iterator it(result.begin());
for (; it != result.end(); ++it)
{
// output的内容会转移到it->second内,
// 会在外部清理,这里removeall即可
output.removeAll();
// 取出每个id关联的结果,和pSection进行clip运算
ClipCurvesByBoundary(pSection, it->second, output);
// 清理 it->second 的内容,置换为 output
deleteContainerOfArx<AcDbEntity>(it->second);
if (!output.isEmpty())
it->second.append(output);
}
EntMapEntities::iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
{
output.removeAll();
ClipCurvesByBoundary(pSection, it2->second, output);
deleteContainerOfArx<AcDbEntity>(it2->second);
if (!output.isEmpty())
it2->second.append(output);
}
}
// 删除一个实体,如果是块引用,则尽量删除其块
void eraseEnt(AcDbObjectId &id, Adesk::Boolean erasing = Adesk::kTrue)
{
AcDbObjectPointer<AcDbBlockReference> entRef(id, AcDb::kForWrite);
if (entRef.openStatus() == Acad::eOk)
{
AcDbObjectId idBlk = entRef->blockTableRecord();
if (entRef->erase(erasing) == Acad::eOk)
{
AcDbBlockTableRecordPointer entTblRec(idBlk, AcDb::kForWrite);
if (entTblRec.openStatus() == Acad::eOk)
{
AcDbObjectIdArray ar;
entTblRec->getBlockReferenceIds(ar);
if (ar.isEmpty())
entTblRec->erase(erasing);
}
}
}
else
{
AcDbEntityPointer ent(id, AcDb::kForWrite);
if (ent.openStatus() == Acad::eOk)
ent->erase(erasing);
}
}
AcGeVector3d getViewDir()
{
AcGePoint3dArray pts;
struct resbuf rb;
acedGetVar(_T("viewdir"), &rb);
ads_point dirPt;
acdbUcs2Wcs(rb.resval.rpoint, dirPt, Adesk::kTrue);
return asVec3d(dirPt);
}
bool Grip_WorldDrawfunc(AcDbGripData *pThis,
AcGiWorldDraw *pWd,
const AcDbObjectId &entId,
AcDbGripOperations::DrawType type,
AcGePoint3d *cursor,
double dGripSize)
{
AcGiFillType eOldFill = pWd->subEntityTraits().fillType();
int nOldColor = pWd->subEntityTraits().color();
AecDbXCamera::GripData *pGrip = (AecDbXCamera::GripData *)pThis->appData();
AcGePoint3d ptGe[5], ptBox[5];
AcGePoint3d ptGrip = pThis->gripPoint();
double dOne = CoreTools::PixelToWcs(1);
ptGe[0] = ptGrip;
ptGe[0].x -= 4 * dOne;
ptGe[1] = ptGrip;
ptGe[1].x += 4 * dOne;
ptBox[0] = ptGe[0];
ptBox[0].y -= 4 * dOne;
ptBox[1] = ptGe[0];
ptBox[1].y += 4 * dOne;
ptBox[2] = ptGe[1];
ptBox[2].y += 4 * dOne;
ptBox[3] = ptGe[1];
ptBox[3].y -= 4 * dOne;
AcGeVector3d vtNow(getViewDir());
if (!vtNow.isCodirectionalTo(AcGeVector3d::kZAxis))
{
AcGePlane pln(ptGrip, vtNow);
AcGeVector3d X, Y;
pln.getCoordSystem(ptGrip, X, Y);
AcGeMatrix3d mat;
mat.setToAlignCoordSys(ptGrip, AcGeVector3d::kXAxis, AcGeVector3d::kYAxis, AcGeVector3d::kZAxis
, ptGrip, X, Y, vtNow);
ptBox[0].transformBy(mat);
ptBox[1].transformBy(mat);
ptBox[2].transformBy(mat);
ptBox[3].transformBy(mat);
}
pWd->subEntityTraits().setFillType(kAcGiFillAlways);
pWd->geometry().polygon(4, ptBox);
pWd->subEntityTraits().setFillType(eOldFill);
// 有frame数据就画线
if (pGrip->m_mode == AecDbXCamera::eVerti && pGrip->m_arSelectFrame.length() > 3)
{
AcGePoint3d arFrame1[] = { pGrip->m_arSelectFrame[1]
, pGrip->m_arSelectFrame[2]
, pGrip->m_arSelectFrame[3]
, pGrip->m_arSelectFrame[0] };
pWd->subEntityTraits().setColor(9);
pWd->geometry().polyline(4, arFrame1);
if (pGrip->m_arSelectFrame.length() > 7)
{
// 画下层线
AcGePoint3d arFrame2[] = { pGrip->m_arSelectFrame[4]
, pGrip->m_arSelectFrame[5]
, pGrip->m_arSelectFrame[6]
, pGrip->m_arSelectFrame[7]
, pGrip->m_arSelectFrame[4] };
pWd->geometry().polyline(5, arFrame2);
AcGePoint3d arFrame3[2] = { pGrip->m_arSelectFrame[0], pGrip->m_arSelectFrame[4] };
pWd->geometry().polyline(2, arFrame3);
arFrame3[0] = pGrip->m_arSelectFrame[1];
arFrame3[1] = pGrip->m_arSelectFrame[5];
pWd->geometry().polyline(2, arFrame3);
arFrame3[0] = pGrip->m_arSelectFrame[2];
arFrame3[1] = pGrip->m_arSelectFrame[6];
pWd->geometry().polyline(2, arFrame3);
arFrame3[0] = pGrip->m_arSelectFrame[3];
arFrame3[1] = pGrip->m_arSelectFrame[7];
pWd->geometry().polyline(2, arFrame3);
}
pWd->subEntityTraits().setColor(nOldColor);
}
else if (pGrip->m_mode == AecDbXCamera::eHoriz && pGrip->m_arSelectFrame.length() > 7)
{
pWd->subEntityTraits().setColor(9);
AcGePoint3d ar[] = { pGrip->m_arSelectFrame[5]
, pGrip->m_arSelectFrame[6]
, pGrip->m_arSelectFrame[7]
, pGrip->m_arSelectFrame[4]
, pGrip->m_arSelectFrame[5] };
pWd->geometry().polyline(5, ar);
AcGePoint3d arFrame[2] = { pGrip->m_arSelectFrame[1], pGrip->m_arSelectFrame[5] };
pWd->geometry().polyline(2, arFrame);
arFrame[0] = pGrip->m_arSelectFrame[0];
arFrame[1] = pGrip->m_arSelectFrame[4];
pWd->geometry().polyline(2, arFrame);
arFrame[0] = pGrip->m_arSelectFrame[2];
arFrame[1] = pGrip->m_arSelectFrame[6];
pWd->geometry().polyline(2, arFrame);
arFrame[0] = pGrip->m_arSelectFrame[3];
arFrame[1] = pGrip->m_arSelectFrame[7];
pWd->geometry().polyline(2, arFrame);
pWd->subEntityTraits().setColor(nOldColor);
}
if (pGrip->m_bDrawResultFrame)
{
AcGePoint3d arFrame[] = { pGrip->m_arResultFrame[1]
, pGrip->m_arResultFrame[2]
, pGrip->m_arResultFrame[3]
, pGrip->m_arResultFrame[0]
, pGrip->m_arResultFrame[1] };
pWd->subEntityTraits().setColor(6);
pWd->geometry().polyline(5, arFrame);
pWd->subEntityTraits().setColor(nOldColor);
}
return true;
}
AcDbViewport *makeViewPort(const AcGePoint3d &ptVp // 视口起始点
, const AcGeVector3d &vtVp) // 视口方向和长度
{
AcDbViewport *pVp = new AcDbViewport;
pVp->setViewTarget(ptVp - vtVp);
pVp->setViewDirection(vtVp);
pVp->setFrontClipDistance(vtVp.length());
pVp->setBackClipDistance(0);
pVp->setFrontClipOn();
pVp->setBackClipOn();
return pVp;
}
//HINSTANCE _getHLRInstance()
//{
// DWORD dRes = 0;
// CString sSHHLrDll, sDbx;
// if (!CoreTools::FindSHHLrDll(sSHHLrDll, sDbx))
// {
// acutPrintf(_T("\n没有找到 SHHLr.dll 或 AsdkHlrApi.lib 文件!"));
// return NULL;
// }
// HINSTANCE hDllInst(NULL);
// if (hDllInst == NULL)
// {
// DWORD dw = ::GetCurrentDirectory(0, NULL);
// CString wkd;
// ::GetCurrentDirectory(dw + 1, wkd.GetBuffer(dw + 1));
// wkd.ReleaseBuffer();
// ::SetCurrentDirectory(sDbx);
// hDllInst = ::GetModuleHandle(sSHHLrDll);
// if (!hDllInst)
// hDllInst = ::LoadLibrary(sSHHLrDll);
// dRes = GetLastError();
// ::SetCurrentDirectory(wkd);
// }
// return hDllInst;
//}
//typedef void(_cdecl *hlr_collect_all)(AcDbObjectIdArray & // 原始实体
// , AcDbEntityArray & // 原始实体的指针,如果实体没有ID的情况下,用此参数传入
// , const int & // 控制参数
// , AcDbViewport * // 视口
// , IDMapEntities & // 结果,first-原实体 second-生成的消隐实体
// , EntMapEntities &); // 结果,first-原实体 second-生成的消隐实体
//typedef void(_cdecl *hlr_collect_simple)(AcDbObjectIdArray &
// , const int &
// , AcDbViewport *
// , IDMapEntities &);
void HlrCalc_simple(AcDbObjectIdArray &arIds
, AcDbViewport *pVp
, const int &control
, IDMapEntities &result)
{
HLR::hlr_collect(arIds, control, pVp, result);
// HINSTANCE hDllInst(getHLRInstance());
// if (!hDllInst)
// {
// acutPrintf(_T("\n加载 HLR 失败"));
// return;
// }
// hlr_collect_simple ptrFunc = (hlr_collect_simple)GetProcAddress(hDllInst, "hlr_collect");
// if (ptrFunc != NULL)
// ptrFunc(arIds, control, pVp, result);
//#ifndef ZWCAD
// if (::FreeLibrary(hDllInst))
// hDllInst = NULL;
//#endif
}
void HlrCalc(AcDbObjectIdArray &arIds
, AcDbEntityArray & arPtrs
, AcDbViewport *pVp
, const int &control
, IDMapEntities &result
, EntMapEntities& result2)
{
HLR::hlr_collect_all(arIds, arPtrs, control, pVp, result, result2);
// HINSTANCE hDllInst(getHLRInstance());
// if (!hDllInst)
// {
// acutPrintf(_T("\n加载 HLR 失败"));
// return;
// }
// hlr_collect_all ptrFunc = (hlr_collect_all)GetProcAddress(hDllInst, "hlr_collect_all");
// if (ptrFunc != NULL)
// ptrFunc(arIds, arPtrs, control, pVp, result, result2);
//#ifndef ZWCAD
// if (::FreeLibrary(hDllInst))
// hDllInst = NULL;
//#endif
}
bool zeroLength(AcDbCurve *pCrv, const double &tol)
{
double dPEnd(.0), dDist(.0);
pCrv->getEndParam(dPEnd);
pCrv->getDistAtParam(dPEnd, dDist);
return COMPARE_DOUBLE::equal_zero(dDist, tol);
}
void rollback(const AcDbObjectIdArray &arids)
{
AcDbEntityArray ar, output;
EntMapEntities eme;
for (int i(0); i < arids.length(); ++i)
{
AcDbEntityPointer ent(arids[i], AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) continue;
AecDbEntityBase *pEnt(AecDbEntityBase::cast(ent));
AecDbCurveBase *pCrv(AecDbCurveBase::cast(ent));
if (pEnt)
pEnt->ProcessHlrResult(ar, eme, output);
if (pCrv)
pCrv->ProcessHlrResult(ar, eme, output);
}
}
bool isEnvelope(AcDbObjectId id)
{
AcDbEntityPointer ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return false;
CString sDXF(ent->isA()->dxfName());
if (HlrCutOption::isEnvelopeEntity(sDXF))
{
// 板需要判断一下,如果有填充,不属于构筑物
if (sDXF == _T("AEC_DBSLAB"))
{
AecDbEwPipeBase *p(AecDbEwPipeBase::cast(ent));
PipeHatch ph;
if (p)
return !p->GetHatch(ph);
else
return false;
}
return true;
}
else
return false;
return false;
}
bool isValidSolid(AcDb3dSolid *pSolid)
{
AcDbExtents ext;
if (pSolid->isNull()) return false;
if (pSolid->getGeomExtents(ext) == Acad::eOk)
{
double dL = ext.maxPoint().distanceTo(ext.minPoint());
if (COMPARE_DOUBLE::equal_zero(dL)) return false;
}
else
return false;
double volume;
AcGePoint3d centroid;
double momInertia[3], prodInertia[3], prinMoments[3], radiiGyration[3];
AcGeVector3d prinAxes[3];
if (pSolid->getMassProp(volume
, centroid
, momInertia
, prodInertia
, prinMoments
, prinAxes
, radiiGyration
, ext) == Acad::eOk)
{
double dL = ext.maxPoint().distanceTo(ext.minPoint());
if (COMPARE_DOUBLE::equal_zero(dL)) return false;
if (COMPARE_DOUBLE::equal_zero(volume)) return false;
}
else
return false;
return true;
}
AcDbEntity* mergeEnvelope(AcDbObjectIdArray &arids)
{
std::map<void *, AcDbHandle> debugMM;
AcDbVoidPtrArray arptrs;
AcDbVoidPtrArray _ar;
AecDbObjXDataMap *pXDataMap(NULL);
for (int i(0); i < arids.length(); ++i)
{
AcDbEntityPointer ent(arids[i], AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) continue;
_ar.removeAll();
AecDbEntityBase *pEnt(AecDbEntityBase::cast(ent));
AecDbCurveBase *pCrv(AecDbCurveBase::cast(ent));
if (pEnt)
{
pEnt->GetDraw3dables(_ar, true);
for (int i(0); i < _ar.length(); ++i)
debugMM.insert(std::make_pair(_ar[i], ent->id().handle()));
arptrs.append(_ar);
pXDataMap = pEnt->GetSpecialtyData(AcDb::kForRead);
}
if (pCrv)
{
pCrv->GetDraw3dables(_ar, true);
for (int i(0); i < _ar.length(); ++i)
debugMM.insert(std::make_pair(_ar[i], ent->id().handle()));
arptrs.append(_ar);
pXDataMap = pCrv->GetSpecialtyData(AcDb::kForRead);
}
}
if (arptrs.isEmpty()) return NULL;
// 找到第一个 3dsolid
AcDb3dSolid *pSolidAll(NULL);
for (int i(0); i < arptrs.length(); ++i)
{
AcDbEntity *pEnt((AcDbEntity *)arptrs[i]);
if (!pEnt) continue;
pSolidAll = AcDb3dSolid::cast(pEnt);
if (!pSolidAll) continue;
if (pSolidAll->isNull())
{
#ifndef NDEBUG
acutPrintf(_T("\nThe 3DSOLID does not have a ShapeManager object. "));
#endif
continue;
}
arptrs.removeAt(i);
break;
}
if (!pSolidAll) return NULL;
if (arptrs.isEmpty()) return pSolidAll;
std::map<void *, AcDbHandle>::const_iterator debugIt(debugMM.end());
TCHAR szHand[19];
for (int i(0); i < arptrs.length(); ++i)
{
AcDbEntity *pEnt((AcDbEntity *)arptrs[i]);
if (!pEnt) continue;
AcDb3dSolid *pSolid(AcDb3dSolid::cast(pEnt));
if (!pSolid) continue;
if (pSolid->isNull())
{
#ifndef NDEBUG
acutPrintf(_T("\nThe 3DSOLID does not have a ShapeManager object. "));
#endif
continue;
}
if (!isValidSolid(pSolid)) continue;
if (pSolidAll->booleanOper(AcDb::kBoolUnite, pSolid) != Acad::eOk)
{
debugIt = debugMM.find((void*)pSolid);
if (debugIt == debugMM.end())
acutPrintf(_T("\n 融合出现错误,构筑物将按照不融和处理。%d"), i);
else
{
memset(szHand,0,sizeof(szHand) );
debugIt->second.getIntoAsciiBuffer(szHand);
acutPrintf(_T("\n 融合出现错误,构筑物将按照不融和处理。%s"), szHand);
}
deleteArrayVoidPtrs<AcDbEntity>(arptrs);
DELETE_PTR(pSolidAll);
return NULL;
}
}
deleteArrayVoidPtrs<AcDbEntity>(arptrs);
return pSolidAll;
}
// 处理一下构筑物的结果
// 1. 重复线
// 2. 争取处理一下融合构筑物,在二维条件下
void fixEnvelopeResult(AcDbEntityArray &arEnve)
{
}
// 给出中心点及长宽,得到一个矩形,左下角点开始,逆时针方向
AcDbRegion* getRect(const AcGePoint3d &ptCenter
, const double &W
, const double &H
, const AcGeVector3d &vtX = AcGeVector3d::kXAxis
, const AcGeVector3d &vtZ = AcGeVector3d::kZAxis)
{
AcGeVector3d Y(vtX), X(vtX);
Y.rotateBy(PI * .5, vtZ);
Y.normalize();
X.normalize();
AcGePoint3d pt0 = ptCenter - X * (W * .5);
pt0 -= Y * (H * .5);
AcGePoint3d pt1 = pt0 + X * W;
AcGePoint3d pt2 = pt1 + Y * H;
AcGePoint3d pt3 = pt2 - X * W;
AcDbVoidPtrArray ar;
ar.append(new AcDbLine(pt0, pt1));
ar.append(new AcDbLine(pt1, pt2));
ar.append(new AcDbLine(pt2, pt3));
ar.append(new AcDbLine(pt3, pt0));
AcDbRegion *pReg(CoreTools::createRegion(ar));
deleteArrayVoidPtrs<AcDbLine>(ar);
return pReg;
}
void processEnvelope(AcDbEntityArray &arEnve)
{
if (HlrCutOption::getHlrMERGE_Envelope())
{ // 构筑物融合后的数据
// 处理一下重复线,设置一下属性
fixEnvelopeResult(arEnve);
double dW(.0);
if (HlrCutOption::getHlrLW_Envelope(dW))
{
for (int i(0); i < arEnve.length(); ++i)
{
AcDbCurve *pCrv((AcDbCurve*)arEnve[i]);
AcDbPolyline *pL(CoreTools::MakePolyline(pCrv));
if (pL)
{
pL->setConstantWidth(dW);
DELETE_PTR(pCrv);
arEnve[i] = pL;
}
}
}
int nClr(256);
AcDbObjectId idLayer(AcDbObjectId::kNull), idLinetype(AcDbObjectId::kNull);
BOOL bLayer = HlrCutOption::getHlrLY_Envelope(idLayer);
BOOL bLinetype = HlrCutOption::getHlrLT_Envelope(idLinetype);
BOOL bClr = HlrCutOption::getHlrCL_Envelope(nClr);
for (int i(0); i < arEnve.length(); ++i)
{
AcDbEntity *pEnt(arEnve[i]);
if (bLayer && idLayer.isValid())
pEnt->setLayer(idLayer);
if (bLinetype && idLinetype.isValid())
pEnt->setLinetype(idLinetype);
if (bClr)
pEnt->setColorIndex(nClr);
}
}
else
{ // 构筑物未融合,每个实体都带有信息,不需要额外操作
// 处理一下重复线
fixEnvelopeResult(arEnve);
}
}
void preprocess(AcDbObjectIdArray &arids // 这个集合会被挑选修改
, const AcGePoint3d &ptPlnO
, const AcGeVector3d &vtPlnN
, IDMapEntities &preID2Ent // 由 “数据库实体” 产生的补充实体
, AcDbEntityArray &preEnt // 由 “非数据库实体” 产生的补充实体(没有ID与之对应)
, AcDbEntityArray &arAll )
{
AcDbObjectIdArray arOther;
// 目前只有构筑物融合需要
if (HlrCutOption::getHlrMERGE_Envelope())
{
AcDbObjectIdArray arEnev;
AecDbXCamera::collectEnvelope(arids, arOther, arEnev);
AcDbEntity *pEnvelope = mergeEnvelope(arEnev);
if (pEnvelope)
{
arids = arOther;
{// 暂时标记一下
AecDbObjXDataMap xData;
xData.SetAt(_T("TYPE"), _T("ENVELOPE"));
xData.Write(pEnvelope, _T("_ENVELOPE_"));
}
arAll.append(pEnvelope);
preEnt.append(pEnvelope);
}
else
{
arOther = arids;
}
}
else
arOther.append(arids);
AcDbEntityArray ar;
for (int i(0); i < arOther.length(); ++i)
{
AcDbEntityPointer ent(arids[i], AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) continue;
ar.removeAll();
AecDbEntityBase *pEnt(AecDbEntityBase::cast(ent));
AecDbCurveBase *pCrv(AecDbCurveBase::cast(ent));
if (pEnt)
pEnt->PreprocessForHlr(ptPlnO, vtPlnN, ar);
if (pCrv)
pCrv->PreprocessForHlr(ptPlnO, vtPlnN, ar);
if (!ar.isEmpty())
{
preID2Ent.insert(std::make_pair(arids[i], ar));
arAll.append(ar);
}
}
}
void process_result( const IDMapEntities &result1
, const EntMapEntities &result2
, const IDMapEntities &mpAdditional
, const AcDbEntityArray &arAdditional
, IDMapEntities &outputWithID
, AcDbEntityArray &outputWithoutID )
{
AcDbEntityArray entAr;
EntMapEntities mpAddi;
#if ARX > 23
std::pair<EntMapEntities::iterator, bool> prAddi;
std::pair<IDMapEntities::iterator, bool> prOutput;
#else
EntMapEntities::_Pairib prAddi;
IDMapEntities::_Pairib prOutput;
#endif
// 构筑物产生的结果
AcDbEntityArray arEnvelope;
// 先处理 arAdditional 里面的数据
// arAdditional 里面是不在数据库里面的实体
// 把它的结果从 result2 里面挑出来
AecDbObjXDataMap xData;
for (int i(0); i < arAdditional.length(); ++i)
{
EntMapEntities::const_iterator it(result2.begin());
for (; it != result2.end(); ++it)
{
if (it->first == arAdditional[i])
{
AcDbEntity *pSrc(it->first);
const AcDbEntityArray &arResult(it->second); // 计算结果
if (xData.Read(pSrc, _T("_ENVELOPE_")))
{ // 说明是构筑物,统一处理,这个分支一般是选择了构筑物融合后参与计算
for (int i(0); i != arResult.length(); ++i)
arEnvelope.append((AcDbEntity*)arResult[i]->clone());
continue;
}
for (int i(0); i != arResult.length(); ++i)
{
AcDbEntity *pEnt = (AcDbEntity *)arResult[i]->clone();
if (!pEnt) continue;
pEnt->setLayer(pSrc->layerId());
pEnt->setLinetype(pSrc->linetypeId());
pEnt->setColorIndex(pSrc->colorIndex());
entAr.append(pEnt);
outputWithoutID.append(entAr);
}
}
}
}
// 不能只查找 result1 的结果
// 因为,如果一个实体的araw3d没有画出任何内容时,result1 里面没有其ID
// 但是,result2 却有可能存在它的补充实体
// 下面,对 result1 进行补充
IDMapEntities __result1(result1);
IDMapEntities::const_iterator _itAdd(mpAdditional.begin());
for (; _itAdd != mpAdditional.end(); ++_itAdd)
{
const AcDbObjectId &id(_itAdd->first);
const AcDbEntityArray &ar(_itAdd->second);
for (int i(0); i < ar.length(); ++i)
{
EntMapEntities::const_iterator it(result2.begin());
for (; it != result2.end(); ++it)
{
if (ar.find(it->first) != -1) // it->first 是 id 的补充实体
{
// 如果,此时,result1 里面没有这个 id 的话
// 说明 这个实体的draw3d没有结果,但是有补充实体
// 需要把这个id放到result1中。
// 不需要判断,直接插入,如果result1里面有这个id,插会失败
__result1.insert(std::make_pair(id, AcDbEntityArray()));
}
}
}
}
AcDbVoidPtrArray subAr;
IDMapEntities::const_iterator it1(__result1.begin());
for (; it1 != __result1.end(); ++it1)
{
entAr.removeAll();
mpAddi.clear();
const AcDbObjectId &id(it1->first);
const AcDbEntityArray &arDraw3d(it1->second);
AcDbEntityPointer ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk)
{ // 如果 ent 无效,但是还存在结果,将结果复制到 output
// 目前只有水平轴网
for (int i(0); i < arDraw3d.length(); ++i)
{
AcDbEntity *pEnt = AecDbXCamera::cloneObject(arDraw3d[i]);
if (!pEnt) continue;
entAr.append(pEnt);
}
}
else
{
// 查询这个 id 有没有补充实体
IDMapEntities::const_iterator itAddi(mpAdditional.find(id));
if (itAddi != mpAdditional.end())
{ // 有补充实体,在 result2 里面找到补充实体的结果
for (int i(0); i < itAddi->second.length(); ++i)
{
// 补充实体
AcDbEntity *pAddi(itAddi->second[i]);
EntMapEntities::const_iterator it2 = result2.find(pAddi);
if (it2 != result2.end())
{ // 补充实体 的 结果
const AcDbEntityArray &ar(it2->second);
prAddi = mpAddi.insert(std::make_pair(pAddi, ar));
if (!prAddi.second)
prAddi.first->second.append(ar);
}
}
}
AecDbEntityBase *pEnt(AecDbEntityBase::cast(ent));
AecDbCurveBase *pCrv(AecDbCurveBase::cast(ent));
if (pEnt)
pEnt->ProcessHlrResult(arDraw3d, mpAddi, entAr);
else if (pCrv)
pCrv->ProcessHlrResult(arDraw3d, mpAddi, entAr);
else // 非上华实体
{
AcDbBlockReference *pRef(AcDbBlockReference::cast(ent));
AcDbObjectId layerID(ent->layerId()), linetypeID(ent->linetypeId());
int color(ent->colorIndex());
for (int i(0); i < arDraw3d.length(); ++i)
{
AcDbEntity *pEnt = (AcDbEntity *)arDraw3d[i]->clone();
if (!pEnt) continue;
if (pRef)
{ // 如果被剖切的实体是块,收集结果,方便后面再打成块
subAr.append(pEnt);
}
else
{
pEnt->setLayer(layerID);
pEnt->setLinetype(linetypeID);
pEnt->setColorIndex(color);
entAr.append(pEnt);
}
}
if (pRef && !subAr.isEmpty())
{ // 如果 ent 是 块参照,它不会有补充实体,结果需要打成块
// 块的属性和 pRef 一样
AcDbBlockReference *pSubRef = CoreTools::makeBlockReference(subAr, NULL);
subAr.removeAll();
if (pSubRef)
{
pSubRef->setLayer(layerID);
pSubRef->setLinetype(linetypeID);
pSubRef->setColorIndex(color);
entAr.append(pSubRef);
}
}
EntMapEntities::const_iterator it(mpAddi.begin());
for (; it != mpAddi.end(); ++it)
{
layerID = it->first->layerId();
linetypeID = it->first->linetypeId();
color = it->first->colorIndex();
for (int i(0); i < it->second.length(); ++i)
{
AcDbEntity *pEnt = (AcDbEntity *)it->second[i]->clone();
if (!pEnt) continue;
pEnt->setLayer(layerID);
pEnt->setLinetype(linetypeID);
pEnt->setColorIndex(color);
entAr.append(pEnt);
}
}
}
if (entAr.isEmpty()) continue;
}
prOutput = outputWithID.insert(std::make_pair(id, entAr));
if (!prOutput.second)
prOutput.first->second.append(entAr);
}
// 收集构筑物产生的结果(一般是不对构筑物进行融合的情况下)
IDMapEntities::iterator it(outputWithID.begin());
for (; it != outputWithID.end(); ++it)
{
if (!isEnvelope(it->first)) continue;
// 是构筑物结果,复制出来,并且删掉outputWithID里面的内容
for (int i(0); i < it->second.length(); ++i)
arEnvelope.append((AcDbEntity*)(it->second[i]->clone()));
deleteContainerOfArx<AcDbEntity>(it->second);
outputWithID.erase(it);
it = outputWithID.begin();
}
// 处理构筑物
processEnvelope(arEnvelope);
outputWithoutID.append(arEnvelope);
}
}
ACRX_DXF_DEFINE_MEMBERS(AecDbXCamera, AecDbEntityBase,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
AcDbProxyEntity::kNoOperation | AcDbProxyEntity::kDisableProxyWarning,
AEC_XCAMERA,
"AecXDbCamera"
"|Product Desc: shanghua earthworm app obj"
"|Company: shanghua inc"
"|WEB Address: www.shanghuasoft.com")
// kCurrentVersionNumber->2 --- 增加 m_arSelectionSet
Adesk::UInt32 AecDbXCamera::kCurrentVersionNumber = 2;
static const Adesk::UInt16 kBlue = 5;
AecDbXCamera::AecDbXCamera(void) { }
AecDbXCamera::~AecDbXCamera(void)
{
deleteContainerOfArx<GripData>(m_GripDatas);
}
Acad::ErrorStatus AecDbXCamera::subErase(Adesk::Boolean erasing)
{
//for (int i(0); i < m_arResults.length(); ++i)
// eraseEnt(m_arResults[i], erasing);
return AecDbEntityBase::subErase(erasing);
}
Acad::ErrorStatus AecDbXCamera::copyFrom(const AcRxObject *pSrc)
{
AssertWriteEnabled();
AecDbXCamera *pCamera = AecDbXCamera::cast(pSrc);
if (pCamera != NULL)
{
m_mapSpecXData.CopyFrom(pCamera->GetSpecialtyData(AcDb::kForRead));
}
return Acad::eOk;
}
void AecDbXCamera::subList() const
{
assertReadEnabled();
AecDbEntityBase::subList();
m_mapSpecXData.List();
}
Acad::ErrorStatus AecDbXCamera::subTransformBy(const AcGeMatrix3d &xform)
{
AssertWriteEnabled();
SetEyePoint(GetEyePoint().transformBy(xform));
SetEyeDirect(GetEyeDirect().transformBy(xform));
SetOutputPoint(GetOutputPoint().transformBy(xform));
return Acad::eOk;
}
Acad::ErrorStatus AecDbXCamera::subGetGripPoints(AcDbGripDataPtrArray &grips,
const double curViewUnitSize,
const int gripSize,
const AcGeVector3d &curViewDir,
const int bitflags) const
{
assertReadEnabled();
AcGePoint3dArray ar;
getGripPoints(ar);
deleteContainerOfArx<GripData>(m_GripDatas);
AcGeVector3d vtZ(getViewDir());
AcGePoint3dArray pts;
if (GetUsageMode() == eVerti)
{
if (vtZ.isParallelTo(AcGeVector3d::kZAxis))
{
// 水平
pts.append(ar[0]);
pts.append(ar[1]);
pts.append(ar[2]);
pts.append(ar[3]);
pts.append(ar[4]);
pts.append(ar[5]);
pts.append(ar.last());
}
else
{ // 非水平
pts.append(ar[4]);
pts.append(ar[10]);
}
// 先把 grippoints 里的点都绘制出来
for (int i(0); i < pts.length(); ++i)
{
GripData *gpd = new GripData;
gpd->m_idx = i;
gpd->m_pt = pts.at(i);
AcDbGripData *pGripData = new AcDbGripData;
pGripData->setGripPoint(pts.at(i));
pGripData->setWorldDraw(Grip_WorldDrawfunc);
m_GripDatas.append(gpd);
pGripData->setAppData(gpd);
grips.append(pGripData);
}
// 第1个点作为绘制点,绘制虚框
GripData &first = *m_GripDatas.first();
first.m_mode = eVerti;
first.m_arSelectFrame.append(ar[0]);
first.m_arSelectFrame.append(ar[2]);
first.m_arSelectFrame.append(ar[3]);
first.m_arSelectFrame.append(ar[5]);
if (!vtZ.isParallelTo(AcGeVector3d::kZAxis)) // 非水平,绘制范围框
{
first.m_arSelectFrame.append(ar[6]);
first.m_arSelectFrame.append(ar[7]);
first.m_arSelectFrame.append(ar[8]);
first.m_arSelectFrame.append(ar[9]);
}
}
else if (GetUsageMode() == eHoriz)
{
if (vtZ.isParallelTo(AcGeVector3d::kZAxis))
{
pts.append(ar[0]);
pts.append(ar[1]);
pts.append(ar[2]);
pts.append(ar[3]);
pts.append(ar[4]);
pts.append(ar.last());
}
else // 非水平,放入 9-10
{
pts.append(ar[9]);
pts.append(ar[10]);
}
for (int i(0); i < pts.length(); ++i)
{
GripData *gpd = new GripData;
gpd->m_idx = i;
gpd->m_pt = pts.at(i);
AcDbGripData *pGripData = new AcDbGripData;
pGripData->setGripPoint(pts.at(i));
pGripData->setWorldDraw(Grip_WorldDrawfunc);
m_GripDatas.append(gpd);
pGripData->setAppData(gpd);
grips.append(pGripData);
}
if (!vtZ.isParallelTo(AcGeVector3d::kZAxis)) // 非水平,绘制范围框
{
// 第1个点作为绘制点,绘制虚框
GripData &first = *m_GripDatas.first();
first.m_mode = eHoriz;
first.m_arSelectFrame.append(ar[0]);
first.m_arSelectFrame.append(ar[1]);
first.m_arSelectFrame.append(ar[2]);
first.m_arSelectFrame.append(ar[3]);
first.m_arSelectFrame.append(ar[5]);
first.m_arSelectFrame.append(ar[6]);
first.m_arSelectFrame.append(ar[7]);
first.m_arSelectFrame.append(ar[8]);
}
}
else // eStatic
{
if (ar.isEmpty()) return Acad::eOk;
GripData *gpd = new GripData;
gpd->m_idx = 0;
gpd->m_pt = ar.last();
AcDbGripData *pGripData = new AcDbGripData;
pGripData->setGripPoint(ar.last());
pGripData->setWorldDraw(Grip_WorldDrawfunc);
m_GripDatas.append(gpd);
pGripData->setAppData(gpd);
grips.append(pGripData);
}
// 显示结果范围
AcGePoint3d ptLT, ptRT, ptRB, ptLB;
if (getResultBox(ptLT, ptRT, ptRB, ptLB))
{
GripData &first = *m_GripDatas.first();
first.m_bDrawResultFrame = true;
first.m_arResultFrame.append(ptLT);
first.m_arResultFrame.append(ptRT);
first.m_arResultFrame.append(ptRB);
first.m_arResultFrame.append(ptLB);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbXCamera::subGetOsnapPoints(AcDb::OsnapMode osnapMode
, INT_PTR gsSelectionMark
, const AcGePoint3d &pickPoint
, const AcGePoint3d &lastPoint
, const AcGeMatrix3d &viewXform
, AcGePoint3dArray &snapPoints
, AcDbIntArray &geomIds) const
{
AcGePoint3dArray ar;
getGripPoints(ar);
if (GetUsageMode() != eStatic)
{
if (GetUsageMode() == eVerti)
{
snapPoints.append(ar[0]);
snapPoints.append(ar[1]);
snapPoints.append(ar[2]);
snapPoints.append(ar[3]);
snapPoints.append(ar[4]);
snapPoints.append(ar[5]);
snapPoints.append(ar[10]);
}
else
{
snapPoints.append(ar[0]);
snapPoints.append(ar[1]);
snapPoints.append(ar[2]);
snapPoints.append(ar[3]);
snapPoints.append(ar[4]);
}
}
AcGePoint3d ptLT, ptRT, ptRB, ptLB;
if (getResultBox(ptLT, ptRT, ptRB, ptLB))
{
snapPoints.append(ptLT);
snapPoints.append(ptRT);
snapPoints.append(ptRB);
snapPoints.append(ptLB);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbXCamera::subMoveGripPointsAt(const AcDbVoidPtrArray &appData
, const AcGeVector3d &offset
, const int bitflags)
{
AssertWriteEnabled();
if (appData.isEmpty()) return Acad::eOk;
bool bFresh(false);
GripData *pAppData = (GripData *)appData.first();
AcGePoint3dArray ar;
getGripPoints(ar);
if (GetUsageMode() == eVerti)
{
AcGePoint3d ptOffset(pAppData->m_pt + offset)
, ptOrig(pAppData->m_pt)
, pt0(ar[0])
, pt1(ar[1])
, pt2(ar[2])
, pt3(ar[3])
, pt4(ar[4])
, pt5(ar[5])
, pt6(ar[6]);
AcGeVector3d vt(getViewDir());
if (vt.isCodirectionalTo(AcGeVector3d::kZAxis))
{
switch (pAppData->m_idx)
{
case 3: // 修改视口宽度
case 5:
{
AcDbLine seg(pt3, pt5);
AcGePoint3d ptNew;
seg.getClosestPointTo(ptOffset, ptNew, Adesk::kTrue);
AcGeVector3d vtOld(pt4 - ptOrig);
AcGeVector3d vtNew(pt4 - ptNew);
if (vtOld.isCodirectionalTo(vtNew) && vtNew.length() > 100)
{
SetWidth(vtNew.length() * 2);
bFresh = true;
}
}
break;
case 1: // 移动眼睛位置
SetEyePoint(GetEyePoint() + offset);
bFresh = true;
break;
case 0: // 旋转 m_vtEye 的方向
{
AcGeVector3d vtOld(pt0 - pt2);
AcGeVector3d vtNew(ptOffset - pt1);
double dAngle = vtOld.angleTo(vtNew, AcGeVector3d::kZAxis);
vtNew = GetEyeDirect();
vtNew.rotateBy(dAngle, AcGeVector3d::kZAxis);
SetEyeDirect(vtNew);
bFresh = true;
}
break;
case 2: // 旋转 m_vtEye 的方向
{
AcGeVector3d vtOld(pt2 - pt0);
AcGeVector3d vtNew(ptOffset - pt1);
double dAngle = vtOld.angleTo(vtNew, AcGeVector3d::kZAxis);
vtNew = GetEyeDirect();
vtNew.rotateBy(dAngle, AcGeVector3d::kZAxis);
SetEyeDirect(vtNew);
bFresh = true;
}
break;
case 4: // 修改 视口的纵深 既 m_vtEye 的长度
{
AcDbLine seg(pt0, pt2);
AcGePoint3d ptClosed;
seg.getClosestPointTo(ptOffset, ptClosed, Adesk::kTrue);
AcGeVector3d vtNew(ptOffset - ptClosed);
double dist(ptOffset.distanceTo(ptClosed));
if (dist > 100)
{
SetEyeDirect(vtNew);
bFresh = true;
}
}
break;
case 6: // 移动输出结果的位置
{
moveOutput(offset);
bFresh = false;
break;
}
default: break;
}
}
else
{
switch (pAppData->m_idx)
{
case 0:
SetHorizTop((pAppData->m_pt + offset).z);
break;
case 1:
SetHorizBottom((pAppData->m_pt + offset).z);
break;
default: break;
}
}
}
else if (GetUsageMode() == eHoriz)
{
AcGePoint3d ptOld, pt2, ptNew, ptClosed, ptEye;
AcDbLine lineH, lineV;
AcGeVector3d vtEye;
AcGeMatrix3d mat;
bFresh = true;
AcGeVector3d vtZ(getViewDir());
ptOld = pAppData->m_pt;
ptNew = ptOld + offset;
if (vtZ.isParallelTo(AcGeVector3d::kZAxis))
{
switch (pAppData->m_idx)
{
case 0:
pt2 = ar[2];
SetEyePoint(CoreTools::MidPt(ptNew, pt2));
lineH.setStartPoint(ar[2]);
lineH.setEndPoint(ar[3]);
lineH.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetHeight(ptNew.distanceTo(ptClosed));
lineV.setStartPoint(ar[1]);
lineV.setEndPoint(ar[2]);
lineV.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetWidth(ptNew.distanceTo(ptClosed));
break;
case 1:
pt2 = ar[3];
SetEyePoint(CoreTools::MidPt(ptNew, pt2));
lineH.setStartPoint(ar[2]);
lineH.setEndPoint(ar[3]);
lineH.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetHeight(ptNew.distanceTo(ptClosed));
lineV.setStartPoint(ar[0]);
lineV.setEndPoint(ar[3]);
lineV.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetWidth(ptNew.distanceTo(ptClosed));
break;
case 2:
pt2 = ar[0];
SetEyePoint(CoreTools::MidPt(ptNew, pt2));
lineH.setStartPoint(ar[0]);
lineH.setEndPoint(ar[1]);
lineH.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetHeight(ptNew.distanceTo(ptClosed));
lineV.setStartPoint(ar[0]);
lineV.setEndPoint(ar[3]);
lineV.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetWidth(ptNew.distanceTo(ptClosed));
break;
case 3:
pt2 = ar[1];
SetEyePoint(CoreTools::MidPt(ptNew, pt2));
lineH.setStartPoint(ar[0]);
lineH.setEndPoint(ar[1]);
lineH.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetHeight(ptNew.distanceTo(ptClosed));
lineV.setStartPoint(ar[2]);
lineV.setEndPoint(ar[1]);
lineV.getClosestPointTo(ptNew, ptClosed, Adesk::kTrue);
SetWidth(ptNew.distanceTo(ptClosed));
break;
case 4: // eye
SetEyePoint(ptNew);
break;
case 5: // output
moveOutput(offset);
bFresh = false;
break;
default:
break;
}
}
else
{
switch (pAppData->m_idx)
{
case 0: // top
ptEye = GetEyePoint();
ptEye.z = ptNew.z;
SetEyePoint(ptEye);
SetHorizTop(ptNew.z);
vtEye = GetEyeDirect();
vtEye = -AcGeVector3d::kZAxis * (GetHorizTop() - GetHorizBottom());
SetEyeDirect(vtEye);
break;
case 1: // bottom
SetHorizBottom(ptNew.z);
vtEye = GetEyeDirect();
vtEye = -AcGeVector3d::kZAxis * (GetHorizTop() - GetHorizBottom());
SetEyeDirect(vtEye);
break;
default:
break;
}
}
}
else // eStatic
{
moveOutput(offset);
bFresh = false;
}
// 当松开夹点时,database() 不为空,可以刷新。
if (database() && bFresh)
{
refresh(true);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbXCamera::dwgInFields(AcDbDwgFiler *pFiler)
{
AssertWriteEnabled();
//----- Read parent class information first.
Acad::ErrorStatus es = Acad::eOk;
if (!pFiler->isKindOf(CMFCDbDwgFiler::desc()))
{
es = AecDbEntityBase::dwgInFields(pFiler);
if (es != Acad::eOk)
return (es);
}
//----- Object version number needs to be read first
Adesk::UInt32 version = 0;
if ((es = pFiler->readUInt32(&version)) != Acad::eOk)
return (es);
if (version > AecDbXCamera::kCurrentVersionNumber)
return (Acad::eMakeMeProxy);
m_mapSpecXData.dwgInFields(pFiler);
m_arResults.removeAll();
Adesk::Int32 num(0);
pFiler->readInt32(&num);
AcDbObjectId id;
for (int i(0); i < num; ++i)
{
pFiler->readSoftPointerId((AcDbSoftPointerId *)&id);
if (id.isValid())
m_arResults.append(id);
}
if (version > 1)
{
pFiler->readInt32(&num);
for (int i(0); i < num; ++i)
{
pFiler->readSoftPointerId((AcDbSoftPointerId *)&id);
if (id.isValid())
m_arSelectionSet.append(id);
}
}
return (pFiler->filerStatus());
}
Acad::ErrorStatus AecDbXCamera::dwgOutFields(AcDbDwgFiler *pFiler) const
{
assertReadEnabled();
//----- Save parent class information first.
Acad::ErrorStatus es = Acad::eOk;
if (!pFiler->isKindOf(CMFCDbDwgFiler::desc()))
{
es = AecDbEntityBase::dwgOutFields(pFiler);
if (es != Acad::eOk)
return (es);
}
//----- Object version number needs to be saved first
if ((es = pFiler->writeUInt32(AecDbXCamera::kCurrentVersionNumber)) != Acad::eOk)
return (es);
m_mapSpecXData.dwgOutFields(pFiler);
pFiler->writeInt32(m_arResults.length());
for (int i(0); i < m_arResults.length(); ++i)
pFiler->writeSoftPointerId(m_arResults[i]);
if (AecDbXCamera::kCurrentVersionNumber > 1)
{
pFiler->writeInt32(m_arSelectionSet.length());
for (int i(0); i < m_arSelectionSet.length(); ++i)
pFiler->writeSoftPointerId(m_arSelectionSet[i]);
}
return (pFiler->filerStatus());
}
Acad::ErrorStatus AecDbXCamera::Draw2d(AcGiDraw &dc) const
{
assertReadEnabled();
AcGePoint3dArray ar;
getGripPoints(ar);
Adesk::UInt16 oldClr = dc.GetColor();
dc.SetColor(6);
if (GetUsageMode() != eStatic)
{
int prec(0);
CString sTop;
sTop.Format(_T("%s , %s"), TypeConvert::d2s(GetHorizTop(), &prec)
, TypeConvert::d2s(GetHorizBottom(), &prec));
double dH;
AcGePoint3d ptIns;
double dRotation(.0);
AcGeVector3d X(AcGeVector3d::kXAxis);
if (GetUsageMode() == eVerti)
{
dc.DrawLine(AcGeLineSeg3d(ar[0], ar[2]));
dH = (ar[2].distanceTo(ar[3]) * .025);
ptIns = (CoreTools::MidPt(ar[0], ar[2]) - GetEyeDirect().normalize() * dH);
X = (ar[2] - ar[0]).normalize();
dRotation = AcGeVector3d::kXAxis.angleTo(X, AcGeVector3d::kZAxis);
}
else
{
dc.DrawLine(AcGeLineSeg3d(ar[0], ar[1]));
dc.DrawLine(AcGeLineSeg3d(ar[1], ar[2]));
dc.DrawLine(AcGeLineSeg3d(ar[2], ar[3]));
dc.DrawLine(AcGeLineSeg3d(ar[3], ar[0]));
dH = (ar[1].distanceTo(ar[2]) * .025);
ptIns = (CoreTools::MidPt(ar[3], ar[2]) - AcGeVector3d::kYAxis * dH);
}
AcDbText txt1;
txt1.setTextString(sTop);
txt1.setPosition(ptIns);
txt1.setHeight(dH);
AcDbExtents ext;
txt1.getGeomExtents(ext);
double dW(ext.maxPoint().x - ext.minPoint().x);
ptIns -= X * (dW * .5);
txt1.setPosition(ptIns);
txt1.setRotation(dRotation);
dc.DrawEntity(txt1);
}
dc.SetColor(oldClr);
return Acad::eOk;
}
Acad::ErrorStatus AecDbXCamera::Draw3d(AcGiDraw &dc) const
{
return Draw2d(dc);
}
void AecDbXCamera::cloneObjects(AcDbObjectIdArray &arids, AcDbEntityArray &ents)
{
for (int i(0); i < arids.length(); ++i)
{
AcDbEntity *pEnt = cloneObject(arids[i]);
if (!pEnt) continue;
ents.append(pEnt);
}
}
AcDbEntity *AecDbXCamera::cloneObject(AcDbEntity *p)
{
if (!p) return NULL;
AcDbEntity *pEnt = (AcDbEntity *)p->clone();
if (!pEnt) return NULL;
pEnt->setLayer(p->layerId());
pEnt->setLinetype(p->linetypeId());
pEnt->setColorIndex(p->colorIndex());
AecDbObjXDataMap xdata;
if (xdata.Read(p, BIMDATA_APP))
xdata.Write(pEnt, BIMDATA_APP);
return pEnt;
}
AcDbEntity *AecDbXCamera::cloneObject(AcDbObjectId &id)
{
AcDbEntityPointer ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) return NULL;
return cloneObject(ent);
}
void AecDbXCamera::collectEnities(resbuf *selType, resbuf *selArea, AcDbObjectIdArray &arIds)
{
ads_name ss, ent;
int nRes = acedSSGet(_T("CP"), selArea, NULL, selType, ss);
if (nRes != RTNORM) return;
Adesk::Int32 lLen = 0;
acedSSLength(ss, &lLen);
AcDbObjectId id;
for (int i = 0; i < lLen; i++)
{
acedSSName(ss, i, ent);
acdbGetObjectId(id, ent);
if (id.isValid())
arIds.append(id);
}
acedSSFree(ss);
}
resbuf *AecDbXCamera::getCollectArea() const
{
assertReadEnabled();
AcGePoint3dArray arPts;
getGripPoints(arPts);
struct resbuf *pointlist(NULL);
if (GetUsageMode() == eVerti)
{
pointlist = acutBuildList(RTPOINT, arPts[0], RTPOINT, arPts[2],
RTPOINT, arPts[3], RTPOINT, arPts[5], RTPOINT, arPts[0], 0);
}
else if (GetUsageMode() == eHoriz)
{
pointlist = acutBuildList(RTPOINT, arPts[0], RTPOINT, arPts[1],
RTPOINT, arPts[2], RTPOINT, arPts[3], RTPOINT, arPts[0], 0);
}
return pointlist;
}
void AecDbXCamera::calcRangeOfElev(double &dMax, double &dMin)
{
AcDbObjectIdArray ar;
collectEnities(ar);
AcGePoint3d ptmax, ptmin;
AcDbExtents ext, all;
for (int i(0); i < ar.length(); ++i)
{
AcDbEntityPointer ent(ar[i], AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) continue;
if (ent->getGeomExtents(ext) != Acad::eOk) continue;
ptmax = ext.maxPoint();
ptmin = ext.minPoint();
if (ptmax.x < ptmin.x
|| ptmax.y < ptmin.y
|| ptmax.z < ptmin.z) continue;
all.addExt(ext);
}
dMax = all.maxPoint().z;
dMin = all.minPoint().z;
if (dMax < dMin)
{
dMax = 0.;
dMin = 0.;
}
}
void AecDbXCamera::collectEnities(AcDbObjectIdArray &arIds) const
{
assertReadEnabled();
/*
struct resbuf *pRb = acutBuildList(
-4, _T("<or")
, RTDXF0, _T("AEC_*")
, -4, _T("<or")
, -4, _T("<and"), RTDXF0, _T("LINE"), 8, _T("Dote"), -4, _T("and>")
, -4, _T("<and"), RTDXF0, _T("LINE"), 8, _T("Axis"), -4, _T("and>")
, -4, _T("or>")
, -4, _T("or>")
, -4, _T("<not")
, -4, _T("<or")
, RTDXF0, _T("AEC_XCAMERA")
, RTDXF0, _T("AEC_ZUOBIAOBIAOZHU")
, RTDXF0, _T("AEC_BIAOGAOBIAOZHU")
, RTDXF0, _T("AEC_JIANTOUYINZHU")
, RTDXF0, _T("AEC_YINCHUBIAOZU")
, RTDXF0, _T("AEC_ZUOFABIAOZHU")
, RTDXF0, _T("AEC_SUOYINTUMING")
, RTDXF0, _T("AEC_POQIE")
, RTDXF0, _T("AEC_YUNXIAN")
, RTDXF0, _T("AEC_ZHEDUANXIAN")
, RTDXF0, _T("AEC_DUICHENZHOU")
, RTDXF0, _T("AEC_ZHIBEIZHEN")
, RTDXF0, _T("AEC_TUMINGBIAOZHU")
, RTDXF0, _T("AEC_CHICUNBIAOZHU")
, RTDXF0, _T("AEC_BANJINGBIAOZHU")
, RTDXF0, _T("AEC_EWPIPEDIM")
, -4, _T("or>")
, -4, _T("not>")
, 0);
*/
struct resbuf *selArea(getCollectArea());
struct resbuf *typelist(getSelectTypeResbuf());
collectEnities(typelist, selArea, arIds);
acutRelRb(selArea);
acutRelRb(typelist);
}
void AecDbXCamera::transfromHlrResult(const AcGePoint3d &_ptEye
, const AcGeVector3d &vtEye
, const AcGeVector3d &vtX
, const AcGePoint3d &_ptOutput
, IDMapEntities &result
, EntMapEntities &result2
, AcDbEntity *pSection)
{
if (!pSection) return;
AcDbEntityArray ptrs;
IDMapEntities::const_iterator it(result.begin());
for (; it != result.end(); ++it)
ptrs.append(it->second);
EntMapEntities::const_iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
ptrs.append(it2->second);
ptrs.append(pSection);
if (ptrs.isEmpty()) return;
AcGeMatrix3d mat;
AcGePoint3d ptEye(_ptEye);
ptEye.z = .0;
mat.setToAlignCoordSys(ptEye
, vtX.normal()
, vtEye.crossProduct(vtX).normal()
, vtEye.normal()
, AcGePoint3d::kOrigin
, AcGeVector3d::kXAxis
, AcGeVector3d::kYAxis
, AcGeVector3d::kZAxis);
AcGeMatrix3d matVerti;
AcGePoint3d ptStart(AcGePoint3d::kOrigin);
for (int i(0); i < ptrs.length(); ++i)
{
AcDbEntity *pEnt((AcDbEntity *)ptrs[i]);
if (pEnt)
pEnt->transformBy(mat);
AcDbCurve *pCrv(AcDbCurve::cast(pEnt));
if (pCrv)
{ // 拉到0标高
pCrv->getStartPoint(ptStart);
matVerti.setTranslation(ptStart.z * -AcGeVector3d::kZAxis);
pCrv->transformBy(matVerti);
}
}
// 只需要pSection的中点做移动点
AcDbExtents ext;
pSection->getGeomExtents(ext);
AcGePoint3d ptResultCenter(CoreTools::MidPt(ext.maxPoint(), ext.minPoint()));
AcGePoint3d ptOutput(_ptOutput);
ptOutput.z = .0;
mat.setToIdentity();
mat.setToTranslation(ptOutput - ptResultCenter);
for (int i(0); i < ptrs.length(); ++i)
{
AcDbEntity *pEnt((AcDbEntity *)ptrs[i]);
if (pEnt)
pEnt->transformBy(mat);
}
}
void AecDbXCamera::transfromHlrResult(IDMapEntities &result
, EntMapEntities &result2
, AcDbEntity *pSection) const
{
assertReadEnabled();
if (!pSection) return;
AcGePoint3dArray arPts;
getGripPoints(arPts);
AcGeVector3d X(AcGeVector3d::kXAxis);
if (GetUsageMode() == eVerti)
{
if (arPts.length() < 2)
return;
X = arPts[0] - arPts[1];
}
AcGeVector3d Z(-GetEyeDirect());
AcGeVector3d Y(Z.crossProduct(X));
transfromHlrResult(GetEyePoint(), Z, X, GetOutputPoint(), result, result2, pSection);
}
void AecDbXCamera::hlrCalc(AcDbObjectIdArray &arIds
, const AcGePoint3d &ptEye
, const AcGeVector3d &vtEye
, const AcGeVector3d &vtX
, const AcGePoint3d &ptOutput
, AcDbPolyline *pSection
, IDMapEntities &outputWithID
, AcDbEntityArray &outputWithoutID
, AcDbEntityArray &arAxisPtrs)
{
// 在数据库中的实体所生成的补充实体
// first-数据库中实体id second-选中实体产生的补充实体
IDMapEntities mpAdditional;
// 不在数据库中的实体生成的补充实体
AcDbEntityArray arAdditional;
/*
HlrCalc 处理三种类型的数据
1.数据库内的实体
2.数据库内的实体产生的补充实体(管线、管件的中心线,阀门的2D表示 etc.)
3.非数据库内的实体产生的补充实体(构筑物融合之后的实体就属于这种类型)
2、3两个数据都放入arAdditional_all里面进行计算
*/
// 所有的补充实体
AcDbEntityArray arAdditional_all;
// 预处理,得到选中实体的补充实体
preprocess(arIds
, ptEye
, vtEye
, mpAdditional
, arAdditional
, arAdditional_all);
// 获取hlr原始结果
std::shared_ptr<AcDbViewport> pVp(makeViewPort(ptEye, -vtEye));
IDMapEntities result1;
EntMapEntities result2;
int control = kEntity|kProgress|kHideTangents|kProject/*|kShowAll|kBlock|kHonorInternals*/;
HlrCalc(arIds, arAdditional_all, pVp.get(), control, result1, result2);
if (result1.empty() && result2.empty())
{
// 如果实体的PreprocessForHlr函数内,设置了 HLR_CALC,从而影响实体的 Draw3d 函数的返回
// 那么,其PreprocessForHlr函数一定要无条件设置回来
// rollback 回调用其内部的PreprocessForHlr函数
rollback(arIds);
return;
}
if (!arAxisPtrs.isEmpty())
result1.insert(std::make_pair(AcDbObjectId::kNull, arAxisPtrs));
// 调整结果位置
transfromHlrResult(ptEye, -vtEye, vtX, ptOutput, result1, result2, pSection);
// 截面裁剪
clipResultBySection(result1, result2, pSection);
// 如果裁剪之后,没有结果了,回退实体状态
if (result1.empty() && result2.empty())
{
rollback(arIds);
return;
}
// 设置属性
process_result(result1, result2, mpAdditional, arAdditional, outputWithID, outputWithoutID);
// 最后把section复制一份放到结果里面
//outputWithoutID.append((AcDbEntity*)pSection->clone());
// 释放draw3d的计算结果
IDMapEntities::iterator it(result1.begin());
for (; it != result1.end(); ++it)
deleteContainerOfArx<AcDbEntity>(it->second);
// 释放补充实体的计算结果
EntMapEntities::iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
deleteContainerOfArx<AcDbEntity>(it2->second);
// 释放 所有补充实体
deleteContainerOfArx<AcDbEntity>(arAdditional_all);
rollback(arIds);
}
void AecDbXCamera::refresh(const bool &bRefreshEntity)
{
assertWriteEnabled();
if (!bRefreshEntity) return;
// 清空输出结果实体
eraseEnts(m_arResults);
// 收集实体
AcDbObjectIdArray arIds;
// 收集轴网
AcDbObjectIdArray arAxis;
// 收集围护结构
if (GetUsageMode() != eStatic)
{
collectEnities(arIds);
collectAxisObject(arAxis);
}
else
{
arIds.append(m_arSelectionSet);
}
if (arIds.isEmpty()) return;
AcGeVector3d X(AcGeVector3d::kXAxis);
if (GetUsageMode() == eVerti)
{
AcGePoint3dArray arPts;
getGripPoints(arPts);
if (arPts.length() < 2)
return;
X = arPts[0] - arPts[1];
}
// 截面
AcDbPolyline *pSection = getSectionPolygon();
IDMapEntities outputWithID; // 可以与数据库实体相关联的结果
AcDbEntityArray outputWithoutID;// 不能与数据库实体相关联的结果
AcDbEntityArray entAxis;
// 计算轴网
if (!arAxis.isEmpty())
{
if (GetUsageMode() == eVerti) // 垂直剖切,轴网自己遮挡一下
{
AcDbExtents extAll;
pSection->getGeomExtents(extAll);
double dMaxZ(extAll.maxPoint().z), dMinZ(extAll.minPoint().z);
double dH(dMaxZ - dMinZ);
// 最高点向上延长30%
dMaxZ += dH * (3. / 10);
// 最低点向上提长度的一半
dMinZ += dH * .5;
// 得到特征点
AcGePoint3dArray arPts;
getGripPoints(arPts);
// 找到和剖切线垂直的,其它的不要
AcGeLineSeg3d cutLine(arPts[1], arPts[0]), axisLine;
for (int i(0); i < arAxis.length(); ++i)
{
AcDbObjectPointer<AcDbLine> line(arAxis[i], AcDb::kForRead);
if (line.openStatus() != Acad::eOk) continue;
axisLine.set(line->startPoint(), line->endPoint());
if (axisLine.isPerpendicularTo(cutLine))
entAxis.append(cloneObject(arAxis[i]));
}
// 将轴网变换到剖切面上
// 以剖切线为轴,翻转轴网
AcGeMatrix3d mat;
mat.setToRotation(-PI * .5 , arPts[2] - arPts[1]);
AcGePoint3d ptS, ptE;
for (int i(0); i < entAxis.length(); ++i)
{
AcDbLine *pL(AcDbLine::cast(entAxis[i]));
if (pL)
{
pL->transformBy(mat);
ptS = pL->startPoint();
ptE = pL->endPoint();
// 修改变换后的标高
pL->setStartPoint(AcGePoint3d(ptS.x, ptS.y, dMinZ));
pL->setEndPoint(AcGePoint3d(ptE.x, ptE.y, dMaxZ));
}
}
}
else if (GetUsageMode() == eHoriz) // 水平剖切,直接复制出来
{
// 拷贝轴网
cloneObjects(arAxis, entAxis);
}
}
hlrCalc(arIds
, GetEyePoint()
, GetEyeDirect()
, X
, GetOutputPoint()
, pSection
, outputWithID
, outputWithoutID
, entAxis );
DELETE_PTR(pSection);
// 输出
IDMapEntities::iterator it;
AcDbObjectId id;
for (it = outputWithID.begin(); it != outputWithID.end(); ++it)
{
for (int i(0); i < it->second.length(); ++i)
{
AcDbEntity *pEnt(it->second[i]);
if (!pEnt) continue;
id = CoreTools::AddToModelSpace(pEnt);
if (id.isValid())
m_arResults.append(id);
else
DELETE_PTR(pEnt);
}
}
for (int i(0); i < outputWithoutID.length(); ++i)
{
AcDbEntity *pEnt(outputWithoutID[i]);
if (!pEnt) continue;
id = CoreTools::AddToModelSpace(pEnt);
if (id.isValid())
m_arResults.append(id);
else
DELETE_PTR(pEnt);
}
// 保险起见,再还原一次
rollback(arIds);
}
void AecDbXCamera::getGripPoints(AcGePoint3dArray &ar) const
{
ar.removeAll();
if (GetUsageMode() == eVerti)
{
/*
垂直剖切
上层
pt0-----------pt1-----------pt2
V V
V V
V V
V V
V V
pt5-----------pt4-----------pt3
pt1 移动眼睛位置
pt0,pt2 修改视口宽度
pt4 修改 视口的纵深 既 m_vtEye 的长度
pt5,pt3 旋转 m_vtEye 的方向
最后一个 pt10 是输出结果的位置点
下层
pt6-------------------------pt7
V V
V V
V V
V V
V V
pt9-----------pt10----------pt8
*/
AcGeVector3d vtEye(GetEyeDirect());
AcGeVector3d vt(vtEye);
vt.rotateBy(PI * .5, AcGeVector3d::kZAxis);
vt.normalize();
vt *= GetWidth() * .5;
AcGePoint3d ptEye(GetEyePoint());
AcGePoint3d pt1(ptEye), pt0(ptEye - vt), pt2(ptEye + vt);
AcGePoint3d pt3 = pt2 + vtEye, pt5 = pt0 + vtEye, pt4 = pt1 + vtEye;
pt0.z = pt1.z = pt2.z = pt3.z = pt4.z = pt5.z = GetHorizTop();
ar.append(pt0);
ar.append(pt1);
ar.append(pt2);
ar.append(pt3);
ar.append(pt4);
ar.append(pt5);
AcGePoint3d pt6(pt0), pt7(pt2), pt8(pt3), pt9(pt5), pt10(pt4);
pt6.z = pt7.z = pt8.z = pt9.z = pt10.z = GetHorizBottom();
ar.append(pt6);
ar.append(pt7);
ar.append(pt8);
ar.append(pt9);
ar.append(pt10);
}
else if (GetUsageMode() == eHoriz)
{
/*
水平剖切
上层
pt0-------------------------pt1
| |
| |
| pt4 |
| |
| |
pt3---------pt9-------------pt2
下层
pt5-------------------------pt6
| |
| |
| |
| |
| |
pt8---------pt10------------pt7
上层是 pt0 ,pt1, pt2, pt3, pt4(pt0, pt1中点, 既是eye点)
下层是 pt5 ,pt6, pt7, pt8
pt9(pt3, pt2 中点)
pt10(pt8, pt7 中点)
pt11(输出结果的位置点)
功能:
pt0-pt3,改变矩形框大小
当不是水平俯视图的时候 pt9,pt10 改变视口深度
*/
AcGePoint3d pt4(GetEyePoint());
double dW(GetWidth()), dH(GetHeight());
AcGePoint3d pt0(pt4);
pt0.x -= dW * .5;
pt0.y += dH * .5;
AcGePoint3d pt1(pt0);
pt1.x += dW;
AcGePoint3d pt2(pt1);
pt2.y -= dH;
AcGePoint3d pt3(pt2);
pt3.x -= dW;
AcGePoint3d pt9(CoreTools::MidPt(pt3, pt2));
pt0.z = pt1.z = pt2.z = pt3.z = pt4.z = pt9.z = GetHorizTop();
AcGePoint3d pt5(pt0), pt6(pt1), pt7(pt2), pt8(pt3), pt10(pt9);
pt5.z = pt6.z = pt7.z = pt8.z = pt10.z = GetHorizBottom();
ar.append(pt0);
ar.append(pt1);
ar.append(pt2);
ar.append(pt3);
ar.append(pt4);
ar.append(pt5);
ar.append(pt6);
ar.append(pt7);
ar.append(pt8);
ar.append(pt9);
ar.append(pt10);
}
AcGePoint3d ptLT, ptRT, ptRB, ptLB;
if (getResultBox(ptLT, ptRT, ptRB, ptLB))
{
ar.append(CoreTools::MidPt(ptLB, ptRB));
}
else
ar.append(GetOutputPoint());
}
AcDbExtents AecDbXCamera::getResultExtent() const
{
AcDbExtents ext, _ext;
for (int i(0); i < m_arResults.length(); ++i)
{
AcDbEntityPointer ent(m_arResults[i], AcDb::kForRead);
if (ent.openStatus() == Acad::eOk)
{
ent->getGeomExtents(_ext);
ext.addExt(_ext);
}
}
return ext;
}
bool AecDbXCamera::getResultBox(AcGePoint3d &ptLT
, AcGePoint3d &ptRT
, AcGePoint3d &ptRB
, AcGePoint3d &ptLB) const
{
if (m_arResults.isEmpty()) return false;
AcDbExtents ext(getResultExtent());
AcGePoint3d ptIns(CoreTools::MidPt(ext.maxPoint(), ext.minPoint()));
double dX(ext.maxPoint().x - ext.minPoint().x)
, dY(ext.maxPoint().y - ext.minPoint().y);
double dDelta(dX > dY ? dY * .1 : dX * .1);
dX += dDelta;
dY += dDelta;
ptLB = ptIns;
ptRB = ptIns;
ptLB.x -= dX * .5;
ptLB.y -= dY * .5;
ptRB.x += dX * .5;
ptRB.y -= dY * .5;
ptRT = ptRB;
ptLT = ptLB;
ptRT.y += dY;
ptLT.y += dY;
return true;
}
AecDbObjXDataMap *AecDbXCamera::GetSpecialtyData(AcDb::OpenMode bMode)
{
if (bMode == AcDb::kForWrite)
AssertWriteEnabled();
else
assertReadEnabled();
return &m_mapSpecXData;
}
const AecDbObjXDataMap *AecDbXCamera::GetSpecialtyData() const
{
assertReadEnabled();
return &m_mapSpecXData;
}
void AecDbXCamera::eraseEnt(AcDbObjectId & id, Adesk::Boolean erasing)
{
::eraseEnt(id, erasing);
}
void AecDbXCamera::eraseEnts(AcDbObjectIdArray & ids, Adesk::Boolean erasing)
{
for (int i(0); i < ids.length(); ++i)
eraseEnt(ids[i]);
ids.removeAll();
}
resbuf* AecDbXCamera::getSelectTypeResbuf()
{
// 构筑物单独处理
return acutBuildList(
RTDXF0, _T("AEC_*,INSERT")
, -4, _T("<not")
, -4, _T("<or")
, RTDXF0, _T("AEC_XCAMERA")
, RTDXF0, _T("AEC_JOGGEDCAMERA")
, RTDXF0, _T("AEC_PFDIM")
, RTDXF0, _T("AEC_ZUOBIAOBIAOZHU")
, RTDXF0, _T("AEC_BIAOGAOBIAOZHU")
, RTDXF0, _T("AEC_JIANTOUYINZHU")
, RTDXF0, _T("AEC_YINCHUBIAOZU")
, RTDXF0, _T("AEC_ZUOFABIAOZHU")
, RTDXF0, _T("AEC_SUOYINTUMING")
, RTDXF0, _T("AEC_POQIE")
, RTDXF0, _T("AEC_YUNXIAN")
, RTDXF0, _T("AEC_ZHEDUANXIAN")
, RTDXF0, _T("AEC_DUICHENZHOU")
, RTDXF0, _T("AEC_ZHIBEIZHEN")
, RTDXF0, _T("AEC_TUMINGBIAOZHU")
, RTDXF0, _T("AEC_CHICUNBIAOZHU")
, RTDXF0, _T("AEC_BANJINGBIAOZHU")
, RTDXF0, _T("AEC_EWPIPEDIM")
, RTDXF0, _T("AEC_DIRPS")
, -4, _T("or>")
, -4, _T("not>")
, 0);
}
void AecDbXCamera::updateSelecttionSet(const AcDbObjectIdArray &ids)
{
AssertWriteEnabled();
m_arSelectionSet.removeAll();
m_arSelectionSet.append(ids);
if (m_arSelectionSet.isEmpty()) return;
AcDbExtents ext, _ext;
for (int i(0); i < m_arSelectionSet.length(); ++i)
{
AcDbEntityPointer ent(m_arSelectionSet[i], AcDb::kForRead);
if (ent.openStatus() != Acad::eOk) continue;
ent->getGeomExtents(_ext);
ext.addExt(_ext);
}
AcGePoint3d ptMax(ext.maxPoint()), ptMin(ext.minPoint());
double dW(ptMax.x - ptMin.x), dH(ptMax.y - ptMin.y);
AcGeVector3d vtEye(-AcGeVector3d::kZAxis * (ptMax.z - ptMin.z));
AcGePoint3d ptEye(CoreTools::MidPt(ptMax, ptMin));
SetEyePoint(ptEye);
SetEyeDirect(vtEye);
SetHorizTop(ptMax.z);
SetHorizBottom(ptMin.z);
SetWidth(dW);
SetHeight(dH);
refresh(true);
}
void AecDbXCamera::collectEnvelope(const AcDbObjectIdArray &arids
, AcDbObjectIdArray &arOther
, AcDbObjectIdArray &arEnve)
{
for (int i(0); i < arids.length(); ++i)
{
const AcDbObjectId &id(arids[i]);
if (isEnvelope(id))
arEnve.append(id);
else
arOther.append(id);
}
}
void AecDbXCamera::collectEnvelope(AcDbObjectIdArray &arids) const
{
assertReadEnabled();
struct resbuf *pointlist(getCollectArea());
if (pointlist)
{
struct resbuf *pRb = HlrCutOption::getEnvelopeFilter();
if (pRb)
{
collectEnities(pRb, pointlist, arids);
acutRelRb(pRb);
}
acutRelRb(pointlist);
}
}
void AecDbXCamera::collectAxisObject(AcDbObjectIdArray &arids) const
{
assertReadEnabled();
struct resbuf *pointlist(getCollectArea());
struct resbuf *pRb(NULL);
if (GetUsageMode() == eHoriz) // 水平
{ // 水平,需要 轴号,标注,轴网
pRb = acutBuildList(
-4, _T("<or")
, -4, _T("<and"), RTDXF0, _T("LINE"), 8, _T("Dote"), -4, _T("and>")
, -4, _T("<and"), RTDXF0, _T("LINE"), 8, _T("AXISTXT"), -4, _T("and>")
, -4, _T("<and"), RTDXF0, _T("INSERT"), 8, _T("AXISTXT"), 2 , _T("_AXISO"), -4, _T("and>")
, -4, _T("<and"), RTDXF0, _T("DIMENSION"), 8, _T("AXISTXT"), -4, _T("and>")
, -4, _T("or>")
, 0);
}
else if ((GetUsageMode() == eVerti))
{ // 垂直,需要 轴号,轴网
pRb = acutBuildList(
-4, _T("<or")
, -4, _T("<and"), RTDXF0, _T("LINE"), 8, _T("Dote"), 62, 256, -4, _T("and>")
, -4, _T("or>")
, 0);
}
collectEnities(pRb, pointlist, arids);
acutRelRb(pRb);
acutRelRb(pointlist);
}
void AecDbXCamera::moveOutput(const AcGeVector3d &vtOffset)
{
SetOutputPoint(GetOutputPoint() + vtOffset);
AcGeMatrix3d mat;
mat.setToTranslation(vtOffset);
for (int i(0); i < m_arResults.length(); ++i)
{
AcDbEntityPointer ent(m_arResults[i], AcDb::kForWrite);
if (ent.openStatus() == Acad::eOk && !ent->isErased())
ent->transformBy(mat);
}
}
AcDbPolyline* AecDbXCamera::getSectionPolygon()
{
AcGePoint3d ptEye(GetEyePoint())
, pt1(AcGePoint3d::kOrigin)
, pt2(AcGePoint3d::kOrigin)
, pt3(AcGePoint3d::kOrigin)
, pt4(AcGePoint3d::kOrigin);
ptEye.z = .0;
AcGeVector3d X(AcGeVector3d::kXAxis), Y(AcGeVector3d::kYAxis), Z(AcGeVector3d::kZAxis);
AcGePoint3dArray ar;
getGripPoints(ar);
AcDbPolyline *pPoly = new AcDbPolyline;
if (GetUsageMode() == eVerti && ar.length() > 7)
{
// 前面应该调用 getEelevRange() 分析出最大最小标高
double dTop(GetHorizTop()), dBottom(GetHorizBottom());
pt1 = ar[0];
pt2 = ar[2];
pt3 = ar[7];
pt4 = ar[6];
AcGeVector3d vecNormal(GetEyeDirect().normal());
AcGeMatrix3d matWcs2Ocs;
matWcs2Ocs.setToWorldToPlane(vecNormal);
pt1.transformBy(matWcs2Ocs);
pt2.transformBy(matWcs2Ocs);
pt3.transformBy(matWcs2Ocs);
pt4.transformBy(matWcs2Ocs);
pPoly->setNormal(vecNormal);
pPoly->setElevation(pt1.z);
pPoly->addVertexAt(0, AcGePoint2d(pt1.x, pt1.y));
pPoly->addVertexAt(1, AcGePoint2d(pt2.x, pt2.y));
pPoly->addVertexAt(2, AcGePoint2d(pt3.x, pt3.y));
pPoly->addVertexAt(3, AcGePoint2d(pt4.x, pt4.y));
pPoly->setClosed(Adesk::kTrue);
}
else if (GetUsageMode() == eHoriz)
{
pt1 = ar[0];
pt2 = ar[1];
pt3 = ar[2];
pt4 = ar[3];
pPoly->setNormal(Z);
pPoly->setElevation(.0);
pPoly->addVertexAt(0, pt1.convert2d(AcGePlane::kXYPlane));
pPoly->addVertexAt(1, pt2.convert2d(AcGePlane::kXYPlane));
pPoly->addVertexAt(2, pt3.convert2d(AcGePlane::kXYPlane));
pPoly->addVertexAt(3, pt4.convert2d(AcGePlane::kXYPlane));
pPoly->setClosed(Adesk::kTrue);
}
return pPoly;
}
bool AecDbXCamera::GetProperties(SimpleProperty::PropertySetByIndex &properties) const
{
AecDbEntityBase::GetProperties(properties);
CoreTools::setLayerPorperty(properties);
SimpleProperty::makeAndInsert(properties, _T("剖面上标高"), GetHorizTop(), true);
SimpleProperty::makeAndInsert(properties, _T("剖面下标高"), GetHorizBottom(), true);
return true;
}
bool AecDbXCamera::SetProperties(SimpleProperty::PropertySetByName &properties)
{
if (properties.m_set.empty())
return false;
AecDbEntityBase::SetProperties(properties);
double dVal(.0);
if (properties.findAndSet(_T("剖面上标高"), dVal))
SetHorizTop(dVal);
if (properties.findAndSet(_T("剖面下标高"), dVal))
SetHorizBottom(dVal);
return true;
}
#pragma region JIG
XCameraJig_V::XCameraJig_V(void): m_pPolyline(NULL)
{
m_pPolyline = new AcDbPolyline;
}
XCameraJig_V::~XCameraJig_V(void)
{
DELETE_PTR(m_pPolyline);
}
AcEdJig::DragStatus XCameraJig_V::DoIt()
{
AcEdJig::DragStatus eStat;
if (m_nStep == 0)
{
setDispPrompt(_T("\n指定第二点:"));
eStat = drag();
}
else if (m_nStep == 1)
{
setDispPrompt(_T("\n指定剖切范围和方向:"));
eStat = drag();
}
else
{
setDispPrompt(_T("\n指定生成结果的位置:"));
eStat = drag();
}
return eStat;
}
AcEdJig::DragStatus XCameraJig_V::sampler()
{
setUserInputControls((UserInputControls) (AcEdJig::kAccept3dCoordinates | AcEdJig::kNullResponseAccepted));
m_pPolyline->reset(false, 0);
AcEdJig::DragStatus eStat;
if (m_nStep == 0)
{
eStat = acquirePoint(m_ptEnd, m_ptStart);
if (eStat == AcEdJig::kNormal)
{
if (m_ptEnd == m_ptStart)
return AcEdJig::kNoChange;
m_ptEnd.z = .0;
m_ptEye = CoreTools::MidPt(m_ptEnd, m_ptStart);
}
}
else if (m_nStep == 1)
{
eStat = acquirePoint(m_ptDir, m_ptEye);
if (eStat == AcEdJig::kNormal)
{
if (m_ptDir == m_ptEye)
return AcEdJig::kNoChange;
m_ptDir.z = .0;
AcDbLine line(m_ptStart, m_ptEnd);
AcGePoint3d ptClosed;
line.getClosestPointTo(m_ptDir, ptClosed, Adesk::kTrue);
m_vtEye = m_ptDir - ptClosed;
}
}
else
{
eStat = acquirePoint(m_ptOutput, m_ptEye);
m_ptOutput.z = .0;
}
return eStat;
}
AcDbEntity *XCameraJig_V::entity() const
{
return m_pPolyline;
}
Adesk::Boolean XCameraJig_V::update()
{
if (m_nStep >= 0)
{
double dw = CoreTools::PixelToWcs(10);
m_pPolyline->addVertexAt(0, m_ptStart.convert2d(AcGePlane::kXYPlane));
m_pPolyline->addVertexAt(1, m_ptEnd.convert2d(AcGePlane::kXYPlane));
m_pPolyline->setWidthsAt(0, dw, dw);
}
if (m_nStep >= 1)
{
AcGePoint3d ptS2(m_ptStart + m_vtEye), ptE2(m_ptEnd + m_vtEye);
m_pPolyline->addVertexAt(2, ptE2.convert2d(AcGePlane::kXYPlane));
m_pPolyline->addVertexAt(3, ptS2.convert2d(AcGePlane::kXYPlane));
m_pPolyline->setClosed(Adesk::kTrue);
}
return Adesk::kTrue;
}
/////////////////////////////////////////////////////////
XCameraJig_H::XCameraJig_H(void): m_pPolyline(NULL)
{
m_pPolyline = new AcDbPolyline;
}
XCameraJig_H::~XCameraJig_H(void)
{
DELETE_PTR(m_pPolyline);
}
AcEdJig::DragStatus XCameraJig_H::DoIt()
{
AcEdJig::DragStatus eStat;
if (m_nStep == 0)
{
setDispPrompt(_T("\n指定切面范围第二点:"));
eStat = drag();
}
else if (m_nStep == 1)
{
setDispPrompt(_T("\n指定生成结果的位置:"));
eStat = drag();
}
return eStat;
}
AcEdJig::DragStatus XCameraJig_H::sampler()
{
setUserInputControls((UserInputControls)(AcEdJig::kAccept3dCoordinates
| AcEdJig::kNullResponseAccepted));
AcEdJig::DragStatus eStat;
if (m_nStep == 0)
{
eStat = acquirePoint(m_ptRB, m_ptLT);
if (eStat == AcEdJig::kNormal)
{
if (m_ptRB == m_ptLT)
return AcEdJig::kNoChange;
m_ptRB.z = .0;
m_ptEye = CoreTools::MidPt(m_ptRB, m_ptLT);
m_ptLB = m_ptLT;
m_ptLB.y = m_ptRB.y;
m_ptRT = m_ptRB;
m_ptRT.y = m_ptLT.y;
}
}
else if (m_nStep == 1)
{
eStat = acquirePoint(m_ptOutput, m_ptEye);
m_ptOutput.z = .0;
}
return eStat;
}
AcDbEntity *XCameraJig_H::entity() const
{
return m_pPolyline;
}
Adesk::Boolean XCameraJig_H::update()
{
if (m_nStep >= 0)
{
m_pPolyline->reset(false, 0);
double dw = CoreTools::PixelToWcs(10);
m_pPolyline->addVertexAt(0, m_ptLT.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(1, m_ptRT.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(2, m_ptRB.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(3, m_ptLB.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(4, m_ptLT.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
}
//if (m_nStep >= 1)
//{
// AcGePoint3d ptS2(m_ptStart + m_vtEye), ptE2(m_ptEnd + m_vtEye);
// m_pPolyline->addVertexAt(2, ptE2.convert2d(AcGePlane::kXYPlane));
// m_pPolyline->addVertexAt(3, ptS2.convert2d(AcGePlane::kXYPlane));
// m_pPolyline->setClosed(Adesk::kTrue);
//}
return Adesk::kTrue;
}
#pragma endregion