499 lines
11 KiB
C++
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();
|
|
}
|
|
|