#include "stdafx.h" //////////////////////////////////////////////////////////////////// // 门窗数据类 //////////////////////////////////////////////////////////////////// TOpeningData::TOpeningData(): m_pBayWin(NULL) { m_opKind = OP_DOOR; m_nThickness = 120.0; m_nWidth=m_nHeight=1500.0; m_nRotation=0.0; m_nBulge=0.0; // Add on 2003/12/16 m_nQuadrant = 0; m_nOpStyle = 0; m_nSlotExt=m_nSlotWidth=0.0; // Add on 2003/12/16 m_nDoorWidth=m_nWinHeight=0; m_nOpStyleEx=0; m_nProWinSlabWidth=100; m_nCornWinProtrude=0; m_dInsWidth = 0.0; m_nMaterial = 0; m_bSlotInsCap = 1; m_dInsBack = 0.0; m_dCornWinTrueProtrude = 0; // sg add 120606,转角窗出挑长度 } // 窗的数据拷贝 TOpeningData & TOpeningData::operator = (const TOpeningData &src) { m_ptLocation = src.m_ptLocation; m_ptLabel = src.m_ptLabel; m_nWidth = src.m_nWidth; m_nThickness = src.m_nThickness; m_nHeight = src.m_nHeight; m_nRotation = src.m_nRotation; m_nQuadrant = src.m_nQuadrant; m_opKind = src.m_opKind; m_nBulge = src.m_nBulge; m_sLabel = src.m_sLabel; m_nIdStyle2d = src.m_nIdStyle2d; m_nIdStyle3d = src.m_nIdStyle3d; m_nIdOfWall = src.m_nIdOfWall; m_nOpStyle = src.m_nOpStyle; m_nOpStyleEx =src.m_nOpStyleEx; m_nSlotExt = src.m_nSlotExt; m_nSlotWidth = src.m_nSlotWidth; if(m_pBayWin) delete m_pBayWin; m_pBayWin=NULL; if(src.m_pBayWin) { m_pBayWin = new XBayWindow(*src.m_pBayWin); } m_nDoorWidth=src.m_nDoorWidth; m_nWinHeight=src.m_nWinHeight; //add by whl on 081021 m_nProWinSlabWidth=src.m_nProWinSlabWidth; m_nCornWinProtrude=src.m_nCornWinProtrude; m_nMaterial = src.m_nMaterial; m_dInsWidth = src.m_dInsWidth; m_dInsBack = src.m_dInsBack; m_bSlotInsCap = src.m_bSlotInsCap; // sg add 120606,转角窗出挑长度 m_dCornWinTrueProtrude = src.m_dCornWinTrueProtrude; return *this; } BOOL TOpeningData::IsLinear() const { BOOL bFirstCase; OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pWall); bFirstCase=(pWall==NULL); if(!bFirstCase) { if(pWall->Is(CURVE_ARC)) { if(GetKind()!=TOpeningData::OP_ARCWIN && GetKind()!=TOpeningData::OP_CORNWIN) bFirstCase=TRUE; } else bFirstCase=TRUE; } OPENOBJ_END(); return bFirstCase; } void TOpeningData::SetHigh(BOOL bTrue) { m_nOpStyle &= ~OPS_ATHIGH; if(bTrue) { if (m_opKind == OP_WINDOW || m_opKind == OP_ARCWIN) { m_nOpStyle |= OPS_ATHIGH; } } } //////////////////////////////////////////////////////////////////// // 取得在水平方向上的门窗轮廓 // nZ--指定的水平标高 // poly: 一定是4边, 0,2边为侧边, 1,3与墙壁重合, 对于不穿透的洞, 边1在墙体内 //void TOpeningData::GetOutlinePoly(ads_real nZ, XPoly2D &poly) const void TOpeningData::GetOutlinePoly(ads_real nZ, XPoly2D &poly ,BOOL bSubtract) const { double nWallThick=GetWallThickness(TRUE); // Modify on 2004/2/23, 考虑保温层厚度 // modify by xlc on 110406 解决弧墙上带形窗端头封口问题 //if(GetKind()!=OP_ARCWIN || !m_nIdOfWall) if(IsLinear()) { XPoint pt[4], ptSide[2]; XPoint ptLoc=m_ptLocation; ptLoc.z = nZ; ads_polar(ptLoc, m_nRotation, m_nWidth/2.0, ptSide[0]); ads_polar(ptLoc, m_nRotation+PI, m_nWidth/2.0, ptSide[1]); OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pWall); if((m_nOpStyle&OPS_NOT_BORE) && pWall) { //不贯穿的洞 int nSideFlag=(m_nQuadrant<2)? OFFSET_LEFT : OFFSET_RIGHT; XCurveSegment curveSide=pWall->GetRelativeSideCurve(nSideFlag, pWall->StartPoint()); XCurveSegment curveIn=pWall->GetRelativeSideCurve(nSideFlag, pWall->StartPoint(), -m_nThickness); curveSide.ProjectToMe(ptSide[1], pt[0]); curveIn.ProjectToMe(ptSide[1], pt[1]); curveIn.ProjectToMe(ptSide[0], pt[2]); curveSide.ProjectToMe(ptSide[0], pt[3]); } else { // modify by xlc on 100824 弧墙上的直门窗洞做减法时将窗厚调整1倍,解决与墙线相交误差 if (bSubtract && pWall && pWall->Is(CURVE_ARC)) { ads_polar(ptSide[0], m_nRotation-PI/2.0, nWallThick, pt[0]); ads_polar(ptSide[0], m_nRotation+PI/2.0, nWallThick, pt[1]); ads_polar(ptSide[1], m_nRotation+PI/2.0, nWallThick, pt[2]); ads_polar(ptSide[1], m_nRotation-PI/2.0, nWallThick, pt[3]); } else { ads_polar(ptSide[0], m_nRotation-PI/2.0, nWallThick/2.0, pt[0]); ads_polar(ptSide[0], m_nRotation+PI/2.0, nWallThick/2.0, pt[1]); ads_polar(ptSide[1], m_nRotation+PI/2.0, nWallThick/2.0, pt[2]); ads_polar(ptSide[1], m_nRotation-PI/2.0, nWallThick/2.0, pt[3]); } } OPENOBJ_END(); poly.SetFlag(1); for(int i=0; i<4; i++) poly.AppendNode(pt[i]); } else { XDbObject objWall(m_nIdOfWall, AcDb::kForRead); if(!!objWall) { TDbWall *pDbWall=TDbWall::cast(objWall.m_pObject); ASSERT(pDbWall); ASSERT(pDbWall->Is(CURVE_ARC)); XArc ar=pDbWall->GetArc(); XPoint ptLoc=m_ptLocation; ptLoc.z=ar.GetCenterPt().z; double nRad=ads_distance(ar.GetCenterPt(), ptLoc); double nSweepAng=m_nWidth/nRad; double nStartAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptLoc)-nSweepAng/2.0), nEndAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptLoc)+nSweepAng/2.0); XArc arMid(ar.GetCenterPt(), nRad, nStartAng, nEndAng); double nThick=pDbWall->GetWidth(); XArc arLeft=arMid.Offset(-nThick/2), arRight=arMid.Offset(nThick/2); XPoint ptStart1, ptStart2, ptEnd1, ptEnd2; arLeft.GetStartPoint(ptStart1); arLeft.GetEndPoint(ptEnd1); arRight.GetStartPoint(ptStart2); arRight.GetEndPoint(ptEnd2); poly.AppendNode(ptStart1); poly.AppendNode(ptStart2, arRight.Bulge()); poly.AppendNode(ptEnd2); poly.AppendNode(ptEnd1, -arLeft.Bulge()); } } } // 判断门窗是否被曲线穿越 Adesk::Boolean TOpeningData::IsGoThroughBy(const XCurveSegment &segSrc) const { //add by xlc on 120607 解决带形窗所在墙基线在墙外时判断墙与门窗的关系错误问题 TGGeCurveSegment seg = segSrc; if (m_opKind == OP_CORNWIN) { TAcDbObjectPtr obj(m_nIdOfWall, AcDb::kForRead); if(!obj) { ; } else { TDbWall *pWall = TDbWall::cast(obj.m_pObject); if(pWall) { double dWidth = min(pWall->GetWidth(0), pWall->GetWidth(1)); if (dWidth < _DIST_SNAP) //基线在外侧时,通过墙中心线对带形窗进行校正 { TGGeCurveSegment cvCenter = pWall->OffsetGeomCenter(LS_FINITE); cvCenter.SetElevation(seg.StartPoint().z); TADSGePoint3d ptInters[2]; int nOld = seg.GetLineFlag(); seg.SetLineFlag(LS_INFINITE); int nNum = cvCenter.Intersection(seg, ptInters[0],ptInters[1]); if (nNum > 0) { if (ptInters[0].Distance(seg.StartPoint()) < ptInters[0].Distance(seg.EndPoint())) { seg.SetStartPoint(ptInters[0]); } else { seg.SetEndPoint(ptInters[0]); } } seg.SetLineFlag(nOld); } } } } XPoly2D poly(1); GetOutlinePoly(seg.StartPoint().z, poly); PointList pts(seg.StartPoint(), seg.EndPoint(), seg.GetBulge()); if(Intersect((XCurveSegment &)seg, poly, pts)) return Adesk::kTrue; return Adesk::kFalse; } // 求门窗立面转平面的转换矩阵 // 仅适用与直窗 void TOpeningData::GetPlanarMatrix(ads_matrix matTrans) const { XPoint ptSide[2]; ads_polar(m_ptLocation, m_nRotation, m_nWidth/2.0, ptSide[0]); ads_polar(m_ptLocation, m_nRotation+PI, m_nWidth/2.0, ptSide[1]); XPoint pt3; pt3 = ptSide[0]; pt3.z += m_nHeight; get_matrix(ptSide[0], ptSide[1], pt3, matTrans); } //////////////////////////////////////// // 取得门窗的边界点(由插入点确定轨迹) // Update New: 支持弧门窗 void TOpeningData::GetSidePoints(XPoint &ptSideBack, XPoint &ptSideFront) const { BOOL bFirstCase=IsLinear(); OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pDbWall); //ASSERT(pDbWall); if(bFirstCase) { //直门窗或无墙的窗 double nRot=m_nRotation; if(pDbWall && pDbWall->Is(CURVE_LINE)) nRot=pDbWall->XLine::Direction(); else if(pDbWall) // 在切换着色模式时有时导致pDbWall无效指针 nRot=ads_angle(pDbWall->GetArc().GetCenterPt(), m_ptLocation)+PI/2; ads_polar(m_ptLocation, nRot, m_nWidth/2.0, ptSideFront); ads_polar(m_ptLocation, nRot+PI, m_nWidth/2.0, ptSideBack); } else { //弧墙上的转角窗或弧窗 XPoint ptLoc=m_ptLocation; ptLoc.z = pDbWall->GetElevation(); XCurveSegment seg=pDbWall->OffsetGeomCenter(LS_INFINITE, TRUE); ASSERT(seg.Is(CURVE_ARC)); double radCen=seg.GetArc().GetRadius(); //中线半径 double radBase=pDbWall->GetArc().GetRadius(); //基线半径 double nWidthOnCen=m_nWidth*radCen/radBase; //中线弧长 double dist1=seg.PathDistance(ptLoc); XPointDir2d pt1, pt2; seg.Polar(dist1-nWidthOnCen/2.0, pt1); seg.Polar(dist1+nWidthOnCen/2.0, pt2); ptSideBack=pt1; ptSideFront=pt2; ptSideBack.z=ptSideFront.z=m_ptLocation.z; } OPENOBJ_END(); } bool TOpeningData::GetCenterCurve(XCurveSegment &wall)const { bool bRet=false; OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pWall); if(pWall) { wall=pWall->OffsetGeomCenter(LS_INFINITE,TRUE); bRet=true; } OPENOBJ_END(); return bRet; } //////////////////////////////////////// // 取得门窗在基线上的边界点 void TOpeningData::GetSidePointsOnBase(XPoint &ptSideBack, XPoint &ptSideFront) const { GetSidePoints(ptSideBack, ptSideFront); OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pWall); //ASSERT(pWall); if(pWall) { pWall->ProjectToMe(XPoint(ptSideBack), ptSideBack); pWall->ProjectToMe(XPoint(ptSideFront), ptSideFront); } OPENOBJ_END(); ptSideBack.z=ptSideFront.z=m_ptLocation.z; /* OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pDbWall); BOOL bFirstCase=IsLinear(); if(bFirstCase) { //直门窗或无墙的窗 ads_polar(m_ptLocation, m_nRotation, m_nWidth/2.0, ptSideFront); ads_polar(m_ptLocation, m_nRotation+PI, m_nWidth/2.0, ptSideBack); } else { XPoint ptLoc=m_ptLocation; ptLoc.z = pDbWall->GetElevation(); XCurveSegment seg=*pDbWall; seg.ProjectToMe(XPoint(ptLoc),ptLoc); double dist1=seg.PathDistance(ptLoc); XPointDir2d pt1, pt2; seg.Polar(dist1-m_nWidth/2.0, pt1); seg.Polar(dist1+m_nWidth/2.0, pt2); ptSideBack=pt1; ptSideFront=pt2; ptSideBack.z=ptSideFront.z=m_ptLocation.z; } OPENOBJ_END() */ } ///////////////////////////////////////////////////////////////////// // 设置门窗的边界点(由插入点确定轨迹), 更新内部数据,包括宽度和插入点, 和标号位置 // 传人的点必须在插入点确定的轨迹上 void TOpeningData::SetSidePoints(const XPoint &ptSideBack, const XPoint &ptSideFront) { BOOL bLinear=IsLinear(); OPENOBJ_BEGIN(m_nIdOfWall, AcDb::kForRead, TDbWall, pDbWall); if(!pDbWall || bLinear) { m_nWidth = ptSideFront.Distance(ptSideBack); XPoint ptNewLoc; Midpoint(ptSideBack, ptSideFront, ptNewLoc); m_ptLabel += ptNewLoc - m_ptLocation; m_ptLocation = ptNewLoc; } else { XCurveSegment seg=pDbWall->OffsetGeomCenter(); seg.SetElevation(ptSideBack.z); double nDist1=seg.PathDistance(ptSideBack); double nDist2=seg.PathDistance(ptSideFront); double nPathDist=(nDist1+nDist2)/2.0; double nWidthCen = fabs(nDist1-nDist2); m_nWidth=nWidthCen*pDbWall->GetArc().GetRadius()/seg.GetArc().GetRadius(); XPointDir2d ptNewLoc; //对于弧窗, 弧上的中点 XPoint ptNew; seg.Polar(nPathDist, ptNewLoc); pDbWall->GetOpeningLocation(ptNewLoc, GetKind(), m_nWidth, ptNew); m_ptLabel += ptNew - m_ptLocation; m_ptLocation = ptNew; } if(pDbWall) m_nRotation = pDbWall->Direction(m_ptLocation); OPENOBJ_END() } // 在立面上的Outline, 投影到门窗中心面(插入点所在的面)上 // 实际上, 已经不包含弧段(已经离散化) void TOpeningData::GetElevOutline(XPoly2D &poly) const { if(m_opKind==OP_DOORWIN) { XPoint ptSide[6]; GetSidePoints(ptSide[0], ptSide[3]); ptSide[4]=ptSide[3]; ptSide[4].z += m_nHeight; ptSide[5]=ptSide[0]; ptSide[5].z += m_nHeight; if(m_nQuadrant==0 || m_nQuadrant==3) { ads_polar(ptSide[0], m_nRotation, m_nWidth-m_nDoorWidth, ptSide[1]); ptSide[2]=ptSide[1]; ptSide[1].z += m_nHeight-m_nWinHeight; ptSide[0].z = ptSide[1].z; } else { ads_polar(ptSide[0], m_nRotation, m_nDoorWidth, ptSide[1]); ptSide[2]=ptSide[1]; ptSide[2].z += m_nHeight-m_nWinHeight; ptSide[3].z = ptSide[2].z; } poly.Reset(); poly.SetFlag(1); for(int i=0; i<6; i++) poly.AppendNode(ptSide[i]); } else { XDbObject objBlock(m_nIdStyle3d, AcDb::kForRead); if(!(!objBlock)) { AcDbBlockTableRecord *pBlock = AcDbBlockTableRecord::cast(objBlock.m_pObject); // 从扩展实体数据取出原始尺寸 resbuf *pxData=pBlock->xData(TCHXD); if(pxData) { resbuf *pNext=pxData->rbnext; if(pNext->restype==1040 && pNext->rbnext && pNext->rbnext->restype==1040) { ads_real nScaleX=1.0, nScaleY=1.0, nScaleZ=1.0; XPoint origenalSize= XPoint(pNext->resval.rreal, 60.0, pNext->rbnext->resval.rreal); assert(origenalSize.x>0.0 && origenalSize.y>0.0 && origenalSize.z>0.0); nScaleX = m_nWidth/origenalSize.x; nScaleY = m_nThickness/origenalSize.y; nScaleZ = m_nHeight/origenalSize.z; pNext=pNext->rbnext->rbnext; if(pNext && pNext->restype==1005 && pNext->resval.rstring) { Entity entOutline; ads_handent(pNext->resval.rstring, entOutline); if(pBlock->isDependent() || !entOutline) { //拱型窗在XREF时无法用这个方法获得 //ads_relrb(pxData); //return; //遍历块表记录,寻找轮廓的POLYLINE AcDbBlockTableRecordIterator* pBlockIterator; Acad::ErrorStatus es = pBlock->newIterator(pBlockIterator); ASSERT(es==Acad::eOk); XString sOutlineEntHandle; for (pBlockIterator->start(); !pBlockIterator->done(); pBlockIterator->step()) { AcDbEntity *pEntity; VERIFY(pBlockIterator->getEntity(pEntity, AcDb::kForRead, Adesk::kTrue)==Acad::eOk); XDbObject obj(pEntity); // So auto close if(!pEntity->isKindOf(AcDbPolyline::desc()) && !pEntity->isKindOf(AcDb2dPolyline::desc()) && !pEntity->isKindOf(AcDbCircle::desc())) continue; TCHAR *pszLayer=pEntity->layer(); ASSERT(pszLayer); XString sPattern(256); sPattern << LAY_BOUNDARY << _T(",*|") << LAY_BOUNDARY; if(ads_wcmatch(pszLayer, sPattern)==RTNORM) { acdbGetAdsName(entOutline.name, pEntity->objectId()); delete [] pszLayer; break; } delete [] pszLayer; } delete pBlockIterator; } XPoint vtNormal(0,0,1); entOutline.GetData(210, &vtNormal); XPoly2D poly2d; if(entOutline.Is(_T("CIRCLE"))) XCurveSegment(entOutline).AsPoly2D(poly2d); else poly2d=XPoly2D(entOutline); if(!poly2d || !poly2d.IsClosed()) ; else { XPoly poly1; poly2d.MapToPolygon1(poly1, _AS_SYS_UNIT(g_nCirDeviation)); //精度应当可以控制 // 转成世界坐标系 Groups gv(vtNormal), g0(0); poly1.TransUCS((resbuf *)&gv, (resbuf *)&g0); XPoint ptBase=pBlock->origin(); //////////////////////////////////// // 让Y坐标同ptBase for(int idx=0; idxy = ptBase.y; // 镜像情况 if(m_nQuadrant==1) nScaleX = -nScaleX; else if(m_nQuadrant==2) { nScaleX = -nScaleX; nScaleY = -nScaleY; } else if(m_nQuadrant==3) nScaleY = -nScaleY; ads_matrix matForInsert; ConstructMatrix(ptBase, m_ptLocation, nScaleX, nScaleY, nScaleZ, m_nRotation, matForInsert); poly1.TransUCS(matForInsert); poly.Reset(); poly.SetFlag(1); for(int n=0; nGetElevation(); } } } return nWallElevation; } // 取得所在的墙的宽度 // 如果不在任何墙上,则同门窗的厚度 ads_real TOpeningData::GetWallThickness(BOOL bIncludeInsulateLayer) const { ads_real nWidthOfWall=m_nThickness; if(!m_nIdOfWall) ; else { XDbObject obj(m_nIdOfWall, AcDb::kForRead); if(!obj) ; else { TDbWall *pWall = TDbWall::cast(obj.m_pObject); if(pWall) { nWidthOfWall = bIncludeInsulateLayer? pWall->GetWidth(4) : pWall->GetWidth(); } } } return nWidthOfWall; } // 取三维样式(图块)的名称 Acad::ErrorStatus TOpeningData::GetStyle3dName(XString &sName) const { if(!m_nIdStyle3d) return Acad::eInvalidInput; OPENOBJ_BEGIN(m_nIdStyle3d, AcDb::kForRead, AcDbBlockTableRecord, rec); if(!rec) return Acad::eInvalidInput; const TCHAR *pszName=NULL; Acad::ErrorStatus es = rec->getName(pszName); if(es!=Acad::eOk || !pszName) return es; sName = pszName; OPENOBJ_END(); return Acad::eOk; } // 取二维样式(图块)的名称 Acad::ErrorStatus TOpeningData::GetStyle2dName(XString &sName) const { if(!m_nIdStyle2d) return Acad::eInvalidInput; OPENOBJ_BEGIN(m_nIdStyle2d, AcDb::kForRead, AcDbBlockTableRecord, rec); if(!rec) return Acad::eInvalidInput; const TCHAR *pszName=NULL; Acad::ErrorStatus es = rec->getName(pszName); if(es!=Acad::eOk || !pszName) return es; sName = pszName; OPENOBJ_END(); return Acad::eOk; } // 取三维样式(图块)的外部名称, 分别指出图库和图块 Acad::ErrorStatus TOpeningData::GetStyle3dName(XString &sDwb, XString &sDwg) const { XString sName; Acad::ErrorStatus es=GetStyle3dName(sName); if(es!=Acad::eOk) return es; return SplitBlockName(sName, sDwb, sDwg); } // 取三维样式(图块)的外部名称, 分别指出图库和图块 Acad::ErrorStatus TOpeningData::GetStyle2dName(XString &sDwb, XString &sDwg) const { XString sName; Acad::ErrorStatus es=GetStyle2dName(sName); if(es!=Acad::eOk) return es; return SplitBlockName(sName, sDwb, sDwg); } // 取门窗类型的描述名称 const TCHAR *TOpeningData::GetKindString() const { const TCHAR *pszKind=NULL; if(m_nOpStyle&OPS_LIFTDOOR) pszKind=_T("电梯门"); else if(m_nOpStyle&OPS_LVTRY) pszKind=_T("隔断门"); else { switch(GetKind()) { case TOpeningData::OP_WINDOW: pszKind=_T("窗"); break; case TOpeningData::OP_DOORWIN: pszKind=_T("门连窗");//modified by fxj 090622 门联窗-》门连窗 break; case TOpeningData::OP_DOOR: pszKind=_T("门"); break; case TOpeningData::OP_TWODOOR: pszKind=_T("子母门"); break; case TOpeningData::OP_ARCWIN: pszKind=_T("弧窗"); break; case TOpeningData::OP_HOLE: pszKind=_T("墙洞"); break; case OP_PROWIN: pszKind=_T("凸窗"); break; case OP_CORNWIN: pszKind=_T("带型窗"); break; case OP_GROUP: pszKind=_T("组合门窗"); break; default: pszKind=_T("未知"); break; } } return pszKind; } XPoint TOpeningData::GetDoorPos() const { XPoint ptLoc=m_ptLocation; if(m_opKind==OP_DOORWIN) { XPoint ptDoorSide, ptDoorOtherSide; if(m_nQuadrant==0 || m_nQuadrant==3) { ads_polar(m_ptLocation, m_nRotation, m_nWidth/2, ptDoorSide); ads_polar(ptDoorSide, m_nRotation+PI, m_nDoorWidth, ptDoorOtherSide); } else { ads_polar(m_ptLocation, m_nRotation+PI, m_nWidth/2, ptDoorSide); ads_polar(ptDoorSide, m_nRotation, m_nDoorWidth, ptDoorOtherSide); } Midpoint(ptDoorSide, ptDoorOtherSide, ptLoc); } return ptLoc; } XPoint TOpeningData::GetWinPos() const { double nWinWidth=m_nWidth-m_nDoorWidth; XPoint ptLoc=m_ptLocation; if(m_opKind==OP_DOORWIN) { XPoint ptWinSide[2]; if(m_nQuadrant==0 || m_nQuadrant==3) { ads_polar(m_ptLocation, m_nRotation+PI, m_nWidth/2, ptWinSide[0]); ads_polar(ptWinSide[0], m_nRotation, nWinWidth, ptWinSide[1]); ptWinSide[0].z=ptWinSide[1].z=m_ptLocation.z+m_nHeight-m_nWinHeight; } else { ads_polar(m_ptLocation, m_nRotation, m_nWidth/2, ptWinSide[1]); ads_polar(ptWinSide[1], m_nRotation+PI, nWinWidth, ptWinSide[0]); ptWinSide[0].z=ptWinSide[1].z=m_ptLocation.z+m_nHeight-m_nWinHeight; } Midpoint(ptWinSide[0], ptWinSide[1], ptLoc) } return ptLoc; } // 返回值:0x01-lnLeft, 0x02-lnRight,lnLeft/lnRight都是无限长 int TOpeningData::GetSideLine2d(XLine &lnLeft, XLine& lnRight) const { XPoint ptOpenLoc = m_ptLocation; ptOpenLoc.z=0; ads_real nOrthoDrt=m_nRotation-PI/2; OPENOBJ_BEGIN(GetWallId(), AcDb::kForRead, TDbWall, pWall); if(pWall) { nOrthoDrt = pWall->OrthoDirection(ptOpenLoc); } OPENOBJ_END(); XLine ln(ptOpenLoc, nOrthoDrt+PI); // 门窗的左右线, 相对于墙的起点和终点方向而言 lnLeft=ln.Offset(-fabs(m_nWidth)/2.0), lnRight=ln.Offset(fabs(m_nWidth)/2.0); lnLeft.SetLineFlag(LS_INFINITE); lnRight.SetLineFlag(LS_FINITE); int nRetFlag=0x01|0x02; //左右都有 OPENOBJ_BEGIN(GetWallId(), AcDb::kForRead, TDbWall, pWall); if(pWall) { BOOL bIsArc=pWall->Is(CURVE_ARC); if(GetKind()==TOpeningData::OP_ARCWIN) { //弧窗的作右线不同于弦窗 ASSERT(pWall->Is(CURVE_ARC)); XArc ar=pWall->GetArc(); TADSGePoint3d ptCen = ar.GetCenterPt(); ptCen.z = 0; ar.SetCenterPt(ptCen); XPoint ptOnWall=ptOpenLoc; pWall->ProjectToMe(ptOpenLoc, ptOnWall); double nRad=ar.GetCenterPt().Distance2d(ptOnWall); double nSweepAng=GetWidth()/nRad; double nStartAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptOnWall)-nSweepAng/2.0), nEndAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptOnWall)+nSweepAng/2.0); XArc arMid(ar.GetCenterPt(), ar.GetCenterPt().Distance2d(ptOpenLoc), nStartAng, nEndAng); XArc arRight = arMid.Offset(200), arLeft = arMid.Offset(-200); arLeft.GetStartPoint(lnLeft.EndPoint()); arLeft.GetEndPoint(lnRight.EndPoint()); arRight.GetEndPoint(lnLeft.StartPoint()); arRight.GetEndPoint(lnRight.StartPoint()); } else if(GetKind()==TOpeningData::OP_CORNWIN) { //转角窗 //Status: 墙的基线与边线重合时,判断错误 XPoint ptOnWall=ptOpenLoc; pWall->ProjectToMe(ptOpenLoc, ptOnWall); double nPathDistLoc=pWall->PathDistance(ptOnWall); XPointDir2d ptStart, ptEnd; //门窗的起始位置和终止位置 pWall->Polar(nPathDistLoc-GetWidth()/2.0, ptStart); pWall->Polar(nPathDistLoc+GetWidth()/2.0, ptEnd); ptStart.z = ptEnd.z = 0.0; BOOL bStartAtCorn=FALSE; BOOL bEndAtCorn=FALSE; if(ptStart.Distance2d(pWall->StartPoint())<_DIST_SNAP) { //lnLeft.StartPoint() = cvRight.StartPoint(); //lnLeft.EndPoint() = cvLeft.StartPoint(); bStartAtCorn=TRUE; } if(ptEnd.Distance(pWall->EndPoint())<_DIST_SNAP) { //lnRight.StartPoint() = cvRight.EndPoint(); //lnRight.EndPoint() = cvLeft.EndPoint(); bEndAtCorn=TRUE; } if(bIsArc && (!bStartAtCorn || !bEndAtCorn)) { //弧墙上的转角窗 XArc ar=pWall->GetArc(); TADSGePoint3d ptCen = ar.GetCenterPt(); ptCen.z = 0; ar.SetCenterPt(ptCen); XPoint ptOnWall=ptOpenLoc; pWall->ProjectToMe(ptOpenLoc, ptOnWall); double nRad=ar.GetCenterPt().Distance2d(ptOnWall); double nSweepAng=GetWidth()/nRad; double nStartAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptOnWall)-nSweepAng/2.0), nEndAng=CT_std_angle(ads_angle(ar.GetCenterPt(), ptOnWall)+nSweepAng/2.0); XArc arMid(ar.GetCenterPt(), ar.GetCenterPt().Distance2d(ptOpenLoc), nStartAng, nEndAng); XArc arRight = arMid.Offset(200), arLeft = arMid.Offset(-200); XPoint ptEnd1, ptEnd2; XPoint ptStart1, ptStart2; arLeft.GetStartPoint(ptEnd1); arLeft.GetEndPoint(ptEnd2); arRight.GetStartPoint(ptStart1); arRight.GetEndPoint(ptStart2); if(!bStartAtCorn) { lnLeft.StartPoint()=ptStart1; lnLeft.EndPoint()=ptEnd1; } if(!bEndAtCorn) { lnRight.StartPoint()=ptStart2; lnRight.EndPoint()=ptEnd2; } } if(bStartAtCorn) nRetFlag &= ~0x01; if(!bEndAtCorn) nRetFlag &= ~0x02; } } OPENOBJ_END(); return nRetFlag; } //add by xlc on 110131 独立门窗接口 BOOL TOpeningData::IsLoneOpening() const { return (m_nOpStyleEx & OPS_LONE) != 0; } Adesk::Boolean TOpeningData::IsHigh() const { //wlw mod 140220 只有窗户和洞才判断 if (m_opKind == OP_WINDOW || m_opKind == OP_ARCWIN) return ((m_nOpStyle&OPS_ATHIGH)!=0); else return Adesk::kFalse; } void TOpeningData::SetLoneOpening(BOOL bTrue) { if (bTrue) { m_nOpStyleEx |= OPS_LONE; } else { m_nOpStyleEx &= ~OPS_LONE; } }