Files
envi-code/SourceCode/Code2026/CoreLibrary/AecDbCamera.cpp
T
gjm c0c04952dc fix: HLR 结果中删除 AecDbEwFitting 产生的退化圆弧
原 isDegenerateArc 以 弧长/半径 比值判断退化圆弧,且无法区分结果来源。
改为按来源实体类型判断:
- result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting;
- result2 的键是无 id 的补充实体指针,先经 mpAdditional
  (数据库实体id -> 其产生的补充实体) 反查归属的数据库实体 id,再判断。

删除规则:结果实体是 AcDbArc 且圆心角为 PI 时删除。
2026-10-16 21:34:08 +08:00

2861 lines
72 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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 "AecDbEwFitting.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
}
// 判断指定 id 的实体是否为 AecDbEwFitting。
bool isFittingId(const AcDbObjectId &id)
{
if (id == AcDbObjectId::kNull)
return false;
AcDbEntityPointer ent(id, AcDb::kForRead);
if (ent.openStatus() != Acad::eOk)
return false;
AcDbEntity *pEnt = ent;
return AecDbEwFitting::cast(pEnt) != NULL;
}
// result2 的键是"产生该批结果的实体指针",这类实体没有 id(是补充实体)。
// 补充实体由某个数据库实体产生,mpAdditional 记录了"数据库实体id -> 其产生的补充实体",
// 因此需反查该指针归属的数据库实体 id,再用该 id 判断类型。
// 找不到归属(例如构筑物融合后不在数据库中的实体)时返回 kNull。
AcDbObjectId fittingIdOfResultKey(AcDbEntity *pSrc, const IDMapEntities &mpAdditional)
{
if (pSrc == NULL)
return AcDbObjectId::kNull;
IDMapEntities::const_iterator it(mpAdditional.begin());
for (; it != mpAdditional.end(); ++it)
{
if (it->second.find(pSrc) != -1) // pSrc 是该 id 产生的补充实体
return it->first;
}
return AcDbObjectId::kNull;
}
// 判断 HLR 结果实体是否为需要删除的"退化圆弧":
// 实体是 AcDbArc,且圆心角为 PI(HLR 计算圆心角溢出后的特征)。
bool isDegenerateArcEntity(AcDbEntity *pEnt)
{
AcDbArc *pArc(AcDbArc::cast(pEnt));
if (pArc == NULL)
return false;
return COMPARE_DOUBLE::equal(pArc->totalAngle(), PI, 1e-9);
}
// 删除 result1 / result2 中由 AecDbEwFitting 经 HLR 计算产生的、圆心角为 PI 的圆弧。
// result1 的键是数据库实体 id,直接判断该 id 是否为 AecDbEwFitting;
// result2 的键是无 id 的补充实体指针,需经 mpAdditional 反查归属的数据库实体 id 再判断。
void removeFittingDegenerateArcs(IDMapEntities &result1
, EntMapEntities &result2
, const IDMapEntities &mpAdditional)
{
IDMapEntities::iterator it(result1.begin());
for (; it != result1.end(); ++it)
{
if (!isFittingId(it->first))
continue;
for (int i(it->second.length() - 1); i >= 0; --i)
{
if (isDegenerateArcEntity(it->second[i]))
{
delete it->second[i];
it->second.removeAt(i);
}
}
}
EntMapEntities::iterator it2(result2.begin());
for (; it2 != result2.end(); ++it2)
{
if (!isFittingId(fittingIdOfResultKey(it2->first, mpAdditional)))
continue;
for (int i(it2->second.length() - 1); i >= 0; --i)
{
if (isDegenerateArcEntity(it2->second[i]))
{
delete it2->second[i];
it2->second.removeAt(i);
}
}
}
}
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);
// 删除由 AecDbEwFitting 经 HLR 计算产生的"退化"圆弧(圆心角溢出为 PI)。
removeFittingDegenerateArcs(result1, result2, mpAdditional);
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