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