#include "stdafx.h" #include "TAecSpaceCell.h" #include "TAecSpaceWall.h" #include "TSearchSpaceFromWall.h" extern int CompNodeByEqual(const XSortWallOnPt *p1, const void *p2); extern AcDbObjectId GetValidTextStyle(AcDbDatabase *pDb, const TCHAR *pStyle); //Acad::ErrorStatus WritePoly2D(AcDbDwgFiler *pFiler, const XPoly2D &poly); //Acad::ErrorStatus ReadPoly2D(AcDbDwgFiler *pFiler, XPoly2D &poly); double GetTextSize(const TCHAR *m_sTextStyle); extern void xh1cpy(TCHAR *to, const TCHAR *src); #define SP_QUANTUM_1 _T("地面面积") #define SP_QUANTUM_2 _T("顶棚面积") #define SP_QUANTUM_3 _T("轴线面积") #define SP_QUANTUM_4 _T("墙壁面积") #define SP_QUANTUM_5 _T("周长") #define SP_QUANTUM_6 _T("踢脚线") #define SP_QUANTUM_7 _T("净容积") //////////////////////////////////////////////////// // 房间实体类 //////////////////////////////////////////////////// // ver:2-TArch5;3-TArch6;4-TArch7;5-TArch8 const Adesk::UInt8 TDbSpace::g_nVersion = 5; ACRX_DXF_DEFINE_MEMBERS(ATSSpace, ATSEntity, AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 1, ATS_SPACE, "ATS_SPACE图形无法解析, 请下载上华软件|网址: www.shanghuasoft.com"); IMPLEMENT_TENTBASE(TDbSpace); TDbSpace::TDbSpace() { m_nSpaceFlag = 0; m_nNewFlag = 0; m_nRotation = 0; m_nTextHeight = 5.0; m_nFloorThick = _AS_SYS_UNIT(120.0); m_nUseArea = 0; m_nOccuArea = 0; m_nCeilArea = 0; m_nWallSurfArea = 0; m_nExtWallArea = 0; m_nExtWinArea = 0; m_nExtDoorArea = 0; m_nType = kUseArea; m_nHatchColor = 256;//默认color by layer m_dbTempSum = 26;//夏季室内设计温度 m_dbTempWin = 18;//冬季室内设计温度 m_nUnitNo = 0; //空调系统单元号 m_dbColdLoad = 0;//冷负荷 m_dbHeatLoad = 0;//热负荷 m_dHatchScale = 100; // sg add 081125 m_dHatchAngle = 0; m_bMText = FALSE; // sg add 081211 m_sSndName = _T("ROOM"); m_bIsStretch = false; } TDbSpace::~TDbSpace() { } BOOL TDbSpace::IsValid() const { BOOL bRet = TDbEntity::IsValid(); if (!bRet) return bRet; bRet = !!m_outline; return bRet; } // 提供对格式刷的支持 void TDbSpace::CopyPropertiesFrom(AcDbEntity *pSrcEntity, unsigned gMatchFlag) { assertWriteEnabled(); TDbEntity::CopyPropertiesFrom(pSrcEntity, gMatchFlag); TDbSpace *pSrc = TDbSpace::cast(pSrcEntity); if (pSrc != NULL) { m_nSpaceFlag = pSrc->m_nSpaceFlag; m_nNewFlag = pSrc->m_nNewFlag; m_nType = pSrc->m_nType; m_nFloorThick = pSrc->m_nFloorThick; m_sHatchStyle = pSrc->m_sHatchStyle; m_nHatchColor = pSrc->m_nHatchColor; m_nRotation = pSrc->m_nRotation; m_nTextHeight = pSrc->m_nTextHeight; if (database() == NULL || pSrcEntity->database() == NULL || database() == pSrcEntity->database()) // add by whl on 060317 { m_idTextStyle = pSrc->m_idTextStyle; m_idHatchLayer = pSrc->m_idHatchLayer; } m_dHatchAngle = pSrc->m_dHatchAngle; // sg add 090206 m_dHatchScale = pSrc->m_dHatchScale; // sg add 110307,根据需求要求,真彩色支持格式刷 SetHatchTrueColor(pSrc->GetHatchTrueColor()); } } Acad::ErrorStatus TDbSpace::SetPathPoly(const XPoly2D &polyPath, const AcGeVector3d&normal) { assertWriteEnabled(); m_outline = polyPath; if (m_outline.PathArea() > 0) m_outline.Reverse(); m_nUseArea = _AS_SQMETER(m_outline.Area()); // sg add 090602,更新周长 m_nPerimeter = m_outline.Distance2d(); return Acad::eOk; } Acad::ErrorStatus TDbSpace::GetPathPoly(XPoly2D &polyPath, AcGeVector3d&normal) const { assertReadEnabled(); polyPath = m_outline; normal = AcGeVector3d::kZAxis; return Acad::eOk; } // sg add 090508,获取所属户,动态数据 AcDbObjectId TDbSpace::GetHouseId() const { assertReadEnabled(); AcDbSoftPointerId idHouse; const TEntityFields &fd = GetFields(); fd.GFD(_T("阳台所属户"), idHouse); return idHouse; } void TDbSpace::SetHouseId(AcDbObjectId id) { assertWriteEnabled(); AcDbSoftPointerId idHouse = id; TEntityFields &fd = Fields(); fd.SFD(_T("阳台所属户"), idHouse); } // sg add 100907,增加粉刷层厚度的动态数据 double TDbSpace::GetStuccoThickness() const { assertReadEnabled(); double dThickness(0); const TEntityFields &fd = GetFields(); fd.GFD(_T("粉刷层厚度"), dThickness); return dThickness; } void TDbSpace::SetStuccoThickness(double dThickness) { // 获取旧的粉刷层厚度 double dOldThickness(0); const TEntityFields &fdOld = GetFields(); // 通过返回值,判断是否有“粉刷层厚度”的动态数据,并在Offset时,进行不同的操作 bool bRet = fdOld.GFD(_T("粉刷层厚度"), dOldThickness); // 设置新的粉刷层厚度 assertWriteEnabled(); TEntityFields &fd = Fields(); fd.SFD(_T("粉刷层厚度"), dThickness); // 自动处理轮廓线问题 XPoly2D polyPath, polyNewPath; AcGeVector3d normal; GetPathPoly(polyPath, normal); // 获得偏移距离 // 注:此处存在问题,跟踪发现GetPathPoly函数得到的普通房间PLine线中的点方向第一次设置后,会发生变化 double dOffset = 0; if (m_nType == kTotalArea) // 如果是建筑轮廓,向外侧偏移 { dOffset = dThickness - dOldThickness; } else // 其他房间,向内侧偏移 { if (!bRet) // 以前没有动态数据 { dOffset = dThickness - dOldThickness; } else { dOffset = dOldThickness - dThickness; } } polyPath.Offset(dOffset, polyNewPath); // 重新设置外轮廓线,并更新面积、周长等数据 SetPathPoly(polyNewPath, normal); } // sg add 100907,增加房间填充真彩色的动态数据,原有的m_nHatchColor不再使用 AcCmColor TDbSpace::GetHatchTrueColor() const { assertReadEnabled(); Adesk::UInt32 nColor = m_nHatchColor; const TEntityFields &fd = GetFields(); fd.GFD(_T("填充真彩颜色"), nColor); AcCmColor color; #if ADS > 23 #if defined(ZWCAD) && (ADS == 24 || defined(R24)) color.setRGB(GetRValue(nColor), GetGValue(nColor), GetBValue(nColor)); #else color.setRGB(nColor); #endif #else color.setColor(nColor); #endif return color; } void TDbSpace::SetHatchTrueColor(const AcCmColor &color) { assertWriteEnabled(); #if ADS > 23 #if defined(ZWCAD) && (ADS == 24 || defined(R24)) Adesk::UInt32 nColor = RGB(color.red(), color.green(), color.blue()); #else Adesk::UInt32 nColor = color.getRGB(); #endif #else Adesk::UInt32 nColor = color.color(); #endif TEntityFields &fd = Fields(); fd.SFD(_T("填充真彩颜色"), nColor); // 考虑与旧版软件图纸交流问题 SetHatchColor(color.colorIndex()); } // add by xly on 101020 支持改进房间对象编号、名称和面积的显示控制 // 设置高级选项中的控制方式:1——随图纸中的变量统一控制,默认,考虑与旧图兼容;0——独立控制 void TDbSpace::SetSpaceDispMode(int nConfig) { assertWriteEnabled(); Adesk::UInt8 nConfigNum = nConfig; TEntityFields &fd = Fields(); fd.SFD(_T("房间显示控制"), nConfigNum); } // 获得高级选项中的控制方式:1——随图纸中的变量统一控制,默认,考虑与旧图兼容;0——独立控制 int TDbSpace::GetSpaceDispMode() const { assertReadEnabled(); Adesk::UInt8 nConfig = 1; // 默认随Config,即:全局控制 const TEntityFields &fd = GetFields(); fd.GFD(_T("房间显示控制"), nConfig); return nConfig; } // 设置房间对象的显示方式 void TDbSpace::SetSpaceDispFlag(int nFlag) { assertWriteEnabled(); Adesk::UInt8 nMode = nFlag; // 获取显示控制方式 int nDispMode = GetSpaceDispMode(); if (nDispMode == 1) // 随图纸中的变量统一控制 { DocSetSpaceDispMode(nFlag); } else // 独立控制 { TEntityFields &fd = Fields(); fd.SFD(_T("房间显示方式"), nMode); } } // 获得房间对象的显示方式 int TDbSpace::GetSpaceDispFlag() const { assertReadEnabled(); // 默认从图纸中拷贝数据 Adesk::UInt8 nMode = DocGetSpaceDispMode(); // 获取显示控制方式 int nDispMode = GetSpaceDispMode(); if (nDispMode == 0) // 独立控制 { const TEntityFields &fd = GetFields(); fd.GFD(_T("房间显示方式"), nMode); } return nMode; } // 设置名称、编号是否显示 void TDbSpace::SetDimNameAndCode(BOOL bDimName, BOOL bDimCode) { assertWriteEnabled(); // 获取显示控制方式 int nFlag = GetSpaceDispFlag(); if (bDimCode && bDimName) // 同时标注 { nFlag |= SPF_NAME_AND_CODE; nFlag &= ~SPF_CODE; nFlag &= ~SPF_NULL; } else if (bDimCode) // 只标注编号 { nFlag &= ~SPF_NAME_AND_CODE; nFlag |= SPF_CODE; nFlag &= ~SPF_NULL; } else if (bDimName) // 只标注名称 { nFlag &= ~SPF_NAME_AND_CODE; nFlag &= ~SPF_CODE; nFlag &= ~SPF_NULL; } else // 都不标注 { nFlag &= ~SPF_NAME_AND_CODE; nFlag &= ~SPF_CODE; nFlag |= SPF_NULL; } SetSpaceDispFlag(nFlag); } // 获得名称是否显示 BOOL TDbSpace::IsDimName() const { assertReadEnabled(); BOOL bRet(FALSE); // 只标注编号,或者都不标注 int nFlag = GetSpaceDispFlag(); if ((nFlag&SPF_NAME_AND_CODE) != 0) // 同时标注名称和编号 { bRet = TRUE; } else if ((nFlag&SPF_CODE) == 0 && (nFlag&SPF_NULL) == 0) // 只标注名称 { bRet = TRUE; } return bRet; } // 获得房间编号是否显示 BOOL TDbSpace::IsDimCode() const { assertReadEnabled(); BOOL bRet(FALSE); // 只标注名称,或者都不标注 int nFlag = GetSpaceDispFlag(); if ((nFlag&SPF_NAME_AND_CODE) != 0) // 同时标注名称和编号 { bRet = TRUE; } else if ((nFlag&SPF_CODE) != 0) // 只标注编号 { bRet = TRUE; } return bRet; } // 设置房间面积是否显示 void TDbSpace::SetDimArea(BOOL bDim) { assertWriteEnabled(); // 获取显示控制方式 int nFlag = GetSpaceDispFlag(); if (bDim) // 标注房间面积 { nFlag |= SPF_AREA; } else // 不标注房间面积 { nFlag &= ~SPF_AREA; } SetSpaceDispFlag(nFlag); } // 获得房间面积是否显示 BOOL TDbSpace::IsDimArea() const { assertReadEnabled(); BOOL bRet(FALSE); int nFlag = GetSpaceDispFlag(); bRet = ((nFlag&SPF_AREA) != 0); // 判断是否标注面积 return bRet; } // 设置面积单位是否显示 void TDbSpace::SetDimUnit(BOOL bDim) { assertWriteEnabled(); // 获取显示控制方式 int nFlag = GetSpaceDispFlag(); if (bDim) // 标注房间面积单位 { nFlag |= SPF_UNIT; } else // 不标注面积单位 { nFlag &= ~SPF_UNIT; } SetSpaceDispFlag(nFlag); } // 获得面积单位是否显示 BOOL TDbSpace::IsDimUnit() const { assertReadEnabled(); BOOL bRet(FALSE); int nFlag = GetSpaceDispFlag(); bRet = ((nFlag&SPF_UNIT) != 0); // 判断是否标注面积单位 return bRet; } Acad::ErrorStatus TDbSpace::subGetClassID(CLSID* pClsid) const { return Acad::eOk; } // 从DWG读入数据: // 注意: 有待加入版本控制 Acad::ErrorStatus TDbSpace::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_nEnFlag); //是否有顶,是否有底 pFiler->readItem((AcGePoint3d *)&m_ptLocation); ReadString(pFiler, m_sCode); ReadString(pFiler, m_sName); pFiler->readItem(&m_nUseArea); pFiler->readItem(&m_nOccuArea); pFiler->readItem(&m_nCeilArea); pFiler->readItem(&m_nWallSurfArea); pFiler->readItem(&m_nExtWallArea); pFiler->readItem(&m_nExtWinArea); pFiler->readItem(&m_nExtDoorArea); pFiler->readItem(&m_nHeight); pFiler->readItem(&m_nPerimeter); pFiler->readItem(&m_nKickboardLength); ReadPoly2D(pFiler, m_outline); if (nVer > 1) { pFiler->readItem(&m_nSpaceFlag); } m_lstWallEnclosure.Reset(); if (nVer > 2) { // TArch6 pFiler->readItem(&m_idTextStyle); pFiler->readItem(&m_nTextHeight); pFiler->readItem(&m_nRotation); pFiler->readItem(&m_nFloorThick); Adesk::UInt8 nCount = 0; pFiler->readItem(&nCount); for (Adesk::UInt8 n = 0; n < nCount; n++) { AcDbSoftPointerId idWall; pFiler->readItem(&idWall); m_lstWallEnclosure.Append(new AcDbObjectId(idWall)); } } else { SetHas3D(FALSE); if (database() == acdbCurDwg()) { m_idTextStyle = InitTextStyle(TS_SPACE); } else { m_idTextStyle = GetValidTextStyle(database(), _T("_TCH_SPACE")); } } if (nVer > 3)//TArch7 { pFiler->readItem(&m_dbTempSum); pFiler->readItem(&m_dbTempWin); pFiler->readItem(&m_nUnitNo); pFiler->readItem(&m_dbColdLoad); pFiler->readItem(&m_dbHeatLoad); ReadString(pFiler, m_strDownFloorCons); ReadString(pFiler, m_strUpFloorCons); } if (nVer > 4)//TArch8 { pFiler->readItem(&m_nNewFlag); Adesk::Int8 type; pFiler->readItem(&type); m_nType = (AreaType)type; ReadString(pFiler, m_sHatchStyle); pFiler->readItem(&m_nHatchColor); pFiler->readItem(&m_idHatchLayer); pFiler->readItem(&m_dHatchScale); // sg add 081124 pFiler->readItem(&m_dHatchAngle); pFiler->readItem(&m_bMText); // sg add 081211 ReadString(pFiler, m_sSndName); // sg add 081215 Adesk::Int32 count; pFiler->readItem(&count); m_lstBalconyArea.Reset(); for (long i = 0; i < count; i++) { AcDbSoftPointerId *pid = new AcDbSoftPointerId; pFiler->readItem(pid); m_lstBalconyArea.Append(pid); } pFiler->readItem(&count); m_lstBalcony.Reset(); for (i = 0; i < count; i++) { AcDbSoftPointerId *pid = new AcDbSoftPointerId; pFiler->readItem(pid); m_lstBalcony.Append(pid); } } // sg add 090602,8.0的正式版起,将“文字转角”并入“布局转角” m_nLayoutRotation = m_nLayoutRotation + m_nRotation; m_nRotation = 0; return pFiler->filerStatus(); } Acad::ErrorStatus TDbSpace::dwgOutFields(AcDbDwgFiler* pFiler) const { assertReadEnabled(); Acad::ErrorStatus es = TDbEntity::dwgOutFields(pFiler); if (es != Acad::eOk) return es; if (g_nSaveTArchVer == 5) pFiler->writeItem((Adesk::UInt8)2); else if (g_nSaveTArchVer == 6) pFiler->writeItem((Adesk::UInt8)3); else if (g_nSaveTArchVer == 7) pFiler->writeItem((Adesk::UInt8)4); else pFiler->writeItem(g_nVersion); pFiler->writeItem(m_nEnFlag); //是否有顶,是否有底 pFiler->writeItem((AcGePoint3d &)m_ptLocation); pFiler->writeItem((const TCHAR *)m_sCode); pFiler->writeItem((const TCHAR *)m_sName); pFiler->writeItem(m_nUseArea); pFiler->writeItem(m_nOccuArea); pFiler->writeItem(m_nCeilArea); pFiler->writeItem(m_nWallSurfArea); pFiler->writeItem(m_nExtWallArea); pFiler->writeItem(m_nExtWinArea); pFiler->writeItem(m_nExtDoorArea); pFiler->writeItem(m_nHeight); pFiler->writeItem(m_nPerimeter); pFiler->writeItem(m_nKickboardLength); WritePoly2D(pFiler, m_outline); if (g_nSaveTArchVer == 5) { Adesk::UInt8 spFlag = ((m_nSpaceFlag&SF_MASK) ? SF_MASK : 0); pFiler->writeItem(spFlag); } else { pFiler->writeItem(m_nSpaceFlag); pFiler->writeItem(m_idTextStyle); pFiler->writeItem(m_nTextHeight); pFiler->writeItem(m_nRotation); pFiler->writeItem(m_nFloorThick); Adesk::UInt8 nCount = m_lstWallEnclosure.Length(); pFiler->writeItem(nCount); for (Adesk::UInt8 i = 0; i < nCount; i++) { AcDbSoftPointerId idWall = m_lstWallEnclosure[i]; // add by xlc on 100825 解决块参照里删除墙后提示丢失参照无法保存的问题 if (idWall.isErased()) { idWall = AcDbObjectId::kNull; } pFiler->writeItem(idWall); } } if (g_nSaveTArchVer > 6) { pFiler->writeItem(m_dbTempSum); pFiler->writeItem(m_dbTempWin); pFiler->writeItem(m_nUnitNo); pFiler->writeItem(m_dbColdLoad); pFiler->writeItem(m_dbHeatLoad); pFiler->writeString(m_strDownFloorCons); pFiler->writeString(m_strUpFloorCons); } if (g_nSaveTArchVer > 7) { pFiler->writeItem(m_nNewFlag); Adesk::Int8 type = (Adesk::Int8)m_nType; pFiler->writeItem(type); pFiler->writeString(m_sHatchStyle); pFiler->writeItem(m_nHatchColor); pFiler->writeItem(m_idHatchLayer); pFiler->writeItem(m_dHatchScale); // sg add 081124 pFiler->writeItem(m_dHatchAngle); pFiler->writeItem(m_bMText); // sg add 081211 pFiler->writeItem(m_sSndName); // sg add 081215 Adesk::Int32 count = m_lstBalconyArea.Length(); pFiler->writeItem(count); for (long i = 0; i < count; i++) pFiler->writeItem(m_lstBalconyArea[i]); count = m_lstBalcony.Length(); pFiler->writeItem(count); for (i = 0; i < count; i++) pFiler->writeItem(m_lstBalcony[i]); } return pFiler->filerStatus(); } Acad::ErrorStatus TDbSpace::dxfInFields(AcDbDxfFiler* pFiler) { assertWriteEnabled(); Acad::ErrorStatus es = TDbEntity::dxfInFields(pFiler); if (es != Acad::eOk) return es; if (!pFiler->atSubclassData(_T("TDbSpace"))) { return Acad::eBadDxfSequence; } XString sTextStyle; double nTextAng = 0.0; double nTextHeight = 5.0; double nSlabThick = 0.0; XString sName, sCode; double r1, r2; int nFlag; Adesk::Int32 type; XPoint pt; Adesk::UInt32 fieldsFlags = 0; resbuf rb; while ((es == Acad::eOk) && ((es = pFiler->readResBuf(&rb)) == Acad::eOk)) { switch (rb.restype) { case AcDb::kDxfInt16: nFlag = rb.resval.rint; fieldsFlags |= 0x01; break; case AcDb::kDxfXCoord: pt = rb.resval.rpoint; fieldsFlags |= 0x02; break; case AcDb::kDxfText: fieldsFlags |= 0x04; sName = rb.resval.rstring; free(rb.resval.rstring); break; case AcDb::kDxfText + 1: sCode = rb.resval.rstring; fieldsFlags |= 0x08; free(rb.resval.rstring); break; case AcDb::kDxfReal + 1: fieldsFlags |= 0x10; r1 = rb.resval.rreal; break; case AcDb::kDxfReal + 2: fieldsFlags |= 0x20; r2 = rb.resval.rreal; break; // TArch6 case AcDb::kDxfTextStyleName: sTextStyle = rb.resval.rstring; fieldsFlags |= 0x40; free(rb.resval.rstring); break; case AcDb::kDxfReal: fieldsFlags |= 0x80; nTextHeight = rb.resval.rreal; break; case AcDb::kDxfReal + 3: fieldsFlags |= 0x100; nSlabThick = rb.resval.rreal; break; case 50: fieldsFlags |= 0x200; nTextAng = rb.resval.rreal; break; case AcDb::kDxfInt32: type = (Adesk::Int32)(rb.resval.rint); fieldsFlags |= 0x400; break; //fall through intentional default: // An unrecognized group. Push it back so that // the subclass can read it again. pFiler->pushBackItem(); es = Acad::eEndOfFile; break; } } // At this point the es variable must contain eEndOfFile // - either from readResBuf() or from pushback. If not, // it indicates that an error happened and we should // return immediately. // if (es != Acad::eEndOfFile) return Acad::eInvalidResBuf; if (fieldsFlags & 0x01) m_nSpaceFlag = nFlag; if (fieldsFlags & 0x02) m_ptLocation = pt; if (fieldsFlags & 0x04) m_sName = sName; if (fieldsFlags & 0x08) m_sCode = sCode; if (fieldsFlags & 0x10) m_nUseArea = r1; if (fieldsFlags & 0x20) m_nPerimeter = r2; AcDbObjectId id; if (fieldsFlags & 0x40) id = TchExport::GetTextStyleId(sName, database()); if (!id) { XString style; xg_getvar(_T("TEXTSTYLE"), style); m_idTextStyle = TchExport::GetTextStyleId(style, database()); } else m_idTextStyle = id; if (fieldsFlags & 0x80) m_nTextHeight = nTextHeight; if (fieldsFlags & 0x100) m_nFloorThick = nSlabThick; if (fieldsFlags & 0x200) m_nRotation = nTextAng; if (fieldsFlags & 0x400) m_nType = (AreaType)type; return pFiler->filerStatus(); } Acad::ErrorStatus TDbSpace::dxfOutFields(AcDbDxfFiler* pFiler) const { Acad::ErrorStatus es = TDbEntity::dxfOutFields(pFiler); assert(es == Acad::eOk); es = pFiler->writeItem(AcDb::kDxfSubclass, _T("TDbSpace")); assert(es == Acad::eOk); pFiler->writeInt16(AcDb::kDxfInt16, m_nSpaceFlag); pFiler->writePoint2d(AcDb::kDxfXCoord, m_ptLocation); pFiler->writeString(AcDb::kDxfText, (const TCHAR *)GetName()); pFiler->writeString(AcDb::kDxfText + 1, (const TCHAR *)GetCode()); pFiler->writeString(AcDb::kDxfTextStyleName, (const TCHAR *)GetSymbolName(m_idTextStyle)); pFiler->writeDouble(AcDb::kDxfReal, m_nTextHeight); pFiler->writeDouble(AcDb::kDxfReal + 1, GetUseArea()); pFiler->writeDouble(AcDb::kDxfReal + 2, GetPerimeter()); pFiler->writeDouble(AcDb::kDxfReal + 3, m_nFloorThick); pFiler->writeDouble(50, m_nRotation); pFiler->writeInt32(AcDb::kDxfInt32, (Adesk::Int32)m_nType); return pFiler->filerStatus(); } Acad::ErrorStatus TDbSpace::subIntersectWith(const AcDbEntity* ent, AcDb::Intersect intType, AcGePoint3dArray& points, INT_PTR thisGsMarker, INT_PTR otherGsMarker) const { assertReadEnabled(); return Acad::eNotApplicable; } Acad::ErrorStatus TDbSpace::subIntersectWith(const AcDbEntity* ent, AcDb::Intersect intType, const AcGePlane& projPlane, AcGePoint3dArray& points, INT_PTR thisGsMarker, INT_PTR otherGsMarker) const { assertReadEnabled(); return Acad::eNotApplicable; } Acad::ErrorStatus TDbSpace::subGetOsnapPoints( AcDb::OsnapMode osnapMode, INT_PTR gsSelectionMark, const AcGePoint3d& ptPick, const AcGePoint3d& lastPoint, const AcGeMatrix3d& viewXform, AcGePoint3dArray& snapPoints, AcDbIntArray& geomIds) const { assertReadEnabled(); Acad::ErrorStatus es = Acad::eNotApplicable; switch (osnapMode) { case AcDb::kOsModeIns: case AcDb::kOsModeNode: snapPoints.append(m_ptLocation); es = Acad::eOk; break; default: //add by lgy 20120221 9.0房间面积对象顶点和边都需要被捕捉 { AcDbVoidPtrArray allEnt; XExplodeStream dc(allEnt); dc.SetPropertiesFrom(this); ExplodeOrDraw2d(dc); // 炸开对象 for (long i = 0L; i < allEnt.length(); i++) { AcDbEntity *pEnt = (AcDbEntity*)allEnt[i]; if (pEnt == NULL || pEnt->isKindOf(TDbText::desc()) || pEnt->isKindOf(AcDbHatch::desc())) { continue; // 如果指针为空,或者是文字和填充对象for循环继续 } pEnt->getOsnapPoints(osnapMode, gsSelectionMark, ptPick, lastPoint, viewXform, snapPoints, geomIds); } } es = Acad::eOk; break; } return es; } // ----------------------------------------------------------------------- // Overriden functions for edit // to do: // 对于自定义柱子,应当允许通过夹点改变边界 Acad::ErrorStatus TDbSpace::subGetGripPoints(AcGePoint3dArray& gripPoints, AcDbIntArray& osnapModes, AcDbIntArray& geomIds) const { gripPoints.append(m_ptLocation); int nEdgeNum = m_outline.TotalSegments(); for (int i = 0; i < nEdgeNum; i++) { XPoint pt = m_outline[i]; gripPoints.append(pt); } // 边上的夹点 for (i = 0; i < nEdgeNum; i++) { XCurveSegment edge; m_outline.Nth(i, edge); XPoint ptMid = edge.MidPoint(); gripPoints.append(ptMid); } return Acad::eOk; } // stretch points is diffrent from grep points, with no midpoint included Acad::ErrorStatus TDbSpace::subGetStretchPoints(AcGePoint3dArray & stretchPoints) const { stretchPoints.append(m_ptLocation); int nEdgeNum = m_outline.TotalSegments(); for (int i = 0; i < nEdgeNum; i++) { XPoint pt = m_outline[i]; stretchPoints.append(pt); } return Acad::eOk; } // Active when being rotated, scaled, moved, etc. Acad::ErrorStatus TDbSpace::subTransformBy(const AcGeMatrix3d& xform) { assertWriteEnabled(); TDbEntity::subTransformBy(xform); ads_matrix mat; memcpy(mat, &xform, sizeof(ads_matrix)); m_ptLocation.TransformBy(mat); m_outline.TransformBy(xform); // sg delete 090602,8.0的正式版起,将“文字转角”并入“布局转角” /* if(!g_bLayoutRotate) { if(!IsMirrorMatrix(xform)) { AcGeVector3d vt(cos(m_nRotation), sin(m_nRotation), 0.0); vt.transformBy(xform); m_nRotation = ads_angle(XPoint(), XPoint(vt[0], vt[1])); } } */ return Acad::eOk; } // 功能: 夹点操作 // 状态: 有待完成修改相关墙体的操作 Acad::ErrorStatus TDbSpace::subMoveGripPointsAt( const AcDbIntArray& indices, const AcGeVector3d& offset) { assertWriteEnabled(); XPoint vtOffset = *(XPoint *)&offset; //m_ptLocation += vtOffset; XPoly2D &m_polyOutline = m_outline; int nTotalEdge = m_outline.TotalSegments(); XPoly2D polyBack(m_polyOutline); vtOffset.z = 0; for (int i = 0; i < indices.length(); i++) { int idx = indices[i]; if (idx == 0) { m_ptLocation += vtOffset; continue; } idx--; //modify by lgy 20120314 不能使用以下方式判断条件是否成立 //ASSERT(idx<2*nTotalEdge); if (!(idx < 2 * nTotalEdge)) { break; } if (idx < nTotalEdge) { // modify by lgy 20120221,9.0房间对象顶点夹点新添加功能 // *m_polyOutline[idx] += vtOffset; if (!GetCtrlToggle()) //移动顶点 { *m_polyOutline[idx] += vtOffset; } else //添加夹点 { // 获取所点位置的夹点,将其偏移后加入到外包装线中设置好凸度值 XPoint ptAdd = *m_polyOutline[idx]; ptAdd += vtOffset; // m_polyOutline.InsertNodeAt(idx+1, ptAdd, m_polyOutline.GetBulge(idx)); // 判断增加到idx之前或者之后 int nPrev = idx - 1; nPrev = DePeriod(nTotalEdge, nPrev); if (nPrev >= 0 && nPrev < nTotalEdge) { XDirectionCurve prevSeg; m_polyOutline.Nth(nPrev, prevSeg); XPoint ptProject1, ptProject2; prevSeg.ProjectToMe(ptAdd, ptProject1); if ((ptProject1&prevSeg) == PR_INSIDE) // 在前1段上 { XDirectionCurve curSeg; m_polyOutline.Nth(idx, curSeg); curSeg.ProjectToMe(ptAdd, ptProject2); if ((ptProject2&curSeg) == PR_INSIDE) // 同时也在当前段上,看离哪个近 { double dDist1 = ptAdd.Distance(ptProject1), dDist2 = ptAdd.Distance(ptProject2); if (dDist1 < dDist2 - _DIST_SNAP) m_polyOutline.InsertNodeAt(idx, ptAdd, m_polyOutline.GetBulge(idx)); else m_polyOutline.InsertNodeAt(idx + 1, ptAdd, m_polyOutline.GetBulge(idx)); } else m_polyOutline.InsertNodeAt(idx, ptAdd, m_polyOutline.GetBulge(idx)); } else m_polyOutline.InsertNodeAt(idx + 1, ptAdd, m_polyOutline.GetBulge(idx)); } else m_polyOutline.InsertNodeAt(idx + 1, ptAdd, m_polyOutline.GetBulge(idx)); } } else { int nEdgeIndex = idx - nTotalEdge; //modify by lgy 20120314 要求不让用ASSERT判断条件 //ASSERT(nEdgeIndex= 0 && nPrev < nTotalEdge) { m_polyOutline.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 = *m_polyOutline[nEdgeIndex] + vtOffset; } // 更新下一点 if (nNext >= 0 && nNext < nTotalEdge) { m_polyOutline.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 = *m_polyOutline[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); } } *m_polyOutline[nEdgeIndex] = ptStart; if (nNext >= 0 && nNext < m_polyOutline.Length()) { *m_polyOutline[nNext] = ptEnd; m_polyOutline.SetBulge(nNext, nNextBulge); } if (nPrev >= 0 && nPrev < m_polyOutline.Length()) m_polyOutline.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) { m_polyOutline.SetBulge(nEdgeIndex, nSignal*arNew.Bulge()); } else { m_polyOutline.SetBulge(nEdgeIndex, -nSignal*arNew.Bulge()); } } } } } Acad::ErrorStatus es = Acad::eOk; if (m_polyOutline.IsSelfIntersect()) { m_polyOutline = polyBack; es = Acad::eInvalidInput; } else { // 判断弧段是否相交 BOOL bSelfIntersect = FALSE; int nSegNum = m_polyOutline.TotalSegments(); for (int m = 0; m < nSegNum; m++) { XCurveSegment seg1; m_polyOutline.Nth(m, seg1); if (fabs(seg1.GetBulge()) < _DIST_SNAP || seg1.GetLength() < _DIST_SNAP) // 去掉短弧线和直线 { continue; } int nPrev = m - 1, nNext = m + 1; nPrev = DePeriod(nSegNum, nPrev); nNext = DePeriod(nSegNum, nNext); for (int n = 0; n < nSegNum; n++) { if (n == m || n == nPrev || n == nNext) continue; XCurveSegment seg2; m_polyOutline.Nth(n, seg2); if (seg2.GetLength() < _DIST_SNAP) // 去掉短弧线 { continue; } XPoint pt1, pt2; if (seg1.Intersection(seg2, pt1, pt2)) { bSelfIntersect = TRUE; break; } } } if (bSelfIntersect) { m_polyOutline = polyBack; es = Acad::eInvalidInput; } else { m_nUseArea = _AS_SQMETER(m_polyOutline.Area()); // 更新周长 m_nPerimeter = m_outline.Distance2d(); } } return es; } // 功能: 夹点操作 Acad::ErrorStatus TDbSpace::subMoveStretchPointsAt( const AcDbIntArray& indices, const AcGeVector3d& offset) { // moidfy by lgy 20120221,9.0房间对象中需要顶点夹点添加新功能,再调用移动夹点函数出错 // return subMoveGripPointsAt(indices, offset); assertWriteEnabled(); XPoint vtOffset = *(XPoint *)&offset; XPoly2D &m_polyOutline = m_outline; int nTotalEdge = m_outline.TotalSegments(); XPoly2D polyBack(m_polyOutline); vtOffset.z = 0; for (int i = 0; i < indices.length(); i++) { int idx = indices[i]; if (idx == 0) { m_ptLocation += vtOffset; continue; } idx--; // modify by lgy 20120314,判断条件时要求不让用assert函数 // ASSERT(idx<2*nTotalEdge); if (!(idx < 2 * nTotalEdge)) { break; } if (idx < nTotalEdge) { *m_polyOutline[idx] += vtOffset; continue; } int nEdgeIndex = idx - nTotalEdge; // modify by lgy 20120314,判断条件时要求不让用assert函数 // ASSERT(nEdgeIndex= 0 && nPrev < nTotalEdge) { m_polyOutline.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 = *m_polyOutline[nEdgeIndex] + vtOffset; } // 更新下一点 if (nNext >= 0 && nNext < nTotalEdge) { m_polyOutline.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 = *m_polyOutline[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); } } *m_polyOutline[nEdgeIndex] = ptStart; if (nNext >= 0 && nNext < m_polyOutline.Length()) { *m_polyOutline[nNext] = ptEnd; m_polyOutline.SetBulge(nNext, nNextBulge); } if (nPrev >= 0 && nPrev < m_polyOutline.Length()) m_polyOutline.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) { m_polyOutline.SetBulge(nEdgeIndex, nSignal*arNew.Bulge()); } else { m_polyOutline.SetBulge(nEdgeIndex, -nSignal*arNew.Bulge()); } } } } Acad::ErrorStatus es = Acad::eOk; if (m_polyOutline.IsSelfIntersect()) { m_polyOutline = polyBack; es = Acad::eInvalidInput; } else { // 判断弧段是否相交 BOOL bSelfIntersect = FALSE; int nSegNum = m_polyOutline.TotalSegments(); for (int m = 0; m < nSegNum; m++) { XCurveSegment seg1; m_polyOutline.Nth(m, seg1); if (fabs(seg1.GetBulge()) < _DIST_SNAP || seg1.GetLength() < _DIST_SNAP) // 去掉短弧线和直线 { continue; } int nPrev = m - 1, nNext = m + 1; nPrev = DePeriod(nSegNum, nPrev); nNext = DePeriod(nSegNum, nNext); for (int n = 0; n < nSegNum; n++) { if (n == m || n == nPrev || n == nNext) continue; XCurveSegment seg2; m_polyOutline.Nth(n, seg2); if (seg2.GetLength() < _DIST_SNAP) // 去掉短弧线 { continue; } XPoint pt1, pt2; if (seg1.Intersection(seg2, pt1, pt2)) { bSelfIntersect = TRUE; break; } } } if (bSelfIntersect) { m_polyOutline = polyBack; es = Acad::eInvalidInput; } else { m_nUseArea = _AS_SQMETER(m_polyOutline.Area()); // 更新周长 m_nPerimeter = m_outline.Distance2d(); } } return es; } // 取得夹点说明 Acad::ErrorStatus TDbSpace::GetGripText(int idx, CString &cs) const { if (idx == 0) cs = _T("移动房间名称"); else { XString sInfo; int i = idx - 1; if (i < m_outline.TotalSegments()) { //modify by lgy 20120221 9.0房间对象顶点夹点需要新功能 //sInfo << _T("移动第") << (i+1) << _T("个顶点"); if (!GetCtrlToggle()) //移动顶点 { sInfo << _T("移动第") << (i + 1) << _T("个顶点(Ctrl-增加顶点)"); } else //添加夹点 { sInfo << _T("增加顶点") << _T("(Ctrl-移动第") << (i + 1) << _T("个顶点)"); } } else { sInfo << _T("移动第") << (i - m_outline.TotalSegments() + 1) << _T("条边"); } cs = sInfo; } return Acad::eOk; } #if ADS>15 void TDbSpace::CreateGrip() { TDbEntity::CreateGrip(); ::CreateGrip(this, m_outline, 1); } Acad::ErrorStatus TDbSpace::EntityToDim(long iGrip, long iDim, const AcDbEntity*pEnt) { TEntityBase *pCurve = TDbSpace::cast(pEnt); if (pCurve == NULL) pCurve = this; XPoly2D polyPath; AcGeVector3d normal; pCurve->GetPathPoly(polyPath, normal); return ::EntityToDim(this, polyPath, iGrip, iDim, 1); } Acad::ErrorStatus TDbSpace::DimToEntity(long iGrip, long iDim, double newValue, const AcGeVector3d& offset) { assertWriteEnabled(); TDbSpace curve; curve.CopyPropertiesFrom(this, 0); Acad::ErrorStatus es = ::DimToEntity(this, m_outline, iGrip, iDim, newValue, offset, 1); if (es == Acad::eOk && !IsValid()) { CopyPropertiesFrom(&curve, 0); return Acad::eInvalidInput; } // sg add 090326,解决“动态输入后,房间面积不随之发生变化”的BUG m_nUseArea = _AS_SQMETER(m_outline.Area()); // sg add 090602,更新周长 m_nPerimeter = m_outline.Distance2d(); return es; } #endif // 控制面积标注精确度 CString TDbSpace::GetAreaByPrecision() const { double dUseArea = IsHalfArea() ? m_nUseArea*0.5 : m_nUseArea; CString csArea; int nPrecisionNum = DocGetSpaceAreaPrecision(); // 小数部分的精确度 switch (nPrecisionNum) { case 0: csArea.Format(_T("%.0f"), dUseArea); break; case 1: csArea.Format(_T("%.1f"), dUseArea); break; case 2: csArea.Format(_T("%.2f"), dUseArea); break; case 3: csArea.Format(_T("%.3f"), dUseArea); break; case 4: csArea.Format(_T("%.4f"), dUseArea); break; case 5: csArea.Format(_T("%.5f"), dUseArea); break; case 6: csArea.Format(_T("%.6f"), dUseArea); break; case 7: csArea.Format(_T("%.7f"), dUseArea); break; case 8: csArea.Format(_T("%.8f"), dUseArea); break; default: csArea.Format(_T("%.2f"), dUseArea); break; } return csArea; } // 获取“房间编号”的绘制外包框 void TDbSpace::GetCodeExtentPts(XPoly2D &poly, XPoint pt, XVector3D vt) const { // XPoint ptTmp1, ptTmp2; // 对角线点 // double dYDist = vt.y*0.5 + 0.15*m_nTextHeight*GetPScale(), // Y方向上的偏移距离 // dXDist = vt.x*0.5 + 0.15*m_nTextHeight*GetPScale(); // X方向上的偏移距离 // ads_polar(pt, -PI/2, dYDist, ptTmp1); // ads_polar(pt, PI/2, dYDist, ptTmp2); // ads_polar(ptTmp1, 0, -dXDist, ptTmp1); // ads_polar(ptTmp2, 0, dXDist, ptTmp2); // // XRectAngle rect(ptTmp1, ptTmp2); // poly.flag = 1; // rect.AsPoly2D(poly); vt.x += vt.y * 0.3; // sg modify 081225,将外包框的算法与文字屏蔽一致 vt.y *= 1.3; // sg modify 090602,8.0的正式版起,将“文字转角”并入“布局转角” // double dXDir = GetRotation() + m_nLayoutRotation, double dXDir = m_nLayoutRotation, dYDir = dXDir + PI / 2.0; ads_polar(pt, dXDir + PI, vt.y*0.1, pt); // 调整中心位置 ads_polar(pt, dYDir + PI, vt.y*0.2, pt); XVector3D u(cos(dXDir), sin(dXDir), 0), v(cos(dYDir), sin(dYDir), 0); u *= vt.x; v *= vt.y; poly.SetFlag(1); poly.AppendNode(pt); poly.AppendNode(pt + u); poly.AppendNode(pt + u + v); poly.AppendNode(pt + v); } double TDbSpace::GetNameDistRatio(BOOL bChineseName) const // 名称位置 { double dResult = 0.7; // modify by xly on 101020,根据8.5需求,房间对象支持编号、名称、面积和面积单位的独立控制显示 // int nSpFlag = DocGetSpaceDispMode(); // if ((nSpFlag&SPF_NAME_AND_CODE) != 0) // 名称、编号同时标注 if (IsDimName() && IsDimCode()) // 名称、编号同时标注 { // sg modify 081225,“建筑轮廓”不绘制“编号” dResult = (m_nType == TDbSpace::kTotalArea) ? 0.7 : 1.6; // 单行名称 if (m_bMText) { dResult = bChineseName ? 2.25 : 1.1; // 两行名称 if (m_nType == TDbSpace::kTotalArea) // 建筑轮廓 { dResult = bChineseName ? 1.4 : 0.25; // 两行名称 } } } // else if (((nSpFlag&SPF_CODE) == 0) && (m_bMText)) // 只标注名称,且为两行文字 else if (IsDimName() && (m_bMText)) // 只标注名称,且为两行文字 { dResult = bChineseName ? 1.4 : 0.25; } return dResult; } double TDbSpace::GetCodeDistRatio() const // 编号位置 { double dResult = 0.7; // modify by xly on 101020,根据8.5需求,房间对象支持编号、名称、面积和面积单位的独立控制显示 // int nSpFlag = DocGetSpaceDispMode(); // if ((nSpFlag&SPF_NAME_AND_CODE) != 0) // 名称、编号同时标注 if (IsDimName() && IsDimCode()) // 名称、编号同时标注 { dResult = m_bMText ? (-0.25) : 0.25; } return dResult; } double TDbSpace::GetAreaDistRatio() const // 面积位置 { double dResult = -0.5; // modify by xly on 101020,根据8.5需求,房间对象支持编号、名称、面积和面积单位的独立控制显示 // int nSpFlag = DocGetSpaceDispMode(); // if ((nSpFlag&SPF_NAME_AND_CODE) != 0) // 名称、编号同时标注 if (IsDimName() && IsDimCode()) // 名称、编号同时标注 { dResult = (m_nType == TDbSpace::kTotalArea) ? -0.5 : -1.1; if (m_bMText) { dResult = (m_nType == TDbSpace::kTotalArea) ? -0.95 : -1.6; } } // else if (((nSpFlag&SPF_CODE) == 0) && (m_bMText)) // 只标注名称,且为两行文字 else if (IsDimName() && (m_bMText)) // 只标注名称,且为两行文字 { dResult = -0.95; } return dResult; } // sg add 081224,支持图形导出命令 Acad::ErrorStatus TDbSpace::DownGradeSave(int nDrawMode, AcDbVoidPtrArray &entSet, BOOL *bErase) { // sg add 090519,如果是按半面积标注,比如:阳台对象,则导出T7后,炸开 // sg modify 101209,如果房间名称和房间编号都不标注,导出T7后,炸开 // if (IsHalfArea()) if ((g_nSaveTArchVer > 3 && g_nSaveTArchVer < 8) && (IsHalfArea() || (!IsDimName() && !IsDimCode()))) { XExplodeStream dc(entSet); if (!OnExplodeOrDraw(dc)) return Acad::eOk; Acad::ErrorStatus es = Acad::eOk; dc.SetPropertiesFrom(this); if (nDrawMode == DRAW_2D) es = ExplodeOrDraw2d(dc); else es = ExplodeOrDraw3d(dc); if (bErase) *bErase = TRUE; return es; } int nSpFlag = DocGetSpaceDispMode(); // sg modify 101216,如果独立控制,导出T7后,炸开,但是需要特殊处理名称和房间编号全部标注的情况 if ((g_nSaveTArchVer>3 && g_nSaveTArchVer < 8) && (GetSpaceDispMode() == 0)) { if ((nSpFlag&SPF_NAME_AND_CODE) != 0 && IsDimName() && IsDimCode()) ; // 特殊处理一下,放置和以前的处理规则不统一,将编号变成单行文字 else { XExplodeStream dc(entSet); if (!OnExplodeOrDraw(dc)) return Acad::eOk; Acad::ErrorStatus es = Acad::eOk; dc.SetPropertiesFrom(this); if (nDrawMode == DRAW_2D) es = ExplodeOrDraw2d(dc); else es = ExplodeOrDraw3d(dc); if (bErase) *bErase = TRUE; return es; } } BOOL bFlag = // 是否Erase原来的,并clone出新对象的标记 m_bMText || HasHatch() || (nSpFlag&SPF_NAME_AND_CODE) != 0; if (bFlag && g_nSaveTArchVer > 3 && g_nSaveTArchVer < 8) // 导出为T5、T6、T7 { XString szName(1024); // sg modify 090423,解决图形导出崩溃问题 szName << m_sName; if (m_bMText) { szName << _T(" ") << m_sSndName; // 两行名称合并为一行 } if (HasHatch()) // 绘制“填充”,增加一个“填充”对象 { // sg modify 090512,解决角度导出后不起作用的问题 // AcDbHatch *pHatch = NewHatchFromPoly2D(m_outline, m_sHatchStyle, m_dHatchScale); // sg modify 090602,填充对象,也要考虑布局转角 // AcDbHatch *pHatch = NewHatchFromPoly2D(m_outline, m_sHatchStyle, m_dHatchScale, m_dHatchAngle); double dCurrentUcs = Ucs2Wcs(0.0); AcDbHatch *pHatch = NewHatchFromPoly2D(m_outline, m_sHatchStyle, m_dHatchScale, m_dHatchAngle + m_nLayoutRotation - dCurrentUcs); if (pHatch != NULL) { pHatch->setLayer(m_idHatchLayer); // sg modify 101207,8.5起支持真彩色设置,修改对应的填充对象导出; // pHatch->setColorIndex(m_nHatchColor); AcCmColor cmColor = GetHatchTrueColor(); pHatch->setColor(cmColor); // pHatch->setPatternAngle(m_dHatchAngle); entSet.append(pHatch); } } TDbSpace *pSpace = NULL; // sg modify 090325,防止导出T7崩溃 { XPushMemVar vTemp(g_nSaveTArchVer, _TCH_VERSION); pSpace = (TDbSpace*)clone(); } pSpace->SetMText(FALSE); pSpace->SetHasHatch(FALSE); pSpace->SetName(szName); entSet.append(pSpace); // 同时标注名称和编号,增加一个“单行文字” // sg add 090527,建筑轮廓不增加编号的单行文字 if ((nSpFlag&SPF_NAME_AND_CODE) != 0 && m_nType != TDbSpace::kTotalArea) { ads_matrix matRot; XPoint ptDim = m_ptLocation; ptDim.y += 1.9*m_nTextHeight*GetPScale(); m_ptLocation.GetRotationMatrix(Layout2Wcs(m_nRotation), matRot); ptDim.TransformBy(matRot); TDbText *pText = new TDbText; pText->CopyPropertiesFrom(this, 0); pText->SetMaskFlag(IsMask()); // 自动屏蔽 pText->SetHeight(m_nTextHeight); pText->SetStyleId(m_idTextStyle); pText->SetAlignment(XExplodeDraw::kMiddleCenter); // sg delete 090602,8.0的正式版起,将“文字转角”并入“布局转角” // pText->SetRotation(m_nRotation); pText->SetLocation(ptDim); pText->SetText(m_sCode); pText->setLayer(layerId()); pText->setColorIndex(colorIndex()); entSet.append(pText); } if (bErase) { *bErase = TRUE; } return Acad::eOk; } return TDbEntity::DownGradeSave(nDrawMode, entSet, bErase); // 其他情况,基类处理 } /////////////////////////////////////////////////////////////// // 显示房间: 编号/名称,面积 // _T("名称")在_T("面积")上面0.5mm Acad::ErrorStatus TDbSpace::ExplodeOrDraw2d(XExplodeDraw &dcText) const { assertReadEnabled(); std::vector holds(0);// 房间所产生的遮盖曲线 // 如果不需要屏蔽文字背景,则先画并且用TGGeSolid先画填充,再画文字 // modify jsx on 060524 TGGeSolid绘制填充的时候,无论是否屏蔽文字背景,都需要先绘制TGGeSolid填充。 if (m_sHatchStyle == "SOLID" || !IsMask()) { DrawHatchInExplode(dcText, holds); DrawTextInExplode(dcText, holds); } else { DrawTextInExplode(dcText, holds); DrawHatchInExplode(dcText, holds); } AcDbObjectId idMe = objectId(); BOOL bHighlight = !idMe; if (!bHighlight) bHighlight = IsHighlight(); if (bHighlight || IsShowOutline()) dcText << m_outline; return Acad::eOk; } Acad::ErrorStatus TDbSpace::ExplodeOrDraw3d(XExplodeDraw &dc) const { assertReadEnabled(); if (Has3D()) { XVector3D vt(0, 0, -m_nFloorThick); XPoly2D polyFloor = m_outline; polyFloor.SetElevation(GetElevation()); dc.DrawBody(polyFloor, vt); } return Acad::eOk; } int TDbSpace::ConvertText(TConvertTextPtr ptr, void *pData) { XString sText; int nRet = ptr(m_sName, sText, pData); if (nRet == RTNORM) { assertWriteEnabled(); m_sName = sText; } return nRet; } // 注:查找替换只需要支持对房间名称的操作 BOOL TDbSpace::GetText(Adesk::UInt32 cookies, TDbText &text) const { // if (cookies != 0) // sg modify 081212,支持两行名称 if ((m_bMText && cookies != 0 && cookies != 1) || (!m_bMText && cookies != 0)) return FALSE; XPoint ptName = m_ptLocation, // 名称或标号的位置,在上面 ptName2 = m_ptLocation, // 第二行名称,sg add 081212 ptArea = m_ptLocation; // 面积的位置,在下面 text.setPropertiesFrom(this); text.SetMaskFlag(IsMask()); // 自动屏蔽 // sg modify 110908,解决外部参照中包含房间标注中的崩溃问题 // 所有的数据从对象中保存的数据读取 /* //AcDbObjectId idStyle = InitTextStyle(TS_SPACE, database()); AcDbObjectId idStyle = InitTextStyle(TS_SPACE); ASSERT(!!idStyle); double nTextSize = 3.5; OPENOBJ_BEGIN(idStyle, AcDb::kForRead, AcDbTextStyleTableRecord, pStyle); ASSERT(pStyle); nTextSize = pStyle->textSize(); if (nTextSize < 1.0E-3) nTextSize = 3.5; OPENOBJ_END(); text.SetHeight(nTextSize); text.SetStyleId(idStyle); int nColor = GetTextStyleColor(idStyle); if (nColor > 0) text.setColorIndex(nColor); */ text.SetHeight(m_nTextHeight); text.SetStyleId(m_idTextStyle); double nTextSize = m_nTextHeight; nTextSize *= GetPScale(); // ptName.y += nTextSize*0.7; // sg modify 081211,只需要支持查找两行“房间名称” // ptArea.y -= nTextSize*0.5; ptName.y += nTextSize*GetNameDistRatio(TRUE); ptName2.y += nTextSize*GetNameDistRatio(FALSE); text.SetAlignment(XExplodeDraw::kMiddleCenter); // text.SetLocation(ptName); // sg modify 081212 // text.SetText(m_sName); if (cookies == 1) // 第二行名称 { text.SetLocation(ptName2); text.SetText(m_sSndName); } else // 第一行名称 { text.SetLocation(ptName); text.SetText(m_sName); } return TRUE; } // 返回发现的位置,同时posStart往前移动(以便继续找下一个使用), TTextPosition TDbSpace::FindSubText(const TCHAR *sSubText, TTextPosition &posStart, TTextRange *pRange) const { TTextPosition pos; if (!sSubText || !sSubText[0]) return pos; TTextPosition posNext = posStart; while (1) { TDbText text; if (!GetText(posNext.m_nCookies, text)) break; TTextPosition posFind = text.FindSubText(sSubText, posNext, pRange); if (!posFind) { posNext.m_nCookies++; posNext.m_nTextPos = 0; } else { posStart = posNext; if (!posStart) { posStart.m_nCookies++; posStart.m_nTextPos = 0; } posFind.m_nCookies = posNext.m_nCookies; pos = posFind; break; } } return pos; } // 返回下一次查找的开始位置 TTextPosition TDbSpace::ReplaceSubText(const TTextPosition &posRep, const TCHAR *sRepText, TTextRange *pRange) { assertWriteEnabled(); TTextPosition posNext; TDbText text; if (!GetText(posRep.m_nCookies, text)) return posNext; posNext = text.ReplaceSubText(posRep, sRepText, pRange); int cookies = posRep.m_nCookies; if (cookies == 0) // 第一行名称,sg modify 081212 { SetName(text.GetText()); } else if (cookies == 1) // 第二行名称 { SetSndName(text.GetText()); // 修改第二行 } /* else if (cookies == 1) { SetText2 (text.GetText()); } */ if (!posNext) { posNext.m_nCookies = posRep.m_nCookies + 1; posNext.m_nTextPos = 0; } return posNext; } void TDbSpace::CreateWipeOut(AcDbVoidPtrArray &entSet) const { AcDbVoidPtrArray ssText; XExplodeStream dc(ssText); dc.SetPropertiesFrom(this); // add by whl on 060404 ExplodeOrDraw2d(dc); int nLen = ssText.length(); for (int i = 0; i < nLen; i++) { TDbText *pText = TDbText::cast((AcRxObject*)ssText[i]); if (pText) { AcDbEntity *pEnt = pText->CreateWipeOut(); if (pEnt) entSet.append(pEnt); } } } ////////////////////////////////////////////////////////////////// // 取 动 态 属 性 显 示 数 据 的 函 数 void TDbSpace::GetTips(DList &lstInfo) const { lstInfo.Append(new TObjInfoUnit(_T("对象类型"), _T("房间"))); lstInfo.Append(new TObjInfoUnit(_T("编号"), m_sCode)); // lstInfo.Append(new TObjInfoUnit(_T("名称"), m_sName)); // sg modify 081212 if (m_bMText) // 两行名称 { lstInfo.Append(new TObjInfoUnit(_T("名称1"), m_sName)); lstInfo.Append(new TObjInfoUnit(_T("名称2"), m_sSndName)); } else // 单行名称 lstInfo.Append(new TObjInfoUnit(_T("名称"), m_sName)); // add xly on 101019,显示房间对象归属套内面积的户号 if (m_nType == kBalconyArea) // 套内阳台 { AcDbObjectId idHouse = GetHouseId(); TDbSpace *pSpace = NULL; if (idHouse.isValid()) // 套内阳台有户号 { CString csCode = _T(""); acdbOpenObject(pSpace, idHouse, AcDb::kForRead); if (pSpace != NULL) { csCode = pSpace->m_sCode; pSpace->close(); } lstInfo.Append(new TObjInfoUnit(_T("归属户号"), csCode)); } else // 套内阳台不属于套内面积 { lstInfo.Append(new TObjInfoUnit(_T("归属户号"), _T(""))); } } lstInfo.Append(new TObjInfoUnit(_T("面积"), XString(_T("%.2f"), m_nUseArea))); lstInfo.Append(new TObjInfoUnit(_T("体积"), XString(_T("%.3f"), GetUseVolume()))); lstInfo.Append(new TObjInfoUnit(_T("周长"), Dist2Str(m_nPerimeter))); // sg modify 090526,多数情况下,m_nKickboardLength也没有随着轮廓线的更新而更新,造成显示错误,因此在此重新计算 // 如果围护结构不存在,踢脚长必然等于周长;有门存在,踢脚线长等于周长,减去门的总长度 double dKickboardLen = m_nKickboardLength; int nLength = m_lstWallEnclosure.Length(); if (nLength == 0) dKickboardLen = m_nPerimeter; // lstInfo.Append(new TObjInfoUnit(_T("踢脚长"), Dist2Str(m_nKickboardLength))); lstInfo.Append(new TObjInfoUnit(_T("踢脚长"), Dist2Str(dKickboardLen))); lstInfo.Append(new TObjInfoUnit(_T("墙壁面积"), XString(_T("%.2f"), m_nWallSurfArea))); lstInfo.Append(new TObjInfoUnit(_T("外墙面积"), XString(_T("%.2f"), m_nExtWallArea))); lstInfo.Append(new TObjInfoUnit(_T("外门面积"), XString(_T("%.2f"), m_nExtDoorArea))); lstInfo.Append(new TObjInfoUnit(_T("外窗面积"), XString(_T("%.2f"), m_nExtWinArea))); } const TCHAR * TDbSpace::GetDefaultLayer() const { return LAY_SPACE; } /////////////////////////////////////////////////////////////////////////////////////////////////////// // 搜索房间中取得数据 Acad::ErrorStatus TDbSpace::UpdateFrom(const XAecSpaceCell &src, BOOL bExtSpace) { double nTotalDoorWidth = 0.0, nTotalHoleArea = 0.0; double nExtWinArea = 0.0, nExtDoorArea = 0.0, nExtWallArea = 0.0; //add by whl on 060329,否则搜索房间会重复记录 m_lstWallEnclosure.Reset(); double dMinHeight = 0.0; for (int k = 0; k < src.Length(); k++) { const XAecSpaceWall &wall = src[k]; OPENOBJ_BEGIN(wall.m_ent.name, AcDb::kForRead, TDbWall, pDbWall); if (pDbWall) { ///////////////////////////////////////////////////////////////////////// // 建立墙和房间的关联, 供概预算软件使用 m_lstWallEnclosure.Append(new AcDbObjectId(pDbWall->objectId())); //不驻留DWG if (objectId()) { if (pDbWall->upgradeOpen() == Acad::eOk) { ASSERT(wall.leftSpace == &src || wall.rightSpace == &src); if (wall.leftSpace == &src) pDbWall->SetLeftSpace(objectId()); else pDbWall->SetRightSpace(objectId()); pDbWall->downgradeOpen(); } } double nHoleArea = _AS_SQMETER(pDbWall->GetHoleArea()); nTotalHoleArea += nHoleArea; DList lstOpenings; pDbWall->GetOpenings(lstOpenings, TRUE); for (int i = 0; i < lstOpenings.Length(); i++) { TOpeningData *pOpening = lstOpenings[i]; if (pOpening->GetKind() == TOpeningData::OP_DOOR) nTotalDoorWidth += pOpening->GetWidth(); } if (pDbWall->IsExternal(0)) { nExtWallArea += _AS_SQMETER(pDbWall->GetSurfaceArea(0)); nExtWinArea += _AS_SQMETER(pDbWall->GetHoleArea(TOpeningData::OP_WINDOW) + pDbWall->GetHoleArea(TOpeningData::OP_PROWIN) + pDbWall->GetHoleArea(TOpeningData::OP_ARCWIN)); nExtDoorArea += _AS_SQMETER(pDbWall->GetHoleArea(TOpeningData::OP_DOOR)); } else if (pDbWall->IsExternal(1)) { nExtWallArea += _AS_SQMETER(pDbWall->GetSurfaceArea(1)); nExtWinArea += _AS_SQMETER(pDbWall->GetHoleArea(TOpeningData::OP_WINDOW) + pDbWall->GetHoleArea(TOpeningData::OP_PROWIN) + pDbWall->GetHoleArea(TOpeningData::OP_ARCWIN)); nExtDoorArea += _AS_SQMETER(pDbWall->GetHoleArea(TOpeningData::OP_DOOR)); } if (dMinHeight < 1e-6 || pDbWall->GetHeight() < dMinHeight) dMinHeight = pDbWall->GetHeight(); } OPENOBJ_END(); } XPoly2D polyWall(1), polyCen; ((XAecSpaceCell &)src).InternalPoly2D(polyWall, bExtSpace ? 2 : 1); ((XAecSpaceCell &)src).CenterPoly2D(polyCen); polyWall.SetElevation(0.0); m_nUseArea = _AS_SQMETER(polyWall.Area()); m_nOccuArea = _AS_SQMETER(polyCen.Area()); m_nCeilArea = _AS_SQMETER(polyWall.Area()); //m_nHeight, m_nPerimeter = polyWall.Distance2d(); m_nWallSurfArea = _AS_SQMETER(m_nHeight*m_nPerimeter) - nTotalHoleArea; m_nKickboardLength = m_nPerimeter - nTotalDoorWidth; m_nExtWinArea = nExtWinArea; m_nExtDoorArea = nExtDoorArea; m_nExtWallArea = nExtWallArea; m_outline = polyWall; if (bExtSpace && m_outline.PathArea() > 0.0) m_outline.Reverse(); else if (!bExtSpace && m_outline.PathArea() < 0.0) m_outline.Reverse(); m_nHeight = dMinHeight; // 节能修改要求,高度设为最小墙高,modified by wyg 20090624 // m_nHeight=DocGetLHeight();//add by whl on 051227 return Acad::eOk; } BOOL TDbSpace::IsMask() const { return ((m_nSpaceFlag&SF_MASK) != 0); } BOOL TDbSpace::IsHighlight() const { return ((m_nSpaceFlag&SF_HIGHLIGHT) != 0); } BOOL TDbSpace::IsShowOutline() const { return ((m_nSpaceFlag&SF_SHOWOUTLINE) != 0); } void TDbSpace::SetMask(BOOL bTrue) { assertWriteEnabled(); if (bTrue) m_nSpaceFlag |= SF_MASK; else m_nSpaceFlag &= ~SF_MASK; } void TDbSpace::SetHighlight(BOOL bTrue) { assertWriteEnabled(); if (bTrue) m_nSpaceFlag |= SF_HIGHLIGHT; else m_nSpaceFlag &= ~SF_HIGHLIGHT; } void TDbSpace::SetShowOutline(BOOL bTrue) { assertWriteEnabled(); if (bTrue) m_nSpaceFlag |= SF_SHOWOUTLINE; else m_nSpaceFlag &= ~SF_SHOWOUTLINE; } // sg modify 081212,两行名称,及名称、编号同时显示 // 注:在位编辑,需要支持名称和编号 void TDbSpace::SetSubText(long i, CString sText) { assertWriteEnabled(); // xly modify 101111,根据8.5需求,房间对象支持编号、名称、面积和面积单位的独立控制显示 // int nSpFlag = DocGetSpaceDispMode(); BOOL bShowName = IsDimName(), bShowCode = IsDimCode(); if (i == 0) { // if ((nSpFlag&SPF_CODE) != 0) if (bShowCode && !bShowName) SetCode(sText); // 编号 // else else if (bShowCode || bShowName) SetName(sText); // 名称(同时标注时,也是名称在编号之上) } else if (i == 1) { // if ((nSpFlag&SPF_NAME_AND_CODE) != 0) if (bShowName && bShowCode) // 同时标注 { if (m_bMText) { SetSndName(sText); // 两行名称中的第二行 } else if (m_nType != TDbSpace::kTotalArea) { SetCode(sText); // 编号 } } // else if ((nSpFlag&SPF_CODE)==0 && m_bMText) // 只标注名称,但为两行名称 else if (bShowCode && m_bMText) // 只标注名称,但为两行名称 { SetSndName(sText); // 两行名称中的第二行 } } else if (i == 2) { // if ((nSpFlag&SPF_NAME_AND_CODE)!=0 && m_bMText && (m_nType!=TDbSpace::kTotalArea)) if (bShowName && bShowCode && m_bMText && (m_nType != TDbSpace::kTotalArea)) { SetCode(sText); // 同时标注,且为两行名称时的编号 } } } // sg add 111116,支持导出XML CString TDbSpace::GetXml(const AcGeMatrix3d& mat) const { TXmlTree xmlTree; POSITION posRoot = xmlTree.Insert(_T("ATS_SPACE"), NULL, NULL); { xmlTree.SetAttribute(posRoot, _T("name"), _T("房间")); xmlTree.SetAttribute(posRoot, _T("comment"), _T("上华对象名称")); } CString strText; POSITION posItem1 = xmlTree.Insert(_T("Object_ID"), posRoot, NULL); { xmlTree.SetAttribute(posItem1, _T("name"), _T("对象编号")); xmlTree.SetAttribute(posItem1, _T("comment"), _T("当前对象的句柄")); strText.Format(_T("%ld"), objectId()); xmlTree.SetItemText(posItem1, strText); } POSITION posItem = NULL; POSITION posItem2 = xmlTree.Insert(_T("Area"), posRoot, posItem1); { xmlTree.SetAttribute(posItem2, _T("name"), _T("面积参数")); posItem = NULL; posItem = xmlTree.Insert(_T("Area_feature"), posItem2, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("面积性质")); AreaType nType = GetType(); switch (nType) { case kUseArea: strText = _T("使用面积"); break; case kHouseArea: strText = _T("套内面积"); break; case kTotalArea: strText = _T("建筑面积"); break; case kHoleArea: strText = _T("洞口面积"); break; case kShareArea: strText = _T("公摊面积"); break; case kBalconyArea: strText = _T("阳台面积"); break; case kOther: strText = _T("其他面积"); break; } xmlTree.SetItemText(posItem, strText); } posItem = xmlTree.Insert(_T("Area_half"), posItem2, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("面积取一半")); strText = IsHalfArea() ? _T("1") : _T("0"); xmlTree.SetItemText(posItem, strText); } posItem = xmlTree.Insert(_T("Area_thick"), posItem2, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("地板厚度")); strText.Format(_T("%.0f"), GetFloorThick()); xmlTree.SetItemText(posItem, strText); } posItem = xmlTree.Insert(_T("Area_finish"), posItem2, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("粉刷层厚度")); strText.Format(_T("%.0f"), GetStuccoThickness()); xmlTree.SetItemText(posItem, strText); } } POSITION posItem3 = xmlTree.Insert(_T("Room"), posRoot, posItem2); { xmlTree.SetAttribute(posItem3, _T("name"), _T("房间参数")); posItem = NULL; posItem = xmlTree.Insert(_T("Room_Name1"), posItem3, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("房间名称")); xmlTree.SetItemText(posItem, m_sName); } if (m_bMText) { posItem = xmlTree.Insert(_T("Room_Name2"), posItem3, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("房间别名")); xmlTree.SetItemText(posItem, m_sSndName); } } posItem = xmlTree.Insert(_T("Room_Number"), posItem3, posItem); { xmlTree.SetAttribute(posItem, _T("name"), _T("房间编号")); xmlTree.SetItemText(posItem, m_sCode); } // cet 2013.7.25 add 导出编号位置 posItem = xmlTree.Insert(_T("LabelPosition"), posItem3, posItem); { XPoint ptLoc = m_ptLocation; ptLoc.TransformBy(mat); xmlTree.SetAttribute(posItem, _T("name"), _T("标记位置")); strText.Format(_T("%f,%f,%f"), ptLoc.x, ptLoc.y, ptLoc.z); xmlTree.SetItemText(posItem, strText); } } POSITION posItem4 = xmlTree.Insert(_T("Baseline"), posRoot, posItem3); { xmlTree.SetAttribute(posItem4, _T("name"), _T("房间轮廓")); posItem = NULL; TADSGePoint3d ptNode; int nLen = m_outline.Length(); for (int i = 0; i < nLen; i++) { ptNode = m_outline[i]; // sg add 120117,对点进行坐标变换 ptNode.TransformBy(mat); strText.Format(_T("Point_%d"), i + 1); posItem = xmlTree.Insert(strText, posItem4, posItem); { strText.Format(_T("第%d点"), i + 1); xmlTree.SetAttribute(posItem, _T("name"), strText); strText.Format(_T("%f,%f,%f"), ptNode.x, ptNode.y, ptNode.z); xmlTree.SetItemText(posItem, strText); } strText.Format(_T("Ang_%d"), i + 1); posItem = xmlTree.Insert(strText, posItem4, posItem); { strText.Format(_T("圆心角%d"), i + 1); xmlTree.SetAttribute(posItem, _T("name"), strText); strText.Format(_T("%f"), m_outline.GetBulge(i)); xmlTree.SetItemText(posItem, strText); } } } CString strBase = TEntityBase::GetXml(mat); CString strXml = xmlTree.GetXml(); int nIndex = strXml.Find(_T(" &holds) const { if (!HasHatch() || !m_sHatchStyle) return; TMasterProperties prop; dc.BackUpProperties(prop); #if ADS < 16 // 15平台没有真彩色 dcText.SetColorLayer(m_nHatchColor, m_idHatchLayer); #else dc.SetLayer(m_idHatchLayer); AcCmColor color = GetHatchTrueColor(); dc.SetTrueColor(color); #endif if (m_sHatchStyle == _T("SOLID") /*&& !IsMask()*/) { dc << TGGeSolid(m_outline); } else { double dTmp = Ucs2Wcs(0.0); TGGeHatch hatch(m_outline, m_sHatchStyle, m_dHatchScale, m_dHatchAngle + m_nLayoutRotation - dTmp); hatch.SetHatchPoly(m_outline); // 确保最外面曲线被正确设置。 if (IsMask() && !holds.empty()) hatch.AppendPoly(holds); dc << hatch; } dc.RestoreProperties(prop); #if ADS > 15 // 15平台没有真彩色 AcCmColor colorOld; colorOld.setColorIndex(colorIndex()); dc.SetTrueColor(colorOld); #endif } void TDbSpace::DrawTextInExplode(TGGiExplodeDrawBase &dc, std::vector &holds) const { BOOL bShowName = IsDimName(), bShowCode = IsDimCode(); if (bShowName && bShowCode) // 同时标注编号和名称 { TDbText text; text.setPropertiesFrom(this); text.SetMaskFlag(IsMask()); // 自动屏蔽 AcDbObjectId idStyle = m_idTextStyle; assert(!!idStyle); double nTextSize = m_nTextHeight; text.SetHeight(nTextSize); text.SetStyleId(idStyle); nTextSize *= GetPScale(); text.SetAlignment(XExplodeDraw::kMiddleCenter); // sg delete 090602,8.0的正式版起,将“文字转角”并入“布局转角” // text.SetRotation(m_nRotation); // 文字角度 ads_matrix matRot; // sg modify 090602,8.0的正式版起,将“文字转角”并入“布局转角” // m_ptLocation.GetRotationMatrix(Layout2Wcs(m_nRotation), matRot); m_ptLocation.GetRotationMatrix(m_nLayoutRotation, matRot); if (!!m_sCode || !!m_sName || g_bExplodeSubText) { XPoint ptDim = m_ptLocation; ptDim.y += nTextSize*GetNameDistRatio(TRUE); // 名称位置,sg modify 081212 ptDim.TransformBy(matRot); text.SetLocation(ptDim); text.SetText(m_sName); if (dc.IsFullExplode()) // 先标注房间名称 text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); if (m_bMText) // 两行名称文字,sg add 081212 { ptDim = m_ptLocation; ptDim.y += nTextSize*GetNameDistRatio(FALSE); ptDim.TransformBy(matRot); text.SetLocation(ptDim); text.SetText(m_sSndName); if (dc.IsFullExplode()) // 标注第二行房间名称 text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); } if (m_nType != TDbSpace::kTotalArea) // 除建筑轮廓外,标编号,sg add 081225 { ptDim = m_ptLocation; ptDim.y += nTextSize*GetCodeDistRatio(); // 编号位置 ptDim.TransformBy(matRot); text.SetLocation(ptDim); text.SetText(m_sCode); if (dc.IsFullExplode()) // 再标注房间编号 text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); XVector3D vtExt = text.GetExtents(); ptDim = text.Align2Base(ptDim, vtExt); XPoly2D polyExtents; // sg add 081211,增加绘制编号外包框的功能 GetCodeExtentPts(polyExtents, ptDim, vtExt); dc << polyExtents; } } if (IsDimArea()) { XPoint ptArea = m_ptLocation; ptArea.y += nTextSize*GetAreaDistRatio(); // 面积位置 ptArea.TransformBy(matRot); text.SetLocation(ptArea); text.SetHeight(text.GetHeight()*0.7); CString csUseArea = GetAreaByPrecision(); // sg modify 081127 if (IsDimUnit()) csUseArea = csUseArea + _T("m^U2^U"); text.SetText(csUseArea); if (dc.IsFullExplode()) text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); } } // else // 只显示名称或编号 else if (bShowName || bShowCode) // 只显示名称或编号 { XPoint ptName = m_ptLocation; // 名称或者标号的位置,在上面 XPoint ptName2 = m_ptLocation; // sg add 081212,第二行名称 XPoint ptArea = m_ptLocation; // 面积的位置,在下面 TDbText text; text.setPropertiesFrom(this); text.SetMaskFlag(IsMask()); // 自动屏蔽 AcDbObjectId idStyle = m_idTextStyle; assert(!!idStyle); double nTextSize = m_nTextHeight; text.SetHeight(nTextSize); text.SetStyleId(idStyle); nTextSize *= GetPScale(); ptName.y += nTextSize*GetNameDistRatio(TRUE); ptArea.y += nTextSize*GetAreaDistRatio(); text.SetAlignment(XExplodeDraw::kMiddleCenter); // sg delete 090602,8.0的正式版起,将“文字转角”并入“布局转角” // text.SetRotation(m_nRotation); ads_matrix matRot; // sg modify 090602,8.0的正式版起,将“文字转角”并入“布局转角” // m_ptLocation.GetRotationMatrix(Layout2Wcs(m_nRotation), matRot); m_ptLocation.GetRotationMatrix(m_nLayoutRotation, matRot); ptName.TransformBy(matRot); ptArea.TransformBy(matRot); // XString sDisp = ((nSpFlag&SPF_CODE)!=0? m_sCode : m_sName); XString sDisp = (bShowCode ? m_sCode : m_sName); if (!!sDisp || g_bExplodeSubText) { text.SetLocation(ptName); if (m_nType == TDbSpace::kTotalArea) // 建筑轮廓永远显示名称,sg modify 090320 sDisp = m_sName; text.SetText(sDisp); if (dc.IsFullExplode()) text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); // sg add 081212,只标注名称,且为两行文字 // if ((nSpFlag&SPF_CODE)==0 && m_bMText) if (bShowName && m_bMText) { ptName2.y += nTextSize * GetNameDistRatio(FALSE); ptName2.TransformBy(matRot); text.SetLocation(ptName2); text.SetText(m_sSndName); if (dc.IsFullExplode()) text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); } } // if (nSpFlag&SPF_AREA) // 标注面积 if (IsDimArea()) // 标注面积 { text.SetLocation(ptArea); text.SetHeight(text.GetHeight()*0.7); CString csUseArea = GetAreaByPrecision(); // sg modify 081127 // if (nSpFlag&SPF_UNIT) if (IsDimUnit()) csUseArea = csUseArea + _T("m^U2^U"); text.SetText(csUseArea); if (dc.IsFullExplode()) text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); } } else // add by xly on 101018,名称、编号都不显示 { if (IsDimArea()) // 标注面积 { // 设置文字信息 TDbText text; text.setPropertiesFrom(this); text.SetMaskFlag(IsMask()); // 自动屏蔽 AcDbObjectId idStyle = m_idTextStyle; assert(!!idStyle); double nTextSize = m_nTextHeight; text.SetHeight(nTextSize); text.SetStyleId(idStyle); nTextSize *= GetPScale(); text.SetAlignment(XExplodeDraw::kMiddleCenter); XPoint ptArea = m_ptLocation; ptArea.y -= nTextSize*GetAreaDistRatio(); ads_matrix matRot; m_ptLocation.GetRotationMatrix(m_nLayoutRotation, matRot); text.SetLocation(ptArea); text.SetHeight(text.GetHeight()*0.7); CString csUseArea = GetAreaByPrecision(); if (IsDimUnit()) // 面积单位的显示 csUseArea = csUseArea + _T("m^U2^U"); text.SetText(csUseArea); if (dc.IsFullExplode()) text.ExplodeOrDraw2d(dc); else dc.DrawEntity(text); text.GetMaskPoly(holds); } } } #if 0 /* ----------------------------------------------------------------------- */ ///////////////////////////////////////////////////////////////////////////////////// // 通过量化属性取得属性量 Acad::ErrorStatus TDbSpace::GetQuantumByName(const TCHAR *pszName, double *pQuantum) const { ASSERT(pszName && pQuantum); Acad::ErrorStatus es = Acad::eOk; double nRes=0.0; if(strcmp(pszName, SP_QUANTUM_1)==0) { nRes = GetUseArea(); } else if(strcmp(pszName, SP_QUANTUM_2)==0) { nRes = GetCeilArea(); } else if(strcmp(pszName, SP_QUANTUM_3)==0) { nRes = GetOccuArea(); } else if(strcmp(pszName, SP_QUANTUM_4)==0) { nRes = GetWallSurfArea(); } else if(strcmp(pszName, SP_QUANTUM_5)==0) { nRes = AS_METER(GetPerimeter()); } else if(strcmp(pszName, SP_QUANTUM_6)==0) { nRes = AS_METER(GetKickboard()); } else if(strcmp(pszName, SP_QUANTUM_7)==0) { nRes = GetUseVolume(); } else { es = Acad::eInvalidInput; } *pQuantum = nRes; return es; } /////////////////////////////////////////////////////////// // 初始化注册量化的属性名字 void TDbSpace::InitQuantumProtocol(BOOL bTrue) { static XQuantumProtocol *pProtocol=NULL; if(bTrue) { pProtocol=new XQuantumProtocol; pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_1)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_2)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_3)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_4)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_5)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_6)); pProtocol->m_lstQuantumNames.Append(strnew(SP_QUANTUM_7)); desc()->addX(XQuantumProtocol::desc(), pProtocol); } else { desc()->delX(XQuantumProtocol::desc()); delete pProtocol; pProtocol = NULL; } } #endif int EditSpace0(AcDbObjectId id) { OPENOBJ_BEGIN(id, AcDb::kForRead, TDbSpace, pSpace); if (!pSpace) return RTERROR; while (1) { adsout << _T("\n选择 [名称(N)/编号(C)/参数(L)]<退出>: "); XString sKeyword; int nRet = 0; INITGET_BEG(0, _T("N C L")); nRet = ads_getkword(_T(""), sKeyword); INITGET_END(); if (nRet != RTNORM) break; if (sKeyword[0] == _T('N')) { XString sName; if (ads_getstring(0, _T("\n房间名称:"), sName) == RTNORM) { if (pSpace->upgradeOpen() != Acad::eOk) return RTERROR; pSpace->assertWriteEnabled(); pSpace->m_sName = sName; pSpace->downgradeOpen(); } } else if (sKeyword[0] == _T('C')) { XString sCode; if (ads_getstring(0, _T("\n房间名称:"), sCode) == RTNORM) { if (pSpace->upgradeOpen() != Acad::eOk) return RTERROR; pSpace->assertWriteEnabled(); pSpace->m_sCode = sCode; pSpace->downgradeOpen(); } } else if (sKeyword[0] == _T('L')) { pSpace->list(); } } OPENOBJ_END(); return RTNORM; } void InitDbSpace(BOOL bTrue) { if (bTrue) { TDbSpace::rxInit(); TDbSpace::SetEditMethod(EditSpace0); acrxBuildClassHierarchy(); //TDbSpace::InitProperty(TRUE); TDbSpace::InitMatchProtocol(TRUE); } else { //TDbSpace::InitQuantumProtocol(FALSE); //TDbSpace::InitProperty(FALSE); TDbSpace::InitMatchProtocol(FALSE); deleteAcRxClass(TDbSpace::desc()); } } // 通过一点确定一房间的信息 // ptPick--WCS point // Return: 0--Fail, 1--Normal Space, 2--External Space int GenSpaceInfo(const XPoint &ptPick0, TDbSpace &space, BOOL bIgnoreVirt) { XPoint ptPick = ptPick0; ptPick.z = 0; BOOL bFindExtSpace = FALSE; // 找到所有墙 PickSet ssWalls0(SS_FREE); if (ssWalls0.Get(_T("X"), NULL, NULL, RBList(RTDXF0, _T("ATS_WALL,ATS_CURTAIN_WALL"), NULL)) != RTNORM) return 0; PickSet ssWalls(SS_FREE); if (bIgnoreVirt) { long num = ssWalls0.Length(); for (long n = 0; n < num; n++) { Entity ent = ssWalls0[n]; BOOL bVirt = FALSE; OPENOBJ_BEGIN(ent, AcDb::kForRead, TDbWall, pWall); if (pWall) { if (pWall->GetUsageFlag() == TWallData::kVirtual) bVirt = TRUE; } OPENOBJ_END(); if (!bVirt) ssWalls += ent; } } else { ssWalls += ssWalls0; } DList lstColu; GetEntFromBlockByDxf(lstColu, _T("ATS_COLUMN")); XSearchSpaceFromWall aSearch; try { aSearch.InitStart(ssWalls, lstColu); } catch (...) { adsout << /*UMSG*/_T("\n发生例外情况!"); return 0; } int nWallNumber = aSearch.walls.Length(); // Search the most near wall XAecSpaceWall *pNearestWall = NULL; ads_real nMinDist = 0.0; for (int i = 0; i < nWallNumber; i++) { XPoint ptProject; XAecSpaceWall *pWall = aSearch.walls[i]; if (pWall->ProjectToMe(ptPick, ptProject) != RTNORM || (ptProject&(*pWall)) != PR_INSIDE) continue; ptProject.z = ptPick.z; //忽略Z坐标 ads_real nDist = ads_distance(ptPick, ptProject); if (!pNearestWall) { nMinDist = nDist; pNearestWall = pWall; } else if (nDist < nMinDist) { nMinDist = nDist; pNearestWall = pWall; } } int nRet = RTERROR; XPoly2D poly(1); int nWho = 0; //1:left; 2:right BOOL bSubtract = TRUE; //用相减的方法,适合于室内; 否则为室外 XAecSpaceCell lSpace, rSpace; if (pNearestWall && aSearch.SearchTwoSpace(*pNearestWall, lSpace, rSpace) == RTNORM) { //找出2房间 XPoly2D lPoly, rPoly; lSpace.CenterPoly2D(lPoly); rSpace.CenterPoly2D(rPoly); int nPrFlag1 = ptPick&lPoly; int nPrFlag2 = ptPick&rPoly; if (nPrFlag1 == PR_INSIDE && nPrFlag2 == PR_INSIDE) { lSpace.InternalPoly2D(lPoly, 0, 0); rSpace.InternalPoly2D(rPoly, 0, 0); //Both include ptPick, then the smaller space is required ads_real nArea1 = lPoly.Area(); ads_real nArea2 = rPoly.Area(); if (nArea1 < nArea2) { poly = lPoly; nWho = 1; } else { poly = rPoly; nWho = 2; } nRet = RTNORM; } else if (nPrFlag1 == PR_INSIDE) { poly = lPoly; nWho = 1; nRet = RTNORM; } else if (nPrFlag2 == PR_INSIDE) { poly = rPoly; nWho = 2; nRet = RTNORM; } else { // Both exclude ptPick, then the larger space is required ads_real nArea1 = lPoly.Area(); ads_real nArea2 = rPoly.Area(); if (nArea1 > nArea2) { poly = lPoly; nWho = 1; } else { poly = rPoly; nWho = 2; } nRet = RTNORM; bSubtract = FALSE; } } else if (pNearestWall) { lSpace.Reset(); rSpace.Reset(); if (aSearch.SearchOneSpace(*pNearestWall, 0, lSpace) == RTNORM) { lSpace.CenterPoly2D(poly); if ((ptPick&poly) == PR_INSIDE) { nWho = 1; nRet = RTNORM; } } else if (aSearch.SearchOneSpace(*pNearestWall, 1, rSpace) == RTNORM) { rSpace.CenterPoly2D(poly); if ((ptPick&poly) == PR_INSIDE) { nWho = 2; nRet = RTNORM; } } } if (nWho && nRet == RTNORM) { if (bSubtract == FALSE) { bFindExtSpace = TRUE; } //扣除柱子部分 XAecSpaceCell *pSpace = nWho == 1 ? &lSpace : &rSpace; space.UpdateFrom(*pSpace, bFindExtSpace); if (bFindExtSpace) return 2; return 1; } return 0; }