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) ;