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

1686 lines
42 KiB
C++

#include "StdAfx.h"
#include "AecDbJoggedCamera.h"
#include "MFCDbDwgFiler.h"
#include "CoreTools.h"
#include "simpleProperty.h"
#include "dbgrip.h"
#include "COMPARE_DOUBLE.h"
#include "hlrcutoption.h"
#define PIXEL_SIZE 4
namespace
{
struct sort_jogged
{
sort_jogged(const AcGeVector3d &vt) : m_vt(vt){}
AcGeVector3d m_vt;
bool operator()(const AecDbJoggedCamera::Camera *pCam1, const AecDbJoggedCamera::Camera *pCam2) const
{
AcGeLine3d line(AcGePoint3d::kOrigin, m_vt);
AcGePoint3d pt1 = line.closestPointTo(pCam1->getMidPoint());
AcGePoint3d pt2 = line.closestPointTo(pCam2->getMidPoint());
if ((pt1 - pt2).isCodirectionalTo(m_vt))
return false;
else
return true;
}
};
// 检查ptChk点,在直线(ptOrg, vt)上的投影点ptClosed在ptOrg的后方
bool checkPoint(const AcGePoint3d &ptOrg
, const AcGeVector3d &vt
, const AcGePoint3d &ptChk
, AcGePoint3d &ptClosed
, const bool &bAllowSame)
{
/*
->vt->
OK: ptOrg->->->ptClosed->->->
NO: ptClosed->->->ptOrg->->->
*/
AcGeLine3d line(ptOrg, vt);
ptClosed = line.closestPointTo(ptChk);
if (ptClosed.isEqualTo(ptOrg))
{
if (bAllowSame)
return true;
else
return false;
}
return (ptClosed - ptOrg).isCodirectionalTo(vt);
}
bool ptInnerSegment(const AcGePoint3d &pt, const AcGeLineSeg3d &seg)
{
double dParam;
double dStart = seg.paramOf(seg.startPoint());
double dEnd = seg.paramOf(seg.endPoint());
if (seg.isOn(pt, dParam))
{
if (dParam < dEnd && dParam > dStart)
return true;
}
return false;
}
bool isColinearAndOverlapping(AcGeLineSeg3d &seg1, AcGeLineSeg3d &seg2)
{
// 不共线,一定不重叠
if (!seg1.isColinearTo(seg2))
return false;
// 已经共线
// 如果seg2的起点或终点在seg1上,并且不在端点上,则认为两线段重叠
if (ptInnerSegment(seg2.startPoint(), seg1)
|| ptInnerSegment(seg2.endPoint(), seg1))
{
return true;
}
// 同上
if (ptInnerSegment(seg1.startPoint(), seg2)
|| ptInnerSegment(seg1.endPoint(), seg2))
{
return true;
}
// 再判断两个线段完全重合
if (seg1.startPoint().isEqualTo(seg2.startPoint())
&& seg1.endPoint().isEqualTo(seg2.endPoint()))
{
return true;
}
if (seg1.startPoint().isEqualTo(seg2.endPoint())
&& seg1.endPoint().isEqualTo(seg2.startPoint()))
{
return true;
}
return false;
}
bool isRegionOverlapping(AcGeLineSeg3d &seg1, AcGeLineSeg3d &seg2)
{
// 如果不平行,则认为区域一定重叠
if (!seg1.isParallelTo(seg2))
return true;
// 如果共线,则用isColinearAndOverlapping来判断
if (seg1.isColinearTo(seg2))
return isColinearAndOverlapping(seg1, seg2);
// 已经平行,但不共线,则判断两线段所在的区域是否重叠
// 让seg1两个端点seg2所在无限直线上投影,得到seg3
// 如果seg3与seg2重叠,则认为两线段所在的区域重叠
AcGeLine3d line(seg2.startPoint(), seg2.direction());
AcGePoint3d pt1 = line.closestPointTo(seg1.startPoint());
AcGePoint3d pt2 = line.closestPointTo(seg1.endPoint());
AcGeLineSeg3d seg3(pt1, pt2);
return isColinearAndOverlapping(seg2, seg3);
}
AcGeVector3d getViewDir()
{
AcGePoint3dArray pts;
struct resbuf rb;
acedGetVar(_T("viewdir"), &rb);
ads_point dirPt;
acdbUcs2Wcs(rb.resval.rpoint, dirPt, Adesk::kTrue);
return asVec3d(dirPt);
}
AcDbExtents getResultExtent(const AcDbObjectIdArray &ar)
{
AcDbExtents ext, _ext;
for (int i(0); i < ar.length(); ++i)
{
AcDbEntityPointer ent(ar[i], AcDb::kForRead);
if (ent.openStatus() == Acad::eOk)
{
ent->getGeomExtents(_ext);
ext.addExt(_ext);
}
}
return ext;
}
bool Grip_WorldDrawfunc(AcDbGripData *pThis,
AcGiWorldDraw *pWd,
const AcDbObjectId &entId,
AcDbGripOperations::DrawType type,
AcGePoint3d *cursor,
double dGripSize)
{
bool bHori(false);
AcGeVector3d vtNow(getViewDir());
if (vtNow.isCodirectionalTo(AcGeVector3d::kZAxis))
bHori = true;
// 画夹点
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 -= PIXEL_SIZE * dOne;
ptGe[1] = ptGrip;
ptGe[1].x += PIXEL_SIZE * dOne;
ptBox[0] = ptGe[0];
ptBox[0].y -= PIXEL_SIZE * dOne;
ptBox[1] = ptGe[0];
ptBox[1].y += PIXEL_SIZE * dOne;
ptBox[2] = ptGe[1];
ptBox[2].y += PIXEL_SIZE * dOne;
ptBox[3] = ptGe[1];
ptBox[3].y -= PIXEL_SIZE * dOne;
if (!bHori)
{
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);
////
// 每次取4个点
AcGePoint3d arFrame[5] = {};
pWd->subEntityTraits().setColor(9);
if (bHori)
{
for (int i(3); i < pGrip->m_arSelectFrame.length(); i += 4)
{
arFrame[0] = pGrip->m_arSelectFrame[i - 3];
arFrame[1] = pGrip->m_arSelectFrame[i - 2];
arFrame[2] = pGrip->m_arSelectFrame[i - 1];
arFrame[3] = pGrip->m_arSelectFrame[i];
pWd->geometry().polyline(4, arFrame);
}
}
else
{
// 8个一组,4个低点在前,4个高点在后
AcGePoint3d ptT1, ptT2, ptT3, ptT4, ptB1, ptB2, ptB3, ptB4;
// 8个点一起取
for (int i(7); i < pGrip->m_arSelectFrame.length(); i += 8)
{
// 4-7
ptT1 = pGrip->m_arSelectFrame[i - 3];
ptT2 = pGrip->m_arSelectFrame[i - 2];
ptT3 = pGrip->m_arSelectFrame[i - 1];
ptT4 = pGrip->m_arSelectFrame[i - 0];
// 0-3
ptB1 = pGrip->m_arSelectFrame[i - 7];
ptB2 = pGrip->m_arSelectFrame[i - 6];
ptB3 = pGrip->m_arSelectFrame[i - 5];
ptB4 = pGrip->m_arSelectFrame[i - 4];
arFrame[0] = ptT1;
arFrame[1] = ptT2;
arFrame[2] = ptT3;
arFrame[3] = ptT4;
arFrame[4] = ptT1;
pWd->geometry().polyline(5, arFrame);
arFrame[0] = ptB1;
arFrame[1] = ptB2;
arFrame[2] = ptB3;
arFrame[3] = ptB4;
pWd->geometry().polyline(4, arFrame);
arFrame[0] = ptT1;
arFrame[1] = ptB1;
pWd->geometry().polyline(2, arFrame);
arFrame[0] = ptT2;
arFrame[1] = ptB2;
pWd->geometry().polyline(2, arFrame);
arFrame[0] = ptT3;
arFrame[1] = ptB3;
pWd->geometry().polyline(2, arFrame);
arFrame[0] = ptT4;
arFrame[1] = ptB4;
pWd->geometry().polyline(2, arFrame);
}
}
// 画结果范围
if (pGrip->m_bDrawResultFrame && !pGrip->m_arResultFrame.isEmpty())
{
// 每次取4个点
for (int i(3), clr = 1; i < pGrip->m_arResultFrame.length(); i += 4, ++clr)
{
arFrame[0] = pGrip->m_arResultFrame[i - 3];
arFrame[1] = pGrip->m_arResultFrame[i - 2];
arFrame[2] = pGrip->m_arResultFrame[i - 1];
arFrame[3] = pGrip->m_arResultFrame[i];
arFrame[4] = arFrame[0];
// 颜色9保留
if (clr == 9) ++clr;
pWd->subEntityTraits().setColor(clr);
pWd->geometry().polyline(5, arFrame);
}
pWd->subEntityTraits().setColor(nOldColor);
}
return true;
}
void addGripData( const int &idxCamera
, const int &idxPoint
, const AcGePoint3d &pt
, AcArray<AecDbXCamera::GripData *> &gripDatas
, AcDbGripDataPtrArray &grips)
{
AecDbXCamera::GripData *gpd = new AecDbXCamera::GripData;
gpd->m_idx = idxCamera;
gpd->m_subIdx = idxPoint;
gpd->m_pt = pt;
AcDbGripData *pGripData = new AcDbGripData;
pGripData->setGripPoint(pt);
pGripData->setWorldDraw(Grip_WorldDrawfunc);
gripDatas.append(gpd);
pGripData->setAppData(gpd);
grips.append(pGripData);
}
}
#pragma region AecDbJoggedCamera::Camera
void AecDbJoggedCamera::Camera::getGripPoints(AcGePoint3dArray &ar) const
{
// 顺时针获取Grip点
/*
0-----1-----|
| |
5 6 2
| |
4-----3-----|
*/
AcGePoint3d pt0 = m_ptStart;
AcGePoint3d pt1 = pt0 + m_vtDir * .5;
AcGePoint3d pt5 = CoreTools::MidPt(m_ptStart, m_ptEnd);
AcGePoint3d pt2 = pt5 + m_vtDir;
AcGePoint3d pt3 = m_ptEnd + m_vtDir * .5;
AcGePoint3d pt4 = m_ptEnd;
AcGePoint3d pt6 = CoreTools::MidPt(pt5, pt2);
pt0.z = pt1.z = pt2.z = pt3.z = pt4.z = pt5.z = pt6.z = .0;
ar.append(pt0);
ar.append(pt1);
ar.append(pt2);
ar.append(pt3);
ar.append(pt4);
ar.append(pt5);
ar.append(pt6);
}
Acad::ErrorStatus AecDbJoggedCamera::Camera::dwgOutFields(AcDbDwgFiler * pFiler) const
{
Acad::ErrorStatus es;
es = pFiler->writeUInt32(AecDbJoggedCamera::Camera::kCurrentVersionNumber);
if (es != Acad::eOk)
return (es);
pFiler->writePoint3d(m_ptStart);
pFiler->writePoint3d(m_ptEnd);
pFiler->writeDouble(m_dMinElev);
pFiler->writeDouble(m_dMaxElev);
pFiler->writeVector3d(m_vtDir);
pFiler->writeInt16(m_iColor);
pFiler->writePoint3d(m_ptOutput);
pFiler->writeInt32(m_arResults.length());
for (int i(0); i < m_arResults.length(); ++i)
pFiler->writeSoftPointerId(m_arResults[i]);
return (pFiler->filerStatus());
}
Acad::ErrorStatus AecDbJoggedCamera::Camera::dwgInFields(AcDbDwgFiler * pFiler)
{
Acad::ErrorStatus es;
Adesk::UInt32 version = 0;
es = pFiler->readUInt32(&version);
if (es != Acad::eOk) return (es);
if (version > AecDbJoggedCamera::Camera::kCurrentVersionNumber) return (Acad::eMakeMeProxy);
pFiler->readPoint3d(&m_ptStart);
pFiler->readPoint3d(&m_ptEnd);
pFiler->readDouble(&m_dMinElev);
pFiler->readDouble(&m_dMaxElev);
pFiler->readVector3d(&m_vtDir);
pFiler->readInt16(&m_iColor);
pFiler->readPoint3d(&m_ptOutput);
if (version > 1)
{
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);
}
}
return (pFiler->filerStatus());
}
AcDbPolyline* AecDbJoggedCamera::Camera::getSectionPolygon() const
{
AcGePoint3dArray ar;
AcGePoint3d pt0(m_ptStart), pt1(m_ptEnd), pt2(m_ptEnd), pt3(m_ptStart);
pt0.z = pt1.z = m_dMinElev;
pt2.z = pt3.z = m_dMaxElev;
AcDbPolyline *pPoly = new AcDbPolyline();
AcGeVector3d vecNormal(m_vtDir.normal());
AcGeMatrix3d matWcs2Ocs;
matWcs2Ocs.setToWorldToPlane(vecNormal);
pt0.transformBy(matWcs2Ocs);
pt1.transformBy(matWcs2Ocs);
pt2.transformBy(matWcs2Ocs);
pt3.transformBy(matWcs2Ocs);
pPoly->setNormal(vecNormal);
pPoly->setElevation(pt0.z);
pPoly->addVertexAt(0, AcGePoint2d(pt0.x, pt0.y));
pPoly->addVertexAt(1, AcGePoint2d(pt1.x, pt1.y));
pPoly->addVertexAt(2, AcGePoint2d(pt2.x, pt2.y));
pPoly->addVertexAt(3, AcGePoint2d(pt3.x, pt3.y));
pPoly->addVertexAt(4, AcGePoint2d(pt0.x, pt0.y));
return pPoly;
}
void AecDbJoggedCamera::Camera::moveGripPointsAt(const int &_idx, const AcGeVector3d &offset)
{
AcGePoint3dArray arPts;
getGripPoints(arPts);
if (arPts.length() < 7) return;
int idx(_idx);
if (idx >= 100)
idx -= 100;
if (idx < 0 || idx >= arPts.length()) return;
AcGeVector3d X((arPts[1] - arPts[0]).normal());
AcGeVector3d Y((arPts[0] - arPts[4]).normal());
AcGePoint3d ptNew(arPts[idx] + offset), ptOnLine;
if (COMPARE_DOUBLE::equal_zero(ptNew.distanceTo(arPts[idx])))
return;
AcGeLine3d lineTop(arPts[0], arPts[0] + m_vtDir);
AcGeLine3d lineBottom(arPts[4], arPts[4] + m_vtDir);
AcGeLine3d lineLeft(arPts[0], arPts[4]);
AcGeLine3d lineRight(arPts[0] + m_vtDir, arPts[4] + m_vtDir);
AcGeVector3d vtNew, vtOld;
AcGeMatrix3d mat;
double dDist(.0), dAngle;
vtNew = ptNew - arPts[5];
switch (_idx)
{
case 0:
vtOld = -getJoggedDir();
dAngle = vtOld.angleTo(vtNew, AcGeVector3d::kZAxis);
m_vtDir.rotateBy(dAngle, AcGeVector3d::kZAxis);
dDist = m_ptStart.distanceTo(m_ptEnd) * .5;
m_ptStart = arPts[5] + vtNew.normal() * dDist;
m_ptEnd = arPts[5] - vtNew.normal() * dDist;
break;
case 4:
vtOld = getJoggedDir();
dAngle = vtOld.angleTo(vtNew, AcGeVector3d::kZAxis);
m_vtDir.rotateBy(dAngle, AcGeVector3d::kZAxis);
dDist = m_ptStart.distanceTo(m_ptEnd) * .5;
m_ptEnd = arPts[5] + vtNew.normal() * dDist;
m_ptStart = arPts[5] - vtNew.normal() * dDist;
break;
case 1: // 移动上端范围
if (offset.isParallelTo(X)) return;
ptOnLine = lineTop.closestPointTo(ptNew);
dDist = ptOnLine.distanceTo(ptNew);
vtNew = ptNew - ptOnLine;
if (!vtNew.isCodirectionalTo(Y))
dDist *= -1;
m_ptStart += Y * dDist;
break;
case 2: // 右侧范围左右移动
if (offset.isParallelTo(Y)) return;
ptOnLine = lineRight.closestPointTo(ptNew);
dDist = ptOnLine.distanceTo(ptNew);
vtNew = ptNew - ptOnLine;
if (!vtNew.isCodirectionalTo(X))
dDist *= -1;
m_vtDir = m_vtDir.normal() * (m_vtDir.length() + dDist);
break;
case 3: // 移动下端范围
if (offset.isParallelTo(X)) return;
ptOnLine = lineBottom.closestPointTo(ptNew);
dDist = ptOnLine.distanceTo(ptNew);
vtNew = ptNew - ptOnLine;
if (!vtNew.isCodirectionalTo(Y))
dDist *= -1;
m_ptEnd += Y * dDist;
break;
case 5: // 左侧范围左右移动
if (offset.isParallelTo(Y)) return;
ptOnLine = lineLeft.closestPointTo(ptNew);
dDist = ptOnLine.distanceTo(ptNew);
vtNew = ptNew - ptOnLine;
if (!vtNew.isCodirectionalTo(X))
dDist *= -1;
m_ptStart += X * dDist;
m_ptEnd += X * dDist;
m_vtDir = m_vtDir.normal() * (m_vtDir.length() - dDist);
break;
case 6: // 移动中点, 负责平移
mat.setToTranslation(offset);
m_ptStart.transformBy(mat);
m_ptEnd.transformBy(mat);
break;
case 101: // 移动顶点
ptNew = arPts[idx];
ptNew.z = m_dMaxElev;
ptNew += offset;
m_dMaxElev = ptNew.z;
if (m_dMinElev > m_dMaxElev)
std::swap(m_dMinElev, m_dMaxElev);
break;
case 100: // 移动底点
ptNew = arPts[idx];
ptNew.z = m_dMinElev;
ptNew += offset;
m_dMinElev = ptNew.z;
if (m_dMinElev > m_dMaxElev)
std::swap(m_dMinElev, m_dMaxElev);
break;
default:
break;
}
}
void AecDbJoggedCamera::Camera::collectEntities(AcDbObjectIdArray & ar)
{
struct resbuf *typelist = AecDbXCamera::getSelectTypeResbuf();
struct resbuf *pointlist = acutBuildList(RTPOINT, m_ptStart, RTPOINT, m_ptEnd,
RTPOINT, m_ptEnd + m_vtDir, RTPOINT, m_ptStart + m_vtDir, RTPOINT, m_ptStart, 0);
AecDbXCamera::collectEnities(typelist, pointlist, ar);
acutRelRb(pointlist);
acutRelRb(typelist);
}
void AecDbJoggedCamera::Camera::moveOutput(const AcGeVector3d &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);
}
}
void AecDbJoggedCamera::Camera::hlrCalc()
{
AecDbXCamera::eraseEnts(m_arResults);
AcDbObjectIdArray ar;
collectEntities(ar);
if (ar.isEmpty()) return;
AcDbPolyline *pSection(getSectionPolygon());
if (!pSection) return;
AecDbXCamera::AcDbEntityArray entAxis;
AecDbXCamera::IDMapEntities outputWithID; // 可以与数据库实体相关联的结果
AecDbXCamera::AcDbEntityArray outputWithoutID;// 不能与数据库实体相关联的结果
AecDbXCamera::hlrCalc(ar
, getMidPoint()
, m_vtDir
, getXDir()
, m_ptOutput
, pSection
, outputWithID
, outputWithoutID
, entAxis);
DELETE_PTR(pSection);
// 输出
AecDbXCamera::IDMapEntities::iterator it(outputWithID.begin());
AcDbObjectId id;
for (; 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);
}
}
#pragma endregion
#pragma region AecDbJoggedCamera
ACRX_DXF_DEFINE_MEMBERS(AecDbJoggedCamera, AecDbEntityBase,
AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent,
AcDbProxyEntity::kNoOperation | AcDbProxyEntity::kDisableProxyWarning,
AEC_JOGGEDCAMERA,
"AecDbJoggedCamera"
"|Product Desc: shanghua earthworm app obj"
"|Company: shanghua inc"
"|WEB Address: www.shanghuasoft.com")
Adesk::UInt32 AecDbJoggedCamera::kCurrentVersionNumber = 2;
Adesk::UInt32 AecDbJoggedCamera::Camera::kCurrentVersionNumber = 2;
AecDbJoggedCamera::AecDbJoggedCamera(): m_bSameSectionDir(false), m_bForcedParallel(false)
{
m_bSameSectionDir = HlrCutOption::getHlrZX_SameDir() == FALSE ? false : true;
m_bForcedParallel = HlrCutOption::getHlrZX_Parallel() == FALSE ? false : true;
}
AecDbJoggedCamera::AecDbJoggedCamera(AecDbJoggedCamera * pSrc)
{
copyFrom(pSrc);
}
AecDbJoggedCamera::~AecDbJoggedCamera()
{
deleteContainerOfArx<GripData>(m_GripDatas);
}
AecDbObjXDataMap * AecDbJoggedCamera::GetSpecialtyData(AcDb::OpenMode bMode)
{
if (bMode == AcDb::kForWrite)
AssertWriteEnabled();
else
assertReadEnabled();
return &m_mapSpecXData;
}
const AecDbObjXDataMap * AecDbJoggedCamera::GetSpecialtyData() const
{
assertReadEnabled();
return &m_mapSpecXData;
}
void AecDbJoggedCamera::subList() const
{
assertReadEnabled();
AecDbEntityBase::subList();
m_mapSpecXData.List();
}
Acad::ErrorStatus AecDbJoggedCamera::copyFrom(const AcRxObject * pSrc)
{
AssertWriteEnabled();
AecDbJoggedCamera *pCamera = AecDbJoggedCamera::cast(pSrc);
if (pCamera == NULL) return Acad::eInvalidInput;
m_mapSpecXData.CopyFrom(pCamera->GetSpecialtyData(AcDb::kForRead));
m_cameras = pCamera->m_cameras;
m_ptOutput = pCamera->m_ptOutput;
m_bSameSectionDir = pCamera->m_bSameSectionDir;
m_bForcedParallel = pCamera->m_bForcedParallel;
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::subTransformBy(const AcGeMatrix3d & xform)
{
AssertWriteEnabled();
AecDbEntityBase::subTransformBy(xform);
for (size_t i(0); i < m_cameras.size(); ++i)
{
Camera &cam = m_cameras[i];
cam.m_ptStart.transformBy(xform);
cam.m_ptEnd.transformBy(xform);
cam.m_vtDir.transformBy(xform);
}
// 剖切结果对齐点不移动
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::subGetGripPoints(AcDbGripDataPtrArray & grips
, const double curViewUnitSize
, const int gripSize
, const AcGeVector3d & curViewDir
, const int bitflags) const
{
assertReadEnabled();
AcGeVector3d vtZ(curViewDir);
bool bHori = vtZ.isParallelTo(AcGeVector3d::kZAxis) == Adesk::kFalse ? false : true;
deleteContainerOfArx<GripData>(m_GripDatas);
getGripPoints(bHori, grips);
getVirtualLine(bHori);
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::subMoveGripPointsAt(const AcDbVoidPtrArray & appData, const AcGeVector3d & offset, const int bitflags)
{
// 如果能进到这个函数,说明至少有一个Camera
AssertWriteEnabled();
if (appData.isEmpty()) return Acad::eOk;
GripData *pAppData = (GripData *)appData.first();
if (pAppData->m_idx == -1 && pAppData->m_subIdx == -1)
{
// 结果点
if (database())
moveOutput(offset);
}
else if ((pAppData->m_idx >= 0 && pAppData->m_idx < m_cameras.size()))
{
switch (pAppData->m_subIdx)
{
case 0: // 移动第一个点, 统一旋转
case 4:
{
AcGePoint3d ptNew = pAppData->m_pt + offset;
AcGeVector3d vtOld = m_cameras.begin()->getJoggedDir();
AcGePoint3d ptOther;
if (pAppData->m_subIdx == 0)
{
ptOther = m_cameras.begin()->getMidPoint();
vtOld *= -1;
}
else if (pAppData->m_subIdx == 4)
{
ptOther = m_cameras.rbegin()->getMidPoint();
}
AcGeVector3d vtNew = ptNew - ptOther;
double dA = vtOld.angleTo(vtNew, AcGeVector3d::kZAxis);
AcGeMatrix3d mat(AcGeMatrix3d::rotation(dA, AcGeVector3d::kZAxis, ptOther));
for (size_t i(0); i < m_cameras.size(); ++i)
m_cameras[i].transformBy(mat);
break;
}
case 101: // 顶点
{
for (size_t i(0); i < m_cameras.size(); ++i)
m_cameras[i].moveGripPointsAt(101, offset);
}
break;
case 100: // 底点
{
for (size_t i(0); i < m_cameras.size(); ++i)
m_cameras[i].moveGripPointsAt(100, offset);
}
break;
default:
{
AcGeVector3d vtOld(m_cameras[pAppData->m_idx].m_vtDir);
// 如果调整了1、6、3夹点,需要判断一下调整后的折线会不会和其他的相交
if (pAppData->m_subIdx == 1 || pAppData->m_subIdx == 3 || pAppData->m_subIdx == 6)
{
Camera cam = m_cameras[pAppData->m_idx];
cam.moveGripPointsAt(pAppData->m_subIdx, offset);
AcGeLineSeg3d seg1(cam.m_ptStart, cam.m_ptEnd), seg2;
for (size_t i(0); i < m_cameras.size(); ++i)
{
if (i == pAppData->m_idx) continue;
seg2.set(m_cameras[i].m_ptStart, m_cameras[i].m_ptEnd);
if (isRegionOverlapping(seg1, seg2))
return Acad::eInvalidInput;
}
m_cameras[pAppData->m_idx] = cam;
if (pAppData->m_subIdx == 1 || pAppData->m_subIdx == 3)
refreshOutputPoint();
}
else
{
m_cameras[pAppData->m_idx].moveGripPointsAt(pAppData->m_subIdx, offset);
}
// 新需求,各个剖切线的方向不需要统一
// 一个折线改变了方向,其他一起改变
if (database() && !vtOld.isCodirectionalTo(m_cameras[pAppData->m_idx].m_vtDir) && m_bSameSectionDir)
{
for (size_t i(0); i < m_cameras.size(); ++i)
{
if (i == pAppData->m_idx) continue;
m_cameras[i].m_vtDir *= -1;
}
refreshOutputPoint();
}
}
break;
}
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::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 > AecDbJoggedCamera::kCurrentVersionNumber)
return (Acad::eMakeMeProxy);
m_mapSpecXData.dwgInFields(pFiler);
pFiler->readPoint3d(&m_ptOutput);
int countOfCameras(0);
pFiler->readInt32((Adesk::Int32 *)&countOfCameras);
m_cameras.resize(countOfCameras);
for (size_t i(0); i < m_cameras.size(); ++i)
{
if (m_cameras[i].dwgInFields(pFiler) != Acad::eOk)
return (es);
}
if (version > 1)
{
pFiler->readBool(&m_bSameSectionDir);
pFiler->readBool(&m_bForcedParallel);
}
return (pFiler->filerStatus());
}
Acad::ErrorStatus AecDbJoggedCamera::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(AecDbJoggedCamera::kCurrentVersionNumber)) != Acad::eOk)
return (es);
m_mapSpecXData.dwgOutFields(pFiler);
pFiler->writePoint3d(m_ptOutput);
pFiler->writeInt32((Adesk::Int32)m_cameras.size());
for (size_t i(0); i < m_cameras.size(); ++i)
{
if (m_cameras[i].dwgOutFields(pFiler) != Acad::eOk)
return (es);
}
pFiler->writeBool(m_bSameSectionDir);
pFiler->writeBool(m_bForcedParallel);
return (pFiler->filerStatus());
}
Acad::ErrorStatus AecDbJoggedCamera::subGetGeomExtents(AcDbExtents & extents) const
{
for (size_t i(0); i < m_cameras.size(); ++i)
{
extents.addPoint(m_cameras[i].m_ptStart);
extents.addPoint(m_cameras[i].m_ptEnd);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::subGetOsnapPoints(AcDb::OsnapMode osnapMode
, INT_PTR gsSelectionMark
, const AcGePoint3d & pickPoint
, const AcGePoint3d & lastPoint
, const AcGeMatrix3d & viewXform
, AcGePoint3dArray & snapPoints
, AcDbIntArray & geomIds) const
{
assertReadEnabled();
AcGePoint3dArray ar;
for (size_t i(0); i < m_cameras.size(); ++i)
{
ar.removeAll();
m_cameras[i].getGripPoints(ar);
if (!ar.isEmpty())
snapPoints.append(ar);
}
return Acad::eOk;
}
Acad::ErrorStatus AecDbJoggedCamera::Draw2d(AcGiDraw & dc) const
{
assertReadEnabled();
// 颜色随层
Adesk::UInt16 oldClr = dc.GetColor();
AcDbObjectId oldLinetype = dc.GetLineTypeId();
double oldLineWidth = dc.GetLineWidth();
AcDbObjectId lTContinuous = CoreTools::GetLTypeId(_T("Continuous"));
AcDbObjectId lTCenter2 = CoreTools::GetLTypeId(_T("CENTER2"));
if (!lTContinuous.isValid())
lTContinuous = oldLinetype;
if (!lTCenter2.isValid())
lTCenter2 = lTContinuous;
dc.SetColor(256);
int iClr(0);
// 绘制剖切线
AcGePoint3d pt1, pt2;
for (size_t i(0); i < m_cameras.size(); ++i)
{
const Camera &cam = m_cameras[i];
pt1 = cam.m_ptStart;
pt2 = cam.m_ptEnd;
//pt1.z = pt2.z = (cam.m_ptStart.z + cam.m_ptEnd.z) * 0.5;
pt1.z = pt2.z = cam.m_dMinElev;
// 颜色随着索引变化, 方便在属性中对应修改
dc.SetColor(cam.m_iColor);
dc.SetLineType(lTContinuous);
dc.SetLineWidth(5.);
dc.DrawLine(AcGeLineSeg3d(pt1, pt2));
DrawElev(dc, cam, cam.m_iColor);
}
dc.SetColor(9);
for (size_t i(1); i < m_cameras.size(); ++i)
{
const Camera &cam0 = m_cameras[i-1];
const Camera &cam1 = m_cameras[i];
pt1 = cam0.m_ptEnd;
pt2 = cam1.m_ptStart;
pt1.z = cam0.m_dMinElev;
pt2.z = cam1.m_dMinElev;
dc.SetLineType(lTCenter2);
dc.SetLineWidth(1.);
dc.DrawLine(AcGeLineSeg3d(pt1, pt2));
}
dc.SetColor(oldClr);
dc.SetLineType(oldLinetype);
dc.SetLineWidth(oldLineWidth);
return Acad::eOk;
}
void AecDbJoggedCamera::DrawElev(AcGiDraw &dc, const Camera &cam, const int &iClr) const
{
assertReadEnabled();
int oldClr = dc.GetColor();
dc.SetColor(iClr);
const AcGePoint3d &pt1 = cam.m_ptStart;
const AcGePoint3d &pt2 = cam.m_ptEnd;
double dH(pt1.distanceTo(pt2) * .025);
AcGePoint3d ptIns = CoreTools::MidPt(pt1, pt2) - cam.m_vtDir.normal() * dH;
AcGeVector3d X = (pt2 - pt1).normalize();
double dRotation = AcGeVector3d::kXAxis.angleTo(X, AcGeVector3d::kZAxis);
CString sTop;
int prec(0);
sTop.Format(_T("%s , %s")
, TypeConvert::d2s(cam.m_dMaxElev, &prec)
, TypeConvert::d2s(cam.m_dMinElev, &prec));
AcDbText txt1;
AcDbExtents ext;
txt1.setTextString(sTop);
txt1.setPosition(ptIns);
txt1.setHeight(dH);
txt1.getGeomExtents(ext);
double dW = ext.maxPoint().x - ext.minPoint().x;
ptIns -= X * (dW * .5);
ptIns.z = cam.m_dMinElev;
txt1.setPosition(ptIns);
txt1.setRotation(dRotation);
dc.DrawEntity(txt1);
dc.SetColor(oldClr);
}
Acad::ErrorStatus AecDbJoggedCamera::Draw3d(AcGiDraw &dc) const
{
assertReadEnabled();
return Draw2d(dc);
}
void AecDbJoggedCamera::moveOutput(const AcGeVector3d & vtOffset)
{
assertWriteEnabled();
m_ptOutput += vtOffset;
refreshOutputPoint();
for (size_t i(0); i < m_cameras.size(); ++i)
m_cameras[i].moveOutput(vtOffset);
}
void AecDbJoggedCamera::getVirtualLine(const bool &bHori) const
{
assertReadEnabled();
// 第1个点作为绘制点,绘制虚框
GripData &first = *m_GripDatas.first();
first.m_mode = AecDbXCamera::eVerti;
first.m_arSelectFrame.removeAll();
AcGePoint3d pt1, pt2, pt3, pt4;
for (size_t i(0); i < m_cameras.size(); ++i)
{
const Camera &cam = m_cameras[i];
pt1 = cam.m_ptStart;
pt2 = cam.m_ptStart + cam.m_vtDir;
pt3 = cam.m_ptEnd + cam.m_vtDir;
pt4 = cam.m_ptEnd;
if (bHori)
{
pt1.z = pt2.z = pt3.z = pt4.z = .0;
// 4个点为一组
first.m_arSelectFrame.append(pt1);
first.m_arSelectFrame.append(pt2);
first.m_arSelectFrame.append(pt3);
first.m_arSelectFrame.append(pt4);
}
else
{
pt1.z = pt2.z = pt3.z = pt4.z = cam.m_dMinElev;
// 4个点为一组,低点在前,高点在后
first.m_arSelectFrame.append(pt1);
first.m_arSelectFrame.append(pt2);
first.m_arSelectFrame.append(pt3);
first.m_arSelectFrame.append(pt4);
pt1.z = pt2.z = pt3.z = pt4.z = cam.m_dMaxElev;
first.m_arSelectFrame.append(pt1);
first.m_arSelectFrame.append(pt2);
first.m_arSelectFrame.append(pt3);
first.m_arSelectFrame.append(pt4);
}
}
// 显示结果范围
AcGePoint3dArray ar;
if (getResultBox(ar))
{
GripData &first = *m_GripDatas.first();
first.m_bDrawResultFrame = true;
first.m_arResultFrame.append(ar);
}
}
bool AecDbJoggedCamera::getResultBox(AcGePoint3dArray &ar) const
{
assertReadEnabled();
AecDbXCamera::IDMapEntities result1;
AecDbXCamera::EntMapEntities result2;
AcGePoint3d pt;
int numVerts;
for (size_t i(0); i < m_cameras.size(); ++i)
{
const Camera *pCam(&m_cameras[i]);
AcDbPolyline *pPoly(pCam->getSectionPolygon());
if (!pPoly) continue;
AecDbXCamera::transfromHlrResult(pCam->getMidPoint()
, pCam->m_vtDir
, pCam->getXDir()
, pCam->m_ptOutput
, result1
, result2
, pPoly);
numVerts = pPoly->numVerts();
if (numVerts < 4)
{
DELETE_PTR(pPoly);
continue;
}
for (int j(0); j < 4; ++j)
{
pPoly->getPointAt(j, pt);
ar.append(pt);
}
DELETE_PTR(pPoly);
}
return ar.length() >= 4;
}
void AecDbJoggedCamera::refreshOutputPoint()
{
// 不重新计算
assertReadEnabled();
if (m_cameras.empty()) return;
// 得到 折线 排序的方向 "左" -> "右"
// 各个折线的中点沿着 vtSort 排序, 得到在m_ptOutput点沿水平方向展开的顺序
std::vector<Camera*> cameras;
for (size_t i(0); i < m_cameras.size(); ++i)
cameras.push_back(&m_cameras[i]);
std::sort(cameras.begin(), cameras.end(), sort_jogged(m_cameras.begin()->getXDir()));
double dAllLen(.0);
for (size_t i(0); i < m_cameras.size(); ++i)
dAllLen += m_cameras[i].getJoggedLength();
AcGePoint3d ptS(m_ptOutput - AcGeVector3d::kXAxis * dAllLen * .5);
AcGeVector3d vt;
double dLen(.0);
for (size_t i(0); i < cameras.size(); ++i)
{
vt = cameras[i]->getJoggedLength() * .5 * AcGeVector3d::kXAxis;
cameras[i]->m_ptOutput = ptS + vt;
ptS += 2 * vt;
}
}
void AecDbJoggedCamera::getGripPoints(const bool &bHori, AcDbGripDataPtrArray &grips) const
{
assertReadEnabled();
if (m_cameras.empty()) return;
if (bHori)
{
// 第一段起点,和第二段终点,其他段的中点
addGripData(0, 0, m_cameras.begin()->m_ptStart, m_GripDatas, grips);
int idx3(0);//上一个camera的第3个点的索引
AcGePoint3dArray pts;
double dOnePixel = CoreTools::PixelToWcs(1);
for (size_t i(0); i < m_cameras.size(); ++i)
{
const Camera &cam = m_cameras[i];
pts.removeAll();
cam.getGripPoints(pts);
// 共6个点
if (pts.length() < 7) continue;
// 每个camera的第pts[1]点可能和上一个camera的第pts[3]点重合
// 此时,应该把当前camera的第二个点向折线绘制方向移动一个夹点的距离
// 没插入pts[1]之前,m_GripDatas的最后一个点是上个camera的第pts[6]点
// 那么再上2个点就是需要比较的第pts[3]点
// 得到上个camera的第6个点
idx3 = m_GripDatas.length() - 3;
// 重合,移动一下pts[1],然后插入ar
if (idx3 > 0 && COMPARE_DOUBLE::equal_zero(m_GripDatas[idx3]->m_pt.distanceTo(pts[1])))
pts[1] += (cam.getJoggedDir()).normal() * PIXEL_SIZE * dOnePixel;
addGripData((int)i, 1, pts[1], m_GripDatas, grips);
addGripData((int)i, 2, pts[2], m_GripDatas, grips);
addGripData((int)i, 3, pts[3], m_GripDatas, grips);
addGripData((int)i, 5, pts[5], m_GripDatas, grips);
addGripData((int)i, 6, pts[6], m_GripDatas, grips);
}
addGripData((int)(m_cameras.size() - 1), 4, m_cameras.rbegin()->m_ptEnd, m_GripDatas, grips);
}
else
{ // 每段上中点和下中点,序号从100开始
// 改为只显示一个,用来统一修改标高
AcGePoint3d pt;
if (!m_cameras.empty())
{
const Camera &cam = *m_cameras.begin();
pt = CoreTools::MidPt(cam.m_ptStart, cam.m_ptEnd);
pt.z = cam.m_dMinElev;
addGripData((int)0, 100 + 0, pt, m_GripDatas, grips);
pt.z = cam.m_dMaxElev;
// 如果m_dMinElev == m_dMaxElev,说明没有高度差
// 上中点需要向上移动一个夹点的距离,避免和下中点重合
if (cam.m_dMinElev == cam.m_dMaxElev)
pt.z += PIXEL_SIZE * CoreTools::PixelToWcs(1);
addGripData((int)0, 100 + 1, pt, m_GripDatas, grips);
}
}
// 对齐点在最后一个
addGripData(-1, -1, m_ptOutput, m_GripDatas, grips);
}
AcGePoint3d AecDbJoggedCamera::getLastPoint() const
{
assertReadEnabled();
if (m_cameras.empty()) return AcGePoint3d::kOrigin;
return m_cameras.rbegin()->m_ptEnd;
}
AcGeVector3d AecDbJoggedCamera::getJoggedDir() const
{
assertReadEnabled();
AcGeVector3d vt(AcGeVector3d::kIdentity);
if (m_cameras.empty()) return vt;
return m_cameras[0].getJoggedDir();
}
AcGeVector3d AecDbJoggedCamera::getSectionDir() const
{
assertReadEnabled();
AcGeVector3d vt(AcGeVector3d::kIdentity);
if (m_cameras.empty()) return vt;
return m_cameras[0].m_vtDir;
}
void AecDbJoggedCamera::delCamera(const int & idx)
{
AssertWriteEnabled();
if (idx < 0 || idx >= m_cameras.size()) return;
Cameras::iterator it(m_cameras.begin());
std::advance(it, idx);
m_cameras.erase(it);
}
const AecDbJoggedCamera::Camera* AecDbJoggedCamera::getCamera(const int & idx) const
{
assertReadEnabled();
if (idx < 0 || idx >= m_cameras.size()) return NULL;
return &m_cameras[idx];
}
void AecDbJoggedCamera::setCameraHeight(const int & idx, const double & dMax, const double & dMin)
{
AssertWriteEnabled();
if (idx < 0 || idx >= m_cameras.size()) return;
Camera &cam(m_cameras[idx]);
if (COMPARE_DOUBLE::equal(dMax, dMin))
{
cam.setElev(1000., 0.);
return;
}
cam.setElev(dMax, dMin);
if (cam.m_dMaxElev < cam.m_dMinElev)
std::swap(cam.m_dMaxElev, cam.m_dMinElev);
}
void AecDbJoggedCamera::setCameraWidth(const int & idx, const AcGePoint3d &ptOut)
{
AssertWriteEnabled();
if (idx < 0 || idx >= m_cameras.size()) return;
Camera &cam(m_cameras[idx]);
AcGePoint3d ptOn = getClosestPoint(cam.m_ptStart, cam.m_ptEnd, ptOut);
double dist(ptOn.distanceTo(ptOut));
if (COMPARE_DOUBLE::equal_zero(dist))
dist = 1000.;
else
{
if (!(ptOut - ptOn).isCodirectionalTo(cam.m_vtDir))
dist *= -1;
}
cam.m_vtDir.normalize();
cam.m_vtDir *= dist;
// 如果不是第一段折线,那么其他的剖切方向都要和第一段一致
if (idx != 0 && !cam.m_vtDir.isCodirectionalTo(m_cameras.begin()->m_vtDir))
cam.m_vtDir *= -1;
}
bool AecDbJoggedCamera::isOverlappingCamera(const int & idx) const
{
assertReadEnabled();
return false;
}
AcGePoint3d AecDbJoggedCamera::getClosestPoint(const AcGePoint3d & ptOn1, const AcGePoint3d & ptOn2, const AcGePoint3d & ptOut)
{
AcGeLine3d line(ptOn1, ptOn2);
return line.closestPointTo(ptOut);
}
AcGePoint3d AecDbJoggedCamera::getClosestPoint(const AcGePoint3d & ptOn, const AcGeVector3d & vt, const AcGePoint3d & ptOut)
{
AcGeLine3d line(ptOn, vt);
return line.closestPointTo(ptOut);
}
void AecDbJoggedCamera::setOutputPoint(const AcGePoint3d & pt)
{
moveOutput(pt - m_ptOutput);
}
bool AecDbJoggedCamera::judgeSegmentCanInsert(const AcGePoint3d &pt1, const AcGePoint3d &pt2, AcGePoint3d &ptClosed) const
{
// 这些子折线,都互相平行,
// 可以共线,不能重合
// 也就是说,这些Camera的m_vtDir方向都相同
if (m_cameras.empty()) return true;
const Camera LastCam = *m_cameras.rbegin();
AcGeVector3d vtDir(LastCam.getJoggedDir());
// 检查第1个点
if (!checkPoint(LastCam.m_ptEnd, vtDir, pt1, ptClosed, true)) return false;
// 检查第2个点
if (!checkPoint(pt1, vtDir, pt2, ptClosed, false)) return false;
return true;
}
bool AecDbJoggedCamera::addCamera(const AcGePoint3d &_pt1
, const AcGePoint3d &_pt2
, const AcGeVector3d &vt)
{
AssertWriteEnabled();
if (m_cameras.empty())
{
m_cameras.push_back(Camera(_pt1, _pt2));
m_cameras.rbegin()->m_vtDir = vt;
m_cameras.rbegin()->m_iColor = 1;
return true;
}
AcGePoint3d ptClosed;
if (!judgeSegmentCanInsert(_pt1, _pt2, ptClosed))
return false;
Camera &lastCam = m_cameras.back();
// 通过judgeSegmentCanInsert检查后,如果pt1-pt2的方向与
// 其他Camera的m_ptStart-m_ptEnd方向不一致,改变方向即可插入
AcGePoint3d pt1 = _pt1, pt2 = _pt2;
if (!lastCam.getJoggedDir().isCodirectionalTo(pt2 - pt1))
std::swap(pt1, pt2);
// 以上条件都满足,不需要判断方向,使用统一的方向,但要得到矢量的长度
m_cameras.push_back(Camera(pt1, pt2));
// 方向改为任意,不需要统一
//m_cameras.rbegin()->m_vtDir = m_cameras.begin()->m_vtDir.normal() * vt.length();
m_cameras.rbegin()->m_vtDir = vt;
// 根据索引设置颜色
if (lastCam.m_iColor == 8)
m_cameras.rbegin()->m_iColor = 10; // 颜色9保留
else
m_cameras.rbegin()->m_iColor = lastCam.m_iColor + 1;
return true;
}
bool AecDbJoggedCamera::GetProperties(SimpleProperty::PropertySetByIndex & properties) const
{
assertReadEnabled();
CString sIndex;
// 上下标高永远用第一段剖切线的
if (m_cameras.empty()) return false;
const Camera &cam = *m_cameras.begin();
SimpleProperty::makeAndInsert(properties, _T("剖切范围上标高"), cam.m_dMaxElev, true);
SimpleProperty::makeAndInsert(properties, _T("剖切范围下标高"), cam.m_dMinElev, true);
for (size_t i(0); i < m_cameras.size(); ++i)
{
const Camera &cam = m_cameras[i];
sIndex.Format(_T("折线%d-剖切宽度"), i + 1);
SimpleProperty::makeAndInsert(properties, sIndex, cam.m_vtDir.length(), true, cam.m_iColor);
}
return true;
}
bool AecDbJoggedCamera::SetProperties(SimpleProperty::PropertySetByName & properties)
{
AssertWriteEnabled();
// 处理 上下标高
if (m_cameras.empty()) return false;
// 按照原始值初始化,哪怕界面上没有修改数值,也能保证数据的正确性
double dMax(m_cameras.begin()->m_dMaxElev), dMin(m_cameras.begin()->m_dMinElev);
properties.findAndSet(_T("剖切范围上标高"), dMax);
properties.findAndSet(_T("剖切范围下标高"), dMin);
if (dMax < dMin)
{
// 交换
std::swap(dMax, dMin);
}
double dVal;
CString sPropertyName(_T(""));
for (size_t i(0); i < m_cameras.size(); ++i)
{
sPropertyName.Format(_T("折线%d-剖切宽度"), i + 1);
if (properties.findAndSet(sPropertyName, dVal))
{
if (dVal < 10.)
{
acutPrintf(_T("\n剖切宽度不能小于10,已自动调整为10。"));
dVal = 10.;
}
m_cameras[i].m_vtDir = m_cameras[i].m_vtDir.normal() * dVal;
}
m_cameras[i].m_dMaxElev = dMax;
m_cameras[i].m_dMinElev = dMin;
}
return true;
}
void AecDbJoggedCamera::refresh()
{
for (size_t i(0); i < m_cameras.size(); ++i)
{
m_cameras[i].hlrCalc();
}
}
#pragma endregion
#pragma region JoggedJig
AcEdJig::DragStatus CJoggedCameraJig::DoIt()
{
m_pPolyline = new AcDbPolyline();
m_pPolyline->setNormal(AcGeVector3d::kZAxis);
m_pPolyline->setElevation(.0);
AcEdJig::DragStatus stat;
AcGePoint3d ptClosest;
AcDbObjectId subid;
while (true)
{
setDispPrompt(_T("\n选取第%d段剖切线的起点:"), m_numOfSeg + 1);
stat = drag();
if (stat == AcEdJig::kNull || stat == AcEdJig::kCancel)
{
deleteSupportLine();
return stat;
}
if (m_pJogged->getCameraCount() == 0)
{
++m_nStep;
break;
}
else
{
if (m_pJogged->judgeSegmentCanInsert(m_ptStart, m_ptStart + m_pJogged->getJoggedDir().normal() * 10, ptClosest))
{
++m_nStep;
deleteSupportLine();
AcDbLine *pLine = new AcDbLine(m_ptStart, m_pJogged->getLastPoint());
pLine->setColorIndex(9);
m_supportLineID = CoreTools::AddToModelSpace(pLine, true);
break;
}
acutPrintf(_T("\n剖切线的起点不能和已有的剖切线区域重叠,请重新拾取!"));
}
}
while (true)
{
setDispPrompt(_T("\n选取第%d段剖切线的终点:"), m_numOfSeg + 1);
stat = drag();
if (stat == AcEdJig::kNull || stat == AcEdJig::kCancel)
{
deleteSupportLine();
return stat;
}
if (m_pJogged->getCameraCount() == 0)
{
++m_nStep;
break;
}
else
{
if (m_pJogged->judgeSegmentCanInsert(m_ptStart, m_ptEnd, ptClosest))
{
if (m_pJogged->isForcedParallel())
m_ptEnd = ptClosest;
++m_nStep;
break;
}
acutPrintf(_T("\n剖切线的终点必须在上个剖切线终点和当前剖切线起点的延长线上,请重新拾取!"));
}
}
setDispPrompt(_T("\n选取第%d段剖切线的方向和范围:"), m_numOfSeg + 1);
stat = drag();
deleteSupportLine();
if (stat == AcEdJig::kNull || stat == AcEdJig::kCancel) return stat;
++m_nStep;
return stat;
}
AcEdJig::DragStatus CJoggedCameraJig::sampler()
{
AcEdJig::DragStatus stat;
setUserInputControls((UserInputControls) (AcEdJig::kAccept3dCoordinates | AcEdJig::kNullResponseAccepted ));
m_pPolyline->reset(false, 0);
if (m_nStep == 0)
{
if (m_numOfSeg != 0)
{
static AcGePoint3d pt0;
AcGePoint3d ptPrev(m_pJogged->getLastPoint());
stat = acquirePoint(m_ptStart, ptPrev);
if (m_ptStart != pt0)
pt0 = m_ptStart;
else if (stat == AcEdJig::kNormal)
return AcEdJig::kNoChange;
}
else
stat = acquirePoint(m_ptStart);
}
else if (m_nStep == 1)
{
static AcGePoint3d pt1;
stat = acquirePoint(m_ptEnd, m_ptStart);
// 当shfit按下时,或者"强制平行"被设置时
bool bShiftPressed = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0 || m_pJogged->isForcedParallel();
if (m_ptEnd != pt1)
pt1 = m_ptEnd;
else if (stat == AcEdJig::kNormal)
return AcEdJig::kNoChange;
if (m_ptEnd.isEqualTo(m_ptStart))
return AcEdJig::kNoChange;
if (bShiftPressed && m_numOfSeg != 0)
{
AcGeVector3d vt = m_pJogged->getJoggedDir();
AcGeLine3d ln(m_ptStart, vt.normal());
m_ptEnd = ln.closestPointTo(m_ptEnd);
}
}
else
{
double dDist(.0);
AcGePoint3d ptMid(CoreTools::MidPt(m_ptStart, m_ptEnd));
if (m_numOfSeg == 0 || !m_pJogged->isSameSectionDir())
{
static AcGePoint3d pt2;
AcGePoint3d ptDir;
stat = acquirePoint(ptDir, ptMid);
if (ptDir != pt2)
pt2 = ptDir;
else if (stat == AcEdJig::kNormal)
return AcEdJig::kNoChange;
AcGeLine3d line(m_ptStart, m_ptEnd);
AcGePoint3d ptOnLine(line.closestPointTo(ptDir));
dDist = ptOnLine.distanceTo(ptDir);
m_vtEye = ptDir - ptOnLine;
}
else
{
stat = acquireDist(dDist, ptMid);
m_vtEye = m_vtEye.normal() * dDist;
}
}
return stat;
}
AcDbEntity *CJoggedCameraJig::entity() const
{
return m_pPolyline;
}
Adesk::Boolean CJoggedCameraJig::update()
{
double dw = CoreTools::PixelToWcs(10);
switch (m_nStep)
{
case 0:
break;
case 1:
{
m_pPolyline->addVertexAt(0, m_ptStart.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(1, m_ptEnd.convert2d(AcGePlane::kXYPlane));
}
break;
case 2:
{
AcGePoint3d ptCloset;
m_pPolyline->addVertexAt(0, m_ptStart.convert2d(AcGePlane::kXYPlane), .0, dw, dw);
m_pPolyline->addVertexAt(1, m_ptEnd.convert2d(AcGePlane::kXYPlane));
m_pPolyline->addVertexAt(2, (m_ptEnd + m_vtEye).convert2d(AcGePlane::kXYPlane));
m_pPolyline->addVertexAt(3, (m_ptStart + m_vtEye).convert2d(AcGePlane::kXYPlane));
m_pPolyline->setClosed(Adesk::kTrue);
}
break;
case 3:
break;
default:
break;
}
return Adesk::kTrue;
}
void CJoggedCameraJig::deleteSupportLine()
{
AcDbEntityPointer entLine(m_supportLineID, AcDb::kForWrite);
if (entLine.openStatus() == Acad::eOk)
entLine->erase();
}
#pragma endregion