Files
envi-code/SourceCode/Code2026/tg_shs/shs_subgeLib/TGGeSurface3D.cpp
T
2026-09-28 15:28:50 +08:00

1526 lines
32 KiB
C++

//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TGGeSurface3D.cpp
// = Version : ver2.0
// = Author : xlc
// = CreateDate : 2002-09-09
// = Description: 类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
#include "StdAfx.h"
#include "TGGeSurface3D.h"
#include "TchGlobalCurveFunc.h"
#include "TPGeCurveMesh.h"
#include "TPGeCurve2D.h"
#include "TGMLine2D.h"
#include "TGObjectList.h"
#include "TGMesh.h"
#include "TGGeCurveInline.h"
TGGeSurface3D::~TGGeSurface3D()
{
}
TGGeAFace3D::TGGeAFace3D()
{
}
TGGeAFace3D::TGGeAFace3D(TGGeCurveSegment cv,double dThick)
: TGGeCurveSegment(cv),m_fThickness(dThick)
{
}
TGGeAFace3D::TGGeAFace3D(TGGeAFace3D &face)
: TGGeCurveSegment(face),m_fThickness(face.m_fThickness)
{
}
//面上一点处
double TGGeAFace3D::GetTopElev()const
{
return StartPoint().z + m_fThickness;
}
double TGGeAFace3D::GetElev()const
{
return StartPoint().z;
}
TGGePlane TGGeAFace3D::GetPlane(TADSGePoint3d pt)const
{
return TGGePlane(pt,GetNormal(pt));
}
double TGGeAFace3D::GetAngle(TADSGePoint3d pt,TVector3D vtLight)const
{
return GetPlane(pt).GetAngle(vtLight);
}
//光线反射,返回false代表无反射
bool TGGeAFace3D::Reflect(TADSGePoint3d pt,TVector3D vtLight,TVector3D&vtRes)const
{
return GetPlane(pt).Reflect(vtLight,vtRes);
}
//是否有反射
bool TGGeAFace3D::IsReflect(TADSGePoint3d pt,TVector3D vtLight)const
{
return GetPlane(pt).IsReflect(vtLight);
}
void TGGeAFace3D::CreatePFace3D(TDPtrList<TGGePFace3D>& res,double nDiv)const
{
if (Is(CURVE_LINE))
{
TGGePFace3D *pFace = new TGGePFace3D;
pFace->AppendNode(StartPoint());
pFace->AppendNode(EndPoint());
TADSGePoint3d pt3 = EndPoint();
pt3.z += m_fThickness;
pFace->AppendNode(pt3);
TADSGePoint3d pt4 = StartPoint();
pt4.z += m_fThickness;
pFace->AppendNode(pt4);
res.Append(pFace);
}
else
{
TGGePoly2D poly,poly1;
AsPoly2D(poly);
poly.Disperse1(poly1,nDiv);
for (long i = 0; i < poly1.TotalSegments(); i++)
{
TGGeCurveSegment cv;
poly1.Nth(i,cv);
TGGePFace3D *pFace = new TGGePFace3D;
pFace->AppendNode(cv.StartPoint());
pFace->AppendNode(cv.EndPoint());
TADSGePoint3d pt3 = cv.EndPoint();
pt3.z += m_fThickness;
pFace->AppendNode(pt3);
TADSGePoint3d pt4 = cv.StartPoint();
pt4.z += m_fThickness;
pFace->AppendNode(pt4);
res.Append(pFace);
}
}
}
void TGGeAFace3D::CreatePFace3D(TGGePFace3D& face)const
{
face.AppendNode(StartPoint());
face.AppendNode(EndPoint());
TADSGePoint3d pt3 = EndPoint();
pt3.z += m_fThickness;
face.AppendNode(pt3);
TADSGePoint3d pt4 = StartPoint();
pt4.z += m_fThickness;
face.AppendNode(pt4);
}
TVector3D TGGeAFace3D::GetNormal(TADSGePoint3d pt)const
{
if (Is(CURVE_LINE))
{
double ang = ads_angle(StartPoint(), EndPoint()) - PI / 2;
return TVector3D(cos(ang),sin(ang));
}
else
{
TGGeArc arc(StartPoint(),EndPoint(),GetBulge());
TVector3D vt = pt - arc.GetCenterPt();
vt.z = 0;
vt.Normalize();
if (GetBulge() < 0)
{
vt.Reverse();
}
return vt;
}
}
//从一点射出的光线与面求交
bool TGGeAFace3D::LightInt(TADSGePoint3d ptFrom, TVector3D vtLight, TADSGePoint3d &ptInt)const
{
if (fabs(vtLight.z) < 1E-6) //光线不能是竖的
{
return false;
}
TGGeCurveSegment cv1 = *this;
TGGeLine cv2(ptFrom,ptFrom + vtLight);
cv1.SetElevation(0);
cv2.SetElevation(0);
TADSGePoint3d pt1,pt2;
int nRet = cv1.Intersection(cv2,pt1,pt2);
if (nRet < 1)
{
return false;
}
TVector3D vtLightXY(vtLight.x,vtLight.y);
vtLightXY.Normalize();
if (nRet == 2) //要过滤一个点
{
TVector3D vt1(pt1 - ptFrom);
vt1.z = 0;
if (vt1.Length() < 1E-6) //ptInt==ptFrom也认为不交
{
pt1 = pt2;
}
else
{
vt1.Normalize();
double dVal = vt1 & vtLightXY;
if ( dVal < 1E-6) //交于反向延长线
{
pt1 = pt2;
}
else
{
TVector3D vt2(pt2 - ptFrom);
vt2.z = 0;
if (vt2.Length() > 1E-6)
{
dVal = vt2 & vtLightXY;
if (dVal > 1E-6)
{
if (pt2.Distance2d(ptFrom) < pt1.Distance2d(ptFrom))
{
pt1 = pt2;
}
}
}
}
}
nRet = 1;
}
if (nRet == 1)
{
ptInt = pt1;
TVector3D vt1(pt1 - ptFrom);
vt1.z = 0;
if (vt1.Length() < 1E-6) //ptInt==ptFrom也认为不交
{
return false;
}
vt1.Normalize();
double dVal = vt1 & vtLightXY;
if (dVal < 1E-6) //交于反向延长线
{
return false;
}
}
TVector3D vt = vtLight;
vt.Scale(ptInt.Distance2d(ptFrom) / cv2.GetLength());
ptInt.z = ptFrom.z + vt.z;
if ((ptInt.z - GetElev()) < -1E-6 || ptInt.z - GetTopElev() > 1E-6)
{
return false;
}
return true;
}
//直线代表入射光线,返回false代表无反射(无阻挡)
bool TGGeAFace3D::Reflect(TGGeLine &lineLight, TGGeLine &lineRes)const
{
TVector3D vtLight(lineLight.EndPoint() - lineLight.StartPoint());
vtLight.Normalize();
TADSGePoint3d ptInt;
lineLight.SetLineFlag(LS_INFINITE);
if (!LightInt(lineLight.StartPoint(),vtLight,ptInt))//不与光线相交
{
return false;
}
TVector3D vtRes;
if (!Reflect(ptInt,vtLight,vtRes)) //不正确的入射方向
{
return false;
}
lineLight.EndPoint() = ptInt;
lineRes.StartPoint() = ptInt;
lineRes.EndPoint() = ptInt + vtRes;
return true;
}
bool TGGeAFace3D::GetShadow(TVector3D vtLightIn,double nElev,TDPtrList<TGGeRegion2D>&lstPoly,bool bSpeed)const
{
if (vtLightIn.z > -1E-4) //不是向下光线
{
return false;
}
if ((GetTopElev() - nElev) < 1E-6) //没有高出投影面
{
return false;
}
double botElev = nElev; //真实低标高
if (GetElev() > nElev)
{
botElev = GetElev();
}
if (Is(CURVE_LINE))
{
TGGePFace3D face;
face.AppendNode(TADSGePoint3d(EndPoint().x,EndPoint().y,botElev));
face.AppendNode(TADSGePoint3d(EndPoint().x,EndPoint().y,GetTopElev()));
face.AppendNode(TADSGePoint3d(StartPoint().x,StartPoint().y,GetTopElev()));
face.AppendNode(TADSGePoint3d(StartPoint().x,StartPoint().y,botElev));
return face.GetShadow(vtLightIn,nElev,lstPoly,bSpeed);
}
else
{
TGGeArc arc(StartPoint(),EndPoint(),GetBulge());
TVector3D vt1 = vtLightIn, vt2 = vtLightIn; //上下表面投影矢量
TGGeCurveSegment *pCv1,*pCv2; //上下表面投影线
TGGeCurveSegment *pCv3,*pCv4; //端点投影线
TGGeCurveSegment *pCv5 = NULL, *pCv6 = NULL; //切点投影线
//下表面投影
if ((botElev - nElev) > 1E-6) //下表面高出投影面
{
double dVal = (nElev - botElev) / vtLightIn.z;
vt1.Scale(dVal);
pCv1 = new TGGeCurveSegment;
*pCv1 = arc;
pCv1->StartPoint() += vt1;
pCv1->EndPoint() += vt1;
pCv1->SetElevation(0);
}
else //下表面与投影面平
{
pCv1 = new TGGeCurveSegment;
*pCv1 = arc;
vt1 = TVector3D(0,0,0);
pCv1->SetElevation(0);
}
//上表面投影
double dVal = (nElev - GetTopElev()) / vtLightIn.z;
vt2.Scale(dVal);
pCv2 = new TGGeCurveSegment;
*pCv2 = arc;
pCv2->StartPoint() += vt2;
pCv2->EndPoint() += vt2;
pCv2->SetElevation(0);
//端点反射
pCv3 = new TGGeCurveSegment(pCv1->StartPoint(),pCv2->StartPoint(),0);
pCv4 = new TGGeCurveSegment(pCv1->EndPoint(),pCv2->EndPoint(),0);
//切点投影
AcGeVector2d vtLightInXY(vtLightIn.x,vtLightIn.y); //入射光线平面矢量
double angLightInXY = vtLightInXY.angle(); //入射光线的平面角
double angTangent0 = NA(angLightInXY + PI / 2); //入射光线与圆第一切点圆心角
double angTangent1 = NA(angLightInXY - PI / 2); //入射光线与圆第二切点圆心角
if (AIN(angTangent0,arc.GetStarAngle(),ALEN(arc.GetStarAngle(),arc.GetEndAngle())))//包含第一切点
{
TADSGePoint3d pt = arc.GetCenterPt() + TADSGePoint3d(arc.GetRadius() * cos(angTangent0),arc.GetRadius() * sin(angTangent0));
pCv5 = new TGGeCurveSegment(pt + vt1, pt + vt2,0);
pCv5->SetElevation(0);
}
if (AIN(angTangent1,arc.GetStarAngle(),ALEN(arc.GetStarAngle(),arc.GetEndAngle())))//包含第二切点
{
TADSGePoint3d pt = arc.GetCenterPt() + TADSGePoint3d(arc.GetRadius() * cos(angTangent1), arc.GetRadius() * sin(angTangent1));
pCv6 = new TGGeCurveSegment(pt + vt1, pt + vt2, 0);
pCv6->SetElevation(0);
}
//搜索区域
TDPtrList<TGGePoly2D> buf;
TDPtrList<TGGeCurveSegment> lstSeg;
lstSeg.Append(pCv1);
lstSeg.Append(pCv2);
lstSeg.Append(pCv3);
lstSeg.Append(pCv4);
if (pCv5 != NULL)
{
lstSeg.Append(pCv5);
}
if (pCv6 != NULL)
{
lstSeg.Append(pCv6);
}
TGObjectList oList,oList1;
for (long i = 0; i < lstSeg.Length(); i++)
{
oList << TGGeCurveSegmentToTPGeCurve2D(*lstSeg[i]);
}
oList.InterBreakCurve2D(oList1);
TPGeCurveMesh mesh(oList1);
mesh.FindAllMesh();
for (mesh.m_allMesh.MoveToFirst(); !mesh.m_allMesh.IsOut(); mesh.m_allMesh.MoveToNext())
{
TPGeCurve2D* pCurve = mesh.m_allMesh.GetCurData()->CreateCurve();
if (!pCurve->IsClockwise())
{
TGMLine2D *pPline = pCurve->PLinearize();
if (pPline != NULL)
{
TGGePoly2D poly(1);
TGMLine2DToTGGePoly2D(*pPline,poly);
delete pPline;
poly.Compress();
poly.SetElevation(nElev);
buf.Append(new TGGePoly2D(poly));
}
}
delete pCurve;
}
if (buf.Length() < 1)
{
return false;
}
for (i = 0; i < buf.Length(); i++)
{
lstPoly.Append(new TGGeRegion2D(*buf[i]));
}
return true;
}
}
bool TGGeAFace3D::Reflect(TVector3D vtLightIn,double nElev,TDPtrList<TGGeRegion2D>& polyRes)const
{
if (vtLightIn.z > -1E-4) //不是向下光线
{
return false;
}
if ((GetTopElev() - nElev) < 1E-6) //没有高出投影面
{
return false;
}
double botElev = nElev; //真实低标高
if (GetElev() > nElev)
{
botElev = GetElev();
}
if (Is(CURVE_LINE))
{
TVector3D vtLightOut;
TGGePFace3D face;
face.AppendNode(TADSGePoint3d(EndPoint().x,EndPoint().y,botElev));
face.AppendNode(TADSGePoint3d(EndPoint().x,EndPoint().y,GetTopElev()));
face.AppendNode(TADSGePoint3d(StartPoint().x,StartPoint().y,GetTopElev()));
face.AppendNode(TADSGePoint3d(StartPoint().x,StartPoint().y,botElev));
TGGePoly2D newPoly(1);
if (face.Reflect(vtLightIn,nElev,vtLightOut,newPoly))
{
polyRes.Append(new TGGeRegion2D(newPoly));
return true;
}
else
{
return false;
}
}
else
{
TGGeArc arc(StartPoint(),EndPoint(),GetBulge()); //所在圆弧
//计算真正有反射作用的圆弧,最多两段
AcGeVector2d vtLightInXY(vtLightIn.x,vtLightIn.y); //入射光线平面矢量
double angLightInXY = vtLightInXY.angle(); //入射光线的平面角
double angTangent0 = AngleRangeTo2PI(angLightInXY + PI / 2);//入射光线与圆第一切点圆心角
if (GetBulge() < 0) //圆内表面反射
{
angTangent0 = AngleRangeTo2PI(angLightInXY - PI / 2);
}
TGObjectList lstArc; //真正有反射作用的圆弧,最多两段
TPGeArc2D arcNew((double*)arc.GetCenterPt(),arc.GetRadius(),arc.GetStarAngle(),arc.Bulge());
TPGeArc2D arcScopeNew((double*)arc.GetCenterPt(),arc.GetRadius(),angTangent0,PI);//标准半圆弧
arcNew.SetElev(0);
arcScopeNew.SetElev(0);
arcNew.Intersect(arcScopeNew,lstArc);
for (lstArc.MoveToFirst(); !lstArc.IsOut(); lstArc.MoveToNext())
{
if (!IS_CLASS(lstArc.GetCurData(),TPGeArc2D)) //过滤非弧交
{
lstArc.DelCur();
}
}
if (lstArc.IsEmpty())
{
return false;
}
//反射
TDPtrList<TGGePoly2D> buf;
for (lstArc.MoveToFirst(); !lstArc.IsOut(); lstArc.MoveToNext())
{
TPGeArc2D* pArc = (TPGeArc2D*)lstArc.GetCurData();
if (!pArc->IsValid())
{
continue;
}
TGMLine2D *pMLine = pArc->MLinearize();
if (pMLine == NULL)
{
continue;
}
if (GetBulge() > 0) //外表面反射
{
TGGePoly2D *pPoly = new TGGePoly2D(1);
//下表面反射
if ((botElev - nElev) > 1E-6) //下表面高出投影面
{
double dVal = (nElev - botElev) / vtLightIn.z;
for (long i = pMLine->GetVertexNum() - 1; i >= 0; i--)
{
TADSGePoint3d pt((double*)(*pMLine)[i]);
TVector3D vtLightOut;
Reflect(pt,vtLightIn,vtLightOut);
TVector3D vt = vtLightOut;
vt.Scale(dVal);
pt += vt;
pPoly->AppendNode(pt);
}
}
else //下表面与投影面平
{
TGPoint pt0 = pArc->GetEndPoint(),pt1 = pArc->GetStartPoint();
pPoly->AppendNode((double*)pt0,-pArc->centralAngle);
pPoly->AppendNode((double*)pt1);
}
//上表面反射
double dVal = (nElev - GetTopElev()) / vtLightIn.z;
for (long i = 0; i < pMLine->GetVertexNum();i++)
{
TADSGePoint3d pt((double*)(*pMLine)[i]);
TVector3D vtLightOut;
Reflect(pt,vtLightIn,vtLightOut);
TVector3D vt = vtLightOut;
vt.Scale(dVal);
pt += vt;
pPoly->AppendNode(pt);
}
delete pMLine;
pPoly->SetElevation(0);
pPoly->Compress();
pPoly->SetElevation(nElev);
buf.Append(pPoly);
}
else //内表面反射,要用搜索范围的方法
{
TDPtrList<TGGeCurveSegment> lstSeg;
TGGePoly2D poly0,poly1; //下表面上表面反射线
double s0 = (nElev - botElev) / vtLightIn.z,
s1 = (nElev - GetTopElev()) / vtLightIn.z;
for (long i = 0; i < pMLine->GetVertexNum(); i++)
{
TADSGePoint3d pt0((double*)(*pMLine)[i]),
pt1((double*)(*pMLine)[i]);
TVector3D vtLightOut;
Reflect(pt0,vtLightIn,vtLightOut);
TVector3D vt0 = vtLightOut, vt1 = vtLightOut;
vt0.Scale(s0);
pt0 += vt0;
vt1.Scale(s1);
pt1 += vt1;
poly0.AppendNode(pt0);
TADSGePoint3d pt2((double*)(*pMLine)[i]);
pt2.z = GetTopElev();
TADSGePoint3d ptInt;
if (LightInt(pt2,vtLightOut,ptInt)) //反射线又与墙面相交,当前未考虑二次反射
{
poly1.AppendNode(ptInt);
}
else
{
poly1.AppendNode(pt1);
}
}
delete pMLine;
poly1.SetElevation(0);
ExplodePoly2D(poly1,lstSeg);
if (botElev - nElev > 1E-6) //下表面高出投影面
{
poly0.SetElevation(0);
ExplodePoly2D(poly0,lstSeg);
}
else if (fabs(botElev - nElev) < 1E-6) //下表面与投影面平
{
TGPoint pt1 = pArc->GetEndPoint(),
pt0 = pArc->GetStartPoint();
TGGeCurveSegment *pSeg = new TGGeCurveSegment((double*)pt0,(double*)pt1,pArc->centralAngle);
pSeg->SetElevation(0);
lstSeg.Append(pSeg);
}
//过渡线
for (i = 0; i < poly0.Length(); i++)
{
lstSeg.Append(new TGGeCurveSegment(*poly0[i],*poly1[i],0));
}
TGObjectList oList,oList1;
for (i = 0; i < lstSeg.Length(); i++)
{
oList << TGGeCurveSegmentToTPGeCurve2D(*lstSeg[i]);
}
oList.InterBreakCurve2D(oList1);
TPGeCurveMesh mesh(oList1);
mesh.FindAllMesh();
bool bExplode = false;
for (mesh.m_allMesh.MoveToFirst(); !mesh.m_allMesh.IsOut(); mesh.m_allMesh.MoveToNext())
{
TPGeCurve2D* pCurve = mesh.m_allMesh.GetCurData()->CreateCurve();
if (!pCurve->IsClockwise()) //找到唯一外轮廓
{
if (pCurve->IsSelfCross()) //理论上有可能
{
mesh.m_allMesh.DelCur(); //这样就剩下内部区域了
bExplode = true; //外轮廓不能用,只好用内部区域
}
else
{
TGMLine2D *pPline = pCurve->PLinearize();
if (pPline != NULL)
{
TGGePoly2D poly(1);
TGMLine2DToTGGePoly2D(*pPline,poly);
delete pPline;
poly.Compress();
poly.SetElevation(nElev);
buf.Append(new TGGePoly2D(poly));
}
}
delete pCurve;
break;
}
else
{
delete pCurve;
}
}
if (bExplode) //使用内部区域
{
for (mesh.m_allMesh.MoveToFirst(); !mesh.m_allMesh.IsOut(); mesh.m_allMesh.MoveToNext())
{
TPGeCurve2D* pCurve = mesh.m_allMesh.GetCurData()->CreateCurve();
TGMLine2D *pPline = pCurve->PLinearize();
if (pPline != NULL)
{
TGGePoly2D poly(1);
TGMLine2DToTGGePoly2D(*pPline,poly);
delete pPline;
poly.Reverse(); //原来朝下
poly.Compress();
poly.SetElevation(nElev);
buf.Append(new TGGePoly2D(poly));
}
delete pCurve;
}
}
}
}
if (buf.Length() < 1)
{
return false;
}
for (long i = 0; i < buf.Length(); i++)
{
polyRes.Append(new TGGeRegion2D(*buf[i]));
}
return true;
}
}
bool TGGeAFace3D::IsReflectOn(TADSGePoint3d pt,TVector3D vtLightIn,TADSGePoint3d &ptInt,TVector3D &vtLightOut)const
{
if (Is(CURVE_LINE))
{
TGGePFace3D face;
CreatePFace3D(face);
return face.IsReflectOn(pt,vtLightIn,ptInt,vtLightOut);
}
else
{
TGGeArc arc(StartPoint(),EndPoint(),GetBulge());
TADSGePoint3d ptCenter = arc.GetCenterPt();
ptCenter.z = 0;
double r = arc.GetRadius();
TADSGePoint3d ptXY(pt.x,pt.y);
//计算可能有反射作用的圆弧
TVector3D vtLightInXY(vtLightIn.x,vtLightIn.y); //入射光线平面矢量
vtLightInXY.Normalize();
double angLightInXY = vtLightInXY.AsAcGeVector2d().angle(); //入射光线的平面角
if (GetBulge() > 0) //外表面反射
{
double angTangent0 = AngleRangeTo2PI(angLightInXY + PI / 2);//入射光线与圆第一切点圆心角
double pa0 = angTangent0, pa1 = angTangent0 + PI;
TGGeLine line0,line1;
acutPolar(ptCenter,pa0,r,line0.StartPoint());
line0.EndPoint() = line0.StartPoint() + vtLightInXY;
acutPolar(ptCenter,pa1,r,line1.StartPoint());
line1.EndPoint() = line1.StartPoint() + vtLightInXY;
int nSide0 = line0.OnWhichSide(ptXY);
int nSide1 = line1.OnWhichSide(ptXY);
if (nSide0 == OFFSET_RIGHT && nSide1 == OFFSET_LEFT
&& ptXY.Distance2d(ptCenter) < r)
{
return false; //不在最大反射区域中
}
else if (nSide0 == 2)
{
ptInt = line0.StartPoint();
}
else if (nSide1 == 2)
{
ptInt = line1.StartPoint();
}
else
{
while(true) //二分法计算交点ptInt,无显式方程
{
double pa2 = (pa0 + pa1) / 2;
TGGeLine line2;
acutPolar(ptCenter,pa2,r,line2.StartPoint());
if (fabs(pa0 - pa1) < 1E-9)
{
ptInt = line2.StartPoint();
break;
}
TVector3D vt;
GetPlane(line2.StartPoint()).Reflect(vtLightInXY,vt);
line2.EndPoint() = line2.StartPoint() + vt;
int nSide2 = line2.OnWhichSide(ptXY);
if (nSide2 == OFFSET_LEFT)
{
line0 = line2;
pa0 = pa2;
}
else if (nSide2 == OFFSET_RIGHT)
{
line1 = line2;
pa1 = pa2;
}
else
{
ptInt = line2.StartPoint();
break;
}
}
}
ptInt.z = 0;
TVector3D vtLightOutXY = TADSGePoint3d(pt.x,pt.y) - ptInt;
vtLightOutXY.Normalize();
vtLightOutXY.Scale(TVector3D(vtLightIn.x,vtLightIn.y).Length());
vtLightOut.x = vtLightOutXY.x;
vtLightOut.y = vtLightOutXY.y;
vtLightOut.z = vtLightIn.z;
TGGeLine lineLightIn(pt,pt - vtLightOut),lineRes;
if (Reflect(lineLightIn,lineRes))
{
ptInt = lineLightIn.EndPoint();
return true;
}
else
{
return false;
}
}
else //内表面反射
{
return false;
}
}
}
bool TGGeAFace3D::Project(TVector3D vtLightIn,double nElev,const TGGePFace3D& face,TDPtrList<TGGeRegion2D>&lstPoly)const
{
if (Is(CURVE_LINE))
{
TGGePFace3D faceTemp;
CreatePFace3D(faceTemp);
return faceTemp.Project(vtLightIn,nElev, face,lstPoly);
}
else
{
return false;
}
}
//-----------------------------------------------------------------------------+
// Copyright (C), 1998-2007, Beijing Tangent Software Co. Ltd.
// = FileName : TGGePFace3D.cpp
// = Version : ver2.0
// = Author : xlc
// = CreateDate : 2002-09-09
// = Description: 类的定义
// = Maintainers:
//
//-----------------------------------------------------------------------------+
TGGePFace3D::TGGePFace3D()
: TGGePoly3D(1)
{
}
TGGePFace3D::TGGePFace3D(const TGGePoly2D&poly)
{ TGGePoly3D::operator = (poly);
}
TGGePFace3D::TGGePFace3D(const TGGe3DFace&face)
{
*this = face.GetPoly3D();
}
TGGePFace3D::~TGGePFace3D()
{
}
//所在平面
TGGePlane TGGePFace3D::GetPlane()const
{
return TGGePlane((*this)[0], GetNormal(true));
}
void TGGePFace3D::CreatePFace3D(TDPtrList<TGGePFace3D>&lstFace, double nDiv)const
{
lstFace.Append(new TGGePFace3D(*this));
}
double TGGePFace3D::GetAngle(TVector3D vtLightIn)const
{
return GetPlane().GetAngle(vtLightIn);
}
//光线反射,返回false代表无反射
bool TGGePFace3D::Reflect(TVector3D vtLightIn, TVector3D &vtLightOut)const
{
return GetPlane().Reflect(vtLightIn,vtLightOut);
}
bool TGGePFace3D::IsReflect(TVector3D vtLightIn)const
{
return GetPlane().IsReflect(vtLightIn);
}
//投影点包含测试
bool TGGePFace3D::IsInclude(TADSGePoint3d pt)const
{
TGGePoly3D poly = *this;
AcGeMatrix3d mat;
mat.setToWorldToPlane(GetNormal(false));
poly.TransformBy(mat);
pt.TransformBy(mat);
poly.SetElevation(0);
pt.z = 0;
int nRet = pt & (TGGePoly2D&)poly;
return nRet != PR_OUTSIDE;
}
//面与直线(段)相交
bool TGGePFace3D::Intersect(const TGGeLine& line,TADSGePoint3d &ptInt)const
{
TGGePlane plane((*this)[0L],GetNormal(false));
if (!plane.Intersect(line,ptInt))//不与相交
{
return false;
}
return IsInclude(ptInt);
}
//ptFrom在面上时返回false
bool TGGePFace3D::LightInt(TADSGePoint3d ptFrom,TVector3D vtLight,TADSGePoint3d &ptInt)const
{
if (!Intersect(TGGeLine(ptFrom,ptFrom + vtLight),ptInt))
{
return false;
}
TVector3D vt(ptInt - ptFrom);
if (vt.Length() < 1E-6)//ptFrom==ptInt也认为不交
{
return false;
}
vt.Normalize();
double s = vt & vtLight;
if (s < 1E-6)//交于反向延长线
{
return false;
}
return true;
}
//光线反射模拟,lineLight输入入射光线,返回时终点设为与面的交点
bool TGGePFace3D::Reflect(TGGeLine &lineLight, TGGeLine& lineRes)const
{
TVector3D vtLight(lineLight.GetEndPoint() - lineLight.GetStartPoint());
vtLight.Normalize();
TVector3D vtRes;
if (!Reflect(vtLight, vtRes)) //不正确的入射方向
{
return false;
}
TADSGePoint3d ptInt;
if (!LightInt(lineLight.GetStartPoint(),vtLight,ptInt))
{
return false;
}
lineLight.SetEndPoint(ptInt);
lineRes.SetStartPoint(ptInt);
lineRes.SetEndPoint(ptInt + vtRes);
return true;
}
//大阳光线反射模拟,lineLight输入入射光线,返回时终点设为与面的交点
bool TGGePFace3D::ReflectSunLight(TGGeLine &lineLight, TGGeLine& lineRes)const
{
TVector3D vtLight(lineLight.GetEndPoint() - lineLight.GetStartPoint());
vtLight.Normalize();
TVector3D vtRes;
if (!Reflect(vtLight, vtRes)) //不正确的入射方向
{
return false;
}
TADSGePoint3d ptInt;
if (!Intersect(lineLight,ptInt))
{
return false;
}
lineLight.SetEndPoint(ptInt);
lineRes.SetStartPoint(ptInt);
lineRes.SetEndPoint(ptInt + vtRes);
return true;
}
//pt在面上时返回false;
bool TGGePFace3D::IsReflectOn(TADSGePoint3d pt,TVector3D vtLightIn,TADSGePoint3d &ptInt,TVector3D &vtLightOut)const
{
if (!Reflect(vtLightIn,vtLightOut))
{
return false;
}
TVector3D v = pt - (*this)[0L];
if (v.Length() < 1E-6)
{
return false;
}
v.Normalize();
double s = v & GetNormal(true);
if (s < 1E-6) //不在前方
{
return false;
}
return Intersect(TGGeLine(pt, pt + vtLightOut, LS_INFINITE), ptInt);
}
void TGGePFace3D::IsReflectOn(TVector3D vtLightIn,const TDPtrList<TADSGePoint3d> &lstPt,TVector3D &vtLightOut,TDPtrList<bool> &res)const
{
for (long i = 0; i < res.Length(); i++)
{
*res[i] = false;
}
if (!Reflect(vtLightIn,vtLightOut))
{
return;
}
TGGePoly3D poly = *this;
AcGeMatrix3d mat;
mat.setToWorldToPlane(vtLightOut.AsAcGeVector3d());
poly.TransformBy(mat);
poly.SetElevation(0);
poly.Compress();
if (poly.Length() < 3)
{
return;
}
for(i = 0; i < lstPt.Length(); i++)
{
TADSGePoint3d pt = lstPt[i];
TVector3D v = pt - (*this)[0L];
if (v.Length() < 1E-6)
{
res.Append(new bool(false));
continue;
}
v.Normalize();
double s = v & GetNormal(true);
if (s < 1E-6) //不在前方
{
res.Append(new bool(false));
}
else
{
pt.TransformBy(mat);
pt.z = 0;
res.Append(new bool((pt & poly) != PR_OUTSIDE)); //认为边界可以照射到
}
}
}
bool TGGePFace3D::GetShadow(TVector3D vtLightIn,double nElev,TDPtrList<TGGeRegion2D>& lstPoly,bool bSpeed)const
{
if (vtLightIn.z > -1E-4) //不是向下光线
{
return false;
}
if (bSpeed)
{
if (!IsReflect(vtLightIn))
{
return false;
}
}
else
{
if (vtLightIn.AsAcGeVector3d().isPerpendicularTo(GetNormal(false))) //与平面平行
{
return false;
}
}
TADSGePoint3d ptMin,ptMax;
GetExtend(ptMin,ptMax);
if ((ptMax.z - nElev) < 1E-6) //上面没有
{
return false;
}
TGGePoly2D polyRes(1);
for (long i = 0; i < Length(); i++)
{
TADSGePoint3d pt = (*this)[i];
TVector3D vt = vtLightIn;
vt.Scale((nElev - pt.z) / vtLightIn.z);
pt += vt;
pt.z = 0;
polyRes.AppendNode(pt);
}
if (polyRes.PathArea() > 0)
{
polyRes.Reverse(); //保证朝上
}
polyRes.Compress();
if ((ptMin.z - nElev) < -1E-6) //有上有下,需要分割出有效部分
{
//准备平面切割线来切割投影
TGGeLine line0;
if (!GetPlane().Intersect(TGGePlane(0,0,1,0),line0))
{
return false;
}
TPGeGLine2D line(TGPoint((double*)(line0.GetStartPoint())),TGPoint((double*)(line0.GetEndPoint())));
line.SetElev(0);
AcGeVector3d vtNormal = GetNormal(true);
if (line.IsVectorRight(TGVector2D(vtNormal.x,vtNormal.y)))
{
line.Reverse();
}
//切割
TGPLine2D polyNew;
TGGePoly2DToTGPLine2D(polyRes,polyNew);
TGObjectList left,right;
line.Cut(polyNew,left,right,right);
if (right.IsEmpty())
{
return false;
}
TGObject *pObj = right.GetAt(0);
if (!IS_CLASS(pObj,TPGeCurve2D))
{
return false;
}
TPGeCurve2D* pCurve = (TPGeCurve2D*)pObj;
TGMLine2D* pMLine = pCurve->MLinearize();
if (pMLine == NULL)
{
return false;
}
pMLine->SetClosed();
TGMLine2DToTGGePoly2D(*pMLine,polyRes);
delete pMLine;
polyRes.Compress();
}
polyRes.SetElevation(nElev);
lstPoly.Append(new TGGeRegion2D(polyRes));
return true;
}
//本面反射光线投影到水平面,这个函数适用于凹多边形
bool TGGePFace3D::Reflect(TVector3D vtLightIn, double nElev, TVector3D &vtLightOut, TGGePoly2D&polyRes)const
{
if (!Reflect(vtLightIn,vtLightOut))
{
return false;
}
if (vtLightOut.z > -1E-4) //不是向下光线
{
return false;
}
TADSGePoint3d ptMin,ptMax;
GetExtend(ptMin,ptMax);
if ((ptMax.z - nElev) < 1E-6) //上面没有
{
return false;
}
polyRes.SetFlag(1);
for (long i = 0; i < Length(); i++)
{
TADSGePoint3d pt = (*this)[i];
TVector3D vt = vtLightOut;
vt.Scale((nElev - pt.z) / vtLightOut.z);
pt += vt;
pt.z = 0;
polyRes.AppendNode(pt);
}
polyRes.Reverse(); //原朝下,保证朝上
polyRes.Compress();
if ((ptMin.z - nElev) < -1E-6) //有上有下,需要分割出有效部分
{
//准备平面切割线来切割投影
TGGeLine line0;
if (!GetPlane().Intersect(TGGePlane(0,0,1,0),line0))
{
return false;
}
TPGeGLine2D line(TGPoint((double*)(line0.GetStartPoint())),TGPoint((double*)(line0.GetEndPoint())));
line.SetElev(0);
AcGeVector3d vtNormal = GetNormal(true);
if (line.IsVectorRight(TGVector2D(vtNormal.x,vtNormal.y)))
{
line.Reverse();
}
//切割
TGPLine2D polyNew;
TGGePoly2DToTGPLine2D(polyRes,polyNew);
TGObjectList left,right;
line.Cut(polyNew,left,right,right);
if (left.IsEmpty())
{
return false;
}
TGObject *pObj = left.GetAt(0);
if (!IS_CLASS(pObj,TPGeCurve2D))
{
return false;
}
TPGeCurve2D* pCurve = (TPGeCurve2D*)pObj;
TGMLine2D* pMLine = pCurve->MLinearize();
if (pMLine == NULL)
{
return false;
}
pMLine->SetClosed();
TGMLine2DToTGGePoly2D(*pMLine,polyRes);
delete pMLine;
polyRes.Compress();
}
polyRes.SetElevation(nElev);
return true;
}
bool TGGePFace3D::Reflect(TVector3D vtLightIn, double nElev, TDPtrList<TGGeRegion2D>& polyRes)const
{
TGGePoly2D newPoly(1);
TVector3D vtLightOut;
if (!Reflect(vtLightIn, nElev, vtLightOut, newPoly))
{
return false;
}
polyRes.Append(new TGGeRegion2D(newPoly));
return true;
}
//本面反射光线投影到三维面,返回覆盖区域,重合面不反射
void TGGePFace3D::Reflect(TVector3D vtLightIn, TGGePFace3D faceDest, TVector3D &vtLightOut, TDPtrList<TGGePFace3D>&faceNewList)const
{
if (!Reflect(vtLightIn,vtLightOut)) //要求本面是正向面
{
return;
}
TVector3D vtLightLast;
if (!faceDest.Reflect(vtLightOut, vtLightLast)) //要求faceDest是正向面
{
return;
}
TGGePoly3D polyDest = faceDest, polyLight = *this;
//准备投影矩阵
AcGeMatrix3d matShadow;
TVector3D vtNormal = faceDest.GetNormal(true);
TGGePlane planeDest(*faceDest[0],vtNormal);
if (!GetShadowMatrix(planeDest, vtLightOut, matShadow))
{
return;
}
//本面投影到接受面
polyLight.TransformBy(matShadow);
//转换到平面求面交
AcGeMatrix3d matW2P;
matW2P.setToWorldToPlane(vtNormal);
polyDest.TransformBy(matW2P);
polyLight.TransformBy(matW2P);
double nOldElev = polyDest[0]->z;
polyDest.SetElevation(0); //经过多次运算的有误差可能出现
polyLight.SetElevation(0);
TDPtrList<TGGePoly2D> lstPoly;
if (TchSubExport::Intersect(polyDest, polyLight, lstPoly) != RTNORM || lstPoly.Length() == 0)
{
return;
}
//由平面面交得到最终WCS下交集
AcGeMatrix3d matP2W;
matP2W.setToPlaneToWorld(vtNormal);
for (long i = 0; i < lstPoly.Length(); i++)
{
TGGePoly3D polyTemp = *lstPoly[i];
polyTemp.Compress();
if (polyTemp.Length() < 3)
{
continue;
}
//面交结果回到WCS
polyTemp.SetElevation(nOldElev);
polyTemp.TransformBy(matP2W);
//保证方向不变
if (polyTemp.GetNormal(true) != vtNormal)
{
polyTemp.Reverse();
}
//由通过中心点的光线与两个面求交来判断两个面相对于光线的前后关系 
TADSGePoint3d ptCenter;
polyTemp.Center(ptCenter);
TADSGePoint3d ptCenter0,ptCenter1;
TGGeLine lineLight(ptCenter,ptCenter + vtLightOut);
if (!Intersect(lineLight,ptCenter0) || !faceDest.Intersect(lineLight,ptCenter1))
{
continue;
}
TVector3D vt = ptCenter1 - ptCenter0;
if (vt.Length() < 1E-6) //重合面不反射
{
continue;
}
vt.Normalize();
if ((vt & vtLightOut) < 1E-6)
{
continue;
}
//最后将polyTemp转化为XPFace3D;
faceNewList.Append(new TGGePFace3D(polyTemp));
}
}
//光线经this面遮挡而在faceDest造成的阴影区(无反射区),重合面不遮挡!
void TGGePFace3D::Project(TVector3D vtLightIn, const TGGePFace3D &faceDest, TDPtrList<TGGePFace3D> &faceNewList)const
{
TVector3D vtLightOut;
if (!Reflect(vtLightIn,vtLightOut) || !faceDest.Reflect(vtLightIn,vtLightOut)) //只处理正向面
{
return;
}
TGGePoly3D polyDest = faceDest,polyLight = *this;
//准备投影矩阵
AcGeMatrix3d matShadow;
TVector3D vtNormal = faceDest.GetNormal(true);
TGGePlane planeDest(faceDest[0],vtNormal);
if (!GetShadowMatrix(planeDest,vtLightIn,matShadow))
{
return;
}
//本面投影到接受面
polyLight.TransformBy(matShadow);
//转换到平面求面交
AcGeMatrix3d matW2P;
matW2P.setToWorldToPlane(vtNormal);
polyDest.TransformBy(matW2P);
polyLight.TransformBy(matW2P);
double nOldElev = polyDest[0]->z;
polyDest.SetElevation(0); //经过多次运算的有误差可能出现
polyLight.SetElevation(0);
TDPtrList<TGGePoly2D> lstPoly;
if (TchSubExport::Intersect(polyDest,polyLight, lstPoly) != RTNORM || lstPoly.Length() == 0)
{
return;
}
//由平面面交得到最终WCS下交集
AcGeMatrix3d matP2W;
matP2W.setToPlaneToWorld(vtNormal);
for (long i = 0; i < lstPoly.Length(); i++)
{
TGGePoly3D polyTemp = *lstPoly[i];
polyTemp.Compress();
if (polyTemp.Length() < 3)
{
continue;
}
//面交结果回到WCS
polyTemp.SetElevation(nOldElev);
polyTemp.TransformBy(matP2W);
//保证方向不变
if (polyTemp.GetNormal(true) != vtNormal)
{
polyTemp.Reverse();
}
//由通过中心点的光线与两个面求交来判断两个面相对于光线的前后关系 
TADSGePoint3d ptCenter;
polyTemp.Center(ptCenter);
TADSGePoint3d ptCenter0,ptCenter1;
TGGeLine lineLight(ptCenter, ptCenter + vtLightIn);
if (!Intersect(lineLight, ptCenter0) || !faceDest.Intersect(lineLight, ptCenter1))
{
continue;
}
TVector3D vt = ptCenter1 - ptCenter0; //重合面不遮挡!
if (vt.Length() < 1E-6)
{
continue;
}
vt.Normalize();
if ((vt & vtLightIn) < 1E-6) //以光线为参考,在后
{
continue;
}
//最后将polyTemp转化为XPFace3D;
faceNewList.Append(new TGGePFace3D(polyTemp));
}
}
//在face遮挡条件下,光线经本面反射,最后在平面上形成的阴影区,考虑了face对入射光线和反射光线的遮挡
bool TGGePFace3D::Project(TVector3D vtLightIn, double nElev, const TGGePFace3D& face, TDPtrList<TGGeRegion2D>&lstPoly)const
{
TDPtrList<TGGeRegion2D> buf;//平面阴影区
//反射光线射到face的区域
TDPtrList<TGGePFace3D> lstDest;
TVector3D vtLightOut;
Reflect(vtLightIn, face, vtLightOut, lstDest);
//face遮挡反射光线导致的阴影
for (long i = 0; i < lstDest.Length(); i++)
{
lstDest[i]->GetShadow(vtLightOut, nElev, buf, true);
}
//face遮挡入射光线而导致的本面上的阴影区(无反射区)
TDPtrList<TGGePFace3D> lstDest1;
face.Project(vtLightIn, *this, lstDest1);
//无反射区形成的反射阴影,无反射也可以看成是遮挡了反射光线!
for (i = 0; i < lstDest1.Length(); i++)
{
lstDest1[i]->Reverse(); //反射面只有转个方向才能通过反射光的遮挡计算!
lstDest1[i]->GetShadow(vtLightOut, nElev, buf, true);
}
if (buf.Length() < 1)
{
return false;
}
else
{
lstPoly << buf;
return true;
}
}