Files
envi-code/SourceCode/Code2026/tg_shs/shs_kernal/DbPolyPathEnt.cpp
T
2026-09-28 15:28:50 +08:00

718 lines
20 KiB
C++

#include "stdafx.h"
ACRX_NO_CONS_DEFINE_MEMBERS(ATSPolyPathEnt, ATSEntity);
const Adesk::UInt8 TDbPolyPathEnt::g_nVersion = 2;
TDbPolyPathEnt::TDbPolyPathEnt()
{
}
TDbPolyPathEnt::~TDbPolyPathEnt()
{
}
BOOL TDbPolyPathEnt::IsValid() const
{
BOOL bRet=TDbEntity::IsValid();
if(!bRet)
return bRet;
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
bRet=(polyPath.Length()>1);
return bRet;
}
// 提供对格式刷的支持
void TDbPolyPathEnt::CopyPropertiesFrom(AcDbEntity *pSrcEntity, unsigned gMatchFlag)
{
assertWriteEnabled();
TDbEntity::CopyPropertiesFrom(pSrcEntity, gMatchFlag);
TDbPolyPathEnt *pSrc=TDbPolyPathEnt::cast(pSrcEntity);
if(pSrc) {
}
}
Acad::ErrorStatus
TDbPolyPathEnt::dwgInFields (AcDbDwgFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es = TDbEntity::dwgInFields(pFiler);
if(es != Acad::eOk) return es;
Adesk::UInt8 nVer;
pFiler->readItem(&nVer);
if(nVer>g_nVersion) {// Version is too new
return Acad::eMakeMeProxy;
}
pFiler->readItem(&m_idBind);
return pFiler->filerStatus();
}
Acad::ErrorStatus
TDbPolyPathEnt::dwgOutFields(AcDbDwgFiler* pFiler) const
{
assertReadEnabled();
Acad::ErrorStatus es = TDbEntity::dwgOutFields(pFiler);
if(es != Acad::eOk) return es;
pFiler->writeItem(g_nVersion);
pFiler->writeItem(m_idBind);
return pFiler->filerStatus();
}
Acad::ErrorStatus TDbPolyPathEnt::dxfInFields (AcDbDxfFiler* pFiler)
{
assertWriteEnabled();
Acad::ErrorStatus es= TDbEntity::dxfInFields(pFiler);
if(es!=Acad::eOk)
return es;
if (!pFiler->atSubclassData(_T("TDbPolyPathEnt"))) {
return Acad::eBadDxfSequence;
}
return pFiler->filerStatus();
// 不读入任何数据
}
Acad::ErrorStatus TDbPolyPathEnt::dxfOutFields(AcDbDxfFiler* pFiler) const
{
assertReadEnabled();
Acad::ErrorStatus es;
es = TDbEntity::dxfOutFields(pFiler);
assert(es == Acad::eOk);
es = pFiler->writeItem(AcDb::kDxfSubclass,_T("TDbPolyPathEnt"));
assert(es == Acad::eOk);
return es;
}
// -----------------------------------------------------------------------
Acad::ErrorStatus
TDbPolyPathEnt::subGetOsnapPoints(
AcDb::OsnapMode osnapMode,
INT_PTR gsSelectionMark,
const AcGePoint3d& ptPick,
const AcGePoint3d& lastPoint,
const AcGeMatrix3d& viewXform,
AcGePoint3dArray& snapPoints,
AcDbIntArray& geomIds) const
{
assertReadEnabled();
if(osnapMode==AcDb::kOsModeNode) {
XVector3D vtNormal=GetNormal();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
for(int i=0; i<polyPath.Length(); i++) {
snapPoints.append(Ecs2Wcs(*polyPath[i], vtNormal).AsAcGePoint3d());
}
return Acad::eOk;
}
return TDbEntity::subGetOsnapPoints(osnapMode, gsSelectionMark,
ptPick, lastPoint, viewXform, snapPoints, geomIds);
}
// Overriden functions for edit
// to do:
// 对于自定义柱子,应当允许通过夹点改变边界
Acad::ErrorStatus TDbPolyPathEnt::subGetGripPoints(AcGePoint3dArray& gripPoints,
AcDbIntArray& osnapModes,
AcDbIntArray& geomIds) const
{
assertReadEnabled();
AcGeVector3d vtNormal;
XPoly2D polyPath;
GetPathPoly(polyPath,vtNormal);
if(!IsBind()) {
int nVertexCount=polyPath.Length();
for(int i=0; i<nVertexCount; i++) {
XPoint ptWcs=Ecs2Wcs(*polyPath[i], vtNormal);
gripPoints.append(ptWcs);
}
//边上的夹点
int nEdgeNum=polyPath.TotalSegments();
for(i=0; i<nEdgeNum; i++) {
XCurveSegment seg;
polyPath.Nth(i, seg);
XPoint ptMid=Ecs2Wcs(seg.MidPoint(), vtNormal);
gripPoints.append(ptMid);
}
}
return Acad::eOk;
}
// stretch points is diffrent from grep points, with no midpoint included
Acad::ErrorStatus TDbPolyPathEnt::subGetStretchPoints(AcGePoint3dArray & stretchPoints) const
{
assertReadEnabled();
if(!IsBind()) {
AcGeVector3d vtNormal;
XPoly2D polyPath;
GetPathPoly(polyPath,vtNormal);
int nVertexCount=polyPath.Length();
for(int i=0; i<nVertexCount; i++) {
XPoint ptWcs=Ecs2Wcs(*polyPath[i], vtNormal);
stretchPoints.append(ptWcs);
}
}
return Acad::eOk;
}
void
TDbPolyPathEnt::GetLocalMatrix(const AcGeMatrix3d& xform, ads_matrix &mat) const
{
assertReadEnabled();
XVector3D vtNormal=GetNormal();
double nElev=0.0;
AcGeMatrix2d xform2d(xform.convertToLocal(vtNormal,nElev));
ads_matrix mat0={{xform2d(0,0), xform2d(0,1), 0, xform2d(0,2)},
{xform2d(1,0), xform2d(1,1), 0, xform2d(1,2)},
{0,0,1, nElev},
{0,0,0,1}};
memcpy(mat, mat0, sizeof(ads_matrix));
}
//////////////////////////////////////////////////////////////
// Active when being rotated, scaled, moved, etc.
Acad::ErrorStatus TDbPolyPathEnt::subTransformBy(const AcGeMatrix3d& xform)
{
assertWriteEnabled();
TDbEntity::subTransformBy(xform);
if(!IsBind()) {
AcGeVector3d vtNormal;
XPoly2D polyPath;
GetPathPoly(polyPath,vtNormal);
ads_matrix mat;
GetLocalMatrix(xform, mat);
double nElev=0.0;
AcGeMatrix2d xform2d(xform.convertToLocal(vtNormal,nElev));
((AcGeVector3d &)vtNormal).normalize();
for(int i=0; i<polyPath.Length(); i++)
polyPath[i]->TransformBy(mat);
// Modify on 2002/1/30 纠正弧段转角错误
if(IsMirrorMatrix(mat))
{
for(int m=0; m<polyPath.Length(); m++)
{
polyPath.SetBulge(m, -polyPath.GetBulge(m));
}
}
SetPathPoly(polyPath,vtNormal);
}
return Acad::eOk;
}
///////////////////////////////////////////
// 功能: 夹点操作
Acad::ErrorStatus TDbPolyPathEnt::subMoveGripPointsAt(
const AcDbIntArray& indices,
const AcGeVector3d& offset)
{
assertWriteEnabled();
if(IsBind())
return Acad::eOk;
XVector3D vtNormal;
XPoly2D polyPath;
GetPathPoly(polyPath,vtNormal);
int nVertexCount=polyPath.Length();
XPoint vtOffset=Wcs2Ecs(*(XPoint *)&offset, vtNormal);
for (int i = 0; i < indices.length(); i++) {
int idx = indices[i];
if(idx<nVertexCount) { // Move vertex
*polyPath[idx] += vtOffset;
} else { // Move Edge or Shape
XPoly2D poly2d(polyPath);
poly2d.SetElevation(0.0);
int nEdgeIndex=idx-nVertexCount;
int nTotalEdge=poly2d.TotalSegments();
if(nEdgeIndex<nTotalEdge) { //移动边
XDirectionCurve cv;
poly2d.Nth(nEdgeIndex, cv);
ASSERT(!!cv);
if(cv.Is(CURVE_LINE)) { // Move
XLine ln=cv.GetLine();
ln.StartPoint() += vtOffset;
ln.EndPoint() += vtOffset;
ln.SetLineFlag(LS_INFINITE);
XDirectionCurve prevSeg, nextSeg;
int nPrev=nEdgeIndex-1, nNext=nEdgeIndex+1;
if(poly2d.IsClosed()) {
nPrev=DePeriod(nTotalEdge, nPrev);
nNext=DePeriod(nTotalEdge, nNext);
}
XPoint ptStart, ptEnd;
BOOL bUpdateIt=TRUE;
//更新起点
if(nPrev>=0 && nPrev<nTotalEdge) {
poly2d.Nth(nPrev, prevSeg);
prevSeg.SetLineFlag(LS_INFINITE);
XPoint ptInt[2];
int nIntNum=prevSeg.Intersection(ln, ptInt[0], ptInt[1]);
if(nIntNum==1) ptStart=ptInt[0];
else if(nIntNum==2) {
ptStart=XLine(ptInt[0], ptInt[1]).NearPoint(ln.StartPoint());
} else bUpdateIt=FALSE;
} else {
ptStart = *poly2d[nEdgeIndex] + vtOffset;
}
// 更新下一点
if(nNext>=0 && nNext<nTotalEdge) {
poly2d.Nth(nNext, nextSeg);
nextSeg.SetLineFlag(LS_INFINITE);
XPoint ptInt[2];
int nIntNum=nextSeg.Intersection(ln, ptInt[0], ptInt[1]);
if(nIntNum==1) ptEnd=ptInt[0];
else if(nIntNum==2) {
ptEnd=XLine(ptInt[0], ptInt[1]).NearPoint(ln.EndPoint());
} else bUpdateIt=FALSE;
} else {
ptEnd = *poly2d[nEdgeIndex+1] + vtOffset;
}
if(bUpdateIt) {
double nPrevBulge=0.0, nNextBulge=0.0;
if(fabs(prevSeg.GetBulge())>1.0E-5) {
XArc prevArc=prevSeg.GetArc();
double nAngBeg=ads_angle(prevArc.GetCenterPt(), prevSeg.StartPoint());
double nAngEnd=ads_angle(prevArc.GetCenterPt(), ptStart);
if(prevSeg.IsMinusArc()) {
nPrevBulge=-CT_std_angle(nAngBeg-nAngEnd);
} else {
nPrevBulge=CT_std_angle(nAngEnd-nAngBeg);
}
}
if(fabs(nextSeg.GetBulge())>1.0E-5) {
XArc nextArc=nextSeg.GetArc();
double nAngBeg=ads_angle(nextArc.GetCenterPt(), ptEnd);
double nAngEnd=ads_angle(nextArc.GetCenterPt(), nextSeg.EndPoint());
if(nextSeg.IsMinusArc()) {
nNextBulge=-CT_std_angle(nAngBeg-nAngEnd);
} else {
nNextBulge=CT_std_angle(nAngEnd-nAngBeg);
}
}
*poly2d[nEdgeIndex] = ptStart;
if(nNext>=0 && nNext<poly2d.Length())
{
*poly2d[nNext] = ptEnd;
poly2d.SetBulge(nNext, nNextBulge);
}
if(nPrev>=0 && nPrev<poly2d.Length())
{
poly2d.SetBulge(nPrev, nPrevBulge);
}
}
} else { // Change Arc Segment--bulge
XPoint ptMid=cv.MidPoint();
XPoint ptMidNew= ptMid + vtOffset;
XArc arNew(cv.StartPoint(), ptMidNew, cv.EndPoint());
if(!!arNew) { //新的弧有效
XCurveSegment cvLine(cv.StartPoint(), cv.EndPoint(), 0.0);
int nSideOld=cvLine.OnWhichSide(ptMid);
int nSideNew=cvLine.OnWhichSide(ptMidNew);
double nSignal=cv.GetBulge()/fabs(cv.GetBulge());
if(nSideOld==nSideNew)
{
poly2d.SetBulge(nEdgeIndex, nSignal*arNew.Bulge());
}
else
{
poly2d.SetBulge(nEdgeIndex, -nSignal*arNew.Bulge());
}
}
}
for(int n=0; n<poly2d.Length(); n++) {
poly2d[n]->z = polyPath[n]->z;
}
polyPath = poly2d;
}
}
}
SetPathPoly(polyPath,vtNormal);
return Acad::eOk;
}
////////////////////////////////////////////////////////
// 功能: 夹点操作
Acad::ErrorStatus TDbPolyPathEnt::subMoveStretchPointsAt(
const AcDbIntArray& indices,
const AcGeVector3d& offset)
{
assertWriteEnabled();
if(IsBind())
return Acad::eOk;
AcGeVector3d vtNormal;
XPoly2D polyPath;
GetPathPoly(polyPath,vtNormal);
int nVertexCount=polyPath.Length();
XPoint vtOffset=Wcs2Ecs(*(XPoint *)&offset, vtNormal);
for (int i = 0; i < indices.length(); i++) {
int idx = indices[i];
if(idx<nVertexCount) // Move vertex
*polyPath[idx] += vtOffset;
}
SetPathPoly(polyPath,vtNormal);
return Acad::eOk;
}
// 取得夹点说明
Acad::ErrorStatus TDbPolyPathEnt::GetGripText(int idx, CString &cs) const
{
assertReadEnabled();
Acad::ErrorStatus es=Acad::eNotApplicable;
if(IsBind())
return Acad::eNotApplicable;
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
int nVertexCount=polyPath.Length();
if(idx<nVertexCount) { // Move vertex
cs.Format(_T("移动第%d个顶点"), idx+1);
es = Acad::eOk;
} else { // Move Edge or Shape
int nEdgeIndex=idx-nVertexCount;
int nTotalEdge=polyPath.TotalSegments();
if(nEdgeIndex<nTotalEdge) { //移动边
cs.Format(_T("移动第%d条边"), nEdgeIndex+1);
es = Acad::eOk;
}
}
return es;
}
Acad::ErrorStatus
TDbPolyPathEnt::subDeepClone(AcDbObject* pOwner,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary) const
{
Acad::ErrorStatus es=TDbEntity::subDeepClone(pOwner, pClonedObject, idMap, isPrimary);
if(es!=Acad::eOk || !m_idBind)
return es;
TDbPolyPathEnt *pClonedEnvelop = TDbPolyPathEnt::cast(pClonedObject);
ASSERT(pClonedEnvelop);
pClonedEnvelop->m_idBind = AcDbObjectId::kNull;
return Acad::eOk;
}
/* ----------------------------------------------------------------------- */
//////////////////////////////////////////////////////////////////////
// derived from AcDbObject, Reactor的唤醒函数
// INSERT实体要被删除/恢复
void TDbPolyPathEnt::erased(const AcDbObject* pDbObj, Adesk::Boolean erasing)
{
if(pDbObj->objectId()==m_idBind && !isWriteEnabled() && isNotifyEnabled()) {
Adesk::Boolean wasWritable;
VERIFY(upgradeFromNotify(wasWritable)==Acad::eOk);
assertWriteEnabled();
m_idBind=NULL;
//erase(erasing);
//UnBind();
VERIFY(downgradeToNotify(wasWritable)==Acad::eOk);
}
}
// 绊定的实体发生变化
void TDbPolyPathEnt::modified(const AcDbObject* pDbObj)
{
if(pDbObj->objectId()==m_idBind && !isWriteEnabled() && isNotifyEnabled()) {
const TEntityBase *pMaster = TEntityBase::Cast(pDbObj);
if(pMaster) {
Adesk::Boolean wasWritable;
VERIFY(upgradeFromNotify(wasWritable)==Acad::eOk);
assertWriteEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
pMaster->GetBindPath(polyPath,normal);
SetPathPoly(polyPath,normal);
VERIFY(downgradeToNotify(wasWritable)==Acad::eOk);
}
}
}
void
TDbPolyPathEnt::UnBind()
{
assertWriteEnabled();
AcDbObjectId id=objectId();
if(!!m_idBind) {
OPENOBJ_BEGIN(m_idBind, AcDb::kForWrite, AcDbEntity, pEnt);
if(pEnt) {
if(!!id)
pEnt->removePersistentReactor(id);
m_idBind=AcDbObjectId::kNull;
}
OPENOBJ_END();
}
}
// 把当前目标绊定到一个对象上
// 注意: 目前仅用坡屋顶来绊定
Acad::ErrorStatus
TDbPolyPathEnt::SetBindObject(const AcDbObjectId &id)
{
assertWriteEnabled();
OPENOBJ_BEGIN(id, AcDb::kForWrite, AcDbEntity, pEnt);
const TEntityBase *pMaster = TEntityBase::Cast(pEnt);
if(pEnt==NULL || !objectId())
return Acad::eInvalidInput;
XPoly2D polyPath;
AcGeVector3d normal;
pMaster->GetBindPath(polyPath,normal);
SetPathPoly(polyPath,normal);
m_idBind = id;
pEnt->addPersistentReactor(objectId());
OPENOBJ_END();
return Acad::eOk;
}
///////////////////////////////////////////////////////////////
XVector3D
TDbPolyPathEnt::GetNormal() const
{
return XVector3D(0,0,1);
}
AcDbObjectId
TDbPolyPathEnt::GetBindObjectId() const
{
assertReadEnabled();
return m_idBind;
}
BOOL
TDbPolyPathEnt::IsBind() const
{
assertReadEnabled();
return (!!m_idBind);
}
void
TDbPolyPathEnt::SetNormal(const XVector3D &vtNormal)
{
}
void
TDbPolyPathEnt::SetElevationAt(int idx, double nElev)
{
assertWriteEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
ASSERT(idx>=0 && idx<polyPath.Length());
polyPath[idx]->z=nElev;
SetPathPoly(polyPath,normal);
}
void
TDbPolyPathEnt::SetSweepAngleAt(int idx, double nAng)
{
assertWriteEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
ASSERT(idx>=0 && idx<polyPath.Length());
polyPath.SetBulge(idx, nAng);
SetPathPoly(polyPath,normal);
}
double
TDbPolyPathEnt::GetElevationAt(int idx) const
{
assertReadEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
ASSERT(idx>=0 && idx<polyPath.Length());
return polyPath[idx]->z;
}
double
TDbPolyPathEnt::GetSweepAngleAt(int idx) const
{
assertReadEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
ASSERT(idx>=0 && idx<polyPath.Length());
return polyPath.GetBulge(idx);
}
BOOL
TDbPolyPathEnt::GetClosestPoint2d(const XPoint &ptTest, XPoint &ptOnCurve) const
{
assertReadEnabled();
AcDbPolyline pline;
XPoly2D poly2d;
AcGeVector3d normal;
GetPathPoly(poly2d,normal);
poly2d.SetElevation(0.0);
PolyConvert(poly2d, pline);
XPoint pt2d=ptTest;
pt2d.z=0;
return (pline.getClosestPointTo(pt2d, ptOnCurve)==Acad::eOk);
}
BOOL
TDbPolyPathEnt::AddVertex(const XPoint &ptAdd)
{
assertWriteEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
XPoint ptOnCurve;
if(GetClosestPoint2d(ptAdd, ptOnCurve)) {
int nPos=HitTestOnBase2d(ptOnCurve);
if(nPos<0) {
nPos = abs(nPos);
nPos--;
XPoly2D poly2d(polyPath);
poly2d.SetElevation(0.0);
XDirectionCurve seg;
poly2d.Nth(nPos, seg);
if(seg.IsMinusArc()) {
XArc ar1=seg.GetArc(), ar2=seg.GetArc();
ar1.SetAngleByPoints(seg.EndPoint(), ptOnCurve);
ar2.SetAngleByPoints(ptOnCurve, seg.StartPoint());
ptOnCurve.z = polyPath[nPos]->z;
polyPath.SetBulge(nPos, - ar2.Bulge());
polyPath.InsertNodeAt(nPos+1, ptAdd, ar1.Bulge());
} else {
XCurveSegment seg1=seg, seg2=seg;
seg1.SetPoints(seg.StartPoint(), ptOnCurve);
seg2.SetPoints(ptOnCurve, seg.EndPoint());
ptOnCurve.z = polyPath[nPos]->z;
polyPath.SetBulge(nPos, seg1.GetBulge());
polyPath.InsertNodeAt(nPos+1, ptAdd, seg2.GetBulge());
}
SetPathPoly(polyPath,normal);
return TRUE;
} else if(nPos>0 && ptOnCurve!=ptAdd){
nPos--;
if(nPos==0) {
polyPath[nPos];
polyPath.InsertNodeAt(nPos, ptAdd);
} else {
polyPath.AppendNode(ptAdd);
}
SetPathPoly(polyPath,normal);
return TRUE;
}
}
return FALSE;
}
BOOL
TDbPolyPathEnt::RemoveVertexAt(int nPos)
{
assertWriteEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
ASSERT(nPos>=0 && nPos<polyPath.Length());
polyPath.Remove(nPos);
polyPath.RemoveBugle(nPos);
SetPathPoly(polyPath,normal);
return TRUE;
}
// >0 命中顶点; <0 命中边; 0--没有命中
// abs(nRet)-1 为命中目标序号
int
TDbPolyPathEnt::HitTestOnBase2d(const XPoint &ptTest, double nTol) const
{
assertReadEnabled();
XPoly2D polyPath;
AcGeVector3d normal;
GetPathPoly(polyPath,normal);
XPoint pt2d=ptTest;
pt2d.z=0;
/*
for(int i=0; i<polyPath.Length(); i++) {
if(pt2d.Distance2d(*polyPath[i])<nTol)
return (i+1);
}
XPushPrec vTemp(nTol, _angSnap);
int nEdgeNum=polyPath.TotalSegments();
for(i=0; i<nEdgeNum; i++) {
XCurveSegment seg;
polyPath.Nth(i, seg);
seg.SetElevation(0.0);
if((pt2d&seg)==PR_INSIDE)
return (-i-1);
}
return 0;
*/
return polyPath.HitTestOnCurve(pt2d, nTol);
}
void InitDbPolyPathEnt(BOOL bTrue)
{
if(bTrue) {
TDbPolyPathEnt::rxInit();
//TDbPolyPathEnt::SetEditMethod(EditPolyPathEnt0);
} else {
deleteAcRxClass(TDbPolyPathEnt::desc());
}
}