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

817 lines
18 KiB
C++

#include "stdafx.h"
#define ACCURACY 0.000001
XContour::XContour()
:m_nVertexNum(90)
{
}
XContour::XContour(const XPoly2D& polySrc,int nVertexNum)
{
Init(polySrc,nVertexNum);
}
XContour::XContour(const XContour& src)
{
m_nVertexNum = src.m_nVertexNum;
int nCount = src.Length();
for (int i = 0; i < nCount; i++) {
Append(new XPoint(src[i]));
}
}
XContour::~XContour()
{
}
void XContour::Init(const XPoly2D& polySrc,int nVertexNum)
{
if (polySrc.Length()<=0)
return ;
if (Length()>0)
Reset();
m_nVertexNum = nVertexNum;
assert(m_nVertexNum >= 3);
double dElev = polySrc[0].z;
XPoly2D poly = polySrc;
poly.SetElevation(dElev);
Poly2DToVertexs(poly);
m_ptWeightCenter = ::GetWeightCenter(poly);
Divide();
}
// 遇弧线离散化
void XContour::Poly2DToVertexs(const XPoly2D& poly)
{
extern int GetCirDivNum(double r, double h);
extern double g_nCirDeviation;
if (poly.Length() <= 0) return;
int nSegNum = poly.TotalSegments();
for(int i = 0; i < nSegNum; i++) {
XDirectionCurve cvSeg;
poly.Nth(i, cvSeg);
if(cvSeg.Is(CURVE_LINE)) {
Append(new XPoint(cvSeg.StartPoint()));
} else {
double intAng = cvSeg.GetBulge();
int nDiv = 30;
if(cvSeg.Is(CURVE_ARC))
nDiv = TchExport::GetCirDivNum(cvSeg.GetArc().GetRadius(), _AS_SYS_UNIT(TchGeLib::g_nCirDeviation));
int nStep = AS_INT(fabs(intAng)/PI/2.0*nDiv);// how many sections
double nDistStep = cvSeg.GetLength()/nStep;
for(int j=0; j<nStep; j++) {
XPointDir2d ptE;
cvSeg.Polar(nDistStep*j, ptE);
Append(new XPoint(ptE));
}
}
}
}
// 以基点为中心均分顶点
void XContour::Divide()
{
int nCount = Length();
if (nCount <= 0) return;
DList<XPoint> lstVertex;
for (int i = 0; i < nCount; i++) {
XPoint ptThis = *(*this)[i];
lstVertex.Append(new XPoint(ptThis));
}
Reset();
const double dAngleTotal = PI*2;
for (int nVertex=0; nVertex<m_nVertexNum; nVertex++) {
double dAngle = dAngleTotal*nVertex/m_nVertexNum;
for (int i=0; i<nCount; i++ ) {
XPoint ptOnContour;
if (Intersection(dAngle,m_ptWeightCenter,*lstVertex[i],
*lstVertex[(i+1)%nCount],ptOnContour)) {
Append(new XPoint(ptOnContour));
break;
}
}
}
}
// 以基点为中心均分顶点
void XContour::Divide(const DList<double>& lstOtherAngle)
{
int nCount = Length();
if (nCount <= 0) return;
DList<XPoint> lstVertex;
for (int i = 0; i < nCount; i++) {
XPoint ptThis = *(*this)[i];
lstVertex.Append(new XPoint(ptThis));
}
Reset();
const double dAngleTotal = PI*2;
int nOther = lstOtherAngle.Length();
for (int nVertex=0; nVertex<m_nVertexNum; nVertex++) {
double dPreAngle = dAngleTotal*nVertex/m_nVertexNum;
double dNextAngle = dAngleTotal*(nVertex+1)/m_nVertexNum;
for (int i=0; i<nCount; i++ ) {
XPoint ptOnContour;
if (Intersection(dPreAngle,m_ptWeightCenter,*lstVertex[i],
*lstVertex[(i+1)%nCount],ptOnContour)) {
Append(new XPoint(ptOnContour));
break;
}
}
//新增加的其他的角度
for (int j=0; j<nOther; j++) {
double dAngle = lstOtherAngle[j];
if (dAngle>dPreAngle && dAngle<dNextAngle) {
for (int i=0; i<nCount; i++ ) {
XPoint ptOnContour;
if (Intersection(dAngle,m_ptWeightCenter,*lstVertex[i],
*lstVertex[(i+1)%nCount],ptOnContour)) {
Append(new XPoint(ptOnContour));
break;
}
}
}
}
}
}
BOOL XContour::Intersection(const double dAngleRayLine,
const XPoint& ptOriginRayLine,
const XPoint& ptStart,
const XPoint& ptEnd,
XPoint& ptResult) const
{
double X0 = ptOriginRayLine.x, Y0 = ptOriginRayLine.y;
double X1 = ptStart.x, Y1 = ptStart.y;
double X2 = ptEnd.x, Y2 = ptEnd.y;
double alfa = dAngleRayLine;
double beta = atan2(Y2-Y1, X2-X1);
double sinBetaMinusAlfa = sin(beta-alfa);
double Xp, Yp;
if (fabs(sinBetaMinusAlfa)>1.0E-9) { // ZJQ Modify here
double t = ((X1-X0)*sin(beta)-(Y1-Y0)*cos(beta))/sinBetaMinusAlfa;
Xp = X0 + t*cos(alfa);
Yp = Y0 + t*sin(alfa);
double dx=fabs(X1-X2), dx1=fabs(Xp-X1), dx2=fabs(X2-Xp);
double dy=fabs(Y1-Y2), dy1=fabs(Yp-Y1), dy2=fabs(Y2-Yp);
double angle=atan2(Yp-Y0, Xp-X0);
//double PI2=PI*2;//removed by whl on 060406
while(alfa < -1.0E-9) alfa += PI2;
while(alfa > 2*PI) alfa -= PI2;
while(angle < -1.0E-9) angle += PI2;
if (fabs(angle-alfa) < ACCURACY &&
fabs(dx-(dx1+dx2)) < ACCURACY &&
fabs(dy-(dy1+dy2)) < ACCURACY) {
ptResult = XPoint(Xp,Yp,ptOriginRayLine.z);
return TRUE;
}
}
return FALSE;
}
BOOL XContour::IsValid() const
{
return m_nVertexNum>=3 && Length()==m_nVertexNum;
}
void XContour::GetAngles(DList<double>& lstAngle) const
{
lstAngle.Reset();
int nNum = Length();
for (int i=0; i<nNum; i++) {
XPoint ptThis = (*this)[i];
double dAngle = ads_angle(m_ptWeightCenter,ptThis);
lstAngle.Append(new double(dAngle));
}
}
void XContour::GetRadius(DList<double>& lstRadiu) const
{
lstRadiu.Reset();
int nNum = Length();
for (int i=0; i<nNum; i++) {
XPoint ptThis = (*this)[i];
double dRadiu = m_ptWeightCenter.Distance(ptThis);
lstRadiu.Append(new double(dRadiu));
}
}
double XContour::GetPerimeter() const
{
double dPerimeter=0;
XPoly2D polyThis(1);
AsPoly2D(polyThis);
dPerimeter = polyThis.Distance2d();
return dPerimeter;
}
double XContour::GetRadius(double dAngle) const
{
double dRadius=0;
//double PI2 = 2*PI;//removed by whl on 060406
while(dAngle<0)
dAngle += PI2;
while(dAngle>=PI2)
dAngle -= PI2;
if(m_nVertexNum!=0) {
double dStepAngle=PI2/m_nVertexNum;
int nThis=int(dAngle/dStepAngle);
if (nThis<=Length()) {
XPoint ptThis = (*this)[nThis];
XPoint ptNext = (*this)[(nThis+1)%Length()];
double dDistanceThis=m_ptWeightCenter.Distance(ptThis);
double dDistanceNext=m_ptWeightCenter.Distance(ptNext);
double dToThisAngle=dAngle-nThis*dStepAngle;
dRadius = dDistanceThis +
(dDistanceNext-dDistanceThis)*dToThisAngle/dStepAngle;
}
}
return dRadius;
}
double XContour::GetArea() const
{
double dArea=0;
XPoly2D polyThis(1);
AsPoly2D(polyThis);
dArea = polyThis.Area();
return dArea;
}
XPoint XContour::GetWeightCenter() const
{
return m_ptWeightCenter;
}
//********************* XContour2D BEGIN ***********************//
XContour2D::XContour2D()
{
}
XContour2D::XContour2D(const XPoly2D& polySrc,
const XPoint& ptBase,
int nVertexNum,
const DList<double>& lstOtherAngle)
{
Init(polySrc,ptBase,nVertexNum,lstOtherAngle);
}
XContour2D::XContour2D(const XContour2D& src)
{
m_nVertexNum = src.m_nVertexNum;
m_ptBase = src.m_ptBase;
int nCount = src.Length();
for (int i = 0; i < nCount; i++) {
Append(new XPoint(src[i]));
}
}
XContour2D::~XContour2D()
{
}
void XContour2D::Init(const XPoly2D& polySrc,
const XPoint& ptBase,
int nVertexNum,
const DList<double>& lstOtherAngle)
{
assert(m_nVertexNum >= 3);
if (polySrc.Length() <= 0) return ;
if (Length()>0) Reset();
m_ptBase = ptBase;
m_nVertexNum = nVertexNum;
double dElev = m_ptBase.z;
XPoly2D poly = polySrc;
poly.SetElevation(dElev);
Poly2DToVertexs(poly);
m_ptWeightCenter = ::GetWeightCenter(poly);
if (lstOtherAngle.Length()>0) {
Divide(lstOtherAngle);
}
else {
Divide();
}
}
BOOL XContour2D::IsValid() const
{
return XContour::IsValid();
}
double XContour2D::GetBaseRadius() const
{
return m_ptWeightCenter.Distance(m_ptBase);
}
double XContour2D::GetBaseAngle() const
{
return ads_angle(m_ptWeightCenter,m_ptBase);
}
//基点与中心点的距离/该方向上的半径
double XContour2D::GetBaseScale() const
{
double dBaseRadius=GetBaseRadius();
double dBaseAngle=GetBaseAngle();
double dRadius=GetRadius(dBaseAngle);
if (fabs(dRadius)>_DIST_SNAP) // ZJQ Modify here
return dBaseRadius/dRadius;
else
return 0;
}
//********************** XContour3D BEGIN *********************//
XContour3D::XContour3D()
{
m_vtNormal = XVector3D(0,0,1);
}
XContour3D::XContour3D(const DList<XPoint>& src,
const XPoint& ptBase,
const XPoint& ptCenter,
const XVector3D& vtNormal)
{
m_vtNormal = vtNormal;
m_ptCenter = ptCenter;
m_ptBase = ptBase;
Init(src);
}
XContour3D::XContour3D(const XContour2D& src,
const XVector3D& vtNormal)
{
m_vtNormal = vtNormal;
m_ptCenter = src.GetWeightCenter();
m_ptBase = src.m_ptBase;
Init(src);
}
XContour3D::XContour3D(const XContour3D& src)
{
m_vtNormal = src.m_vtNormal;
m_ptBase = src.m_ptBase;
m_ptCenter = src.m_ptCenter;
Init(src);
}
XContour3D::~XContour3D()
{
}
XContour3D & XContour3D::operator = (const XContour3D& src)
{
if (Length()>0) Reset();
m_vtNormal = src.m_vtNormal;
m_ptBase = src.m_ptBase;
m_ptCenter = src.m_ptCenter;
Init(src);
return *this;
}
void XContour3D::Init(const DList<XPoint>& src)
{
int nCount = src.Length();
for (int i=0; i<nCount; i++) {
Append(new XPoint(src[i]));
}
}
void XContour3D::
RotateBy(const double dAngle,const XVector3D& vtAxis,const XPoint& ptBase)
{
int nCount = Length();
AcGePoint3d ptTemp;
for (int i=0; i<nCount; i++ ) {
XPoint &ptThis = *(*this)[i];
ptTemp = ptThis;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
ptThis = ptTemp;
}
ptTemp = m_ptBase;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
m_ptBase = ptTemp;
ptTemp = m_ptCenter;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
m_ptCenter = ptTemp;
AcGeVector3d vtTemp = m_vtNormal;
vtTemp.rotateBy(dAngle, vtAxis);
m_vtNormal = vtTemp;
}
void XContour3D::
ScaleBy(const double dFactor,const XPoint& ptBase)
{
int nCount = Length();
AcGePoint3d ptTemp;
for (int i=0; i<nCount; i++ ) {
XPoint &ptThis = *(*this)[i];
ptTemp = ptThis;
ptTemp.scaleBy(dFactor, ptBase);
ptThis = ptTemp;
}
ptTemp = m_ptBase;
ptTemp.scaleBy(dFactor, ptBase);
m_ptBase = ptTemp;
ptTemp = m_ptCenter;
ptTemp.scaleBy(dFactor, ptBase);
m_ptCenter = ptTemp;
}
void XContour3D::RotateTo(const XPoint &ptPath,const XVector3D& vtDir)
{
double dAngle = ads_angle(XPoint(),vtDir);
dAngle = CT_std_angle(dAngle-PI/2);
ads_matrix mat;
ptPath.GetRotationMatrix(dAngle, mat);
TransUCS(mat);
m_ptBase.TransformBy(mat);
m_ptCenter.TransformBy(mat);
}
void XContour3D::
AttachOn(const XPoint& ptOnPlane,const XVector3D& vtPlaneNormal)
{
MoveTo(ptOnPlane);
RotateTo(ptOnPlane,vtPlaneNormal);
AcGeVector3d vtNormal(m_vtNormal);
vtNormal.z *= -1;
XVector3D vtRotateAxis = vtNormal.crossProduct(vtPlaneNormal);
double dRotateAngle = vtNormal.angleTo(vtPlaneNormal, vtRotateAxis);
RotateBy(dRotateAngle, vtRotateAxis, ptOnPlane);
}
void XContour3D::MoveTo(const XPoint& ptDestine)
{
XVector3D vtOff = ptDestine - m_ptBase;
int nCount = Length();
for (int i=0; i<nCount; i++ ) {
XPoint &ptThis = *(*this)[i];
ptThis += vtOff;
}
m_ptBase += vtOff;
m_ptCenter += vtOff;
}
XExtendEnd::XExtendEnd()
{
}
XExtendEnd::XExtendEnd(const XPoly2D& polySrc,
const XPoint& ptBase)
{
Init(polySrc,ptBase);
}
XExtendEnd::XExtendEnd(const XExtendEnd& src)
{
m_ptBase = src.m_ptBase;
m_ptLeft = src.m_ptLeft;
m_ptRight = src.m_ptRight;
}
XExtendEnd::~XExtendEnd()
{
}
void XExtendEnd::Init(const XPoly2D& polySrc,
const XPoint& ptBase)
{
m_ptBase = ptBase;
polySrc.GetExtend(m_ptLeft,m_ptRight);
m_ptLeft.y = m_ptBase.y;
m_ptLeft.z = m_ptBase.z;
m_ptRight.y = m_ptBase.y;
m_ptRight.z = m_ptBase.z;
}
double XExtendEnd::GetDistance() const
{
return m_ptLeft.Distance(m_ptRight);
}
void XExtendEnd::ScaleBy(const double dFactor,
const XPoint& ptBase,
BOOL bBaseScale)
{
AcGePoint3d ptTemp;
ptTemp = m_ptLeft;
ptTemp.scaleBy(dFactor, ptBase);
m_ptLeft = ptTemp;
ptTemp = m_ptRight;
ptTemp.scaleBy(dFactor, ptBase);
m_ptRight = ptTemp;
if(bBaseScale) {
ptTemp = m_ptBase;
ptTemp.scaleBy(dFactor, ptBase);
m_ptBase = ptTemp;
}
}
void XExtendEnd::RotateBy(const double dAngle,
const XVector3D& vtAxis,
const XPoint& ptBase)
{
AcGePoint3d ptTemp;
ptTemp = m_ptBase;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
m_ptBase = ptTemp;
ptTemp = m_ptLeft;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
m_ptLeft = ptTemp;
ptTemp = m_ptRight;
ptTemp.rotateBy(dAngle, vtAxis, ptBase);
m_ptRight = ptTemp;
}
void XExtendEnd::MoveTo(const XPoint& ptDestine)
{
XVector3D vtOff=ptDestine-m_ptBase;
m_ptBase += vtOff;
m_ptLeft += vtOff;
m_ptRight+= vtOff;
}
XPoint XExtendEnd::GetCenter() const
{
XPoint ptCenter;
Midpoint(m_ptRight,m_ptLeft,ptCenter);
return ptCenter;
}
void XExtendEnd::AttachOn(const XPoint& ptOnPath,
const XVector3D& vtPathNormal)
{
MoveTo(ptOnPath);
double dAngle=ads_angle(XPoint(0,0,0),vtPathNormal);
RotateBy(dAngle, AcGeVector3d(0,0,1), ptOnPath);
}
TPolyPath::TPolyPath():
m_bLineDeviation(FALSE)
{
extern double g_nCirDeviation;
m_dDeviation = _AS_SYS_UNIT(TchGeLib::g_nCirDeviation);
}
TPolyPath::TPolyPath(const XPoly2D& polySrc,
BOOL bLineDeviation)
{
extern double g_nCirDeviation;
m_dDeviation = _AS_SYS_UNIT(TchGeLib::g_nCirDeviation);
Init(polySrc,bLineDeviation);
}
TPolyPath::TPolyPath(const XPoly2D& polySrc,
double dDeviation,
BOOL bLineDeviation)
{
extern double g_nCirDeviation;
m_dDeviation = dDeviation;
Init(polySrc,bLineDeviation);
}
TPolyPath::~TPolyPath()
{
}
void TPolyPath::Init(const XPoly2D& polySrc,
BOOL bLineDeviation)
{
extern int GetCirDivNum(double r, double h);
Reset();
m_bLineDeviation = bLineDeviation;
if (polySrc.Length()<=0) return;
Append(new XPoint(polySrc[0]));
int nSegNum = polySrc.TotalSegments();
for(int i = 0; i < nSegNum; i++) {
XDirectionCurve cvSeg;
polySrc.Nth(i, cvSeg);
if(cvSeg.Is(CURVE_LINE)) {
if (m_bLineDeviation) {//直线也分段
double dLineDistance = cvSeg.GetLength();
//直线分段(周长作为半径)
int nDiv = TchExport::GetCirDivNum(dLineDistance,m_dDeviation);
int nStep = AS_INT(nDiv/10);
if (nStep <= 0) nStep++;
double nDistStep = dLineDistance/nStep;
for(int j=0; j<nStep; j++) {
XPointDir2d ptE;
cvSeg.Polar(nDistStep*(j+1), ptE);
Append(new XPoint(ptE));
}
} else {
Append(new XPoint(cvSeg.EndPoint()));
}
} else {
double intAng = cvSeg.GetBulge();
int nDiv = 30;
if(cvSeg.Is(CURVE_ARC))
nDiv = TchExport::GetCirDivNum(cvSeg.GetArc().GetRadius(), m_dDeviation);
int nStep = AS_INT(fabs(intAng)/PI/2.0*nDiv);// how many sections
double nDistStep = cvSeg.GetLength()/nStep;
for(int j=0; j<nStep; j++) {
XPointDir2d ptE;
cvSeg.Polar(nDistStep*(j+1), ptE);
Append(new XPoint(ptE));
}
}
}
}
// Distance from the 1st vertex.
double TPolyPath::GetDistAtVertex(int index) const
{
double dDistance = 0;
if (0<=index && index<Length()) {
for ( int i=1; i<=index; i++ ) {
XPoint ptThis = (*this)[i-1];
XPoint ptNext = (*this)[i];
dDistance += ptThis.Distance(ptNext);
}
}
return dDistance;
}
/////////////////////////////////////////////////////////////////////////////////
XTriangleWeiCen::~XTriangleWeiCen()
{
}
XPoint XTriangleWeiCen::WeightCenter()
{
XPoint ptWeightCenter;
ptWeightCenter.x = (vertex1.x + vertex2.x + vertex3.x)/3;
ptWeightCenter.y = (vertex1.y + vertex2.y + vertex3.y)/3;
ptWeightCenter.z = (vertex1.z + vertex2.z + vertex3.z)/3;
return ptWeightCenter;
}
double XTriangleWeiCen::Area()
{
AcGeVector3d vtA = vertex1.AsAcGeVector3d();
AcGeVector3d vtB = vertex2.AsAcGeVector3d();
AcGeVector3d vtC = vertex3.AsAcGeVector3d();
AcGeVector3d vtAB = vtB - vtA;
AcGeVector3d vtAC = vtC - vtA;
AcGeVector3d vtCrossProduct = vtAB.crossProduct(vtAC);
AcGeVector3d vtZAxis(0,0,1);
double dArea = 0.5*vtCrossProduct.length();
if ( vtCrossProduct.angleTo(vtZAxis) >= PI )
dArea *= -1;
return dArea;
}
// 取得重心
XPoint GetWeightCenter(const XPoly2D& poly)
{
extern int GetCirDivNum(double r, double h);
extern double g_nCirDeviation;
if (poly.Length()<=0) return XPoint(0,0,0);
XPoint ptWeightCenter;
//顶点链表
DList<XPoint> lstVertex;
int nSegNum = poly.TotalSegments();
for(int k = 0; k < nSegNum; k++) {
XDirectionCurve cvSeg;
poly.Nth(k, cvSeg);
if(cvSeg.Is(CURVE_LINE)) {
lstVertex.Append(new XPoint(cvSeg.StartPoint()));
} else {
double intAng = cvSeg.GetBulge();
int nDiv = 30;
if(cvSeg.Is(CURVE_ARC))
nDiv = TchExport::GetCirDivNum(cvSeg.GetArc().GetRadius(), _AS_SYS_UNIT(TchGeLib::g_nCirDeviation));
int nStep = AS_INT(fabs(intAng)/PI/2.0*nDiv);// how many sections
double nDistStep = cvSeg.GetLength()/nStep;
for(int j=0; j<nStep; j++) {
XPointDir2d ptE;
cvSeg.Polar(nDistStep*j, ptE);
lstVertex.Append(new XPoint(ptE));
}
}
}
//转换为三角形,计算三角形重心
int nStep = lstVertex.Length()-1;
if (nStep < 0) {
return XPoint(0,0,0);
}
else if (nStep == 0) {
ptWeightCenter = *lstVertex[0];
}
else {
double dSigemaMiXi=0, dSigemaMiYi=0, dSigemaMi=0;
for (int n=1; n<nStep; n++ ) {
XPoint pt1=*lstVertex[0];
XPoint pt2=*lstVertex[n];
XPoint pt3=*lstVertex[n+1];
//adsout << "\nTriangle=" << pt1 << pt2 << pt3;
XTriangleWeiCen triangleUnit(pt1,
pt2,pt3);
XPoint ptWi= triangleUnit.WeightCenter();
//adsout << "\nptWi=" << ptWi;
double dMi = triangleUnit.Area();
dSigemaMiXi = dSigemaMiXi + dMi*ptWi.x;
dSigemaMiYi = dSigemaMiYi + dMi*ptWi.y;
dSigemaMi = dSigemaMi + dMi;
}
if ( fabs(dSigemaMi)>1.0E-9 ) {
ptWeightCenter = XPoint(dSigemaMiXi/dSigemaMi,
dSigemaMiYi/dSigemaMi,(*lstVertex[0]).z);
} else {
ptWeightCenter = XPoint(0,0,0);
}
}
return ptWeightCenter;
}
// 取得周线顶点数(同分弧精度 g_nCirDeviation 相联系,有待修改)
int GetContourDivNum(double dPerimeter)
{
extern double g_nCirDeviation;
extern int GetCirDivNum(double r, double h);
//周长作为半径
int nDiv = TchExport::GetCirDivNum(dPerimeter/PI/2.0,_AS_SYS_UNIT(TchGeLib::g_nCirDeviation));
if (nDiv < 3) nDiv = 3;
return nDiv;
}