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

601 lines
21 KiB
C++

#include "stdafx.h"
// extern GEOAPI XPface * ConstructPolyFace(const AcDbVoidPtrArray &entSet);
// 已经坐标变换到polyClip平面上
BOOL PolyClip3D(XPolygonEx &polySrc, const XPoly2D &polyClip, DList<XPolygonEx> &inSet,
DList<XPolygonEx> &outSet)
{
ASSERT(polySrc.Length()>=3);
XVector3D vtNorm;
if (polySrc.GetNormal(vtNorm)!=RTNORM)
return FALSE;
((AcGeVector3d &)vtNorm).normalize();
double nVal=(vtNorm&XVector3D(0,0,1));
BOOL bVert=(fabs(nVal)<1.0E-6);
BOOL nRet=TRUE;
if (bVert) {
/*
int nEdgeNum=0, nInNum=0, nOutNum=0;
double nElev=polyClip[0].z;
for(int i=0; i<polySrc.Length(); i++) {
XPoint ptVert=*polySrc[i];
ptVert.z = nElev;
int nFlag=(ptVert&polyClip);
if (nFlag==PR_INSIDE)
nInNum++;
else if (nFlag==PR_OUTSIDE)
nOutNum++;
else
nEdgeNum++;
}
if (nInNum==0 && nOutNum>0)
outSet.Append(new XPolygonEx(polySrc));
else if (nOutNum==0 && nInNum>0)
inSet.Append(new XPolygonEx(polySrc));
else */
nRet=FALSE; //求解过程比较复杂,暂时放弃
} else {
AcGePlane srcPlane(*polySrc[0], vtNorm);
AcGePlane tarPlane((AcGePoint3d &)*polyClip[0], AcGeVector3d(0,0,1));
ASSERT(fabs(polyClip[0].z)<_DIST_SNAP);
// 被裁剪面投影到裁剪区域平面内,并设置z=0
XPoly2D poly2d(1);
for(int i=0; i<polySrc.Length(); i++) {
XPoint ptVert=*polySrc[i];
//投影产生poly2d
XPoint ptPrj=((AcGePoint3d &)ptVert).orthoProject(tarPlane);
ptPrj.z=0;
poly2d.AppendNode(ptPrj);
}
// 内、外部的区域
DList<XPoly2D> lstInSide, lstOutSide;
TchSubExport::Intersect(poly2d, polyClip, lstInSide);
TchSubExport::Subtract(poly2d, polyClip, lstOutSide);
for(int m=0; m<2; m++) {
DList<XPoly2D> &lstRegion=m? lstOutSide : lstInSide;
DList<XPolygonEx> &lstSet=m? outSet : inSet;
for(int k=0; k<lstRegion.Length(); k++) {
XPoly2D &polyReg=*lstRegion[k];
if (polyReg.PathArea()>1.0E-6)
polyReg.Reverse();
XPolygonEx *pNewReg=new XPolygonEx;
for(int i=0; i<polyReg.Length(); i++) {
XCurveSegment seg;
polyReg.Nth(i, seg);
XPoint ptMid=seg.MidPoint();
int nHitFlag=poly2d.HitTestOnCurve(ptMid);
BOOL bVis=(abs(nHitFlag)>0? polySrc.IsVisible(abs(nHitFlag)-1) : TRUE);
XPoint ptNew=((AcGePoint3d &)seg.StartPoint()).project(srcPlane, AcGeVector3d(0,0,1));
pNewReg->AppendNode(ptNew, bVis);
}
lstSet.Append(pNewReg);
}
}
}
return nRet;
}
// 坐标变换不正确,应当使用投影的方法
BOOL PolyClip3DFace(const AcDbPolyline &plane, const AcDbFace &face,
AcDbVoidPtrArray &inSet, AcDbVoidPtrArray &outSet)
{
//extern GEOAPI void Trianglize(const XPolygonEx &poly2d, DList<AcDbFace> &lstFace);
AcGePoint3d ptArray[4];
Adesk::Boolean visArray[4];
for(int i=0; i<4; i++) {
VERIFY(face.getVertexAt(i, ptArray[i])==Acad::eOk);
VERIFY(face.isEdgeVisibleAt(i, visArray[i])==Acad::eOk);
}
BOOL bTri=FALSE;
for(i=0; i<4; i++) {
int j=i+1;
if (j==4) j=0;
if (ptArray[i].distanceTo(ptArray[j])<_DIST_SNAP) {
switch(j) {
case 1: //消除第1顶点
ptArray[1]=ptArray[2];
ptArray[2]=ptArray[3];
visArray[0]=visArray[1];
visArray[1]=visArray[2];
visArray[2]=visArray[3];
break;
case 2: //消除第2顶点
ptArray[2]=ptArray[3];
visArray[1]=visArray[2];
visArray[2]=visArray[3];
break;
case 3: //消除第3顶点
visArray[2]=visArray[3];
break;
}
bTri=TRUE;
break;
}
}
XPoly2D polyClip;
PolyConvert(plane, polyClip);
XVector3D vtNormal;
(AcGeVector3d &)vtNormal=plane.normal();
polyClip.SetElevation(0.0);
int nLen=(bTri? 3 : 4);
XPolygonEx polySrc;
for(i=0; i<nLen; i++) {
XPoint pt;
pt=ptArray[i];
pt=Wcs2Ecs(pt, vtNormal);
polySrc.AppendNode(pt, visArray[i]);
}
DList<XPolygonEx> frontSet, backSet;
BOOL bRet=PolyClip3D(polySrc, polyClip, frontSet, backSet);
if (!bRet)
return bRet;
for(int m=0; m<2; m++) {
DList<XPolygonEx> &lstSet=m? backSet : frontSet;
int nCount=lstSet.Length();
for(int n=0; n<nCount; n++) {
XPolygonEx *pRegion=lstSet[n];
/*
for(int k=0; k<pRegion->Length(); k++) {
*(*pRegion)[k]=Ecs2Wcs(*(*pRegion)[k], vtNormal);
}
DList<AcDbFace> lstFaces(0);
Trianglize(*pRegion, lstFaces);
for(k=0; k<lstFaces.Length(); k++) {
AcDbFace *pFace=lstFaces[k];
pFace->setPropertiesFrom(&face);
if (m==0)
inSet.append(pFace);
else
outSet.append(pFace);
}
*/
DList<XTriangle> lstTris;
double nElev=(*pRegion)[0]->z;
pRegion->SetElevation(0.0);
if (pRegion->Trianglize(lstTris, TRUE)==RTNORM) {
for(int k=0; k<lstTris.Length(); k++) {
XTriangle *triangle=lstTris[k];
Adesk::Boolean bSide1=!(triangle->m_nFlag&SIDE1_INVISIBLE);
Adesk::Boolean bSide2=!(triangle->m_nFlag&SIDE2_INVISIBLE);
Adesk::Boolean bSide3=!(triangle->m_nFlag&SIDE3_INVISIBLE);
triangle->vertex1.z=triangle->vertex2.z=triangle->vertex3.z=nElev;
XPoint pt1=Ecs2Wcs(triangle->vertex1, vtNormal);
XPoint pt2=Ecs2Wcs(triangle->vertex2, vtNormal);
XPoint pt3=Ecs2Wcs(triangle->vertex3, vtNormal);
AcDbFace *pFace=new AcDbFace(pt1, pt2, pt3, pt1,
bSide1, bSide2, bSide3);
pFace->setPropertiesFrom(&face);
if (m==0)
inSet.append(pFace);
else
outSet.append(pFace);
}
}
}
}
return TRUE;
}
// 3DFace的裁剪
BOOL Clip3DFace(const AcGePlane &plane, const AcGePoint3d *ptArray,
const Adesk::Boolean *visArray, BOOL bTri,
AcDbVoidPtrArray &frontSet, AcDbVoidPtrArray &backSet)
{
AcGeVector3d vtNormal=plane.normal();
XPoint *ptArray1=(XPoint *)ptArray;
XVector3D vtNorm;
CT_vector_plan3p(ptArray1[0], ptArray1[1], ptArray1[2], vtNorm);
AcGePlane plan1(ptArray[0], vtNorm);
AcGeLine3d line;
if (!plane.intersectWith(plan1, line)) {
return FALSE;
}
// 用交线和3DFACE的边求交。
int nVertice=(bTri? 3 : 4);
int nIntFlag1=0, nIntFlag2=0; // 在顶点则为负(-idx-1),在边则为正(idx+1)
AcGePoint3d ptInt1, ptInt2;
for(int i=0; i<nVertice; i++) {
int iNext=i+1;
if (iNext==nVertice)
iNext=0;
AcGeLineSeg3d lnEdge(ptArray[i], ptArray[iNext]);
AcGePoint3d ptInt;
if (line.intersectWith(lnEdge, ptInt)) {
if (ptInt==ptArray[iNext]) {
if (nIntFlag1) {
nIntFlag2=-iNext-1;
ptInt2=ptInt;
break;
} else {
nIntFlag1=-iNext-1;
ptInt1=ptInt;
}
} else if (ptInt==ptArray[i]) {
if (i==0) {
nIntFlag1=-1;
ptInt1=ptInt;
}
} else {
if (nIntFlag1) {
nIntFlag2=i+1;
ptInt2=ptInt;
break;
} else {
nIntFlag1=i+1;
ptInt1=ptInt;
}
}
}
}
XPolygonEx poly1, poly2;
if (nIntFlag1 && nIntFlag2 && ptInt1!=ptInt2) {
// nFlag1~nFlag2, poly1
for(int n=abs(nIntFlag1)-1; n<=abs(nIntFlag2)-1; n++) {
if (n==abs(nIntFlag1)-1)
poly1.AppendNode(ptInt1, visArray[n]);
else if (n==abs(nIntFlag2)-1 && nIntFlag2<0)
poly1.AppendNode(ptInt2, TRUE); //裁剪边可见
else
poly1.AppendNode(ptArray[n], visArray[n]);
}
if (nIntFlag2>0)
poly1.AppendNode(ptInt2, TRUE);
// nFlag2~nFlag1, poly2
for(n=abs(nIntFlag2)-1; n<=abs(nIntFlag1)-1+nVertice; n++) {
if (n==abs(nIntFlag2)-1)
poly2.AppendNode(ptInt2, visArray[DePeriod(nVertice, n)]);
else if (n==abs(nIntFlag1)-1+nVertice && nIntFlag2<0)
poly2.AppendNode(ptInt1, TRUE);
else
poly2.AppendNode(ptArray[DePeriod(nVertice,n)],
visArray[DePeriod(nVertice,n)]);
}
if (nIntFlag1>0)
poly2.AppendNode(ptInt1, TRUE);
} else {
return FALSE;
}
XPoint ptMid;
Midpoint(ptInt1, ptInt2, ptMid);
for(int nSide=0; nSide<2; nSide++) {
XPolygonEx &poly2d=(nSide? poly2 : poly1);
if (poly2d.Length()>=3) {
XPoint ptCen1;
poly2d.Center(ptCen1);
XVector3D vt1=ptCen1-ptMid;
XVector3D vt2;
(AcGeVector3d &)vt2=vtNormal;
double nVal=(vt1&vt2);
BOOL bFrontSet=(nVal>0.0);
if (poly2d.Length()>=5) {
DList<XTriangle> lstTris;
if (poly2d.Trianglize(lstTris, TRUE)==RTNORM) {
for(int n=0; n<lstTris.Length(); n++) {
XTriangle *triangle=lstTris[n];
Adesk::Boolean bSide1=!(triangle->m_nFlag&SIDE1_INVISIBLE);
Adesk::Boolean bSide2=!(triangle->m_nFlag&SIDE2_INVISIBLE);
Adesk::Boolean bSide3=!(triangle->m_nFlag&SIDE3_INVISIBLE);
AcDbFace *pFace=new AcDbFace(triangle->vertex1, triangle->vertex2,
triangle->vertex3, triangle->vertex1, bSide1, bSide2, bSide3);
if (bFrontSet)
frontSet.append(pFace);
else
backSet.append(pFace);
}
}
} else {
AcDbFace *pFace=NULL;
if (poly2d.Length()==3) {
pFace=new AcDbFace(*poly2d[0], *poly2d[1], *poly2d[2],
*poly2d[0], poly2d.IsVisible(0),
poly2d.IsVisible(1), poly2d.IsVisible(2));
} else {
pFace=new AcDbFace(*poly2d[0], *poly2d[1], *poly2d[2], *poly2d[3],
poly2d.IsVisible(0), poly2d.IsVisible(1),
poly2d.IsVisible(2), poly2d.IsVisible(3));
}
if (bFrontSet)
frontSet.append(pFace);
else
backSet.append(pFace);
}
}
}
return TRUE;
}
// 用面裁剪3dface
BOOL Clip3DFace(const AcGePlane &plane, const AcDbFace &face,
AcDbVoidPtrArray &frontSet, AcDbVoidPtrArray &backSet)
{
XPlane planeMe;
// [2010-3-16 9:34 wubo] 移植到新Geo库
// plane.getCoefficients(planeMe.a, planeMe.b, planeMe.c, planeMe.d);
double dParaA = planeMe.GetParaA();
double dParaB = planeMe.GetParaB();
double dParaC = planeMe.GetParaC();
double dParaD = planeMe.GetParaD();
plane.getCoefficients(dParaA, dParaB, dParaC, dParaD);
planeMe.SetParaA(dParaA);
planeMe.SetParaB(dParaB);
planeMe.SetParaC(dParaC);
planeMe.SetParaD(dParaD);
X3DFace faceMe(face);
DList<X3DFace> upFaces, downFaces;
BOOL bOk=faceMe.SectByPlane(planeMe, upFaces, downFaces);
for(int kk=0; kk<upFaces.Length(); kk++) {
frontSet.append(upFaces[kk]->AsDbFace());
}
for(kk=0; kk<downFaces.Length(); kk++) {
backSet.append(downFaces[kk]->AsDbFace());
}
return bOk;
AcGePoint3d ptArray[4];
Adesk::Boolean visArray[4];
for(int i=0; i<4; i++) {
VERIFY(face.getVertexAt(i, ptArray[i])==Acad::eOk);
VERIFY(face.isEdgeVisibleAt(i, visArray[i])==Acad::eOk);
}
BOOL bTri=FALSE;
for(i=0; i<4; i++) {
int j=i+1;
if (j==4) j=0;
if (ptArray[i].distanceTo(ptArray[j])<_DIST_SNAP) {
switch(j) {
case 1: //消除第1顶点
ptArray[1]=ptArray[2];
ptArray[2]=ptArray[3];
visArray[0]=visArray[1];
visArray[1]=visArray[2];
visArray[2]=visArray[3];
break;
case 2: //消除第2顶点
ptArray[2]=ptArray[3];
visArray[1]=visArray[2];
visArray[2]=visArray[3];
break;
case 3: //消除第3顶点
visArray[2]=visArray[3];
break;
}
bTri=TRUE;
break;
}
}
if (bTri) {
if ((XPoint(ptArray[2])&XLine(XPoint(ptArray[0]), XPoint(ptArray[1])))!=PR_OUTSIDE)
return FALSE; //共线
}
BOOL bRet=Clip3DFace(plane, ptArray, visArray, bTri, frontSet, backSet);
if (!bRet) {
XPoint ptCen;
ptCen.x=(ptArray[0].x+ptArray[1].x+ptArray[2].x)/3.0;
ptCen.y=(ptArray[0].y+ptArray[1].y+ptArray[2].y)/3.0;
ptCen.z=(ptArray[0].z+ptArray[1].z+ptArray[2].z)/3.0;
// 平行平面
XPoint pt=ptArray[0].orthoProject(plane);
XVector3D vt1=ptCen-pt;
XVector3D vt2;
AcGeVector3d vtNormal=plane.normal();
(AcGeVector3d &)vt2=vtNormal;
double nVal=(vt1&vt2);
BOOL bFrontSet=(nVal>0.0);
AcDbFace *pFace=(AcDbFace *)face.clone();
if (bFrontSet)
frontSet.append(pFace);
else
backSet.append(pFace);
bRet = TRUE;
}
int nCount=frontSet.length();
for(int n=0; n<nCount; n++) {
AcDbEntity *pEnt=(AcDbEntity *)frontSet[n];
pEnt->setPropertiesFrom(&face);
}
nCount=backSet.length();
for(n=0; n<nCount; n++) {
AcDbEntity *pEnt=(AcDbEntity *)backSet[n];
pEnt->setPropertiesFrom(&face);
}
return bRet;
}
// Command: 平面切割
void Clip3D()
{
PickSet ss(SS_FREE);
RBList mask=ads_buildlist(RTDXF0, _T("3DSOLID,REGION,3DBODY,3DFACE,POLYLINE,LINE,ARC,CIRCLE"), NULL);
if (SelectEntities(_T("\n选择待切割的三维对象:"), ss, mask)!=RTNORM)
return;
XPoint pt1, pt2;
int nRetCode;
//INITGET_BEG(0, _T("P"));
nRetCode=ads_getpoint(NULL, _T("\n切割线第一点<退出>:"), pt1);
//INITGET_END();
if (nRetCode!=RTNORM && nRetCode!=RTKWORD)
return;
AcDbPolyline *pClip=NULL;
AcGePlane plane;
if (nRetCode==RTKWORD) {
RBList mask(RTDXF0, _T("LWPOLYLINE"), 70, 1, NULL);
Entity entPoly;
if (entPoly.FilterSelect(_T("\n选择作为裁剪边界的封闭多段线<退出>:"), mask)!=RTNORM)
return;
OPENOBJ_BEGIN(entPoly, AcDb::kForRead, AcDbPolyline, pLine);
ASSERT(pLine);
pClip=(AcDbPolyline*)pLine->clone();
OPENOBJ_END();
} else {
if (XGetPoint(pt1, _T("\n切割线第二点"), pt2)!=RTNORM)
return;
XVector3D vt1=pt2-pt1;
vt1=Ucs2Wcs(vt1, TRUE);
XVector3D vt0(0,0,1);
vt0=Ucs2Wcs(vt0, TRUE);
XVector3D vt2=vt0*vt1;
plane=AcGePlane((const AcGePoint3d &)Ucs2Wcs(pt1), (const AcGeVector3d &)vt2);
}
long lCount=ss.Length();
for(long i=0; i<lCount; i++) {
Entity ent=ss[i];
AcDbVoidPtrArray frontSet, backSet;
OPENOBJ_BEGIN(ent, AcDb::kForRead, AcDbEntity, pEnt);
ASSERT(pEnt);
TMasterProperties prop;
prop.SetFrom(pEnt);
AcDbVoidPtrArray entSet0;
if (pEnt->isA()==AcDbFace::desc()) {
if (pClip)
PolyClip3DFace(*pClip, *(AcDbFace *)pEnt, frontSet, backSet);
else
Clip3DFace(plane, *(AcDbFace *)pEnt, frontSet, backSet);
} else if (pEnt->isKindOf(AcDbCurve::desc())) {
double nThickness=0.0;
if (pEnt->isA()==AcDbLine::desc())
nThickness=((AcDbLine *)pEnt)->thickness();
else if (pEnt->isA()==AcDbArc::desc())
nThickness=((AcDbArc *)pEnt)->thickness();
else if (pEnt->isA()==AcDbCircle::desc())
nThickness=((AcDbCircle *)pEnt)->thickness();
else if (pEnt->isA()==AcDbPolyline::desc())
nThickness=((AcDbPolyline *)pEnt)->thickness();
else if (pEnt->isA()==AcDb2dPolyline::desc())
nThickness=((AcDb2dPolyline *)pEnt)->thickness();
if (nThickness>_DIST_SNAP) {
AcDbVoidPtrArray entSet;
InitModel(prop, pEnt, NULL, entSet);
int num=entSet.length();
for(int n=0; n<num; n++) {
AcDbEntity *pFace=(AcDbEntity *)entSet[n];
if (pFace->isA()==AcDbFace::desc()) {
if (pClip) {
if (!PolyClip3DFace(*pClip, *(AcDbFace *)pFace, frontSet, backSet)) {
entSet0.append(pFace->clone());
}
} else
Clip3DFace(plane, *(AcDbFace *)pFace, frontSet, backSet);
}
}
ReleaseEntSet(entSet);
}
} else {
AcDbVoidPtrArray entSet;
InitModel(prop, pEnt, NULL, entSet);
int num=entSet.length();
for(int n=0; n<num; n++) {
AcDbEntity *pFace=(AcDbEntity *)entSet[n];
if (pFace->isA()==AcDbFace::desc()) {
if (pClip) {
if (!PolyClip3DFace(*pClip, *(AcDbFace *)pFace, frontSet, backSet)) {
entSet0.append(pFace->clone());
}
} else
Clip3DFace(plane, *(AcDbFace *)pFace, frontSet, backSet);
}
}
ReleaseEntSet(entSet);
}
if (frontSet.length()>0 || backSet.length()>0) {
if (pEnt->upgradeOpen()==Acad::eOk) {
pEnt->erase();
pEnt->downgradeOpen();
// 不能裁剪的变成单独的PFACE/3DFACE
for(int nn=0; nn<3; nn++) {
AcDbVoidPtrArray *pEntSet=NULL;
if (nn==0)
pEntSet=&entSet0;
else if (nn==1)
pEntSet=&frontSet;
else
pEntSet=&backSet;
AcDbVoidPtrArray &eSet=*pEntSet;
int num=eSet.length();
if (num>1) {
XPface *pFace=ConstructPolyFace(eSet);
if (pFace) {
pFace->Make();
Entity entLast;
entLast.GetLast();
OPENOBJ_BEGIN(entLast, AcDb::kForWrite, AcDbEntity, pLast);
if (pLast)
pLast->setPropertiesFrom(pEnt);
OPENOBJ_END();
delete pFace;
}
ReleaseEntSet(eSet);
} else if (num==1){
AcDbEntity *pFace=(AcDbFace *)eSet[0];
pFace->setPropertiesFrom(pEnt);
AddToCurrentSpace(pFace, Adesk::kTrue);
}
}
} else {
ReleaseEntSet(frontSet);
ReleaseEntSet(backSet);
ReleaseEntSet(entSet0);
}
} else {
ReleaseEntSet(frontSet);
ReleaseEntSet(backSet);
ReleaseEntSet(entSet0);
}
OPENOBJ_END();
}
if (pClip)
delete pClip;
}
// Command: 区域封面
void Poly2Face()
{
Entity entPoly;
if (SelectEntity(_T("\n选择封闭的多段线<退出>: "), entPoly,
RBList(RTDXF0, _T("POLYLINE,LWPOLYLINE"), 70, 1, NULL))==RTNORM) {
XPoly2D poly2d(entPoly);
XPoly poly1;
poly2d.MapToPolygon1(poly1, _AS_SYS_UNIT(g_nCirDeviation));
XPolygonEx polyEx(poly1);
XTrianglePface lstTris;
if (polyEx.Trianglize(lstTris, TRUE)==RTNORM) {
lstTris.MakePolyface();
adsout << _T("\n成功的转成面!");
}
}
}