Files
envi-code/SourceCode/Code2026/tg_shs/shs_kernal/Openingdata.cpp
T
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

857 lines
29 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#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;
}
}