From d7ec1fd30449e15b0d06d762f47a1e97ce1c282f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 18 Sep 2023 10:21:49 +0200 Subject: [PATCH 01/31] =?UTF-8?q?EgtGeomKernel=20:=20-=20aggiunta=20delle?= =?UTF-8?q?=20coordinate=20U=20e=20V=20ai=20vertici=20delle=20TriMesh.=20M?= =?UTF-8?q?anca=20da=20modificare=20:=20-=20funzione=20MoveVertex=20-=20su?= =?UTF-8?q?rfBezier.cpp=20quando=20verr=C3=A0=20aggiunto=20il=20ramo=20Tri?= =?UTF-8?q?m&Mesh.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- StmFromTriangleSoup.cpp | 4 ++-- SurfTriMesh.cpp | 46 +++++++++++++++++++++++++++++++++++++++-- SurfTriMesh.h | 15 ++++++++++---- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/StmFromTriangleSoup.cpp b/StmFromTriangleSoup.cpp index 08db0c7..8c55a74 100644 --- a/StmFromTriangleSoup.cpp +++ b/StmFromTriangleSoup.cpp @@ -99,14 +99,14 @@ StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, cons //---------------------------------------------------------------------------- int -StmFromTriangleSoup::AddVertex( const Point3d& ptP) +StmFromTriangleSoup::AddVertex( const Point3d& ptP, const double dU, const double dV) { // verifico se già presente int nId ; if ( m_VertGrid.Find( ptP, 2 * EPS_SMALL, nId)) return nId ; // aggiungo il vertice - if ( ( nId = m_pSTM->AddVertex( ptP)) == SVT_NULL) + if ( ( nId = m_pSTM->AddVertex( ptP, dU, dV)) == SVT_NULL) return SVT_NULL ; m_VertGrid.InsertPoint( ptP, nId) ; return nId ; diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 76ad9e9..d171748 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -107,7 +107,7 @@ SurfTriMesh::Clear( void) //---------------------------------------------------------------------------- int -SurfTriMesh::AddVertex( const Point3d& ptVert) +SurfTriMesh::AddVertex( const Point3d& ptVert, const double dU, const double dV) { // imposto ricalcolo m_nStatus = TO_VERIFY ; @@ -118,7 +118,11 @@ SurfTriMesh::AddVertex( const Point3d& ptVert) try { m_vVert.emplace_back( ptVert) ;} catch(...) { return SVT_NULL ;} // ne determino l'indice - return int( m_vVert.size() - 1) ; + int nId = int( m_vVert.size() - 1) ; + // aggiugo le coordinate corrispondenti allo spazio parametrico + m_vVert[nId].dU = dU ; + m_vVert[nId].dV = dV ; + return nId ; } //---------------------------------------------------------------------------- @@ -475,6 +479,19 @@ SurfTriMesh::GetVertex( int nId, Point3d& ptP) const return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetVertexParam( int nId, double& dU, double& dV) const +{ + // verifico esistenza del vertice + if ( nId < 0 || nId >= GetVertexSize() || m_vVert[nId].nIdTria == SVT_DEL) + return false ; + // recupero i dati + dU = m_vVert[nId].dU ; + dV = m_vVert[nId].dV ; + return true ; +} + //---------------------------------------------------------------------------- int SurfTriMesh::GetFirstVertex( Point3d& ptP) const @@ -482,6 +499,13 @@ SurfTriMesh::GetFirstVertex( Point3d& ptP) const return GetNextVertex( SVT_NULL, ptP) ; } +//---------------------------------------------------------------------------- +int +SurfTriMesh::GetFirstVertexParam( int nId, double& dU, double& dV) const +{ + return GetNextVertexParam( SVT_NULL, dU, dV) ; +} + //---------------------------------------------------------------------------- int SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const @@ -499,6 +523,24 @@ SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const return nId ; } +//---------------------------------------------------------------------------- +int +SurfTriMesh::GetNextVertexParam( int nId, double& dU, double& dV) const +{ + // cerco il primo successivo valido + do { + nId ++ ; + } while ( nId < GetVertexSize() && m_vVert[nId].nIdTria == SVT_DEL) ; + // se oltrepassata fine + if ( nId >= GetVertexSize()) + return SVT_NULL ; + // recupero i dati + dU = m_vVert[nId].dU ; + dV = m_vVert[nId].dV ; + // ritorno indice triangolo corrente + return nId ; +} + //---------------------------------------------------------------------------- bool SurfTriMesh::GetTriangle( int nId, int nIdVert[3]) const diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 6ae2946..9f8c8d1 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -28,11 +28,15 @@ class SurfFlatRegion ; class StmVert { public : - StmVert( void) : ptP(), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {} - StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0) {} - StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF), nTemp( 0) {} + StmVert( void) : ptP(), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0), dU( -1), dV( -1) {} + StmVert( const Point3d& ptQ) : ptP( ptQ), nIdTria( SVT_NULL), nFlag( 0), nTemp( 0), dU( -1), dV( -1) {} + StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF), nTemp( 0), dU( -1), dV( -1) {} public : Point3d ptP ; + double dU ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x nSpanV) + // della sup di Bezier // -1 se non definito + double dV ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x nSpanV) + // della sup di Bezier // -1 se non definito int nIdTria ; int nFlag ; mutable int nTemp ; @@ -215,7 +219,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW { m_dSmoothAng = std::max( dSmoothAngDeg, EPS_ANG_SMALL) ; m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; m_OGrMgr.Reset() ; } - int AddVertex( const Point3d& ptVert) override ; + int AddVertex( const Point3d& ptVert, const double dU = -1 , const double dV = -1) override ; bool MoveVertex( int nInd, const Point3d& ptNewVert) override ; int AddTriangle( const int nIdVert[3], int nTFlag = 0) override ; bool RemoveTriangle( int nId) override ; @@ -244,8 +248,11 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW double GetSmoothAngle( void) const override { return m_dSmoothAng ; } bool GetVertex( int nId, Point3d& ptP) const override ; + bool GetVertexParam( int nId, double& dU, double& dV) const override ; int GetFirstVertex( Point3d& ptP) const override ; + int GetFirstVertexParam( int nId, double& dU, double& dV) const override ; int GetNextVertex( int nId, Point3d& ptP) const override ; + int GetNextVertexParam( int nId, double& dU, double& dV) const override ; bool GetTriangle( int nId, int nIdVert[3]) const override ; int GetFirstTriangle( int nIdVert[3]) const override ; int GetNextTriangle( int nId, int nIdVert[3]) const override ; From a3531c484127b5b76172d219cecfc30325f358d5 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 18 Sep 2023 10:33:50 +0200 Subject: [PATCH 02/31] EgtGeomKernel : - correzione su coordinate U e V ai vertici delle TriMesh. --- StmFromTriangleSoup.cpp | 9 +++++---- SurfTriMesh.h | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/StmFromTriangleSoup.cpp b/StmFromTriangleSoup.cpp index 8c55a74..87bae4e 100644 --- a/StmFromTriangleSoup.cpp +++ b/StmFromTriangleSoup.cpp @@ -76,18 +76,19 @@ StmFromTriangleSoup::AddTriangle( const Triangle3d& Tria) //---------------------------------------------------------------------------- bool -StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2) +StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2, + const double dU0, const double dV0,const double dU1, const double dV1,const double dU2, const double dV2) { // verifico inizializzazione if ( m_pSTM == nullptr) return false ; // ciclo sui tre vertici int nIdV[3] ; - if ( ( nIdV[0] = AddVertex( ptP0)) == SVT_NULL) + if ( ( nIdV[0] = AddVertex( ptP0, dU0, dV0)) == SVT_NULL) return false ; - if ( ( nIdV[1] = AddVertex( ptP1)) == SVT_NULL) + if ( ( nIdV[1] = AddVertex( ptP1, dU1, dV1)) == SVT_NULL) return false ; - if ( ( nIdV[2] = AddVertex( ptP2)) == SVT_NULL) + if ( ( nIdV[2] = AddVertex( ptP2, dU2, dV2)) == SVT_NULL) return false ; // se i vertici sono tutti diversi tra loro, inserisco il triangolo if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) { diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 9f8c8d1..69b8a8a 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -33,9 +33,9 @@ class StmVert StmVert( const Point3d& ptQ, int nIdT, int nF) : ptP( ptQ), nIdTria( nIdT), nFlag( nF), nTemp( 0), dU( -1), dV( -1) {} public : Point3d ptP ; - double dU ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x nSpanV) + double dU ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x 1000) ( nSpanV x 1000) // della sup di Bezier // -1 se non definito - double dV ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x nSpanV) + double dV ; // parametro riferito alle coordinate del punto nello spazio parametrico ( nSpanU x 1000) ( nSpanV x 1000) // della sup di Bezier // -1 se non definito int nIdTria ; int nFlag ; From b4058ad363290a6f2f25804bfc7b2c4990fc5203 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 8 Feb 2024 09:28:49 +0100 Subject: [PATCH 03/31] EgtGeomKernel : - aggiunta delle intersezioni tra linee e SupBez. --- EgtGeomKernel.vcxproj | 2 + IntersLineSurfBez.cpp | 108 ++++++++++++++++++++++++++++++++++++++++++ IntersLineSurfBez.h | 1 + SurfTriMesh.h | 2 - 4 files changed, 111 insertions(+), 2 deletions(-) create mode 100644 IntersLineSurfBez.cpp create mode 100644 IntersLineSurfBez.h diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 8c884bb..ebcb8d6 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -309,6 +309,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -449,6 +450,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp new file mode 100644 index 0000000..080d110 --- /dev/null +++ b/IntersLineSurfBez.cpp @@ -0,0 +1,108 @@ +//---------------------------------------------------------------------------- +// EgalTech 2024 +//---------------------------------------------------------------------------- +// File : IntersLineSurfBez.cpp Data : 06.02.24 Versione : 2.6b1 +// Contenuto : Implementazione della intersezione linea/superficie bezier. +// +// +// +// Modifiche : 06.02.24 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineBox.h" +#include "/EgtDev/Include/EGkIntersLineTria.h" +#include "/EgtDev/Include/EGkIntersLineSurfTm.h" +#include "/EgtDev/Include/EGkIntersLineSurfBez.h" +#include "/EgtDev/Include/EGkSurfBezier.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +// Intersezione di una linea con una superficie TriMesh +//---------------------------------------------------------------------------- +bool +IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier& SBz, + ILSBIVECTOR& vInfo, bool bFinite) +{ + // verifico linea + Vector3d vtDir = vtL ; + if ( ! vtDir.Normalize( EPS_ZERO)) + return false ; + // verifico superficie + if ( &SBz == nullptr) + return false ; + // verifico parametro di ritorno + if ( &vInfo == nullptr) + return false ; + vInfo.clear() ; + + // trovo le intersezioni con la trimesh ausiliaria + const ISurfTriMesh* pSurfTm = SBz.GetAuxSurf() ; + ILSIVECTOR vInfoTm ; + if ( ! IntersLineSurfTm( ptL, vtL, dLen, *pSurfTm, vInfoTm, bFinite)) + return false ; + + // ricavo le intersezioni con la superficie di Bezier + for ( IntLinStmInfo InfoTm : vInfoTm ) { + int nIL, nTT ; + double dUU, dUU2, dCos ; + Point3d ptP, ptP2, ptSP, ptSP2 ; + IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, nTT, dCos, ptP, ptP2, ptSP, ptSP2) ; + vInfo.emplace_back( InfoBz) ; + } + + //////////////////////////////////////////////////////// interlineSurfTm + + + // limito la linea al box dei triangoli della superficie + BBox3d b3Stm = Stm.GetAllTriaBox() ; + if ( b3Stm.IsEmpty()) + return false ; + // lo ingrandisco per non avere problemi con faccia piana su piani canonici + b3Stm.Expand( 10 * EPS_SMALL) ; + double dU1, dU2 ; + if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2)) + return true ; + if ( bFinite) { + dU1 = max( dU1, 0.) ; + dU2 = min( dU2, dLen) ; + if ( dU2 - dU1 < EPS_SMALL) + return true ; + } + Point3d ptStart = ptL + dU1 * vtL ; + double dLenEff = dU2 - dU1 ; + // cerco i triangoli intersecati dalla linea + const double BOX_STEP = 10 ; + int nStep = int( ceil( dLenEff / BOX_STEP)) ; + Vector3d vtStep = dLenEff / nStep * vtL ; + INTVECTOR vPrevT ; + for ( int i = 0 ; i < nStep ; ++ i) { + BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ; + INTVECTOR vT ; + if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) { + for ( auto nT : vT) { + if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) { + vPrevT.emplace_back( nT) ; + Triangle3d Tria ; + Stm.GetTriangle( nT, Tria) ; + // aggiorno info con intersezione + UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; + } + } + } + } + + // ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea + OrderInfoIntersLineSurfTm( vInfo) ; + + return true ; + + //////////////////////////////////////////////////////// interlineSurfTm + + + return true ; +} \ No newline at end of file diff --git a/IntersLineSurfBez.h b/IntersLineSurfBez.h new file mode 100644 index 0000000..6f70f09 --- /dev/null +++ b/IntersLineSurfBez.h @@ -0,0 +1 @@ +#pragma once diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 12e4efe..e78f3f5 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -257,9 +257,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool GetVertex( int nId, Point3d& ptP) const override ; bool GetVertexParam( int nId, double& dU, double& dV) const override ; int GetFirstVertex( Point3d& ptP) const override ; - int GetFirstVertexParam( int nId, double& dU, double& dV) const override ; int GetNextVertex( int nId, Point3d& ptP) const override ; - int GetNextVertexParam( int nId, double& dU, double& dV) const override ; bool GetTriangle( int nId, int nIdVert[3]) const override ; int GetFirstTriangle( int nIdVert[3]) const override ; int GetNextTriangle( int nId, int nIdVert[3]) const override ; From 2c159d7ce6a05b1d1e9547f1283f9a697e868cdd Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 8 Feb 2024 12:02:12 +0100 Subject: [PATCH 04/31] EgtGeomKernel : - aggiunta funzione di raffinamento dei punti di intersezione per Bezier. --- IntersLineSurfBez.cpp | 114 ++++++++++++++++++++++++++---------------- 1 file changed, 71 insertions(+), 43 deletions(-) diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index 080d110..3637788 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -18,6 +18,7 @@ #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkSurfBezier.h" +#include "/EgtDev/Extern/Eigen/Dense" using namespace std ; @@ -48,61 +49,88 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS // ricavo le intersezioni con la superficie di Bezier for ( IntLinStmInfo InfoTm : vInfoTm ) { - int nIL, nTT ; + // devo raffinare i parametri lungo la curva, l'angolo e i punti di intersezione double dUU, dUU2, dCos ; - Point3d ptP, ptP2, ptSP, ptSP2 ; - IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, nTT, dCos, ptP, ptP2, ptSP, ptSP2) ; + Point3d ptI, ptI2 ; + // devo trovare le intersezioni + Point3d ptSP, ptSP2 ; + RefinePoints( pSurfTm, InfoTm.nILTT, InfoTm.nT, ptI, ptI2,ptSP, ptSP2) ; + IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, InfoTm.nT, dCos, InfoTm.ptI, InfoTm.ptI2, ptSP, ptSP2) ; vInfo.emplace_back( InfoBz) ; } //////////////////////////////////////////////////////// interlineSurfTm - // limito la linea al box dei triangoli della superficie - BBox3d b3Stm = Stm.GetAllTriaBox() ; - if ( b3Stm.IsEmpty()) - return false ; - // lo ingrandisco per non avere problemi con faccia piana su piani canonici - b3Stm.Expand( 10 * EPS_SMALL) ; - double dU1, dU2 ; - if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2)) - return true ; - if ( bFinite) { - dU1 = max( dU1, 0.) ; - dU2 = min( dU2, dLen) ; - if ( dU2 - dU1 < EPS_SMALL) - return true ; - } - Point3d ptStart = ptL + dU1 * vtL ; - double dLenEff = dU2 - dU1 ; - // cerco i triangoli intersecati dalla linea - const double BOX_STEP = 10 ; - int nStep = int( ceil( dLenEff / BOX_STEP)) ; - Vector3d vtStep = dLenEff / nStep * vtL ; - INTVECTOR vPrevT ; - for ( int i = 0 ; i < nStep ; ++ i) { - BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ; - INTVECTOR vT ; - if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) { - for ( auto nT : vT) { - if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) { - vPrevT.emplace_back( nT) ; - Triangle3d Tria ; - Stm.GetTriangle( nT, Tria) ; - // aggiorno info con intersezione - UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; - } - } - } - } + //// limito la linea al box dei triangoli della superficie + // BBox3d b3Stm = Stm.GetAllTriaBox() ; + // if ( b3Stm.IsEmpty()) + // return false ; + //// lo ingrandisco per non avere problemi con faccia piana su piani canonici + // b3Stm.Expand( 10 * EPS_SMALL) ; + // double dU1, dU2 ; + // if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2)) + // return true ; + // if ( bFinite) { + // dU1 = max( dU1, 0.) ; + // dU2 = min( dU2, dLen) ; + // if ( dU2 - dU1 < EPS_SMALL) + // return true ; + // } + // Point3d ptStart = ptL + dU1 * vtL ; + // double dLenEff = dU2 - dU1 ; + //// cerco i triangoli intersecati dalla linea + // const double BOX_STEP = 10 ; + // int nStep = int( ceil( dLenEff / BOX_STEP)) ; + // Vector3d vtStep = dLenEff / nStep * vtL ; + // INTVECTOR vPrevT ; + // for ( int i = 0 ; i < nStep ; ++ i) { + // BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ; + // INTVECTOR vT ; + // if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) { + // for ( auto nT : vT) { + // if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) { + // vPrevT.emplace_back( nT) ; + // Triangle3d Tria ; + // Stm.GetTriangle( nT, Tria) ; + // // aggiorno info con intersezione + // UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; + // } + // } + // } + // } - // ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea - OrderInfoIntersLineSurfTm( vInfo) ; + //// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea + // OrderInfoIntersLineSurfTm( vInfo) ; - return true ; + // return true ; //////////////////////////////////////////////////////// interlineSurfTm return true ; +} + +//---------------------------------------------------------------------------- +// raffino i punti di intersezione e recupero le rispettive coordinate nello spazio parametrico +bool +RefinePoints( const ISurfTriMesh* pSurfTm ,int nIL, int nT, Point3d& ptI, Point3d& ptI2, Point3d& ptSP, Point3d& ptSP2) { + int nVert[3] ; + pSurfTm->GetTriangle( nT, nVert) ; + double dU0, dV0, dU1, dV1,dU2, dV2 ; + pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; + pSurfTm->GetVertexParam( nVert[1], dU1, dV1) ; + pSurfTm->GetVertexParam( nVert[2], dU2, dV2) ; + Point3d pt0, pt1, pt2 ; + pSurfTm->GetVertex( nVert[0], pt0) ; + pSurfTm->GetVertex( nVert[1], pt1) ; + pSurfTm->GetVertex( nVert[2], pt2) ; + Eigen::Matrix3d m3x3 ; + //m3x3 << pt0.x, pt1.x, pt2.x, pt0.y, pt1.y, pt2.y, pt0.z, pt1.z, pt2.z ; + m3x3.col(0) << pt0.x, pt0.y , pt0.z ; + m3x3.col(1) << pt1.x, pt1.y , pt1.z ; + m3x3.col(2) << pt2.x, pt2.y , pt2.z ; + Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; + Eigen::Vector3d x = m3x3.fullPivLu().solve(b) ; + } \ No newline at end of file From 0f8012ce61a002ca5e4cb165bda353601c674c5e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 12 Feb 2024 12:52:56 +0100 Subject: [PATCH 05/31] EgtGeomKernel : - implementata l'intersezione tra linea e sup bezier. --- EgtGeomKernel.vcxproj.filters | 3 + IntersLineSurfBez.cpp | 293 +++++++++++++++++++++++----------- SurfTriMesh.cpp | 7 - 3 files changed, 199 insertions(+), 104 deletions(-) diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index c24cae1..b22fe9d 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -273,6 +273,9 @@ File di origine\GeoInters + + File di origine\GeoInters + File di origine\GeoCreate diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index 3637788..34e45fe 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -13,108 +13,21 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "IntersLineBox.h" #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Extern/Eigen/Dense" +#include "DistPointLine.h" +#include "CurveLine.h" using namespace std ; -//---------------------------------------------------------------------------- -// Intersezione di una linea con una superficie TriMesh -//---------------------------------------------------------------------------- -bool -IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier& SBz, - ILSBIVECTOR& vInfo, bool bFinite) -{ - // verifico linea - Vector3d vtDir = vtL ; - if ( ! vtDir.Normalize( EPS_ZERO)) - return false ; - // verifico superficie - if ( &SBz == nullptr) - return false ; - // verifico parametro di ritorno - if ( &vInfo == nullptr) - return false ; - vInfo.clear() ; - - // trovo le intersezioni con la trimesh ausiliaria - const ISurfTriMesh* pSurfTm = SBz.GetAuxSurf() ; - ILSIVECTOR vInfoTm ; - if ( ! IntersLineSurfTm( ptL, vtL, dLen, *pSurfTm, vInfoTm, bFinite)) - return false ; - - // ricavo le intersezioni con la superficie di Bezier - for ( IntLinStmInfo InfoTm : vInfoTm ) { - // devo raffinare i parametri lungo la curva, l'angolo e i punti di intersezione - double dUU, dUU2, dCos ; - Point3d ptI, ptI2 ; - // devo trovare le intersezioni - Point3d ptSP, ptSP2 ; - RefinePoints( pSurfTm, InfoTm.nILTT, InfoTm.nT, ptI, ptI2,ptSP, ptSP2) ; - IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, InfoTm.nT, dCos, InfoTm.ptI, InfoTm.ptI2, ptSP, ptSP2) ; - vInfo.emplace_back( InfoBz) ; - } - - //////////////////////////////////////////////////////// interlineSurfTm - - - //// limito la linea al box dei triangoli della superficie - // BBox3d b3Stm = Stm.GetAllTriaBox() ; - // if ( b3Stm.IsEmpty()) - // return false ; - //// lo ingrandisco per non avere problemi con faccia piana su piani canonici - // b3Stm.Expand( 10 * EPS_SMALL) ; - // double dU1, dU2 ; - // if ( ! IntersLineBox( ptL, vtL, b3Stm.GetMin() , b3Stm.GetMax(), dU1, dU2)) - // return true ; - // if ( bFinite) { - // dU1 = max( dU1, 0.) ; - // dU2 = min( dU2, dLen) ; - // if ( dU2 - dU1 < EPS_SMALL) - // return true ; - // } - // Point3d ptStart = ptL + dU1 * vtL ; - // double dLenEff = dU2 - dU1 ; - //// cerco i triangoli intersecati dalla linea - // const double BOX_STEP = 10 ; - // int nStep = int( ceil( dLenEff / BOX_STEP)) ; - // Vector3d vtStep = dLenEff / nStep * vtL ; - // INTVECTOR vPrevT ; - // for ( int i = 0 ; i < nStep ; ++ i) { - // BBox3d b3Box( ptStart + i * vtStep, ptStart + ( i + 1) * vtStep) ; - // INTVECTOR vT ; - // if ( Stm.GetAllTriaOverlapBox( b3Box, vT)) { - // for ( auto nT : vT) { - // if ( find( vPrevT.begin(), vPrevT.end(), nT) == vPrevT.end()) { - // vPrevT.emplace_back( nT) ; - // Triangle3d Tria ; - // Stm.GetTriangle( nT, Tria) ; - // // aggiorno info con intersezione - // UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; - // } - // } - // } - // } - - //// ordino il vettore delle eventuali intersezioni secondo il senso crescente del parametro di linea - // OrderInfoIntersLineSurfTm( vInfo) ; - - // return true ; - - //////////////////////////////////////////////////////// interlineSurfTm - - - return true ; -} - //---------------------------------------------------------------------------- // raffino i punti di intersezione e recupero le rispettive coordinate nello spazio parametrico bool -RefinePoints( const ISurfTriMesh* pSurfTm ,int nIL, int nT, Point3d& ptI, Point3d& ptI2, Point3d& ptSP, Point3d& ptSP2) { +FindParametricCoord( const ISurfTriMesh* pSurfTm ,int nIL, int nT, const Point3d& ptI, Point3d& ptSP) { + // recupero i dati dei vertici del triangolo che fa intersezione int nVert[3] ; pSurfTm->GetTriangle( nT, nVert) ; double dU0, dV0, dU1, dV1,dU2, dV2 ; @@ -125,12 +38,198 @@ RefinePoints( const ISurfTriMesh* pSurfTm ,int nIL, int nT, Point3d& ptI, Point3 pSurfTm->GetVertex( nVert[0], pt0) ; pSurfTm->GetVertex( nVert[1], pt1) ; pSurfTm->GetVertex( nVert[2], pt2) ; - Eigen::Matrix3d m3x3 ; - //m3x3 << pt0.x, pt1.x, pt2.x, pt0.y, pt1.y, pt2.y, pt0.z, pt1.z, pt2.z ; - m3x3.col(0) << pt0.x, pt0.y , pt0.z ; - m3x3.col(1) << pt1.x, pt1.y , pt1.z ; - m3x3.col(2) << pt2.x, pt2.y , pt2.z ; + // calcolo approssimativamente le coordinate nello spazio parametrico del punto di intersezione + // quindi prima calcolo la composizione lineare tra i vertici del triangolo per ottenere il punto di intersezione + Eigen::Matrix3d mA ; + mA.col(0) << pt0.x, pt0.y , pt0.z ; + mA.col(1) << pt1.x, pt1.y , pt1.z ; + mA.col(2) << pt2.x, pt2.y , pt2.z ; Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; - Eigen::Vector3d x = m3x3.fullPivLu().solve(b) ; + Eigen::Vector3d x = mA.fullPivLu().solve(b) ; + // applico questa composizione alle loro coordinate parametriche + Eigen::Matrix3d mB ; + mB.col(0) << dU0, dV0, 0 ; + mB.col(1) << dU1, dV1, 0 ; + mB.col(2) << dU2, dV2, 0 ; + Eigen::Vector3d ptParam = mB * x ; + ptSP.x = ptParam.x() ; + ptSP.y = ptParam.y() ; + return true ; +} +//---------------------- +bool +RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite, + const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) { + // la funzione raffina la posisione del punto ptSP, minimizzando la distanza dalla retta e restituisce il punto di intersezione ptIBz + pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; + // usando un algoritmo di newton cerco di avvicinarmi il più possibile alla retta + DistPointLine dpl( ptIBz, ptL, vtL, dLen, bFinite) ; + double dDistNew = 0, dDistPre = 0 ; + dpl.GetDist(dDistNew) ; + + int nCount = 0 ; + double dh = EPS_SMALL ; + pSurfBz->GetPointD1D2( ptSP.x, ptSP.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; + // metodo di newton in più dimensioni + // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. + while ( dDistNew > EPS_SMALL && nCount < 100) { + dDistPre = dDistNew ; + Point3d ptIBzNew1 ; + pSurfBz->GetPointD1D2( ( ptSP.x + dh) / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + DistPointLine dplNewU( ptIBzNew1, ptL, vtL, dLen, bFinite) ; + dplNewU.GetDist( dDistNew) ; + double dfdU = ( dDistNew - dDistPre) / dh ; + Point3d ptIBzNew2 ; + pSurfBz->GetPointD1D2( ptSP.x / SBZ_TREG_COEFF, ( ptSP.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + DistPointLine dplNewV( ptIBzNew2, ptL, vtL, dLen, bFinite) ; + dplNewV.GetDist( dDistNew) ; + double dfdV = ( dDistNew - dDistPre) / dh ; + //// opzione 0 + ////scelgo h1 e h2 separatamente e in modo da annullare f(x) + //// opzione 1 + //// valore fisso + //double dr = EPS_SMALL ; + //if ( dDistPre > 1) + // dr = 1 ; + //else if ( dDistPre > 0.1) + // dr = 0.1 ; + //else if ( dDistPre > 0.01) + // dr = 0.01 ; + //// opzione 2 + //// valore direttamente vincolato + //double dr = dDistPre ; + //// opzione 3 + //// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve + //double dh1 = Dist( ptIBz, ptIBzNew1) ; + //double dh2 = Dist( ptIBz, ptIBzNew2) ; + // potrei valutare il nuovo spostamento in base all'ultima variazione di dDist + // potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico) + // mi avvicino cercando di annullare la distanza in un colpo solo + double dr = - dDistPre / ( dfdU + dfdV) ; + pSurfBz->GetPointD1D2(( ptSP.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptSP.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz) ; + DistPointLine dplNew( ptIBz, ptL, vtL, dLen, bFinite) ; + dplNew.GetDist( dDistNew) ; + ++nCount ; + } + + return nCount != 99 ; +} + +////---------------------------------------------------------------------------- +//bool +//RefineIntersBisec( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite, +// const ISurfBezier* pSurfBz, Point3d& ptSP, Point3d& ptIBz) { +// +//} + +//---------------------------------------------------------------------------- +void +UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos, + const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo) +{ + if ( nILT == ILTT_IN || nILT == ILTT_EDGE || nILT == ILTT_VERT) { + double dU = ( ptIBz - ptL) * vtDir ; + vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ; + } + else if ( nILT == ILTT_SEGM || nILT == ILTT_SEGM_ON_EDGE) { + double dU = ( ptIBz - ptL) * vtDir ; + double dU2 = ( ptIBz2 - ptL) * vtDir ; + vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ; + } +} + +//---------------------------------------------------------------------------- +void +OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo) +{ + // se non trovati, esco + if ( vInfo.size() == 0) + return ; + // ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea + sort( vInfo.begin(), vInfo.end(), + []( const IntLinSbzInfo& a, const IntLinSbzInfo& b) + { double dUa = ( ( a.nILTT == ILTT_SEGM || a.nILTT == ILTT_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ; + double dUb = ( ( b.nILTT == ILTT_SEGM || b.nILTT == ILTT_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ; + return ( dUa < dUb) ; }) ; +} + +//---------------------------------------------------------------------------- +// Intersezione di una linea con una superficie TriMesh +//---------------------------------------------------------------------------- +bool +IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz, + ILSBIVECTOR& vInfo, bool bFinite) +{ + PtrOwner pCL( CreateCurveLine()) ; + pCL->SetPVL(ptL, vtL, dLen) ; + // verifico linea + Vector3d vtDir = vtL ; + if ( ! vtDir.Normalize( EPS_ZERO)) + return false ; + // verifico superficie + if ( pSurfBz == nullptr) + return false ; + // verifico parametro di ritorno + if ( &vInfo == nullptr) + return false ; + vInfo.clear() ; + + // trovo le intersezioni con la trimesh ausiliaria + const ISurfTriMesh* pSurfTm = pSurfBz->GetAuxSurf() ; + ILSIVECTOR vInfoTm ; + if ( ! IntersLineSurfTm( ptL, vtL, dLen, *pSurfTm, vInfoTm, bFinite)) + return false ; + // ricavo le intersezioni con la superficie di Bezier + for ( IntLinStmInfo InfoTm : vInfoTm ) { + // devo raffinare i parametri lungo la curva, l'angolo e i punti di intersezione + Point3d ptI, ptI2 ; + // devo trovare le intersezioni + Point3d ptSP, ptSP2 ; // coordinate parametriche delle soluzioni + FindParametricCoord( pSurfTm, InfoTm.nILTT, InfoTm.nT, InfoTm.ptI, ptSP) ; + Point3d ptIBz, ptIBz2 ; + if ( ! RefineIntersNewton( ptL, vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) { + /////// posso provare anche a rilanciare newton con un punto di partenza diverso oppure con una direzione di avvicinamento diversa/////////////////////////////////// + // per restare nel triangolo mi sposto verso un vertice + int nVert[3] ; + pSurfTm->GetTriangle( InfoTm.nT, nVert) ; + double dU0, dV0 ; + pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; + ptSP = ptSP + Point3d(dU0, dV0, 0) ; + if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) + return false ; + } + Vector3d vtN ; + pSurfBz->GetPointNrmD1D2(ptSP.x / SBZ_TREG_COEFF, ptSP.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz, vtN) ; + double dCos = vtN * vtL ; + double dCos2 = 0 ; + // eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione) + if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) { + FindParametricCoord( pSurfTm, InfoTm.nILTT, InfoTm.nT, InfoTm.ptI2, ptSP2) ; + if ( !RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) { + int nVert[3] ; + pSurfTm->GetTriangle( InfoTm.nT, nVert) ; + double dU0, dV0 ; + pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; + ptSP = ptSP + Point3d(dU0, dV0, 0) ; + if ( ! RefineIntersNewton( ptL,vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) + return false ; + } + pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ; + dCos2 = vtN * vtL ; + } + //IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, InfoTm.nT, dCos, ptIBz, ptIBz2, ptSP, ptSP2) ; + //vInfo.emplace_back( InfoBz) ; + UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ; + } + + OrderInfoIntersLineSurfBz( vInfo) ; + + //////////////////////////////////////////////////////// interlineSurfTm + //UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; + // OrderInfoIntersLineSurfTm( vInfo) ; + //////////////////////////////////////////////////////// interlineSurfTm + + + return true ; } \ No newline at end of file diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 19157d9..8bac766 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -505,13 +505,6 @@ SurfTriMesh::GetFirstVertex( Point3d& ptP) const return GetNextVertex( SVT_NULL, ptP) ; } -//---------------------------------------------------------------------------- -int -SurfTriMesh::GetFirstVertexParam( int nId, double& dU, double& dV) const -{ - return GetNextVertexParam( SVT_NULL, dU, dV) ; -} - //---------------------------------------------------------------------------- int SurfTriMesh::GetNextVertex( int nId, Point3d& ptP) const From 5d62db3e73e1c54103363c5246754b9a18314c1b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 14 Feb 2024 14:40:57 +0100 Subject: [PATCH 06/31] EgtGeomKernel : - aggiunta funzione per creare una sfera come sup Bezier. --- EgtGeomKernel.vcxproj | 1 + EgtGeomKernel.vcxproj.filters | 3 ++ SbzStandard.cpp | 80 +++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 SbzStandard.cpp diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 8c884bb..6fe399c 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -310,6 +310,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index c24cae1..4802df7 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -510,6 +510,9 @@ File di origine\GeoElevation + + File di origine\GeoCreate + diff --git a/SbzStandard.cpp b/SbzStandard.cpp new file mode 100644 index 0000000..5dd2cbe --- /dev/null +++ b/SbzStandard.cpp @@ -0,0 +1,80 @@ +//---------------------------------------------------------------------------- +// EgalTech 2024 +//---------------------------------------------------------------------------- +// File : SbzSphere.cpp Data : 14.02.2024 Versione : 2.6b2 +// Contenuto : Implementazione di funzioni per creazione di superfici Sbz +// standard : Box, Pyramid, Cylinder, Sphere, Cone. +// +// +// Modifiche : 14.02.2024 DB Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CurveArc.h" +#include "SurfTriMesh.h" +#include "SurfBezier.h" +#include "/EgtDev/Include/EGkSbzStandard.h" + +using namespace std ; + +//------------------------------------------------------------------------------- +ISurfBezier* +CreateBezierSphere( const Point3d& ptCenter, double dR) +{ + // creo una superficie di Bezier di grado 2 con 45 punti di controllo + PtrOwner pSrfBez( CreateSurfBezier()) ; + int nDegU = 2 ; + int nDegV = 2 ; + int nSpanU = 4 ; // i poli della sfera sono a coordinate ( 0,0,-R) e ( 0,0,R) + int nSpanV = 2 ; + bool bRat = true ; + double dW = SQRT2 ; + pSrfBez->Init(nDegU, nDegV, nSpanU, nSpanV, bRat) ; + // polo inferiore // dW = 1, dW = SQRT2 / 2 + for ( int i = 0 ; i < 9; ++i) { + if ( i % 2 == 0) + dW = 1 ; + else + dW = SQRT2 / 2 ; + pSrfBez->SetControlPoint( i, 0, ptCenter + Point3d( 0, 0, -dR), dW) ; + } + // definisco la gabbia esterna // dW = SQRT2 / 2, dW = 1 / 2 + // parto dal punto ( 0,-dR, -dR) e completo riga per riga + double dH = -dR ; + for ( int j = 1 ; j < 4 ; ++j ) { + Vector3d vtDir ( 0, -dR, 0) ; + Point3d pt(-dR,-dR,dH) ; + for ( int i = 0; i < 9 ; ++i ) { + // ogni due punti ruoto di 90 gradi a sinistra + if ( i%2 == 0) { + vtDir.Rotate( Z_AX, 90) ; + if ( j%2 == 1) + dW = SQRT2 / 2 ; + else + dW = 1 ; + } + else { + if ( j%2 == 1) + dW = 1. / 2. ; + else + dW = SQRT2 / 2 ; + } + pt += vtDir ; + pSrfBez->SetControlPoint( i, j, ptCenter + pt, dW) ; + } + dH += dR ; + } + // polo superiore // dW = 1, dW = SQRT2 / 2 + for ( int i = 0 ; i < 9; ++i) { + if ( i % 2 == 0) + dW = 1 ; + else + dW = SQRT2 / 2 ; + pSrfBez->SetControlPoint( i, 4, ptCenter + Point3d( 0, 0, dR), dW) ; + } + + return Release( pSrfBez) ; +} From c303b1273d8a77a588cd643473ed8260e07b6e40 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 20 Feb 2024 12:28:45 +0100 Subject: [PATCH 07/31] EgtGeomKernel : - aggiunta la funzione per creare una sfera come superficie bezier - aggiunta la funzione per tagliare una superificie bezier con un piano. --- IntersLineSurfBez.cpp | 46 +---- SurfBezier.cpp | 449 ++++++++++++++++++++++++++++++++++-------- SurfBezier.h | 7 +- Tree.cpp | 179 ++++++++++++++++- Tree.h | 103 ++++++++-- 5 files changed, 647 insertions(+), 137 deletions(-) diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index 34e45fe..7ee2c8e 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -17,46 +17,11 @@ #include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include "/EgtDev/Include/EGkIntersLineSurfBez.h" #include "/EgtDev/Include/EGkSurfBezier.h" -#include "/EgtDev/Extern/Eigen/Dense" #include "DistPointLine.h" #include "CurveLine.h" using namespace std ; -//---------------------------------------------------------------------------- -// raffino i punti di intersezione e recupero le rispettive coordinate nello spazio parametrico -bool -FindParametricCoord( const ISurfTriMesh* pSurfTm ,int nIL, int nT, const Point3d& ptI, Point3d& ptSP) { - // recupero i dati dei vertici del triangolo che fa intersezione - int nVert[3] ; - pSurfTm->GetTriangle( nT, nVert) ; - double dU0, dV0, dU1, dV1,dU2, dV2 ; - pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; - pSurfTm->GetVertexParam( nVert[1], dU1, dV1) ; - pSurfTm->GetVertexParam( nVert[2], dU2, dV2) ; - Point3d pt0, pt1, pt2 ; - pSurfTm->GetVertex( nVert[0], pt0) ; - pSurfTm->GetVertex( nVert[1], pt1) ; - pSurfTm->GetVertex( nVert[2], pt2) ; - // calcolo approssimativamente le coordinate nello spazio parametrico del punto di intersezione - // quindi prima calcolo la composizione lineare tra i vertici del triangolo per ottenere il punto di intersezione - Eigen::Matrix3d mA ; - mA.col(0) << pt0.x, pt0.y , pt0.z ; - mA.col(1) << pt1.x, pt1.y , pt1.z ; - mA.col(2) << pt2.x, pt2.y , pt2.z ; - Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; - Eigen::Vector3d x = mA.fullPivLu().solve(b) ; - // applico questa composizione alle loro coordinate parametriche - Eigen::Matrix3d mB ; - mB.col(0) << dU0, dV0, 0 ; - mB.col(1) << dU1, dV1, 0 ; - mB.col(2) << dU2, dV2, 0 ; - Eigen::Vector3d ptParam = mB * x ; - ptSP.x = ptParam.x() ; - ptSP.y = ptParam.y() ; - return true ; -} - //---------------------- bool RefineIntersNewton( const Point3d& ptL, const Vector3d& vtL, double dLen, bool bFinite, @@ -162,7 +127,10 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS ILSBIVECTOR& vInfo, bool bFinite) { PtrOwner pCL( CreateCurveLine()) ; - pCL->SetPVL(ptL, vtL, dLen) ; + if ( bFinite) + pCL->SetPVL(ptL, vtL, dLen) ; + else + pCL->SetPVL(ptL, vtL, 1e6) ; // verifico linea Vector3d vtDir = vtL ; if ( ! vtDir.Normalize( EPS_ZERO)) @@ -186,7 +154,7 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS Point3d ptI, ptI2 ; // devo trovare le intersezioni Point3d ptSP, ptSP2 ; // coordinate parametriche delle soluzioni - FindParametricCoord( pSurfTm, InfoTm.nILTT, InfoTm.nT, InfoTm.ptI, ptSP) ; + pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI, ptSP, InfoTm.nILTT) ; Point3d ptIBz, ptIBz2 ; if ( ! RefineIntersNewton( ptL, vtL, dLen, bFinite, pSurfBz, ptSP, ptIBz)) { /////// posso provare anche a rilanciare newton con un punto di partenza diverso oppure con una direzione di avvicinamento diversa/////////////////////////////////// @@ -205,8 +173,8 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS double dCos2 = 0 ; // eventualmente ripeto tutto per ptI2 ( se ho un'intersezione con sovrapposizione) if ( InfoTm.nILTT == ILTT_SEGM || InfoTm.nILTT == ILTT_SEGM_ON_EDGE ) { - FindParametricCoord( pSurfTm, InfoTm.nILTT, InfoTm.nT, InfoTm.ptI2, ptSP2) ; - if ( !RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) { + pSurfBz->UnprojectPointFromStm( InfoTm.nT, InfoTm.ptI2, ptSP2, InfoTm.nILTT) ; + if ( ! RefineIntersNewton(ptL, vtL, dLen, bFinite, pSurfBz, ptSP2, ptIBz2) ) { int nVert[3] ; pSurfTm->GetTriangle( InfoTm.nT, nVert) ; double dU0, dV0 ; diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 265236c..e8326a5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -29,6 +29,13 @@ #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkIntersPlaneSurfTm.h" +#include "/EgtDev/Include/EGkChainCurves.h" +#include "/EgtDev/Include/EGkIntersLineSurfBez.h" +#include "/EgtDev/Include/EGkDistPointSurfTm.h" +#include "/EgtDev/Extern/Eigen/Dense" +#include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -129,15 +136,28 @@ SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) //---------------------------------------------------------------------------- bool -SurfBezier::SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) +SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtract) { // verifico la regione passata if ( &sfrTrimReg == nullptr || ! sfrTrimReg.IsValid()) return false ; + // se la normale ha z negativa ribalto la superficie, sennò le operazioni di intersect e subtract non funzionano + if ( sfrTrimReg.GetNormVersor().z < 0) + sfrTrimReg.Invert() ; // limito la regione allo spazio parametrico della superficie PtrOwner< ISurfFlatRegion> pSfrTrim( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - if ( IsNull( pSfrTrim) || ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid()) - return false ; + // bIntersectOrSubtract == true per ottenere lo spazio parametrico trimmato devo fare l'INTERSEZIONE tra il rettangolo totale e l'area passata + if ( bIntersectOrSubtract) { + if ( IsNull( pSfrTrim) || ! pSfrTrim->Intersect( sfrTrimReg) || ! pSfrTrim->IsValid()) + return false ; + } + // bIntersectOrSubtract == false per ottenere lo spazio parametrico trimmato devo fare la SOTTRAZIONE tra il rettangolo totale e l'area passata + else { + if ( IsNull( pSfrTrim) || ! pSfrTrim->Subtract( sfrTrimReg) || ! pSfrTrim->IsValid()) + return false ; + } + ResetAuxSurf() ; + delete m_pSTM ; // assegno la regione di trim m_bTrimmed = true ; delete m_pTrimReg ; @@ -1411,82 +1431,6 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const return 0 ; return dLen ; } -// -////---------------------------------------------------------------------------- -//const SurfTriMesh* -//SurfBezier::GetAuxSurf( void) const -//{ -// // la superficie deve essere validata -// if ( m_nStatus != OK) { -// ResetAuxSurf() ; -// return nullptr ; -// } -// // se gi� calcolata, la restituisco -// if ( m_pSTM != nullptr) -// return m_pSTM ; -// // costruttore della superficie -// StmFromTriangleSoup stmSoup ; -// if ( ! stmSoup.Start()) -// return nullptr ; -// // definisco il numero degli step in U e in V -// double dMaxLenU = 0 ; -// for ( int j = 0 ; j <= m_nDegV * m_nSpanV ; ++ j) -// dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ; -// int nStepU = GetSteps( m_nDegU, m_nSpanU, dMaxLenU, 2) ; -// double dMaxLenV = 0 ; -// for ( int i = 0 ; i <= m_nDegU * m_nSpanU ; ++ i) -// dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ; -// int nStepV = GetSteps( m_nDegV, m_nSpanV, dMaxLenV, 2) ; -// // prima curva isoparametrica (potrebbe essere un solo punto) -// PolyLine PL1 ; -// GetCurveOnU( 0, nStepU, PL1) ; -// bool bSingle1 = ( PL1.GetPointNbr() == 1) ; -// // ciclo sulle isoparametriche -// for ( int i = 1 ; i <= nStepV ; ++ i) { -// // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo) -// double dV = double( i) * m_nSpanV / nStepV ; -// PolyLine PL2 ; -// GetCurveOnU( dV, nStepU, PL2) ; -// bool bSingle2 = ( PL2.GetPointNbr() == 1) ; -// // inserisco i triangoli della striscia nel costruttore della TriMesh -// Point3d ptP1c, ptP2c ; -// Point3d ptP1n, ptP2n ; -// bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ; -// if ( bNext) { -// if ( bSingle1 && bSingle2) -// bNext = false ; -// if ( bSingle1) -// ptP1n = ptP1c ; -// else -// bNext = bNext && PL1.GetNextPoint( ptP1n) ; -// if ( bSingle2) -// ptP2n = ptP2c ; -// else -// bNext = bNext && PL2.GetNextPoint( ptP2n) ; -// } -// while ( bNext) { -// // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo) -// if ( ! AreSamePointApprox( ptP1c, ptP2c)) -// stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ; -// // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi) -// if ( ! AreSamePointApprox( ptP1n, ptP2n)) -// stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ; -// // passo alla successiva coppia -// ptP1c = ptP1n ; -// ptP2c = ptP2n ; -// bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ; -// } -// // salvo isoparametrica PL2 in PL1 -// PL1.GetUPointList().swap( PL2.GetUPointList()) ; -// bSingle1 = bSingle2 ; -// } -// // la completo -// if ( ! stmSoup.End()) -// return nullptr ; -// // la salvo -// m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; -// return m_pSTM ; -//} //---------------------------------------------------------------------------- const SurfTriMesh* @@ -1531,6 +1475,9 @@ SurfBezier::GetAuxSurf( void) const //} //// per usare i polygon basic/////////////////// + // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria + Tree.GetEdge3D( m_vPLEdges) ; + // qui non sarebbe male stampare un messaggio di errore nel log se avevo un'area da disegnare ma non sono usciti dei poligoni if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ; @@ -1618,3 +1565,347 @@ SurfBezier::ResetTrimRegion( void) delete( m_pTrimReg) ; m_pTrimReg = nullptr ; } + +//---------------------------------------------------------------------------- +ICurveComposite* +SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const +{ + // do per scontato che la compo sia una spezzata, visto che arriva dall'intersezione tra un piano e una trimesh + + const ICurve* pCrv0 = pCC->GetCurve( 0) ; + PolyLine pl ; + Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ; + DistPointSurfTm distPtStm0( pt3D, *GetAuxSurf()) ; + // aggiungo il primo punto + int nTriaIndex ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; + if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D)) + return nullptr ; + pl.AddUPoint( 0, pt2D) ; + // aggiungo tutti i successivi + for ( int i = 1 ; i < int( pCC->GetCurveCount()) ; ++i) { + const ICurve* pCrv = pCC->GetCurve( i) ; + pCrv->GetEndPoint( pt3D) ; + DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ; + distPtStm.GetMinDistTriaIndex( nTriaIndex) ; + if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D)) + return nullptr ; + pl.AddUPoint( i, pt2D) ; + } + PtrOwner pCC2D ( CreateCurveComposite()) ; + pCC2D->FromPolyLine( pl) ; + return Release( pCC2D) ; +} + + +//---------------------------------------------------------------------------- +bool +SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) +{ + // faccio l'intersezione della trimesh ausiliaria con il piano posso ottenere: punti, curve 3d e triangoli( coplanari al piano di taglio) + // i punti li escludo + // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim + // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim + + PNTVECTOR vPnt ; + BIPNTVECTOR vBPnt ; + TRIA3DVECTOR vTria ; + IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; + + // recupero la superficie di trim a cui devo aggiungere tutt i nuovi loop di trim + PtrOwner sfrTrimReg ( GetTrimRegion()) ; + if ( IsNull( sfrTrimReg)) + sfrTrimReg.Set( CreateBasicSurfFlatRegion()) ; + + // concateno le curve 3d + ChainCurves chainC ; + double dToler = EPS_SMALL ; + chainC.Init( false, dToler, int( vBPnt.size())) ; + for ( int i = 0 ; i < int( vBPnt.size()) ; ++ i) { + Vector3d vtDir = vBPnt[i].second - vBPnt[i].first ; + vtDir.Normalize() ; + if ( ! chainC.AddCurve( i + 1, vBPnt[i].first, vtDir, vBPnt[i].second, vtDir)) + return false ; + } + // GESTIONE DELLE CURVE OTTENUTE DALL'INTERSEZIONE + + // recupero i percorsi concatenati + Point3d ptNear = ( vBPnt.empty() ? ORIG : vBPnt[0].first) ; + INTVECTOR vId ; + // Devo controllare se i trim intersecano il bordo dello spazio parametrico ed eventualmente spezzare le curve di trim in 2D tenendo conto della periodicità + // costruisco le curveCompo che rappresetano gli edge + ICRVCOMPOPVECTOR vCCEdge ; + for ( int i= 0 ; i < int( m_vPLEdges.size()); ++i) { + vCCEdge.emplace_back() ; + vCCEdge.back()->FromPolyLine( m_vPLEdges[i]) ; + } + // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi + ICRVCOMPOPOVECTOR vpCCOpen ; + ICRVCOMPOPOVECTOR vpCCClosed ; + while ( chainC.GetChainFromNear( ptNear, false, vId)) { + // creo una curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita + bool bAdded = true ; + for ( int i = 0 ; i < int( vId.size()) ; ++ i) { + // creo un segmento di retta + PtrOwner pLine( CreateCurveLine()) ; + if ( IsNull( pLine)) + return false ; + // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) + int nInd = abs( vId[i]) - 1 ; + Point3d ptStart = ( bAdded ? vBPnt[nInd].first : ptNear) ; + Point3d ptEnd = vBPnt[nInd].second ; + // provo ad accodarlo alla composita + bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && + pLine->Set( ptStart, ptEnd) && + pCrvCompo->AddCurve( Release( pLine), true, dToler)) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando + double dCrvLen ; + if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) + continue ; + // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene + Point3d ptStart, ptEnd ; + if ( pCrvCompo->GetStartPoint( ptStart) && + pCrvCompo->GetEndPoint( ptEnd) && + AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) && + ! AreSamePointApprox( ptStart, ptEnd)) { + // porto il punto finale a coincidere esattamente con l'inizio + pCrvCompo->ModifyEnd( ptStart) ; + } + // assegno estrusione come direzione normale al piano + pCrvCompo->SetExtrusion( plPlane.GetVersN()) ; + // unisco segmenti allineati + pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; + + // porto la curva nello spazio parametrico + PtrOwner pCC( UnprojectCurveFromStm( pCrvCompo)) ; + + // le curve aperte le tengo da parte per giuntarle alla fine col bordo + if ( ! pCC->IsClosed()) + vpCCOpen.emplace_back( Release( pCC)) ; + // le curve chiuse le metto tutte insieme subito + else + vpCCClosed.emplace_back( Release( pCC)) ; // da controllare che funzioni anche se passo i loop con orientamenti sbagliati////////// + } + + // creo il nuovo bordo usando i loop aperti + POLYLINEMATRIX vPolygons ; + if ( int(vpCCOpen.size()) != 0 ) { + Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ; + POLYLINEVECTOR vPL ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) { + PolyLine pl ; + vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ; + vPL.emplace_back( pl) ; + } + Tree.AddCutsToRoot( vPL) ; + Tree.CreateCellContour( vPolygons) ; + } + + //GESTIONE DEI TRIANGOLI RISULTANTI DALL'INTERSEZIONE + StmFromTriangleSoup StmFts ; + if ( ! StmFts.Start()) + return GDB_ID_NULL ; + for ( int i = 0 ; i < int( vTria.size()) ; ++ i) + // inserisco il triangolo nella nuova superficie + StmFts.AddTriangle( vTria[i]) ; + // valido la superficie e calcolo le adiacenze + if ( ! StmFts.End()) + return GDB_ID_NULL ; + // se superficie con triangoli + PtrOwner pNewStm( StmFts.GetSurf()) ; + POLYLINEVECTOR vPLTria ; + if ( ! IsNull( pNewStm) && pNewStm->GetTriangleCount() > 0) { + pNewStm->GetLoops( vPLTria) ; + } + + SurfFlatRegionByContours sfrContour ; + // aggiungo i tagli sul bordo + for ( int i = 0 ; i < int( vPolygons.size()); ++i ) { + for ( int j = 0 ; j < int( vPolygons[i].size()); ++j) { + PtrOwner pCC( CreateCurveComposite()) ; + pCC->FromPolyLine( vPolygons[i][j]) ; + sfrContour.AddCurve( Release( pCC)) ; + } + } + // aggiungo i loop chiusi + for ( int i = 0 ; i < int( vpCCClosed.size()); ++i ) + sfrContour.AddCurve( Release( vpCCClosed[i])) ; + // aggiungo loop derivati dai triangoli + for ( int i = 0 ; i < int( vPLTria.size()); ++i ) { + PtrOwner pCC( CreateCurveComposite()) ; + pCC->FromPolyLine( vPLTria[i]) ; + sfrContour.AddCurve( Release( pCC)) ; + } + PtrOwner pSFR( sfrContour.GetSurf()) ; + if ( IsNull( pSFR) || ! pSFR->IsValid()) + return false ; + + // se la superficie ha normale con z negativa la inverto + if ( pSFR->GetNormVersor().z < 0) + pSFR->Invert() ; + + // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) + // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio + int nChunkMin = 0 , nLoopMin = 0 ; + // sono nello spazio parametrico, quindi le aree delle curve possono essere molto grandi + double dAreaMin = 1e30 ; + bool bPos = false ; + for ( int c = 0 ; c < int( pSFR->GetChunkCount()); ++c) { + PtrOwner pSurf( pSFR->CloneChunk( c)) ; + for ( int l = 0 ; l < pSurf->GetLoopCount( 0); ++l) { + PtrOwner pCrv( pSurf->GetLoop( 0, l)) ; + double dArea ; pCrv->GetAreaXY( dArea) ; + if ( abs( dArea) < dAreaMin) { + nChunkMin = c ; + nLoopMin = l ; + dAreaMin = abs( dArea) ; + bPos = dArea > 0 ; + } + } + } + + // aggiorno la superficie di trim + Point3d ptStart ; + Vector3d vtDir ; + PtrOwner pCrv( pSFR->GetLoop( nChunkMin, nLoopMin)) ; + pCrv->GetStartPoint( ptStart) ; + pCrv->GetStartDir( vtDir) ; + vtDir.Rotate( Z_AX, bPos? 90 : -90) ; + PtrOwner pCL( CreateCurveLine()) ; + pCL->SetPVL( ptStart, vtDir, 1e6) ; + IntersCurveCurve icc( *Release( pCL), *Release(pCrv)) ; + // verifico di guardare verso l'interno ( il numero di intersezioni deve essere pari visto che partivo da un punto sulla curva) + if ( icc.GetIntersCount()%2 != 0) + return false ; // o sennò un altro tentativo prima di rinunciare + IntCrvCrvInfo iccInfo ; + icc.GetIntCrvCrvInfo( 1, iccInfo) ; + Point3d ptI = iccInfo.IciA[0].ptI ; + Point3d ptToCheck = ( ptStart + ptI) / 2 ; + Point3d pt3D ; GetPointD1D2( ptToCheck.x / SBZ_TREG_COEFF, ptToCheck.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + double dDist = DistPointPlane( pt3D, plPlane) ; + + // ho due casi in cui devo invertire(prendere il complementare rispetto allo spazio parametrico) la superficie: + // 1. se il punto è sopra il piano ed era dentro una curva CCW + // 2. se il punto è sotto il piano ed era interno ad una curva CW + + PtrOwner pSrfFR_Copy( pSFR->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) + SetTrimRegion( *Release( pSFR), false) ; + else + SetTrimRegion( *Release( pSFR)) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const +{ + // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche + const ISurfTriMesh* pSurfTm = GetAuxSurf() ; + // recupero i dati dei vertici del triangolo che fa intersezione + int nVert[3] ; + pSurfTm->GetTriangle( nT, nVert) ; + double dU0, dV0, dU1, dV1,dU2, dV2 ; + pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; + pSurfTm->GetVertexParam( nVert[1], dU1, dV1) ; + pSurfTm->GetVertexParam( nVert[2], dU2, dV2) ; + Point3d pt0, pt1, pt2 ; + pSurfTm->GetVertex( nVert[0], pt0) ; + pSurfTm->GetVertex( nVert[1], pt1) ; + pSurfTm->GetVertex( nVert[2], pt2) ; + // se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice + if ( nIL == 3 ) { + if ( AreSamePointApprox(ptI, pt0)) + ptSP.Set( dU0, dV0, 0) ; + else if ( AreSamePointApprox(ptI, pt1)) + ptSP.Set( dU1, dV1, 0) ; + else if ( AreSamePointApprox(ptI, pt2)) + ptSP.Set( dU2, dV2, 0) ; + return true ; + } + // calcolo approssimativamente le coordinate nello spazio parametrico del punto di intersezione + // quindi prima calcolo la composizione lineare tra i vertici del triangolo per ottenere il punto di intersezione + Eigen::Matrix3d mA ; + mA.col(0) << pt0.x, pt0.y , pt0.z ; + mA.col(1) << pt1.x, pt1.y , pt1.z ; + mA.col(2) << pt2.x, pt2.y , pt2.z ; + Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; + Eigen::Vector3d x = mA.fullPivLu().solve(b) ; + // applico questa composizione alle loro coordinate parametriche + Eigen::Matrix3d mB ; + mB.col(0) << dU0, dV0, 0 ; + mB.col(1) << dU1, dV1, 0 ; + mB.col(2) << dU2, dV2, 0 ; + Eigen::Vector3d ptParam = mB * x ; + ptSP.x = ptParam.x() ; + ptSP.y = ptParam.y() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const +{ + // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton + // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D + // ripeto cercando di avvicinarmi il più possibile + // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino + DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; + int nTriaIndex ; dptSurfTm.GetMinDistTriaIndex( nTriaIndex) ; + Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; + UnprojectPointFromStm( nTriaIndex, ptI, ptParam) ; + Point3d ptBez ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto + double dDistNew = Dist( pt3D, ptBez) ; + double dDistPre = dDistNew ; + + int nCount = 0 ; + double dh = EPS_SMALL ; + // metodo di newton in più dimensioni + // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. + while ( dDistNew > EPS_SMALL && nCount < 100) { + dDistPre = dDistNew ; + Point3d ptIBzNew1 ; + GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + dDistNew = Dist( pt3D, ptIBzNew1) ; + double dfdU = ( dDistNew - dDistPre) / dh ; + Point3d ptIBzNew2 ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + dDistNew = Dist( pt3D, ptIBzNew2) ; + double dfdV = ( dDistNew - dDistPre) / dh ; + //// opzione 0 + ////scelgo h1 e h2 separatamente e in modo da annullare f(x) + //// opzione 1 + //// valore fisso + //double dr = EPS_SMALL ; + //if ( dDistPre > 1) + // dr = 1 ; + //else if ( dDistPre > 0.1) + // dr = 0.1 ; + //else if ( dDistPre > 0.01) + // dr = 0.01 ; + //// opzione 2 + //// valore direttamente vincolato + //double dr = dDistPre ; + //// opzione 3 + //// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve + //double dh1 = Dist( ptIBz, ptIBzNew1) ; + //double dh2 = Dist( ptIBz, ptIBzNew2) ; + // potrei valutare il nuovo spostamento in base all'ultima variazione di dDist + // potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico) + // mi avvicino cercando di annullare la distanza in un colpo solo + double dr = - dDistPre / ( dfdU + dfdV) ; + GetPointD1D2(( ptParam.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptParam.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + dDistNew = Dist( pt3D, ptBez) ; + ++nCount ; + } + return nCount != 99 ; +} diff --git a/SurfBezier.h b/SurfBezier.h index 9f357d1..7e150f4 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -87,7 +87,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool SetControlPoint( int nIndU, int nIndV, const Point3d& ptCtrl, double dW) override { return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; } bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ; - bool SetTrimRegion( const ISurfFlatRegion& sfrTrimReg) override ; + bool SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtract = true) override ; SurfFlatRegion* GetTrimRegion( void) const override ; bool GetInfo( int& nDegU, int& nDegV, int& nSpanU, int& nSpanV, bool& bIsRat, bool& bTrimmed) const override ; const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override @@ -112,6 +112,10 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; const SurfTriMesh* GetAuxSurf( void) const override ; bool GetLeaves( std::vector>& vLeaves) const override ; + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; + bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const override ; + ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ; + bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -175,6 +179,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei + mutable POLYLINEVECTOR m_vPLEdges ; // vettore delle polyline degli edge nello spazio 3D } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index 9bdfaca..2c63934 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -49,6 +49,14 @@ Tree::~Tree( void) { } +//---------------------------------------------------------------------------- +Tree::Tree( const Point3d ptBl, const Point3d ptTr) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) +{ + Cell cRoot( ptBl, ptTr) ; + m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; +} + //---------------------------------------------------------------------------- void Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax) @@ -931,6 +939,7 @@ Tree::Balance() void Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const { + // le celle restituite sono ordinate per x crescente if ( vTopNeighs.empty()) { if ( m_mTree.at( nId).m_nTop == -2) return ; @@ -1000,6 +1009,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const vector vCells ; for ( int k : vTopNeighs) vCells.push_back( m_mTree.at( k)) ; + // le celle restituite sono ordinate per x crescente sort( vCells.begin(), vCells.end(), Cell::minorX) ; vTopNeighs.clear() ; for ( Cell c : vCells) @@ -1011,6 +1021,7 @@ Tree::GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const void Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const { + // le celle restituite sono ordinate per x crescente if ( vBottomNeighs.empty()) { if ( m_mTree.at( nId).m_nBottom == -2) return ; @@ -1080,6 +1091,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const vector vCells ; for ( int k : vBottomNeighs) vCells.push_back( m_mTree.at( k)) ; + // le celle restituite sono ordinate per x crescente sort( vCells.begin(), vCells.end(), Cell::minorX) ; vBottomNeighs.clear() ; for ( Cell c : vCells) @@ -1090,6 +1102,7 @@ Tree::GetBottomNeigh( int nId, INTVECTOR& vBottomNeighs) const void Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const { + // le celle restituite sono ordinate per y crescente if ( vLeftNeighs.empty()) { if ( m_mTree.at( nId).m_nLeft == -2) return ; @@ -1159,6 +1172,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const vector vCells ; for ( int k : vLeftNeighs) vCells.push_back( m_mTree.at( k)) ; + // le celle restituite sono ordinate per y crescente sort( vCells.begin(), vCells.end(), Cell::minorY) ; vLeftNeighs.clear() ; for ( Cell c : vCells) @@ -1169,6 +1183,7 @@ Tree::GetLeftNeigh( int nId, INTVECTOR& vLeftNeighs) const void Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const { + // le celle restituite sono ordinate per y crescente if ( vRightNeighs.empty()) { if ( m_mTree.at( nId).m_nRight == -2) return ; @@ -1238,6 +1253,7 @@ Tree::GetRightNeigh( int nId, INTVECTOR& vRightNeighs) const vector vCells ; for ( int k : vRightNeighs) vCells.push_back( m_mTree.at( k)) ; + // le celle restituite sono ordinate per y crescente sort( vCells.begin(), vCells.end(), Cell::minorY) ; vRightNeighs.clear() ; for ( Cell c : vCells) @@ -1418,9 +1434,16 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells) { - if ( m_vPolygons.empty()) { + // condizioni per il calcolo dei poligoni di base + if ( m_vPolygons.empty() || // se non li ho mai calcolati + ( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle + ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size())) { // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle + // se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie + if ( vCells.empty()) + vCells = m_vnLeaves ; + PNTVECTOR vVertices ; INTVECTOR vNeigh ; // setto le celle che sono sul LeftEdge e sul TopEdge @@ -1440,7 +1463,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons) bool bBottomRight , bTopLeft ; // scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline della cella anche i vertici, delle celle adiacenti, // che sono sui lati della cella corrente - for ( int nId : m_vnLeaves) { + for ( int nId : vCells) { vVertices.clear() ; vNeigh.clear() ; vVertices.push_back( m_mTree.at( nId).GetBottomLeft()) ; @@ -3521,3 +3544,153 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const return false ; return true ; } + +//---------------------------------------------------------------------------- +bool +Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) +{ + INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge + // recupero le celle sui quattro bordi + vEdges.emplace_back() ; + GetRootNeigh( 0, vEdges[0]) ; + // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, + // quindi devo invertire gli Edge 0 e 1 + reverse( vEdges[0].begin(), vEdges[0].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 1, vEdges[1]) ; + reverse( vEdges[1].begin(), vEdges[1].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 2, vEdges[2]) ; + vEdges.emplace_back() ; + GetRootNeigh( 3, vEdges[3]) ; + + // recupero i poligoni base delle celle sui bordi + POLYLINEMATRIX mPL ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[0], vEdges[0]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[1], vEdges[1]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[2], vEdges[2]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[3], vEdges[3]) ; + + // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato + for ( int i = 0 ; i < int( mPL.size()) ; ++i) { + vPLEdges.emplace_back() ; + int nPtCount = 0 ; + // scorro sui poligoni delle celle di un lato + for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { + Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; + // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato + if ( i == 0 && AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) ) { + // scorro fino alla fine di quel lato + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { + vPLEdges.back().AddUPoint( nPtCount, pt) ; + ++ nPtCount ; + } + } + else if ( i == 1 && AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) ) { + // scorro fino alla fine di quel lato + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + vPLEdges.back().AddUPoint( nPtCount, pt) ; + ++ nPtCount ; + } + } + else if ( i == 2 && AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) ) { + // scorro fino alla fine di quel lato + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + vPLEdges.back().AddUPoint( nPtCount, pt) ; + ++ nPtCount ; + } + } + else if ( i == 3 && AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) ) { + // scorro fino alla fine di quel lato + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + vPLEdges.back().AddUPoint( nPtCount, pt) ; + ++ nPtCount ; + } + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) +{ + // questa funzione dà per scontato di stare lavorando sulla root di uno spazio parametrico di cui si sta solamente calcolando + // il Contour. La funzione da chiamare dopo questa è la CreateCellContour. + // i tagli sono sempre delle linee che tagliano da parte a parte la cella, quindi sono curve aperte + if ( m_mTree.size() > 1) + return false ; + int nRoot = -1 ; + for ( int i = 0 ; i < int( vCuts.size()); ++i) { + PolyLine pl = vCuts.at( i) ; + m_mTree.at( nRoot).m_vInters.emplace_back() ; + Point3d pt ; pl.GetFirstPoint( pt) ; + int nEdgeIn ; OnWhichEdge( nRoot, pt, nEdgeIn) ; + m_mTree.at( nRoot).m_vInters.back().nIn = nEdgeIn ; + PNTVECTOR vInters ; + vInters.emplace_back( pt) ; + while ( pl.GetNextPoint( pt)) + vInters.emplace_back( pt) ; + pl.GetLastPoint( pt) ; + int nEdgeOut ; OnWhichEdge( nRoot, pt, nEdgeOut) ; + m_mTree.at( nRoot).m_vInters.back().nOut = nEdgeOut ; + } + // chiamo una funzione per renderli coerenti + AdjustCuts() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::AdjustCuts( void) +{ + // li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR + sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ; + // ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione + bool bPreviousWasStart = m_mTree.at( -1).m_vInters.at(0).bSortedbyStart ; + for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) { + if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) { + reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ; + bPreviousWasStart = m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ; + } + else + bPreviousWasStart = ! m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Tree::CreateCellContour( POLYLINEMATRIX& vPolygons) +{ + // questa funzione è pensata per essere chiamata dopo la AddCutsToRoot, per creare il poligono di un'unica cella a cui sono stati aggiunti dei tagli + if ( m_mTree.size() > 1) + return false ; + int nRoot = -1 ; + // preparo tutto per poter chiamare la createCellPolygon + m_vnLeaves.push_back( nRoot) ; + INTVECTOR vToCheck( (int) m_mTree.at(nRoot).m_vInters.size()) ; + generate_n( vToCheck.begin(), (int) m_mTree.at(nRoot).m_vInters.size(), generator()) ; + int nPoly = 0 ; + INTVECTOR vnParentChunk ; + PolyLine pl ; + pl.AddUPoint(0, m_mTree.at(nRoot).GetTopRight()) ; + pl.AddUPoint(1, m_mTree.at(nRoot).GetTopLeft()) ; + pl.AddUPoint(2, m_mTree.at(nRoot).GetBottomLeft()) ; + pl.AddUPoint(3, m_mTree.at(nRoot).GetBottomRight()) ; + pl.Close() ; + // ora posso creare il poligono della cella con i tagli + while( (int)vToCheck.size() != 0) { + int nPolyBefore = nPoly ; + CreateCellPolygons( 0, vPolygons, vToCheck, nPoly, vnParentChunk, pl) ; + if ( nPolyBefore == nPoly) + break ; + } + return true ; +} \ No newline at end of file diff --git a/Tree.h b/Tree.h index ea60bb6..0ae3288 100644 --- a/Tree.h +++ b/Tree.h @@ -27,11 +27,12 @@ struct Inters { int nOut ; bool bCCW ; int nChunk ; + bool bSortedbyStart ; // riordino le intersezioni per lato in senso antiorario dal top - // se ho pi� intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR + // se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR bool operator < ( Inters& b) { - // trovo in che ordine stanno i due strat, tenendo conto anche della possibilit� che siano vertici + // trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; const auto iter1 = find( vEdges.begin(), vEdges.end(), nIn) ; int nPos1 = std::distance( vEdges.begin(), iter1) ; @@ -52,7 +53,7 @@ struct Inters { pl.Close() ; pl.GetAreaXY( dAreaB) ; } - // se nIn � un vertice sistemo il valore + // se nIn è un vertice sistemo il valore int nEdgeIn = nIn ; if ( nIn > 3) nEdgeIn = nIn - 4 ; @@ -63,6 +64,67 @@ struct Inters { ( bEqIn && nEdgeIn == 2 && vpt[0].x < b.vpt[0].x) || ( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ; } + + static bool FirstEncounter ( Inters& a, Inters& b) + { + // riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima. + // ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso + // nell'intersezione salvo se il taglio è stato ordinato guardando l'ingresso o l'uscita + INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ; + // trovo i lati di ingresso e uscita + const auto iter1 = find( vEdges.begin(), vEdges.end(), a.nIn) ; + int nPos1 = std::distance( vEdges.begin(), iter1) ; + const auto iter2 = find( vEdges.begin(), vEdges.end(), a.nOut) ; + int nPos2 = std::distance( vEdges.begin(), iter2) ; + const auto iter3 = find( vEdges.begin(), vEdges.end(), b.nIn) ; + int nPos3 = std::distance( vEdges.begin(), iter3) ; + const auto iter4 = find( vEdges.begin(), vEdges.end(), b.nOut) ; + int nPos4 = std::distance( vEdges.begin(), iter4) ; + int nFirstA = 0 ; + int nFirstB = 0 ; + // salvo l'indice del primo punto dell'intersezione che ho incontrato scorrendo il bordo da ptTR + // salvo il lato che viene prima confrontando ingresso e uscita + if ( nPos2 < nPos1) { + nPos1 = nPos2 ; + nFirstA = int( a.vpt.size()) ; + } + // se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita + else if ( nPos2 == nPos1 ) { + if ( nPos1 == 0 ) + nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : int( a.vpt.size()) ; + else if ( nPos1 == 1 ) + nFirstA = a.vpt[0].y > a.vpt.back().y ? 0 : int( a.vpt.size()) ; + else if ( nPos1 == 2 ) + nFirstA = a.vpt[0].x < a.vpt.back().x ? 0 : int( a.vpt.size()) ; + else if ( nPos1 == 3 ) + nFirstA = a.vpt[0].y < a.vpt.back().y ? 0 : int( a.vpt.size()) ; + } + if ( nPos4 < nPos3) { + nPos3 = nPos4 ; + nFirstB = int( b.vpt.size()) ; + } + else if ( nPos4 == nPos3 ) { + if ( nPos3 == 0 ) + nFirstB = b.vpt[0].x > b.vpt.back().x ? 0 : int( b.vpt.size()) ; + else if ( nPos3 == 1 ) + nFirstB = b.vpt[0].y > b.vpt.back().y ? 0 : int( b.vpt.size()) ; + else if ( nPos3 == 2 ) + nFirstB = b.vpt[0].x < b.vpt.back().x ? 0 : int( b.vpt.size()) ; + else if ( nPos3 == 3 ) + nFirstB = b.vpt[0].y < b.vpt.back().y ? 0 : int( b.vpt.size()) ; + } + a.bSortedbyStart = nFirstA == 0 ; + b.bSortedbyStart = nFirstB == 0 ; + // se sono diversi ritorno il confronto + if ( nPos1 != nPos3) + return nPos1 < nPos3 ; + // se sono uguali devo valutare il punto di intersezione + return ( nPos1 == 0 && a.vpt[nFirstA].x > b.vpt[nFirstB].x) || + ( nPos1 == 1 && a.vpt[nFirstA].y > b.vpt[nFirstB].y) || + ( nPos1 == 2 && a.vpt[nFirstA].x < b.vpt[nFirstB].x) || + ( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ; + } + bool operator == ( Inters& b) { return AreSamePointExact( vpt[0], b.vpt[0]) ; @@ -73,8 +135,8 @@ struct Inters { } } ; // nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario -// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da l� in senso antiorario -// -1 se la curva � sempre dentro la cella +// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario +// -1 se la curva è sempre dentro la cella //---------------------------------------------------------------------------- class Cell @@ -116,6 +178,10 @@ class Cell { return m_ptPbl ; } Point3d GetTopRight( void) const { return m_ptPtr ; } + Point3d GetTopLeft( void) const + { return Point3d( m_ptPbl.x, m_ptPtr.y) ; } + Point3d GetBottomRight( void) const + { return Point3d( m_ptPtr.x, m_ptPbl.y); } double GetSplitValue( void) const { return m_dSplit ; } bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, senn� orizzontalmente @@ -138,24 +204,24 @@ class Cell int m_nLeft ; // cella adiacente al lato left int m_nRight ; // cella adiacente al lato right int m_nParent ; // cella genitore - int m_nDepth ; // profondit� della cella rispetto a root - double m_dSplit ; // parametro a cui � stata splittata la cella + int m_nDepth ; // profondità della cella rispetto a root + double m_dSplit ; // parametro a cui è stata splittata la cella int m_nChild1 ; // prima cella figlio int m_nChild2 ; // seconda cella figlio int m_nFlag ; // falg che indica la caratterizzazione della cella rispetto ai loop di trim // 0 esterna, 1 intersecata, 2 contiene un loop, 3 intersecata e contenente un loop, 4 contenuta in un loop - int m_nFlag2 ; // falg che indica se la cella � stata attraversata durante l'ultima fase del labelling - int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 met� e met� - bool m_bOnLeftEdge ; // flag che indica se la cella � sul lato sinistro ( per superfici chiuse sul parametro U) - bool m_bOnTopEdge ; // flag che indica se la cella � sul lato top ( per superfici chiuse sul parametro V) + int m_nFlag2 ; // falg che indica se la cella è stata attraversata durante l'ultima fase del labelling + int m_nRightEdgeIn ; // 0 right edge fuori, 1 right edge dentro, 2 metà e metà + bool m_bOnLeftEdge ; // flag che indica se la cella è sul lato sinistro ( per superfici chiuse sul parametro U) + bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V) std::vector m_vInters ; // vettore delle intersezioni della cella con i loop di trim - // ogni elemento del vettore � l'insieme dei punti che caratterizza un atrtaversamento della cella + // ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella private : Point3d m_ptPbl ; // punto bottom left Point3d m_ptPtr ; // punto top right - bool m_bProcessed ; // flag che indica se la cella � stata processata - bool m_bSplitVert ; // flag che indica in quale direzione � stata divisa la cella + bool m_bProcessed ; // flag che indica se la cella è stata processata + bool m_bSplitVert ; // flag che indica in quale direzione è stata divisa la cella } ; //---------------------------------------------------------------------------- @@ -165,16 +231,21 @@ class Tree ~Tree( void) ; Tree( void) ; Tree ( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; + Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno void SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ; bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini) bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax � il massimo per la dimensione maggiore di un triangolo della trimesh // dSideMin � lunghezza minima del lato di una cella nello spazio reale bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; bool GetPolygons( POLYLINEMATRIX& vPolygons) ; - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero + bool GetEdge3D ( POLYLINEVECTOR& vPLEdges) ; // restituisce gli edge 3D come curve composite void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell + // funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico + bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree + bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli private : bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert @@ -205,6 +276,8 @@ class Tree bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata) bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL + bool AdjustCuts( void) ; + private : const SurfBezier* m_pSrfBz ; // superficie di bezier From 156d0eea4b6d4cb675a9c348481d50349db53d60 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 22 Feb 2024 17:39:44 +0100 Subject: [PATCH 08/31] EgtGeomKernel : - corretta e migliorata la fuzione di cut per superfici di Bezier. Manca : - da migliorare i tagli multipli alle superfici di Bezier. --- SurfBezier.cpp | 425 +++++++++++++++++++++++++++++++++++++++---------- SurfBezier.h | 6 +- Tree.cpp | 159 ++++++++++++++---- Tree.h | 28 ++-- 4 files changed, 491 insertions(+), 127 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index e8326a5..ee91115 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -45,7 +45,7 @@ GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ; //---------------------------------------------------------------------------- SurfBezier::SurfBezier( void) : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false), - m_bTrimmed( false), m_pTrimReg( nullptr), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} + m_bTrimmed( false), m_bClosedU( false), m_bClosedV( false), m_pTrimReg(nullptr), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { } @@ -138,6 +138,8 @@ SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) bool SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtract) { + // controllo se aveo trim precedenti ed eventualmente faccio un'intersezione con lo spazio esistente + // verifico la regione passata if ( &sfrTrimReg == nullptr || ! sfrTrimReg.IsValid()) return false ; @@ -157,11 +159,14 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac return false ; } ResetAuxSurf() ; - delete m_pSTM ; // assegno la regione di trim m_bTrimmed = true ; - delete m_pTrimReg ; - m_pTrimReg = GetBasicSurfFlatRegion( Release( pSfrTrim)) ; + if ( m_pTrimReg != nullptr ) { + if ( ! m_pTrimReg->Intersect( *pSfrTrim)) + return false ; + } + else + m_pTrimReg = GetBasicSurfFlatRegion( Release( pSfrTrim)) ; return true ; } @@ -1441,7 +1446,7 @@ SurfBezier::GetAuxSurf( void) const ResetAuxSurf() ; return nullptr ; } - // se gi� calcolata, la restituisco + // se già calcolata, la restituisco if ( m_pSTM != nullptr) return m_pSTM ; @@ -1475,8 +1480,22 @@ SurfBezier::GetAuxSurf( void) const //} //// per usare i polygon basic/////////////////// + + /////////////////// così facendo sto recuperando gli Edge e la chiususra solo dell'ULTIMO TREE analizzato!!!!! (in caso di trim che creano più chunk analizzo più tree separatamente)/////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // aggiorno la chiusura della superficie + m_bClosedU = Tree.IsClosedU() ; + m_bClosedV = Tree.IsClosedV() ; + m_vbPole = Tree.GetPoles() ; + // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - Tree.GetEdge3D( m_vPLEdges) ; + POLYLINEVECTOR vPLEdges ; + Tree.GetEdge3D( vPLEdges) ; + for ( int i= 0 ; i < int( vPLEdges.size()); ++i) { + m_vCCEdge.emplace_back( CreateBasicCurveComposite()) ; + m_vCCEdge.back()->FromPolyLine( vPLEdges[i]) ; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // qui non sarebbe male stampare un messaggio di errore nel log se avevo un'area da disegnare ma non sono usciti dei poligoni if ( int(vvPL.size()) == 0) @@ -1582,7 +1601,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const return nullptr ; pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi - for ( int i = 1 ; i < int( pCC->GetCurveCount()) ; ++i) { + for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; pCrv->GetEndPoint( pt3D) ; DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ; @@ -1596,6 +1615,37 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const return Release( pCC2D) ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler) +{ + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando + double dCrvLen ; + if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) + return true ; + // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene + Point3d ptStart, ptEnd ; + if ( pCrvCompo->GetStartPoint( ptStart) && + pCrvCompo->GetEndPoint( ptEnd) && + AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) && + ! AreSamePointApprox( ptStart, ptEnd)) { + // porto il punto finale a coincidere esattamente con l'inizio + pCrvCompo->ModifyEnd( ptStart) ; + } + // unisco segmenti allineati + pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; + + // porto la curva nello spazio parametrico + PtrOwner pCC( UnprojectCurveFromStm( pCrvCompo)) ; + + // le curve aperte le tengo da parte per giuntarle alla fine col bordo + if ( ! pCC->IsClosed()) + vpCCOpen.emplace_back( Release( pCC)) ; + // le curve chiuse le metto tutte insieme subito + else + vpCCClosed.emplace_back( Release( pCC)) ; + return true ; +} //---------------------------------------------------------------------------- bool @@ -1609,13 +1659,17 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; + // con queste righe funzionano anche i tagli multipli//////////////////////////////////////////////// + bool bMod = false ; + // ATTENZIONE!!!!! ad ogni "return false" in questa funzione dovrei reimpostare "m_bTrimmed = true" se bMod == true/////////////////////////////////////////////////// + if ( m_bTrimmed) { + m_bTrimmed = false ; + ResetAuxSurf() ; + bMod = true ; + } + ////i tagli multipli//////////////////////////////////////////////// IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; - // recupero la superficie di trim a cui devo aggiungere tutt i nuovi loop di trim - PtrOwner sfrTrimReg ( GetTrimRegion()) ; - if ( IsNull( sfrTrimReg)) - sfrTrimReg.Set( CreateBasicSurfFlatRegion()) ; - // concateno le curve 3d ChainCurves chainC ; double dToler = EPS_SMALL ; @@ -1631,13 +1685,14 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // recupero i percorsi concatenati Point3d ptNear = ( vBPnt.empty() ? ORIG : vBPnt[0].first) ; INTVECTOR vId ; - // Devo controllare se i trim intersecano il bordo dello spazio parametrico ed eventualmente spezzare le curve di trim in 2D tenendo conto della periodicità - // costruisco le curveCompo che rappresetano gli edge - ICRVCOMPOPVECTOR vCCEdge ; - for ( int i= 0 ; i < int( m_vPLEdges.size()); ++i) { - vCCEdge.emplace_back() ; - vCCEdge.back()->FromPolyLine( m_vPLEdges[i]) ; - } + + // debug///////////////////////////////////////////////////////// + //vector vGeoObj ; + //vGeoObj.push_back( static_cast(vCCEdge[1])) ; + //vGeoObj.push_back( static_cast(vCCEdge[3])) ; + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_3d_edges.nge") ; + // debug///////////////////////////////////////////////////////// + // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; @@ -1648,10 +1703,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita bool bAdded = true ; + bool bPrevLineThroughEdge = false ; for ( int i = 0 ; i < int( vId.size()) ; ++ i) { // creo un segmento di retta - PtrOwner pLine( CreateCurveLine()) ; - if ( IsNull( pLine)) + ICurveLine* pLine( CreateCurveLine()) ; + if ( pLine == nullptr) return false ; // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) int nInd = abs( vId[i]) - 1 ; @@ -1659,37 +1715,79 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) Point3d ptEnd = vBPnt[nInd].second ; // provo ad accodarlo alla composita bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && - pLine->Set( ptStart, ptEnd) && - pCrvCompo->AddCurve( Release( pLine), true, dToler)) ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - } - // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando - double dCrvLen ; - if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) - continue ; - // se curva chiusa entro 5 volte la tolleranza ma considerata aperta, la chiudo bene - Point3d ptStart, ptEnd ; - if ( pCrvCompo->GetStartPoint( ptStart) && - pCrvCompo->GetEndPoint( ptEnd) && - AreSamePointEpsilon( ptStart, ptEnd, 5. * dToler) && - ! AreSamePointApprox( ptStart, ptEnd)) { - // porto il punto finale a coincidere esattamente con l'inizio - pCrvCompo->ModifyEnd( ptStart) ; - } - // assegno estrusione come direzione normale al piano - pCrvCompo->SetExtrusion( plPlane.GetVersN()) ; - // unisco segmenti allineati - pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; + pLine->Set( ptStart, ptEnd)) ; + // se la superficie è chiusa devo controllare se sto attraversando un edge con un trim + if ( (m_bClosedU || m_bClosedV) && ! bPrevLineThroughEdge) { + IntersCurveCurve icc0( *pLine, *m_vCCEdge[0]) ; + IntersCurveCurve icc1( *pLine, *m_vCCEdge[1]) ; + IntersCurveCurve icc2( *pLine, *m_vCCEdge[2]) ; + IntersCurveCurve icc3( *pLine, *m_vCCEdge[3]) ; + // se non ho intersezioni proseguo aggiungendo il punto + if ( icc0.GetIntersCount() == 0 && + icc1.GetIntersCount() == 0 && + icc2.GetIntersCount() == 0 && + icc3.GetIntersCount() == 0) { + // se non ho intersezioni con gli edge posso aggiungere semplicemente alla compo + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + else { + // recupero la prima intersezione che trovo + // se ho intersezioni multiple è perché sono edge sovrapposti + IntCrvCrvInfo iccInfo ; + if ( icc0.GetIntersCount() != 0) + icc0.GetIntCrvCrvInfo( 0, iccInfo) ; + else if ( icc1.GetIntersCount() != 0) + icc1.GetIntCrvCrvInfo( 0, iccInfo) ; + else if ( icc2.GetIntersCount() != 0) + icc2.GetIntCrvCrvInfo( 0, iccInfo) ; + else if ( icc3.GetIntersCount() != 0) + icc3.GetIntCrvCrvInfo( 0, iccInfo) ; - // porto la curva nello spazio parametrico - PtrOwner pCC( UnprojectCurveFromStm( pCrvCompo)) ; - - // le curve aperte le tengo da parte per giuntarle alla fine col bordo - if ( ! pCC->IsClosed()) - vpCCOpen.emplace_back( Release( pCC)) ; - // le curve chiuse le metto tutte insieme subito - else - vpCCClosed.emplace_back( Release( pCC)) ; // da controllare che funzioni anche se passo i loop con orientamenti sbagliati////////// + ICurveLine* pCLPart1 ( CreateCurveLine()) ; + // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root + Vector3d vtDir ; pLine->GetStartDir( vtDir) ; + Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; + pCLPart1->Set( ptStart, ptBeforeTheEdge) ; + pCrvCompo->AddCurve( pCLPart1, true, dToler) ; + bAdded = false ; + AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; + pCrvCompo->Clear() ; + // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato + // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject + //ICurveLine* pCLPart2 ( CreateCurveLine()) ; + Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; + //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; + //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; + ptNear = ptBeyondTheEdge ; + bPrevLineThroughEdge = true ; + } + } + // sennò procedo normalmente aggiungendo il punto + else { + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + bPrevLineThroughEdge = false ; + } + } + AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; + } + ////debug + //vector vGeoObj ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + ////debug + if ( int( vpCCOpen.size()) != 0) { + // devo verificare se devo giuntare la prima curva aperta con l'ultima + Point3d ptStartOpen, ptEndOpen ; + vpCCOpen.front()->GetStartPoint( ptStartOpen) ; + vpCCOpen.back()->GetEndPoint( ptEndOpen) ; + if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { + vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; + Release( vpCCOpen[0]) ; + vpCCOpen.erase( vpCCOpen.begin()) ; + } } // creo il nuovo bordo usando i loop aperti @@ -1703,6 +1801,15 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vPL.emplace_back( pl) ; } Tree.AddCutsToRoot( vPL) ; + ////debug + //vector vGeoObj ; + //for ( int k = 0 ; k < int( vPL.size()) ; ++ k) { + // PtrOwner pCrv( CreateCurveComposite()) ; + // pCrv->FromPolyLine( vPL[k]) ; + // vGeoObj.emplace_back( static_cast(Release( pCrv))) ; + //} + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ; + ////debug Tree.CreateCellContour( vPolygons) ; } @@ -1729,6 +1836,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) for ( int j = 0 ; j < int( vPolygons[i].size()); ++j) { PtrOwner pCC( CreateCurveComposite()) ; pCC->FromPolyLine( vPolygons[i][j]) ; + ////debug + //PtrOwner pCrvCopy( pCC->Clone()) ; + //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_trim_curve2D.nge") ; + ////debug sfrContour.AddCurve( Release( pCC)) ; } } @@ -1771,19 +1882,29 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // aggiorno la superficie di trim Point3d ptStart ; - Vector3d vtDir ; + Vector3d vtDir, vtDirS, vtDirE ; PtrOwner pCrv( pSFR->GetLoop( nChunkMin, nLoopMin)) ; pCrv->GetStartPoint( ptStart) ; - pCrv->GetStartDir( vtDir) ; - vtDir.Rotate( Z_AX, bPos? 90 : -90) ; + pCrv->GetStartDir( vtDirS) ; + pCrv->GetEndDir( vtDirE) ; + //vtDirS.Rotate( Z_AX, bPos? 90 : -90) ; + vtDir = vtDirS + vtDirE ; PtrOwner pCL( CreateCurveLine()) ; - pCL->SetPVL( ptStart, vtDir, 1e6) ; - IntersCurveCurve icc( *Release( pCL), *Release(pCrv)) ; - // verifico di guardare verso l'interno ( il numero di intersezioni deve essere pari visto che partivo da un punto sulla curva) - if ( icc.GetIntersCount()%2 != 0) - return false ; // o sennò un altro tentativo prima di rinunciare + pCL->SetPVL( ptStart, vtDirS, 1e6) ; + IntersCurveCurve icc( *pCL, *pCrv) ; IntCrvCrvInfo iccInfo ; - icc.GetIntCrvCrvInfo( 1, iccInfo) ; + // verifico di guardare verso l'interno ( il numero di intersezioni deve essere pari visto che partivo da un punto sulla curva) + if ( icc.GetIntersCount()%2 != 0) { + vtDir = vtDirS - vtDirE ; + PtrOwner pCL2( CreateCurveLine()) ; pCL2->SetPVL( ptStart, vtDir, 1e6) ; + IntersCurveCurve icc2( *pCL2, *pCrv) ; + if ( icc2.GetIntersCount()%2 != 0) + return false ; + icc2.GetIntCrvCrvInfo( 1, iccInfo) ; + } + else + icc.GetIntCrvCrvInfo( 1, iccInfo) ; + Point3d ptI = iccInfo.IciA[0].ptI ; Point3d ptToCheck = ( ptStart + ptI) / 2 ; Point3d pt3D ; GetPointD1D2( ptToCheck.x / SBZ_TREG_COEFF, ptToCheck.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; @@ -1793,12 +1914,20 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW + //debug PtrOwner pSrfFR_Copy( pSFR->Clone()) ; SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) - SetTrimRegion( *Release( pSFR), false) ; - else - SetTrimRegion( *Release( pSFR)) ; + //debug + + // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente + if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { + if ( ! SetTrimRegion( *pSFR, false) || ! m_pTrimReg->IsValid()) + return false ; + } + else { + if ( ! SetTrimRegion( *pSFR) || ! m_pTrimReg->IsValid()) + return false ; + } return true ; } @@ -1812,40 +1941,168 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // recupero i dati dei vertici del triangolo che fa intersezione int nVert[3] ; pSurfTm->GetTriangle( nT, nVert) ; - double dU0, dV0, dU1, dV1,dU2, dV2 ; - pSurfTm->GetVertexParam( nVert[0], dU0, dV0) ; - pSurfTm->GetVertexParam( nVert[1], dU1, dV1) ; - pSurfTm->GetVertexParam( nVert[2], dU2, dV2) ; - Point3d pt0, pt1, pt2 ; - pSurfTm->GetVertex( nVert[0], pt0) ; - pSurfTm->GetVertex( nVert[1], pt1) ; - pSurfTm->GetVertex( nVert[2], pt2) ; + PNTVECTOR vPtPa(3) ; + pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; + pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; + pSurfTm->GetVertexParam( nVert[2], vPtPa[2].x,vPtPa[2].y) ; + PNTVECTOR vPT(3) ; + pSurfTm->GetVertex( nVert[0], vPT[0]) ; + pSurfTm->GetVertex( nVert[1], vPT[1]) ; + pSurfTm->GetVertex( nVert[2], vPT[2]) ; + // se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici + if ( m_bClosedU || m_bClosedV) { + double dParamH = m_nSpanV * SBZ_TREG_COEFF ; + double dParamL = m_nSpanU * SBZ_TREG_COEFF ; + // devo trovare il lato più lungo e confrontarlo con le dimensioni dello spazio parametrico + Vector3d vtDir ; + double dDist ; + if ( DistXY( vPtPa[0], vPtPa[1]) > DistXY( vPtPa[1], vPtPa[2]) && DistXY( vPtPa[0], vPtPa[1]) > Dist( vPtPa[0], vPtPa[2])){ + vtDir = vPtPa[1] - vPtPa[0] ; + dDist = DistXY( vPtPa[0], vPtPa[1]) ; + } + else if ( DistXY( vPtPa[1], vPtPa[2]) > DistXY( vPtPa[0], vPtPa[1]) && DistXY( vPtPa[1], vPtPa[2]) > Dist( vPtPa[0], vPtPa[2])){ + vtDir = vPtPa[2] - vPtPa[1] ; + dDist = DistXY( vPtPa[1], vPtPa[2]) ; + } + else if ( DistXY( vPtPa[0], vPtPa[2]) > DistXY( vPtPa[0], vPtPa[1]) && DistXY( vPtPa[0], vPtPa[2]) > Dist( vPtPa[1], vPtPa[2])){ + vtDir = vPtPa[2] - vPtPa[0] ; + dDist = DistXY( vPtPa[0], vPtPa[2]) ; + } + vtDir.Normalize() ; + // se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice + // siano da correggere per periodicità + if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.95 ) { + // trovo se dei punti del triangolo sono sul bordo dello spazio parametrico + BOOLVECTOR vbOn(3) ; + for ( int p = 0 ; p < 3; ++p ) { + if ( m_vCCEdge[1]->IsAPoint()) { + Point3d pt ; + m_vCCEdge[1]->GetStartPoint( pt) ; + vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] =m_vCCEdge[1]->IsPointOn( vPT[p]) ; + if ( m_vCCEdge[3]->IsAPoint()) { + Point3d pt ; + m_vCCEdge[3]->GetStartPoint( pt) ; + vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] =m_vCCEdge[3]->IsPointOn( vPT[p]) ; + } + // controllo che almeno un punto sia su un edge + if ( vbOn[0] || vbOn[1] || vbOn[2]) { + double dRightX ; + // tengo per buone le coordinate dei punti che NON sono sul bordo dello spazio parametrico + for ( int p = 0 ; p < 3; ++p) { + if ( !vbOn[p] ) { + dRightX = vPtPa[p].x ; + break ; + } + } + for ( int p = 0 ; p < 3; ++p) { + if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) { + if ( vPtPa[p].x < EPS_SMALL) + vPtPa[p].x = dParamL ; + else + vPtPa[p].x = 0 ; + } + } + } + } + else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.95) { + BOOLVECTOR vbOn(3) ; + for ( int p = 0 ; p < 3; ++p ) { + if ( m_vCCEdge[0]->IsAPoint()) { + Point3d pt ; + m_vCCEdge[0]->GetStartPoint( pt) ; + vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] =m_vCCEdge[0]->IsPointOn( vPT[p]) ; + if ( m_vCCEdge[2]->IsAPoint()) { + Point3d pt ; + m_vCCEdge[2]->GetStartPoint( pt) ; + vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] =m_vCCEdge[2]->IsPointOn( vPT[p]) ; + } + // controllo che almeno un punto sia su un edge + if ( vbOn[0] || vbOn[1] || vbOn[2]) { + double dRightY ; + // tengo per buone le coordinate dei punti che NON sono sul bordo dello spazio parametrico + for ( int p = 0 ; p < 3; ++p) { + if ( ! vbOn[p]) { + dRightY = vPtPa[p].y ; + break ; + } + } + for ( int p = 0 ; p < 3; ++p) { + if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) { + if ( vPtPa[p].y < EPS_SMALL) + vPtPa[p].y = dParamH ; + else + vPtPa[p].y = 0 ; + } + } + } + } + } + // devo anche tener conto della possibilità che i lati siano collassati in poli + //if ( m_vbPole[0]) + // ; // se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice if ( nIL == 3 ) { - if ( AreSamePointApprox(ptI, pt0)) - ptSP.Set( dU0, dV0, 0) ; - else if ( AreSamePointApprox(ptI, pt1)) - ptSP.Set( dU1, dV1, 0) ; - else if ( AreSamePointApprox(ptI, pt2)) - ptSP.Set( dU2, dV2, 0) ; + if ( AreSamePointApprox(ptI, vPT[0])) + ptSP = vPtPa[0] ; + else if ( AreSamePointApprox(ptI, vPT[1])) + ptSP = vPtPa[1] ; + else if ( AreSamePointApprox(ptI, vPT[2])) + ptSP = vPtPa[2] ; return true ; } // calcolo approssimativamente le coordinate nello spazio parametrico del punto di intersezione // quindi prima calcolo la composizione lineare tra i vertici del triangolo per ottenere il punto di intersezione Eigen::Matrix3d mA ; - mA.col(0) << pt0.x, pt0.y , pt0.z ; - mA.col(1) << pt1.x, pt1.y , pt1.z ; - mA.col(2) << pt2.x, pt2.y , pt2.z ; + mA.col(0) << vPT[0].x, vPT[0].y , vPT[0].z ; + mA.col(1) << vPT[1].x, vPT[1].y , vPT[1].z ; + mA.col(2) << vPT[2].x, vPT[2].y , vPT[2].z ; Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; Eigen::Vector3d x = mA.fullPivLu().solve(b) ; // applico questa composizione alle loro coordinate parametriche Eigen::Matrix3d mB ; - mB.col(0) << dU0, dV0, 0 ; - mB.col(1) << dU1, dV1, 0 ; - mB.col(2) << dU2, dV2, 0 ; + mB.col(0) << vPtPa[0].x, vPtPa[0].y, 0 ; + mB.col(1) << vPtPa[1].x, vPtPa[1].y, 0 ; + mB.col(2) << vPtPa[2].x, vPtPa[2].y, 0 ; Eigen::Vector3d ptParam = mB * x ; ptSP.x = ptParam.x() ; ptSP.y = ptParam.y() ; + // controllo se le coordinate sono nello spazio parametrico ed eventualmente se posso sistemarle tenendo conto della periodicità ( se la superficie è chiusa) + if ( ptSP.x < 0) { + if ( m_bClosedU) + ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; + else + ptSP.x = 0 ; + } + if ( ptSP.x > m_nSpanU * SBZ_TREG_COEFF ) { + if ( m_bClosedU) + ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; + else + ptSP.x = m_nSpanU * SBZ_TREG_COEFF ; + } + if ( ptSP.y < 0 ) { + if ( m_bClosedV) + ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; + else + ptSP.y = 0 ; + } + if ( ptSP.y > m_nSpanV * SBZ_TREG_COEFF ) { + if ( m_bClosedU) + ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; + else + ptSP.y = m_nSpanV * SBZ_TREG_COEFF ; + } return true ; } diff --git a/SurfBezier.h b/SurfBezier.h index 7e150f4..6e2ae77 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -163,6 +163,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; double GetCurveOnUApproxLen( double dV) const ; double GetCurveOnVApproxLen( double dU) const ; + bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL) ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -174,12 +175,15 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW int m_nSpanV ; // numero di pezze in V bool m_bRat ; // flag di razionale/polinomiale bool m_bTrimmed ; // flag per presenza regione di trim + mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U + mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V + mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei - mutable POLYLINEVECTOR m_vPLEdges ; // vettore delle polyline degli edge nello spazio 3D + mutable ICRVCOMPOPVECTOR m_vCCEdge ;// vettore delle curve compo degli edge nello spazio 3D } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index 2c63934..5c895b7 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -30,7 +30,8 @@ using namespace std ; //---------------------------------------------------------------------------- Tree::Tree( void) - : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}), + m_bSplitPatches( true), m_bTestMode( false) { Point3d ptBl( 0, 0), ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ; Cell cRoot( ptBl, ptTr) ; @@ -39,7 +40,8 @@ Tree::Tree( void) //---------------------------------------------------------------------------- Tree::Tree( const SurfBezier* pSrfBz, const bool bSplitPatches, const Point3d& ptMin, const Point3d& ptMax) - : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}), + m_bSplitPatches( true), m_bTestMode( false) { SetSurf( pSrfBz, bSplitPatches, ptMin, ptMax) ; } @@ -51,7 +53,8 @@ Tree::~Tree( void) //---------------------------------------------------------------------------- Tree::Tree( const Point3d ptBl, const Point3d ptTr) - : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_bSplitPatches( true), m_bTestMode( false) + : m_pSrfBz( nullptr), m_bTrimmed( false), m_bBilinear( false), m_bMulti( false), m_bClosedU( false), m_bClosedV( false), m_vbPole( { false, false, false, false}), + m_bSplitPatches( true), m_bTestMode( false) { Cell cRoot( ptBl, ptTr) ; m_mTree.insert( pair< int, Cell>( -1, cRoot)) ; @@ -227,16 +230,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi // devo controllare se i punti ai parametri U=0 e U=1 sono tutti coincidenti // in caso devo fare uno split nell'altra direzione bool bOk = false ; - bool bCapped0 = true, bCapped1 = true ; - Point3d ptV0, ptV1 ; - // controllo se tutti i punti sull'isoparametrica sono uguali + bool bPole0 = true, bPole1 = true ; + Point3d ptU0, ptU1 ; + // controllo se tutti i punti di controllo sull'isoparametrica sono uguali for ( int i = 1 ; i < nDegV * nSpanV + 1 ; ++ i) { - ptV0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ; - bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptV0) ; - ptV1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ; - bCapped1 = bCapped1 && AreSamePointApprox( ptP10, ptV1) ; + ptU0 = m_pSrfBz->GetControlPoint( i * ( nDegU * nSpanU + 1), &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ; + ptU1 = m_pSrfBz->GetControlPoint( ( i + 1) * ( nDegU * nSpanU + 1) - 1, &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ; } - if ( bCapped0 && bCapped1) { + m_vbPole[1] = bPole0 ; + m_vbPole[3] = bPole1 ; + if ( bPole0 && bPole1) { m_mTree[0].SetSplitDirVert( true) ; Split( 0) ; m_mTree[1].SetSplitDirVert( true) ; @@ -256,16 +261,18 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi // devo controllare se i punti ai parametri V=0 e V=1 sono tutti coincidenti // in caso devo fare uno split nell'altra direzione bool bOk = false ; - bool bCapped0 = true, bCapped1 = true ; - Point3d ptU0, ptU1 ; + bool bPole0 = true, bPole1 = true ; + Point3d ptV0, ptV1 ; // controllo se tutti i punti sull'isoparametrica sono uguali for ( int i = 1 ; i < nDegU * nSpanU + 1 ; ++ i) { - ptU0 = m_pSrfBz->GetControlPoint( i, &bOk) ; - bCapped0 = bCapped0 && AreSamePointApprox( ptP00, ptU0) ; - ptU1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; - bCapped1 = bCapped1 && AreSamePointApprox( ptP01, ptU1) ; + ptV0 = m_pSrfBz->GetControlPoint( i, &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; + ptV1 = m_pSrfBz->GetControlPoint( i + ( nDegU * nSpanU + 1) * ( nDegV * nSpanV), &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; } - if ( bCapped0 && bCapped1) { + m_vbPole[0] = bPole0 ; + m_vbPole[3] = bPole1 ; + if ( bPole0 && bPole1) { m_mTree[0].SetSplitDirVert( false) ; Split( 0) ; m_mTree[1].SetSplitDirVert( false) ; @@ -1434,12 +1441,13 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) //---------------------------------------------------------------------------- bool -Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells) +Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells) { // condizioni per il calcolo dei poligoni di base if ( m_vPolygons.empty() || // se non li ho mai calcolati ( ! m_vPolygons.empty() && ! vCells.empty()) || // se ho già calcolato dei poligoni ma ne sto chiedendo di un altro gruppo di celle ( vCells.empty() && m_vPolygons.size() != m_vnLeaves.size())) { // se sto chiedendo i poligoni di tutte le celle, ma i poligoni già calcolati sono meno delle celle + m_vPolygons.clear() ; // se non ho dato un elenco di celle in input do per scontato che la chiamata sia per calcolare i poligoni di tutte le foglie if ( vCells.empty()) vCells = m_vnLeaves ; @@ -1463,6 +1471,7 @@ Tree::GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells) bool bBottomRight , bTopLeft ; // scorro lungo tutte le celle leaves e oltre agli angoli della cella aggiungo alla polyline della cella anche i vertici, delle celle adiacenti, // che sono sui lati della cella corrente + // N.B. :i poligoni sono costruiti a partire dal ptBL !!! for ( int nId : vCells) { vVertices.clear() ; vNeigh.clear() ; @@ -3582,34 +3591,64 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) // scorro sui poligoni delle celle di un lato for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; + Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato - if ( i == 0 && AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) ) { + if ( i == 0) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; + ++ nPtCount ; // scorro fino alla fine di quel lato - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ; + ++ nPtCount ; } - else if ( i == 1 && AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) ) { + else if ( i == 1 ) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; + ++ nPtCount ; // scorro fino alla fine di quel lato - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { vPLEdges.back().AddUPoint( nPtCount, pt) ; ++ nPtCount ; } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; + ++ nPtCount ; } - else if ( i == 2 && AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) ) { + else if ( i == 2) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; + ++ nPtCount ; // scorro fino alla fine di quel lato - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { vPLEdges.back().AddUPoint( nPtCount, pt) ; ++ nPtCount ; } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; + ++ nPtCount ; } - else if ( i == 3 && AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) ) { + else if ( i == 3) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; + ++ nPtCount ; // scorro fino alla fine di quel lato - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { vPLEdges.back().AddUPoint( nPtCount, pt) ; ++ nPtCount ; } + vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; + ++ nPtCount ; } } } @@ -3631,14 +3670,69 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) PolyLine pl = vCuts.at( i) ; m_mTree.at( nRoot).m_vInters.emplace_back() ; Point3d pt ; pl.GetFirstPoint( pt) ; - int nEdgeIn ; OnWhichEdge( nRoot, pt, nEdgeIn) ; + int nEdgeIn ; + // se non trovo il primo punto esattamente su un lato, estendo il primo tratto della polyline all'inditro finchè trovo un'intersezione con un lato + // questa intersezione diventa il nuovo primo punto del vettore intersezione + if ( ! OnWhichEdge(nRoot, pt, nEdgeIn) ) { + Point3d ptSecond ; pl.GetNextPoint( ptSecond) ; + PtrOwner pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecond, pt - ptSecond, 1e6) ; + PtrOwner pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ; + PtrOwner pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ; + PtrOwner pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ; + PtrOwner pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ; + IntersCurveCurve icc0( *pCL, *pCL0) ; + IntersCurveCurve icc1( *pCL, *pCL1) ; + IntersCurveCurve icc2( *pCL, *pCL2) ; + IntersCurveCurve icc3( *pCL, *pCL3) ; + IntCrvCrvInfo iccInfo ; + if (icc0.GetCrossIntersCount() != 0) + icc0.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc1.GetCrossIntersCount() != 0) + icc1.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc2.GetCrossIntersCount() != 0) + icc2.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc3.GetCrossIntersCount() != 0) + icc3.GetIntCrvCrvInfo( 0, iccInfo) ; + pt = iccInfo.IciA[0].ptI ; + if ( ! OnWhichEdge(nRoot, pt, nEdgeIn)) + return false ; + } m_mTree.at( nRoot).m_vInters.back().nIn = nEdgeIn ; PNTVECTOR vInters ; vInters.emplace_back( pt) ; while ( pl.GetNextPoint( pt)) vInters.emplace_back( pt) ; pl.GetLastPoint( pt) ; - int nEdgeOut ; OnWhichEdge( nRoot, pt, nEdgeOut) ; + int nEdgeOut ; + // se non trovo l'ultimo punto esattamente su un lato, estendo l'ultimo tratto della polyline in avnti finchè trovo un'intersezione con un lato + // questa intersezione diventa il nuovo ultimo punto del vettore intersezione + if ( ! OnWhichEdge(nRoot, pt, nEdgeOut) ) { + Point3d ptSecondToLast ; pl.GetNextPoint( ptSecondToLast) ; + PtrOwner pCL( CreateCurveLine()) ; pCL->SetPVL( ptSecondToLast, pt - ptSecondToLast, 1e6) ; + PtrOwner pCL0( CreateCurveLine()) ; pCL0->Set( m_mTree.at(-1).GetTopRight(), m_mTree.at(-1).GetTopLeft()) ; + PtrOwner pCL1( CreateCurveLine()) ; pCL1->Set( m_mTree.at(-1).GetTopLeft(), m_mTree.at(-1).GetBottomLeft()) ; + PtrOwner pCL2( CreateCurveLine()) ; pCL2->Set( m_mTree.at(-1).GetBottomLeft(), m_mTree.at(-1).GetBottomRight()) ; + PtrOwner pCL3( CreateCurveLine()) ; pCL3->Set( m_mTree.at(-1).GetBottomRight(), m_mTree.at(-1).GetTopRight()) ; + IntersCurveCurve icc0( *pCL, *pCL0) ; + IntersCurveCurve icc1( *pCL, *pCL1) ; + IntersCurveCurve icc2( *pCL, *pCL2) ; + IntersCurveCurve icc3( *pCL, *pCL3) ; + IntCrvCrvInfo iccInfo ; + if (icc0.GetCrossIntersCount() != 0) + icc0.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc1.GetCrossIntersCount() != 0) + icc1.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc2.GetCrossIntersCount() != 0) + icc2.GetIntCrvCrvInfo( 0, iccInfo) ; + else if (icc3.GetCrossIntersCount() != 0) + icc3.GetIntCrvCrvInfo( 0, iccInfo) ; + pt = iccInfo.IciA[0].ptI ; + vInters.pop_back() ; + vInters.emplace_back( pt) ; + if ( ! OnWhichEdge(nRoot, pt, nEdgeOut)) + return false ; + } + m_mTree.at( nRoot).m_vInters.back().vpt = vInters ; m_mTree.at( nRoot).m_vInters.back().nOut = nEdgeOut ; } // chiamo una funzione per renderli coerenti @@ -3650,6 +3744,8 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) bool Tree::AdjustCuts( void) { + if ( int( m_mTree.at( -1).m_vInters.size()) == 1) + return true ; // li riordino per ordine di quali taglio incontrerei percorrendo il bordo della cella a partire da ptTR sort( m_mTree.at( -1).m_vInters.begin(), m_mTree.at( -1).m_vInters.end(), [](Inters& a, Inters& b){ return Inters::FirstEncounter(a,b) ;}) ; // ora controllo che le intersezioni che trovo siano ingressi alternati ad uscite, sennò inverto l'intersezione @@ -3657,6 +3753,9 @@ Tree::AdjustCuts( void) for ( int i = 0 ; i < int( m_mTree.at( -1).m_vInters.size()); ++i) { if ( m_mTree.at( -1).m_vInters.at(i).bSortedbyStart == bPreviousWasStart) { reverse( m_mTree.at( -1).m_vInters.at(i).vpt.begin(), m_mTree.at( -1).m_vInters.at(i).vpt.end()) ; + int nEdgeOutNew = m_mTree.at( -1).m_vInters.at(i).nIn ; + m_mTree.at( -1).m_vInters.at(i).nIn = m_mTree.at( -1).m_vInters.at(i).nOut ; + m_mTree.at( -1).m_vInters.at(i).nOut = nEdgeOutNew ; bPreviousWasStart = m_mTree.at( -1).m_vInters.at(i).bSortedbyStart ; } else diff --git a/Tree.h b/Tree.h index 0ae3288..d3ee8be 100644 --- a/Tree.h +++ b/Tree.h @@ -86,32 +86,32 @@ struct Inters { // salvo il lato che viene prima confrontando ingresso e uscita if ( nPos2 < nPos1) { nPos1 = nPos2 ; - nFirstA = int( a.vpt.size()) ; + nFirstA = int( a.vpt.size()) - 1 ; } // se ingresso e uscita sono sullo stesso lato allora confronto le coordinate per capire se viene prima l'ingresso o l'uscita else if ( nPos2 == nPos1 ) { if ( nPos1 == 0 ) - nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : int( a.vpt.size()) ; + nFirstA = a.vpt[0].x > a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ; else if ( nPos1 == 1 ) - nFirstA = a.vpt[0].y > a.vpt.back().y ? 0 : int( a.vpt.size()) ; + nFirstA = a.vpt[0].y > a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ; else if ( nPos1 == 2 ) - nFirstA = a.vpt[0].x < a.vpt.back().x ? 0 : int( a.vpt.size()) ; + nFirstA = a.vpt[0].x < a.vpt.back().x ? 0 : ( int( a.vpt.size()) - 1) ; else if ( nPos1 == 3 ) - nFirstA = a.vpt[0].y < a.vpt.back().y ? 0 : int( a.vpt.size()) ; + nFirstA = a.vpt[0].y < a.vpt.back().y ? 0 : ( int( a.vpt.size()) - 1) ; } if ( nPos4 < nPos3) { nPos3 = nPos4 ; - nFirstB = int( b.vpt.size()) ; + nFirstB = int( b.vpt.size()) - 1 ; } else if ( nPos4 == nPos3 ) { if ( nPos3 == 0 ) - nFirstB = b.vpt[0].x > b.vpt.back().x ? 0 : int( b.vpt.size()) ; + nFirstB = b.vpt[0].x > b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ; else if ( nPos3 == 1 ) - nFirstB = b.vpt[0].y > b.vpt.back().y ? 0 : int( b.vpt.size()) ; + nFirstB = b.vpt[0].y > b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ; else if ( nPos3 == 2 ) - nFirstB = b.vpt[0].x < b.vpt.back().x ? 0 : int( b.vpt.size()) ; + nFirstB = b.vpt[0].x < b.vpt.back().x ? 0 : ( int( b.vpt.size()) - 1) ; else if ( nPos3 == 3 ) - nFirstB = b.vpt[0].y < b.vpt.back().y ? 0 : int( b.vpt.size()) ; + nFirstB = b.vpt[0].y < b.vpt.back().y ? 0 : ( int( b.vpt.size()) - 1) ; } a.bSortedbyStart = nFirstA == 0 ; b.bSortedbyStart = nFirstB == 0 ; @@ -238,14 +238,17 @@ class Tree // dSideMin � lunghezza minima del lato di una cella nello spazio reale bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; bool GetPolygons( POLYLINEMATRIX& vPolygons) ; - bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR& vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero + bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero bool GetEdge3D ( POLYLINEVECTOR& vPLEdges) ; // restituisce gli edge 3D come curve composite void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell // funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree - bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli + bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli + bool IsClosedU( void) { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U + bool IsClosedV( void) { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V + std::vector GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli private : bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert @@ -291,6 +294,7 @@ class Tree bool m_bMulti ; // superficie multi-patch bool m_bClosedU ; // superficie chiusa lungo il parametro U bool m_bClosedV ; // superficie chiusa lungo il parametro V + BOOLVECTOR m_vbPole ; // vettore che indica se i vari lati sono collassati in poli ( indici riferiti all'ordine degli edge) bool m_bSplitPatches ; // flag che indica se le patches sono state divise prima della creazione dell'albero int m_nDegU ; // grado della superficie nel parametro U int m_nDegV ; // grado della superficie nel parametro V From 4bada73c835f2f410a61885045a459015ac19922 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 23 Feb 2024 10:19:04 +0100 Subject: [PATCH 09/31] EgtGeomKernel : - inizio modifica al calcolo di tagli multipli ad una superficie di Bezier. --- SurfBezier.cpp | 216 ++++++++++++++++++++++++++++++++++++++++++------- Tree.cpp | 16 ++-- 2 files changed, 197 insertions(+), 35 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index ee91115..c40e390 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1659,15 +1659,15 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; - // con queste righe funzionano anche i tagli multipli//////////////////////////////////////////////// - bool bMod = false ; - // ATTENZIONE!!!!! ad ogni "return false" in questa funzione dovrei reimpostare "m_bTrimmed = true" se bMod == true/////////////////////////////////////////////////// - if ( m_bTrimmed) { - m_bTrimmed = false ; - ResetAuxSurf() ; - bMod = true ; - } - ////i tagli multipli//////////////////////////////////////////////// + //// con queste righe funzionano anche i tagli multipli//////////////////////////////////////////////// + //bool bMod = false ; + //// ATTENZIONE!!!!! ad ogni "return false" in questa funzione dovrei reimpostare "m_bTrimmed = true" se bMod == true/////////////////////////////////////////////////// + //if ( m_bTrimmed) { + // m_bTrimmed = false ; + // ResetAuxSurf() ; + // bMod = true ; + //} + //////i tagli multipli//////////////////////////////////////////////// IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; // concateno le curve 3d @@ -1791,26 +1791,188 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } // creo il nuovo bordo usando i loop aperti - POLYLINEMATRIX vPolygons ; + //POLYLINEMATRIX vPolygons ; if ( int(vpCCOpen.size()) != 0 ) { - Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ; - POLYLINEVECTOR vPL ; - for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) { - PolyLine pl ; - vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ; - vPL.emplace_back( pl) ; - } - Tree.AddCutsToRoot( vPL) ; - ////debug - //vector vGeoObj ; - //for ( int k = 0 ; k < int( vPL.size()) ; ++ k) { - // PtrOwner pCrv( CreateCurveComposite()) ; - // pCrv->FromPolyLine( vPL[k]) ; - // vGeoObj.emplace_back( static_cast(Release( pCrv))) ; + //Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ; + //POLYLINEVECTOR vPL ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) { + // PolyLine pl ; + // vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ; + // vPL.emplace_back( pl) ; //} - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ; - ////debug - Tree.CreateCellContour( vPolygons) ; + //Tree.AddCutsToRoot( vPL) ; + + //////debug + ////vector vGeoObj ; + ////for ( int k = 0 ; k < int( vPL.size()) ; ++ k) { + //// PtrOwner pCrv( CreateCurveComposite()) ; + //// pCrv->FromPolyLine( vPL[k]) ; + //// vGeoObj.emplace_back( static_cast(Release( pCrv))) ; + ////} + ////SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ; + //////debug + + //Tree.CreateCellContour( vPolygons) ; + + + + // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie + // recupero la regione attuale + PtrOwner pNewTrim( GetTrimRegion()->Clone()) ; + + + // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo + BOOLVECTOR vbAdded( vpCCOpen.size()) ; + fill(vbAdded.begin(), vbAdded.end(), false) ; + PtrOwner pCCNewEdge( CreateCurveComposite()) ; + PtrOwner pCL( CreateCurveLine()) ; + bool bAddedAll = false ; + int nFirstIntersChunck = -1 ; + int nFirstIntersLoop = -1 ; + double dParamFirstInters = -1 ; + // parto aggiungendo il primo taglio + int nNewToAdd = 0 ; + //while ( ! bAddedAll) { + while ( nNewToAdd != -1) { + // aggiungo il taglio + PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; + pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ; + // aggiorno la lista degli aggiunti + vbAdded[nNewToAdd] = true ; + + + + // ora devo trovare la sua intersezione con un edge + // visto che scorro tutto ogni volta posso almeno evitare il conto se incontro l'edge da cui avevo già trovato lo start + int nChunkE = -1 ; + int nLoopE = -1 ; + int nChunkS = -1 ; + int nLoopS = -1 ; + // scorro tutti i chunk e tutti i loop per trovare l'intersezione + int nInters = 0 ; // per ogni loop devo trovare due intersezioni, una di partenza e una di arrivo + IntCrvCrvInfo iccInfo0 ; + IntCrvCrvInfo iccInfo1 ; + bool bStartInters0 = false ; + for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + if ( c == nChunkS && l == nLoopS) + continue ; + PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; + IntersCurveCurve icc( *pLastCC, *pLoop) ; + if ( icc.GetIntersCount() == 0) + continue ; + if ( icc.GetIntersCount() == 1){ + if ( nInters == 0) { + icc.GetIntCrvCrvInfo( 0, iccInfo0) ; + // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio + if ( iccInfo0.IciA->dU < EPS_SMALL ) { + nChunkS = c ; + nLoopS = l ; + bStartInters0 = true ; + } + else { + nChunkE = c ; + nLoopE = l ; + bStartInters0 = false ; + } + } + else if ( nInters == 1) { + icc.GetIntCrvCrvInfo( 1, iccInfo1) ; + // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio + if ( iccInfo0.IciA->dU < EPS_SMALL ) { + nChunkS = c ; + nLoopS = l ; + } + else { + nChunkE = c ; + nLoopE = l ; + } + } + else + return false ; + ++nInters ; + } + else if (icc.GetIntersCount() == 2) { + icc.GetIntCrvCrvInfo( 0, iccInfo0) ; + // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio + if ( iccInfo0.IciA->dU < EPS_SMALL ) { + nChunkS = c ; + nLoopS = l ; + bStartInters0 = true ; + } + else { + nChunkE = c ; + nLoopE = l ; + bStartInters0 = false ; + } + icc.GetIntCrvCrvInfo( 1, iccInfo1) ; + // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio + if ( iccInfo1.IciA->dU < EPS_SMALL ) { + nChunkS = c ; + nLoopS = l ; + } + else { + nChunkE = c ; + nLoopE = l ; + } + ++nInters ; + ++nInters ; + } + // quando ho trovato due intersezioni esco + if ( nInters == 2) + break ; + } + // quando ho trovato due intersezioni esco + if ( nInters == 2) + break ; + } + // se ho appena aggiunto il primo taglio mi salvo il suo start che mi indicherà dove terminare la ricostruzione del bordo + if ( nNewToAdd == 0 ) { + nFirstIntersChunck = nChunkS ; + nFirstIntersLoop = nLoopS ; + dParamFirstInters = bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU ; + } + // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente + // devo quindi trovare la prossima intersezione con un taglio + ICCIVECTOR vICCI ; + PtrOwner pLoop( pNewTrim->GetLoop( nChunkE, nLoopE)) ; + for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; + if ( icc.GetIntersCount() == 0) + continue ; + else if ( icc.GetIntersCount() == 1) { + vICCI.emplace_back() ; + icc.GetIntCrvCrvInfo( 0, vICCI.back()) ; + } + + + } + + // trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio + pLoop->TrimStartAtParam(bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU) ; + pLoop->TrimEndAtParam() ; + // se arrivo fino alla fine del loop devo ricominciare a seguire il loop fino ad un'intersezione? + PtrOwner pLoop2( pNewTrim->GetLoop( nChunkE, nLoopE)) ; + pLoop->TrimEndAtParam() ;// appiccico un pezzo dall'inizio + + + + + // trovo il prossimo taglio ancora da aggiungere + nNewToAdd = -1 ; + for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { + if ( ! vbAdded[b]) { + nNewToAdd = b ; + //vbAdded[b] = true ; + break ; + } + } + //// controllo se ho aggiunto tutti i tagli + //bAddedAll = true ; + //for ( int b = 0 ; b < int( vbAdded.size()) ; ++b ) { + // bAddedAll = bAddedAll && vbAdded[b] ; + //} + } } //GESTIONE DEI TRIANGOLI RISULTANTI DALL'INTERSEZIONE diff --git a/Tree.cpp b/Tree.cpp index 5c895b7..d7cdb1a 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3685,13 +3685,13 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) IntersCurveCurve icc2( *pCL, *pCL2) ; IntersCurveCurve icc3( *pCL, *pCL3) ; IntCrvCrvInfo iccInfo ; - if (icc0.GetCrossIntersCount() != 0) + if (icc0.GetIntersCount() != 0) icc0.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc1.GetCrossIntersCount() != 0) + else if (icc1.GetIntersCount() != 0) icc1.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc2.GetCrossIntersCount() != 0) + else if (icc2.GetIntersCount() != 0) icc2.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc3.GetCrossIntersCount() != 0) + else if (icc3.GetIntersCount() != 0) icc3.GetIntCrvCrvInfo( 0, iccInfo) ; pt = iccInfo.IciA[0].ptI ; if ( ! OnWhichEdge(nRoot, pt, nEdgeIn)) @@ -3718,13 +3718,13 @@ Tree::AddCutsToRoot( POLYLINEVECTOR& vCuts) IntersCurveCurve icc2( *pCL, *pCL2) ; IntersCurveCurve icc3( *pCL, *pCL3) ; IntCrvCrvInfo iccInfo ; - if (icc0.GetCrossIntersCount() != 0) + if (icc0.GetIntersCount() != 0) icc0.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc1.GetCrossIntersCount() != 0) + else if (icc1.GetIntersCount() != 0) icc1.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc2.GetCrossIntersCount() != 0) + else if (icc2.GetIntersCount() != 0) icc2.GetIntCrvCrvInfo( 0, iccInfo) ; - else if (icc3.GetCrossIntersCount() != 0) + else if (icc3.GetIntersCount() != 0) icc3.GetIntCrvCrvInfo( 0, iccInfo) ; pt = iccInfo.IciA[0].ptI ; vInters.pop_back() ; From 3a623996d2317b4e2e34e666044e4d6119af909d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 26 Feb 2024 09:48:02 +0100 Subject: [PATCH 10/31] =?UTF-8?q?EgtGeomKernel=20:=20-=20corretta=20la=20f?= =?UTF-8?q?unzione=20per=20il=20trim=20di=20sup.=20di=20Bezier=20con=20pia?= =?UTF-8?q?ni,=20in=20zone=20di=20salto=20per=20periodicit=C3=A0=20e=20in?= =?UTF-8?q?=20caso=20di=20tagli=20multipli.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 337 +++++++++++++++++++++++-------------------------- 1 file changed, 159 insertions(+), 178 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c40e390..26d8e37 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -36,6 +36,7 @@ #include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkGeoObjSave.h" +#include using namespace std ; @@ -1647,6 +1648,22 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& return true ; } +typedef tuple TRINT ; + +//static bool operator==(TRINT& ta, TRINT& tb) +//{ +// return get<0>(ta) == get<0>(tb) && get<1>(ta) == get<1>(tb) && get<2>(ta) == get<2>(tb) ; +//} + +template<> +struct hash { + std::size_t operator()(const TRINT& t) const + { + // Compute individual hash values for first, second and third and combine them using XOR and bit shifting: + return ((hash()(get<0>(t))) ^ (hash()(get<1>(t)) << 1) >> 1) ^ (hash()(get<2>(t)) << 1) ; + } +}; + //---------------------------------------------------------------------------- bool SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) @@ -1772,12 +1789,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; } - ////debug - //vector vGeoObj ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; - ////debug + //debug + vector vGeoObj ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + //debug if ( int( vpCCOpen.size()) != 0) { // devo verificare se devo giuntare la prima curva aperta con l'ultima Point3d ptStartOpen, ptEndOpen ; @@ -1790,188 +1807,162 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } - // creo il nuovo bordo usando i loop aperti - //POLYLINEMATRIX vPolygons ; + + //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti + SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { - //Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ; - //POLYLINEVECTOR vPL ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) { - // PolyLine pl ; - // vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ; - // vPL.emplace_back( pl) ; - //} - //Tree.AddCutsToRoot( vPL) ; - - //////debug - ////vector vGeoObj ; - ////for ( int k = 0 ; k < int( vPL.size()) ; ++ k) { - //// PtrOwner pCrv( CreateCurveComposite()) ; - //// pCrv->FromPolyLine( vPL[k]) ; - //// vGeoObj.emplace_back( static_cast(Release( pCrv))) ; - ////} - ////SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ; - //////debug - - //Tree.CreateCellContour( vPolygons) ; - - - // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie // recupero la regione attuale - PtrOwner pNewTrim( GetTrimRegion()->Clone()) ; - + unordered_map mInters ; + // costruisco la mappa delle intersezioni + PtrOwner pNewTrim( CreateBasicSurfFlatRegion()) ; + if ( m_bTrimmed) + pNewTrim.Set( GetTrimRegion()->Clone()) ; + else + pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; + //debug + PtrOwner pSrfCopy( pNewTrim->Clone()) ; + SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; + //debug + + ////debug + //PtrOwner pCrvCopy( pNewTrim->GetLoop(0,0)) ; + //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_actualTrimRegionEdge.nge") ; + ////debug + + for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; + // prima curva è il loop, seconda curva è il loop + IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; + if ( icc.GetIntersCount() != 0) { + ICCIVECTOR vICC ; + for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) { + IntCrvCrvInfo iccInfo ; + icc.GetIntCrvCrvInfo( i, iccInfo) ; + vICC.emplace_back( iccInfo) ; + } + mInters.insert( pair( TRINT(c,l,t), vICC)) ; + } + } + } + } // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; fill(vbAdded.begin(), vbAdded.end(), false) ; PtrOwner pCCNewEdge( CreateCurveComposite()) ; PtrOwner pCL( CreateCurveLine()) ; - bool bAddedAll = false ; - int nFirstIntersChunck = -1 ; - int nFirstIntersLoop = -1 ; + //bool bAddedAll = false ; + TRINT tiFirstInters ; double dParamFirstInters = -1 ; // parto aggiungendo il primo taglio int nNewToAdd = 0 ; - //while ( ! bAddedAll) { + bool bFirstCurveOfEdge = true ; while ( nNewToAdd != -1) { // aggiungo il taglio - PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; + //PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ; // aggiorno la lista degli aggiunti vbAdded[nNewToAdd] = true ; - - - - // ora devo trovare la sua intersezione con un edge - // visto che scorro tutto ogni volta posso almeno evitare il conto se incontro l'edge da cui avevo già trovato lo start - int nChunkE = -1 ; - int nLoopE = -1 ; - int nChunkS = -1 ; - int nLoopS = -1 ; - // scorro tutti i chunk e tutti i loop per trovare l'intersezione - int nInters = 0 ; // per ogni loop devo trovare due intersezioni, una di partenza e una di arrivo - IntCrvCrvInfo iccInfo0 ; - IntCrvCrvInfo iccInfo1 ; - bool bStartInters0 = false ; - for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { - for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { - if ( c == nChunkS && l == nLoopS) - continue ; - PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; - IntersCurveCurve icc( *pLastCC, *pLoop) ; - if ( icc.GetIntersCount() == 0) - continue ; - if ( icc.GetIntersCount() == 1){ - if ( nInters == 0) { - icc.GetIntCrvCrvInfo( 0, iccInfo0) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - bStartInters0 = true ; - } - else { - nChunkE = c ; - nLoopE = l ; - bStartInters0 = false ; - } - } - else if ( nInters == 1) { - icc.GetIntCrvCrvInfo( 1, iccInfo1) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - } - else { - nChunkE = c ; - nLoopE = l ; + // di questo taglio mi salvo il chunk e loop di start e end + TRINT tiStart, tiEnd ; + for (const auto& pair : mInters) { + if ( get<2>(pair.first) == nNewToAdd ) { + for (int p = 0 ; p < int(pair.second.size()) ; ++p) { + if ( pair.second[p].IciB->dU < EPS_SMALL) { + tiStart = pair.first ; + if ( bFirstCurveOfEdge){ + // salvo l'inizio del taglio che è la prima curva di questa curva compo + tiFirstInters = pair.first ; + dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop + bFirstCurveOfEdge = false ; } } else - return false ; - ++nInters ; + tiEnd = pair.first ; } - else if (icc.GetIntersCount() == 2) { - icc.GetIntCrvCrvInfo( 0, iccInfo0) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo0.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - bStartInters0 = true ; - } - else { - nChunkE = c ; - nLoopE = l ; - bStartInters0 = false ; - } - icc.GetIntCrvCrvInfo( 1, iccInfo1) ; - // do per scontato di avere solo intersezioni all'inizio o alla fine del taglio - if ( iccInfo1.IciA->dU < EPS_SMALL ) { - nChunkS = c ; - nLoopS = l ; - } - else { - nChunkE = c ; - nLoopE = l ; - } - ++nInters ; - ++nInters ; - } - // quando ho trovato due intersezioni esco - if ( nInters == 2) - break ; } - // quando ho trovato due intersezioni esco - if ( nInters == 2) - break ; - } - // se ho appena aggiunto il primo taglio mi salvo il suo start che mi indicherà dove terminare la ricostruzione del bordo - if ( nNewToAdd == 0 ) { - nFirstIntersChunck = nChunkS ; - nFirstIntersLoop = nLoopS ; - dParamFirstInters = bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU ; } + // devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente // devo quindi trovare la prossima intersezione con un taglio - ICCIVECTOR vICCI ; - PtrOwner pLoop( pNewTrim->GetLoop( nChunkE, nLoopE)) ; - for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { - IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; - if ( icc.GetIntersCount() == 0) - continue ; - else if ( icc.GetIntersCount() == 1) { - vICCI.emplace_back() ; - icc.GetIntCrvCrvInfo( 0, vICCI.back()) ; - } - - + int nInters = -1 ; + double dNextCut = numeric_limits::infinity() ; + double dEndCurrentCut ; + for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) { + // se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop + if ( mInters[tiEnd][0].IciB->dU > EPS_SMALL) + dEndCurrentCut = mInters[tiEnd][0].IciA->dU ; } - + // se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop + for ( const auto& pair : mInters) { + if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { + for ( int i = 0 ; i < int(pair.second.size()); ++i ) { + // se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora + // mi salvo questa nuova che ho trovato + if ( pair.second[i].IciA->dU < dNextCut && pair.second[i].IciA->dU > dEndCurrentCut) { + dNextCut = pair.second[i].IciA->dU ; + nInters = get<2>(pair.first) ; + } + } + } + } + bool bRestart = false ; + if ( nInters == -1) { + bRestart = true ; + dNextCut = numeric_limits::infinity() ; + for ( const auto& pair : mInters) { + if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { + for ( int i = 0 ; i < int(pair.second.size()); ++i ) { + // se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora + // mi salvo questa nuova che ho trovato + if ( pair.second[i].IciA->dU < dNextCut) { + dNextCut = pair.second[i].IciA->dU ; + nInters = get<2>(pair.first) ; + } + } + } + } + } + PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; // trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio - pLoop->TrimStartAtParam(bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU) ; - pLoop->TrimEndAtParam() ; - // se arrivo fino alla fine del loop devo ricominciare a seguire il loop fino ad un'intersezione? - PtrOwner pLoop2( pNewTrim->GetLoop( nChunkE, nLoopE)) ; - pLoop->TrimEndAtParam() ;// appiccico un pezzo dall'inizio - - - - - // trovo il prossimo taglio ancora da aggiungere - nNewToAdd = -1 ; - for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { - if ( ! vbAdded[b]) { - nNewToAdd = b ; - //vbAdded[b] = true ; - break ; + pLoopTrimmed->TrimEndAtParam( dNextCut) ; + // se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato + if ( ! bRestart) { + pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ; + pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ; + } + else { + // prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa + // andare al punto finale e quindi tornare al punto iniziale + PtrOwner pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; + pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ; + pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ; + // e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio + pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ; + } + // se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento + // alla flat region e comincio a costruire un altro bordo + // altrimenti continuo ad aggiungere curve al bordo corrente + if ( nInters == get<2>(tiFirstInters) ) { + pCCNewEdge->Close() ; + sfrContour.AddCurve( Release( pCCNewEdge)) ; + pCCNewEdge.Set( CreateBasicCurveComposite()) ; + bFirstCurveOfEdge = true ; + // trovo il prossimo taglio ancora da aggiungere + nNewToAdd = -1 ; + for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { + if ( ! vbAdded[b]) { + nNewToAdd = b ; + //vbAdded[b] = true ; + break ; + } } } - //// controllo se ho aggiunto tutti i tagli - //bAddedAll = true ; - //for ( int b = 0 ; b < int( vbAdded.size()) ; ++b ) { - // bAddedAll = bAddedAll && vbAdded[b] ; - //} + else + nNewToAdd = nInters; } } @@ -1992,19 +1983,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pNewStm->GetLoops( vPLTria) ; } - SurfFlatRegionByContours sfrContour ; - // aggiungo i tagli sul bordo - for ( int i = 0 ; i < int( vPolygons.size()); ++i ) { - for ( int j = 0 ; j < int( vPolygons[i].size()); ++j) { - PtrOwner pCC( CreateCurveComposite()) ; - pCC->FromPolyLine( vPolygons[i][j]) ; - ////debug - //PtrOwner pCrvCopy( pCC->Clone()) ; - //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_trim_curve2D.nge") ; - ////debug - sfrContour.AddCurve( Release( pCC)) ; - } - } // aggiungo i loop chiusi for ( int i = 0 ; i < int( vpCCClosed.size()); ++i ) sfrContour.AddCurve( Release( vpCCClosed[i])) ; @@ -2076,10 +2054,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - //debug - PtrOwner pSrfFR_Copy( pSFR->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + ////debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { @@ -2211,9 +2189,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } + // questa è ancora da sviluppare ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // devo anche tener conto della possibilità che i lati siano collassati in poli - //if ( m_vbPole[0]) - // ; + if ( m_vbPole[0] ) { + ; + } + // se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice if ( nIL == 3 ) { if ( AreSamePointApprox(ptI, vPT[0])) From 6efb3a6e7f147b7ba630de0e3ab34dc22863f49b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 27 Feb 2024 16:34:28 +0100 Subject: [PATCH 11/31] EgtGeomKernel : - corretta funzione di trim di sup. di Bezier con piani, in zone di punti di polo. --- SurfBezier.cpp | 359 ++++++++++++++++++++++++++++++++++++++++--------- SurfBezier.h | 6 +- Tree.cpp | 2 +- 3 files changed, 301 insertions(+), 66 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 26d8e37..f98f28a 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -241,7 +241,7 @@ SurfBezier::IsAPoint( void) const if ( ! AreSamePointApprox( m_vPtCtrl[0], m_vPtCtrl[i])) return false ; } - + return true ; } @@ -1482,20 +1482,24 @@ SurfBezier::GetAuxSurf( void) const //// per usare i polygon basic/////////////////// - /////////////////// così facendo sto recuperando gli Edge e la chiususra solo dell'ULTIMO TREE analizzato!!!!! (in caso di trim che creano più chunk analizzo più tree separatamente)/////////////// + /////////////////// così facendo sto recuperando gli Edge e la chiusura solo dell'ULTIMO TREE analizzato!!!!! (in caso di trim che creano più chunk analizzo più tree separatamente)/////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // aggiorno la chiusura della superficie m_bClosedU = Tree.IsClosedU() ; m_bClosedV = Tree.IsClosedV() ; - m_vbPole = Tree.GetPoles() ; + //m_vbPole = Tree.GetPoles() ; // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria POLYLINEVECTOR vPLEdges ; Tree.GetEdge3D( vPLEdges) ; + bool bComposed = true ; for ( int i= 0 ; i < int( vPLEdges.size()); ++i) { m_vCCEdge.emplace_back( CreateBasicCurveComposite()) ; - m_vCCEdge.back()->FromPolyLine( vPLEdges[i]) ; + if ( ! m_vCCEdge.back()->FromPolyLine( vPLEdges[i])) + bComposed = false ; } + if ( ! bComposed) + m_vPLEdge = vPLEdges ; //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // qui non sarebbe male stampare un messaggio di errore nel log se avevo un'area da disegnare ma non sono usciti dei poligoni @@ -1568,6 +1572,24 @@ SurfBezier::GetLeaves( vector>& vLeaves) const return true ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::GetTriangles2D( vector>& vTria2D) const +{ + const ISurfTriMesh* pSTM = GetAuxSurf() ; + for ( int t = 0 ; t < int(pSTM->GetTriangleCount()) ; ++t ) { + double dU0, dU1, dU2, dV0, dV1, dV2 ; + int nVert[3] ; + pSTM->GetTriangle( t, nVert); + pSTM->GetVertexParam( nVert[0], dU0, dV0) ; + pSTM->GetVertexParam( nVert[1], dU1, dV1) ; + pSTM->GetVertexParam( nVert[2], dU2, dV2) ; + Point3d pt0(dU0,dV0), pt1(dU1,dV1), pt2(dU2,dV2) ; + vTria2D.emplace_back( tuple(t, pt0, pt1, pt2)) ; + } + return true ; +} + //---------------------------------------------------------------------------- void SurfBezier::ResetAuxSurf( void) const @@ -1584,6 +1606,10 @@ SurfBezier::ResetTrimRegion( void) if ( m_pTrimReg != nullptr) delete( m_pTrimReg) ; m_pTrimReg = nullptr ; + ResetAuxSurf() ; + m_bTrimmed = false ; + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; } //---------------------------------------------------------------------------- @@ -1598,18 +1624,35 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const DistPointSurfTm distPtStm0( pt3D, *GetAuxSurf()) ; // aggiungo il primo punto int nTriaIndex ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; - if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D)) + // passo anche i riferimenti del prossimo punto + Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; + DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ; + int nTriaIndexNext = -1 ; + distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ; + if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, pt3DEnd, nTriaIndexNext)) return nullptr ; + //if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D)) { + // Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; + // DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ; + // int nTriaIndexNext = -1 ; + // distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ; + // if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, nTriaIndexNext)) + // return nullptr ; + // nTriaIndex = nTriaIndexNext ; + //} pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi + int nTriaIndexPrev = nTriaIndex ; for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; + Point3d pt3DPrev = pt3D ; pCrv->GetEndPoint( pt3D) ; DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ; distPtStm.GetMinDistTriaIndex( nTriaIndex) ; - if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D)) + if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D, 5, pt3DPrev, nTriaIndexPrev)) return nullptr ; pl.AddUPoint( i, pt2D) ; + nTriaIndexPrev = nTriaIndex ; } PtrOwner pCC2D ( CreateCurveComposite()) ; pCC2D->FromPolyLine( pl) ; @@ -1638,6 +1681,8 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& // porto la curva nello spazio parametrico PtrOwner pCC( UnprojectCurveFromStm( pCrvCompo)) ; + if ( IsNull( pCC)) + return false ; // le curve aperte le tengo da parte per giuntarle alla fine col bordo if ( ! pCC->IsClosed()) @@ -1789,12 +1834,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; } - //debug - vector vGeoObj ; - for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; - //debug + ////debug + //vector vGeoObj ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + ////debug if ( int( vpCCOpen.size()) != 0) { // devo verificare se devo giuntare la prima curva aperta con l'ultima Point3d ptStartOpen, ptEndOpen ; @@ -1806,7 +1851,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vpCCOpen.erase( vpCCOpen.begin()) ; } } - + ////debug + //vector vGeoObj2 ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + ////debug //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; @@ -1820,10 +1870,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pNewTrim.Set( GetTrimRegion()->Clone()) ; else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - //debug - PtrOwner pSrfCopy( pNewTrim->Clone()) ; - SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; - //debug + ////debug + //PtrOwner pSrfCopy( pNewTrim->Clone()) ; + //SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; + ////debug ////debug //PtrOwner pCrvCopy( pNewTrim->GetLoop(0,0)) ; @@ -1856,7 +1906,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) PtrOwner pCL( CreateCurveLine()) ; //bool bAddedAll = false ; TRINT tiFirstInters ; - double dParamFirstInters = -1 ; + //double dParamFirstInters = -1 ; // parto aggiungendo il primo taglio int nNewToAdd = 0 ; bool bFirstCurveOfEdge = true ; @@ -1876,7 +1926,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( bFirstCurveOfEdge){ // salvo l'inizio del taglio che è la prima curva di questa curva compo tiFirstInters = pair.first ; - dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop + //dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop bFirstCurveOfEdge = false ; } } @@ -1893,8 +1943,8 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) double dEndCurrentCut ; for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) { // se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop - if ( mInters[tiEnd][0].IciB->dU > EPS_SMALL) - dEndCurrentCut = mInters[tiEnd][0].IciA->dU ; + if ( mInters[tiEnd][i].IciB->dU > EPS_SMALL) + dEndCurrentCut = mInters[tiEnd][i].IciA->dU ; } // se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop for ( const auto& pair : mInters) { @@ -1909,9 +1959,9 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } - bool bRestart = false ; + //bool bRestart = false ; if ( nInters == -1) { - bRestart = true ; + //bRestart = true ; dNextCut = numeric_limits::infinity() ; for ( const auto& pair : mInters) { if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { @@ -1926,23 +1976,41 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } + + // se tutto va bene queste due righe sostituiscono tutto il casino qua sotto PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; - // trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio - pLoopTrimmed->TrimEndAtParam( dNextCut) ; - // se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato - if ( ! bRestart) { - pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ; - pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ; - } - else { - // prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa - // andare al punto finale e quindi tornare al punto iniziale - PtrOwner pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; - pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ; - pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ; - // e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio - pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ; - } + pCCNewEdge->AddCurve(pLoopTrimmed->CopyParamRange( dEndCurrentCut, dNextCut)) ; + + /////////////////////////////////////sostituito da CopyParamRange//////////////////////////////////////////////////////////////////////////////////////////////////////////// + //PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; + //// se i trim che devo fare sono sulla stessa sotto-curva della compo devo riscalare il valore per il trim allo start prima di trimmare l'end + //if ( int( dNextCut) == int( dEndCurrentCut)) { + // PtrOwner pLoopCompo( GetCurveComposite( pLoopTrimmed->Clone())) ; + // const ICurve* pSubCrv = pLoopCompo->GetCurve( int(dNextCut)) ; + // double dLenAtParam0, dLenAtParam1 ; + // pSubCrv->GetLengthAtParam( dEndCurrentCut, dLenAtParam0) ; + // pSubCrv->GetLengthAtParam( dNextCut, dLenAtParam1) ; + // dEndCurrentCut = dLenAtParam0 / dLenAtParam1 ; + //} + //// trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio + //pLoopTrimmed->TrimEndAtParam( dNextCut) ; + + //// se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato + //if ( ! bRestart) { + // pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ; + // pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ; + //} + //else { + // // prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa + // // andare al punto finale e quindi tornare al punto iniziale + // PtrOwner pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; + // pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ; + // pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ; + // // e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio + // pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ; + //} + ///////////////////////////////////sostituito da CopyParamRange////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento // alla flat region e comincio a costruire un altro bordo // altrimenti continuo ad aggiungere curve al bordo corrente @@ -2020,6 +2088,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } + ////debug + //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_flip.nge", GDB_SV_BIN) ; + ////debug + // aggiorno la superficie di trim Point3d ptStart ; Vector3d vtDir, vtDirS, vtDirE ; @@ -2038,9 +2111,17 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vtDir = vtDirS - vtDirE ; PtrOwner pCL2( CreateCurveLine()) ; pCL2->SetPVL( ptStart, vtDir, 1e6) ; IntersCurveCurve icc2( *pCL2, *pCrv) ; - if ( icc2.GetIntersCount()%2 != 0) - return false ; - icc2.GetIntCrvCrvInfo( 1, iccInfo) ; + if ( icc2.GetIntersCount()%2 != 0) { + vtDir = vtDirS ; + vtDir.Rotate( Z_AX, bPos? 90 : -90) ; + PtrOwner pCL3( CreateCurveLine()) ; pCL3->SetPVL( ptStart, vtDir, 1e6) ; + IntersCurveCurve icc3( *pCL3, *pCrv) ; + if ( icc3.GetIntersCount()%2 != 0) + return false ; + icc3.GetIntCrvCrvInfo( 1, iccInfo) ; + } + else + icc2.GetIntCrvCrvInfo( 1, iccInfo) ; } else icc.GetIntCrvCrvInfo( 1, iccInfo) ; @@ -2068,6 +2149,14 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( ! SetTrimRegion( *pSFR) || ! m_pTrimReg->IsValid()) return false ; } + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + ////debug + //PtrOwner pSrfFR_Copy3( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy3), "D:\\Temp\\inters\\trimmed_paramSpace.nge", GDB_SV_BIN) ; + ////debug return true ; } @@ -2075,9 +2164,62 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //---------------------------------------------------------------------------- bool SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const +{ + return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1), -1) ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, int nTPrev) const { // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche const ISurfTriMesh* pSurfTm = GetAuxSurf() ; + // devo subito capire se sono in un polo o no + // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto + bool bIsPole = false ; + int nInters = 0 ; + INTVECTOR vInters ; + if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3]) { + for ( int c = 0 ; c < 4 ; ++c) { + if ( ! m_vCCEdge[c]->IsValid()) { + Point3d pt ; + m_vPLEdge[c].GetFirstPoint( pt) ; + vInters.push_back( AreSamePointApprox( pt, ptI) ? 1 : 0) ; + nInters += vInters.back() ; + } + else { + vInters.push_back( m_vCCEdge[c]->IsPointOn( ptI) ? 1 : 0) ; + nInters += vInters.back() ; + } + } + + // se ho tre intersezioni vuol dire che un lato è collassato in un punto e il punto di cui voglio la controimmagine è esattamente nel polo + if ( nInters == 3) { + bIsPole = true ; + //// salvo pure come triangolo di riferimento quello del punto precedente + //const ISurfTriMesh* pSurfTm2 = GetAuxSurf() ; + //int nVert[3] ; + //pSurfTm2->GetTriangle( nT, nVert) ; + //PNTVECTOR vPtPa(3) ; + //pSurfTm2->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; + //pSurfTm2->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; + //pSurfTm2->GetVertexParam( nVert[2], vPtPa[2].x,vPtPa[2].y) ; + //if ( nTPrev != -1) + // nT = nTPrev ; + //else + // // se non avevo un punto precedente allora vuol dire che mi stanno passando un punto singolo e non posso dire nulla sulle coordinate + // // parametriche di questo punto + // return false ; + + // visto che sono in un polo devo verificare di aver ricevuto il triangolo giusto + // mi sposto verso il punto successivo o precedente e ricalcolo il triangolo di appartenenza + Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ; + // ricalcolo il triangolo di appartenenza + DistPointSurfTm dPtStm( ptI2, *pSurfTm) ; + dPtStm.GetMinDistTriaIndex( nT) ; + } + } + // recupero i dati dei vertici del triangolo che fa intersezione int nVert[3] ; pSurfTm->GetTriangle( nT, nVert) ; @@ -2090,9 +2232,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in pSurfTm->GetVertex( nVert[1], vPT[1]) ; pSurfTm->GetVertex( nVert[2], vPT[2]) ; // se la superficie è chiusa controllo se devo tenere conto della periodicità nel prendere le coordinate parametriche dei vertici + double dParamH, dParamL ; if ( m_bClosedU || m_bClosedV) { - double dParamH = m_nSpanV * SBZ_TREG_COEFF ; - double dParamL = m_nSpanU * SBZ_TREG_COEFF ; + dParamH = m_nSpanV * SBZ_TREG_COEFF ; + dParamL = m_nSpanU * SBZ_TREG_COEFF ; // devo trovare il lato più lungo e confrontarlo con le dimensioni dello spazio parametrico Vector3d vtDir ; double dDist ; @@ -2115,20 +2258,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // trovo se dei punti del triangolo sono sul bordo dello spazio parametrico BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { - if ( m_vCCEdge[1]->IsAPoint()) { + if ( ! m_vCCEdge[1]->IsValid()) { Point3d pt ; - m_vCCEdge[1]->GetStartPoint( pt) ; + m_vPLEdge[1].GetFirstPoint( pt) ; vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; } else - vbOn[p] =m_vCCEdge[1]->IsPointOn( vPT[p]) ; - if ( m_vCCEdge[3]->IsAPoint()) { + vbOn[p] = m_vCCEdge[1]->IsPointOn( vPT[p]) ; + if ( ! m_vCCEdge[3]->IsValid()) { Point3d pt ; - m_vCCEdge[3]->GetStartPoint( pt) ; - vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + m_vPLEdge[3].GetFirstPoint( pt) ; + vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; } else - vbOn[p] =m_vCCEdge[3]->IsPointOn( vPT[p]) ; + vbOn[p] = vbOn[p] || m_vCCEdge[3]->IsPointOn( vPT[p]) ; } // controllo che almeno un punto sia su un edge if ( vbOn[0] || vbOn[1] || vbOn[2]) { @@ -2153,20 +2296,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.95) { BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { - if ( m_vCCEdge[0]->IsAPoint()) { + if ( ! m_vCCEdge[0]->IsValid()) { Point3d pt ; - m_vCCEdge[0]->GetStartPoint( pt) ; + m_vPLEdge[0].GetFirstPoint( pt) ; vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; } else - vbOn[p] =m_vCCEdge[0]->IsPointOn( vPT[p]) ; - if ( m_vCCEdge[2]->IsAPoint()) { + vbOn[p] = m_vCCEdge[0]->IsPointOn( vPT[p]) ; + if ( ! m_vCCEdge[2]->IsValid()) { Point3d pt ; - m_vCCEdge[2]->GetStartPoint( pt) ; - vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; + m_vPLEdge[2].GetFirstPoint( pt) ; + vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; } else - vbOn[p] =m_vCCEdge[2]->IsPointOn( vPT[p]) ; + vbOn[p] = vbOn[p] || m_vCCEdge[2]->IsPointOn( vPT[p]) ; } // controllo che almeno un punto sia su un edge if ( vbOn[0] || vbOn[1] || vbOn[2]) { @@ -2189,14 +2332,58 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } - // questa è ancora da sviluppare ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // devo anche tener conto della possibilità che i lati siano collassati in poli - if ( m_vbPole[0] ) { - ; + if ( bIsPole) { + int nInters = -1 ; + for ( int c = 0 ; c < 4 ; ++c) { + if ( ( c == 0 && vInters[0] == vInters[3]) || + ( c != 0 && vInters[c] == vInters[c - 1])){ + nInters = c ; + break ; + } + } + // se non ho trovato il lato su cui ho il polo + if ( nInters == -1) + return false ; + // trovo quale vertice è sull'edge di polo + BOOLVECTOR vbOn(3) ; + fill( vbOn.begin(), vbOn.end(), false) ; + for ( int p = 0 ; p < 3; ++p ) { + for ( int c = 0 ; c < 4; ++c) { + if ( ! m_vCCEdge[c]->IsValid()) { + Point3d pt ; + m_vPLEdge[c].GetFirstPoint( pt) ; + vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] = vbOn[p] || m_vCCEdge[c]->IsPointOn( vPT[p]) ; + } + } + // trovo la coordinata giusta da tenere ( x o y a seconda dell'edge) + double dRightX, dRightY ; + for ( int p = 0 ; p < 3; ++p) { + if ( ! vbOn[p]) { + if ( nInters == 0 || nInters == 2) { + dRightX = vPtPa[p].x ; + dRightY = nInters == 0 ? dParamH : 0 ; + } + else if ( nInters == 1 || nInters == 3) { + dRightX = nInters == 1 ? 0 : dParamL ; + dRightY = vPtPa[p].y ; + } + } + } + // correggo le coordinate del punto sull'edge di polo + for ( int p = 0 ; p < 3 ; ++p) { + if ( vbOn[p]) { + vPtPa[p].x = dRightX ; + vPtPa[p].y = dRightY ; + } + } } - // se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice - if ( nIL == 3 ) { + // se l'intersezione era su un vertice ( NON DI POLO) restituisco le coordinate parametriche del vertice + if ( nIL == 3 && ! bIsPole) { if ( AreSamePointApprox(ptI, vPT[0])) ptSP = vPtPa[0] ; else if ( AreSamePointApprox(ptI, vPT[1])) @@ -2260,7 +2447,8 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; int nTriaIndex ; dptSurfTm.GetMinDistTriaIndex( nTriaIndex) ; Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; - UnprojectPointFromStm( nTriaIndex, ptI, ptParam) ; + if ( ! UnprojectPointFromStm( nTriaIndex, ptI, ptParam)) + return false ; Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto @@ -2309,3 +2497,46 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const } return nCount != 99 ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::CalcPoles( void) +{ + // controllo se uno o più lati sono in realtà dei poli + for ( int i = 0 ; i < 4 ; ++i) + m_vbPole.emplace_back( true) ; + // scorro i punti di controllo e vedo subito + bool bOk = false ; + bool bPole0 = true, bPole1 = true ; + Point3d ptU0, ptU1 ; + // controllo l'edge 0 e 2 per vedere se tutti i punti dell'edge sono coincidenti + Point3d ptP00 = GetControlPoint( 0, &bOk) ; + Point3d ptP10 = GetControlPoint( m_nDegU * m_nSpanU, &bOk) ; + for ( int i = 1 ; i < m_nDegV * m_nSpanV + 1 ; ++ i) { + ptU0 = GetControlPoint( i * ( m_nDegU * m_nSpanU + 1), &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptU0) ; + ptU1 = GetControlPoint( ( i + 1) * ( m_nDegU * m_nSpanU + 1) - 1, &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP10, ptU1) ; + if ( ! bPole0 && ! bPole1) + break ; + } + m_vbPole[1] = bPole0 ; + m_vbPole[3] = bPole1 ; + // controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti + Point3d ptV0, ptV1 ; + Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ; + bPole0 = true ; + bPole1 = true ; + for ( int i = 1 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) { + ptV0 = GetControlPoint( i, &bOk) ; + bPole0 = bPole0 && AreSamePointApprox( ptP00, ptV0) ; + ptV1 = GetControlPoint( i + ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ; + bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; + if ( ! bPole0 && ! bPole1) + break ; + } + m_vbPole[0] = bPole0 ; + m_vbPole[2] = bPole1 ; + + return true ; +} diff --git a/SurfBezier.h b/SurfBezier.h index 6e2ae77..be2d6ff 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -112,10 +112,13 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; const SurfTriMesh* GetAuxSurf( void) const override ; bool GetLeaves( std::vector>& vLeaves) const override ; + bool GetTriangles2D( std::vector>& vTria2D) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, int nTPrev = -1) const override ; // a nIL si può passare 5 come valore di default bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const override ; ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; + bool CalcPoles( void) override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -177,13 +180,14 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool m_bTrimmed ; // flag per presenza regione di trim mutable bool m_bClosedU ; // flag che indica se la superficie è chiusa lungo il parametro U mutable bool m_bClosedV ; // flag che indica se la superficie è chiusa lungo il parametro V - mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli + mutable BOOLVECTOR m_vbPole ; // vettore di flag che indicano se i lati sono collassati in dei poli PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei mutable ICRVCOMPOPVECTOR m_vCCEdge ;// vettore delle curve compo degli edge nello spazio 3D + mutable POLYLINEVECTOR m_vPLEdge ; // vettore delle polyline degli edge nello spazio 3D } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index d7cdb1a..2bc1786 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -271,7 +271,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi bPole1 = bPole1 && AreSamePointApprox( ptP01, ptV1) ; } m_vbPole[0] = bPole0 ; - m_vbPole[3] = bPole1 ; + m_vbPole[2] = bPole1 ; if ( bPole0 && bPole1) { m_mTree[0].SetSplitDirVert( false) ; Split( 0) ; From 7a2af0b5f2646bd785094c5b6b4aba75f3f33b0a Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 28 Feb 2024 10:30:49 +0100 Subject: [PATCH 12/31] EgtGeomKernel : - spostato il filtro delle intersezioni Line-SupBez da executor a GeomKernel. --- IntersLineSurfBez.cpp | 72 ++++++++++++++++++++++++++++++++++++++----- SurfBezier.cpp | 45 +-------------------------- 2 files changed, 65 insertions(+), 52 deletions(-) diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index 7ee2c8e..d752710 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -186,18 +186,74 @@ IntersLineSurfBz( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS pSurfBz->GetPointNrmD1D2( ptSP2.x / SBZ_TREG_COEFF, ptSP2.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBz2, vtN) ; dCos2 = vtN * vtL ; } - //IntLinSbzInfo InfoBz( InfoTm.nILTT, dUU, dUU2, InfoTm.nT, dCos, ptIBz, ptIBz2, ptSP, ptSP2) ; - //vInfo.emplace_back( InfoBz) ; UpdateInfoIntersLineSurfBz( ptL, vtL, InfoTm.nILTT, InfoTm.nT, ptSP, ptIBz, dCos, ptSP2, ptIBz2, dCos2, vInfo) ; } OrderInfoIntersLineSurfBz( vInfo) ; - //////////////////////////////////////////////////////// interlineSurfTm - //UpdateInfoIntersLineSurfTm( ptL, vtDir, dLen, nT, Tria, vInfo, bFinite) ; - // OrderInfoIntersLineSurfTm( vInfo) ; - //////////////////////////////////////////////////////// interlineSurfTm - - return true ; +} + +//---------------------------------------------------------------------------- +bool +FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters) +{ + // tengo per buone la classificazione delle intersezioni fatte sulla trimesh + // ciclo sulle intersezioni + for ( const auto& Info : vInfo) { + // se intersezione puntuale + if ( Info.nILTT == ILTT_VERT || Info.nILTT == ILTT_EDGE || Info.nILTT == ILTT_IN) { + int nFlag = LSBT_TOUCH ; + if ( Info.dCosDN > EPS_ZERO) + nFlag = LSBT_OUT ; + else if ( Info.dCosDN < -EPS_ZERO) + nFlag = LSBT_IN ; + vInters.emplace_back( nFlag, Info.dU) ; + } + // se altrimenti intersezione con coincidenza + else if ( Info.nILTT == ILTT_SEGM || Info.nILTT == ILTT_SEGM_ON_EDGE) { + vInters.emplace_back( LSBT_TG_INI, Info.dU) ; + vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ; + } + } + // elimino intersezioni ripetute + for ( size_t j = 1 ; j < vInters.size() ; ) { + // intersezione precedente + size_t i = j - 1 ; + // se hanno lo stesso parametro + if ( abs( vInters[i].second - vInters[j].second) < EPS_SMALL) { + // se sono entrambe entranti o uscenti, elimino la seconda + if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_IN) || + ( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_OUT)) { + vInters.erase( vInters.begin() + j) ; + continue ; + } + // se una entrante e l'altra uscente, cambio in touch ed elimino la seconda + else if ( ( vInters[i].first == LSBT_IN && vInters[j].first == LSBT_OUT) || + ( vInters[i].first == LSBT_OUT && vInters[j].first == LSBT_IN)) { + vInters[i].first = LSBT_TOUCH ; + vInters.erase( vInters.begin() + j) ; + continue ; + } + // se una puntuale e l'altra inizio di coincidenza, elimino la prima + else if ( ( vInters[i].first == LSBT_IN || vInters[i].first == LSBT_OUT || vInters[i].first == LSBT_TOUCH) && vInters[j].first == LSBT_TG_INI) { + vInters.erase( vInters.begin() + i) ; + continue ; + } + // se una fine di coincidenza e l'altra puntuale, elimino la seconda + else if ( vInters[i].first == LSBT_TG_FIN && ( vInters[j].first == LSBT_IN || vInters[j].first == LSBT_OUT || vInters[j].first == LSBT_TOUCH)) { + vInters.erase( vInters.begin() + j) ; + continue ; + } + // se una fine di coincidenza e l'altra inizio di coincidenza, elimino entrambe + else if ( i > 0 && vInters[i].first == LSBT_TG_FIN && vInters[j].first == LSBT_TG_INI) { + vInters.erase( vInters.begin() + j) ; + vInters.erase( vInters.begin() + i) ; + -- j ; + continue ; + } + } + // passo alla successiva + ++ j ; + } } \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index f98f28a..c154435 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -35,7 +35,6 @@ #include "/EgtDev/Include/EGkDistPointSurfTm.h" #include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Include/EGkCurveComposite.h" -#include "/EgtDev/Include/EGkGeoObjSave.h" #include using namespace std ; @@ -1748,13 +1747,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) Point3d ptNear = ( vBPnt.empty() ? ORIG : vBPnt[0].first) ; INTVECTOR vId ; - // debug///////////////////////////////////////////////////////// - //vector vGeoObj ; - //vGeoObj.push_back( static_cast(vCCEdge[1])) ; - //vGeoObj.push_back( static_cast(vCCEdge[3])) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_3d_edges.nge") ; - // debug///////////////////////////////////////////////////////// - // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; @@ -1834,12 +1826,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; } - ////debug - //vector vGeoObj ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; - ////debug + if ( int( vpCCOpen.size()) != 0) { // devo verificare se devo giuntare la prima curva aperta con l'ultima Point3d ptStartOpen, ptEndOpen ; @@ -1851,12 +1838,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vpCCOpen.erase( vpCCOpen.begin()) ; } } - ////debug - //vector vGeoObj2 ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; - ////debug //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; @@ -1870,15 +1851,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pNewTrim.Set( GetTrimRegion()->Clone()) ; else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - ////debug - //PtrOwner pSrfCopy( pNewTrim->Clone()) ; - //SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; - ////debug - - ////debug - //PtrOwner pCrvCopy( pNewTrim->GetLoop(0,0)) ; - //SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_actualTrimRegionEdge.nge") ; - ////debug for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { @@ -2088,11 +2060,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } - ////debug - //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_flip.nge", GDB_SV_BIN) ; - ////debug - // aggiorno la superficie di trim Point3d ptStart ; Vector3d vtDir, vtDirS, vtDirE ; @@ -2135,11 +2102,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - ////debug - //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - ////debug - // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { if ( ! SetTrimRegion( *pSFR, false) || ! m_pTrimReg->IsValid()) @@ -2152,11 +2114,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // imposto ricalcolo della grafica m_OGrMgr.Reset() ; - - ////debug - //PtrOwner pSrfFR_Copy3( GetTrimRegion()->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy3), "D:\\Temp\\inters\\trimmed_paramSpace.nge", GDB_SV_BIN) ; - ////debug return true ; } From 96ea6bc73e0dc4654a27e95bfda10b4bd51f4210 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 1 Mar 2024 11:37:12 +0100 Subject: [PATCH 13/31] EgtGeomKernel : - correzioni al cut di una superficie Bezier. --- IntersLineSurfBez.cpp | 1 + SurfBezier.cpp | 307 ++++++++++++++++++++++++++++++------------ SurfBezier.h | 6 +- Tree.cpp | 9 +- 4 files changed, 231 insertions(+), 92 deletions(-) diff --git a/IntersLineSurfBez.cpp b/IntersLineSurfBez.cpp index d752710..3f792e7 100644 --- a/IntersLineSurfBez.cpp +++ b/IntersLineSurfBez.cpp @@ -256,4 +256,5 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters) // passo alla successiva ++ j ; } + return true ; } \ No newline at end of file diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c154435..d2cd281 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -36,6 +36,7 @@ #include "/EgtDev/Extern/Eigen/Dense" #include "/EgtDev/Include/EGkCurveComposite.h" #include +#include "/EgtDev/Include/EGkGeoObjSave.h" using namespace std ; @@ -1620,15 +1621,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const const ICurve* pCrv0 = pCC->GetCurve( 0) ; PolyLine pl ; Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ; - DistPointSurfTm distPtStm0( pt3D, *GetAuxSurf()) ; - // aggiungo il primo punto - int nTriaIndex ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; - // passo anche i riferimenti del prossimo punto Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; - DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ; - int nTriaIndexNext = -1 ; - distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ; - if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, pt3DEnd, nTriaIndexNext)) + if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd)) return nullptr ; //if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D)) { // Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; @@ -1641,17 +1635,13 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const //} pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi - int nTriaIndexPrev = nTriaIndex ; for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; Point3d pt3DPrev = pt3D ; pCrv->GetEndPoint( pt3D) ; - DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ; - distPtStm.GetMinDistTriaIndex( nTriaIndex) ; - if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D, 5, pt3DPrev, nTriaIndexPrev)) + if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev)) return nullptr ; pl.AddUPoint( i, pt2D) ; - nTriaIndexPrev = nTriaIndex ; } PtrOwner pCC2D ( CreateCurveComposite()) ; pCC2D->FromPolyLine( pl) ; @@ -1660,8 +1650,12 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const //---------------------------------------------------------------------------- bool -SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler) +SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler) { + //debug + vpCC3D.emplace_back( pCrvCompo->Clone()) ; + //debug + // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando double dCrvLen ; if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) @@ -1717,6 +1711,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim + ////debug + //PtrOwner pSFRTrim ( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSFRTrim), "D:\\Temp\\inters\\original_trim.nge", GDB_SV_BIN) ; + ////debug + PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; @@ -1731,6 +1730,16 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //////i tagli multipli//////////////////////////////////////////////// IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; + ////debug + //vector vGeoObj3 ; + //for ( int i = 0 ; i < int(m_vCCEdge.size()); ++i ) { + // if ( ! m_vCCEdge[i]->IsValid()) + // continue ; + // vGeoObj3.emplace_back(static_cast( m_vCCEdge[i]->Clone())) ; + //} + //SaveGeoObj( vGeoObj3, "D:\\Temp\\inters\\Edge3D.nge") ; + ////debug + // concateno le curve 3d ChainCurves chainC ; double dToler = EPS_SMALL ; @@ -1750,6 +1759,9 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; + //debug + ICRVCOMPOPOVECTOR vpCC3D ; + //debug while ( chainC.GetChainFromNear( ptNear, false, vId)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; @@ -1798,23 +1810,53 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) else if ( icc3.GetIntersCount() != 0) icc3.GetIntCrvCrvInfo( 0, iccInfo) ; + if ( i == 48 ) { + //debug + vector vGeoObj5 ; + vGeoObj5.emplace_back(static_cast( pLine->Clone())) ; + vGeoObj5.emplace_back(static_cast( m_vCCEdge[1]->GetCurve(12)->Clone())) ; + SaveGeoObj( vGeoObj5, "D:\\Temp\\inters\\inters3D_error.nge") ; + //debug + } + + ICurveLine* pCLPart1 ( CreateCurveLine()) ; // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root Vector3d vtDir ; pLine->GetStartDir( vtDir) ; Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; - pCLPart1->Set( ptStart, ptBeforeTheEdge) ; - pCrvCompo->AddCurve( pCLPart1, true, dToler) ; - bAdded = false ; - AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; - pCrvCompo->Clear() ; - // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato - // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject - //ICurveLine* pCLPart2 ( CreateCurveLine()) ; - Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; - //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; - //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; - ptNear = ptBeyondTheEdge ; - bPrevLineThroughEdge = true ; + // se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova + // a partire dall'intersezione + if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + pCLPart1->Set( ptStart, ptBeforeTheEdge) ; + pCrvCompo->AddCurve( pCLPart1, true, dToler) ; + bAdded = false ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; + pCrvCompo->Clear() ; + // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato + // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject + //ICurveLine* pCLPart2 ( CreateCurveLine()) ; + Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; + //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; + //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; + ptNear = ptBeyondTheEdge ; + bPrevLineThroughEdge = true ; + --i ; + } + else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) { + // se l'intersezione era all'inizio allora aggiungo e basta + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + // se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova + // indipendente dall'interesezione + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; + pCrvCompo->Clear() ; + ptNear = ( bAdded ? ptEnd : ptStart) ; + } } } // sennò procedo normalmente aggiungendo il punto @@ -1824,36 +1866,75 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bPrevLineThroughEdge = false ; } } - AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ; + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + return false ; } + ////debug + //vector vGeoObj4 ; + //for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) + // vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; + //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; + ////debug + + //debug + vector vGeoObj ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + //debug + if ( int( vpCCOpen.size()) != 0) { - // devo verificare se devo giuntare la prima curva aperta con l'ultima + //// devo verificare se devo giuntare la prima curva aperta con l'ultima + //Point3d ptStartOpen, ptEndOpen ; + //vpCCOpen.front()->GetStartPoint( ptStartOpen) ; + //vpCCOpen.back()->GetEndPoint( ptEndOpen) ; + //if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { + // vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; + // Release( vpCCOpen[0]) ; + // vpCCOpen.erase( vpCCOpen.begin()) ; + //} + + // devo controllare se devo giuntare queste curve aperte tra loro Point3d ptStartOpen, ptEndOpen ; - vpCCOpen.front()->GetStartPoint( ptStartOpen) ; - vpCCOpen.back()->GetEndPoint( ptEndOpen) ; - if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { - vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; - Release( vpCCOpen[0]) ; - vpCCOpen.erase( vpCCOpen.begin()) ; + for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) { + // controllo se la fine di questa curva coincide con lo start di un'altra + } } + ////debug + //vector vGeoObj2 ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + ////debug //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { // qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie // recupero la regione attuale - unordered_map mInters ; - // costruisco la mappa delle intersezioni + + PtrOwner pNewTrim( CreateBasicSurfFlatRegion()) ; if ( m_bTrimmed) pNewTrim.Set( GetTrimRegion()->Clone()) ; else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; + ////debug + //PtrOwner pSrfCopy( pNewTrim->Clone()) ; + //SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; + ////debug + + // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region + unordered_map mInters ; + //chunk for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + // loop for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + bool bHasSomeIntersection = false ; + // trim for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; // prima curva è il loop, seconda curva è il loop @@ -1866,8 +1947,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vICC.emplace_back( iccInfo) ; } mInters.insert( pair( TRINT(c,l,t), vICC)) ; + bHasSomeIntersection = true ; } } + // se un trim non fa intersezioni allora c'è qualcosa di sbagliato + if ( ! bHasSomeIntersection) + return false ; } } @@ -2102,6 +2187,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW + ////debug + //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + ////debug + // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { if ( ! SetTrimRegion( *pSFR, false) || ! m_pTrimReg->IsValid()) @@ -2112,6 +2202,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } + ////debug + //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + ////debug + // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2122,20 +2217,29 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bool SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const { - return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1), -1) ; + return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1)) ; } //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, int nTPrev) const +SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext) const { // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche const ISurfTriMesh* pSurfTm = GetAuxSurf() ; + int nTriaIndex = nT ; + if ( nT == -1) { + DistPointSurfTm distPtStm0( ptI, *pSurfTm) ; + distPtStm0.GetMinDistTriaIndex( nTriaIndex) ; + } + // aggiungo il primo punto // devo subito capire se sono in un polo o no // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto bool bIsPole = false ; int nInters = 0 ; INTVECTOR vInters ; + // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles + if ( int( m_vbPole.size()) == 0) + return false ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3]) { for ( int c = 0 ; c < 4 ; ++c) { if ( ! m_vCCEdge[c]->IsValid()) { @@ -2169,17 +2273,23 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // return false ; // visto che sono in un polo devo verificare di aver ricevuto il triangolo giusto - // mi sposto verso il punto successivo o precedente e ricalcolo il triangolo di appartenenza + // se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza + if ( AreSamePointExact( ptIPrevOrNext, Point3d(-1,-1,-1))){ // controllo che non sia quello definito di default + DistPointSurfTm dPtStm( ptIPrevOrNext, *pSurfTm) ; + double dDist = INFINITO ; dPtStm.GetDist( dDist) ; + if ( dDist > 0.1) + return false ; + } Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ; // ricalcolo il triangolo di appartenenza DistPointSurfTm dPtStm( ptI2, *pSurfTm) ; - dPtStm.GetMinDistTriaIndex( nT) ; + dPtStm.GetMinDistTriaIndex( nTriaIndex) ; } } // recupero i dati dei vertici del triangolo che fa intersezione int nVert[3] ; - pSurfTm->GetTriangle( nT, nVert) ; + pSurfTm->GetTriangle( nTriaIndex, nVert) ; PNTVECTOR vPtPa(3) ; pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; @@ -2211,7 +2321,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in vtDir.Normalize() ; // se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice // siano da correggere per periodicità - if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.95 ) { + if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) { // trovo se dei punti del triangolo sono sul bordo dello spazio parametrico BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { @@ -2250,7 +2360,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } - else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.95) { + else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) { BOOLVECTOR vbOn(3) ; for ( int p = 0 ; p < 3; ++p ) { if ( ! m_vCCEdge[0]->IsValid()) { @@ -2395,64 +2505,89 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const +SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const { // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D // ripeto cercando di avvicinarmi il più possibile // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; - int nTriaIndex ; dptSurfTm.GetMinDistTriaIndex( nTriaIndex) ; Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; - if ( ! UnprojectPointFromStm( nTriaIndex, ptI, ptParam)) + if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev)) return false ; Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto double dDistNew = Dist( pt3D, ptBez) ; - double dDistPre = dDistNew ; + double dDistPre ; + double dDist0, dDist1; int nCount = 0 ; double dh = EPS_SMALL ; // metodo di newton in più dimensioni // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. - while ( dDistNew > EPS_SMALL && nCount < 100) { - dDistPre = dDistNew ; - Point3d ptIBzNew1 ; - GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; - dDistNew = Dist( pt3D, ptIBzNew1) ; - double dfdU = ( dDistNew - dDistPre) / dh ; - Point3d ptIBzNew2 ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; - dDistNew = Dist( pt3D, ptIBzNew2) ; - double dfdV = ( dDistNew - dDistPre) / dh ; - //// opzione 0 - ////scelgo h1 e h2 separatamente e in modo da annullare f(x) - //// opzione 1 - //// valore fisso - //double dr = EPS_SMALL ; - //if ( dDistPre > 1) - // dr = 1 ; - //else if ( dDistPre > 0.1) - // dr = 0.1 ; - //else if ( dDistPre > 0.01) - // dr = 0.01 ; - //// opzione 2 - //// valore direttamente vincolato - //double dr = dDistPre ; - //// opzione 3 - //// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve - //double dh1 = Dist( ptIBz, ptIBzNew1) ; - //double dh2 = Dist( ptIBz, ptIBzNew2) ; - // potrei valutare il nuovo spostamento in base all'ultima variazione di dDist - // potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico) - // mi avvicino cercando di annullare la distanza in un colpo solo - double dr = - dDistPre / ( dfdU + dfdV) ; - GetPointD1D2(( ptParam.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptParam.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + bool bRetry = false ; + double dApproach = 0.01 ; + bool bDesperate = false ; + double dAng = 1 ; + double dr = 5 ; + double dfdU, dfdV ; + while ( dDistNew > 3 * EPS_SMALL && nCount < 100) { + if ( ! bRetry) { + dDistPre = dDistNew ; + // derivata in U + Point3d ptIBzNew1 ; + GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + dDist0 = Dist( pt3D, ptIBzNew1) ; + dfdU = ( dDist0 - dDistPre) / dh ; + // derivata in V + Point3d ptIBzNew2 ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + dDist1 = Dist( pt3D, ptIBzNew2) ; + dfdV = ( dDist1 - dDistPre) / dh ; + } + // calcolo le nuove coordinate + Vector3d vtDir ; + double dASum = abs(dfdU) + abs(dfdV) ; + double dSSum = sqrt( pow(dfdU,2) + pow( dfdV,2)) ; + vtDir.Set( - dfdU, - dfdV, 0) ; + if ( ! vtDir.Normalize() ) + vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ; + dr = dDistPre / dASum ; + // in modalità Retry riduco lo spostamento + vtDir *= dr * ( bRetry ? 0.1 : 0.5) ; + if ( bDesperate) { + // in depserate mode riduco lo spostamento e comincio a cambiare progressivamente la direzione oscillando tra destra e sinistra della direzione "naturale" + vtDir *= 0.5 ; + dAng *= -1.25 ; + // riduco ulteriormente lo spostamento dopo qualche giro in desperate mode + if ( abs( dAng) > 5) + vtDir *= 0.5 ; + vtDir.Rotate( Z_AX, dAng) ; + } + ptParam += vtDir ; + // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; dDistNew = Dist( pt3D, ptBez) ; + dApproach = dDistPre - dDistNew ; + // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode + if ( dApproach < EPS_ZERO) { + if ( bRetry) + bDesperate = true ; // entro in desperate mode + ptParam -= vtDir ; + bRetry = true ; + // se ho già fatto 9 giri in desperate mode allora esco + if ( abs( dAng) > 8) + break ; + } + else { + bRetry = false ; + bDesperate = false ; + dAng = 1 ; + } ++nCount ; } - return nCount != 99 ; + return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } //---------------------------------------------------------------------------- @@ -2477,8 +2612,8 @@ SurfBezier::CalcPoles( void) if ( ! bPole0 && ! bPole1) break ; } - m_vbPole[1] = bPole0 ; - m_vbPole[3] = bPole1 ; + m_vbPole[1] = bPole0 ; // u = 0 corrisponde all'edge 1 + m_vbPole[3] = bPole1 ; // u = 1 corrisponde all'edge 3 // controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti Point3d ptV0, ptV1 ; Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ; @@ -2492,8 +2627,8 @@ SurfBezier::CalcPoles( void) if ( ! bPole0 && ! bPole1) break ; } - m_vbPole[0] = bPole0 ; - m_vbPole[2] = bPole1 ; + m_vbPole[0] = bPole1 ; // v = 1 corrisponde all'edge 0 + m_vbPole[2] = bPole0 ; // v = 0 corrisponde all'edge 2 return true ; } diff --git a/SurfBezier.h b/SurfBezier.h index be2d6ff..724cb0f 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -114,8 +114,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetLeaves( std::vector>& vLeaves) const override ; bool GetTriangles2D( std::vector>& vTria2D) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; - bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, int nTPrev = -1) const override ; // a nIL si può passare 5 come valore di default - bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const override ; + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev) const override ; // a nIL si può passare 5 come valore di default + bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const override ; ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; @@ -166,7 +166,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; double GetCurveOnUApproxLen( double dV) const ; double GetCurveOnVApproxLen( double dU) const ; - bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL) ; + bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler = EPS_SMALL) ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto diff --git a/Tree.cpp b/Tree.cpp index 2bc1786..8b56faf 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3616,7 +3616,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; @@ -3630,7 +3631,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; @@ -3644,7 +3646,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) ++ nPtCount ; // scorro fino alla fine di quel lato while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { - vPLEdges.back().AddUPoint( nPtCount, pt) ; + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + vPLEdges.back().AddUPoint( nPtCount, pt3d) ; ++ nPtCount ; } vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; From 45226d0b6f416d9a4908c32d732dd2aeb8368da4 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 4 Mar 2024 14:51:23 +0100 Subject: [PATCH 14/31] EgtGeomKernel : - correzione errori nel cut delle sup. di Bezier - miglioramento del raffinamento dell'unproject per sup. di Bezier. --- SurfBezier.cpp | 479 +++++++++++++++++++++++++++++++------------------ SurfBezier.h | 6 +- 2 files changed, 311 insertions(+), 174 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d2cd281..d8eca30 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1613,39 +1613,90 @@ SurfBezier::ResetTrimRegion( void) } //---------------------------------------------------------------------------- -ICurveComposite* -SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const +bool +SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const { // do per scontato che la compo sia una spezzata, visto che arriva dall'intersezione tra un piano e una trimesh - + // creo la chain dei punti che sto riportando nel parametrico + ChainCurves chainC ; + double dToler = EPS_SMALL ; + //chainC.Init( false, dToler, int( pCC->GetCurveCount())) ; + chainC.Init( false, dToler, 2) ; + const ICurve* pCrv0 = pCC->GetCurve( 0) ; PolyLine pl ; Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ; Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; - if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd)) - return nullptr ; - //if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D)) { - // Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; - // DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ; - // int nTriaIndexNext = -1 ; - // distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ; - // if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, nTriaIndexNext)) - // return nullptr ; - // nTriaIndex = nTriaIndexNext ; - //} - pl.AddUPoint( 0, pt2D) ; + bool bThroughEdge = false ; + if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd, &bThroughEdge)) + return false ; + + //pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi + BIPNTVECTOR vBPnt ; + BOOLVECTOR vbThroughEdge ; + bThroughEdge = false ; for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; Point3d pt3DPrev = pt3D ; + Point3d pt2DPrev = pt2D ; + if ( bThroughEdge ) { + // devo cambiare le coordinate di pt3DPrev per periodicità + // capisco su quale lato è e lo porto sul lato opposto + if ( m_bClosedU ) { + if ( pt2DPrev.x < 1) + pt2DPrev.x = m_nSpanU * SBZ_TREG_COEFF ; + else if ( (m_nSpanU * SBZ_TREG_COEFF - pt2DPrev.x) < 1) + pt2DPrev.x = 0 ; + } + if ( m_bClosedV ) { + if ( pt2DPrev.y < 1) + pt2DPrev.y = m_nSpanV * SBZ_TREG_COEFF ; + else if ( (m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y) < 1) + pt2DPrev.y = 0 ; + } + } pCrv->GetEndPoint( pt3D) ; - if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev)) - return nullptr ; - pl.AddUPoint( i, pt2D) ; + if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge)) + return false ; + vbThroughEdge.push_back( bThroughEdge) ; + //pl.AddUPoint( i, pt2D) ; + Vector3d vtDir = pt2D - pt2DPrev ; + vtDir.Normalize() ; + vBPnt.emplace_back( BIPOINT( pt2DPrev, pt2D)) ; + if ( ! chainC.AddCurve( i + 1, pt2DPrev, vtDir, pt2D, vtDir)) + return false ; } - PtrOwner pCC2D ( CreateCurveComposite()) ; - pCC2D->FromPolyLine( pl) ; - return Release( pCC2D) ; + // ricostruisco le catene in 2D + Point3d ptNear ; pCrv0->GetStartPoint( ptNear) ; + INTVECTOR vId ; + bool bAdded = true ; + while( chainC.GetChainFromNear( pt3D, false, vId)) { + PtrOwner pCC2D ( CreateCurveComposite()) ; + for ( int i = 0 ; i < int( vId.size()) ; ++ i) { + // creo un segmento di retta + ICurveLine* pLine( CreateCurveLine()) ; + if ( pLine == nullptr) + return false ; + // recupero gli estremi (non vanno mai invertiti per opzione di concatenamento) + int nInd = abs( vId[i]) - 1 ; + Point3d ptStart = ( bAdded ? vBPnt[nInd].first : ptNear) ; + Point3d ptEnd = vBPnt[nInd].second ; + // provo ad accodarlo alla composita + bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && + pLine->Set( ptStart, ptEnd)) ; + bAdded = bAdded && pCC2D->AddCurve( pLine, true, dToler) ; + if ( vbThroughEdge[i]) { + vpCC.emplace_back( Release(pCC2D)) ; + pCC2D.Set( CreateCurveComposite()) ; + } + ptNear = ( bAdded ? ptEnd : ptStart) ; + } + if ( pCC2D->IsValid()) + vpCC.emplace_back( Release(pCC2D)) ; + } + //pCC2D->FromPolyLine( pl) ; + return true ; } //---------------------------------------------------------------------------- @@ -1673,16 +1724,17 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& pCrvCompo->MergeCurves( 0.5 * dToler, ANG_TOL_STD_DEG) ; // porto la curva nello spazio parametrico - PtrOwner pCC( UnprojectCurveFromStm( pCrvCompo)) ; - if ( IsNull( pCC)) + ICRVCOMPOPVECTOR vCC ; + if ( ! UnprojectCurveFromStm( pCrvCompo, vCC)) return false ; - - // le curve aperte le tengo da parte per giuntarle alla fine col bordo - if ( ! pCC->IsClosed()) - vpCCOpen.emplace_back( Release( pCC)) ; - // le curve chiuse le metto tutte insieme subito - else - vpCCClosed.emplace_back( Release( pCC)) ; + for ( int i = 0 ; i < int( vCC.size()); ++i) { + // le curve aperte le tengo da parte per giuntarle alla fine col bordo + if ( ! vCC[i]->IsClosed() ) + vpCCOpen.emplace_back( vCC[i]) ; + // le curve chiuse le metto tutte insieme subito + else + vpCCClosed.emplace_back( vCC[i]) ; + } return true ; } @@ -1769,7 +1821,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita bool bAdded = true ; - bool bPrevLineThroughEdge = false ; + //bool bPrevLineThroughEdge = false ; for ( int i = 0 ; i < int( vId.size()) ; ++ i) { // creo un segmento di retta ICurveLine* pLine( CreateCurveLine()) ; @@ -1782,133 +1834,131 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // provo ad accodarlo alla composita bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && pLine->Set( ptStart, ptEnd)) ; - // se la superficie è chiusa devo controllare se sto attraversando un edge con un trim - if ( (m_bClosedU || m_bClosedV) && ! bPrevLineThroughEdge) { - IntersCurveCurve icc0( *pLine, *m_vCCEdge[0]) ; - IntersCurveCurve icc1( *pLine, *m_vCCEdge[1]) ; - IntersCurveCurve icc2( *pLine, *m_vCCEdge[2]) ; - IntersCurveCurve icc3( *pLine, *m_vCCEdge[3]) ; - // se non ho intersezioni proseguo aggiungendo il punto - if ( icc0.GetIntersCount() == 0 && - icc1.GetIntersCount() == 0 && - icc2.GetIntersCount() == 0 && - icc3.GetIntersCount() == 0) { - // se non ho intersezioni con gli edge posso aggiungere semplicemente alla compo - bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - } - else { - // recupero la prima intersezione che trovo - // se ho intersezioni multiple è perché sono edge sovrapposti - IntCrvCrvInfo iccInfo ; - if ( icc0.GetIntersCount() != 0) - icc0.GetIntCrvCrvInfo( 0, iccInfo) ; - else if ( icc1.GetIntersCount() != 0) - icc1.GetIntCrvCrvInfo( 0, iccInfo) ; - else if ( icc2.GetIntersCount() != 0) - icc2.GetIntCrvCrvInfo( 0, iccInfo) ; - else if ( icc3.GetIntersCount() != 0) - icc3.GetIntCrvCrvInfo( 0, iccInfo) ; + bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + ptNear = ( bAdded ? ptEnd : ptStart) ; - if ( i == 48 ) { - //debug - vector vGeoObj5 ; - vGeoObj5.emplace_back(static_cast( pLine->Clone())) ; - vGeoObj5.emplace_back(static_cast( m_vCCEdge[1]->GetCurve(12)->Clone())) ; - SaveGeoObj( vGeoObj5, "D:\\Temp\\inters\\inters3D_error.nge") ; - //debug - } + // // se la superficie è chiusa devo controllare se sto attraversando un edge con un trim + // if ( (m_bClosedU || m_bClosedV) && ! bPrevLineThroughEdge) { + // IntersCurveCurve icc0( *pLine, *m_vCCEdge[0]) ; + // IntersCurveCurve icc1( *pLine, *m_vCCEdge[1]) ; + // IntersCurveCurve icc2( *pLine, *m_vCCEdge[2]) ; + // IntersCurveCurve icc3( *pLine, *m_vCCEdge[3]) ; + // // se non ho intersezioni proseguo aggiungendo il punto + // if ( icc0.GetIntersCount() == 0 && + // icc1.GetIntersCount() == 0 && + // icc2.GetIntersCount() == 0 && + // icc3.GetIntersCount() == 0) { + // // se non ho intersezioni con gli edge posso aggiungere semplicemente alla compo + // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + // ptNear = ( bAdded ? ptEnd : ptStart) ; + // } + // else { + // // recupero la prima intersezione che trovo + // // se ho intersezioni multiple è perché sono edge sovrapposti + // IntCrvCrvInfo iccInfo ; + // if ( icc0.GetIntersCount() != 0) + // icc0.GetIntCrvCrvInfo( 0, iccInfo) ; + // else if ( icc1.GetIntersCount() != 0) + // icc1.GetIntCrvCrvInfo( 0, iccInfo) ; + // else if ( icc2.GetIntersCount() != 0) + // icc2.GetIntCrvCrvInfo( 0, iccInfo) ; + // else if ( icc3.GetIntersCount() != 0) + // icc3.GetIntCrvCrvInfo( 0, iccInfo) ; - - ICurveLine* pCLPart1 ( CreateCurveLine()) ; - // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root - Vector3d vtDir ; pLine->GetStartDir( vtDir) ; - Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; - // se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova - // a partire dall'intersezione - if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { - pCLPart1->Set( ptStart, ptBeforeTheEdge) ; - pCrvCompo->AddCurve( pCLPart1, true, dToler) ; - bAdded = false ; - if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) - return false ; - pCrvCompo->Clear() ; - // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato - // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject - //ICurveLine* pCLPart2 ( CreateCurveLine()) ; - Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; - //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; - //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; - ptNear = ptBeyondTheEdge ; - bPrevLineThroughEdge = true ; - --i ; - } - else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) { - // se l'intersezione era all'inizio allora aggiungo e basta - bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - } - else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { - // se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova - // indipendente dall'interesezione - bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) - return false ; - pCrvCompo->Clear() ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - } - } - } - // sennò procedo normalmente aggiungendo il punto - else { - bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - ptNear = ( bAdded ? ptEnd : ptStart) ; - bPrevLineThroughEdge = false ; - } + // ICurveLine* pCLPart1 ( CreateCurveLine()) ; + // // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root + // Vector3d vtDir ; pLine->GetStartDir( vtDir) ; + // Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; + // // se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova + // // a partire dall'intersezione + // if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + // pCLPart1->Set( ptStart, ptBeforeTheEdge) ; + // pCrvCompo->AddCurve( pCLPart1, true, dToler) ; + // bAdded = false ; + // if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + // return false ; + // pCrvCompo->Clear() ; + // // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato + // // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject + // //ICurveLine* pCLPart2 ( CreateCurveLine()) ; + // Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; + // //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; + // //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; + // ptNear = ptBeyondTheEdge ; + // bPrevLineThroughEdge = true ; + // --i ; + // } + // else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) { + // // se l'intersezione era all'inizio allora aggiungo e basta + // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + // ptNear = ( bAdded ? ptEnd : ptStart) ; + // } + // else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { + // // se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova + // // indipendente dall'interesezione + // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + // if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + // return false ; + // pCrvCompo->Clear() ; + // ptNear = ( bAdded ? ptEnd : ptStart) ; + // } + // } + // } + // // sennò procedo normalmente aggiungendo il punto + // else { + // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; + // ptNear = ( bAdded ? ptEnd : ptStart) ; + // bPrevLineThroughEdge = false ; + // } } if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) return false ; } - ////debug - //vector vGeoObj4 ; - //for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) - // vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; - //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; - ////debug - //debug - vector vGeoObj ; - for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; + vector vGeoObj4 ; + for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) + vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; + SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; //debug - if ( int( vpCCOpen.size()) != 0) { - //// devo verificare se devo giuntare la prima curva aperta con l'ultima - //Point3d ptStartOpen, ptEndOpen ; - //vpCCOpen.front()->GetStartPoint( ptStartOpen) ; - //vpCCOpen.back()->GetEndPoint( ptEndOpen) ; - //if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { - // vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; - // Release( vpCCOpen[0]) ; - // vpCCOpen.erase( vpCCOpen.begin()) ; - //} - - // devo controllare se devo giuntare queste curve aperte tra loro - Point3d ptStartOpen, ptEndOpen ; - for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) { - // controllo se la fine di questa curva coincide con lo start di un'altra - - } - } ////debug - //vector vGeoObj2 ; + //vector vGeoObj ; //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; ////debug + //queste righe non servono più perché faccio già il chain mentre porto la curva in 2D + // + //if ( int( vpCCOpen.size()) != 0) { + // //// devo verificare se devo giuntare la prima curva aperta con l'ultima + // //Point3d ptStartOpen, ptEndOpen ; + // //vpCCOpen.front()->GetStartPoint( ptStartOpen) ; + // //vpCCOpen.back()->GetEndPoint( ptEndOpen) ; + // //if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { + // // vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; + // // Release( vpCCOpen[0]) ; + // // vpCCOpen.erase( vpCCOpen.begin()) ; + // //} + // + // // devo controllare se devo giuntare queste curve aperte tra loro + // Point3d ptStartOpen, ptEndOpen ; + // for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) { + // // controllo se la fine di questa curva coincide con lo start di un'altra + + // } + //} + + + + //debug + vector vGeoObj2 ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + //debug + //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { @@ -1929,15 +1979,17 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region unordered_map mInters ; - //chunk - for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { - // loop - for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { - bool bHasSomeIntersection = false ; - // trim - for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + int nInters = 0 ; + bool bStartFound = false ; + bool bEndFound = false ; + // trim + for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + //chunk + for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + // loop + for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; - // prima curva è il loop, seconda curva è il loop + // prima curva è il loop, seconda curva è il trim IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ; if ( icc.GetIntersCount() != 0) { ICCIVECTOR vICC ; @@ -1947,12 +1999,72 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) vICC.emplace_back( iccInfo) ; } mInters.insert( pair( TRINT(c,l,t), vICC)) ; - bHasSomeIntersection = true ; + if ( int( vICC.size() == 2)) { + bStartFound = true ; + bEndFound = true ; + } + else if ( int(vICC.size() == 1) ) { + if ( vICC[0].IciB->dU < EPS_SMALL) + bStartFound = true ; + else + bEndFound = true ; + } + } + nInters += int( icc.GetIntersCount()) ; + } + } + if ( nInters != 2) { + // se un trim non fa 2 intersezioni allora devo estendere la curva allo start e/o all'end per creare le intersezioni + Point3d ptStart ; vpCCOpen[t]->GetStartPoint( ptStart) ; + Point3d ptEnd ; vpCCOpen[t]->GetEndPoint( ptEnd) ; + PtrOwner pCrv( vpCCOpen[t]->Clone()) ; + double dExtension = m_nSpanU > m_nSpanV ? m_nSpanU : m_nSpanV ; + dExtension *= SBZ_TREG_COEFF ; + if ( ! bStartFound) + pCrv->ExtendStartByLen( dExtension) ; + if ( ! bEndFound) + pCrv->ExtendEndByLen( dExtension) ; + double dDistStart = 1e6, dDistEnd = 1e6 ; + // vettore per l'intersezione di start + ICCIVECTOR vICCStart ; + vICCStart.emplace_back() ; + // vettore per l'intersezione di end + ICCIVECTOR vICCEnd ; + vICCEnd.emplace_back() ; + TRINT tStart, tEnd ; + //chunk + for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { + // loop + for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) { + PtrOwner pLoop( pNewTrim->GetLoop( c, l)) ; + // prima curva è il loop, seconda curva è il trim + IntersCurveCurve icc( *pLoop, *pCrv) ; + if ( icc.GetIntersCount() != 0) { + for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) { + IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( i, iccInfo) ; + if ( Dist( iccInfo.IciA->ptI, ptStart) < dDistStart) { + vICCStart[0] = iccInfo ; + tStart = TRINT( c, l, t) ; + } + if ( Dist( iccInfo.IciA->ptI, ptEnd) < dDistEnd) { + vICCEnd[0] = iccInfo ; + tEnd = TRINT( c, l, t) ; + } + } + } } } - // se un trim non fa intersezioni allora c'è qualcosa di sbagliato - if ( ! bHasSomeIntersection) - return false ; + // ricostruisco gli elementi per la mappa mInters + // se ho intersezione con due loop diverse due entry diverse (immediato) + // se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni + if ( tStart == tEnd) { + vICCStart.emplace_back( vICCEnd[0]) ; + mInters.insert( pair(tStart, vICCStart)) ; + } + else { + mInters.insert( pair(tStart, vICCStart)) ; + mInters.insert( pair(tEnd, vICCEnd)) ; + } } } @@ -2125,6 +2237,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( pSFR->GetNormVersor().z < 0) pSFR->Invert() ; + //debug + PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; + //debug + // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio int nChunkMin = 0 , nLoopMin = 0 ; @@ -2188,8 +2305,8 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 2. se il punto è sotto il piano ed era interno ad una curva CW ////debug - //PtrOwner pSrfFR_Copy( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; ////debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente @@ -2202,10 +2319,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } - ////debug - //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; - ////debug + //debug + PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + //debug // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2222,8 +2339,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext) const +SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, bool* bThroughEdge) const { + if ( bThroughEdge != nullptr) + *bThroughEdge = false ; // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche const ISurfTriMesh* pSurfTm = GetAuxSurf() ; int nTriaIndex = nT ; @@ -2240,7 +2359,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles if ( int( m_vbPole.size()) == 0) return false ; - if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3]) { + if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3] || m_bClosedU || m_bClosedV) { for ( int c = 0 ; c < 4 ; ++c) { if ( ! m_vCCEdge[c]->IsValid()) { Point3d pt ; @@ -2255,8 +2374,9 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } // se ho tre intersezioni vuol dire che un lato è collassato in un punto e il punto di cui voglio la controimmagine è esattamente nel polo - if ( nInters == 3) { - bIsPole = true ; + if ( nInters == 3 || ( m_bClosedU && ( vInters[1] == 1 || vInters[3] == 1)) || ( m_bClosedV && ( vInters[1] == 1 || vInters[3] == 1))) { + if ( nInters == 3) + bIsPole = true ; //// salvo pure come triangolo di riferimento quello del punto precedente //const ISurfTriMesh* pSurfTm2 = GetAuxSurf() ; //int nVert[3] ; @@ -2272,14 +2392,16 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // // parametriche di questo punto // return false ; - // visto che sono in un polo devo verificare di aver ricevuto il triangolo giusto + // visto che sono in un polo o su un lato di chiusura devo verificare di aver ricevuto il triangolo giusto // se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza if ( AreSamePointExact( ptIPrevOrNext, Point3d(-1,-1,-1))){ // controllo che non sia quello definito di default DistPointSurfTm dPtStm( ptIPrevOrNext, *pSurfTm) ; double dDist = INFINITO ; dPtStm.GetDist( dDist) ; - if ( dDist > 0.1) + if ( dDist > 0.2) return false ; } + if ( bThroughEdge != nullptr) + *bThroughEdge = true ; Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ; // ricalcolo il triangolo di appartenenza DistPointSurfTm dPtStm( ptI2, *pSurfTm) ; @@ -2505,7 +2627,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const +SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bThroughEdge) const { // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D @@ -2513,7 +2635,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; - if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev)) + if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) return false ; Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; @@ -2532,7 +2654,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dAng = 1 ; double dr = 5 ; double dfdU, dfdV ; - while ( dDistNew > 3 * EPS_SMALL && nCount < 100) { + while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { if ( ! bRetry) { dDistPre = dDistNew ; // derivata in U @@ -2587,6 +2709,21 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d } ++nCount ; } + // se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto + if ( bThroughEdge != nullptr && *bThroughEdge) { + if ( m_bClosedU ) { + if ( ptParam.x < abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x)) + ptParam.x = 0 ; + else + ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; + } + if ( m_bClosedV ) { + if ( ptParam.y < abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y)) + ptParam.y = 0 ; + else + ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; + } + } return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } diff --git a/SurfBezier.h b/SurfBezier.h index 724cb0f..195f7fd 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -114,9 +114,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetLeaves( std::vector>& vLeaves) const override ; bool GetTriangles2D( std::vector>& vTria2D) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; - bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev) const override ; // a nIL si può passare 5 come valore di default - bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const override ; - ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ; + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; // a nIL si può passare 5 come valore di default + bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; + bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; From bf3760808e1a3580fedcc87b69c5ace0748df951 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 5 Mar 2024 17:17:12 +0100 Subject: [PATCH 15/31] EgtGeomKernel : - correzione di errori nella gestione del taglio sul polo e sul bordo di chiusura di una sup. di Bezier. --- SurfBezier.cpp | 544 ++++++++++++++++++++++++++++++++----------------- SurfBezier.h | 1 + 2 files changed, 358 insertions(+), 187 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d8eca30..39f0e90 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1612,6 +1612,42 @@ SurfBezier::ResetTrimRegion( void) m_OGrMgr.Reset() ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV) const +{ + dUV += dxy ; + if ( bUOrV) { + if ( dUV < 0) { + if ( m_bClosedU) + dUV += m_nSpanU * SBZ_TREG_COEFF ; + else + dUV = 0 ; + } + if ( dUV > m_nSpanU * SBZ_TREG_COEFF ) { + if ( m_bClosedU) + dUV -= m_nSpanU * SBZ_TREG_COEFF ; + else + dUV = m_nSpanU * SBZ_TREG_COEFF ; + } + } + else { + if ( dUV ) { + if ( m_bClosedV) + dUV += m_nSpanV * SBZ_TREG_COEFF ; + else + dUV = 0 ; + } + if ( dUV > m_nSpanV * SBZ_TREG_COEFF ) { + if ( m_bClosedU) + dUV -= m_nSpanV * SBZ_TREG_COEFF ; + else + dUV = m_nSpanV * SBZ_TREG_COEFF ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const @@ -1628,43 +1664,79 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ; Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; bool bThroughEdge = false ; + BOOLVECTOR vbThroughEdge ; if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd, &bThroughEdge)) return false ; + vbThroughEdge.push_back( bThroughEdge) ; //pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi BIPNTVECTOR vBPnt ; - BOOLVECTOR vbThroughEdge ; + bThroughEdge = false ; + int nRejected = 0 ; for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) { const ICurve* pCrv = pCC->GetCurve( i) ; Point3d pt3DPrev = pt3D ; Point3d pt2DPrev = pt2D ; - if ( bThroughEdge ) { - // devo cambiare le coordinate di pt3DPrev per periodicità + bool bPrevIsPole = false ; + if ( bThroughEdge) { + // devo cambiare le coordinate di pt2DPrev per periodicità // capisco su quale lato è e lo porto sul lato opposto - if ( m_bClosedU ) { + Point3d pt = pt2DPrev ; + if ( m_bClosedU) { if ( pt2DPrev.x < 1) pt2DPrev.x = m_nSpanU * SBZ_TREG_COEFF ; else if ( (m_nSpanU * SBZ_TREG_COEFF - pt2DPrev.x) < 1) pt2DPrev.x = 0 ; } - if ( m_bClosedV ) { + if ( m_bClosedV) { if ( pt2DPrev.y < 1) pt2DPrev.y = m_nSpanV * SBZ_TREG_COEFF ; else if ( (m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y) < 1) pt2DPrev.y = 0 ; } + bPrevIsPole = AreSamePointApprox( pt, pt2DPrev) ; } pCrv->GetEndPoint( pt3D) ; if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge)) return false ; - vbThroughEdge.push_back( bThroughEdge) ; + if ( bPrevIsPole) { + // se il punto precedente era di polo allora devo correggere le sue coordinate 2D + if ( ( m_vbPole[0] || m_vbPole[2] )) { + if ( pt2DPrev.y < 1 || m_nSpanV * SBZ_TREG_COEFF - pt2DPrev.y < 1) + pt2DPrev.x = pt2D.x ; + } + if ( ( m_vbPole[1] || m_vbPole[3] )) { + if ( pt2DPrev.x < 1 || m_nSpanU * SBZ_TREG_COEFF - pt2DPrev.x < 1) + pt2DPrev.y = pt2D.y ; + } + } //pl.AddUPoint( i, pt2D) ; Vector3d vtDir = pt2D - pt2DPrev ; vtDir.Normalize() ; + // se mi accorgo che sto per tracciare un taglio lungo un bordo posso semplicmente evitarlo + if ( (1 - abs(vtDir.x) < EPS_SMALL && (pt2D.y < EPS_SMALL || m_nSpanV * SBZ_TREG_COEFF - pt2D.y < 1)) || // parallelo agli edge 0 e 2 e su uno di questi + (1 - abs(vtDir.y) < EPS_SMALL && (pt2D.x < EPS_SMALL || m_nSpanU * SBZ_TREG_COEFF - pt2D.x < 1))) { // parallello agli edge 1 e 3 e su uno di questi + ++ nRejected ; + continue ; + } + if ( bThroughEdge && vbThroughEdge.back()) { + double dParamH, dParamL ; + dParamH = m_nSpanV * SBZ_TREG_COEFF ; + dParamL = m_nSpanU * SBZ_TREG_COEFF ; + // sia questo punto che il precedente sono su un edge, ma il segmento che li unisce non è parallelo ad un edge + // potrei star tracciando un taglio sul bordo di chiusura + // controllo se sto tracciando una linea che unisce due lati di chiusura, allora in realtà sdtarei tracciando un taglio sull'edge e quindi posso non tracciarlo + if ( (abs( vtDir.x) > abs( vtDir.y) && Dist( pt2D, pt2DPrev) > dParamL * 0.5) || + (abs( vtDir.y) > abs( vtDir.x) && Dist( pt2D, pt2DPrev) > dParamH * 0.5)) { + ++ nRejected ; + continue ; + } + } + vbThroughEdge.push_back( bThroughEdge) ; vBPnt.emplace_back( BIPOINT( pt2DPrev, pt2D)) ; - if ( ! chainC.AddCurve( i + 1, pt2DPrev, vtDir, pt2D, vtDir)) + if ( ! chainC.AddCurve( i + 1 - nRejected, pt2DPrev, vtDir, pt2D, vtDir)) return false ; } // ricostruisco le catene in 2D @@ -1686,10 +1758,10 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && pLine->Set( ptStart, ptEnd)) ; bAdded = bAdded && pCC2D->AddCurve( pLine, true, dToler) ; - if ( vbThroughEdge[i]) { - vpCC.emplace_back( Release(pCC2D)) ; - pCC2D.Set( CreateCurveComposite()) ; - } + //if ( vbThroughEdge[i]) { + // vpCC.emplace_back( Release(pCC2D)) ; + // pCC2D.Set( CreateCurveComposite()) ; + //} ptNear = ( bAdded ? ptEnd : ptStart) ; } if ( pCC2D->IsValid()) @@ -2042,11 +2114,13 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( icc.GetIntersCount() != 0) { for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) { IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( i, iccInfo) ; - if ( Dist( iccInfo.IciA->ptI, ptStart) < dDistStart) { + if ( ! bStartFound && Dist( iccInfo.IciA->ptI, ptStart) < dDistStart) { + dDistStart = Dist( iccInfo.IciA->ptI, ptStart) ; vICCStart[0] = iccInfo ; tStart = TRINT( c, l, t) ; } - if ( Dist( iccInfo.IciA->ptI, ptEnd) < dDistEnd) { + if ( ! bEndFound && Dist( iccInfo.IciA->ptI, ptEnd) < dDistEnd) { + dDistEnd = Dist( iccInfo.IciA->ptI, ptEnd) ; vICCEnd[0] = iccInfo ; tEnd = TRINT( c, l, t) ; } @@ -2054,23 +2128,47 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } + // ricostruisco gli elementi per la mappa mInters - // se ho intersezione con due loop diverse due entry diverse (immediato) - // se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni - if ( tStart == tEnd) { - vICCStart.emplace_back( vICCEnd[0]) ; - mInters.insert( pair(tStart, vICCStart)) ; + if ( ! bStartFound && ! bEndFound) { + if ( tStart == tEnd) { + // se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni + vICCStart.emplace_back( vICCEnd[0]) ; + mInters.insert( pair(tStart, vICCStart)) ; + } + else{ + // se ho intersezione con due loop diverse due entry diverse le inserisco + mInters.insert( pair(tStart, vICCStart)) ; + mInters.insert( pair(tEnd, vICCEnd)) ; + } + // ridefinisco il taglio aperto con la sua versione estesa che arriva a toccare i loop dello spazio parametrico + vpCCOpen[t].Set( GetCurveComposite(pCrv->CopyParamRange( vICCStart[0].IciB->dU, vICCEnd[0].IciB->dU))) ; } else { - mInters.insert( pair(tStart, vICCStart)) ; - mInters.insert( pair(tEnd, vICCEnd)) ; + // devo verificare se avevo già trovato una delle due intersezioni e se era sullo stesso loop o no + if ( ! bStartFound) { + if ( mInters.count( tStart) ==1) + mInters[tStart].emplace_back( vICCStart[0]) ; + else + mInters.insert( pair( tStart, vICCStart)) ; + pCrv->TrimStartAtParam( vICCStart[0].IciB->dU) ; + vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ; + } + if ( ! bEndFound) { + if ( mInters.count( tEnd) == 1) + mInters[tEnd].emplace_back( vICCEnd[0]) ; + else + mInters.insert( pair( tEnd, vICCEnd)) ; + pCrv->TrimEndAtParam( vICCEnd[0].IciB->dU) ; + vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ; + } } } } // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; - fill(vbAdded.begin(), vbAdded.end(), false) ; + std::fill( vbAdded.begin(), vbAdded.end(), false) ; PtrOwner pCCNewEdge( CreateCurveComposite()) ; PtrOwner pCL( CreateCurveLine()) ; //bool bAddedAll = false ; @@ -2272,7 +2370,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //vtDirS.Rotate( Z_AX, bPos? 90 : -90) ; vtDir = vtDirS + vtDirE ; PtrOwner pCL( CreateCurveLine()) ; - pCL->SetPVL( ptStart, vtDirS, 1e6) ; + pCL->SetPVL( ptStart, vtDir, 1e6) ; IntersCurveCurve icc( *pCL, *pCrv) ; IntCrvCrvInfo iccInfo ; // verifico di guardare verso l'interno ( il numero di intersezioni deve essere pari visto che partivo da un punto sulla curva) @@ -2444,78 +2542,129 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice // siano da correggere per periodicità if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) { - // trovo se dei punti del triangolo sono sul bordo dello spazio parametrico - BOOLVECTOR vbOn(3) ; + // trovo se dei vertici del triangolo sono sul bordo dello spazio parametrico + INTVECTOR vOn(3) ; + fill( vOn.begin(), vOn.end(), -1) ; + int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { - if ( ! m_vCCEdge[1]->IsValid()) { - Point3d pt ; - m_vPLEdge[1].GetFirstPoint( pt) ; - vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; - } - else - vbOn[p] = m_vCCEdge[1]->IsPointOn( vPT[p]) ; - if ( ! m_vCCEdge[3]->IsValid()) { - Point3d pt ; - m_vPLEdge[3].GetFirstPoint( pt) ; - vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; - } - else - vbOn[p] = vbOn[p] || m_vCCEdge[3]->IsPointOn( vPT[p]) ; - } - // controllo che almeno un punto sia su un edge - if ( vbOn[0] || vbOn[1] || vbOn[2]) { - double dRightX ; - // tengo per buone le coordinate dei punti che NON sono sul bordo dello spazio parametrico - for ( int p = 0 ; p < 3; ++p) { - if ( !vbOn[p] ) { - dRightX = vPtPa[p].x ; - break ; + for ( int ed = 0 ; ed < 4; ++ed) { + if ( ! m_vCCEdge[ed]->IsValid()) { + Point3d pt ; + m_vPLEdge[ed].GetFirstPoint( pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if (m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) + vOn[p] = ed ; } } - for ( int p = 0 ; p < 3; ++p) { - if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) { - if ( vPtPa[p].x < EPS_SMALL) - vPtPa[p].x = dParamL ; - else - vPtPa[p].x = 0 ; + } + //// controllo che i vertici che stanno su un edge siano davvero sul lato di chiusura e non sull'eventuale polo + + //// se ho poli + //if ( m_vbPole[0] || m_vbPole[2]) { + // // se un vertice sta su un polo me lo segno + // auto it0 = find(vOn.begin(), vOn.end(), 0) ; + // auto it2 = find(vOn.begin(), vOn.end(), 2) ; + // if ( it0 != vOn.end()) { + // bVertOnPole = true ; + // nVertOnPole = it0 - vOn.begin() ; + // } + // if ( it2 != vOn.end() ) { + // bVertOnPole = true ; + // nVertOnPole = it2 - vOn.begin() ; + // } + //} + + // controllo che almeno un vertice sia su un edge e se è l'unico vertice, che non sia su un polo + if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { + // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate + if ( vOn[0] * vOn[1] * vOn[2] < 0 || + (vOn[0] > 0 && vOn[0] != nVertOnPole) || + (vOn[1] > 0 && vOn[1] != nVertOnPole) || + (vOn[2] > 0 && vOn[2] != nVertOnPole)) { + double dRightX ; + // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico + for ( int p = 0 ; p < 3; ++p) { + if ( vOn[p] == -1) { + dRightX = vPtPa[p].x ; + break ; + } + } + for ( int p = 0 ; p < 3; ++p) { + if ( abs(vPtPa[p].x - dRightX) > EPS_SMALL ) { + if ( vPtPa[p].x < EPS_SMALL) + vPtPa[p].x = dParamL ; + else + vPtPa[p].x = 0 ; + } } } } } else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) { - BOOLVECTOR vbOn(3) ; + INTVECTOR vOn(3) ; + fill( vOn.begin(), vOn.end(), -1) ; + int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { - if ( ! m_vCCEdge[0]->IsValid()) { - Point3d pt ; - m_vPLEdge[0].GetFirstPoint( pt) ; - vbOn[p] = AreSamePointApprox( pt, vPT[p]) ; - } - else - vbOn[p] = m_vCCEdge[0]->IsPointOn( vPT[p]) ; - if ( ! m_vCCEdge[2]->IsValid()) { - Point3d pt ; - m_vPLEdge[2].GetFirstPoint( pt) ; - vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; - } - else - vbOn[p] = vbOn[p] || m_vCCEdge[2]->IsPointOn( vPT[p]) ; - } - // controllo che almeno un punto sia su un edge - if ( vbOn[0] || vbOn[1] || vbOn[2]) { - double dRightY ; - // tengo per buone le coordinate dei punti che NON sono sul bordo dello spazio parametrico - for ( int p = 0 ; p < 3; ++p) { - if ( ! vbOn[p]) { - dRightY = vPtPa[p].y ; - break ; + for (int ed = 0 ; ed < 4 ; ++ed) { + if ( ! m_vCCEdge[ed]->IsValid()) { + Point3d pt ; + m_vPLEdge[ed].GetFirstPoint( pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if( m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) + vOn[p] = ed ; } } - for ( int p = 0 ; p < 3; ++p) { - if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) { - if ( vPtPa[p].y < EPS_SMALL) - vPtPa[p].y = dParamH ; - else - vPtPa[p].y = 0 ; + } + //// controllo che i vertici che stanno su un edge siano davvero sul lato di chiusura e non sull'eventuale polo + //// se ho poli + //if ( m_vbPole[1] || m_vbPole[3]) { + // // se un vertice sta su un polo me lo segno + // auto it1 = find(vOn.begin(), vOn.end(), 1) ; + // auto it3 = find(vOn.begin(), vOn.end(), 3) ; + // if ( it1 != vOn.end()) { + // bVertOnPole = true ; + // nVertOnPole = it1 - vOn.begin() ; + // } + // if ( it3 != vOn.end() ) { + // bVertOnPole = true ; + // nVertOnPole = it3 - vOn.begin() ; + // } + //} + + // controllo che almeno un vertice sia su un edge + if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { + // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate + if ( vOn[0] * vOn[1] * vOn[2] < 0 || + (vOn[0] > 0 && vOn[0] != nVertOnPole) || + (vOn[1] > 0 && vOn[1] != nVertOnPole) || + (vOn[2] > 0 && vOn[2] != nVertOnPole)) { + double dRightY ; + // tengo per buone le coordinate dei vertici che NON sono sul bordo dello spazio parametrico + for ( int p = 0 ; p < 3; ++p) { + if ( vOn[p] == -1) { + dRightY = vPtPa[p].y ; + break ; + } + } + for ( int p = 0 ; p < 3; ++p) { + if ( abs(vPtPa[p].y - dRightY) > EPS_SMALL) { + if ( vPtPa[p].y < EPS_SMALL) + vPtPa[p].y = dParamH ; + else + vPtPa[p].y = 0 ; + } } } } @@ -2536,7 +2685,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in return false ; // trovo quale vertice è sull'edge di polo BOOLVECTOR vbOn(3) ; - fill( vbOn.begin(), vbOn.end(), false) ; + std::fill( vbOn.begin(), vbOn.end(), false) ; for ( int p = 0 ; p < 3; ++p ) { for ( int c = 0 ; c < 4; ++c) { if ( ! m_vCCEdge[c]->IsValid()) { @@ -2599,27 +2748,27 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in ptSP.y = ptParam.y() ; // controllo se le coordinate sono nello spazio parametrico ed eventualmente se posso sistemarle tenendo conto della periodicità ( se la superficie è chiusa) if ( ptSP.x < 0) { - if ( m_bClosedU) - ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; - else + //if ( m_bClosedU) + // ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; + //else ptSP.x = 0 ; } if ( ptSP.x > m_nSpanU * SBZ_TREG_COEFF ) { - if ( m_bClosedU) - ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; - else + //if ( m_bClosedU) + // ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; + //else ptSP.x = m_nSpanU * SBZ_TREG_COEFF ; } if ( ptSP.y < 0 ) { - if ( m_bClosedV) - ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; - else + //if ( m_bClosedV) + // ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; + //else ptSP.y = 0 ; } if ( ptSP.y > m_nSpanV * SBZ_TREG_COEFF ) { - if ( m_bClosedU) - ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; - else + //if ( m_bClosedU) + // ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; + //else ptSP.y = m_nSpanV * SBZ_TREG_COEFF ; } return true ; @@ -2629,101 +2778,122 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in bool SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bThroughEdge) const { - // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton - // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D - // ripeto cercando di avvicinarmi il più possibile - // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino - DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; - Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; - if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) - return false ; - Point3d ptBez ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; - // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto - double dDistNew = Dist( pt3D, ptBez) ; - double dDistPre ; - double dDist0, dDist1; + // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton + // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D + // ripeto cercando di avvicinarmi il più possibile + // per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino + DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ; + Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; + if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) + return false ; + Point3d ptBez ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto + double dDistNew = Dist( pt3D, ptBez) ; + double dDistPre ; + double dDist0, dDist1; - int nCount = 0 ; - double dh = EPS_SMALL ; - // metodo di newton in più dimensioni - // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. - bool bRetry = false ; - double dApproach = 0.01 ; - bool bDesperate = false ; - double dAng = 1 ; - double dr = 5 ; - double dfdU, dfdV ; - while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { - if ( ! bRetry) { - dDistPre = dDistNew ; - // derivata in U - Point3d ptIBzNew1 ; - GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; - dDist0 = Dist( pt3D, ptIBzNew1) ; - dfdU = ( dDist0 - dDistPre) / dh ; - // derivata in V - Point3d ptIBzNew2 ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; - dDist1 = Dist( pt3D, ptIBzNew2) ; - dfdV = ( dDist1 - dDistPre) / dh ; - } - // calcolo le nuove coordinate - Vector3d vtDir ; - double dASum = abs(dfdU) + abs(dfdV) ; - double dSSum = sqrt( pow(dfdU,2) + pow( dfdV,2)) ; - vtDir.Set( - dfdU, - dfdV, 0) ; - if ( ! vtDir.Normalize() ) - vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ; - dr = dDistPre / dASum ; - // in modalità Retry riduco lo spostamento - vtDir *= dr * ( bRetry ? 0.1 : 0.5) ; - if ( bDesperate) { - // in depserate mode riduco lo spostamento e comincio a cambiare progressivamente la direzione oscillando tra destra e sinistra della direzione "naturale" + int nCount = 0 ; + double dh = EPS_SMALL ; + // metodo di newton in più dimensioni + // vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi. + bool bRetry = false ; + double dApproach = 0.01 ; + bool bDesperate = false ; + double dAng = 1 ; + double dr = 5 ; + double dfdU, dfdV ; + //// se il punto era su un edge allora l'ho già trovato giusto + //if ( bThroughEdge != nullptr && *bThroughEdge) + // return true ; + while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { + if ( ! bRetry) { + dDistPre = dDistNew ; + // derivata in U + Point3d ptIBzNew1 ; + GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + dDist0 = Dist( pt3D, ptIBzNew1) ; + dfdU = ( dDist0 - dDistPre) / dh ; + // derivata in V + Point3d ptIBzNew2 ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + dDist1 = Dist( pt3D, ptIBzNew2) ; + dfdV = ( dDist1 - dDistPre) / dh ; + } + // calcolo le nuove coordinate + Vector3d vtDir ; + double dASum = abs(dfdU) + abs(dfdV) ; + double dSSum = sqrt( pow(dfdU,2) + pow( dfdV,2)) ; + vtDir.Set( - dfdU, - dfdV, 0) ; + if ( ! vtDir.Normalize() ) + vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ; + dr = dDistPre / dASum ; + // in modalità Retry riduco lo spostamento + vtDir *= dr * ( bRetry ? 0.1 : 0.5) ; + if ( bDesperate) { + // in depserate mode riduco lo spostamento e comincio a cambiare progressivamente la direzione oscillando tra destra e sinistra della direzione "naturale" + vtDir *= 0.5 ; + dAng *= -1.25 ; + // riduco ulteriormente lo spostamento dopo qualche giro in desperate mode + if ( abs( dAng) > 5) vtDir *= 0.5 ; - dAng *= -1.25 ; - // riduco ulteriormente lo spostamento dopo qualche giro in desperate mode - if ( abs( dAng) > 5) - vtDir *= 0.5 ; - vtDir.Rotate( Z_AX, dAng) ; - } - ptParam += vtDir ; - // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; - dDistNew = Dist( pt3D, ptBez) ; - dApproach = dDistPre - dDistNew ; - // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode - if ( dApproach < EPS_ZERO) { - if ( bRetry) - bDesperate = true ; // entro in desperate mode - ptParam -= vtDir ; - bRetry = true ; - // se ho già fatto 9 giri in desperate mode allora esco - if ( abs( dAng) > 8) - break ; - } - else { - bRetry = false ; - bDesperate = false ; - dAng = 1 ; - } - ++nCount ; + vtDir.Rotate( Z_AX, dAng) ; } - // se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto - if ( bThroughEdge != nullptr && *bThroughEdge) { - if ( m_bClosedU ) { - if ( ptParam.x < abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x)) - ptParam.x = 0 ; - else - ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; - } - if ( m_bClosedV ) { - if ( ptParam.y < abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y)) - ptParam.y = 0 ; - else - ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; - } + ptParam += vtDir ; + // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; + dDistNew = Dist( pt3D, ptBez) ; + dApproach = dDistPre - dDistNew ; + // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode + if ( dApproach < EPS_ZERO) { + if ( bRetry) + bDesperate = true ; // entro in desperate mode + ptParam -= vtDir ; + bRetry = true ; + // se ho già fatto 9 giri in desperate mode allora esco + if ( abs( dAng) > 8) + break ; } + else { + bRetry = false ; + bDesperate = false ; + dAng = 1 ; + } + ++nCount ; + } + //// se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto + //if ( bThroughEdge != nullptr && *bThroughEdge) { + // if ( m_bClosedU) { + // if ( abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x) < 1) + // ptParam.x = 0 ; + // else if ( ptParam.x < 1) + // ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; + // } + // if ( m_bClosedV) { + // if ( abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y) < 1) + // ptParam.y = 0 ; + // else if ( ptParam.y < 1) + // ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; + // } + //} + + // se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto + // guardo a quale dei due lati sono più vicino + // devo distinguere il caso di un triangolo a metà dello spazio, con un vertice su un lato di polo, ma senza vertici su lati di chiusura + if ( bThroughEdge != nullptr && *bThroughEdge) { + if ( m_bClosedU) { + if ( ptParam.x < 1) + ptParam.x = 0 ; + else if ( abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x) < 1) + ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; + } + if ( m_bClosedV) { + if ( ptParam.y < 1) + ptParam.y = 0 ; + else if ( abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y) < 1) + ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; + } + } return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } diff --git a/SurfBezier.h b/SurfBezier.h index 195f7fd..f424972 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -119,6 +119,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; + bool IncreaseUV( double& dU, double dx, bool bUOrV) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 6a92f6b80f943e8ad86f3239117a48975e957608 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 6 Mar 2024 14:52:57 +0100 Subject: [PATCH 16/31] EgtGeomKernel : - pulizia del codice. --- SurfBezier.cpp | 404 +++++++++++++------------------------------------ SurfBezier.h | 3 +- 2 files changed, 111 insertions(+), 296 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 39f0e90..9c7f00c 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1614,37 +1614,67 @@ SurfBezier::ResetTrimRegion( void) //---------------------------------------------------------------------------- bool -SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV) const +SurfBezier::IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const { - dUV += dxy ; + if ( ptUVCopy != nullptr) { + IncreaseUV( ptUV.x, vtH.x, true, &(*ptUVCopy).x, bModifyOrig) ; + IncreaseUV( ptUV.y, vtH.y, true, &(*ptUVCopy).y, bModifyOrig) ; + } + else { + IncreaseUV( ptUV.x, vtH.x, true, nullptr, bModifyOrig) ; + IncreaseUV( ptUV.y, vtH.y, true, nullptr, bModifyOrig) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bool bModifyOrig) const +{ + double dUVTest ; + if ( dUVCopy != nullptr) { + *dUVCopy = dUV + dxy ; + dUVTest = *dUVCopy ; + } + if ( bModifyOrig) { + dUV += dxy ; + dUVTest = dUV ; + } + if ( bUOrV) { - if ( dUV < 0) { - if ( m_bClosedU) - dUV += m_nSpanU * SBZ_TREG_COEFF ; - else - dUV = 0 ; + if ( dUVTest < 0) { + //if ( m_bClosedU) + // dUVTest += m_nSpanU * SBZ_TREG_COEFF ; + //else + dUVTest = 0 ; } - if ( dUV > m_nSpanU * SBZ_TREG_COEFF ) { - if ( m_bClosedU) - dUV -= m_nSpanU * SBZ_TREG_COEFF ; - else - dUV = m_nSpanU * SBZ_TREG_COEFF ; + else if ( dUVTest > m_nSpanU * SBZ_TREG_COEFF ) { + //if ( m_bClosedU) + // dUVTest -= m_nSpanU * SBZ_TREG_COEFF ; + //else + dUVTest = m_nSpanU * SBZ_TREG_COEFF ; } } else { - if ( dUV ) { - if ( m_bClosedV) - dUV += m_nSpanV * SBZ_TREG_COEFF ; - else - dUV = 0 ; + if ( dUVTest < 0) { + //if ( m_bClosedV) + // dUVTest += m_nSpanV * SBZ_TREG_COEFF ; + //else + dUVTest = 0 ; } - if ( dUV > m_nSpanV * SBZ_TREG_COEFF ) { - if ( m_bClosedU) - dUV -= m_nSpanV * SBZ_TREG_COEFF ; - else - dUV = m_nSpanV * SBZ_TREG_COEFF ; + else if ( dUVTest > m_nSpanV * SBZ_TREG_COEFF ) { + //if ( m_bClosedV) + // dUVTest -= m_nSpanV * SBZ_TREG_COEFF ; + //else + dUVTest = m_nSpanV * SBZ_TREG_COEFF ; } } + if ( bModifyOrig) + dUV = dUVTest ; + if ( dUVCopy != nullptr) + *dUVCopy = dUVTest ; + return true ; } @@ -1656,7 +1686,6 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& // creo la chain dei punti che sto riportando nel parametrico ChainCurves chainC ; double dToler = EPS_SMALL ; - //chainC.Init( false, dToler, int( pCC->GetCurveCount())) ; chainC.Init( false, dToler, 2) ; const ICurve* pCrv0 = pCC->GetCurve( 0) ; @@ -1669,7 +1698,6 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& return false ; vbThroughEdge.push_back( bThroughEdge) ; - //pl.AddUPoint( 0, pt2D) ; // aggiungo tutti i successivi BIPNTVECTOR vBPnt ; @@ -1712,7 +1740,6 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& pt2DPrev.y = pt2D.y ; } } - //pl.AddUPoint( i, pt2D) ; Vector3d vtDir = pt2D - pt2DPrev ; vtDir.Normalize() ; // se mi accorgo che sto per tracciare un taglio lungo un bordo posso semplicmente evitarlo @@ -1758,16 +1785,11 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& bAdded = ( Dist( ptStart, ptEnd) > dToler / 2 && pLine->Set( ptStart, ptEnd)) ; bAdded = bAdded && pCC2D->AddCurve( pLine, true, dToler) ; - //if ( vbThroughEdge[i]) { - // vpCC.emplace_back( Release(pCC2D)) ; - // pCC2D.Set( CreateCurveComposite()) ; - //} ptNear = ( bAdded ? ptEnd : ptStart) ; } if ( pCC2D->IsValid()) vpCC.emplace_back( Release(pCC2D)) ; } - //pCC2D->FromPolyLine( pl) ; return true ; } @@ -1812,11 +1834,6 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& typedef tuple TRINT ; -//static bool operator==(TRINT& ta, TRINT& tb) -//{ -// return get<0>(ta) == get<0>(tb) && get<1>(ta) == get<1>(tb) && get<2>(ta) == get<2>(tb) ; -//} - template<> struct hash { std::size_t operator()(const TRINT& t) const @@ -1843,15 +1860,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; - //// con queste righe funzionano anche i tagli multipli//////////////////////////////////////////////// - //bool bMod = false ; - //// ATTENZIONE!!!!! ad ogni "return false" in questa funzione dovrei reimpostare "m_bTrimmed = true" se bMod == true/////////////////////////////////////////////////// - //if ( m_bTrimmed) { - // m_bTrimmed = false ; - // ResetAuxSurf() ; - // bMod = true ; - //} - //////i tagli multipli//////////////////////////////////////////////// IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; ////debug @@ -1908,91 +1916,17 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pLine->Set( ptStart, ptEnd)) ; bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; ptNear = ( bAdded ? ptEnd : ptStart) ; - - // // se la superficie è chiusa devo controllare se sto attraversando un edge con un trim - // if ( (m_bClosedU || m_bClosedV) && ! bPrevLineThroughEdge) { - // IntersCurveCurve icc0( *pLine, *m_vCCEdge[0]) ; - // IntersCurveCurve icc1( *pLine, *m_vCCEdge[1]) ; - // IntersCurveCurve icc2( *pLine, *m_vCCEdge[2]) ; - // IntersCurveCurve icc3( *pLine, *m_vCCEdge[3]) ; - // // se non ho intersezioni proseguo aggiungendo il punto - // if ( icc0.GetIntersCount() == 0 && - // icc1.GetIntersCount() == 0 && - // icc2.GetIntersCount() == 0 && - // icc3.GetIntersCount() == 0) { - // // se non ho intersezioni con gli edge posso aggiungere semplicemente alla compo - // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - // ptNear = ( bAdded ? ptEnd : ptStart) ; - // } - // else { - // // recupero la prima intersezione che trovo - // // se ho intersezioni multiple è perché sono edge sovrapposti - // IntCrvCrvInfo iccInfo ; - // if ( icc0.GetIntersCount() != 0) - // icc0.GetIntCrvCrvInfo( 0, iccInfo) ; - // else if ( icc1.GetIntersCount() != 0) - // icc1.GetIntCrvCrvInfo( 0, iccInfo) ; - // else if ( icc2.GetIntersCount() != 0) - // icc2.GetIntCrvCrvInfo( 0, iccInfo) ; - // else if ( icc3.GetIntersCount() != 0) - // icc3.GetIntCrvCrvInfo( 0, iccInfo) ; - - // ICurveLine* pCLPart1 ( CreateCurveLine()) ; - // // spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root - // Vector3d vtDir ; pLine->GetStartDir( vtDir) ; - // Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ; - // // se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova - // // a partire dall'intersezione - // if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { - // pCLPart1->Set( ptStart, ptBeforeTheEdge) ; - // pCrvCompo->AddCurve( pCLPart1, true, dToler) ; - // bAdded = false ; - // if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) - // return false ; - // pCrvCompo->Clear() ; - // // comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato - // // probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject - // //ICurveLine* pCLPart2 ( CreateCurveLine()) ; - // Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL; - // //pCLPart2->Set( ptBeyondTheEdge, ptEnd) ; - // //bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ; - // ptNear = ptBeyondTheEdge ; - // bPrevLineThroughEdge = true ; - // --i ; - // } - // else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) { - // // se l'intersezione era all'inizio allora aggiungo e basta - // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - // ptNear = ( bAdded ? ptEnd : ptStart) ; - // } - // else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) { - // // se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova - // // indipendente dall'interesezione - // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - // if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) - // return false ; - // pCrvCompo->Clear() ; - // ptNear = ( bAdded ? ptEnd : ptStart) ; - // } - // } - // } - // // sennò procedo normalmente aggiungendo il punto - // else { - // bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; - // ptNear = ( bAdded ? ptEnd : ptStart) ; - // bPrevLineThroughEdge = false ; - // } } if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) return false ; } - //debug - vector vGeoObj4 ; - for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) - vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; - SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; - //debug + ////debug + //vector vGeoObj4 ; + //for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) + // vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; + //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; + ////debug ////debug //vector vGeoObj ; @@ -2001,29 +1935,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; ////debug - //queste righe non servono più perché faccio già il chain mentre porto la curva in 2D - // - //if ( int( vpCCOpen.size()) != 0) { - // //// devo verificare se devo giuntare la prima curva aperta con l'ultima - // //Point3d ptStartOpen, ptEndOpen ; - // //vpCCOpen.front()->GetStartPoint( ptStartOpen) ; - // //vpCCOpen.back()->GetEndPoint( ptEndOpen) ; - // //if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) { - // // vpCCOpen.back()->AddCurve( vpCCOpen.front()) ; - // // Release( vpCCOpen[0]) ; - // // vpCCOpen.erase( vpCCOpen.begin()) ; - // //} - // - // // devo controllare se devo giuntare queste curve aperte tra loro - // Point3d ptStartOpen, ptEndOpen ; - // for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) { - // // controllo se la fine di questa curva coincide con lo start di un'altra - - // } - //} - - - //debug vector vGeoObj2 ; for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) @@ -2171,15 +2082,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) std::fill( vbAdded.begin(), vbAdded.end(), false) ; PtrOwner pCCNewEdge( CreateCurveComposite()) ; PtrOwner pCL( CreateCurveLine()) ; - //bool bAddedAll = false ; TRINT tiFirstInters ; - //double dParamFirstInters = -1 ; // parto aggiungendo il primo taglio int nNewToAdd = 0 ; bool bFirstCurveOfEdge = true ; while ( nNewToAdd != -1) { // aggiungo il taglio - //PtrOwner pLastCC( vpCCOpen[nNewToAdd]->Clone()) ; pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ; // aggiorno la lista degli aggiunti vbAdded[nNewToAdd] = true ; @@ -2193,7 +2101,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( bFirstCurveOfEdge){ // salvo l'inizio del taglio che è la prima curva di questa curva compo tiFirstInters = pair.first ; - //dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop bFirstCurveOfEdge = false ; } } @@ -2226,9 +2133,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } - //bool bRestart = false ; if ( nInters == -1) { - //bRestart = true ; dNextCut = numeric_limits::infinity() ; for ( const auto& pair : mInters) { if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) { @@ -2248,36 +2153,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; pCCNewEdge->AddCurve(pLoopTrimmed->CopyParamRange( dEndCurrentCut, dNextCut)) ; - /////////////////////////////////////sostituito da CopyParamRange//////////////////////////////////////////////////////////////////////////////////////////////////////////// - //PtrOwner pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; - //// se i trim che devo fare sono sulla stessa sotto-curva della compo devo riscalare il valore per il trim allo start prima di trimmare l'end - //if ( int( dNextCut) == int( dEndCurrentCut)) { - // PtrOwner pLoopCompo( GetCurveComposite( pLoopTrimmed->Clone())) ; - // const ICurve* pSubCrv = pLoopCompo->GetCurve( int(dNextCut)) ; - // double dLenAtParam0, dLenAtParam1 ; - // pSubCrv->GetLengthAtParam( dEndCurrentCut, dLenAtParam0) ; - // pSubCrv->GetLengthAtParam( dNextCut, dLenAtParam1) ; - // dEndCurrentCut = dLenAtParam0 / dLenAtParam1 ; - //} - //// trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio - //pLoopTrimmed->TrimEndAtParam( dNextCut) ; - - //// se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato - //if ( ! bRestart) { - // pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ; - // pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ; - //} - //else { - // // prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa - // // andare al punto finale e quindi tornare al punto iniziale - // PtrOwner pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ; - // pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ; - // pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ; - // // e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio - // pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ; - //} - ///////////////////////////////////sostituito da CopyParamRange////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento // alla flat region e comincio a costruire un altro bordo // altrimenti continuo ad aggiungere curve al bordo corrente @@ -2291,7 +2166,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) { if ( ! vbAdded[b]) { nNewToAdd = b ; - //vbAdded[b] = true ; break ; } } @@ -2335,10 +2209,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( pSFR->GetNormVersor().z < 0) pSFR->Invert() ; - //debug - PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; + ////debug // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio @@ -2417,10 +2291,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } - //debug - PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + ////debug // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2432,13 +2306,14 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bool SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const { - return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1)) ; + return UnprojectPointFromStm( nT, ptI, ptSP, nIL, P_INVALID) ; } //---------------------------------------------------------------------------- bool SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, bool* bThroughEdge) const { + ptSP = ORIG ; if ( bThroughEdge != nullptr) *bThroughEdge = false ; // dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche @@ -2475,29 +2350,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( nInters == 3 || ( m_bClosedU && ( vInters[1] == 1 || vInters[3] == 1)) || ( m_bClosedV && ( vInters[1] == 1 || vInters[3] == 1))) { if ( nInters == 3) bIsPole = true ; - //// salvo pure come triangolo di riferimento quello del punto precedente - //const ISurfTriMesh* pSurfTm2 = GetAuxSurf() ; - //int nVert[3] ; - //pSurfTm2->GetTriangle( nT, nVert) ; - //PNTVECTOR vPtPa(3) ; - //pSurfTm2->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ; - //pSurfTm2->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ; - //pSurfTm2->GetVertexParam( nVert[2], vPtPa[2].x,vPtPa[2].y) ; - //if ( nTPrev != -1) - // nT = nTPrev ; - //else - // // se non avevo un punto precedente allora vuol dire che mi stanno passando un punto singolo e non posso dire nulla sulle coordinate - // // parametriche di questo punto - // return false ; - // visto che sono in un polo o su un lato di chiusura devo verificare di aver ricevuto il triangolo giusto // se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza - if ( AreSamePointExact( ptIPrevOrNext, Point3d(-1,-1,-1))){ // controllo che non sia quello definito di default - DistPointSurfTm dPtStm( ptIPrevOrNext, *pSurfTm) ; - double dDist = INFINITO ; dPtStm.GetDist( dDist) ; - if ( dDist > 0.2) - return false ; - } + if ( ! ptIPrevOrNext.IsValid()) + return false ; if ( bThroughEdge != nullptr) *bThroughEdge = true ; Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ; @@ -2563,23 +2419,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } - //// controllo che i vertici che stanno su un edge siano davvero sul lato di chiusura e non sull'eventuale polo - - //// se ho poli - //if ( m_vbPole[0] || m_vbPole[2]) { - // // se un vertice sta su un polo me lo segno - // auto it0 = find(vOn.begin(), vOn.end(), 0) ; - // auto it2 = find(vOn.begin(), vOn.end(), 2) ; - // if ( it0 != vOn.end()) { - // bVertOnPole = true ; - // nVertOnPole = it0 - vOn.begin() ; - // } - // if ( it2 != vOn.end() ) { - // bVertOnPole = true ; - // nVertOnPole = it2 - vOn.begin() ; - // } - //} - // controllo che almeno un vertice sia su un edge e se è l'unico vertice, che non sia su un polo if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate @@ -2627,22 +2466,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in } } } - //// controllo che i vertici che stanno su un edge siano davvero sul lato di chiusura e non sull'eventuale polo - //// se ho poli - //if ( m_vbPole[1] || m_vbPole[3]) { - // // se un vertice sta su un polo me lo segno - // auto it1 = find(vOn.begin(), vOn.end(), 1) ; - // auto it3 = find(vOn.begin(), vOn.end(), 3) ; - // if ( it1 != vOn.end()) { - // bVertOnPole = true ; - // nVertOnPole = it1 - vOn.begin() ; - // } - // if ( it3 != vOn.end() ) { - // bVertOnPole = true ; - // nVertOnPole = it3 - vOn.begin() ; - // } - //} - // controllo che almeno un vertice sia su un edge if ( vOn[0] > 0 || vOn[1] > 0 || vOn[2] > 0) { // se ho più un vertice sul lato oppure se ne ho solo uno ma non è sul polo allora procedo alla correzione delle coordinate @@ -2744,33 +2567,36 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in mB.col(1) << vPtPa[1].x, vPtPa[1].y, 0 ; mB.col(2) << vPtPa[2].x, vPtPa[2].y, 0 ; Eigen::Vector3d ptParam = mB * x ; - ptSP.x = ptParam.x() ; - ptSP.y = ptParam.y() ; - // controllo se le coordinate sono nello spazio parametrico ed eventualmente se posso sistemarle tenendo conto della periodicità ( se la superficie è chiusa) - if ( ptSP.x < 0) { - //if ( m_bClosedU) - // ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; - //else - ptSP.x = 0 ; - } - if ( ptSP.x > m_nSpanU * SBZ_TREG_COEFF ) { - //if ( m_bClosedU) - // ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; - //else - ptSP.x = m_nSpanU * SBZ_TREG_COEFF ; - } - if ( ptSP.y < 0 ) { - //if ( m_bClosedV) - // ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; - //else - ptSP.y = 0 ; - } - if ( ptSP.y > m_nSpanV * SBZ_TREG_COEFF ) { - //if ( m_bClosedU) - // ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; - //else - ptSP.y = m_nSpanV * SBZ_TREG_COEFF ; - } + IncreaseUV( ptSP.x, ptParam.x(), true) ; + IncreaseUV( ptSP.y, ptParam.y(), false) ; + //ptSP.x = ptParam.x() ; + //ptSP.y = ptParam.y() ; + + //// controllo se le coordinate sono nello spazio parametrico ed eventualmente se posso sistemarle tenendo conto della periodicità ( se la superficie è chiusa) + //if ( ptSP.x < 0) { + // //if ( m_bClosedU) + // // ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; + // //else + // ptSP.x = 0 ; + //} + //if ( ptSP.x > m_nSpanU * SBZ_TREG_COEFF ) { + // //if ( m_bClosedU) + // // ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; + // //else + // ptSP.x = m_nSpanU * SBZ_TREG_COEFF ; + //} + //if ( ptSP.y < 0 ) { + // //if ( m_bClosedV) + // // ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; + // //else + // ptSP.y = 0 ; + //} + //if ( ptSP.y > m_nSpanV * SBZ_TREG_COEFF ) { + // //if ( m_bClosedU) + // // ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; + // //else + // ptSP.y = m_nSpanV * SBZ_TREG_COEFF ; + //} return true ; } @@ -2803,20 +2629,21 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dAng = 1 ; double dr = 5 ; double dfdU, dfdV ; - //// se il punto era su un edge allora l'ho già trovato giusto - //if ( bThroughEdge != nullptr && *bThroughEdge) - // return true ; while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { if ( ! bRetry) { dDistPre = dDistNew ; // derivata in U Point3d ptIBzNew1 ; - GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + //GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; + double dUh ; IncreaseUV( ptParam.x, dh, true, &dUh, false) ; + GetPointD1D2( dUh / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; dDist0 = Dist( pt3D, ptIBzNew1) ; dfdU = ( dDist0 - dDistPre) / dh ; // derivata in V Point3d ptIBzNew2 ; - GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + //GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; + double dVh ; IncreaseUV( ptParam.y, dh, false, &dVh, false) ; + GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, dVh / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; dDist1 = Dist( pt3D, ptIBzNew2) ; dfdV = ( dDist1 - dDistPre) / dh ; } @@ -2839,7 +2666,9 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d vtDir *= 0.5 ; vtDir.Rotate( Z_AX, dAng) ; } - ptParam += vtDir ; + //ptParam += vtDir ; + IncreaseUV( ptParam.x, vtDir.x, true) ; + IncreaseUV( ptParam.y, vtDir.y, false) ; // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; dDistNew = Dist( pt3D, ptBez) ; @@ -2861,21 +2690,6 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d } ++nCount ; } - //// se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto - //if ( bThroughEdge != nullptr && *bThroughEdge) { - // if ( m_bClosedU) { - // if ( abs( m_nSpanU * SBZ_TREG_COEFF - ptParam.x) < 1) - // ptParam.x = 0 ; - // else if ( ptParam.x < 1) - // ptParam.x = m_nSpanU * SBZ_TREG_COEFF ; - // } - // if ( m_bClosedV) { - // if ( abs( m_nSpanV * SBZ_TREG_COEFF - ptParam.y) < 1) - // ptParam.y = 0 ; - // else if ( ptParam.y < 1) - // ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; - // } - //} // se il punto era su un edge allora verifico che sia ancora su un edge, sennò ce lo riporto // guardo a quale dei due lati sono più vicino diff --git a/SurfBezier.h b/SurfBezier.h index f424972..68adb11 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -119,7 +119,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; - bool IncreaseUV( double& dU, double dx, bool bUOrV) const override ; + bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; + bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 1acd97d42ab281c724143e0b9ba57913313db666 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 8 Mar 2024 09:55:53 +0100 Subject: [PATCH 17/31] =?UTF-8?q?EgtGeomKernel=20:=20-=20correzioni=20all'?= =?UTF-8?q?aggiunta=20di=20taglia=20aperti=20(nel=20parametrico)=20ad=20un?= =?UTF-8?q?a=20superficie=20di=20bezier=20gi=C3=A0=20trimmata.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SurfBezier.cpp | 94 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 9c7f00c..3147013 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -37,6 +37,7 @@ #include "/EgtDev/Include/EGkCurveComposite.h" #include #include "/EgtDev/Include/EGkGeoObjSave.h" +#include "/EgtDev/Include/EGkGeoPoint3d.h" using namespace std ; @@ -1928,13 +1929,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; ////debug - ////debug - //vector vGeoObj ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ; - ////debug - //debug vector vGeoObj2 ; for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) @@ -1967,6 +1961,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bool bEndFound = false ; // trim for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { + nInters = 0 ; //chunk for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { // loop @@ -2039,9 +2034,13 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } } - + // ricostruisco gli elementi per la mappa mInters if ( ! bStartFound && ! bEndFound) { + // ridefinisco il taglio aperto con la sua versione estesa che arriva a toccare i loop dello spazio parametrico + vpCCOpen[t].Set( GetCurveComposite(pCrv->CopyParamRange( vICCStart[0].IciB->dU, vICCEnd[0].IciB->dU))) ; + // correggo il parametro dell'intersezione allo start + vICCStart[0].IciB->dU = 0 ; if ( tStart == tEnd) { // se ho intersezione con un loop solo allora accorpo i due vettori delle intersezioni vICCStart.emplace_back( vICCEnd[0]) ; @@ -2052,18 +2051,18 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) mInters.insert( pair(tStart, vICCStart)) ; mInters.insert( pair(tEnd, vICCEnd)) ; } - // ridefinisco il taglio aperto con la sua versione estesa che arriva a toccare i loop dello spazio parametrico - vpCCOpen[t].Set( GetCurveComposite(pCrv->CopyParamRange( vICCStart[0].IciB->dU, vICCEnd[0].IciB->dU))) ; } else { // devo verificare se avevo già trovato una delle due intersezioni e se era sullo stesso loop o no if ( ! bStartFound) { - if ( mInters.count( tStart) ==1) + pCrv->TrimStartAtParam( vICCStart[0].IciB->dU) ; + vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ; + // correggo il parametro dell'intersezione allo start + vICCStart[0].IciB->dU = 0 ; + if ( mInters.count( tStart) == 1) mInters[tStart].emplace_back( vICCStart[0]) ; else mInters.insert( pair( tStart, vICCStart)) ; - pCrv->TrimStartAtParam( vICCStart[0].IciB->dU) ; - vpCCOpen[t].Set( GetCurveComposite( Release( pCrv))) ; } if ( ! bEndFound) { if ( mInters.count( tEnd) == 1) @@ -2077,6 +2076,13 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } + //debug + vector vGeoObj ; + for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\openCuts_afterExtensionTrim.nge") ; + //debug + // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; std::fill( vbAdded.begin(), vbAdded.end(), false) ; @@ -2209,10 +2215,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( pSFR->GetNormVersor().z < 0) pSFR->Invert() ; - ////debug - //PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; - ////debug + //debug + PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; + //debug // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio @@ -2276,10 +2282,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - ////debug - //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - ////debug + //debug + PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + //debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { @@ -2291,10 +2297,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } - ////debug - //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; - ////debug + //debug + PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + //debug // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2612,6 +2618,11 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) return false ; + //debug + bool bDrawPoints = false ; + if ( ptParam.x < 5 && ptParam.x > 4) + bDrawPoints = true ; + //debug Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto @@ -2629,7 +2640,17 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dAng = 1 ; double dr = 5 ; double dfdU, dfdV ; + + // debug + vector vGeoObj ; + if ( bDrawPoints) { + IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; + GeoPnt->Set( ptBez) ; + vGeoObj.emplace_back(static_cast( GeoPnt)) ; + } + //debug while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { + if ( ! bRetry) { dDistPre = dDistNew ; // derivata in U @@ -2667,17 +2688,28 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d vtDir.Rotate( Z_AX, dAng) ; } //ptParam += vtDir ; - IncreaseUV( ptParam.x, vtDir.x, true) ; - IncreaseUV( ptParam.y, vtDir.y, false) ; + //IncreaseUV( ptParam.x, vtDir.x, true) ; + //IncreaseUV( ptParam.y, vtDir.y, false) ; + Point3d ptCopy = ptParam ; + IncreaseUV( ptParam, vtDir, nullptr, true) ; // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; dDistNew = Dist( pt3D, ptBez) ; + // debug + if ( bDrawPoints) { + IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; + GeoPnt->Set( ptBez) ; + vGeoObj.emplace_back(static_cast( GeoPnt)) ; + } + //debug + dApproach = dDistPre - dDistNew ; // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode if ( dApproach < EPS_ZERO) { if ( bRetry) bDesperate = true ; // entro in desperate mode - ptParam -= vtDir ; + //ptParam -= vtDir ; + ptParam = ptCopy ; bRetry = true ; // se ho già fatto 9 giri in desperate mode allora esco if ( abs( dAng) > 8) @@ -2708,6 +2740,12 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d ptParam.y = m_nSpanV * SBZ_TREG_COEFF ; } } + + //debug + if ( bDrawPoints) + SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\Point_refinement.nge") ; + //debug + return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } From 13ecae382953275f18d2aea1cfb7855c27168b5e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 8 Mar 2024 16:16:02 +0100 Subject: [PATCH 18/31] EgtGeomKernel : - correzione del raffinamento dei punti di intersezione tra un piano e una sup di bezier. --- SurfBezier.cpp | 135 ++++++++++++++++++++++++++----------------------- SurfBezier.h | 10 ++-- 2 files changed, 79 insertions(+), 66 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 3147013..064520e 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1681,7 +1681,7 @@ SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bo //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const +SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const { // do per scontato che la compo sia una spezzata, visto che arriva dall'intersezione tra un piano e una trimesh // creo la chain dei punti che sto riportando nel parametrico @@ -1695,7 +1695,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ; bool bThroughEdge = false ; BOOLVECTOR vbThroughEdge ; - if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd, &bThroughEdge)) + if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd, &bThroughEdge, pPlCut)) return false ; vbThroughEdge.push_back( bThroughEdge) ; @@ -1728,7 +1728,7 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& bPrevIsPole = AreSamePointApprox( pt, pt2DPrev) ; } pCrv->GetEndPoint( pt3D) ; - if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge)) + if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev, &bThroughEdge, pPlCut)) return false ; if ( bPrevIsPole) { // se il punto precedente era di polo allora devo correggere le sue coordinate 2D @@ -1796,12 +1796,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& //---------------------------------------------------------------------------- bool -SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler) +SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler, const Plane3d* pPlCut) const { - //debug - vpCC3D.emplace_back( pCrvCompo->Clone()) ; - //debug - // se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando double dCrvLen ; if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler) @@ -1820,7 +1816,7 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& // porto la curva nello spazio parametrico ICRVCOMPOPVECTOR vCC ; - if ( ! UnprojectCurveFromStm( pCrvCompo, vCC)) + if ( ! UnprojectCurveFromStm( pCrvCompo, vCC, pPlCut)) return false ; for ( int i = 0 ; i < int( vCC.size()); ++i) { // le curve aperte le tengo da parte per giuntarle alla fine col bordo @@ -1918,7 +1914,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; ptNear = ( bAdded ? ptEnd : ptStart) ; } - if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D)) + //debug + vpCC3D.emplace_back( pCrvCompo->Clone()) ; + //debug + if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, EPS_SMALL, &plPlane)) return false ; } @@ -1929,12 +1928,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; ////debug - //debug - vector vGeoObj2 ; - for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; - //debug + ////debug + //vector vGeoObj2 ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; + ////debug //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; @@ -1962,6 +1961,8 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // trim for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) { nInters = 0 ; + bStartFound = false ; + bEndFound = false ; //chunk for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) { // loop @@ -2076,12 +2077,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } - //debug - vector vGeoObj ; - for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\openCuts_afterExtensionTrim.nge") ; - //debug + ////debug + //vector vGeoObj ; + //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) + // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; + //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\openCuts_afterExtensionTrim.nge") ; + ////debug // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; @@ -2215,10 +2216,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( pSFR->GetNormVersor().z < 0) pSFR->Invert() ; - //debug - PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; + ////debug // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio @@ -2282,10 +2283,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - //debug - PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; + ////debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { @@ -2297,10 +2298,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } - //debug - PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; - SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; - //debug + ////debug + //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; + //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; + ////debug // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2608,7 +2609,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in //---------------------------------------------------------------------------- bool -SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bThroughEdge) const +SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bThroughEdge, const Plane3d* pPlCut) const { // dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton // trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D @@ -2618,15 +2619,20 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) return false ; - //debug - bool bDrawPoints = false ; - if ( ptParam.x < 5 && ptParam.x > 4) - bDrawPoints = true ; - //debug + ////debug + //bool bDrawPoints = false ; + //if ( ptParam.x < 5 && ptParam.x > 4) + // bDrawPoints = true ; + ////debug Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto - double dDistNew = Dist( pt3D, ptBez) ; + + double dDistPoint = Dist( pt3D, ptBez) ; + double dDistPlane = DistPointPlane( ptBez, *pPlCut) ; + + //double dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : ( Dist( pt3D, ptBez) + abs(DistPointPlane( ptBez, *pPlCut))) ; + double dDistNew = abs(DistPointPlane( ptBez, *pPlCut)) ; double dDistPre ; double dDist0, dDist1; @@ -2641,14 +2647,14 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dr = 5 ; double dfdU, dfdV ; - // debug - vector vGeoObj ; - if ( bDrawPoints) { - IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; - GeoPnt->Set( ptBez) ; - vGeoObj.emplace_back(static_cast( GeoPnt)) ; - } - //debug + //// debug + //vector vGeoObj ; + //if ( bDrawPoints) { + // IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; + // GeoPnt->Set( ptBez) ; + // vGeoObj.emplace_back(static_cast( GeoPnt)) ; + //} + ////debug while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { if ( ! bRetry) { @@ -2658,14 +2664,16 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d //GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; double dUh ; IncreaseUV( ptParam.x, dh, true, &dUh, false) ; GetPointD1D2( dUh / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; - dDist0 = Dist( pt3D, ptIBzNew1) ; + //dDist0 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew1) : ( Dist( pt3D, ptIBzNew1) + abs(DistPointPlane( ptIBzNew1, *pPlCut))) ; + dDist0 = abs(DistPointPlane( ptIBzNew1, *pPlCut)) ; dfdU = ( dDist0 - dDistPre) / dh ; // derivata in V Point3d ptIBzNew2 ; //GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; double dVh ; IncreaseUV( ptParam.y, dh, false, &dVh, false) ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, dVh / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; - dDist1 = Dist( pt3D, ptIBzNew2) ; + //dDist1 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew2) : ( Dist( pt3D, ptIBzNew2) + abs(DistPointPlane( ptIBzNew2, *pPlCut))) ; + dDist1 = abs(DistPointPlane( ptIBzNew2, *pPlCut)) ; dfdV = ( dDist1 - dDistPre) / dh ; } // calcolo le nuove coordinate @@ -2694,14 +2702,15 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d IncreaseUV( ptParam, vtDir, nullptr, true) ; // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; - dDistNew = Dist( pt3D, ptBez) ; - // debug - if ( bDrawPoints) { - IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; - GeoPnt->Set( ptBez) ; - vGeoObj.emplace_back(static_cast( GeoPnt)) ; - } - //debug + //dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : ( Dist( pt3D, ptBez) + abs(DistPointPlane( ptBez, *pPlCut))) ; + dDistNew = abs(DistPointPlane( ptBez, *pPlCut)) ; + //// debug + //if ( bDrawPoints) { + // IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; + // GeoPnt->Set( ptBez) ; + // vGeoObj.emplace_back(static_cast( GeoPnt)) ; + //} + ////debug dApproach = dDistPre - dDistNew ; // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode @@ -2741,10 +2750,10 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d } } - //debug - if ( bDrawPoints) - SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\Point_refinement.nge") ; - //debug + ////debug + //if ( bDrawPoints) + // SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\Point_refinement.nge") ; + ////debug return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } diff --git a/SurfBezier.h b/SurfBezier.h index 68adb11..62d0bd7 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -115,8 +115,12 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetTriangles2D( std::vector>& vTria2D) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; // a nIL si può passare 5 come valore di default - bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; - bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC) const override ; + // restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie + // ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie + // pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato + bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ; + // pPlCut è il piano di taglio su cui giace la curva + bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ; bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; bool CalcPoles( void) override ; bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; @@ -168,7 +172,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; double GetCurveOnUApproxLen( double dV) const ; double GetCurveOnVApproxLen( double dU) const ; - bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler = EPS_SMALL) ; + bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From a04a748552e1939542b50761f9bf43cdedaf1d00 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 8 Mar 2024 16:29:10 +0100 Subject: [PATCH 19/31] EgtGeomKernel : - pulizia del codice - aggiunta commenti. --- SurfBezier.cpp | 157 +++---------------------------------------------- SurfBezier.h | 10 +++- 2 files changed, 18 insertions(+), 149 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 064520e..0aa70bb 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1644,32 +1644,16 @@ SurfBezier::IncreaseUV( double& dUV, double dxy, bool bUOrV, double* dUVCopy, bo } if ( bUOrV) { - if ( dUVTest < 0) { - //if ( m_bClosedU) - // dUVTest += m_nSpanU * SBZ_TREG_COEFF ; - //else + if ( dUVTest < 0) dUVTest = 0 ; - } - else if ( dUVTest > m_nSpanU * SBZ_TREG_COEFF ) { - //if ( m_bClosedU) - // dUVTest -= m_nSpanU * SBZ_TREG_COEFF ; - //else + else if ( dUVTest > m_nSpanU * SBZ_TREG_COEFF ) dUVTest = m_nSpanU * SBZ_TREG_COEFF ; - } } else { - if ( dUVTest < 0) { - //if ( m_bClosedV) - // dUVTest += m_nSpanV * SBZ_TREG_COEFF ; - //else + if ( dUVTest < 0) dUVTest = 0 ; - } - else if ( dUVTest > m_nSpanV * SBZ_TREG_COEFF ) { - //if ( m_bClosedV) - // dUVTest -= m_nSpanV * SBZ_TREG_COEFF ; - //else + else if ( dUVTest > m_nSpanV * SBZ_TREG_COEFF ) dUVTest = m_nSpanV * SBZ_TREG_COEFF ; - } } if ( bModifyOrig) dUV = dUVTest ; @@ -1849,26 +1833,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim // accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim - ////debug - //PtrOwner pSFRTrim ( GetTrimRegion()->Clone()) ; - //SaveGeoObj( Release(pSFRTrim), "D:\\Temp\\inters\\original_trim.nge", GDB_SV_BIN) ; - ////debug - PNTVECTOR vPnt ; BIPNTVECTOR vBPnt ; TRIA3DVECTOR vTria ; IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ; - ////debug - //vector vGeoObj3 ; - //for ( int i = 0 ; i < int(m_vCCEdge.size()); ++i ) { - // if ( ! m_vCCEdge[i]->IsValid()) - // continue ; - // vGeoObj3.emplace_back(static_cast( m_vCCEdge[i]->Clone())) ; - //} - //SaveGeoObj( vGeoObj3, "D:\\Temp\\inters\\Edge3D.nge") ; - ////debug - // concateno le curve 3d ChainCurves chainC ; double dToler = EPS_SMALL ; @@ -1888,9 +1857,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi ICRVCOMPOPOVECTOR vpCCOpen ; ICRVCOMPOPOVECTOR vpCCClosed ; - //debug - ICRVCOMPOPOVECTOR vpCC3D ; - //debug + while ( chainC.GetChainFromNear( ptNear, false, vId)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; @@ -1898,7 +1865,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; // recupero gli estremi dei segmenti, creo le linee e le inserisco nella composita bool bAdded = true ; - //bool bPrevLineThroughEdge = false ; for ( int i = 0 ; i < int( vId.size()) ; ++ i) { // creo un segmento di retta ICurveLine* pLine( CreateCurveLine()) ; @@ -1914,27 +1880,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ; ptNear = ( bAdded ? ptEnd : ptStart) ; } - //debug - vpCC3D.emplace_back( pCrvCompo->Clone()) ; - //debug if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, EPS_SMALL, &plPlane)) return false ; } - ////debug - //vector vGeoObj4 ; - //for ( int i = 0 ; i < int(vpCC3D.size()); ++i ) - // vGeoObj4.emplace_back(static_cast( vpCC3D[i]->Clone())) ; - //SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.nge") ; - ////debug - - ////debug - //vector vGeoObj2 ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj2.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ; - ////debug - //comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti SurfFlatRegionByContours sfrContour ; if ( int(vpCCOpen.size()) != 0 ) { @@ -1948,11 +1897,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) else pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ; - ////debug - //PtrOwner pSrfCopy( pNewTrim->Clone()) ; - //SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ; - ////debug - // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region unordered_map mInters ; int nInters = 0 ; @@ -2077,13 +2021,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) } } - ////debug - //vector vGeoObj ; - //for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) - // vGeoObj.emplace_back(static_cast( vpCCOpen[i]->Clone())) ; - //SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\openCuts_afterExtensionTrim.nge") ; - ////debug - // vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo BOOLVECTOR vbAdded( vpCCOpen.size()) ; std::fill( vbAdded.begin(), vbAdded.end(), false) ; @@ -2216,11 +2153,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) if ( pSFR->GetNormVersor().z < 0) pSFR->Invert() ; - ////debug - //PtrOwner pSrfFR_Copy00( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy00), "D:\\Temp\\inters\\failed_trim_complementary.nge", GDB_SV_BIN) ; - ////debug - // verifico se la superficie che ho ottenuto è corretta o devo prendere il complementare ( rispetto allo spazio parametrico totale) // per verificarlo prendo un punto su questa superficie e verifico dove sta il suo corrispettivo 3D rispetto al piano di taglio int nChunkMin = 0 , nLoopMin = 0 ; @@ -2282,11 +2214,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // ho due casi in cui devo invertire(prendere il complementare rispetto allo spazio parametrico) la superficie: // 1. se il punto è sopra il piano ed era dentro una curva CCW // 2. se il punto è sotto il piano ed era interno ad una curva CW - - ////debug - //PtrOwner pSrfFR_Copy0( pSFR->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy0), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ; - ////debug // la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) { @@ -2298,11 +2225,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) return false ; } - ////debug - //PtrOwner pSrfFR_Copy( GetTrimRegion()->Clone()) ; - //SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ; - ////debug - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2576,34 +2498,6 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in Eigen::Vector3d ptParam = mB * x ; IncreaseUV( ptSP.x, ptParam.x(), true) ; IncreaseUV( ptSP.y, ptParam.y(), false) ; - //ptSP.x = ptParam.x() ; - //ptSP.y = ptParam.y() ; - - //// controllo se le coordinate sono nello spazio parametrico ed eventualmente se posso sistemarle tenendo conto della periodicità ( se la superficie è chiusa) - //if ( ptSP.x < 0) { - // //if ( m_bClosedU) - // // ptSP.x += m_nSpanU * SBZ_TREG_COEFF ; - // //else - // ptSP.x = 0 ; - //} - //if ( ptSP.x > m_nSpanU * SBZ_TREG_COEFF ) { - // //if ( m_bClosedU) - // // ptSP.x -= m_nSpanU * SBZ_TREG_COEFF ; - // //else - // ptSP.x = m_nSpanU * SBZ_TREG_COEFF ; - //} - //if ( ptSP.y < 0 ) { - // //if ( m_bClosedV) - // // ptSP.y += m_nSpanV * SBZ_TREG_COEFF ; - // //else - // ptSP.y = 0 ; - //} - //if ( ptSP.y > m_nSpanV * SBZ_TREG_COEFF ) { - // //if ( m_bClosedU) - // // ptSP.y -= m_nSpanV * SBZ_TREG_COEFF ; - // //else - // ptSP.y = m_nSpanV * SBZ_TREG_COEFF ; - //} return true ; } @@ -2619,11 +2513,6 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ; if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev, bThroughEdge)) return false ; - ////debug - //bool bDrawPoints = false ; - //if ( ptParam.x < 5 && ptParam.x > 4) - // bDrawPoints = true ; - ////debug Point3d ptBez ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto @@ -2631,8 +2520,7 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dDistPoint = Dist( pt3D, ptBez) ; double dDistPlane = DistPointPlane( ptBez, *pPlCut) ; - //double dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : ( Dist( pt3D, ptBez) + abs(DistPointPlane( ptBez, *pPlCut))) ; - double dDistNew = abs(DistPointPlane( ptBez, *pPlCut)) ; + double dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : abs(DistPointPlane( ptBez, *pPlCut)) ; double dDistPre ; double dDist0, dDist1; @@ -2647,14 +2535,6 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d double dr = 5 ; double dfdU, dfdV ; - //// debug - //vector vGeoObj ; - //if ( bDrawPoints) { - // IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; - // GeoPnt->Set( ptBez) ; - // vGeoObj.emplace_back(static_cast( GeoPnt)) ; - //} - ////debug while ( dDistNew > 2 * EPS_SMALL && nCount < 100) { if ( ! bRetry) { @@ -2664,16 +2544,14 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d //GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; double dUh ; IncreaseUV( ptParam.x, dh, true, &dUh, false) ; GetPointD1D2( dUh / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ; - //dDist0 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew1) : ( Dist( pt3D, ptIBzNew1) + abs(DistPointPlane( ptIBzNew1, *pPlCut))) ; - dDist0 = abs(DistPointPlane( ptIBzNew1, *pPlCut)) ; + dDist0 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew1) : abs(DistPointPlane( ptIBzNew1, *pPlCut)) ; dfdU = ( dDist0 - dDistPre) / dh ; // derivata in V Point3d ptIBzNew2 ; //GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; double dVh ; IncreaseUV( ptParam.y, dh, false, &dVh, false) ; GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, dVh / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ; - //dDist1 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew2) : ( Dist( pt3D, ptIBzNew2) + abs(DistPointPlane( ptIBzNew2, *pPlCut))) ; - dDist1 = abs(DistPointPlane( ptIBzNew2, *pPlCut)) ; + dDist1 = pPlCut == nullptr ? Dist( pt3D, ptIBzNew2) : abs(DistPointPlane( ptIBzNew2, *pPlCut)) ; dfdV = ( dDist1 - dDistPre) / dh ; } // calcolo le nuove coordinate @@ -2695,29 +2573,17 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d vtDir *= 0.5 ; vtDir.Rotate( Z_AX, dAng) ; } - //ptParam += vtDir ; - //IncreaseUV( ptParam.x, vtDir.x, true) ; - //IncreaseUV( ptParam.y, vtDir.y, false) ; Point3d ptCopy = ptParam ; IncreaseUV( ptParam, vtDir, nullptr, true) ; // calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; - //dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : ( Dist( pt3D, ptBez) + abs(DistPointPlane( ptBez, *pPlCut))) ; - dDistNew = abs(DistPointPlane( ptBez, *pPlCut)) ; - //// debug - //if ( bDrawPoints) { - // IGeoPoint3d* GeoPnt( CreateGeoPoint3d()) ; - // GeoPnt->Set( ptBez) ; - // vGeoObj.emplace_back(static_cast( GeoPnt)) ; - //} - ////debug + dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : abs(DistPointPlane( ptBez, *pPlCut)) ; dApproach = dDistPre - dDistNew ; // se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode if ( dApproach < EPS_ZERO) { if ( bRetry) bDesperate = true ; // entro in desperate mode - //ptParam -= vtDir ; ptParam = ptCopy ; bRetry = true ; // se ho già fatto 9 giri in desperate mode allora esco @@ -2750,11 +2616,6 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d } } - ////debug - //if ( bDrawPoints) - // SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\Point_refinement.nge") ; - ////debug - return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ; } diff --git a/SurfBezier.h b/SurfBezier.h index 62d0bd7..8cae257 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -111,18 +111,25 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; const SurfTriMesh* GetAuxSurf( void) const override ; + // funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione. bool GetLeaves( std::vector>& vLeaves) const override ; bool GetTriangles2D( std::vector>& vTria2D) const override ; + // funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier + // a nIL si può passare 5 come valore di default bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ; - bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; // a nIL si può passare 5 come valore di default + bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, bool* bTroughEdge = nullptr) const override ; // restituisce il corrispettivo parametrico di un punto qualunque della trimesh associata alla superficie // ptIPrev è un punto addizionale che precede o segue il punto pt3D nel caso in cui il punto faccia parte di una curva 3d sulla superficie // pPlCut è il piano di taglio su cui dovrebbe giacere il punto raffinato bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev, bool* bTroughEdge = nullptr, const Plane3d* plCut = nullptr) const override ; // pPlCut è il piano di taglio su cui giace la curva bool UnprojectCurveFromStm( const ICurveComposite* pCC, ICRVCOMPOPVECTOR& vpCC, const Plane3d* pPlCut) const override ; + // funzione per tagliare una superficie di bezier con un piano ( cancello la parte dal lato positivo della normale del piano). + // bSaveOnEq indica se tenere i triangoli (della trimesh associata) che sono sul piano bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ; + // funzione che calcola se gli edge sono collassati in poli. DEVE ESSERE STATA CHIAMATA PRIMA DI UN CUT bool CalcPoles( void) override ; + // funzioni per incrementare le coordinate restando dentro lo spazio parametrico bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; @@ -172,6 +179,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; double GetCurveOnUApproxLen( double dV) const ; double GetCurveOnVApproxLen( double dU) const ; + // funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico) bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; private : From 469d1c3445def9faefcae8fbd4dea30f280b65b2 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Tue, 12 Mar 2024 09:35:09 +0100 Subject: [PATCH 20/31] EgtGeomKernel : - aggiunta della funzione per richiedere gli edge 3D o come linea spezzata o come curva Bezier. #11 --- SurfBezier.cpp | 119 +++++++++++++++++++++++++++++++++++++++++++++++-- SurfBezier.h | 2 + 2 files changed, 118 insertions(+), 3 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 0aa70bb..6ddd9ee 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -2517,9 +2517,6 @@ SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ; // usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto - double dDistPoint = Dist( pt3D, ptBez) ; - double dDistPlane = DistPointPlane( ptBez, *pPlCut) ; - double dDistNew = pPlCut == nullptr ? Dist( pt3D, ptBez) : abs(DistPointPlane( ptBez, *pPlCut)) ; double dDistPre ; double dDist0, dDist1; @@ -2661,3 +2658,119 @@ SurfBezier::CalcPoles( void) return true ; } + +//---------------------------------------------------------------------------- +bool +SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) const +{ + // se nEdge non è definito ( == -1) allora restituisco tutti gli edge in ordine + if ( m_pSTM == nullptr) + GetAuxSurf() ; + + if ( nEdge == -1 ) { + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + } + else + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; + return true ; +} + +//---------------------------------------------------------------------------- +ICurveComposite* +SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const +{ + if ( nEdge < 0 || nEdge > 3) + return nullptr ; + ICurveComposite* pCrvCompo( CreateBasicCurveComposite()) ; + switch ( nEdge) { + case 0 : { + // se il bool è true allora restituisco gli edge con la loro approssimazione in forma di linea spezzata 3D + if ( bLineOrBezier) + pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + // se il bool è falso restituisco le curve Bezier di edge + else { + //edge 0, scorro sulle patch in U + for ( int i = 0 ; i < m_nSpanU ; ++i) { + PtrOwner pCrvBz0( CreateBasicCurveBezier()) ; + if ( IsNull(pCrvBz0) || ! pCrvBz0->Init( m_nDegU, m_bRat)) + return nullptr ; + for ( int p = 0 ; p < m_nDegU + 1 ; ++p ) { + int nIndex = ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV) + m_nDegU * i + p ; + if ( ! m_bRat) + pCrvBz0->SetControlPoint( p, GetControlPoint( nIndex, nullptr)) ; + else + pCrvBz0->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ; + } + pCrvCompo->AddCurve( Release( pCrvBz0)) ; + } + } + break ; + } + case 1 : { + if ( bLineOrBezier) + pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + else { + //edge 1, scorro sulle patch in V + for ( int i = 0 ; i < m_nSpanV ; ++i) { + PtrOwner pCrvBz1( CreateBasicCurveBezier()) ; + if ( IsNull(pCrvBz1) || ! pCrvBz1->Init( m_nDegV, m_bRat)) + return nullptr ; + for ( int p = 0 ; p < m_nDegU + 1 ; ++p ) { + int nIndex = ( m_nDegU * m_nSpanU + 1) * p ; + if ( ! m_bRat) + pCrvBz1->SetControlPoint( p, GetControlPoint( nIndex, nullptr)) ; + else + pCrvBz1->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ; + } + pCrvCompo->AddCurve( Release( pCrvBz1)) ; + } + } + break ; + } + case 2 : { + if ( bLineOrBezier) + pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + else { + // edge 2, scorro sulle patch in U + for ( int i = 0 ; i < m_nSpanU ; ++i) { + PtrOwner pCrvBz2( CreateBasicCurveBezier()) ; + if ( IsNull(pCrvBz2) || ! pCrvBz2->Init( m_nDegU, m_bRat)) + return nullptr ; + for ( int p = 0 ; p < m_nDegU + 1 ; ++p ) { + if ( ! m_bRat) + pCrvBz2->SetControlPoint( p, GetControlPoint(m_nDegU * i + p, nullptr)) ; + else + pCrvBz2->SetControlPoint( p, GetControlPoint(m_nDegU * i + p, nullptr), GetControlWeight(m_nDegU * i + p, nullptr)) ; + } + pCrvCompo->AddCurve( Release( pCrvBz2)) ; + } + } + break ; + } + case 3 : { + if ( bLineOrBezier) + pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + else { + // edge 3, scorro sulle patch in V + for ( int i = 0 ; i < m_nSpanV ; ++i) { + PtrOwner pCrvBz3( CreateBasicCurveBezier()) ; + if ( IsNull(pCrvBz3) || ! pCrvBz3->Init( m_nDegV, m_bRat)) + return nullptr ; + for ( int p = 0 ; p < m_nDegV + 1 ; ++p ) { + int nIndex = ( m_nDegU * m_nSpanU + 1) * ( i + p + 1) - 1 ; + if ( ! m_bRat) + pCrvBz3->SetControlPoint( p, GetControlPoint( nIndex, nullptr)) ; + else + pCrvBz3->SetControlPoint( p, GetControlPoint( nIndex, nullptr), GetControlWeight( nIndex, nullptr)) ; + } + pCrvCompo->AddCurve( Release( pCrvBz3)) ; + } + } + break ; + } + } + return pCrvCompo ; +} \ No newline at end of file diff --git a/SurfBezier.h b/SurfBezier.h index 8cae257..cbf44e6 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -132,6 +132,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzioni per incrementare le coordinate restando dentro lo spazio parametrico bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; + bool GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -181,6 +182,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW double GetCurveOnVApproxLen( double dU) const ; // funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico) bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; + ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto From 67c03daa422e5b7d3b3c49ea285bb5fc2fa65488 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 13 Mar 2024 15:59:55 +0100 Subject: [PATCH 21/31] EgtGeomKernel : - nella get Edges3D per sup di Bezier gestito il caso di sup trimmate. --- SurfBezier.cpp | 210 ++++++++++++++++++++++++++--------------- SurfBezier.h | 13 ++- Tree.cpp | 249 ++++++++++++++++++++++++++++++++----------------- Tree.h | 14 ++- 4 files changed, 320 insertions(+), 166 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 6ddd9ee..91899e1 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -162,13 +162,13 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac } ResetAuxSurf() ; // assegno la regione di trim - m_bTrimmed = true ; if ( m_pTrimReg != nullptr ) { if ( ! m_pTrimReg->Intersect( *pSfrTrim)) return false ; } else m_pTrimReg = GetBasicSurfFlatRegion( Release( pSfrTrim)) ; + m_bTrimmed = true ; return true ; } @@ -771,7 +771,6 @@ SurfBezier::Load( NgeReader& ngeIn) } // se trimmata, lettura della regione if ( bTrimmed) { - m_bTrimmed = true ; // creo l'oggetto ResetTrimRegion() ; m_pTrimReg = CreateBasicSurfFlatRegion() ; @@ -781,6 +780,7 @@ SurfBezier::Load( NgeReader& ngeIn) IGeoObjRW* pGObjRW = dynamic_cast( m_pTrimReg) ; if ( pGObjRW == nullptr || ! pGObjRW->Load( ngeIn)) return false ; + m_bTrimmed = true ; } // eseguo validazione @@ -1439,6 +1439,38 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const return dLen ; } +//---------------------------------------------------------------------------- +bool +SurfBezier::UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const +{ + bool bComposed = true ; + m_mCCEdge.clear() ; + for ( int i= 0 ; i < int( mPl.size()); ++i) { + m_mCCEdge.emplace_back() ; + for ( int j = 0 ; j < int ( mPl[i].size()) ; ++j) { + m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; + PolyLine pl3D ; + Point3d pt ; mPl[i][j].GetFirstPoint( pt) ; + Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + int nCount = 0 ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + while( mPl[i][j].GetNextPoint( pt)){ + GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + } + if ( ! m_mCCEdge.back().back()->FromPolyLine( pl3D)) + bComposed = false ; + } + } + // se degli edge hanno delle curve non valide allora salvo anche le polyline + if ( ! bComposed) + m_mPlEdge = mPl ; + + return true ; +} + //---------------------------------------------------------------------------- const SurfTriMesh* SurfBezier::GetAuxSurf( void) const @@ -1459,6 +1491,7 @@ SurfBezier::GetAuxSurf( void) const BIPNTVECTOR vTrees ; Tree.GetIndependentTrees( vTrees) ; bool bTest = false ; // per debug + POLYLINEMATRIX mPlEdges(4) ; for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; @@ -1472,8 +1505,13 @@ SurfBezier::GetAuxSurf( void) const Tree.BuildTree( 5 * LIN_TOL_FINE, 0.1) ; } Tree.GetPolygons( vvPL) ; - //Tree.GetPolygonsBasic( vPL) ; // per usare i polygon basic + + // aggiorno la chiusura della superficie + m_bClosedU = m_bClosedU || Tree.IsClosedU() ; + m_bClosedV = m_bClosedU || Tree.IsClosedV() ; + // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria + Tree.GetEdges3D( mPlEdges) ; } //// per usare i polygon basic////////////////////// //for (int k = 0 ; k < (int)vPL.size(); ++k) { @@ -1482,28 +1520,35 @@ SurfBezier::GetAuxSurf( void) const //} //// per usare i polygon basic/////////////////// + UpdateEdgeFromTree( mPlEdges) ; - /////////////////// così facendo sto recuperando gli Edge e la chiusura solo dell'ULTIMO TREE analizzato!!!!! (in caso di trim che creano più chunk analizzo più tree separatamente)/////////////// - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // aggiorno la chiusura della superficie - m_bClosedU = Tree.IsClosedU() ; - m_bClosedV = Tree.IsClosedV() ; - //m_vbPole = Tree.GetPoles() ; + /////////////////////da testare///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // bool bComposed = true ; + // m_mCCEdge.clear() ; + // for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { + // m_mCCEdge.emplace_back() ; + // for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { + // m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; + // PolyLine pl3D ; + // Point3d pt ; mPlEdges[i][j].GetFirstPoint( pt) ; + // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // int nCount = 0 ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // while( mPlEdges[i][j].GetNextPoint( pt)){ + // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // } + // if ( ! m_mCCEdge.back().back()->FromPolyLine( mPlEdges[i][j]) ) + // bComposed = false ; + // } + // } - // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - POLYLINEVECTOR vPLEdges ; - Tree.GetEdge3D( vPLEdges) ; - bool bComposed = true ; - for ( int i= 0 ; i < int( vPLEdges.size()); ++i) { - m_vCCEdge.emplace_back( CreateBasicCurveComposite()) ; - if ( ! m_vCCEdge.back()->FromPolyLine( vPLEdges[i])) - bComposed = false ; - } - if ( ! bComposed) - m_vPLEdge = vPLEdges ; - //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // if ( ! bComposed) + // m_mPLEdge = mPlEdges ; + // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // qui non sarebbe male stampare un messaggio di errore nel log se avevo un'area da disegnare ma non sono usciti dei poligoni if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ; @@ -2227,7 +2272,7 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) // imposto ricalcolo della grafica m_OGrMgr.Reset() ; - + return true ; } @@ -2257,21 +2302,24 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in // se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto bool bIsPole = false ; int nInters = 0 ; - INTVECTOR vInters ; + INTVECTOR vInters(4) ; + fill( vInters.begin(), vInters.end(), 0) ; // se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles if ( int( m_vbPole.size()) == 0) return false ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3] || m_bClosedU || m_bClosedV) { for ( int c = 0 ; c < 4 ; ++c) { - if ( ! m_vCCEdge[c]->IsValid()) { - Point3d pt ; - m_vPLEdge[c].GetFirstPoint( pt) ; - vInters.push_back( AreSamePointApprox( pt, ptI) ? 1 : 0) ; - nInters += vInters.back() ; - } - else { - vInters.push_back( m_vCCEdge[c]->IsPointOn( ptI) ? 1 : 0) ; - nInters += vInters.back() ; + for ( int i = 0 ; i < int( m_mCCEdge[c].size()) ; ++i) { + if ( ! m_mCCEdge[c][i]->IsValid() ) { + Point3d pt ; + m_mPlEdge[c][i].GetFirstPoint(pt) ; + vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ; + nInters += vInters.back() ; + } + else { + vInters[c] = m_mCCEdge[c][i]->IsPointOn(ptI) ? 1 : 0 ; + nInters += vInters.back() ; + } } } @@ -2333,18 +2381,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { for ( int ed = 0 ; ed < 4; ++ed) { - if ( ! m_vCCEdge[ed]->IsValid()) { - Point3d pt ; - m_vPLEdge[ed].GetFirstPoint( pt) ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; + for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { + if ( ! m_mCCEdge[ed][i]->IsValid() ) { + Point3d pt ; + m_mPlEdge[ed][i].GetFirstPoint(pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if (m_mCCEdge[ed][i]->IsPointOn(vPT[p]) && vOn[p] == -1 ) + vOn[p] = ed ; } - } - else { - if (m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) - vOn[p] = ed ; } } } @@ -2380,18 +2430,20 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in int nVertOnPole = -1 ; for ( int p = 0 ; p < 3; ++p ) { for (int ed = 0 ; ed < 4 ; ++ed) { - if ( ! m_vCCEdge[ed]->IsValid()) { - Point3d pt ; - m_vPLEdge[ed].GetFirstPoint( pt) ; - if ( AreSamePointApprox( pt, vPT[p])) { - vOn[p] = ed ; - // se un vertice sta su un polo me lo segno - nVertOnPole = p ; + for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { + if ( ! m_mCCEdge[ed][i]->IsValid()) { + Point3d pt ; + m_mPlEdge[ed][i].GetFirstPoint( pt) ; + if ( AreSamePointApprox( pt, vPT[p])) { + vOn[p] = ed ; + // se un vertice sta su un polo me lo segno + nVertOnPole = p ; + } + } + else { + if( m_mCCEdge[ed][i]->IsPointOn( vPT[p]) && vOn[p] == -1) + vOn[p] = ed ; } - } - else { - if( m_vCCEdge[ed]->IsPointOn( vPT[p]) && vOn[p] == -1) - vOn[p] = ed ; } } } @@ -2440,13 +2492,15 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in std::fill( vbOn.begin(), vbOn.end(), false) ; for ( int p = 0 ; p < 3; ++p ) { for ( int c = 0 ; c < 4; ++c) { - if ( ! m_vCCEdge[c]->IsValid()) { - Point3d pt ; - m_vPLEdge[c].GetFirstPoint( pt) ; - vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; + for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) { + if ( ! m_mCCEdge[c][i]->IsValid()) { + Point3d pt ; + m_mPlEdge[c][i].GetFirstPoint( pt) ; + vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; + } + else + vbOn[p] = vbOn[p] || m_mCCEdge[c][i]->IsPointOn( vPT[p]) ; } - else - vbOn[p] = vbOn[p] || m_vCCEdge[c]->IsPointOn( vPT[p]) ; } } // trovo la coordinata giusta da tenere ( x o y a seconda dell'edge) @@ -2667,14 +2721,23 @@ SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) c if ( m_pSTM == nullptr) GetAuxSurf() ; - if ( nEdge == -1 ) { - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + // se la superficie non è trimmata mi basta recuperare gli edge della superficie + if ( ! m_bTrimmed) { + // se decidessi di non restituire gli edge chiusi e i poli posso discriminare qui + if ( nEdge == -1 ) { + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + } + else + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; + } + // se la superficie è trimmata devo recuperare i loop dello spazio parametrico + else { + for ( int i = 0 ; i < int(m_vCCLoop.size()) ; ++i) + vCC.emplace_back( m_vCCLoop[i]->Clone()) ; } - else - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; return true ; } @@ -2682,14 +2745,15 @@ SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) c ICurveComposite* SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const { - if ( nEdge < 0 || nEdge > 3) + // questa funzione dà per scontato che la superficie NON sia trimmata + if ( nEdge < 0 || nEdge > 3 || m_bTrimmed) return nullptr ; ICurveComposite* pCrvCompo( CreateBasicCurveComposite()) ; switch ( nEdge) { case 0 : { // se il bool è true allora restituisco gli edge con la loro approssimazione in forma di linea spezzata 3D if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; // se il bool è falso restituisco le curve Bezier di edge else { //edge 0, scorro sulle patch in U @@ -2711,7 +2775,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 1 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { //edge 1, scorro sulle patch in V for ( int i = 0 ; i < m_nSpanV ; ++i) { @@ -2732,7 +2796,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 2 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { // edge 2, scorro sulle patch in U for ( int i = 0 ; i < m_nSpanU ; ++i) { @@ -2752,7 +2816,7 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } case 3 : { if ( bLineOrBezier) - pCrvCompo = m_vCCEdge[nEdge]->Clone() ; + pCrvCompo = m_mCCEdge[nEdge][0]->Clone() ; else { // edge 3, scorro sulle patch in V for ( int i = 0 ; i < m_nSpanV ; ++i) { diff --git a/SurfBezier.h b/SurfBezier.h index cbf44e6..b01b1a7 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -19,9 +19,12 @@ #include "CurveComposite.h" #include "SurfTriMesh.h" #include "SurfFlatRegion.h" +//#include "Tree.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkGeoCollection.h" +using namespace std ; +class Tree ; //---------------------------------------------------------------------------- class SurfBezier : public ISurfBezier, public IGeoObjRW @@ -132,6 +135,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzioni per incrementare le coordinate restando dentro lo spazio parametrico bool IncreaseUV( double& dU, double dx, bool bUOrV, double* dUVCopy = nullptr, bool bModifyOrig = true) const override ; bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; + // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier + // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate bool GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; public : // IGeoObjRW @@ -182,7 +187,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW double GetCurveOnVApproxLen( double dU) const ; // funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico) bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; + // restituisce il singolo edge della superficie non trimmata ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; + bool UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -202,8 +209,10 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei - mutable ICRVCOMPOPVECTOR m_vCCEdge ;// vettore delle curve compo degli edge nello spazio 3D - mutable POLYLINEVECTOR m_vPLEdge ; // vettore delle polyline degli edge nello spazio 3D + mutable vector m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D + mutable POLYLINEMATRIX m_mPlEdge ; // vettoredei vettori delle polyline degli edge della superficie nello spazio 3D + mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata + mutable POLYLINEVECTOR m_vPLLoop ; // vettore delle polyline dei loop della superficie trimmata } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index 8b56faf..ad80b37 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -1395,6 +1395,12 @@ Tree::GetPolygons( POLYLINEMATRIX& vPolygons) else { POLYLINEVECTOR vPolygonsBasic ; GetPolygonsBasic( vPolygonsBasic) ; + // aggiungo 4 elementi al vettore che contiene ciò che resta degli edge dopo il trim + for ( int i = 0 ; i < 4 ; ++i) { + m_vCEdge2D.emplace_back() ; + m_vCEdge2D.back().second.Init( false, EPS_SMALL, 1) ; + } + // percorro i loop, trovo le intersezioni con le celle e le categorizzo if ( ! TraceLoopLabelCell( vPolygonsBasic)) return false ; // scorro sulle celle e costruisco i poligoni @@ -1808,6 +1814,40 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells return nCells ; } +//---------------------------------------------------------------------------- +bool +Tree::UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) +{ + Point3d ptLast ; + pl.GetLastPoint( ptLast) ; + if ( pl.AddUPoint( nCount, pt)) + ++ nCount ; + if ( pl.GetPointNbr() != 1 ) { + Vector3d vtDir = pt - ptLast ; + if ( ! vtDir.Normalize()) + return false ; + // se sono allineato con gli edge della cella ROOT + int nEdge = -1 ; + if ( abs( vtDir.x) > 1 - EPS_SMALL) { + if ( pt.y < EPS_SMALL) + nEdge = 2 ; + else if ( m_nSpanV * SBZ_TREG_COEFF - pt.y < EPS_SMALL) + nEdge = 0 ; + } + else if ( abs( vtDir.y) > 1 - EPS_SMALL) { + if ( pt.x < EPS_SMALL ) + nEdge = 1 ; + else if ( m_nSpanU * SBZ_TREG_COEFF - pt.x < EPS_SMALL ) + nEdge = 3 ; + } + if ( nEdge != -1) { + m_vCEdge2D[nEdge].second.AddCurve( m_vCEdge2D[nEdge].first.size() + 1, ptLast, vtDir, pt, vtDir) ; + m_vCEdge2D[nEdge].first.emplace_back( BIPOINT( ptLast, pt)) ; + } + } + return true ; +} + //---------------------------------------------------------------------------- bool Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) @@ -1820,6 +1860,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) // percorro i loop trovando le interezioni con le celle e riempiendo i vettori m_vInters delle varie celle for ( int i = 0 ; i < (int) m_vPlApprox.size() ; ++ i) { PolyLine plLoop = get<0>( m_vPlApprox[i]) ; + // creo la polyline che aggiunge alla polyline originale degli split dove interseca le celle ( serve per ricostruire gli edge aperti della superficie) + PolyLine plLoopSplit ; + int nPtLoopSplit = 0 ; // controllo se il loop è CCW o CW bool bCCW = get<1>( m_vPlApprox[i]) ; // trovo in quale cella è il ptStart @@ -1831,6 +1874,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) advance( ptSecond, 1) ; CurveLine clFirst ; clFirst.Set( ptFirst->first, ptSecond->first) ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptFirst->first) ; // individuo la cella da cui parte il loop INTVECTOR nCells = FindCell( ptStart, clFirst) ; int nId ; @@ -1895,9 +1940,13 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) m_mTree[nId].m_vInters.back().bCCW = bCCW ; // salvo il chunk del loop m_mTree[nId].m_vInters.back().nChunk = m_mChunk[i] ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, vptInters.back()) ; } // aggiungo la fine del segmento nel vettore delle intersezioni vptInters.push_back( ptCurr) ; + // aggiorno la polyline splittata + UpdateSplitLoop( plLoopSplit, nPtLoopSplit, ptCurr) ; } if ( nId == nFirstCell) vptInters.pop_back() ; @@ -1946,6 +1995,8 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) m_mTree[nId].m_vInters[nPass].nOut = nOut ; } } + // salvo la polyline splittata + m_vPlLoop2D.emplace_back( plLoopSplit) ; } // riordino i vettori di intersezione per ogni cella e setto il flag RightEdgeIn @@ -3556,106 +3607,130 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const //---------------------------------------------------------------------------- bool -Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges) -{ - INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge - // recupero le celle sui quattro bordi - vEdges.emplace_back() ; - GetRootNeigh( 0, vEdges[0]) ; - // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, - // quindi devo invertire gli Edge 0 e 1 - reverse( vEdges[0].begin(), vEdges[0].end()) ; - vEdges.emplace_back() ; - GetRootNeigh( 1, vEdges[1]) ; - reverse( vEdges[1].begin(), vEdges[1].end()) ; - vEdges.emplace_back() ; - GetRootNeigh( 2, vEdges[2]) ; - vEdges.emplace_back() ; - GetRootNeigh( 3, vEdges[3]) ; +Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) +{ + // se la superficie non è trimmata ricostruisco dalle celle al bordo + if ( ! m_bTrimmed) { + INTMATRIX vEdges ; // le righe sono gli edge a partire dallo 0, le colonne sono le celle che compongono quell'edge + // recupero le celle sui quattro bordi + vEdges.emplace_back() ; + GetRootNeigh( 0, vEdges[0]) ; + // le celle sui bordi orizzontali sono ordinate per x o y crescente, ma i io voglio costruire gli edge in senso antiorario a partire dal ptTR, + // quindi devo invertire gli Edge 0 e 1 + reverse( vEdges[0].begin(), vEdges[0].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 1, vEdges[1]) ; + reverse( vEdges[1].begin(), vEdges[1].end()) ; + vEdges.emplace_back() ; + GetRootNeigh( 2, vEdges[2]) ; + vEdges.emplace_back() ; + GetRootNeigh( 3, vEdges[3]) ; - // recupero i poligoni base delle celle sui bordi - POLYLINEMATRIX mPL ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[0], vEdges[0]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[1], vEdges[1]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[2], vEdges[2]) ; - mPL.emplace_back() ; - GetPolygonsBasic( mPL[3], vEdges[3]) ; + // recupero i poligoni base delle celle sui bordi + POLYLINEMATRIX mPL ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[0], vEdges[0]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[1], vEdges[1]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[2], vEdges[2]) ; + mPL.emplace_back() ; + GetPolygonsBasic( mPL[3], vEdges[3]) ; - // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato - for ( int i = 0 ; i < int( mPL.size()) ; ++i) { - vPLEdges.emplace_back() ; - int nPtCount = 0 ; - // scorro sui poligoni delle celle di un lato - for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { - Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; - Point3d pt3d ; - // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato - if ( i == 0) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato + for ( int i = 0 ; i < int( mPL.size()) ; ++i) { + //mPLEdges.emplace_back() ; + mPLEdges.back().emplace_back() ; + int nPtCount = 0 ; + // scorro sui poligoni delle celle di un lato + for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { + Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; + Point3d pt3d ; + // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato + if ( i == 0) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[2]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[0][c]).GetTopLeft())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[0][c])[3]) ; - ++ nPtCount ; - } - else if ( i == 1 ) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 1 ) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetTopLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[3]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ; - ++ nPtCount ; - } - else if ( i == 2) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 2) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomLeft()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[0]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ; - ++ nPtCount ; - } - else if ( i == 3) { - while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { - continue ; - } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; - ++ nPtCount ; - // scorro fino alla fine di quel lato - while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { - m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; - vPLEdges.back().AddUPoint( nPtCount, pt3d) ; + else if ( i == 3) { + while ( ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetBottomRight()) && mPL[i][c].GetNextPoint( pt)) { + continue ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[1]) ; + ++ nPtCount ; + // scorro fino alla fine di quel lato + while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) { + m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ; + mPLEdges.back().back().AddUPoint( nPtCount, pt3d) ; + ++ nPtCount ; + } + mPLEdges.back().back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; ++ nPtCount ; } - vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ; - ++ nPtCount ; } } } - + // se la superficie è trimmata ricostruisco dai loop splittati ricostruiti durante il TraceLoop + else { + // per ogni edge creo le compo che compongono l'edge dopo i trim ( possono essere più compo separate tra loro) + for ( int i = 0 ; i < 4 ; ++i) { + INTVECTOR vId ; + Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; + while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) { + PolyLine pl2D ; + int nInd = abs( vId[0]) - 1 ; + pl2D.AddUPoint( 0, m_vCEdge2D[i].first[nInd].first) ; + int nCount = 1 ; + for ( int j = 1 ; j < int( vId.size()) ; ++j) { + nInd = abs( vId[j]) - 1 ; + if ( pl2D.AddUPoint( nCount, m_vCEdge2D[i].first[nInd].second)) + ++ nCount ; + } + // qui devo fare dei controlli prima di aggiungere questa polyline? + mPLEdges[i].emplace_back( pl2D) ; + } + } + } return true ; } diff --git a/Tree.h b/Tree.h index d3ee8be..8c45bc7 100644 --- a/Tree.h +++ b/Tree.h @@ -18,6 +18,7 @@ #include "GeoConst.h" #include "CurveLine.h" #include "/EgtDev/Include/EGkPolyLine.h" +#include "/EgtDev/Include/EGkChainCurves.h" #include //---------------------------------------------------------------------------- @@ -241,13 +242,15 @@ class Tree bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero // ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati bool GetLeaves ( std::vector& vLeaves) const ; // restituisce gli indici delle foglie nell'albero - bool GetEdge3D ( POLYLINEVECTOR& vPLEdges) ; // restituisce gli edge 3D come curve composite + bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline + bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle + { for ( int i = 0 ; i < int( m_vPlLoop2D.size()); ++i) vPl.emplace_back( m_vPlLoop2D[i]) ; return true ; }; void SetTestMode( void) { m_bTestMode = true ;} ; // attivando la test mode, per la costruzione dell'albero viene usata la funzione BuiltTree_test e viene corretta di conseguenza la FindCell // funzioni da usare per ricostruire tagli che vanno aggiunti allo spazio parametrico bool AddCutsToRoot( POLYLINEVECTOR& vCuts) ; // aggiunge i tagli al tree bool CreateCellContour( POLYLINEMATRIX& vPolygons) ; // crea il nuovo contorno esterno, tenendo conto dei tagli - bool IsClosedU( void) { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U - bool IsClosedV( void) { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V + bool IsClosedU( void) const { return m_bClosedU ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro U + bool IsClosedV( void) const { return m_bClosedV ;} ; // funzione che riferisce se la superficie è chiusa lungo il parametro V std::vector GetPoles( void) { return m_vbPole ;} ; // funzione che restituisce i flag che indicano se i lati sono collassati in dei poli private : @@ -280,6 +283,7 @@ class Tree bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW) bool OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const ; // indica a quale edge o vertice il punto è vicino entro EPS_SMALL bool AdjustCuts( void) ; + bool UpdateSplitLoop( PolyLine& pl, int& nCount, Point3d& pt) ; private : @@ -289,7 +293,7 @@ class Tree INTMATRIX m_vChunk ; // elenco dei loop divisi per chunk std::map m_mChunk ; // mappa in cui vengono salvati chunk di appartenza per ogni loop di trim ICURVEPOVECTOR m_vLoop ; // curve di loop - std::vector> m_vPlApprox ; // vettore contenente le approssimazioni dei loop + std::vector> m_vPlApprox ; // vettore contenente le approssimazioni dei loop // il bool indica se la curva è CCW bool m_bBilinear ; // superficie bilineare bool m_bMulti ; // superficie multi-patch bool m_bClosedU ; // superficie chiusa lungo il parametro U @@ -306,4 +310,6 @@ class Tree INTVECTOR m_vnLeaves ; // vettore delle foglie INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch bool m_bTestMode ; // bool che indica se la test mode è attiva + POLYLINEVECTOR m_vPlLoop2D ; // vettore che contiene le polyline che rappresentano i loop di trim tenendo conto della divisione in celle + std::vector> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim. } ; \ No newline at end of file From 8c4b0bde37777f49696965ea88a96fa17813f66b Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 13 Mar 2024 16:36:12 +0100 Subject: [PATCH 22/31] EgtGeomKernel : - corretto un bug nell'aggiornamento della grafica dopo il trim di sup di Bezier. #11 --- SurfBezier.cpp | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 91899e1..4669b80 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -168,6 +168,9 @@ SurfBezier::SetTrimRegion( ISurfFlatRegion& sfrTrimReg, bool bIntersectOrSubtrac } else m_pTrimReg = GetBasicSurfFlatRegion( Release( pSfrTrim)) ; + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + // setto la superficie trimmata m_bTrimmed = true ; return true ; } @@ -1522,33 +1525,6 @@ SurfBezier::GetAuxSurf( void) const UpdateEdgeFromTree( mPlEdges) ; - /////////////////////da testare///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - // bool bComposed = true ; - // m_mCCEdge.clear() ; - // for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { - // m_mCCEdge.emplace_back() ; - // for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { - // m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; - // PolyLine pl3D ; - // Point3d pt ; mPlEdges[i][j].GetFirstPoint( pt) ; - // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // int nCount = 0 ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // while( mPlEdges[i][j].GetNextPoint( pt)){ - // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // } - // if ( ! m_mCCEdge.back().back()->FromPolyLine( mPlEdges[i][j]) ) - // bComposed = false ; - // } - // } - - // if ( ! bComposed) - // m_mPLEdge = mPlEdges ; - // //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ; From 93678ce56ce718e1a6a9c41938804e65c6aad5bb Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 14 Mar 2024 10:03:34 +0100 Subject: [PATCH 23/31] EgtGeomKernel : - migliorata la gestione dell'aggiornamento degli edge3D delle superfici Bezier. --- SurfBezier.cpp | 70 ++++++++++++++++++++++++++++++++++++++++---------- SurfBezier.h | 6 ++--- 2 files changed, 59 insertions(+), 17 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 4669b80..d368e81 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1444,32 +1444,61 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const //---------------------------------------------------------------------------- bool -SurfBezier::UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const +SurfBezier::UpdateEdgesFromTree( Tree& tr) const { + POLYLINEMATRIX mPlEdges(4) ; + tr.GetEdges3D( mPlEdges) ; bool bComposed = true ; - m_mCCEdge.clear() ; - for ( int i= 0 ; i < int( mPl.size()); ++i) { - m_mCCEdge.emplace_back() ; - for ( int j = 0 ; j < int ( mPl[i].size()) ; ++j) { - m_mCCEdge.back().emplace_back(CreateBasicCurveComposite()) ; + //m_mCCEdge.clear() ; + for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { + //m_mCCEdge.emplace_back() ; + for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { + m_mCCEdge[i].emplace_back(CreateBasicCurveComposite()) ; PolyLine pl3D ; - Point3d pt ; mPl[i][j].GetFirstPoint( pt) ; + Point3d pt ; mPlEdges[i][j].GetFirstPoint( pt) ; Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; int nCount = 0 ; pl3D.AddUPoint( nCount, pt3D) ; ++ nCount ; - while( mPl[i][j].GetNextPoint( pt)){ + while( mPlEdges[i][j].GetNextPoint( pt)){ GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; pl3D.AddUPoint( nCount, pt3D) ; ++ nCount ; } - if ( ! m_mCCEdge.back().back()->FromPolyLine( pl3D)) + if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)){ bComposed = false ; + // qui NON faccio il pop_back dell'elemento aggiunto, anche se rimasto vuoto, perché devo avere corrispondenza per il numero di elementi tra m_mCCEdge e m_mPlEdge + } } } // se degli edge hanno delle curve non valide allora salvo anche le polyline - if ( ! bComposed) - m_mPlEdge = mPl ; + if ( ! bComposed) { + for ( int i = 0 ; i < int(mPlEdges.size()) ; ++i) { + for ( int j = 0 ; j < int(mPlEdges[i].size()) ; ++j ) { + m_mPlEdge[i].emplace_back( mPlEdges[i][j]) ; + } + } + } + + if ( m_bTrimmed ) { + POLYLINEVECTOR vPl ; + tr.GetSplitLoops( vPl) ; + for( int i = 0 ; i < int( vPl.size()); ++i) { + m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; + PolyLine pl3D ; + Point3d pt ; vPl[i].GetFirstPoint( pt) ; + Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + int nCount = 0 ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + while( vPl[i].GetNextPoint( pt)){ + GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + } + m_vCCLoop.back()->FromPolyLine(pl3D) ; + } + } return true ; } @@ -1494,7 +1523,12 @@ SurfBezier::GetAuxSurf( void) const BIPNTVECTOR vTrees ; Tree.GetIndependentTrees( vTrees) ; bool bTest = false ; // per debug - POLYLINEMATRIX mPlEdges(4) ; + //POLYLINEMATRIX mPlEdges(4) ; + // resetto il vettore degli edge + m_mCCEdge.clear() ; + m_mCCEdge = vector(4) ; + //m_mPlEdge.clear() ; + //m_mPlEdge = vector(4) ; for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; @@ -1514,7 +1548,8 @@ SurfBezier::GetAuxSurf( void) const m_bClosedU = m_bClosedU || Tree.IsClosedU() ; m_bClosedV = m_bClosedU || Tree.IsClosedV() ; // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - Tree.GetEdges3D( mPlEdges) ; + //Tree.GetEdges3D( mPlEdges) ; + UpdateEdgesFromTree( Tree) ; } //// per usare i polygon basic////////////////////// //for (int k = 0 ; k < (int)vPL.size(); ++k) { @@ -1523,7 +1558,6 @@ SurfBezier::GetAuxSurf( void) const //} //// per usare i polygon basic/////////////////// - UpdateEdgeFromTree( mPlEdges) ; if ( int(vvPL.size()) == 0) LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface couldn't be triangulated, hence wasn't drawn") ; @@ -2284,7 +2318,9 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( int( m_vbPole.size()) == 0) return false ; if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3] || m_bClosedU || m_bClosedV) { + // scorro sugli edge for ( int c = 0 ; c < 4 ; ++c) { + // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[c].size()) ; ++i) { if ( ! m_mCCEdge[c][i]->IsValid() ) { Point3d pt ; @@ -2355,8 +2391,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in INTVECTOR vOn(3) ; fill( vOn.begin(), vOn.end(), -1) ; int nVertOnPole = -1 ; + // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { + // scorro sugli edge for ( int ed = 0 ; ed < 4; ++ed) { + // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { if ( ! m_mCCEdge[ed][i]->IsValid() ) { Point3d pt ; @@ -2404,8 +2443,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in INTVECTOR vOn(3) ; fill( vOn.begin(), vOn.end(), -1) ; int nVertOnPole = -1 ; + // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { + //scorro sugli edge for (int ed = 0 ; ed < 4 ; ++ed) { + // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { if ( ! m_mCCEdge[ed][i]->IsValid()) { Point3d pt ; diff --git a/SurfBezier.h b/SurfBezier.h index b01b1a7..7238f9b 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -189,7 +189,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ; // restituisce il singolo edge della superficie non trimmata ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ; - bool UpdateEdgeFromTree( POLYLINEMATRIX& mPl) const ; + bool UpdateEdgesFromTree( Tree& tr) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -210,9 +210,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei mutable vector m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D - mutable POLYLINEMATRIX m_mPlEdge ; // vettoredei vettori delle polyline degli edge della superficie nello spazio 3D + mutable POLYLINEMATRIX m_mPlEdge ; // vettore dei vettori delle polyline degli edge della superficie nello spazio 3D mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata - mutable POLYLINEVECTOR m_vPLLoop ; // vettore delle polyline dei loop della superficie trimmata + //mutable POLYLINEVECTOR m_vPlLoop ; // vettore delle polyline dei loop della superficie trimmata } ; //----------------------------------------------------------------------------- From 4483434711c3940fe76004b6ff41a31c90e96a76 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 14 Mar 2024 18:02:16 +0100 Subject: [PATCH 24/31] EgtGeomKernel : - migliorata gestione degli edge3D delle sup di Bezier. #11 --- CurveComposite.cpp | 25 +++++++++++++++++++++++++ CurveComposite.h | 6 ++++-- SurfBezier.cpp | 38 +++++++++++++------------------------- SurfBezier.h | 2 -- Tree.cpp | 1 - 5 files changed, 42 insertions(+), 30 deletions(-) diff --git a/CurveComposite.cpp b/CurveComposite.cpp index a384685..8eba98f 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -3763,3 +3763,28 @@ CurveComposite::ResetVoronoiObject() const delete m_pVoronoiObj ; m_pVoronoiObj = nullptr ; } + +//---------------------------------------------------------------------------- +bool +CurveComposite::FromPoint(Point3d& ptStart) +{ + // verifico lo stato + if ( m_nStatus != TO_VERIFY) + return false ; + // assegno il punto e setto lo stato + m_ptStart = ptStart ; + m_nStatus = IS_A_POINT ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::GetOnlyPoint(Point3d& ptStart) const +{ + // verifico lo stato + if ( m_nStatus != IS_A_POINT) + return false ; + // restituisco il punto + ptStart = m_ptStart ; + return true ; +} diff --git a/CurveComposite.h b/CurveComposite.h index ee458fc..f60baf8 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -150,7 +150,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool IsParamAtJoint( double dU) const override ; ICurve* RemoveFirstOrLastCurve( bool bLast = true) override ; bool ChangeStartPoint( double dU) override ; - bool AddPoint( const Point3d& ptStart) override ; + bool AddPoint( const Point3d& ptStart) override ; // funzione per aggiungere il ptStart prima di usare la funzione AddLine bool AddLine( const Point3d& ptNew, bool bEndOrStart = true) override ; bool AddLineTg( double dLen, bool bEndOrStart = true) override ; bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ; @@ -177,6 +177,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ; bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ; bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ; + bool FromPoint( Point3d& ptStart) override ; // funzione per settare la curva ad un unico punto + bool GetOnlyPoint( Point3d& ptStart) const override ; // funzione per recuperare l'unico punto da cui è composta la curva ( degenere) public : // IGeoObjRW int GetNgeId( void) const override ; @@ -209,7 +211,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW void ResetVoronoiObject( void) const ; private : - enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; + enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ; private : typedef std::deque PCRVSMPL_DEQUE ; diff --git a/SurfBezier.cpp b/SurfBezier.cpp index d368e81..534cb3d 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1448,10 +1448,7 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const { POLYLINEMATRIX mPlEdges(4) ; tr.GetEdges3D( mPlEdges) ; - bool bComposed = true ; - //m_mCCEdge.clear() ; for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { - //m_mCCEdge.emplace_back() ; for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { m_mCCEdge[i].emplace_back(CreateBasicCurveComposite()) ; PolyLine pl3D ; @@ -1465,17 +1462,9 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const pl3D.AddUPoint( nCount, pt3D) ; ++ nCount ; } - if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)){ - bComposed = false ; - // qui NON faccio il pop_back dell'elemento aggiunto, anche se rimasto vuoto, perché devo avere corrispondenza per il numero di elementi tra m_mCCEdge e m_mPlEdge - } - } - } - // se degli edge hanno delle curve non valide allora salvo anche le polyline - if ( ! bComposed) { - for ( int i = 0 ; i < int(mPlEdges.size()) ; ++i) { - for ( int j = 0 ; j < int(mPlEdges[i].size()) ; ++j ) { - m_mPlEdge[i].emplace_back( mPlEdges[i][j]) ; + if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)) { + Point3d ptStart ; pl3D.GetFirstPoint( ptStart) ; + m_mCCEdge[i].back()->FromPoint( ptStart) ; } } } @@ -1523,12 +1512,9 @@ SurfBezier::GetAuxSurf( void) const BIPNTVECTOR vTrees ; Tree.GetIndependentTrees( vTrees) ; bool bTest = false ; // per debug - //POLYLINEMATRIX mPlEdges(4) ; // resetto il vettore degli edge m_mCCEdge.clear() ; m_mCCEdge = vector(4) ; - //m_mPlEdge.clear() ; - //m_mPlEdge = vector(4) ; for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; @@ -1548,7 +1534,6 @@ SurfBezier::GetAuxSurf( void) const m_bClosedU = m_bClosedU || Tree.IsClosedU() ; m_bClosedV = m_bClosedU || Tree.IsClosedV() ; // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria - //Tree.GetEdges3D( mPlEdges) ; UpdateEdgesFromTree( Tree) ; } //// per usare i polygon basic////////////////////// @@ -2235,7 +2220,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) pCrv->GetStartPoint( ptStart) ; pCrv->GetStartDir( vtDirS) ; pCrv->GetEndDir( vtDirE) ; - //vtDirS.Rotate( Z_AX, bPos? 90 : -90) ; vtDir = vtDirS + vtDirE ; PtrOwner pCL( CreateCurveLine()) ; pCL->SetPVL( ptStart, vtDir, 1e6) ; @@ -2322,9 +2306,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for ( int c = 0 ; c < 4 ; ++c) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[c].size()) ; ++i) { - if ( ! m_mCCEdge[c][i]->IsValid() ) { + if ( ! m_mCCEdge[c][i]->IsValid()) { Point3d pt ; - m_mPlEdge[c][i].GetFirstPoint(pt) ; + if ( ! m_mCCEdge[c][i]->GetOnlyPoint(pt)) + return false ; vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ; nInters += vInters.back() ; } @@ -2397,9 +2382,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for ( int ed = 0 ; ed < 4; ++ed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { - if ( ! m_mCCEdge[ed][i]->IsValid() ) { + if ( ! m_mCCEdge[ed][i]->IsValid()) { Point3d pt ; - m_mPlEdge[ed][i].GetFirstPoint(pt) ; + if ( ! m_mCCEdge[ed][i]->GetOnlyPoint(pt)) + return false ; if ( AreSamePointApprox( pt, vPT[p])) { vOn[p] = ed ; // se un vertice sta su un polo me lo segno @@ -2451,7 +2437,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { if ( ! m_mCCEdge[ed][i]->IsValid()) { Point3d pt ; - m_mPlEdge[ed][i].GetFirstPoint( pt) ; + if ( ! m_mCCEdge[ed][i]->GetOnlyPoint( pt)) + return false ; if ( AreSamePointApprox( pt, vPT[p])) { vOn[p] = ed ; // se un vertice sta su un polo me lo segno @@ -2513,7 +2500,8 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in for( int i = 0 ; int( m_mCCEdge[c].size()) ; ++i) { if ( ! m_mCCEdge[c][i]->IsValid()) { Point3d pt ; - m_mPlEdge[c][i].GetFirstPoint( pt) ; + if ( ! m_mCCEdge[c][i]->GetOnlyPoint( pt)) + return false ; vbOn[p] = vbOn[p] || AreSamePointApprox( pt, vPT[p]) ; } else diff --git a/SurfBezier.h b/SurfBezier.h index 7238f9b..20ae6b3 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -210,9 +210,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW int m_nTempProp[2] ; // vettore proprietà temporanee double m_dTempParam[2] ; // vettore parametri temporanei mutable vector m_mCCEdge ;// vettore dei vettori che contengono le curve compo degli edge della superficie nello spazio 3D - mutable POLYLINEMATRIX m_mPlEdge ; // vettore dei vettori delle polyline degli edge della superficie nello spazio 3D mutable ICRVCOMPOPOVECTOR m_vCCLoop ; // vettore dei loop della superficie trimmata - //mutable POLYLINEVECTOR m_vPlLoop ; // vettore delle polyline dei loop della superficie trimmata } ; //----------------------------------------------------------------------------- diff --git a/Tree.cpp b/Tree.cpp index ad80b37..38b6b62 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3639,7 +3639,6 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { - //mPLEdges.emplace_back() ; mPLEdges.back().emplace_back() ; int nPtCount = 0 ; // scorro sui poligoni delle celle di un lato From 632b711b2a97c9b54a009757b20d3b30ec6dc35a Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 20 Mar 2024 09:40:16 +0100 Subject: [PATCH 25/31] EgtGeomKernel : - edge 3D di una Bezier tramite calcolo delle autointersezioni in 3D. --- SurfBezier.cpp | 400 +++++++++++++++++++++++++++++++++++++++++++++++-- SurfBezier.h | 2 +- 2 files changed, 390 insertions(+), 12 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 534cb3d..c97719b 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -38,6 +38,7 @@ #include #include "/EgtDev/Include/EGkGeoObjSave.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" +#include "/EgtDev/Include/EGkIntervals.h" using namespace std ; @@ -1469,9 +1470,16 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const } } - if ( m_bTrimmed ) { + if ( m_bTrimmed) { POLYLINEVECTOR vPl ; tr.GetSplitLoops( vPl) ; + + //// per split nel parametrico + //for( int i = 0 ; i < int( vPl.size()); ++i) { + // m_vCCLoop2D.emplace_back(CreateBasicCurveComposite()) ; + // m_vCCLoop2D.back()->FromPolyLine(vPl[i]) ; + //} + for( int i = 0 ; i < int( vPl.size()); ++i) { m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; PolyLine pl3D ; @@ -1532,7 +1540,7 @@ SurfBezier::GetAuxSurf( void) const // aggiorno la chiusura della superficie m_bClosedU = m_bClosedU || Tree.IsClosedU() ; - m_bClosedV = m_bClosedU || Tree.IsClosedV() ; + m_bClosedV = m_bClosedV || Tree.IsClosedV() ; // salvo i bordi in 3d, che servono in caso si voglia trimmare la superficie DOPO aver costruito la trimesh ausiliaria UpdateEdgesFromTree( Tree) ; } @@ -1868,6 +1876,34 @@ struct hash { bool SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) { + //// debug per controllare le autointersezione degli edge 3D + //ICRVCOMPOPOVECTOR vCCEdge ; + //GetOpenEdges3D(vCCEdge, true, -1) ; + //SelfIntersCurve sic( *vCCEdge[0]) ; + //PNTVECTOR vPnt0 ; + //DBLVECTOR vdU ; + //IntCrvCrvInfo iccInfo0 ; + //for ( int i = 0 ; sic.GetIntCrvCrvInfo( i, iccInfo0) ; ++ i) { + // if ( ! iccInfo0.bOverlap) { + // vPnt0.push_back( iccInfo0.IciA[0].ptI) ; + // vPnt0.push_back( iccInfo0.IciB[0].ptI) ; + // vdU.push_back(iccInfo0.IciA[0].dU) ; + // vdU.push_back(iccInfo0.IciB[0].dU) ; + // } + // else { + // vPnt0.push_back( iccInfo0.IciA[0].ptI) ; + // vPnt0.push_back( iccInfo0.IciA[1].ptI) ; + // vPnt0.push_back( iccInfo0.IciB[0].ptI) ; + // vPnt0.push_back( iccInfo0.IciB[1].ptI) ; + // vdU.push_back(iccInfo0.IciA[0].dU) ; + // vdU.push_back(iccInfo0.IciA[1].dU) ; + // vdU.push_back(iccInfo0.IciB[0].dU) ; + // vdU.push_back(iccInfo0.IciB[1].dU) ; + // } + //} + //int a = 0 ; + + // faccio l'intersezione della trimesh ausiliaria con il piano posso ottenere: punti, curve 3d e triangoli( coplanari al piano di taglio) // i punti li escludo // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim @@ -2721,9 +2757,10 @@ SurfBezier::CalcPoles( void) //---------------------------------------------------------------------------- bool -SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) const +SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) const { // se nEdge non è definito ( == -1) allora restituisco tutti gli edge in ordine + // se bOpenOrAll è true allora restituisco solo gli edge aperti e che non sono di polo if ( m_pSTM == nullptr) GetAuxSurf() ; @@ -2731,18 +2768,359 @@ SurfBezier::GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) c if ( ! m_bTrimmed) { // se decidessi di non restituire gli edge chiusi e i poli posso discriminare qui if ( nEdge == -1 ) { - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + vCC = ICRVCOMPOPOVECTOR(4) ; + if ( ! m_bClosedV ) { + if ( ! m_vbPole[0]) + vCC[0].Set( GetSingleEdge3D( bLineOrBezier, 0)) ; + if ( ! m_vbPole[2]) + vCC[2].Set( GetSingleEdge3D( bLineOrBezier, 2)) ; + } + if ( ! m_bClosedU ) { + if ( ! m_vbPole[1]) + vCC[1].Set( GetSingleEdge3D( bLineOrBezier, 1)) ; + if ( ! m_vbPole[3]) + vCC[3].Set( GetSingleEdge3D( bLineOrBezier, 3)) ; + } + //// se li volessi restituire tutti + //vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 0)) ; + //vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 1)) ; + //vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 2)) ; + //vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, 3)) ; + } + else { + if ( (((nEdge == 0 || nEdge == 2) && ! m_bClosedV) || ((nEdge == 1 || nEdge == 3) && ! m_bClosedU)) && ! m_vbPole[nEdge]) + vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; } - else - vCC.emplace_back( GetSingleEdge3D( bLineOrBezier, nEdge)) ; } // se la superficie è trimmata devo recuperare i loop dello spazio parametrico else { - for ( int i = 0 ; i < int(m_vCCLoop.size()) ; ++i) - vCC.emplace_back( m_vCCLoop[i]->Clone()) ; + //per split nel parametrico + // + //// devo ricostruire i bordi aperti in caso di superficie chiusa + //// costruisco gli edge + //ICurveLine* pCLU0( CreateCurveLine()) ; + //ICurveLine* pCLU1( CreateCurveLine()) ; + //ICurveLine* pCLV0( CreateCurveLine()) ; + //ICurveLine* pCLV1( CreateCurveLine()) ; + //if ( m_bClosedU ) { + // pCLU0->Set( Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0), ORIG) ; + // pCLU1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0)) ; + //} + //if ( m_bClosedV ) { + // pCLV0->Set( ORIG, Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0)) ; + // pCLV1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0), Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0)) ; + //} + //ICRVLINEPOVECTOR vEdge ; + //// li metto con l'ordine degli edge + //vEdge.emplace_back( pCLV1) ; + //vEdge.emplace_back( pCLU0) ; + //vEdge.emplace_back( pCLV0) ; + //vEdge.emplace_back( pCLU1) ; + //// costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e il loop esterno dello spazio parametrico + //// i 4 elementi fanno riferimento ai 4 edge. per ogni loop viene salvato il vettore delle intersezioni con tale edege + //vector> vmInters(4) ; + //unordered_map mAdded ; // salvo per ogni loop il gruppo di mLoopTo3D in cui è finito + //for ( int l = 0 ; l < int( m_vCCLoop2D.size()) ; ++ l) { + // // devo controllare se i loop si appoggiano a bordi chiusi + // // se ne ho più di uno che si appoggia allora devo vedere se trovo dei gruppi di loop che in realtà in 3d sono un edge unico, ma nel 2d risultano a cavallo dell'edge di chiusura + // PtrOwner pLoop( m_vCCLoop2D[l]->Clone()) ; + // //int nInters = 0 ; + // for ( int j = 0 ; j < 4 ; ++j) { + // // il primo è un loop di trim, il secondo è un edge dello spazio parametrico + // IntersCurveCurve icc( *pLoop, *vEdge[j]) ; + // ICCIVECTOR vICC ; + // for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i ) { + // IntCrvCrvInfo iccInfo ; + // icc.GetIntCrvCrvInfo( i, iccInfo) ; + // vICC.push_back( iccInfo) ; + // } + // if ( int(vICC.size()) > 0) { + // vmInters[j].insert(pair(l, vICC)) ; + // //++ nInters ; + // } + // } + // //if ( nInters > 0) + // // li aggiungo tutti, tanto devo costruire anche quelli che non fanno intersezioni con gli edge + // mAdded.insert( pair( l, -1)) ; + //} + //INTMATRIX mLoopTo3D ; + //// se ho delle intersezioni devo capire se ci sono loop che vanno abbinati e metterli nell'ordine giusto + //// per ogni intersezione controllo se ptStart o ptEnd corrispondono a quelli di qualche altro loop passando attraverso un edge chiuso + //if ( m_bClosedV) { + // // scorro i loop che fanno intersezioni con l'edge 0 ( V=1) + // for ( pair vInters0 : vmInters[0]) { + // // se il loop corrente è già stato aggiunto lo salto + // if ( mAdded[vInters0.first] != -1) + // continue ; + // INTVECTOR vPairing ; + // // scorro le intersezioni del loop + // for ( IntCrvCrvInfo inters0 : vInters0.second) { + // Point3d ptStart = inters0.IciA[0].ptI ; + // Point3d ptEnd = inters0.IciA[1].ptI ; + // // voglio che il punto start sia quello con la x minore + // if ( ptStart.x > ptEnd.x) + // swap( ptStart, ptEnd) ; + // // cerco sui loop (non ancora aggiunti) che fanno intersezioni con l'edge opposto ( edge 2, V=0) se ho una corrispondenza + // // se trovo un abbinamento con un loop che fa già parte di un gruppo mi salvo il numero del gruppo + // int nGroup = -1 ; + // for ( pair vInters2 : vmInters[2] ) { + // //if ( mAdded[vInters2.first] != -1) + // // continue ; ////// non è vero!!!!! dovrei semplicemente aggiungere il loop corrente al gruppo a cui appartiene questo loop/////////////////////////// + // + // + // // scorro le intersezioni di questo loop + // for ( IntCrvCrvInfo inters2 : vInters2.second) { + // // se lo start e end del loop corrente sono compresi tra lo start e l'end di un loop che fa intesezione sull'edge opposto ( o viceversa) allora devo accoppairli + // // il loop che fa intersezione sull'edge opposto potrebbe essere il corrente stesso + // Point3d ptStart2 = inters2.IciA[0].ptI ; + // Point3d ptEnd2 = inters2.IciA[1].ptI ; + // // come ptStart2 prendo quello con la x minore + // if ( ptStart2.x > ptEnd.x) + // swap( ptStart2, ptEnd2) ; + // if ( ((ptStart.x - 1 < ptStart2.x && ptStart2.x < ptEnd.x + 1) && (ptStart.x - 1 < ptEnd2.x && ptEnd2.x < ptEnd.x + 1)) || + // ((ptStart2.x - 1 < ptStart.x && ptStart.x < ptEnd2.x + 1) && (ptStart2.x - 1 < ptEnd.x && ptEnd.x < ptEnd2.x + 1))) { + // // aggiungo il loop alla lista degli accoppiati e salvo l'indice del gruppo a cui è stato aggiunto + // if ( mAdded[vInters2.first] == -1) { + // vPairing.push_back( vInters2.first) ; + // mAdded[vInters2.first] == int(mLoopTo3D.size()) ; + // } + // else if ( mAdded[vInters2.first] != -1){ + // nGroup = mAdded[vInters2.first] ; + // } + // // qui dovrei anche decidere come trimmare le curve e quante curve 3D devono uscire da questo loop che fa intersezione con gli edge + // asasdasa + + // break ; + // } + // } + // } + // // aggiungo il loop corrente + // vPairing.push_back( vInters0.first) ; + // if ( nGroup == -1 ) { + // mAdded[vInters0.first] == int( mLoopTo3D.size()) ; + // if ( int( mLoopTo3D.size()) > 0 && int(mLoopTo3D.back().size()) > 0) + // mLoopTo3D.emplace_back(vPairing) ; + // else + // mLoopTo3D.back() = vPairing ; + // } + // else { + // mAdded[vInters0.first] = nGroup ; + // mLoopTo3D[nGroup].emplace_back( vPairing) ; + // } + // } + // } + // // qua devo ciclare di nuovo sui loop che fanno intersezione con l'edge 2 per verificare se li ho aggiunti tutti + //} + //if ( m_bClosedU ) { + // for ( int i = 0 ; i < int( vmInters[1].size()) ; ++i ) { + // Point3d ptStart, ptEnd ; + // } + //} + + //// qui portei estrarre una funzione che proietta curve dal parametrico al 3D + //// scorro i gruppi di loop 2D formati da loop che partecipano alla formazione dello stesso loop nel 3D + //for( int i = 0 ; i < int( mLoopTo3D.size()); ++i) { + // vCC.emplace_back(CreateBasicCurveComposite()) ; + // PolyLine pl3D ; + // // scorro i loop 2D all'interno del gruppo + // for ( int j = 0 ; j < int( mLoopTo3D[i].size()) ; ++j) { + // // la composita è una spezzata composta da linee, quindi la ricostruisco come polyline in 3D + // Point3d pt ; m_vCCLoop2D[mLoopTo3D[i][j]]->GetStartPoint( pt) ; + // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // int nCount = 0 ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // // scorro le curve singole della composita + // for ( int k = 0 ; k < m_vCCLoop2D[mLoopTo3D[i][j]]->GetCurveCount() ; ++k){ + // // recupero l'end point della curva e lo porto in 3D + // m_vCCLoop2D[mLoopTo3D[i][j]]->GetCurve( k)->GetEndPoint( pt) ; + // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // } + // } + // vCC.back()->FromPolyLine(pl3D) ; + //} + + //// se volessi restiturie tutto passo i loop del parametrico portati in 3D + //for ( int i = 0 ; i < int(m_vCCLoop2D.size()) ; ++i) + // vCC.emplace_back( m_vCCLoop2D[i]->Clone()) ; + + + + //// se il lato di chiusura è orientato come Z allora cambio sistema di riferimento per trovare le intersezioni XY + //bool bMod = false ; + //Frame3d frRot ; + //if ( m_bClosedU) { + // Point3d ptP00 ; GetPointD1D2( 0 , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; + // Point3d ptP01 ; GetPointD1D2( 0 , m_nSpanV * SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ; + // Point3d ptP0001 ; GetPointD1D2( 0 , m_nSpanV * SBZ_TREG_COEFF / 2, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP0001) ; + // Vector3d vtDir01 = ptP01 - ptP00 ; + // Vector3d vtDir0001 = ptP0001 - ptP00 ; + // if ( ! vtDir01.Normalize() || ! vtDir0001.Normalize()) + // return false ; + // if ( AreSameVectorApprox( vtDir01, vtDir0001) && AreSameOrOppositeVectorApprox( vtDir01, Z_AX)) { + // // il lato di chiusura è parallelo all'asse Z, quindi prima di calcolare le autointersezioni devo cambiare sistema di riferimento + // bMod = true ; + // frRot.Set( ORIG, X_AX /*+ Y_AX*/) ; + // //for ( int j = 0 ; j < int(m_vCCLoop.size()) ; ++j ) + // // m_vCCLoop[j]->ToLoc( frRot) ; + // } + //} + //if ( m_bClosedV) { + // Point3d ptP00 ; GetPointD1D2( 0 , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; + // Point3d ptP10 ; GetPointD1D2( m_nSpanU * SBZ_TREG_COEFF , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ; + // Point3d ptP0010 ; GetPointD1D2( m_nSpanU * SBZ_TREG_COEFF / 2, 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP0010) ; + // Vector3d vtDir10 = ptP10 - ptP00 ; + // Vector3d vtDir0010 = ptP0010 - ptP00 ; + // if ( ! vtDir10.Normalize() || ! vtDir0010.Normalize()) + // return false ; + // if ( AreSameVectorApprox( vtDir10, vtDir0010) && AreSameOrOppositeVectorApprox( vtDir10, Z_AX)) { + // // il lato di chiusura è parallelo all'asse Z, quindi prima di calcolare le autointersezioni devo cambiare sistema di riferimento + // bMod = true ; + // frRot.Set( ORIG, X_AX + Y_AX) ; + // //for ( int j = 0 ; j < int(m_vCCLoop.size()) ; ++j ) + // // m_vCCLoop[j]->ToLoc( frRot) ; + // } + //} + + + // con le inters in 3D + for ( int i = 0 ; i < int( m_vCCLoop.size()) ; ++i) { + //if ( bMod) + // m_vCCLoop[i]->ToLoc( frRot) ; + + //// debug + ////disegno le curve nel nuovo riferimento + //vCC.emplace_back( Release(m_vCCLoop[i])) ; + // continue ; + ////debug + + // le autotintersezioni in 3D fanno casino!!!!!!!!! + //// calcolo le autointersezioni per capire quali tratti sono sul lato di chiusura + //SelfIntersCurve sic( *m_vCCLoop[i]) ; + //PNTVECTOR vPnt ; + //DBLVECTOR vdU ; + //IntCrvCrvInfo iccInfo0 ; + //for ( int j = 0 ; sic.GetIntCrvCrvInfo( j, iccInfo0) ; ++ j) { + // if ( ! iccInfo0.bOverlap) { + // Point3d ptA = iccInfo0.IciA[0].ptI ; + // Point3d ptB = iccInfo0.IciB[0].ptI ; + // if ( AreSamePointApprox( ptA, ptB)) { + // vPnt.push_back( ptA) ; + // vPnt.push_back( ptB) ; + // vdU.push_back(iccInfo0.IciA[0].dU) ; + // vdU.push_back(iccInfo0.IciB[0].dU) ; + // } + // } + // else { + // Point3d ptA0 = iccInfo0.IciA[0].ptI ; + // Point3d ptB0 = iccInfo0.IciB[0].ptI ; + // if ( AreSamePointApprox( ptA0, ptB0) ) { + // vPnt.push_back( ptA0) ; + // vPnt.push_back( ptB0) ; + // vdU.push_back(iccInfo0.IciA[0].dU) ; + // vdU.push_back(iccInfo0.IciB[0].dU) ; + // } + // Point3d ptA1 = iccInfo0.IciA[1].ptI ; + // Point3d ptB1 = iccInfo0.IciB[1].ptI ; + // if ( AreSamePointApprox( ptA1, ptB1) ) { + // vPnt.push_back( ptA1) ; + // vPnt.push_back( ptB1) ; + // vdU.push_back(iccInfo0.IciA[1].dU) ; + // vdU.push_back(iccInfo0.IciB[1].dU) ; + // } + // } + //} + //sort( vdU.begin(), vdU.end()) ; + //if ( bMod) + // m_vCCLoop[i]->ToGlob( frRot) ; + + + // calcolo le autointersezioni a mano + // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) + //double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; + //Intervals inDomain ; inDomain.Set( dStart, dEnd) ; + DBLVECTOR vdU ; + BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; + fill( vbErased.begin(), vbErased.end(), false) ; + // scorro tutte le curve singole della compo + for ( int k = 0 ; k < int( m_vCCLoop[i]->GetCurveCount()); ++k) { + const ICurve* pCrvA = m_vCCLoop[i]->GetCurve( k) ; + if ( vbErased[k]) + continue ; + Point3d ptStartA ; pCrvA->GetStartPoint( ptStartA) ; + Point3d ptEndA ; pCrvA->GetEndPoint( ptEndA) ; + // devo confrontarla con tutte le successive + for ( int w = k + 1 ; w < int(m_vCCLoop[i]->GetCurveCount()); ++w ) { + const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; + Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; + Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; + if ( ( AreSamePointApprox( ptStartA, ptEndB) && AreSamePointApprox( ptEndA, ptStartB)) || + ( AreSamePointApprox( ptStartA, ptStartB) && AreSamePointApprox( ptEndA, ptEndB))) { + vbErased[k] = true ; + //inDomain.Subtract(k, k+1) ; + vbErased[w] = true ; + //inDomain.Subtract(w, w+1) ; + break ; + } + } + // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve + // ci sono intersezioni sennò non posso accorgermene + } + double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; + if ( vbErased[0]) + vdU.emplace_back( dStart) ; + for ( int w = 1 ; w < int( vbErased.size()) ; ++w) { + if ( (vbErased[w] && ! vbErased[w - 1]) || (! vbErased[w] && vbErased[w - 1])) + vdU.emplace_back( w) ; + } + if ( vbErased.back()) + vdU.emplace_back( dEnd) ; + ICRVCOMPOPOVECTOR vpCCOpen ; + //double dStartA, dEndA ; inDomain.GetFirst( dStartA, dEndA) ; + //double dStartB, dEndB ; inDomain.GetLast( dStartB, dEndB) ; + //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( dStartA + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; + //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( dEndB - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; + + + //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( vdU[0] + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; + //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( vdU.back() - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; + //// scopro quali sono gli intervalli da tenere e quali da cancellare + //int nFirst = 0 ; + //if ( AreSamePointApprox( ptTest0, ptTest1)) { + // nFirst = 1 ; + // if ( vdU[0] > EPS_SMALL ) + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; + //} + + if ( vdU[0] > EPS_SMALL) + vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; + + for ( int j = 0 ; j < int(vdU.size() / 2) - 1 ; ++j) + vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU[j*2 + 1], vdU[(j+ 1)*2]))) ; + + // se dopo l'ultimo dU ho ancora un pezzo di curva allora lo aggiungo + if ( dEnd - vdU.back() > EPS_SMALL) { + vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU.end()[-2], vdU.back()))) ; + } + + // creo la chain a mano con le compo + BOOLVECTOR vbAdded( vpCCOpen.size()) ; + fill( vbAdded.begin(), vbAdded.end(), false) ; + for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { + if ( vbAdded[k]) + continue ; + PtrOwner pCC( vpCCOpen[k]->Clone()) ; + vbAdded[k] = true ; + for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { + if ( pCC->AddCurve( vpCCOpen[t]->Clone())) + vbAdded[t] = true ; + } + // aggiungo la curva agli edge 3d da restituire + vCC.emplace_back( Release( pCC)) ; + } + } } return true ; } diff --git a/SurfBezier.h b/SurfBezier.h index 20ae6b3..c24eaf7 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -137,7 +137,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate - bool GetEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; + bool GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 3f02119ef782f120859f4d67b015bfdff2486baa Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 20 Mar 2024 11:56:50 +0100 Subject: [PATCH 26/31] EgtGeomKernel : - corretta la funzione che restituisce gli edge 3D di una Bezier. --- SurfBezier.cpp | 93 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c97719b..99c853f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3039,9 +3039,9 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg // calcolo le autointersezioni a mano // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) - //double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - //Intervals inDomain ; inDomain.Set( dStart, dEnd) ; - DBLVECTOR vdU ; + double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; + Intervals inDomain ; inDomain.Set( dStart, dEnd) ; + //DBLVECTOR vdU ; BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; fill( vbErased.begin(), vbErased.end(), false) ; // scorro tutte le curve singole della compo @@ -3056,34 +3056,65 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; - if ( ( AreSamePointApprox( ptStartA, ptEndB) && AreSamePointApprox( ptEndA, ptStartB)) || - ( AreSamePointApprox( ptStartA, ptStartB) && AreSamePointApprox( ptEndA, ptEndB))) { + //if ( ( AreSamePointApprox( ptStartA, ptEndB) && AreSamePointApprox( ptEndA, ptStartB)) || + // ( AreSamePointApprox( ptStartA, ptStartB) && AreSamePointApprox( ptEndA, ptEndB))) { + // vbErased[k] = true ; + // //inDomain.Subtract(k, k+1) ; + // vbErased[w] = true ; + // //inDomain.Subtract(w, w+1) ; + // break ; + //} + IntCrvCrvInfo iccInfo ; + Vector3d vtDirSA ; pCrvA->GetStartDir( vtDirSA) ; + Vector3d vtDirSB ; pCrvB->GetStartDir( vtDirSB) ; + if ( AreSameOrOppositeVectorApprox( vtDirSA, Z_AX) || AreSameOrOppositeVectorApprox( vtDirSB, Z_AX)) { + Frame3d frOptimal ; + if ( (vtDirSA ^ vtDirSB).Len() > EPS_SMALL) + frOptimal.Set( ORIG, vtDirSA ^ vtDirSB, vtDirSA) ; + else + frOptimal.Set( ORIG, X_AX, vtDirSA) ; + PtrOwner pCrvNewA( pCrvA->Clone()) ; + pCrvNewA->ToLoc( frOptimal) ; + PtrOwner pCrvNewB( pCrvB->Clone()) ; + pCrvNewB->ToLoc( frOptimal) ; + IntersCurveCurve icc( *pCrvNewA, *pCrvNewB) ; + icc.GetIntCrvCrvInfo( 0, iccInfo) ; + } + else { + IntersCurveCurve icc( *pCrvA, *pCrvB) ; + icc.GetIntCrvCrvInfo( 0, iccInfo) ; + } + // se sono sovrapposte allora devo eliminare la parte comune + if ( iccInfo.bOverlap && ( AreSamePointApprox( ptStartA, ptEndB) || AreSamePointApprox( ptEndA, ptStartB) || + AreSamePointApprox( ptStartA, ptStartB) || AreSamePointApprox( ptEndA, ptEndB))) { + inDomain.Subtract( k + iccInfo.IciA[0].dU, k + iccInfo.IciA[1].dU) ; vbErased[k] = true ; - //inDomain.Subtract(k, k+1) ; + inDomain.Subtract( w + iccInfo.IciB[0].dU, w + iccInfo.IciB[1].dU) ; vbErased[w] = true ; - //inDomain.Subtract(w, w+1) ; break ; } } // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve // ci sono intersezioni sennò non posso accorgermene } - double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - if ( vbErased[0]) - vdU.emplace_back( dStart) ; - for ( int w = 1 ; w < int( vbErased.size()) ; ++w) { - if ( (vbErased[w] && ! vbErased[w - 1]) || (! vbErased[w] && vbErased[w - 1])) - vdU.emplace_back( w) ; - } - if ( vbErased.back()) - vdU.emplace_back( dEnd) ; + //double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; + //if ( vbErased[0]) + // vdU.emplace_back( dStart) ; + //for ( int w = 1 ; w < int( vbErased.size()) ; ++w) { + // if ( (vbErased[w] && ! vbErased[w - 1]) || (! vbErased[w] && vbErased[w - 1])) + // vdU.emplace_back( w) ; + //} + //if ( vbErased.back()) + // vdU.emplace_back( dEnd) ; + ICRVCOMPOPOVECTOR vpCCOpen ; //double dStartA, dEndA ; inDomain.GetFirst( dStartA, dEndA) ; //double dStartB, dEndB ; inDomain.GetLast( dStartB, dEndB) ; //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( dStartA + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( dEndB - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; - + ////questo pezzo in teoria non serve perché gli intervalli segnalati sono quelli da cancellare( con dU) + //// con Intervals, quello che resta è quello da tenere //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( vdU[0] + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( vdU.back() - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; //// scopro quali sono gli intervalli da tenere e quali da cancellare @@ -3094,16 +3125,26 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; //} - if ( vdU[0] > EPS_SMALL) - vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; - for ( int j = 0 ; j < int(vdU.size() / 2) - 1 ; ++j) - vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU[j*2 + 1], vdU[(j+ 1)*2]))) ; - - // se dopo l'ultimo dU ho ancora un pezzo di curva allora lo aggiungo - if ( dEnd - vdU.back() > EPS_SMALL) { - vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU.end()[-2], vdU.back()))) ; - } + //// ricostruisco la curva finale prendendo tutto tranne i tratti sovrapposti + // + //// con vdU + //if ( vdU[0] > EPS_SMALL) + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; + + //for ( int j = 0 ; j < int(vdU.size() / 2) - 1 ; ++j) + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU[j*2 + 1], vdU[(j+ 1)*2]))) ; + // + //// se dopo l'ultimo dU ho ancora un pezzo di curva allora lo aggiungo + //if ( dEnd - vdU.back() > EPS_SMALL) { + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU.end()[-2], vdU.back()))) ; + //} + + // con Intervals + double dStart0, dEnd0 ; inDomain.GetFirst( dStart0, dEnd0) ; + vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; + while ( inDomain.GetNext( dStart0, dEnd0)) + vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; // creo la chain a mano con le compo BOOLVECTOR vbAdded( vpCCOpen.size()) ; From 718f5ce716d4fa43b8f98bf9f8ffa0a12774d08e Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 20 Mar 2024 17:55:24 +0100 Subject: [PATCH 27/31] EgtGeomKernel : - ottimizzata la funzione per restituire gli edge 3D di una Bezier. MANCA: - debug - debug su closedV - debug closedU + ClosedV. --- SurfBezier.cpp | 737 ++++++++++++++++++++++++------------------------- 1 file changed, 363 insertions(+), 374 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 99c853f..709aec5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1475,26 +1475,27 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const tr.GetSplitLoops( vPl) ; //// per split nel parametrico - //for( int i = 0 ; i < int( vPl.size()); ++i) { - // m_vCCLoop2D.emplace_back(CreateBasicCurveComposite()) ; - // m_vCCLoop2D.back()->FromPolyLine(vPl[i]) ; - //} - for( int i = 0 ; i < int( vPl.size()); ++i) { m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; - PolyLine pl3D ; - Point3d pt ; vPl[i].GetFirstPoint( pt) ; - Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - int nCount = 0 ; - pl3D.AddUPoint( nCount, pt3D) ; - ++ nCount ; - while( vPl[i].GetNextPoint( pt)){ - GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - pl3D.AddUPoint( nCount, pt3D) ; - ++ nCount ; - } - m_vCCLoop.back()->FromPolyLine(pl3D) ; + m_vCCLoop.back()->FromPolyLine(vPl[i]) ; } + + //// Loop 3D + //for( int i = 0 ; i < int( vPl.size()); ++i) { + // m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; + // PolyLine pl3D ; + // Point3d pt ; vPl[i].GetFirstPoint( pt) ; + // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // int nCount = 0 ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // while( vPl[i].GetNextPoint( pt)){ + // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + // pl3D.AddUPoint( nCount, pt3D) ; + // ++ nCount ; + // } + // m_vCCLoop.back()->FromPolyLine(pl3D) ; + //} } return true ; @@ -2794,374 +2795,362 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg } // se la superficie è trimmata devo recuperare i loop dello spazio parametrico else { - //per split nel parametrico - // - //// devo ricostruire i bordi aperti in caso di superficie chiusa - //// costruisco gli edge - //ICurveLine* pCLU0( CreateCurveLine()) ; - //ICurveLine* pCLU1( CreateCurveLine()) ; - //ICurveLine* pCLV0( CreateCurveLine()) ; - //ICurveLine* pCLV1( CreateCurveLine()) ; - //if ( m_bClosedU ) { - // pCLU0->Set( Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0), ORIG) ; - // pCLU1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0)) ; - //} - //if ( m_bClosedV ) { - // pCLV0->Set( ORIG, Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0)) ; - // pCLV1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0), Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0)) ; - //} - //ICRVLINEPOVECTOR vEdge ; - //// li metto con l'ordine degli edge - //vEdge.emplace_back( pCLV1) ; - //vEdge.emplace_back( pCLU0) ; - //vEdge.emplace_back( pCLV0) ; - //vEdge.emplace_back( pCLU1) ; - //// costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e il loop esterno dello spazio parametrico - //// i 4 elementi fanno riferimento ai 4 edge. per ogni loop viene salvato il vettore delle intersezioni con tale edege - //vector> vmInters(4) ; - //unordered_map mAdded ; // salvo per ogni loop il gruppo di mLoopTo3D in cui è finito - //for ( int l = 0 ; l < int( m_vCCLoop2D.size()) ; ++ l) { - // // devo controllare se i loop si appoggiano a bordi chiusi - // // se ne ho più di uno che si appoggia allora devo vedere se trovo dei gruppi di loop che in realtà in 3d sono un edge unico, ma nel 2d risultano a cavallo dell'edge di chiusura - // PtrOwner pLoop( m_vCCLoop2D[l]->Clone()) ; - // //int nInters = 0 ; - // for ( int j = 0 ; j < 4 ; ++j) { - // // il primo è un loop di trim, il secondo è un edge dello spazio parametrico - // IntersCurveCurve icc( *pLoop, *vEdge[j]) ; - // ICCIVECTOR vICC ; - // for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i ) { - // IntCrvCrvInfo iccInfo ; - // icc.GetIntCrvCrvInfo( i, iccInfo) ; - // vICC.push_back( iccInfo) ; - // } - // if ( int(vICC.size()) > 0) { - // vmInters[j].insert(pair(l, vICC)) ; - // //++ nInters ; - // } - // } - // //if ( nInters > 0) - // // li aggiungo tutti, tanto devo costruire anche quelli che non fanno intersezioni con gli edge - // mAdded.insert( pair( l, -1)) ; - //} - //INTMATRIX mLoopTo3D ; - //// se ho delle intersezioni devo capire se ci sono loop che vanno abbinati e metterli nell'ordine giusto - //// per ogni intersezione controllo se ptStart o ptEnd corrispondono a quelli di qualche altro loop passando attraverso un edge chiuso - //if ( m_bClosedV) { - // // scorro i loop che fanno intersezioni con l'edge 0 ( V=1) - // for ( pair vInters0 : vmInters[0]) { - // // se il loop corrente è già stato aggiunto lo salto - // if ( mAdded[vInters0.first] != -1) - // continue ; - // INTVECTOR vPairing ; - // // scorro le intersezioni del loop - // for ( IntCrvCrvInfo inters0 : vInters0.second) { - // Point3d ptStart = inters0.IciA[0].ptI ; - // Point3d ptEnd = inters0.IciA[1].ptI ; - // // voglio che il punto start sia quello con la x minore - // if ( ptStart.x > ptEnd.x) - // swap( ptStart, ptEnd) ; - // // cerco sui loop (non ancora aggiunti) che fanno intersezioni con l'edge opposto ( edge 2, V=0) se ho una corrispondenza - // // se trovo un abbinamento con un loop che fa già parte di un gruppo mi salvo il numero del gruppo - // int nGroup = -1 ; - // for ( pair vInters2 : vmInters[2] ) { - // //if ( mAdded[vInters2.first] != -1) - // // continue ; ////// non è vero!!!!! dovrei semplicemente aggiungere il loop corrente al gruppo a cui appartiene questo loop/////////////////////////// - // - // - // // scorro le intersezioni di questo loop - // for ( IntCrvCrvInfo inters2 : vInters2.second) { - // // se lo start e end del loop corrente sono compresi tra lo start e l'end di un loop che fa intesezione sull'edge opposto ( o viceversa) allora devo accoppairli - // // il loop che fa intersezione sull'edge opposto potrebbe essere il corrente stesso - // Point3d ptStart2 = inters2.IciA[0].ptI ; - // Point3d ptEnd2 = inters2.IciA[1].ptI ; - // // come ptStart2 prendo quello con la x minore - // if ( ptStart2.x > ptEnd.x) - // swap( ptStart2, ptEnd2) ; - // if ( ((ptStart.x - 1 < ptStart2.x && ptStart2.x < ptEnd.x + 1) && (ptStart.x - 1 < ptEnd2.x && ptEnd2.x < ptEnd.x + 1)) || - // ((ptStart2.x - 1 < ptStart.x && ptStart.x < ptEnd2.x + 1) && (ptStart2.x - 1 < ptEnd.x && ptEnd.x < ptEnd2.x + 1))) { - // // aggiungo il loop alla lista degli accoppiati e salvo l'indice del gruppo a cui è stato aggiunto - // if ( mAdded[vInters2.first] == -1) { - // vPairing.push_back( vInters2.first) ; - // mAdded[vInters2.first] == int(mLoopTo3D.size()) ; - // } - // else if ( mAdded[vInters2.first] != -1){ - // nGroup = mAdded[vInters2.first] ; - // } - // // qui dovrei anche decidere come trimmare le curve e quante curve 3D devono uscire da questo loop che fa intersezione con gli edge - // asasdasa + //// con split nel parametrico//////////////////////////////////////////////////////// + // devo ricostruire i bordi aperti in caso di superficie chiusa + // costruisco gli edge + ICurveLine* pCLU0( CreateCurveLine()) ; + ICurveLine* pCLU1( CreateCurveLine()) ; + ICurveLine* pCLV0( CreateCurveLine()) ; + ICurveLine* pCLV1( CreateCurveLine()) ; + if ( m_bClosedU ) { + pCLU0->Set( Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0), ORIG) ; + pCLU1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0)) ; + } + if ( m_bClosedV ) { + pCLV0->Set( ORIG, Point3d( m_nSpanU * SBZ_TREG_COEFF, 0, 0)) ; + pCLV1->Set( Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF, 0), Point3d( 0, m_nSpanV * SBZ_TREG_COEFF, 0)) ; + } + ICRVLINEPOVECTOR vEdge ; + // li metto con l'ordine degli edge + vEdge.emplace_back( pCLV1) ; + vEdge.emplace_back( pCLU0) ; + vEdge.emplace_back( pCLV0) ; + vEdge.emplace_back( pCLU1) ; + // costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e il loop esterno dello spazio parametrico + // i 4 elementi fanno riferimento ai 4 edge. per ogni loop viene salvato il vettore delle intersezioni con tale edege + vector> vmInters(4) ; + // comincio anche a creare il vettore di vettori associati ad ogni loop che fa almeno un'intersezione con un edge. + // in ogni vettore verranno salvati l'indice del loop all'interno del vettore dei loop e gli indici di tutti i loop che deriveranno da sue divisioni in più curve + unordered_map mSplitLoop ; + int nOriginalLoops = int( m_vCCLoop.size()) ; + for ( int l = 0 ; l < nOriginalLoops ; ++ l) { + bool bInters = false ; + // devo controllare se i loop si appoggiano a bordi chiusi + // se ne ho più di uno che si appoggia allora devo vedere se trovo dei gruppi di loop che in realtà in 3d sono un edge unico, ma nel 2d risultano a cavallo dell'edge di chiusura + PtrOwner pLoop( m_vCCLoop[l]->Clone()) ; + for ( int j = 0 ; j < 4 ; ++j) { + // il primo è un loop di trim, il secondo è un edge dello spazio parametrico + IntersCurveCurve icc( *pLoop, *vEdge[j]) ; + ICCIVECTOR vICC ; + for ( int i = 0 ; i < int(icc.GetIntersCount()) ; ++i ) { + IntCrvCrvInfo iccInfo ; + icc.GetIntCrvCrvInfo( i, iccInfo) ; + vICC.push_back( iccInfo) ; + } + if ( int(vICC.size()) > 0) { + vmInters[j].insert(pair(l, vICC)) ; + bInters = true ; + } + } + if ( bInters) + mSplitLoop.insert( pair( l, INTVECTOR({l}))) ; + } - // break ; - // } - // } - // } - // // aggiungo il loop corrente - // vPairing.push_back( vInters0.first) ; - // if ( nGroup == -1 ) { - // mAdded[vInters0.first] == int( mLoopTo3D.size()) ; - // if ( int( mLoopTo3D.size()) > 0 && int(mLoopTo3D.back().size()) > 0) - // mLoopTo3D.emplace_back(vPairing) ; - // else - // mLoopTo3D.back() = vPairing ; - // } - // else { - // mAdded[vInters0.first] = nGroup ; - // mLoopTo3D[nGroup].emplace_back( vPairing) ; - // } - // } - // } - // // qua devo ciclare di nuovo sui loop che fanno intersezione con l'edge 2 per verificare se li ho aggiunti tutti - //} - //if ( m_bClosedU ) { - // for ( int i = 0 ; i < int( vmInters[1].size()) ; ++i ) { - // Point3d ptStart, ptEnd ; - // } - //} + if ( m_bClosedV) { + // scorro i loop che fanno intersezioni con l'edge 0 ( V=1) e le riporto sull'edge opposto + for ( pair vInters0 : vmInters[0]) { + // scorro le intersezioni del loop + for ( IntCrvCrvInfo inters0 : vInters0.second) { + Point3d ptStart0 = inters0.IciA[0].ptI ; + Point3d ptEnd0 = inters0.IciA[1].ptI ; + // porto i punti sull'edge opposto + ptStart0.y = 0 ; + ptEnd0.y = 0 ; + // scorro le intersezioni sull'edge opposto e quando trovo un loop che tra le sue intersezioni contiene uno dei punti che ho appena portato + // su qusto edge allora cancello la parte comune + for ( pair vInters2 : vmInters[2] ) { + // scorro le intersezioni di questo loop + for ( IntCrvCrvInfo inters2 : vInters2.second) { + // se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora + // devo cancellare la parte comune + Point3d ptStart2 = inters2.IciA[0].ptI ; + Point3d ptEnd2 = inters2.IciA[1].ptI ; + // come ptStart2 prendo quello con la x minore + if ( ptStart2.x > ptEnd2.x) + swap( ptStart2, ptEnd2) ; + if ( (( ptStart0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptEnd0.x + EPS_SMALL) && ( ptStart0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptEnd0.x + EPS_SMALL)) || + (( ptStart2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptEnd2.x + EPS_SMALL) && ( ptStart2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptEnd2.x + EPS_SMALL))) { + PtrOwner pCL( CreateBasicCurveLine()) ; + pCL->Set( ptStart0, ptEnd0) ; + // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale + for ( int w = 0 ; w < int( mSplitLoop[vInters2.first].size()) ; ++w) { + int nIndex2 = mSplitLoop[vInters2.first][w] ; + IntersCurveCurve icc( *m_vCCLoop[nIndex2], *pCL) ; + IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + if ( ! iccInfo.bOverlap) + continue ; + // se parto da una curva chiusa semplicemente tolgo un pezzo + if ( m_vCCLoop[nIndex2]->IsClosed()) { + ICurveComposite* pCC2( GetCurveComposite( m_vCCLoop[nIndex2]->CopyParamRange( iccInfo.IciA[1].dU, iccInfo.IciA[0].dU))) ; + m_vCCLoop[nIndex2].Set( pCC2) ; + } + else { + // se la curva era già aperta allora otterrò due curve separate + ICurveComposite* pCC2a( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; + pCC2a->TrimEndAtParam( iccInfo.IciA[1].dU) ; + ICurveComposite* pCC2b( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; + pCC2b->TrimStartAtParam( iccInfo.IciA[0].dU) ; + m_vCCLoop[nIndex2].Set( pCC2a) ; + m_vCCLoop.emplace_back( pCC2b) ; + mSplitLoop[vInters2.first].push_back( m_vCCLoop.size() - 1) ; + } + + // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza + Point3d ptOverlapS = iccInfo.IciB[0].ptI ; + Point3d ptOverlapE = iccInfo.IciB[1].ptI ; + ptOverlapS.y = m_nSpanV * SBZ_TREG_COEFF ; + ptOverlapE.y = m_nSpanV * SBZ_TREG_COEFF ; + double dStart0, dEnd0 ; + // scorro tutte le curve in cui è stato splittato il loop iniziale + for ( int j = 0 ; int( mSplitLoop[vInters0.first].size()) ; ++j ) { + int nIndex0 = mSplitLoop[vInters0.first][j] ; + if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) + continue ; + // se parto da una curva chiusa semplicemente tolgo un pezzo + if ( m_vCCLoop[nIndex0]->IsClosed()) { + ICurveComposite* pCC0( GetCurveComposite( m_vCCLoop[nIndex0]->CopyParamRange( dEnd0, dStart0))) ; + m_vCCLoop[nIndex0].Set( pCC0) ; + } + else { + // se la curva era già aperta allora otterrò due curve separate + ICurveComposite* pCC0a( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; + pCC0a->TrimEndAtParam( dStart0) ; + ICurveComposite* pCC0b( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; + pCC0b->TrimStartAtParam( dEnd0) ; + m_vCCLoop[nIndex0].Set( pCC0a) ; + m_vCCLoop.emplace_back( pCC0b) ; + mSplitLoop[vInters0.first].push_back( m_vCCLoop.size() - 1) ; + } + break ; + } + break ; + } + break ; + } + } + } + } + } + } - //// qui portei estrarre una funzione che proietta curve dal parametrico al 3D - //// scorro i gruppi di loop 2D formati da loop che partecipano alla formazione dello stesso loop nel 3D - //for( int i = 0 ; i < int( mLoopTo3D.size()); ++i) { - // vCC.emplace_back(CreateBasicCurveComposite()) ; - // PolyLine pl3D ; - // // scorro i loop 2D all'interno del gruppo - // for ( int j = 0 ; j < int( mLoopTo3D[i].size()) ; ++j) { - // // la composita è una spezzata composta da linee, quindi la ricostruisco come polyline in 3D - // Point3d pt ; m_vCCLoop2D[mLoopTo3D[i][j]]->GetStartPoint( pt) ; - // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // int nCount = 0 ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // // scorro le curve singole della composita - // for ( int k = 0 ; k < m_vCCLoop2D[mLoopTo3D[i][j]]->GetCurveCount() ; ++k){ - // // recupero l'end point della curva e lo porto in 3D - // m_vCCLoop2D[mLoopTo3D[i][j]]->GetCurve( k)->GetEndPoint( pt) ; - // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // } - // } - // vCC.back()->FromPolyLine(pl3D) ; - //} + if ( m_bClosedU) { + // scorro i loop che fanno intersezioni con l'edge 1 ( U=0) e le riporto sull'edge opposto + for ( pair vInters1 : vmInters[1]) { + // scorro le intersezioni del loop + for ( IntCrvCrvInfo inters1 : vInters1.second) { + Point3d ptStart1 = inters1.IciA[0].ptI ; + Point3d ptEnd1 = inters1.IciA[1].ptI ; + // porto i punti sull'edge opposto + ptStart1.x = m_nSpanU * SBZ_TREG_COEFF ; + ptEnd1.x = m_nSpanU * SBZ_TREG_COEFF ; + // scorro le intersezioni sull'edge opposto e quando trovo un loop che tra le sue intersezioni contiene uno dei punti che ho appena portato + // su qusto edge allora cancello la parte comune + for ( pair vInters3 : vmInters[3] ) { + // scorro le intersezioni di questo loop + for ( IntCrvCrvInfo inters3 : vInters3.second) { + // se lo start o end del loop corrente è compreso tra lo start e l'end di un loop che fa intesezione sull'edge opposto allora + // devo cancellare la parte comune + Point3d ptStart3 = inters3.IciA[0].ptI ; + Point3d ptEnd3 = inters3.IciA[1].ptI ; + // come ptStart3 prendo quello con la y maggiore + if ( ptStart3.y < ptEnd3.y) + swap( ptStart3, ptEnd3) ; + if ( (( ptEnd1.y - EPS_SMALL< ptStart3.y && ptStart3.y < ptStart1.y + EPS_SMALL) && ( ptEnd1.y - EPS_SMALL < ptEnd3.y && ptEnd3.y < ptStart1.y + EPS_SMALL)) || + (( ptEnd3.y - EPS_SMALL < ptStart1.y && ptStart1.y < ptStart3.y + EPS_SMALL) && ( ptEnd3.y - EPS_SMALL < ptEnd1.y && ptEnd1.y < ptStart3.y + EPS_SMALL))) { + PtrOwner pCL( CreateBasicCurveLine()) ; + pCL->Set( ptStart1, ptEnd1) ; + // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale + for ( int w = 0 ; w < int( mSplitLoop[vInters3.first].size()) ; ++w) { + int nIndex3 = mSplitLoop[vInters3.first][w] ; + IntersCurveCurve icc( *m_vCCLoop[nIndex3], *pCL) ; + IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + if ( ! iccInfo.bOverlap) + continue ; + // se parto da una curva chiusa semplicemente tolgo un pezzo + if ( m_vCCLoop[nIndex3]->IsClosed()) { + ICurveComposite* pCC3( GetCurveComposite( m_vCCLoop[nIndex3]->CopyParamRange( iccInfo.IciA[1].dU, iccInfo.IciA[0].dU))) ; + m_vCCLoop[nIndex3].Set( pCC3) ; + } + else { + // se la curva era già aperta allora otterrò due curve separate + ICurveComposite* pCC3a( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; + pCC3a->TrimEndAtParam( iccInfo.IciA[0].dU) ; + ICurveComposite* pCC3b( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; + pCC3b->TrimStartAtParam( iccInfo.IciA[1].dU) ; + m_vCCLoop[nIndex3].Set( pCC3a) ; + m_vCCLoop.emplace_back( pCC3b) ; + mSplitLoop[vInters3.first].push_back( m_vCCLoop.size() - 1) ; + } + + // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza + Point3d ptOverlapS = iccInfo.IciB[0].ptI ; + Point3d ptOverlapE = iccInfo.IciB[1].ptI ; + ptOverlapS.x = 0 ; + ptOverlapE.x = 0 ; + double dStart1, dEnd1 ; + // scorro tutte le curve in cui è stato splittato il loop iniziale + for ( int j = 0 ; int( mSplitLoop[vInters1.first].size()) ; ++j ) { + int nIndex1 = mSplitLoop[vInters1.first][j] ; + if ( ! m_vCCLoop[nIndex1]->GetParamAtPoint( ptOverlapS, dStart1) || ! m_vCCLoop[nIndex1]->GetParamAtPoint( ptOverlapE, dEnd1)) + continue ; + // se parto da una curva chiusa semplicemente tolgo un pezzo + if ( m_vCCLoop[nIndex1]->IsClosed()) { + ICurveComposite* pCC1( GetCurveComposite( m_vCCLoop[nIndex1]->CopyParamRange( dStart1, dEnd1))) ; + m_vCCLoop[nIndex1].Set( pCC1) ; + } + else { + // se la curva era già aperta allora otterrò due curve separate + ICurveComposite* pCC1a( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; + pCC1a->TrimEndAtParam( dEnd1) ; + ICurveComposite* pCC1b( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; + pCC1b->TrimStartAtParam( dStart1) ; + m_vCCLoop[nIndex1].Set( pCC1a) ; + m_vCCLoop.emplace_back( pCC1b) ; + mSplitLoop[vInters1.first].push_back( m_vCCLoop.size() - 1) ; + } + break ; + } + break ; + } + break ; + } + } + } + } + } + } + + // qui portei estrarre una funzione che proietta curve dal parametrico al 3D + // scorro i gruppi di loop 2D formati da loop che partecipano alla formazione dello stesso loop nel 3D + ICRVCOMPOPOVECTOR vpCCOpen ; + for( int i = 0 ; i < int( m_vCCLoop.size()); ++i) { + vpCCOpen.emplace_back(CreateBasicCurveComposite()) ; + PolyLine pl3D ; + // la composita è una spezzata composta da linee, quindi la ricostruisco come polyline in 3D + Point3d pt ; m_vCCLoop[i]->GetStartPoint( pt) ; + Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + int nCount = 0 ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + // scorro le curve singole della composita + for ( int k = 0 ; k < m_vCCLoop[i]->GetCurveCount() ; ++k){ + // recupero l'end point della curva e lo porto in 3D + m_vCCLoop[i]->GetCurve( k)->GetEndPoint( pt) ; + GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + pl3D.AddUPoint( nCount, pt3D) ; + ++ nCount ; + } + vpCCOpen.back()->FromPolyLine(pl3D) ; + } + // creo la chain a mano con le compo + BOOLVECTOR vbAdded( vpCCOpen.size()) ; + fill( vbAdded.begin(), vbAdded.end(), false) ; + for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { + if ( vbAdded[k]) + continue ; + PtrOwner pCC( vpCCOpen[k]->Clone()) ; + vbAdded[k] = true ; + for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { + if ( pCC->AddCurve( vpCCOpen[t]->Clone())) + vbAdded[t] = true ; + } + // aggiungo la curva agli edge 3d da restituire + vCC.emplace_back( Release( pCC)) ; + } + + //// con split nel parametrico//////////////////////////////////////////////////////// //// se volessi restiturie tutto passo i loop del parametrico portati in 3D //for ( int i = 0 ; i < int(m_vCCLoop2D.size()) ; ++i) // vCC.emplace_back( m_vCCLoop2D[i]->Clone()) ; + //// con le inters in 3D/////////////////////////////////////////////////// + //for ( int i = 0 ; i < int( m_vCCLoop.size()) ; ++i) { + // //// debug + // ////disegno le curve nel nuovo riferimento + // //vCC.emplace_back( Release(m_vCCLoop[i])) ; + // // continue ; + // ////debug - //// se il lato di chiusura è orientato come Z allora cambio sistema di riferimento per trovare le intersezioni XY - //bool bMod = false ; - //Frame3d frRot ; - //if ( m_bClosedU) { - // Point3d ptP00 ; GetPointD1D2( 0 , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; - // Point3d ptP01 ; GetPointD1D2( 0 , m_nSpanV * SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP01) ; - // Point3d ptP0001 ; GetPointD1D2( 0 , m_nSpanV * SBZ_TREG_COEFF / 2, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP0001) ; - // Vector3d vtDir01 = ptP01 - ptP00 ; - // Vector3d vtDir0001 = ptP0001 - ptP00 ; - // if ( ! vtDir01.Normalize() || ! vtDir0001.Normalize()) - // return false ; - // if ( AreSameVectorApprox( vtDir01, vtDir0001) && AreSameOrOppositeVectorApprox( vtDir01, Z_AX)) { - // // il lato di chiusura è parallelo all'asse Z, quindi prima di calcolare le autointersezioni devo cambiare sistema di riferimento - // bMod = true ; - // frRot.Set( ORIG, X_AX /*+ Y_AX*/) ; - // //for ( int j = 0 ; j < int(m_vCCLoop.size()) ; ++j ) - // // m_vCCLoop[j]->ToLoc( frRot) ; + // // calcolo le autointersezioni a mano + // // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) + // double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; + // Intervals inDomain ; inDomain.Set( dStart, dEnd) ; + // //DBLVECTOR vdU ; + // BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; + // fill( vbErased.begin(), vbErased.end(), false) ; + // // scorro tutte le curve singole della compo + // for ( int k = 0 ; k < int( m_vCCLoop[i]->GetCurveCount()); ++k) { + // const ICurve* pCrvA = m_vCCLoop[i]->GetCurve( k) ; + // if ( vbErased[k]) + // continue ; + // Point3d ptStartA ; pCrvA->GetStartPoint( ptStartA) ; + // Point3d ptEndA ; pCrvA->GetEndPoint( ptEndA) ; + // // devo confrontarla con tutte le successive + // for ( int w = k + 1 ; w < int(m_vCCLoop[i]->GetCurveCount()); ++w ) { + // const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; + // Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; + // Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; + // IntCrvCrvInfo iccInfo ; + // Vector3d vtDirSA ; pCrvA->GetStartDir( vtDirSA) ; + // Vector3d vtDirSB ; pCrvB->GetStartDir( vtDirSB) ; + // if ( AreSameOrOppositeVectorApprox( vtDirSA, Z_AX) || AreSameOrOppositeVectorApprox( vtDirSB, Z_AX)) { + // Frame3d frOptimal ; + // if ( (vtDirSA ^ vtDirSB).Len() > EPS_SMALL) + // frOptimal.Set( ORIG, vtDirSA ^ vtDirSB, vtDirSA) ; + // else + // frOptimal.Set( ORIG, X_AX, vtDirSA) ; + // PtrOwner pCrvNewA( pCrvA->Clone()) ; + // pCrvNewA->ToLoc( frOptimal) ; + // PtrOwner pCrvNewB( pCrvB->Clone()) ; + // pCrvNewB->ToLoc( frOptimal) ; + // IntersCurveCurve icc( *pCrvNewA, *pCrvNewB) ; + // icc.GetIntCrvCrvInfo( 0, iccInfo) ; + // } + // else { + // IntersCurveCurve icc( *pCrvA, *pCrvB) ; + // icc.GetIntCrvCrvInfo( 0, iccInfo) ; + // } + // // se sono sovrapposte allora devo eliminare la parte comune + // if ( iccInfo.bOverlap && ( AreSamePointApprox( ptStartA, ptEndB) || AreSamePointApprox( ptEndA, ptStartB) || + // AreSamePointApprox( ptStartA, ptStartB) || AreSamePointApprox( ptEndA, ptEndB))) { + // inDomain.Subtract( k + iccInfo.IciA[0].dU, k + iccInfo.IciA[1].dU) ; + // vbErased[k] = true ; + // inDomain.Subtract( w + iccInfo.IciB[0].dU, w + iccInfo.IciB[1].dU) ; + // vbErased[w] = true ; + // break ; + // } + // } + // // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve + // // ci sono intersezioni sennò non posso accorgermene + // } + + // ICRVCOMPOPOVECTOR vpCCOpen ; + + // // con Intervals + // double dStart0, dEnd0 ; inDomain.GetFirst( dStart0, dEnd0) ; + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; + // while ( inDomain.GetNext( dStart0, dEnd0)) + // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; + // + // // creo la chain a mano con le compo + // BOOLVECTOR vbAdded( vpCCOpen.size()) ; + // fill( vbAdded.begin(), vbAdded.end(), false) ; + // for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { + // if ( vbAdded[k]) + // continue ; + // PtrOwner pCC( vpCCOpen[k]->Clone()) ; + // vbAdded[k] = true ; + // for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { + // if ( pCC->AddCurve( vpCCOpen[t]->Clone())) + // vbAdded[t] = true ; + // } + // // aggiungo la curva agli edge 3d da restituire + // vCC.emplace_back( Release( pCC)) ; // } //} - //if ( m_bClosedV) { - // Point3d ptP00 ; GetPointD1D2( 0 , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP00) ; - // Point3d ptP10 ; GetPointD1D2( m_nSpanU * SBZ_TREG_COEFF , 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP10) ; - // Point3d ptP0010 ; GetPointD1D2( m_nSpanU * SBZ_TREG_COEFF / 2, 0, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptP0010) ; - // Vector3d vtDir10 = ptP10 - ptP00 ; - // Vector3d vtDir0010 = ptP0010 - ptP00 ; - // if ( ! vtDir10.Normalize() || ! vtDir0010.Normalize()) - // return false ; - // if ( AreSameVectorApprox( vtDir10, vtDir0010) && AreSameOrOppositeVectorApprox( vtDir10, Z_AX)) { - // // il lato di chiusura è parallelo all'asse Z, quindi prima di calcolare le autointersezioni devo cambiare sistema di riferimento - // bMod = true ; - // frRot.Set( ORIG, X_AX + Y_AX) ; - // //for ( int j = 0 ; j < int(m_vCCLoop.size()) ; ++j ) - // // m_vCCLoop[j]->ToLoc( frRot) ; - // } - //} - - - // con le inters in 3D - for ( int i = 0 ; i < int( m_vCCLoop.size()) ; ++i) { - //if ( bMod) - // m_vCCLoop[i]->ToLoc( frRot) ; - - //// debug - ////disegno le curve nel nuovo riferimento - //vCC.emplace_back( Release(m_vCCLoop[i])) ; - // continue ; - ////debug - - // le autotintersezioni in 3D fanno casino!!!!!!!!! - //// calcolo le autointersezioni per capire quali tratti sono sul lato di chiusura - //SelfIntersCurve sic( *m_vCCLoop[i]) ; - //PNTVECTOR vPnt ; - //DBLVECTOR vdU ; - //IntCrvCrvInfo iccInfo0 ; - //for ( int j = 0 ; sic.GetIntCrvCrvInfo( j, iccInfo0) ; ++ j) { - // if ( ! iccInfo0.bOverlap) { - // Point3d ptA = iccInfo0.IciA[0].ptI ; - // Point3d ptB = iccInfo0.IciB[0].ptI ; - // if ( AreSamePointApprox( ptA, ptB)) { - // vPnt.push_back( ptA) ; - // vPnt.push_back( ptB) ; - // vdU.push_back(iccInfo0.IciA[0].dU) ; - // vdU.push_back(iccInfo0.IciB[0].dU) ; - // } - // } - // else { - // Point3d ptA0 = iccInfo0.IciA[0].ptI ; - // Point3d ptB0 = iccInfo0.IciB[0].ptI ; - // if ( AreSamePointApprox( ptA0, ptB0) ) { - // vPnt.push_back( ptA0) ; - // vPnt.push_back( ptB0) ; - // vdU.push_back(iccInfo0.IciA[0].dU) ; - // vdU.push_back(iccInfo0.IciB[0].dU) ; - // } - // Point3d ptA1 = iccInfo0.IciA[1].ptI ; - // Point3d ptB1 = iccInfo0.IciB[1].ptI ; - // if ( AreSamePointApprox( ptA1, ptB1) ) { - // vPnt.push_back( ptA1) ; - // vPnt.push_back( ptB1) ; - // vdU.push_back(iccInfo0.IciA[1].dU) ; - // vdU.push_back(iccInfo0.IciB[1].dU) ; - // } - // } - //} - //sort( vdU.begin(), vdU.end()) ; - //if ( bMod) - // m_vCCLoop[i]->ToGlob( frRot) ; - - - // calcolo le autointersezioni a mano - // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) - double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - Intervals inDomain ; inDomain.Set( dStart, dEnd) ; - //DBLVECTOR vdU ; - BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; - fill( vbErased.begin(), vbErased.end(), false) ; - // scorro tutte le curve singole della compo - for ( int k = 0 ; k < int( m_vCCLoop[i]->GetCurveCount()); ++k) { - const ICurve* pCrvA = m_vCCLoop[i]->GetCurve( k) ; - if ( vbErased[k]) - continue ; - Point3d ptStartA ; pCrvA->GetStartPoint( ptStartA) ; - Point3d ptEndA ; pCrvA->GetEndPoint( ptEndA) ; - // devo confrontarla con tutte le successive - for ( int w = k + 1 ; w < int(m_vCCLoop[i]->GetCurveCount()); ++w ) { - const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; - Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; - Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; - //if ( ( AreSamePointApprox( ptStartA, ptEndB) && AreSamePointApprox( ptEndA, ptStartB)) || - // ( AreSamePointApprox( ptStartA, ptStartB) && AreSamePointApprox( ptEndA, ptEndB))) { - // vbErased[k] = true ; - // //inDomain.Subtract(k, k+1) ; - // vbErased[w] = true ; - // //inDomain.Subtract(w, w+1) ; - // break ; - //} - IntCrvCrvInfo iccInfo ; - Vector3d vtDirSA ; pCrvA->GetStartDir( vtDirSA) ; - Vector3d vtDirSB ; pCrvB->GetStartDir( vtDirSB) ; - if ( AreSameOrOppositeVectorApprox( vtDirSA, Z_AX) || AreSameOrOppositeVectorApprox( vtDirSB, Z_AX)) { - Frame3d frOptimal ; - if ( (vtDirSA ^ vtDirSB).Len() > EPS_SMALL) - frOptimal.Set( ORIG, vtDirSA ^ vtDirSB, vtDirSA) ; - else - frOptimal.Set( ORIG, X_AX, vtDirSA) ; - PtrOwner pCrvNewA( pCrvA->Clone()) ; - pCrvNewA->ToLoc( frOptimal) ; - PtrOwner pCrvNewB( pCrvB->Clone()) ; - pCrvNewB->ToLoc( frOptimal) ; - IntersCurveCurve icc( *pCrvNewA, *pCrvNewB) ; - icc.GetIntCrvCrvInfo( 0, iccInfo) ; - } - else { - IntersCurveCurve icc( *pCrvA, *pCrvB) ; - icc.GetIntCrvCrvInfo( 0, iccInfo) ; - } - // se sono sovrapposte allora devo eliminare la parte comune - if ( iccInfo.bOverlap && ( AreSamePointApprox( ptStartA, ptEndB) || AreSamePointApprox( ptEndA, ptStartB) || - AreSamePointApprox( ptStartA, ptStartB) || AreSamePointApprox( ptEndA, ptEndB))) { - inDomain.Subtract( k + iccInfo.IciA[0].dU, k + iccInfo.IciA[1].dU) ; - vbErased[k] = true ; - inDomain.Subtract( w + iccInfo.IciB[0].dU, w + iccInfo.IciB[1].dU) ; - vbErased[w] = true ; - break ; - } - } - // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve - // ci sono intersezioni sennò non posso accorgermene - } - //double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - //if ( vbErased[0]) - // vdU.emplace_back( dStart) ; - //for ( int w = 1 ; w < int( vbErased.size()) ; ++w) { - // if ( (vbErased[w] && ! vbErased[w - 1]) || (! vbErased[w] && vbErased[w - 1])) - // vdU.emplace_back( w) ; - //} - //if ( vbErased.back()) - // vdU.emplace_back( dEnd) ; - - ICRVCOMPOPOVECTOR vpCCOpen ; - //double dStartA, dEndA ; inDomain.GetFirst( dStartA, dEndA) ; - //double dStartB, dEndB ; inDomain.GetLast( dStartB, dEndB) ; - //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( dStartA + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; - //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( dEndB - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; - - ////questo pezzo in teoria non serve perché gli intervalli segnalati sono quelli da cancellare( con dU) - //// con Intervals, quello che resta è quello da tenere - //Point3d ptTest0 ; m_vCCLoop[i]->GetPointD1D2( vdU[0] + EPS_SMALL, ICurve::FROM_MINUS, ptTest0) ; - //Point3d ptTest1 ; m_vCCLoop[i]->GetPointD1D2( vdU.back() - EPS_SMALL, ICurve::FROM_MINUS, ptTest1) ; - //// scopro quali sono gli intervalli da tenere e quali da cancellare - //int nFirst = 0 ; - //if ( AreSamePointApprox( ptTest0, ptTest1)) { - // nFirst = 1 ; - // if ( vdU[0] > EPS_SMALL ) - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; - //} - - - //// ricostruisco la curva finale prendendo tutto tranne i tratti sovrapposti - // - //// con vdU - //if ( vdU[0] > EPS_SMALL) - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( 0, vdU[0]))) ; - - //for ( int j = 0 ; j < int(vdU.size() / 2) - 1 ; ++j) - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU[j*2 + 1], vdU[(j+ 1)*2]))) ; - // - //// se dopo l'ultimo dU ho ancora un pezzo di curva allora lo aggiungo - //if ( dEnd - vdU.back() > EPS_SMALL) { - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( vdU.end()[-2], vdU.back()))) ; - //} - - // con Intervals - double dStart0, dEnd0 ; inDomain.GetFirst( dStart0, dEnd0) ; - vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - while ( inDomain.GetNext( dStart0, dEnd0)) - vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - - // creo la chain a mano con le compo - BOOLVECTOR vbAdded( vpCCOpen.size()) ; - fill( vbAdded.begin(), vbAdded.end(), false) ; - for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { - if ( vbAdded[k]) - continue ; - PtrOwner pCC( vpCCOpen[k]->Clone()) ; - vbAdded[k] = true ; - for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { - if ( pCC->AddCurve( vpCCOpen[t]->Clone())) - vbAdded[t] = true ; - } - // aggiungo la curva agli edge 3d da restituire - vCC.emplace_back( Release( pCC)) ; - } - } + //// con le inters in 3D/////////////////////////////////////////////////// } return true ; } From 535011072d0c704a728e4edaca2a01abeedc037d Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 21 Mar 2024 12:57:59 +0100 Subject: [PATCH 28/31] EgtGeomKernel : - corretta e ultimata la funzione edges3D per Bezier. #11 --- SurfBezier.cpp | 224 +++++++++++++++++-------------------------------- Tree.cpp | 5 +- 2 files changed, 81 insertions(+), 148 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 709aec5..17433aa 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1447,7 +1447,7 @@ SurfBezier::GetCurveOnVApproxLen( double dU) const bool SurfBezier::UpdateEdgesFromTree( Tree& tr) const { - POLYLINEMATRIX mPlEdges(4) ; + POLYLINEMATRIX mPlEdges ; tr.GetEdges3D( mPlEdges) ; for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { @@ -1464,7 +1464,9 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const ++ nCount ; } if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)) { - Point3d ptStart ; pl3D.GetFirstPoint( ptStart) ; + Point3d ptStart ; + if ( ! pl3D.GetFirstPoint( ptStart)) + continue ; m_mCCEdge[i].back()->FromPoint( ptStart) ; } } @@ -1474,28 +1476,11 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const POLYLINEVECTOR vPl ; tr.GetSplitLoops( vPl) ; - //// per split nel parametrico + // recupero i loop nel parametrico for( int i = 0 ; i < int( vPl.size()); ++i) { m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; m_vCCLoop.back()->FromPolyLine(vPl[i]) ; } - - //// Loop 3D - //for( int i = 0 ; i < int( vPl.size()); ++i) { - // m_vCCLoop.emplace_back(CreateBasicCurveComposite()) ; - // PolyLine pl3D ; - // Point3d pt ; vPl[i].GetFirstPoint( pt) ; - // Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // int nCount = 0 ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // while( vPl[i].GetNextPoint( pt)){ - // GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - // pl3D.AddUPoint( nCount, pt3D) ; - // ++ nCount ; - // } - // m_vCCLoop.back()->FromPolyLine(pl3D) ; - //} } return true ; @@ -2795,7 +2780,6 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg } // se la superficie è trimmata devo recuperare i loop dello spazio parametrico else { - //// con split nel parametrico//////////////////////////////////////////////////////// // devo ricostruire i bordi aperti in caso di superficie chiusa // costruisco gli edge ICurveLine* pCLU0( CreateCurveLine()) ; @@ -2865,11 +2849,11 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg // devo cancellare la parte comune Point3d ptStart2 = inters2.IciA[0].ptI ; Point3d ptEnd2 = inters2.IciA[1].ptI ; - // come ptStart2 prendo quello con la x minore - if ( ptStart2.x > ptEnd2.x) + // come ptStart2 prendo quello con la x maggiore + if ( ptStart2.x < ptEnd2.x) swap( ptStart2, ptEnd2) ; - if ( (( ptStart0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptEnd0.x + EPS_SMALL) && ( ptStart0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptEnd0.x + EPS_SMALL)) || - (( ptStart2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptEnd2.x + EPS_SMALL) && ( ptStart2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptEnd2.x + EPS_SMALL))) { + if ( (( ptEnd0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptStart0.x + EPS_SMALL) && ( ptEnd0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptStart0.x + EPS_SMALL)) || + (( ptEnd2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptStart2.x + EPS_SMALL) && ( ptEnd2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptStart2.x + EPS_SMALL))) { PtrOwner pCL( CreateBasicCurveLine()) ; pCL->Set( ptStart0, ptEnd0) ; // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale @@ -2877,6 +2861,11 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg int nIndex2 = mSplitLoop[vInters2.first][w] ; IntersCurveCurve icc( *m_vCCLoop[nIndex2], *pCL) ; IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + for ( int k = 0 ; k < icc.GetIntersCount() ; ++k) { + icc.GetIntCrvCrvInfo( k, iccInfo) ; + if ( iccInfo.bOverlap) + break ; + } if ( ! iccInfo.bOverlap) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo @@ -2887,12 +2876,18 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC2a( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; - pCC2a->TrimEndAtParam( iccInfo.IciA[1].dU) ; + bool bDoneA = pCC2a->TrimEndAtParam( iccInfo.IciA[0].dU) ; ICurveComposite* pCC2b( GetCurveComposite( m_vCCLoop[nIndex2]->Clone())) ; - pCC2b->TrimStartAtParam( iccInfo.IciA[0].dU) ; - m_vCCLoop[nIndex2].Set( pCC2a) ; - m_vCCLoop.emplace_back( pCC2b) ; - mSplitLoop[vInters2.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC2b->TrimStartAtParam( iccInfo.IciA[1].dU) ; + if ( bDoneA) { + m_vCCLoop[nIndex2].Set( pCC2a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC2b) ; + mSplitLoop[vInters2.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex2].Set( pCC2b) ; } // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza @@ -2902,30 +2897,35 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg ptOverlapE.y = m_nSpanV * SBZ_TREG_COEFF ; double dStart0, dEnd0 ; // scorro tutte le curve in cui è stato splittato il loop iniziale - for ( int j = 0 ; int( mSplitLoop[vInters0.first].size()) ; ++j ) { + for ( int j = 0 ; j < int( mSplitLoop[vInters0.first].size()) ; ++j ) { int nIndex0 = mSplitLoop[vInters0.first][j] ; - if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) + if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo if ( m_vCCLoop[nIndex0]->IsClosed()) { - ICurveComposite* pCC0( GetCurveComposite( m_vCCLoop[nIndex0]->CopyParamRange( dEnd0, dStart0))) ; + ICurveComposite* pCC0( GetCurveComposite( m_vCCLoop[nIndex0]->CopyParamRange( dStart0, dEnd0))) ; m_vCCLoop[nIndex0].Set( pCC0) ; } else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC0a( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; - pCC0a->TrimEndAtParam( dStart0) ; + bool bDoneA = pCC0a->TrimEndAtParam( dEnd0) ; ICurveComposite* pCC0b( GetCurveComposite( m_vCCLoop[nIndex0]->Clone())) ; - pCC0b->TrimStartAtParam( dEnd0) ; - m_vCCLoop[nIndex0].Set( pCC0a) ; - m_vCCLoop.emplace_back( pCC0b) ; - mSplitLoop[vInters0.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC0b->TrimStartAtParam( dStart0) ; + if ( bDoneA) { + m_vCCLoop[nIndex0].Set( pCC0a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC0b) ; + mSplitLoop[vInters0.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex0].Set( pCC0b) ; } break ; } break ; } - break ; } } } @@ -2963,7 +2963,12 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg for ( int w = 0 ; w < int( mSplitLoop[vInters3.first].size()) ; ++w) { int nIndex3 = mSplitLoop[vInters3.first][w] ; IntersCurveCurve icc( *m_vCCLoop[nIndex3], *pCL) ; - IntCrvCrvInfo iccInfo ; icc.GetIntCrvCrvInfo( 0, iccInfo) ; + IntCrvCrvInfo iccInfo ; + for ( int k = 0 ; k < icc.GetIntersCount() ; ++k) { + icc.GetIntCrvCrvInfo( k, iccInfo) ; + if ( iccInfo.bOverlap) + break ; + } if ( ! iccInfo.bOverlap) continue ; // se parto da una curva chiusa semplicemente tolgo un pezzo @@ -2974,12 +2979,18 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC3a( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; - pCC3a->TrimEndAtParam( iccInfo.IciA[0].dU) ; + bool bDoneA = pCC3a->TrimEndAtParam( iccInfo.IciA[0].dU) ; ICurveComposite* pCC3b( GetCurveComposite( m_vCCLoop[nIndex3]->Clone())) ; - pCC3b->TrimStartAtParam( iccInfo.IciA[1].dU) ; - m_vCCLoop[nIndex3].Set( pCC3a) ; - m_vCCLoop.emplace_back( pCC3b) ; - mSplitLoop[vInters3.first].push_back( m_vCCLoop.size() - 1) ; + bool bDoneB = pCC3b->TrimStartAtParam( iccInfo.IciA[1].dU) ; + if ( bDoneA) { + m_vCCLoop[nIndex3].Set( pCC3a) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC3b) ; + mSplitLoop[vInters3.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB ) + m_vCCLoop[nIndex3].Set( pCC3b) ; } // per togliere la parte comune al loop corrente devo riportare i punti di intersezione sull'edge di partenza @@ -3001,18 +3012,23 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg else { // se la curva era già aperta allora otterrò due curve separate ICurveComposite* pCC1a( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; - pCC1a->TrimEndAtParam( dEnd1) ; + bool bDoneA = pCC1a->TrimEndAtParam( dEnd1) ; ICurveComposite* pCC1b( GetCurveComposite( m_vCCLoop[nIndex1]->Clone())) ; - pCC1b->TrimStartAtParam( dStart1) ; + bool bDoneB = pCC1b->TrimStartAtParam( dStart1) ; + if ( bDoneA) { m_vCCLoop[nIndex1].Set( pCC1a) ; - m_vCCLoop.emplace_back( pCC1b) ; - mSplitLoop[vInters1.first].push_back( m_vCCLoop.size() - 1) ; + if ( bDoneB) { + m_vCCLoop.emplace_back( pCC1b) ; + mSplitLoop[vInters1.first].push_back( m_vCCLoop.size() - 1) ; + } + } + else if ( bDoneB) + m_vCCLoop[nIndex1].Set( pCC1b) ; } break ; } break ; } - break ; } } } @@ -3050,107 +3066,21 @@ SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdg continue ; PtrOwner pCC( vpCCOpen[k]->Clone()) ; vbAdded[k] = true ; - for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { - if ( pCC->AddCurve( vpCCOpen[t]->Clone())) - vbAdded[t] = true ; + bool bAddedOne = true ; + while( bAddedOne) { + bAddedOne = false ; + for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { + if ( vbAdded[t]) + continue ; + if ( pCC->AddCurve( vpCCOpen[t]->Clone())) { + vbAdded[t] = true ; + bAddedOne = true ; + } + } } // aggiungo la curva agli edge 3d da restituire vCC.emplace_back( Release( pCC)) ; } - - //// con split nel parametrico//////////////////////////////////////////////////////// - - //// se volessi restiturie tutto passo i loop del parametrico portati in 3D - //for ( int i = 0 ; i < int(m_vCCLoop2D.size()) ; ++i) - // vCC.emplace_back( m_vCCLoop2D[i]->Clone()) ; - - - //// con le inters in 3D/////////////////////////////////////////////////// - //for ( int i = 0 ; i < int( m_vCCLoop.size()) ; ++i) { - // //// debug - // ////disegno le curve nel nuovo riferimento - // //vCC.emplace_back( Release(m_vCCLoop[i])) ; - // // continue ; - // ////debug - - // // calcolo le autointersezioni a mano - // // le premesse sono che le compo è formata da curveLine e che i tratti eventualmente sovrapposti sono linee interamente coincidenti ( start-end e viceversa) - // double dStart, dEnd ; m_vCCLoop[i]->GetDomain( dStart, dEnd) ; - // Intervals inDomain ; inDomain.Set( dStart, dEnd) ; - // //DBLVECTOR vdU ; - // BOOLVECTOR vbErased( m_vCCLoop[i]->GetCurveCount()) ; - // fill( vbErased.begin(), vbErased.end(), false) ; - // // scorro tutte le curve singole della compo - // for ( int k = 0 ; k < int( m_vCCLoop[i]->GetCurveCount()); ++k) { - // const ICurve* pCrvA = m_vCCLoop[i]->GetCurve( k) ; - // if ( vbErased[k]) - // continue ; - // Point3d ptStartA ; pCrvA->GetStartPoint( ptStartA) ; - // Point3d ptEndA ; pCrvA->GetEndPoint( ptEndA) ; - // // devo confrontarla con tutte le successive - // for ( int w = k + 1 ; w < int(m_vCCLoop[i]->GetCurveCount()); ++w ) { - // const ICurve* pCrvB = m_vCCLoop[i]->GetCurve( w) ; - // Point3d ptStartB ; pCrvB->GetStartPoint( ptStartB) ; - // Point3d ptEndB ; pCrvB->GetEndPoint( ptEndB) ; - // IntCrvCrvInfo iccInfo ; - // Vector3d vtDirSA ; pCrvA->GetStartDir( vtDirSA) ; - // Vector3d vtDirSB ; pCrvB->GetStartDir( vtDirSB) ; - // if ( AreSameOrOppositeVectorApprox( vtDirSA, Z_AX) || AreSameOrOppositeVectorApprox( vtDirSB, Z_AX)) { - // Frame3d frOptimal ; - // if ( (vtDirSA ^ vtDirSB).Len() > EPS_SMALL) - // frOptimal.Set( ORIG, vtDirSA ^ vtDirSB, vtDirSA) ; - // else - // frOptimal.Set( ORIG, X_AX, vtDirSA) ; - // PtrOwner pCrvNewA( pCrvA->Clone()) ; - // pCrvNewA->ToLoc( frOptimal) ; - // PtrOwner pCrvNewB( pCrvB->Clone()) ; - // pCrvNewB->ToLoc( frOptimal) ; - // IntersCurveCurve icc( *pCrvNewA, *pCrvNewB) ; - // icc.GetIntCrvCrvInfo( 0, iccInfo) ; - // } - // else { - // IntersCurveCurve icc( *pCrvA, *pCrvB) ; - // icc.GetIntCrvCrvInfo( 0, iccInfo) ; - // } - // // se sono sovrapposte allora devo eliminare la parte comune - // if ( iccInfo.bOverlap && ( AreSamePointApprox( ptStartA, ptEndB) || AreSamePointApprox( ptEndA, ptStartB) || - // AreSamePointApprox( ptStartA, ptStartB) || AreSamePointApprox( ptEndA, ptEndB))) { - // inDomain.Subtract( k + iccInfo.IciA[0].dU, k + iccInfo.IciA[1].dU) ; - // vbErased[k] = true ; - // inDomain.Subtract( w + iccInfo.IciB[0].dU, w + iccInfo.IciB[1].dU) ; - // vbErased[w] = true ; - // break ; - // } - // } - // // quando raggiungo la prima intersezione potrei anche uscire dal for.. però devo salvarmi da qualche parte tra quali sottocurve - // // ci sono intersezioni sennò non posso accorgermene - // } - - // ICRVCOMPOPOVECTOR vpCCOpen ; - - // // con Intervals - // double dStart0, dEnd0 ; inDomain.GetFirst( dStart0, dEnd0) ; - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - // while ( inDomain.GetNext( dStart0, dEnd0)) - // vpCCOpen.emplace_back( GetCurveComposite( m_vCCLoop[i]->CopyParamRange( dStart0, dEnd0))) ; - // - // // creo la chain a mano con le compo - // BOOLVECTOR vbAdded( vpCCOpen.size()) ; - // fill( vbAdded.begin(), vbAdded.end(), false) ; - // for ( int k = 0 ; k < int( vpCCOpen.size()); ++k ) { - // if ( vbAdded[k]) - // continue ; - // PtrOwner pCC( vpCCOpen[k]->Clone()) ; - // vbAdded[k] = true ; - // for ( int t = k ; t < int(vpCCOpen.size()); ++t ) { - // if ( pCC->AddCurve( vpCCOpen[t]->Clone())) - // vbAdded[t] = true ; - // } - // // aggiungo la curva agli edge 3d da restituire - // vCC.emplace_back( Release( pCC)) ; - // } - //} - //// con le inters in 3D/////////////////////////////////////////////////// } return true ; } diff --git a/Tree.cpp b/Tree.cpp index 38b6b62..f390ec2 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -73,6 +73,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches, const Point3d& ptMi m_vPlApprox.clear() ; m_vChunk.clear() ; m_vPolygons.clear() ; + m_vPlLoop2D.clear() ; m_pSrfBz = pSrfBz ; m_bSplitPatches = bSplitPatches ; @@ -3639,10 +3640,11 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { - mPLEdges.back().emplace_back() ; + mPLEdges.emplace_back() ; int nPtCount = 0 ; // scorro sui poligoni delle celle di un lato for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { + mPLEdges.back().emplace_back() ; Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato @@ -3713,6 +3715,7 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) else { // per ogni edge creo le compo che compongono l'edge dopo i trim ( possono essere più compo separate tra loro) for ( int i = 0 ; i < 4 ; ++i) { + mPLEdges.emplace_back() ; INTVECTOR vId ; Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) { From c94a62f5b24b5f8dabbd8c11e05776a0d7cedd26 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Thu, 21 Mar 2024 15:00:37 +0100 Subject: [PATCH 29/31] EgtGeomKernel - cambiato il nome della funzione per richiedere gli edge di una Bezier. --- SurfBezier.cpp | 2 +- SurfBezier.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 17433aa..bb9143f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -2743,7 +2743,7 @@ SurfBezier::CalcPoles( void) //---------------------------------------------------------------------------- bool -SurfBezier::GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) const +SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) const { // se nEdge non è definito ( == -1) allora restituisco tutti gli edge in ordine // se bOpenOrAll è true allora restituisco solo gli edge aperti e che non sono di polo diff --git a/SurfBezier.h b/SurfBezier.h index c24eaf7..0b57644 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -137,7 +137,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool IncreaseUV( Point3d& ptUV, Vector3d vtH , Point3d* ptUVCopy, bool bModifyOrig) const override ; // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier // se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate - bool GetOpenEdges3D( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; + bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; From 4ab4a2fc81056f9a30e6a6b579ccf80f1efe0b3f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Fri, 22 Mar 2024 16:11:51 +0100 Subject: [PATCH 30/31] EgtGeomKernel : - correzioni ad Edges3D della Bezier. #11 --- SurfBezier.cpp | 86 ++++++++++++++++++++------------------------------ Tree.cpp | 14 +++++--- 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index bb9143f..c71578f 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -1452,20 +1452,9 @@ SurfBezier::UpdateEdgesFromTree( Tree& tr) const for ( int i= 0 ; i < int( mPlEdges.size()); ++i) { for ( int j = 0 ; j < int ( mPlEdges[i].size()) ; ++j) { m_mCCEdge[i].emplace_back(CreateBasicCurveComposite()) ; - PolyLine pl3D ; - Point3d pt ; mPlEdges[i][j].GetFirstPoint( pt) ; - Point3d pt3D ; GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - int nCount = 0 ; - pl3D.AddUPoint( nCount, pt3D) ; - ++ nCount ; - while( mPlEdges[i][j].GetNextPoint( pt)){ - GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; - pl3D.AddUPoint( nCount, pt3D) ; - ++ nCount ; - } - if ( ! m_mCCEdge[i].back()->FromPolyLine(pl3D)) { + if ( ! m_mCCEdge[i].back()->FromPolyLine(mPlEdges[i][j]) ) { Point3d ptStart ; - if ( ! pl3D.GetFirstPoint( ptStart)) + if ( ! mPlEdges[i][j].GetFirstPoint( ptStart)) continue ; m_mCCEdge[i].back()->FromPoint( ptStart) ; } @@ -1509,6 +1498,7 @@ SurfBezier::GetAuxSurf( void) const // resetto il vettore degli edge m_mCCEdge.clear() ; m_mCCEdge = vector(4) ; + m_vCCLoop.clear() ; for ( int i = 0 ; i < (int) vTrees.size() ; ++ i) { Point3d ptMin = std::get<0>( vTrees[i]) ; Point3d ptMax = std::get<1>( vTrees[i]) ; @@ -1862,34 +1852,6 @@ struct hash { bool SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq) { - //// debug per controllare le autointersezione degli edge 3D - //ICRVCOMPOPOVECTOR vCCEdge ; - //GetOpenEdges3D(vCCEdge, true, -1) ; - //SelfIntersCurve sic( *vCCEdge[0]) ; - //PNTVECTOR vPnt0 ; - //DBLVECTOR vdU ; - //IntCrvCrvInfo iccInfo0 ; - //for ( int i = 0 ; sic.GetIntCrvCrvInfo( i, iccInfo0) ; ++ i) { - // if ( ! iccInfo0.bOverlap) { - // vPnt0.push_back( iccInfo0.IciA[0].ptI) ; - // vPnt0.push_back( iccInfo0.IciB[0].ptI) ; - // vdU.push_back(iccInfo0.IciA[0].dU) ; - // vdU.push_back(iccInfo0.IciB[0].dU) ; - // } - // else { - // vPnt0.push_back( iccInfo0.IciA[0].ptI) ; - // vPnt0.push_back( iccInfo0.IciA[1].ptI) ; - // vPnt0.push_back( iccInfo0.IciB[0].ptI) ; - // vPnt0.push_back( iccInfo0.IciB[1].ptI) ; - // vdU.push_back(iccInfo0.IciA[0].dU) ; - // vdU.push_back(iccInfo0.IciA[1].dU) ; - // vdU.push_back(iccInfo0.IciB[0].dU) ; - // vdU.push_back(iccInfo0.IciB[1].dU) ; - // } - //} - //int a = 0 ; - - // faccio l'intersezione della trimesh ausiliaria con il piano posso ottenere: punti, curve 3d e triangoli( coplanari al piano di taglio) // i punti li escludo // le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim @@ -2333,11 +2295,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in if ( ! m_mCCEdge[c][i]->GetOnlyPoint(pt)) return false ; vInters[c] = AreSamePointApprox( pt, ptI) ? 1 : 0 ; - nInters += vInters.back() ; + nInters += vInters[c] ; } else { vInters[c] = m_mCCEdge[c][i]->IsPointOn(ptI) ? 1 : 0 ; - nInters += vInters.back() ; + nInters += vInters[c] ; } } } @@ -2398,10 +2360,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in INTVECTOR vOn(3) ; fill( vOn.begin(), vOn.end(), -1) ; int nVertOnPole = -1 ; + INTVECTOR vEdgesClosed = { 1, 3} ; // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { // scorro sugli edge - for ( int ed = 0 ; ed < 4; ++ed) { + for ( int ed : vEdgesClosed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { if ( ! m_mCCEdge[ed][i]->IsValid()) { @@ -2451,10 +2414,11 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in INTVECTOR vOn(3) ; fill( vOn.begin(), vOn.end(), -1) ; int nVertOnPole = -1 ; + INTVECTOR vEdgesClosed = { 0, 2} ; // scorro sui vertici for ( int p = 0 ; p < 3; ++p ) { //scorro sugli edge - for (int ed = 0 ; ed < 4 ; ++ed) { + for (int ed : vEdgesClosed) { // scorro sui tratti che compongono l'edge for ( int i = 0 ; i < int( m_mCCEdge[ed].size()) ; ++i) { if ( ! m_mCCEdge[ed][i]->IsValid()) { @@ -2570,7 +2534,27 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in mA.col(0) << vPT[0].x, vPT[0].y , vPT[0].z ; mA.col(1) << vPT[1].x, vPT[1].y , vPT[1].z ; mA.col(2) << vPT[2].x, vPT[2].y , vPT[2].z ; - Eigen::Vector3d b ( ptI.x, ptI.y, ptI.z) ; + int nCount = 0 ; + Vector3d vtMod( 0, 0, 0) ; + while ( abs( mA.determinant()) < EPS_SMALL) { + if ( nCount %3 == 0) { + mA.row(0) << vPT[0].x + 1, vPT[1].x + 1, vPT[2].x + 1 ; + vtMod.x += 1 ; + } + else if ( nCount %3 == 1) { + mA.row(1) << vPT[0].y + 1, vPT[1].y + 1, vPT[2].y + 1 ; + vtMod.y += 1 ; + } + else if ( nCount %3 == 2) { + mA.row(2) << vPT[0].z + 1, vPT[1].z + 1, vPT[2].z + 1 ; + vtMod.z += 1 ; + } + ++nCount ; + if ( nCount == 10) + return false ; + } + Point3d ptNewI = ptI + vtMod ; + Eigen::Vector3d b ( ptNewI.x, ptNewI.y, ptNewI.z) ; Eigen::Vector3d x = mA.fullPivLu().solve(b) ; // applico questa composizione alle loro coordinate parametriche Eigen::Matrix3d mB ; @@ -2852,8 +2836,8 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con // come ptStart2 prendo quello con la x maggiore if ( ptStart2.x < ptEnd2.x) swap( ptStart2, ptEnd2) ; - if ( (( ptEnd0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptStart0.x + EPS_SMALL) && ( ptEnd0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptStart0.x + EPS_SMALL)) || - (( ptEnd2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptStart2.x + EPS_SMALL) && ( ptEnd2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptStart2.x + EPS_SMALL))) { + if ( (( ptEnd0.x - EPS_SMALL< ptStart2.x && ptStart2.x < ptStart0.x + EPS_SMALL) || ( ptEnd0.x - EPS_SMALL < ptEnd2.x && ptEnd2.x < ptStart0.x + EPS_SMALL)) || + (( ptEnd2.x - EPS_SMALL < ptStart0.x && ptStart0.x < ptStart2.x + EPS_SMALL) || ( ptEnd2.x - EPS_SMALL < ptEnd0.x && ptEnd0.x < ptStart2.x + EPS_SMALL))) { PtrOwner pCL( CreateBasicCurveLine()) ; pCL->Set( ptStart0, ptEnd0) ; // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale @@ -2955,8 +2939,8 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con // come ptStart3 prendo quello con la y maggiore if ( ptStart3.y < ptEnd3.y) swap( ptStart3, ptEnd3) ; - if ( (( ptEnd1.y - EPS_SMALL< ptStart3.y && ptStart3.y < ptStart1.y + EPS_SMALL) && ( ptEnd1.y - EPS_SMALL < ptEnd3.y && ptEnd3.y < ptStart1.y + EPS_SMALL)) || - (( ptEnd3.y - EPS_SMALL < ptStart1.y && ptStart1.y < ptStart3.y + EPS_SMALL) && ( ptEnd3.y - EPS_SMALL < ptEnd1.y && ptEnd1.y < ptStart3.y + EPS_SMALL))) { + if ( (( ptEnd1.y - EPS_SMALL< ptStart3.y && ptStart3.y < ptStart1.y + EPS_SMALL) || ( ptEnd1.y - EPS_SMALL < ptEnd3.y && ptEnd3.y < ptStart1.y + EPS_SMALL)) || + (( ptEnd3.y - EPS_SMALL < ptStart1.y && ptStart1.y < ptStart3.y + EPS_SMALL) || ( ptEnd3.y - EPS_SMALL < ptEnd1.y && ptEnd1.y < ptStart3.y + EPS_SMALL))) { PtrOwner pCL( CreateBasicCurveLine()) ; pCL->Set( ptStart1, ptEnd1) ; // devo scorrere su tutte le curve che sono state ottenute dallo split del loop originale @@ -3000,7 +2984,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con ptOverlapE.x = 0 ; double dStart1, dEnd1 ; // scorro tutte le curve in cui è stato splittato il loop iniziale - for ( int j = 0 ; int( mSplitLoop[vInters1.first].size()) ; ++j ) { + for ( int j = 0 ; j < int( mSplitLoop[vInters1.first].size()) ; ++j ) { int nIndex1 = mSplitLoop[vInters1.first][j] ; if ( ! m_vCCLoop[nIndex1]->GetParamAtPoint( ptOverlapS, dStart1) || ! m_vCCLoop[nIndex1]->GetParamAtPoint( ptOverlapE, dEnd1)) continue ; diff --git a/Tree.cpp b/Tree.cpp index f390ec2..12568fd 100644 --- a/Tree.cpp +++ b/Tree.cpp @@ -3641,10 +3641,10 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) // scorro sui gruppi di polyline che rappresentano i poligoni delle celle lungo un lato for ( int i = 0 ; i < int( mPL.size()) ; ++i) { mPLEdges.emplace_back() ; + mPLEdges.back().emplace_back() ; int nPtCount = 0 ; // scorro sui poligoni delle celle di un lato for ( int c = 0 ; c < int( mPL[i].size()) ; ++c) { - mPLEdges.back().emplace_back() ; Point3d pt ; mPL[i][c].GetFirstPoint( pt) ; Point3d pt3d ; // a seconda del lato controllo di stare scorrendo il poligono prendendo solo i punti su quel lato @@ -3719,17 +3719,21 @@ Tree::GetEdges3D( POLYLINEMATRIX& mPLEdges) INTVECTOR vId ; Point3d ptNear = m_mTree.at(-1).GetBottomLeft() ; while( m_vCEdge2D[i].second.GetChainFromNear(ptNear, false, vId) ) { - PolyLine pl2D ; + PolyLine pl3D ; int nInd = abs( vId[0]) - 1 ; - pl2D.AddUPoint( 0, m_vCEdge2D[i].first[nInd].first) ; + Point3d pt2D = m_vCEdge2D[i].first[nInd].first ; + Point3d pt3D ; m_pSrfBz->GetPointD1D2( pt2D.x / SBZ_TREG_COEFF, pt2D.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + pl3D.AddUPoint( 0, pt3D) ; int nCount = 1 ; for ( int j = 1 ; j < int( vId.size()) ; ++j) { nInd = abs( vId[j]) - 1 ; - if ( pl2D.AddUPoint( nCount, m_vCEdge2D[i].first[nInd].second)) + pt2D = m_vCEdge2D[i].first[nInd].second ; + m_pSrfBz->GetPointD1D2( pt2D.x / SBZ_TREG_COEFF, pt2D.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3D) ; + if ( pl3D.AddUPoint( nCount, pt3D)) ++ nCount ; } // qui devo fare dei controlli prima di aggiungere questa polyline? - mPLEdges[i].emplace_back( pl2D) ; + mPLEdges[i].emplace_back( pl3D) ; } } } From 7882964b268480cf63bef8a4c5a715bf578a5fef Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 25 Mar 2024 09:59:21 +0100 Subject: [PATCH 31/31] EgtGeomKernel : - corretto bug nella richiesta degli edge3D di una Bezier. --- SurfBezier.cpp | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index c71578f..e0a3465 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -2818,7 +2818,9 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con // scorro i loop che fanno intersezioni con l'edge 0 ( V=1) e le riporto sull'edge opposto for ( pair vInters0 : vmInters[0]) { // scorro le intersezioni del loop - for ( IntCrvCrvInfo inters0 : vInters0.second) { + for ( IntCrvCrvInfo inters0 : vInters0.second) { + if ( ! inters0.bOverlap) + continue ; Point3d ptStart0 = inters0.IciA[0].ptI ; Point3d ptEnd0 = inters0.IciA[1].ptI ; // porto i punti sull'edge opposto @@ -2880,7 +2882,7 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con ptOverlapS.y = m_nSpanV * SBZ_TREG_COEFF ; ptOverlapE.y = m_nSpanV * SBZ_TREG_COEFF ; double dStart0, dEnd0 ; - // scorro tutte le curve in cui è stato splittato il loop iniziale + // scorro tutte le curve in cui è stato splittato il loop corrente for ( int j = 0 ; j < int( mSplitLoop[vInters0.first].size()) ; ++j ) { int nIndex0 = mSplitLoop[vInters0.first][j] ; if ( ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapS, dStart0) || ! m_vCCLoop[nIndex0]->GetParamAtPoint( ptOverlapE, dEnd0)) @@ -2906,9 +2908,9 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con else if ( bDoneB) m_vCCLoop[nIndex0].Set( pCC0b) ; } - break ; + //break ; } - break ; + //break ; } } } @@ -2922,6 +2924,8 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con for ( pair vInters1 : vmInters[1]) { // scorro le intersezioni del loop for ( IntCrvCrvInfo inters1 : vInters1.second) { + if ( ! inters1.bOverlap) + continue ; Point3d ptStart1 = inters1.IciA[0].ptI ; Point3d ptEnd1 = inters1.IciA[1].ptI ; // porto i punti sull'edge opposto @@ -3009,9 +3013,9 @@ SurfBezier::GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge) con else if ( bDoneB) m_vCCLoop[nIndex1].Set( pCC1b) ; } - break ; + //break ; } - break ; + //break ; } } }