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

819 lines
30 KiB
C++

#include "stdafx.h"
#include "DbSlopeRoof.h"
//***************************************************************************************************
// 坡屋顶求体积
//***************************************************************************************************
AcGePoint3d GetIntegralPointX(AcGePoint3d p1, AcGePoint3d p2, AcGePoint3d p3)
{
AcGePoint3d ptRet;
if(p1.x > p2.x && p1.x < p3.x || p1.x > p3.x && p1.x < p2.x)
ptRet = p1;
else if(p2.x > p1.x && p2.x < p3.x || p2.x > p3.x && p2.x < p1.x)
ptRet = p2;
else if(p3.x > p1.x && p3.x < p2.x || p3.x > p2.x && p3.x < p1.x)
ptRet = p3;
else{
if(fabs(p1.x - p2.x) < 0.0001){
if(p1.y > p2.y)
ptRet = p1;
else
ptRet = p2;
}
else if(fabs(p1.x - p3.x) < 0.0001){
if(p1.y > p3.y)
ptRet = p1;
else
ptRet = p3;
}
else if(fabs(p2.x - p3.x) < 0.0001){
if(p2.y > p3.y)
ptRet = p2;
else
ptRet = p3;
}
}
return ptRet;
}
double GetIntegralX(double dA, double dB, double dC, AcGePoint3d p1, AcGePoint3d p2, AcGePoint3d p3)
{
double dRet(0);
AcGePoint3d pt0, pt1, pt2;
pt0 = GetIntegralPointX(p1, p2, p3);
if(pt0 == p1){
if(p2.x < p3.x){
pt1 = p2;
pt2 = p3;
}
else{
pt1 = p3;
pt2 = p2;
}
}
else if(pt0 == p2){
if(p1.x < p3.x){
pt1 = p1;
pt2 = p3;
}
else{
pt1 = p3;
pt2 = p1;
}
}
else if(pt0 == p3){
if(p1.x < p2.x){
pt1 = p1;
pt2 = p2;
}
else{
pt1 = p2;
pt2 = p1;
}
}
double x0 = pt0.x;
double x1 = pt1.x;
double x2 = pt2.x;
double y0 = pt0.y;
double y1 = pt1.y;
double y2 = pt2.y;
double d1 = x0*x0-x1*x1;
double d2 = x2*x2-x0*x0;
double d3 = x0*x0*x0-x1*x1*x1;
double d4 = x2*x2*x2-x0*x0*x0;
double d5 = (y0-y1)/(x0-x1);
double d6 = (y1-y2)/(x1-x2);
double d7 = (y2-y0)/(x2-x0);
double nTmp3 = 1.0/3.0;
if(pt0.y > pt1.y || pt0.y > pt2.y){//正三角形
double nTmp = 0;
if(fabs(x0-x1) > 0.00001 && fabs(x1 - x2) > 0.00001)//有2个点x坐标相同,只积分一次
nTmp = 0.5*d1*(y0 - y1 - d5*x0 + d6*x1) + nTmp3*d3*(d5 - d6);
if(fabs(x1 - x2) > 0.00001 && fabs(x2 - x0) > 0.00001)
nTmp += 0.5*d2*(y2 - y1 - d7*x2 + d6*x1) + nTmp3*d4*(d7 - d6);
dRet = nTmp;
}
else{ //倒三角形
double nTmp = 0;
if(fabs(x0-x1) > 0.00001 && fabs(x1 - x2) > 0.00001)
nTmp = 0.5*d1*(y1 - y0 - d6*x1 + d5*x0) + nTmp3*d3*(d6 - d5);
if(fabs(x1 - x2) > 0.00001 && fabs(x2 - x0) > 0.00001)
nTmp += 0.5*d2*(y1 - y2 - d6*x1 + d7*x2) + nTmp3*d4*(d6 - d7);
dRet = nTmp;
}
return dRet;
}
double GetIntegralY(double dA, double dB, double dC, AcGePoint3d p1, AcGePoint3d p2, AcGePoint3d p3)
{
AcGePoint3d ptTmp1, ptTmp2, ptTmp3;
ptTmp1.x = p1.y;
ptTmp1.y = p1.x;
ptTmp1.z = 0;
ptTmp2.x = p2.y;
ptTmp2.y = p2.x;
ptTmp2.z = 0;
ptTmp3.x = p3.y;
ptTmp3.y = p3.x;
ptTmp3.z = 0;
return GetIntegralX(dA, dB, dC, ptTmp1, ptTmp2, ptTmp3);
}
//函数:通过积分,得到空间三角形投影到XY平面的体积
// 入口参数:
//dA, dB, dC 代表 aX + bY + cZ = 1 空间三角形的平面方程
//p1, p2, p3 代表 投影三角形的3个顶点坐标
//返回:体积
double GetTriangleVolumeByIntegral(double dA, double dB, double dC, AcGePoint3d p1, AcGePoint3d p2, AcGePoint3d p3)
{
p1.x = p1.x / 1000; //转化为米
p2.x = p2.x / 1000; //转化为米
p3.x = p3.x / 1000; //转化为米
p1.y = p1.y / 1000; //转化为米
p2.y = p2.y / 1000; //转化为米
p3.y = p3.y / 1000; //转化为米
p1.z = p1.z / 1000; //转化为米
p2.z = p2.z / 1000; //转化为米
p3.z = p3.z / 1000; //转化为米
double dRet(0);
XPoly2D poly;
poly.AppendNode(p1);
poly.AppendNode(p2);
poly.AppendNode(p3);
poly.AppendNode(p1);
double nProjectArea = poly.Area();
double nCalcTmp = 1/dC*nProjectArea;
double nX = dA / dC * GetIntegralX(dA, dB, dC, p1, p2, p3);
double nY = dB / dC *GetIntegralY(dA, dB, dC, p1, p2, p3);
dRet = nCalcTmp - nX - nY;
return dRet;
}
double GetTriangleVolumeByIntegral(double dA, AcGePoint3d p1, AcGePoint3d p2, AcGePoint3d p3)
{
double dHeight = ((p1.z - dA) + (p2.z - dA) + (p3.z - dA)) / 3;
dHeight = dHeight / 1000;
p1.x = p1.x / 1000; //转化为米
p2.x = p2.x / 1000; //转化为米
p3.x = p3.x / 1000; //转化为米
p1.y = p1.y / 1000; //转化为米
p2.y = p2.y / 1000; //转化为米
p3.y = p3.y / 1000; //转化为米
p1.z = 0.0;
p2.z = 0.0;
p3.z = 0.0;
double dRet(0);
XPoly2D poly;
poly.AppendNode(p1);
poly.AppendNode(p2);
poly.AppendNode(p3);
poly.AppendNode(p1);
double nProjectArea = poly.Area();
dRet = nProjectArea * dHeight;
return dRet;
}
double VolumeRoof2(AcDbObjectId id)
{
double dRet(0);
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbSlopeRoof, pRoof);
if(pRoof){
XPoly2D poly;
poly = pRoof->GetOutlinePoly();
double dElev = pRoof->GetElevation();
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
double nV = GetTriangleVolumeByIntegral(dElev, p1, p2, p3);
if(nV > 0)
dRet += nV;
}
}
ReleaseEntSet(TriangleSet);
}
OPENOBJ_END();
//人字
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDualSlopeRoof, pRoof);
if(pRoof){
double dRoofEle(0);
DocSetDrawMode(DRAW_3D);
AcDbExtents ext;
pRoof->getGeomExtents(ext);
double dElev = pRoof->GetElevation();
DocSetDrawMode(DRAW_2D);
dRoofEle = pRoof->GetElevation();
// dRoofEle = ext.minPoint().z; // sr 2012-9-27 屋顶带厚度,应该直接读取GetElevation()
XPoly2D poly;
pRoof->GetPolyPath(poly);
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
double nV = GetTriangleVolumeByIntegral(dElev, p1, p2, p3);
if(nV > 0)
dRet += nV;
}
}
ReleaseEntSet(TriangleSet);
}
OPENOBJ_END();
//攒尖屋顶
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbCuspRoof, pRoof);
if(pRoof){
double dRoofEle(0);
DocSetDrawMode(DRAW_3D);
AcDbExtents ext;
pRoof->getGeomExtents(ext);
DocSetDrawMode(DRAW_2D);
dRoofEle = pRoof->GetElevation();
// dRoofEle = ext.minPoint().z; // sr 2012-9-27 屋顶带厚度,应该直接读取GetElevation()
XPoly2D poly;
pRoof->GetPolyPath(poly);
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
double dElev = pRoof->GetElevation();
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
double dA(0), dB(0), dC(0), dD(0);
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
double nV = GetTriangleVolumeByIntegral(dElev, p1, p2, p3);
if(nV > 0)
dRet += nV;
}
}
ReleaseEntSet(TriangleSet);
}
OPENOBJ_END();
return dRet;
}
double VolumeRoof(AcDbObjectId id)
{
double dRet(0);
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbSlopeRoof, pRoof);
if(pRoof){
XPoly2D poly;
poly = pRoof->GetOutlinePoly();
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
double dA(0), dB(0), dC(0), dD(0);
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
AcGePlane plane(p1, vtNormal); //投影三角形的平面
plane.getCoefficients(dA, dB, dC, dD);
dD = dD*(-1);
AcGeVector3d vtNormal2 = plane.normal();
p1 = p1.project(planeXY, vtNormalZ);
p2 = p2.project(planeXY, vtNormalZ);
p3 = p3.project(planeXY, vtNormalZ);
dA = dA / dD * 1000;
dB = dB / dD * 1000;
dC = dC / dD * 1000;
double nang = vtNormalZ.angleTo(vtNormal);
double nV = GetTriangleVolumeByIntegral(dA, dB, dC, p1, p2, p3);
if(nV > 0)
dRet += nV;
if(nV < 0){//积分算法有错误,在特点的▽▼△▲下,体积《0
double nV2 = GetTriangleVolumeByIntegral(dA, dB, dC, p1, p2, p3);
AcGePoint3d p11,p22,p33;
pFace->getVertexAt(0, p11);
pFace->getVertexAt(1, p22);
pFace->getVertexAt(2, p33);
AcDbFace *pFaceNew = new AcDbFace();
pFaceNew->setVertexAt(0, p11);
pFaceNew->setVertexAt(1, p22);
pFaceNew->setVertexAt(2, p33);
pFaceNew->setVertexAt(3, p11);
AddToModelSpace(pFaceNew, Adesk::kTrue);
}
}
}
ReleaseEntSet(TriangleSet);
//因为计算完体积有bug,投影到0标高的体积。所以减去下面的部分。
double dArea = poly.Area()/1000000;
dRet -= dArea * pRoof->GetElevation()/1000.0;
}
OPENOBJ_END();
//人字
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbDualSlopeRoof, pRoof);
if(pRoof){
double dRoofEle(0);
DocSetDrawMode(DRAW_3D);
AcDbExtents ext;
pRoof->getGeomExtents(ext);
DocSetDrawMode(DRAW_2D);
dRoofEle = pRoof->GetElevation();
// dRoofEle = ext.minPoint().z; // sr 2012-9-27 屋顶带厚度,应该直接读取GetElevation()
XPoly2D poly;
pRoof->GetPolyPath(poly);
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
double dA(0), dB(0), dC(0), dD(0);
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
AcGePlane plane(p1, vtNormal); //投影三角形的平面
plane.getCoefficients(dA, dB, dC, dD);
dD = dD*(-1);
AcGeVector3d vtNormal2 = plane.normal();
p1 = p1.project(planeXY, vtNormalZ);
p2 = p2.project(planeXY, vtNormalZ);
p3 = p3.project(planeXY, vtNormalZ);
dA = dA / dD * 1000;
dB = dB / dD * 1000;
dC = dC / dD * 1000;
double nang = vtNormalZ.angleTo(vtNormal);
double nV = GetTriangleVolumeByIntegral(dA, dB, dC, p1, p2, p3);
if(nV > 0)
dRet += nV;
if(nV < 0){//积分算法有错误,在特点的▽▼△▲下,体积《0
AcGePoint3d p11,p22,p33;
pFace->getVertexAt(0, p11);
pFace->getVertexAt(1, p22);
pFace->getVertexAt(2, p33);
AcDbFace *pFaceNew = new AcDbFace();
pFaceNew->setVertexAt(0, p11);
pFaceNew->setVertexAt(1, p22);
pFaceNew->setVertexAt(2, p33);
pFaceNew->setVertexAt(3, p11);
AddToModelSpace(pFaceNew, Adesk::kTrue);
}
}
}
ReleaseEntSet(TriangleSet);
//因为计算完体积有bug,投影到0标高的体积。所以减去下面的部分。
double dArea = poly.Area()/1000000;
dRet -= dArea * dRoofEle/1000.0;
}
OPENOBJ_END();
//攒尖屋顶
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbCuspRoof, pRoof);
if(pRoof){
double dRoofEle(0);
DocSetDrawMode(DRAW_3D);
AcDbExtents ext;
pRoof->getGeomExtents(ext);
DocSetDrawMode(DRAW_2D);
dRoofEle = pRoof->GetElevation();
// dRoofEle = ext.minPoint().z; // sr 2012-9-27 屋顶带厚度,应该直接读取GetElevation()
XPoly2D poly;
pRoof->GetPolyPath(poly);
AcGeVector3d vtNormalZ(0,0,1);
AcGePlane planeXY(*poly[0], vtNormalZ); //确定投影面
AcDbVoidPtrArray entSet;
AcDbVoidPtrArray TriangleSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001 )
continue;
if(p1 == p4){
TriangleSet.append(pEnt->clone());
}
else{
//注意保证逆时针方向
AcDbFace *pFaceNew1 = new AcDbFace();
pFaceNew1->setVertexAt(0, p1);
pFaceNew1->setVertexAt(1, p2);
pFaceNew1->setVertexAt(2, p3);
pFaceNew1->setVertexAt(3, p1);
TriangleSet.append(pFaceNew1);
AcDbFace *pFaceNew2 = new AcDbFace();
pFaceNew2->setVertexAt(0, p1);
pFaceNew2->setVertexAt(1, p3);
pFaceNew2->setVertexAt(2, p4);
pFaceNew2->setVertexAt(3, p1);
TriangleSet.append(pFaceNew2);
}
}
}
ReleaseEntSet(entSet);
nLen=TriangleSet.length();
double dA(0), dB(0), dC(0), dD(0);
for(n=0; n<nLen; n++) {
AcDbEntity *pEnt=(AcDbEntity *)TriangleSet[n];
if(pEnt->isKindOf(AcDbFace::desc())) {
AcDbFace *pFace = AcDbFace::cast(pEnt);
AcGePoint3d p1,p2,p3;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
AcGePlane plane(p1, vtNormal); //投影三角形的平面
plane.getCoefficients(dA, dB, dC, dD);
dD = dD*(-1);
AcGeVector3d vtNormal2 = plane.normal();
p1 = p1.project(planeXY, vtNormalZ);
p2 = p2.project(planeXY, vtNormalZ);
p3 = p3.project(planeXY, vtNormalZ);
dA = dA / dD * 1000;
dB = dB / dD * 1000;
dC = dC / dD * 1000;
double nang = vtNormalZ.angleTo(vtNormal);
double nV = GetTriangleVolumeByIntegral(dA, dB, dC, p1, p2, p3);
if(nV > 0)
dRet += nV;
if(nV < 0){//积分算法有错误,在特点的▽▼△▲下,体积《0
AcGePoint3d p11,p22,p33;
pFace->getVertexAt(0, p11);
pFace->getVertexAt(1, p22);
pFace->getVertexAt(2, p33);
AcDbFace *pFaceNew = new AcDbFace();
pFaceNew->setVertexAt(0, p11);
pFaceNew->setVertexAt(1, p22);
pFaceNew->setVertexAt(2, p33);
pFaceNew->setVertexAt(3, p11);
AddToModelSpace(pFaceNew, Adesk::kTrue);
}
}
}
ReleaseEntSet(TriangleSet);
//因为计算完体积有bug,投影到0标高的体积。所以减去下面的部分。
double dArea = poly.Area()/1000000;
dRet -= dArea * dRoofEle/1000.0;
}
OPENOBJ_END();
return dRet;
}
void GetRoofAllPoly(AcDbObjectId id, DList<XPoly2D> &lstPoly)
{
double dRet(0);
OPENOBJ_BEGIN(id, AcDb::kForRead, TDbPolyPathEnt, pRoof);
if(pRoof){
AcDbVoidPtrArray entSet;
XExplodeStream dc(entSet);
pRoof->ExplodeOrDraw3d(dc);
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);
AcGePoint3d p1,p2,p3,p4;
pFace->getVertexAt(0, p1);
pFace->getVertexAt(1, p2);
pFace->getVertexAt(2, p3);
pFace->getVertexAt(3, p4);
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
if(vtNormal.z < 0.00001)
continue;
XPoly2D *poly = new XPoly2D();
poly->AppendNode(p1);
poly->AppendNode(p2);
poly->AppendNode(p3);
poly->AppendNode(p4);
if(p1 != p4)
poly->AppendNode(p1);
lstPoly.Append(poly);
}
}
ReleaseEntSet(entSet);
}
OPENOBJ_END();
return;
}
void VolumeRoofCmd2()
{
Entity entRoof;
RBList rbMask(RTDXF0, _T("ATS_SLOPEROOF,ATS_DUALROOF,ATS_CUSPROOF"), NULL);
if(SelectEntity(_T("\n请选择坡屋顶<退出>:"), entRoof, rbMask) != RTNORM)
return;
AcDbObjectId id = NULL;
acdbGetObjectId(id, entRoof);
double dV2 = VolumeRoof2(id);
adsout << _T("\n新计算坡屋顶的体积为:") << dV2 << _T("立方米\n");
}
void VolumeRoofCmd()
{
Entity entRoof;
RBList rbMask(RTDXF0, _T("ATS_SLOPEROOF,ATS_DUALROOF,ATS_CUSPROOF"), NULL);
if(SelectEntity(_T("\n请选择坡屋顶<退出>:"), entRoof, rbMask) != RTNORM)
return;
AcDbObjectId id = NULL;
acdbGetObjectId(id, entRoof);
double dV = VolumeRoof(id);
adsout << _T("\n坡屋顶的体积为:") << dV << _T("立方米\n");
DList<XPoly2D> lstPoly;
GetRoofAllPoly(id, lstPoly);
int len = lstPoly.Length();
double dArea(0);
for(int i=0;i<len;i++){
XPoly2D poly = *lstPoly[i];
// poly.Make();
AcGePoint3d p1,p2,p3;
p1 = *poly[0];
p2 = *poly[1];
p3 = *poly[2];
AcGeVector3d vt1(p2.x - p1.x, p2.y - p1.y, p2.z - p1.z);
AcGeVector3d vt2(p3.x - p2.x, p3.y - p2.y, p3.z - p2.z);
AcGeVector3d vtNormal = vt1.crossProduct(vt2);
vtNormal.normalize();
AcGeMatrix3d mat;
mat.setToWorldToPlane(vtNormal);
poly.TransformBy(mat);
poly.SetElevation(0);
double dTmp = poly.Area()/1000000;
dArea += dTmp;
}
adsout << _T("\n坡屋顶的面积为:") << dArea << _T("平方米\n");
}