#include "stdafx.h" #include "dbid.h" extern int GetContourDivNum(double dPerimeter); static int CompareObjectIds(const AcDbSoftPointerId *p1, const void *p2) { if(*p1==*(const AcDbSoftPointerId *)p2) return 0; return 1; } static int CompareArea(const XPoly2D *p1, const XPoly2D *p2) { if(p1->Area()>p2->Area()) return 1; return -1; } TReactor::TReactor() { } TReactor::TReactor(const TReactor& src) { int nCount = src.m_lstReactor.Length(); for (int i = 0; i < nCount; i++) { AcDbSoftPointerId* objId = new AcDbSoftPointerId(src.m_lstReactor[i]); m_lstReactor.Append(objId); } } TReactor::~TReactor() { } BOOL TReactor::IsValid() const { int nCount = m_lstReactor.Length(); for (int i=0; i0; } void TReactor:: GetReactors(DList& lstReactorId) const { lstReactorId.Reset(); int nCount = m_lstReactor.Length(); for (int i=0; i& lstReactorId) { int nCount = lstReactorId.Length(); for (int i=0; iobjectId()); } Acad::ErrorStatus TReactor::Detach(AcDbObject* pObj) { if(pObj==NULL) return Acad::eNullObjectPointer; return Detach(pObj->objectId()); } Acad::ErrorStatus TReactor::Attach(const AcDbObjectId& objId) { if(IsExist(objId)) return Acad::eAlreadyInDb; m_lstReactor.Append(new AcDbSoftPointerId(objId)); return Acad::eOk; } Acad::ErrorStatus TReactor::Detach(const AcDbObjectId& objId) { if (!IsExist(objId)) return Acad::eKeyNotFound; m_lstReactor.Remove(); return Acad::eOk; } void TReactor::DetachAll() { m_lstReactor.Reset(); } Acad::ErrorStatus TReactor::DwgInFields(AcDbDwgFiler* pFiler) { Adesk::Int32 nCount; pFiler->readItem(&nCount); m_lstReactor.Reset(); for (int i=0; ireadItem(&idTemp); m_lstReactor.Append(new AcDbSoftPointerId(idTemp)); } return pFiler->filerStatus(); } Acad::ErrorStatus TReactor::DwgOutFields(AcDbDwgFiler* pFiler) const { int nCount = m_lstReactor.Length(); pFiler->writeInt32(nCount);// nCount of ids for (int i=0; iwriteSoftPointerId(idRector); } return pFiler->filerStatus(); } Acad::ErrorStatus TReactor::DxfInFields(AcDbDxfFiler* pFiler) { resbuf rb; Acad::ErrorStatus es=Acad::eOk; m_lstReactor.Reset(); while ((es == Acad::eOk) && ((es=pFiler->readResBuf(&rb)) == Acad::eOk)) { if (rb.restype == AcDb::kDxfSoftPointerId) { AcDbSoftPointerId idTemp; #ifdef _WIN64 idTemp.setFromOldId(rb.resval.mnInt64); #else idTemp.setFromOldId(rb.resval.rlong); #endif m_lstReactor.Append(new AcDbSoftPointerId(idTemp)); } else { pFiler->pushBackItem(); es = Acad::eEndOfFile; } } if (es != Acad::eEndOfFile) return Acad::eInvalidResBuf; return pFiler->filerStatus(); } Acad::ErrorStatus TReactor::DxfOutFields(AcDbDxfFiler* pFiler) const { int nCount = m_lstReactor.Length(); for (int i=0; iwriteItem(AcDb::kDxfSoftPointerId,m_lstReactor[i]); } return pFiler->filerStatus(); } void TReactor::TransformBy(const AcGeMatrix3d xform) { int nCount = m_lstReactor.Length(); for (int i=0; itransformBy(xform); } OPENOBJ_END(); } } BOOL TReactor::IsShowReactor() const { BOOL bShow=TRUE; int nCount = m_lstReactor.Length(); for(int i=0; ivisibility(); if (oldVas == AcDb::kInvisible) { bShow = FALSE; break; } } OPENOBJ_END(); } return bShow; } void TReactor::ShowReactor(BOOL bShow) { AcDb::Visibility oldVas, newVal = bShow?AcDb::kVisible:AcDb::kInvisible; int nCount = m_lstReactor.Length(); for(int i=0; ivisibility(); if (oldVas != newVal) { if(pEnt->upgradeOpen()==Acad::eOk) { pEnt->assertWriteEnabled(); pEnt->setVisibility(newVal); pEnt->downgradeOpen(); } } } OPENOBJ_END(); } } void TReactor::EraseReactor(BOOL bEraseAll) { int nCount = m_lstReactor.Length(); if(bEraseAll){ for(int i=0; ierase(); } OPENOBJ_END(); } } else { for(int i=0; ireactors(); if (pReactors != NULL && pReactors->length() > 0) { for (int j = 0; j < pReactors->length(); j++) { pSomething = pReactors->at(j); if (acdbIsPersistentReactor(pSomething)) { nPersistentNum++; break; } } } //如果少于两个,删除 if (nPersistentNum<=0){ if(pObj->upgradeOpen()==Acad::eOk) { pObj->assertWriteEnabled(); pObj->erase(); pObj->downgradeOpen(); } } } OPENOBJ_END(); } } DetachAll(); } void TReactor::RemovePersistentReactor(const AcDbObjectId& objId) { if (objId.isNull()) return; int nCount = m_lstReactor.Length(); for(int j=0; jreactors(); if (pReactors==NULL || pReactors->length()<=0) continue; for (int k = 0; k < pReactors->length(); k++) { pSomething = pReactors->at(k); if (acdbIsPersistentReactor(pSomething)) { AcDbObjectId idPer=acdbPersistentReactorObjectId(pSomething); if (idPer == objId) { if(pReactor->upgradeOpen()==Acad::eOk) { pReactor->assertWriteEnabled(); pReactor->removePersistentReactor(objId); pReactor->downgradeOpen(); } break; } } } OPENOBJ_END(); } } /////////////////////////////////////////////////////////////// // 类名 : TReactor END // 类名 : TSlope BEGIN /////////////////////////////////////////////////////////////// void TSlope::ResetAll() { m_subSlopes.Reset(); Reset(); } void TSlope::GetPolys(DList &lstPoly) const { XPoly2D* poly2d = new XPoly2D(*this); if(poly2d->Length() > 0) lstPoly.Append(poly2d); else delete poly2d; int nCount = m_subSlopes.Length(); for(int i=0; i &sortedRegions, TSlope *parent) { if(!IsValid()) return; DList lstOutside(FALSE), lstInside(FALSE); int nRegionNum=sortedRegions.Length(); XPoly2D polyThis=(*this); polyThis.SetElevation(0.0); for(int n=nRegionNum-1; n>=0; n--) { XPoly2D *polyTemp=sortedRegions[n]; XPoly2D &poly2d=(*polyTemp); XPoint ptMid=poly2d.GetInsidePoint(); // ptMid.z=0; int nPrFlag=(ptMid&polyThis); //只有z坐标为0,才能判断正确的关系 DList &rList=(nPrFlag==PR_INSIDE? lstInside : lstOutside); if(!rList) rList.Append(polyTemp); else { rList[0]; rList.Insert(polyTemp); } } if(lstInside.Length()) { TSlope *pSub=new TSlope; (XPoly2D &)(*pSub)=*lstInside.Tail(); lstInside.Remove(lstInside.Length()-1); //Remove tail m_subSlopes.Append(pSub); if(lstInside.Length()) pSub->ProcessSlope(lstInside, this); } if(parent && lstOutside.Length()) parent->ProcessSlope(lstOutside); } void TSlope::TransformBy(const AcGeMatrix3d xform) { XPoly2D::TransformBy(xform); for(int i=0; iTransformBy(xform); } Acad::ErrorStatus TSlope::DwgInFields (AcDbDwgFiler* filer) { double nElev=0; filer->readItem(&nElev); Acad::ErrorStatus es=ReadPoly2D(filer, *this); if(es!=Acad::eOk) return es; SetElevation(nElev); m_subSlopes.Reset(); Adesk::UInt16 nCount=0; filer->readItem(&nCount); for(int i=0; iDwgInFields(filer); m_subSlopes.Append(pSub); } return Acad::eOk; } Acad::ErrorStatus TSlope::DwgOutFields(AcDbDwgFiler* filer) const { if(Length()<1) return Acad::eInvalidInput; double nElev=(*this)[0].z; filer->writeItem(nElev); Acad::ErrorStatus es=WritePoly2D(filer, *this); if(es!=Acad::eOk) return es; Adesk::UInt16 nCount=m_subSlopes.Length(); filer->writeItem(nCount); for(int i=0; i=2); return bRet; } // 绘制二维 Acad::ErrorStatus TSlope::ExplodeOrDraw2d(XExplodeDraw &dc) const { XPoly2D poly2d(*this); poly2d.SetElevation(0.0); dc << poly2d; for(int i=0; iz; dc.DrawShell(polyThis); for(int i=0; iz; polySub.SetElevation(nElev); XVector3D vt(0,0, nElev1-nElev); dc.DrawMesh(polySub, vt); } for(i=0; i lstPoly; m_slope.GetPolys(lstPoly); int nCount=lstPoly.Length(); if(nCount <= 0) return; //生成新的Pline线 PickSet ssPline(SS_FREE); ssPline.IncludeBegin(); for (int i=0; isetColorIndex(color); pEnt->addPersistentReactor(idSlope); } OPENOBJ_END(); } SetReactors(arReactorId); EnableReact(TRUE); } // 提供对格式刷的支持 void TDbSlope::CopyPropertiesFrom(AcDbEntity *pSrcEntity, unsigned gMatchFlag) { assertWriteEnabled(); TDbEntity::CopyPropertiesFrom(pSrcEntity, gMatchFlag); TDbSlope *pSrc=TDbSlope::cast(pSrcEntity); if(pSrc) { } } BOOL TDbSlope::IsValid() const { BOOL bValid=TDbEntity::IsValid(); if(!bValid) return bValid; bValid=TReactor::IsValid(); if(!bValid) return bValid; bValid = m_slope.IsValid(); return bValid; } /* Acad::ErrorStatus TDbSlope::getClassID(CLSID* pClsid) const { return Acad::eOk; } */ // 从DWG读入数据: Acad::ErrorStatus TDbSlope::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; } es = pFiler->readItem(&m_nControlFlag); es = pFiler->readItem(&m_nVertexNum); es = pFiler->readItem(&m_nCMFlag); es = pFiler->readItem(&m_bEnableReact); es = pFiler->readItem(&m_bShowSlope); es = pFiler->readItem(&m_bTransformBy); es = TReactor::DwgInFields(pFiler); if(es != Acad::eOk) return es; es = m_slope.DwgInFields(pFiler); if(es != Acad::eOk) return es; return pFiler->filerStatus(); } Acad::ErrorStatus TDbSlope::dwgOutFields(AcDbDwgFiler* pFiler) const { assertReadEnabled(); Acad::ErrorStatus es = TDbEntity::dwgOutFields(pFiler); if(es != Acad::eOk) return es; es = pFiler->writeItem(g_nVersion); es = pFiler->writeItem(m_nControlFlag); es = pFiler->writeItem(m_nVertexNum); es = pFiler->writeItem(m_nCMFlag); es = pFiler->writeItem(m_bEnableReact); es = pFiler->writeItem(m_bShowSlope); es = pFiler->writeItem(m_bTransformBy); es = TReactor::DwgOutFields(pFiler); if(es != Acad::eOk) return es; es = m_slope.DwgOutFields(pFiler); if(es != Acad::eOk) return es; return pFiler->filerStatus(); } Acad::ErrorStatus TDbSlope::dxfInFields (AcDbDxfFiler* pFiler) { assertWriteEnabled(); Acad::ErrorStatus es=TDbEntity::dxfInFields(pFiler); if(es!=Acad::eOk) return es; if (!pFiler->atSubclassData(_T("TDbSlope"))) { return Acad::eBadDxfSequence; } es = TReactor::DxfInFields(pFiler); if(es!=Acad::eOk) return es; return pFiler->filerStatus(); } Acad::ErrorStatus TDbSlope::dxfOutFields(AcDbDxfFiler* pFiler) const { Acad::ErrorStatus es; es = TDbEntity::dxfOutFields(pFiler); assert(es == Acad::eOk); es = pFiler->writeItem(AcDb::kDxfSubclass,_T("TDbSlope")); assert(es == Acad::eOk); es = TReactor::DxfOutFields(pFiler); assert(es == Acad::eOk); return es; } Acad::ErrorStatus TDbSlope::subGetClassID(CLSID* pClsid) const { return Acad::eOk; } Acad::ErrorStatus TDbSlope::subDeepClone(AcDbObject* pOwner, AcDbObject*& pClonedObject, AcDbIdMapping& idMap, Adesk::Boolean isPrimary) const { Acad::ErrorStatus es= TDbEntity::subDeepClone(pOwner, pClonedObject, idMap, isPrimary); if(es!=Acad::eOk) return es; if(!HasReactor()) return Acad::eOk; TDbSlope *pClonedSlope = TDbSlope::cast(pClonedObject); ASSERT(pClonedSlope); pClonedSlope->DetachAll(); return Acad::eOk; } Acad::ErrorStatus TDbSlope::subTransformBy(const AcGeMatrix3d& xform) { extern XString GetCurCommand(); assertWriteEnabled(); TDbEntity::subTransformBy(xform); if (!m_bTransformBy) return Acad::eOk; if(HasReactor()) { if(database()!=NULL) { EnableReact(FALSE); TReactor::TransformBy(xform); EnableReact(TRUE); } } //圆周的分段数 BOOL bComputeVertex=FALSE; int nVertexOld=0,nVertexNew=0; if (_tcsicmp(GetCurCommand(), _T("SCALE"))==0 && m_nVertexNum>0) { bComputeVertex=TRUE; } if (bComputeVertex) { double dPerimeter=m_slope.Distance3d(); if(dPerimeter>0) { nVertexOld=GetContourDivNum(dPerimeter); } } m_slope.TransformBy(xform); //圆周的分段数 if (bComputeVertex) { double dPerimeter=m_slope.Distance3d(); if(dPerimeter>0) { nVertexNew=GetContourDivNum(dPerimeter); } if (nVertexOld>0 && nVertexNew>0) { double dScale = nVertexNew/nVertexOld; m_nVertexNum = AS_INT(m_nVertexNum*dScale); } } return Acad::eOk; } Acad::ErrorStatus TDbSlope::subGetOsnapPoints(AcDb::OsnapMode osnapMode, INT_PTR gsSelectionMark, const AcGePoint3d& ptPick, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const { Acad::ErrorStatus es=Acad::eOk; int expMode=GetExplodeMode(); if(expMode==DRAW_2D) { es = TDbEntity::subGetOsnapPoints(osnapMode, gsSelectionMark, ptPick, lastPoint, viewXform, snapPoints, geomIds); } return es; } Acad::ErrorStatus TDbSlope::subErase(Adesk::Boolean bErasing) { AcDbObjectId idSlope=objectId(); Acad::ErrorStatus es = TDbEntity::subErase(bErasing); if (es != Acad::eOk) return es; RemovePersistentReactor(idSlope); EraseReactor(); return Acad::eOk; } // 绘制二维 Acad::ErrorStatus TDbSlope::ExplodeOrDraw2d(XExplodeDraw &dc) const { if (!Has2D()) { return Acad::eOk; } else { return m_slope.ExplodeOrDraw2d(dc); } } static int CompareByX(const XPoint *p1, const XPoint *p2) { if(p1->xx) return -1; return 1; } static int CompareByY(const XPoint *p1, const XPoint *p2) { if(p1->yy) return -1; return 1; } // 由X和Y两个方向进行拟合出高度 Acad::ErrorStatus TDbSlope::DrawSlope3d(XExplodeDraw &dc) const { DList lstOutlines; m_slope.GetPolys(lstOutlines); XPoly2D polyExt=m_slope; int row=100, col=100; double nExtElev=polyExt.Head()->z; XPoint ptLow, ptUp; polyExt.SetElevation(0.0); polyExt.GetExtend(ptLow, ptUp); AcGePoint3d *vertices=new AcGePoint3d[row*col]; XPointList *rowIntPoints=new XPointList[row]; XPointList *colIntPoints=new XPointList[col]; double nRowSpace=(ptUp.y-ptLow.y)/(row-1); double nColSpace=(ptUp.x-ptLow.x)/(col-1); // 求行交点,并按x由小到大排序 XLine lnRow; lnRow.SetLineFlag(LS_FINITE); lnRow.StartPoint().x=ptLow.x-_DIST_SNAP; lnRow.EndPoint().x=ptUp.x+_DIST_SNAP; for(int m=0; mz; poly.SetElevation(0.0); AcDbPolyline pline; PolyConvert(poly, pline); ln2d.intersectWith(&pline, AcDb::kOnBothOperands, ptArray); for(int k=0; kz; poly.SetElevation(0.0); AcDbPolyline pline; PolyConvert(poly, pline); ln2d.intersectWith(&pline, AcDb::kOnBothOperands, ptArray); for(int k=0; k &lstInfo) const { lstInfo.Append(new TObjInfoUnit(_T("对象类型"), _T("等高线"))); } void TDbSlope::erased(const AcDbObject* pObj,Adesk::Boolean bErasing) { if (!IsEnableReact()) return; Adesk::Boolean bWritable; Acad::ErrorStatus es = upgradeFromNotify(bWritable); if (es == Acad::eOk) { AcDbObjectId idReactor = pObj->objectId(); if (bErasing) { Detach(idReactor); } else { Attach(idReactor); } downgradeToNotify(bWritable); } } void TDbSlope::modified(const AcDbObject* pObj) { if (!IsEnableReact()) return; if (pObj->database()==NULL) return; if (isErased()) return; ads_name entReactor; AcDbObjectId idReactor = pObj->objectId(); //当前实体是否是自己的反应器 if(!IsExist(idReactor) || acdbGetAdsName(entReactor,idReactor)!=Acad::eOk) { return; } //当前反应器 DList lstRegion; XPoly2D* pReg=new XPoly2D(entReactor); pReg->Compress(); if (pReg->Length()>0 && pReg->IsClosed()) { lstRegion.Append(pReg); } else { delete pReg; return; } //构造截面 int nCount = m_lstReactor.Length(); for (int i=0; iCompress(); if (pReg->Length()>0 && pReg->IsClosed()) { lstRegion.Append(pReg); } else { delete pReg; } } } if (lstRegion.Length()<=0) return; Adesk::Boolean bWritable; Acad::ErrorStatus es = upgradeFromNotify(bWritable); if (es == Acad::eOk) { assertWriteEnabled(); m_slope.ResetAll(); lstRegion.QuickSort(CompareArea); (XPoly2D &)(m_slope)=*lstRegion.Tail(); lstRegion.Remove(lstRegion.Length()-1); m_slope.ProcessSlope(lstRegion); downgradeToNotify(bWritable); }/* else { if(upgradeOpen()==Acad::eOk) { m_slope.ResetAll(); lstRegion.QuickSort(CompareArea); (XPoly2D &)(m_slope)=*lstRegion.Tail(); lstRegion.Remove(lstRegion.Length()-1); m_slope.ProcessSlope(lstRegion); downgradeOpen(); } }*/ } // 创建斜坡等高线 void CreateSlope() { RBList mask=ads_buildlist(-4, _T(""), RTDXF0, _T("CIRCLE"), -4, _T("or>"), NULL); PickSet ssSelect(SS_FREE); if(SelectEntities(_T("\n选择闭合曲线"), ssSelect, mask)!=RTNORM) return; //**** 以下是未定义永久响应的斜坡实体 ****// /*DList lstRegion; long lCount=ssSelect.Length(); for(long idx=0L; idxIsSelfIntersect()) delete pReg; else lstRegion.Append(pReg); } int nRegionNum=lstRegion.Length(); if(!nRegionNum) return; TDbSlope *pSlope=new TDbSlope; lstRegion.QuickSort(CompareArea);//快速排序(从小到大) (XPoly2D &)(pSlope->m_slope)=*lstRegion.Tail(); lstRegion.Remove(lstRegion.Length()-1); pSlope->m_slope.ProcessSlope(lstRegion); pSlope->AddToMSpace(Adesk::kTrue);*/ //**** 以上是未定义永久响应的斜坡实体 ****// //**** 以下是定义永久响应的斜坡实体 ****// //转换成Id,去除不符合的实体 DList lstRegion;//截面 AcDbObjectIdArray arReactorId;//id值 long lCount=ssSelect.Length(); for(long index=0L; indexEnableReact(FALSE); lstRegion.QuickSort(CompareArea);//快速排序(从小到大) (XPoly2D &)(pSlope->m_slope)=*lstRegion.Tail(); lstRegion.Remove(lstRegion.Length()-1); pSlope->m_slope.ProcessSlope(lstRegion); idSlope=pSlope->AddToMSpace(Adesk::kFalse); //构造斜坡反应堆(永久响应) if(!idSlope.isNull()) { int nLen=arReactorId.length(); for(int i=0; isetColorIndex(1); pEnt->setVisibility(AcDb::kInvisible); pEnt->addPersistentReactor(idSlope); } OPENOBJ_END(); } } pSlope->SetReactors(arReactorId); pSlope->EnableReact(TRUE); pSlope->close(); //**** 以上是定义永久响应的斜坡实体 ****// } // 编辑TDbSlope实体 int EditSlope(AcDbObjectId id) { OPENOBJ_BEGIN(id, AcDb::kForRead, TDbSlope, pSlope); if(pSlope == NULL) return RTERROR; while(1) { XString sPrompts, sKeywords; BOOL bHas2D=pSlope->Has2D(); BOOL bHasReactor=pSlope->HasReactor(); BOOL bShowSlope=pSlope->IsShowSlope(); if(!bHas2D) { sPrompts << _T("\n选择 [显示二维(S)"); sKeywords << _T("S"); } else { if(bHasReactor) { sPrompts << _T("\n选择 [显示响应(S)"); sKeywords << _T("S"); } else { sPrompts << _T("\n选择 [新建响应(N)"); sKeywords << _T("N"); } } //显示模式:梯田和斜坡 if(bShowSlope) { sPrompts << _T("/改变分段数(C)/显示梯田(M)]<退出>:"); sKeywords << _T(" C M"); } else { sPrompts << _T("/显示斜坡(M)]<退出>:"); sKeywords << _T(" M"); } XString sKeyword; int nRet=0; INITGET_BEG(0, sKeywords); nRet=ads_getkword(sPrompts, sKeyword); INITGET_END(); if(nRet!=RTNORM) break; TCHAR cKey=sKeyword[0]; if(cKey==_T('S')) { if(pSlope->upgradeOpen()==Acad::eOk) { pSlope->assertWriteEnabled(); pSlope->EnableReact(FALSE); if(!bHas2D) { pSlope->SetHas2D(TRUE); pSlope->ShowReactor(FALSE); pSlope->EnableTransformBy(TRUE); } else { pSlope->SetHas2D(FALSE); pSlope->ShowReactor(TRUE); pSlope->EnableTransformBy(FALSE); } pSlope->EnableReact(TRUE); pSlope->downgradeOpen(); } } /*else if(cKey==_T('E')){//删除响应 if(pSlope->upgradeOpen()==Acad::eOk) { pSlope->assertWriteEnabled(); pSlope->EraseReactor(); pSlope->downgradeOpen(); } }*/ else if(cKey==_T('N')) {//新建响应 if(pSlope->upgradeOpen()==Acad::eOk) { pSlope->assertWriteEnabled(); pSlope->NewReactor(); pSlope->downgradeOpen(); } } else if(cKey==_T('C')) {//顶点数 int nVertexNum=pSlope->GetVertexNum(); while(1) { XString sPrompts(_T("\n输入圆周上分段数目<%d>:"),nVertexNum); if (acedGetInt(sPrompts,&nVertexNum)!=RTNORM) { break; } if (nVertexNum<3) { adsout << _T("\n分段数不能小于3,请重新输入!"); } else { if(pSlope->upgradeOpen()==Acad::eOk) { pSlope->assertWriteEnabled(); pSlope->SetVertexNum(nVertexNum); pSlope->downgradeOpen(); break; } } } } else if(cKey==_T('M')) {//显示模式 if(pSlope->upgradeOpen()==Acad::eOk) { pSlope->assertWriteEnabled(); pSlope->ShowSlope(!bShowSlope); pSlope->downgradeOpen(); } } } OPENOBJ_END(); return RTNORM; } void InitDbSlope(BOOL bTrue) { if(bTrue) { TDbSlope::rxInit(); TDbSlope::SetEditMethod(EditSlope); acrxBuildClassHierarchy(); TDbSlope::InitMatchProtocol(TRUE); } else { TDbSlope::InitMatchProtocol(FALSE); deleteAcRxClass(TDbSlope::desc()); } }