Files
envi-code/SourceCode/Code2026/tg_shs/shs_kernal/Openingdata.cpp
T

856 lines
28 KiB
C++
Raw Normal View History

2026-09-28 15:28:50 +08:00
#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; idx<poly1.Length(); idx++)
poly1[idx]->y = 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; n<poly1.Length(); n++)
poly.AppendNode(*poly1[n]);
ads_relrb(pxData); // Release xdata, add 99/8/8 ZJQ
return;
}
}
}
ads_relrb(pxData);
}
}
//UpdateNew: 现在支持弧型窗
XPoint ptSide[4];
GetSidePoints(ptSide[1], ptSide[0]);
ptSide[2]=ptSide[1]; ptSide[2].z += m_nHeight;
ptSide[3]=ptSide[0]; ptSide[3].z += m_nHeight;
poly.Reset();
poly.SetFlag(1);
for(int i=0; i<4; i++)
poly.AppendNode(ptSide[i]);
}
}
// 取得立面(三维)上的轮廓线, poly是封闭的
void TOpeningData::GetOutlinePoly(XPoly &poly, int nCirDiv) const
{
XPoly2D poly0;
GetElevOutline(poly0);
poly0.MapToPolygon(poly, nCirDiv);
}
// 求门窗洞的面积, 单位同绘图单位一致, 没有换算成米
double TOpeningData::GetOutlineArea() const
{
XPoly poly;
GetOutlinePoly(poly);
ads_matrix matTrans;
GetPlanarMatrix(matTrans);
poly.TransUCS(matTrans);
return fabs(poly.PathArea());
}
// 求门窗洞的周长
double TOpeningData::GetOutlineLength() const
{
XPoly poly;
GetOutlinePoly(poly);
double nLen=0.0;
for(int i=0; i<poly.Length(); i++) {
XLine ln;
poly.NthLine(i, ln);
nLen += ln.GetLength();
}
return nLen;
}
// 取得所在的墙的基面标高
// 如果不在任何墙上,则取0
ads_real TOpeningData::GetWallElevation() const
{
ads_real nWallElevation=0.0; //m_ptLocation.z;
if(!m_nIdOfWall) ;
else {
XDbObject obj(m_nIdOfWall, AcDb::kForRead);
if(!obj) ;
else {
TDbWall *pWall = TDbWall::cast(obj.m_pObject);
if(pWall) {
nWallElevation = pWall->GetElevation();
}
}
}
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;
}
}