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

499 lines
11 KiB
C++

#include "stdafx.h"
#include "resource.h"
//add by xlc on 070712
//求线与线的交点
BOOL GetLineIntPoint(AcDbCurve *projLine,AcGePoint3d ptStart,AcGePoint3d ptEnd,AcGePoint3d &ptInt)
{
AcDbLine line(ptStart,ptEnd);
AcGePoint3dArray points;
if (projLine != NULL)
projLine->intersectWith(&line, AcDb::kOnBothOperands, points);
if (points.length() > 0)
{
ptInt = points.at(0);
return TRUE;
}
return FALSE;
}
//add by xlc on 070712
//获得线段与屋顶面边线的投影交点
void GetLineIntSectPoint(DList<X3DFace> &lstFace, //[in]屋顶面
XLine xLine, //[in]线段
XPoly3D &poly //[out]投影点数组
)
{
int num = lstFace.Length();
for(int i = 0; i < lstFace.Length(); i++) //获得直线所在平面与投影面的交点
{
AcDbLine line(xLine.StartPoint(),xLine.EndPoint());
X3DFace face(*lstFace[i]);
face.MakeBetter();
AcGePlane roof(AcGePoint3d(face.GetVertex(0)),AcGePoint3d(face.GetVertex(1)),AcGePoint3d(face.GetVertex(2)));
AcDbCurve *projLine = NULL; //在face平面上的投影线
line.getProjectedCurve(roof, AcGeVector3d::kZAxis, projLine);
if (projLine != NULL)
{
AcGePoint3d ptInt; //平面与face面交线与face边的交点
if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(0)),AcGePoint3d(face.GetVertex(1)),ptInt) && face.IsVisible(0))
poly.AppendNode(ptInt);
if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(1)),AcGePoint3d(face.GetVertex(2)),ptInt) && face.IsVisible(1))
poly.AppendNode(ptInt);
if (!face.IsTriangle(2))
{
if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(2)),AcGePoint3d(face.GetVertex(3)),ptInt) && face.IsVisible(2))
poly.AppendNode(ptInt);
if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(3)),AcGePoint3d(face.GetVertex(0)),ptInt) && face.IsVisible(3))
poly.AppendNode(ptInt);
}
else
{
if (GetLineIntPoint(projLine,AcGePoint3d(face.GetVertex(2)),AcGePoint3d(face.GetVertex(0)),ptInt) && face.IsVisible(2))
poly.AppendNode(ptInt);
}
delete projLine;
}
}
}
//add by xlc on 070712
//获得线段在屋顶面上的投影点
//返回值:TRUE,成功;FALSE,失败
BOOL GetLineEndIntSectPoint(DList<X3DFace> &lstFace, //[in]屋顶面
XLine xLine, //[in]线段
XPoint &start, //[out]xLine线起点的投影点
XPoint &end //[out]xLine线终点的投影点
)
{
int posS = 0,posE = 0; //face在链表中的位置
XPoint ptStart(xLine.StartPoint().x,xLine.StartPoint().y,0),
ptEnd(xLine.EndPoint().x,xLine.EndPoint().y,0);
BOOL bFindS = FALSE,bFindE = FALSE; //是否找到起始点所在的face
//找线段端点所在的face
for(int i = 0; i < lstFace.Length(); i++)
{
AcGePoint3d pt;
XPoly2D polyFace(1);
X3DFace face(*lstFace[i]);
face.MakeBetter();
for(int j = 0; j < 3; j++)
{
pt = face.GetVertex(j);
polyFace.AppendNode(pt);
}
if (!face.IsTriangle(2))//四边形
{
pt = face.GetVertex(3);
polyFace.AppendNode(pt);
}
polyFace.SetElevation(0.0); //投影到z=0的平面上
if (!bFindS)
{
if ( (ptStart & polyFace) != PR_OUTSIDE)
{
posS = i;
bFindS = TRUE;
}
}
if (!bFindE)
{
if ( (ptEnd & polyFace) != PR_OUTSIDE)
{
posE = i;
bFindE = TRUE;
}
}
if (bFindS && bFindE)
break;
}
//线段端点上的face面
if (bFindS)
{
X3DFace pFace(*lstFace[posS]);
pFace.MakeBetter();
AcGePlane sPlane(AcGePoint3d(pFace.GetVertex(0)),
AcGePoint3d(pFace.GetVertex(1)),AcGePoint3d(pFace.GetVertex(2)));
AcGePoint3d tmp = xLine.StartPoint();
tmp.z += _AS_SYS_UNIT(1000.0);// [11/15/2007 nsh]
AcGeLine3d sLine(AcGePoint3d(xLine.StartPoint()),tmp);
sLine.intersectWith(sPlane,start);
//modify by xlc on 080303 部分在屋顶外边简单处理
if (!bFindE)
{
end = xLine.EndPoint();
end.z = start.z;
}
}
else
//modify by xlc on 080303 部分在屋顶外边简单处理
//{
// return FALSE;
//}
{
if (!bFindE)
{
return FALSE;
}
}
if (bFindE)
{
X3DFace pFace(*lstFace[posE]);
pFace.MakeBetter();
AcGePlane ePlane(AcGePoint3d(pFace.GetVertex(0)),
AcGePoint3d(pFace.GetVertex(1)),AcGePoint3d(pFace.GetVertex(2)));
AcGePoint3d tmp = xLine.EndPoint();
tmp.z +=_AS_SYS_UNIT(1000.0);// [11/15/2007 nsh]
AcGeLine3d eLine(AcGePoint3d(xLine.EndPoint()),tmp);
eLine.intersectWith(ePlane,end);
//modify by xlc on 080303 部分在屋顶外边简单处理
if (!bFindS)
{
start = xLine.StartPoint();
start.z = end.z;
}
}
//modify by xlc on 080303 部分在屋顶外边简单处理
//else
//{
// return FALSE;
//}
return TRUE;
}
//add by xlc on 070712
//计算平板的高度
BOOL CalSlabMaxHeight(XPoly2D polyOutline, //[in]平板线
double botElev, //[in]平板底标高
double &height, //[in/out]平板高度
DList<X3DFace> &lstFace //[in]屋顶面
)
{
XPoint start,end;
XLine xLine1(*polyOutline[0],*polyOutline[polyOutline.Length()-1]);
//modify by xlc on 080303
BOOL bFlag=TRUE; //bFlag为TRUE时为变量height初始化
if (GetLineEndIntSectPoint(lstFace,xLine1,start,end)) //获得线端点的投影点
{
if (bFlag)
{
height = start.z;
bFlag = FALSE;
}
if (height > end.z)
height = end.z;
XPoly3D poly;
GetLineIntSectPoint(lstFace,xLine1,poly); //获得线平面与face平面边线的交点
for(int j = 0; j < poly.Length(); j++)
{
if (height > poly[j]->z)
{
height = poly[j]->z;
}
}
}
for(int i = 0; i < polyOutline.Length()-1; i++)
{
XPoly3D poly1;
XLine xLine(*polyOutline[i],*polyOutline[i+1]);
GetLineIntSectPoint(lstFace,xLine,poly1);
for(int j = 0; j < poly1.Length(); j++)
{
//modify by xlc on 080303
if (bFlag)
{
height=poly1[j]->z;
bFlag=FALSE;
}
if (height > poly1[j]->z)
{
height = poly1[j]->z;
}
}
if (!GetLineEndIntSectPoint(lstFace,xLine,start,end))
{
//modify by xlc on 080303 部分在屋顶外边简单处理
//return FALSE;
continue;
}
if (height > start.z)
height = start.z;
if (height > end.z)
height = end.z;
}
height -= _DIST_SNAP;
if (height < botElev)
{
return FALSE;
}
return TRUE;
}
//add by xlc on 070712
//线段与屋顶的交线
BOOL GetLineIntSectPoly(DList<X3DFace> &lstFace, //[in]屋顶面
XLine xLine, //[in]线段
XPoly3D &poly //[out]交线
)
{
GetLineIntSectPoint(lstFace,xLine,poly); //获得线段平面在face平面上的交点
//删除重合点
int ptNum = poly.Length();
for(int i = 0; i < ptNum-1; i++)
{
for(int j = i+1;j < ptNum;)
{
if (*poly[i] == *poly[j])
{
poly.RemoveNode(j);
ptNum--;
continue;
}
j++;
}
}
//排序
Array<XPoint> ptArray; //交点
if (ptNum > 0)
{
ptArray.Realloc(ptNum);
for(long i = 0; i < ptNum; i++)
{
ptArray[i] = *poly[i];
}
bool bIncrease = true;
if (fabs(xLine.StartPoint().x - xLine.EndPoint().x) < 1e-6)
{
if (xLine.StartPoint().y - xLine.EndPoint().y > 0)
bIncrease = false;
}
else
{
if (xLine.StartPoint().x - xLine.EndPoint().x > 0)
bIncrease = false;
}
ptArray.Arrange(bIncrease); //按线段起点到终点的顺序排序
for(i = 0; i < ptNum; i++)
{
*poly[i] = ptArray[i];
}
}
//求线段的起点和终点与face的交点
XPoint start,end;
if (!GetLineEndIntSectPoint(lstFace,xLine,start,end))
return FALSE;
//添加线段的端点
if (poly.Length() > 0)
{
if (start != *poly[0])
{
poly.InsertNodeAt(0,start);
}
}
else
{
poly.InsertNodeAt(0,start);
}
if (end != *poly[poly.Length()-1])
{
poly.AppendNode(end);
}
return TRUE;
}
//add by xlc on 070712
//获得屋顶向内的面
void GetAllRoofPoly(AcDbObjectId id, //[in]屋顶对象ID
DList<X3DFace> &lstFace //[out]屋顶向内的面
)
{
OPENOBJ_BEGIN(id, AcDb::kForRead, AcDbEntity, pRoof);
if (pRoof)
{
int nFlag = 0; //是否屋顶对象,0:非屋顶对象;1:人字屋顶或攒尖屋顶,矩形屋顶;2:任意屋顶(有内侧缺面)
BOOL bRoof = FALSE; //是否可视为屋顶
if (pRoof->isKindOf(TDbDualSlopeRoof::desc())
|| pRoof->isKindOf(TDbCuspRoof::desc())
|| pRoof->isKindOf(TDbMountRoof::desc())
)
{
nFlag = 1;
bRoof = TRUE;
}
else if (pRoof->isKindOf(TDbSlopeRoof::desc()))
{
nFlag = 2;
bRoof = TRUE;
}
else if (pRoof->isKindOf(AcDbPolyFaceMesh::desc())
|| pRoof->isKindOf(AcDbPolygonMesh::desc())
|| pRoof->isKindOf(AcDbFace::desc())
)
{
bRoof = TRUE;
}
if (bRoof)
{
TMasterProperties prop;
AcDbVoidPtrArray entSet;
int nOldMode=DocGetDrawMode();
DocSetDrawMode(DRAW_3D);
if (nFlag == 2)
{
AcDbEntity *pEnt = (AcDbEntity*)pRoof->clone();
if (pEnt)
{
double height = _AS_SYS_UNIT(200.0);// [11/15/2007 nsh]
AcGeMatrix3d mat;
mat.setToTranslation(AcGeVector3d(0,0,-height));
pEnt->upgradeOpen();
pEnt->transformBy(mat);
InitModel(prop, pEnt, NULL, entSet);
delete pEnt;
}
}
else
{
InitModel(prop, pRoof, NULL, entSet);
}
DocSetDrawMode(nOldMode);
int nLen=entSet.length();
for(int n=0; n<nLen; n++)
{
AcDbEntity *pEnt=(AcDbEntity *)entSet[n];
if (pEnt->isKindOf(AcDbFace::desc()))
{
AcDbFace *pFace = AcDbFace::cast(pEnt);
if (pFace != NULL)
{
X3DFace p3DFace(*pFace);
XVector3D vtNormal = p3DFace.GetNormal();
if (fabs(vtNormal.z) < 1.0e-6) //立面
continue;
if (nFlag == 1)
{
if (vtNormal.z > 1.0e-6) //人字坡顶或攒尖屋顶向下的面
continue;
}
else if (nFlag == 2)
{
if (vtNormal.z < 1.0e-6) //任意坡顶向上的面
continue;
}
lstFace.Append(new X3DFace(p3DFace));
}
}
}
ReleaseEntSet(entSet);
}
}
OPENOBJ_END();
}
//平板对齐屋顶
void SlabAlignRoof()
{
RBList rbMask1(RTDXF0, _T("TCH_MOUNTROOF,TCH_SLOPEROOF,TCH_CUSPROOF,TCH_DUALROOF,POLYLINE,3DFACE"), NULL);
PickSet ssRoofs(SS_FREE);
int nRetCode=SelectEntities(_T("\n请选择屋顶:"), ssRoofs, rbMask1);
if (nRetCode!=RTNORM)
return;
RBList rbMask(RTDXF0, _T("TCH_SLAB"), NULL);
PickSet ssSlabs(SS_FREE);
nRetCode=SelectEntities(_T("\n请选择平板:"), ssSlabs, rbMask);
if (nRetCode!=RTNORM)
return;
DList<X3DFace> lstFace;
long m = 0;
do
{
AcDbObjectId id; //任意屋顶id
if (acdbGetObjectId(id, ssRoofs[m]) != Acad::eOk)
{
m++;
continue;
}
GetAllRoofPoly(id, lstFace); //获得屋顶的下表面
m++;
}while(m < ssRoofs.Length());
if (lstFace.Length() < 1)
return;
acedSetStatusBarProgressMeter(_T("正在处理中,请稍候..."),1,ssSlabs.Length());
long n = 0;
do
{
acedSetStatusBarProgressMeterPos(n+1);
XDbObject obj(ssSlabs[n],AcDb::kForWrite);
TDbSlab *pSlab = TDbSlab::cast(obj.m_pObject);
XPoly2D polyOutline=pSlab->GetOutline();;
double botElev=0,height=0;
botElev=pSlab->GetElevation();
if (CalSlabMaxHeight(polyOutline,botElev,height,lstFace))
{
pSlab->assertWriteEnabled();
pSlab->SetThickness(height);
}
n++;
} while(n < ssSlabs.Length());
acedRestoreStatusBar();
}