diff --git a/PolyLine.cpp b/PolyLine.cpp index 3e0ff5a..2e1f3d1 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2013-2013 //---------------------------------------------------------------------------- // File : PolyLine.cpp Data : 22.12.13 Versione : 1.4l3 @@ -53,7 +53,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart) { // se da aggiungere in coda if ( bEndOrStart) { - // se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok + // se il punto è uguale all'ultimo (ignoro parametro), non lo inserisco ma ok if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.back().first)) { ++ m_nRejected ; return true ; @@ -68,7 +68,7 @@ PolyLine::AddUPoint( double dPar, const Point3d& ptP, bool bEndOrStart) } // altrimenti si aggiunge in testa else { - // se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok + // se il punto è uguale al primo (ignoro parametro), non lo inserisco ma ok if ( m_lUPoints.size() > 0 && AreSamePointApprox( ptP, m_lUPoints.front().first)) { ++ m_nRejected ; return true ; @@ -92,7 +92,7 @@ PolyLine::Close( void) // ci devono essere almeno 2 punti if ( m_lUPoints.size() < 2) return false ; - // verifico non sia già chiuso + // verifico non sia già chiuso if ( AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first)) return false ; // aggiungo un punto uguale al primo in coda @@ -219,7 +219,7 @@ PolyLine::ToLoc( const Frame3d& frRef) bool PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) { - // se i due riferimenti coincidono, non devo fare alcunché + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; // ciclo sui punti @@ -233,7 +233,7 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) bool PolyLine::Join( PolyLine& PL, double dOffsetPar) { - // se l'altra polilinea non contiene alcunchè, esco con ok + // se l'altra polilinea non contiene alcunchè, esco con ok if ( PL.m_lUPoints.size() == 0) return true ; // verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra @@ -385,7 +385,7 @@ PolyLine::GetPrevUPoint( double* pdPar, Point3d* pptP, bool bNotFirst) const bool PolyLine::GetCurrUPoint( double* pdPar, Point3d* pptP) const { - // verifico validità punto corrente + // verifico validità punto corrente if ( m_iter == m_lUPoints.end()) return false ; @@ -426,7 +426,7 @@ PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* bool PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) const { - // parametro e punto iniziali (è il precedente finale) + // parametro e punto iniziali (è il precedente finale) if ( m_iter == m_lUPoints.end()) return false ; if ( pdIni != nullptr) @@ -510,19 +510,19 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co ptsPCA.AddPoint( Media( ptP1, ptP2, 0.25), dLen / 2) ; ptsPCA.AddPoint( Media( ptP1, ptP2, 0.75), dLen / 2) ; } - // recupero il rango, ovvero la dimensionalità dell'insieme di punti + // recupero il rango, ovvero la dimensionalità dell'insieme di punti nRank = ptsPCA.GetRank() ; // se dimensione nulla, o non ci sono punti o sono tutti praticamente coincidenti if ( nRank == 0) return ptsPCA.GetCenter( ptCen) ; // se dimensione 1, allora i punti sono distribuiti su una linea if ( nRank == 1) { - // assegno il centro e la direzione della linea (il verso è indifferente) + // assegno il centro e la direzione della linea (il verso è indifferente) ptsPCA.GetCenter( ptCen) ; ptsPCA.GetPrincipalComponent( 0, vtDir) ; return true ; } - // altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono + // altrimenti dimensione 2 o 3, allora è determinato un piano principale, verifico se tutti i punti vi giacciono // Center and normal vector ptsPCA.GetCenter( ptCen) ; Vector3d vtX, vtY ; @@ -530,9 +530,9 @@ PolyLine::IsFlat( int& nRank, Point3d& ptCen, Vector3d& vtDir, double dToler) co ptsPCA.GetPrincipalComponent( 1, vtY) ; vtDir = vtX ^ vtY ; if ( ! vtDir.Normalize()) { - // riduco la dimensionalità a lineare + // riduco la dimensionalità a lineare nRank = 1 ; - // assegno il centro e la direzione della linea (il verso è indifferente) + // assegno il centro e la direzione della linea (il verso è indifferente) ptsPCA.GetCenter( ptCen) ; vtDir = vtX ; return true ; @@ -561,12 +561,12 @@ PolyLine::IsFlat( Plane3d& plPlane, double dToler) const plPlane.Reset() ; return false ; } - // recupero dati sulla planarità della polilinea + // recupero dati sulla planarità della polilinea int nRank ; Point3d ptCen ; Vector3d vtDir ; bool bFlat = IsFlat( nRank, ptCen, vtDir, dToler) ; - // imposto il piano a seconda della dimensionalità + // imposto il piano a seconda della dimensionalità switch ( nRank) { case 0 : // punto plPlane.Set( ptCen, Z_AX) ; @@ -639,13 +639,13 @@ PolyLine::GetAreaXY( double& dArea) const // verifico sia chiusa if ( ! IsClosed()) return false ; - // calcolo l'area considerando solo XY (è la Z di Newell) + // calcolo l'area considerando solo XY (è la Z di Newell) dArea = 0 ; Point3d ptIni, ptFin ; for ( bool bFound = GetFirstLine( ptIni, ptFin) ; bFound ; bFound = GetNextLine( ptIni, ptFin)) { dArea += ( ptIni.x - ptFin.x) * ( ptIni.y + ptFin.y) ; // projection on xy } - // considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area + // considero anche la linea tra l'ultimo e il primo punto perchè in alcuni casi potrebbero definire area // significativa anche se sono coincidenti per le nostre tolleranze ptIni = ptFin ; GetFirstPoint( ptFin) ; @@ -746,7 +746,7 @@ DouglasPeuckerSimplification( const PNTUVECTOR& vPtU, const double dSqTol, const } } - // se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra + // se la distanza massima trovata è sopra la tolleranza, allora controllo la parte di PolyLine tra // (nIndStart, nMaxInd) e quella tra (nMaxInd, nIndEnd) if ( dMaxSqDist > dSqTol) { // inserisco il punto @@ -789,7 +789,7 @@ PolyLine::RemoveAlignedPoints( double dToler) } // altrimenti chiusa else { - // cerco il punto più distante dal primo + // cerco il punto più distante dal primo double dMaxDist = 0. ; int nMaxInd = 0 ; for ( int i = 1 ; i < int( vPtU.size()) ; ++ i) { @@ -966,7 +966,7 @@ PolyLine::MyApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler) } } } - // non è stato eliminato alcunché + // non è stato eliminato alcunché // ripristino la tolleranza corrente dCurrToler = dToler ; // avanzo il terzetto di uno step @@ -1007,7 +1007,7 @@ PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide) bool PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide) { - // ciclo i controlli finchè non ci sono rimozioni + // ciclo i controlli finchè non ci sono rimozioni bool bRemoved = true ; while ( bRemoved) { bRemoved = false ; @@ -1035,7 +1035,7 @@ PolyLine::MyMakeConvex( const Vector3d& vtN, bool bLeftSide) bRemoved = true ; continue ; } - // non è stato eliminato alcunché : avanzo il terzetto di uno step + // non è stato eliminato alcunché : avanzo il terzetto di uno step precP = currP ; currP = nextP ; ++ nextP ; @@ -1062,7 +1062,7 @@ PolyLine::Invert( bool bInvertU) m_lUPoints.reverse() ; // se richiesto, inverto anche il parametro U if ( bInvertU) { - // recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione + // recupero il primo valore di U che è il vecchio finale ed è il riferimento di inversione double dUfin = m_lUPoints.front().second ; // ciclo su tutti gli elementi for ( auto& UPoint : m_lUPoints) { @@ -1277,7 +1277,7 @@ PolyLine::GetMinAreaRectangleXY( Point3d& ptCen, Vector3d& vtAx, double& dLen, d bool PolyLine::Trim( const Plane3d& plPlane, bool bInVsOut) { - // se vuota non faccio alcunché + // se vuota non faccio alcunché if ( m_lUPoints.size() == 0) return false ; @@ -1379,7 +1379,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler return false ; // Riferimento alla lista dei punti PNTULIST& List = const_cast( plPoly).GetUPointList() ; - // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto + // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto double dMinSqDist = SQ_INFINITO ; Point3d ptMinDist ; auto itMinDistEnd = List.end() ; @@ -1468,7 +1468,7 @@ GetPointParamOnPolyLine( const Point3d& ptP, const PolyLine& plPoly, double dTol // assegno nuovo inizio ptStart = ptEnd ; } - // Il punto è sulla linea se la sua distanza rispetta la tolleranza + // Il punto è sulla linea se la sua distanza rispetta la tolleranza return ( dMinSqDist < dToler * dToler) ; } @@ -1481,7 +1481,7 @@ ChangePolyLineStart( PolyLine& plPoly, const Point3d& ptNewStart, double dToler) return false ; // Riferimento alla lista dei punti PNTULIST& LoopList = const_cast( plPoly).GetUPointList() ; - // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto + // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto double dMinSqDist = SQ_INFINITO ; auto itMinDistEnd = LoopList.end() ; auto itStart = LoopList.begin() ; @@ -1525,7 +1525,7 @@ SplitPolyLineAtPoint( const PolyLine& plPoly, const Point3d& ptP, double dToler, return false ; // Riferimento alla lista dei punti const PNTULIST& LoopList = const_cast( plPoly).GetUPointList() ; - // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto + // Ciclo sui segmenti della polilinea per cercare il segmento più vicino al punto double dMinSqDist = SQ_INFINITO ; auto itMinDistEnd = LoopList.end() ; auto itStart = LoopList.begin() ; @@ -1608,7 +1608,7 @@ AssociatePolyLinesMinDistPoints( const PolyLine& PL1, const PolyLine& PL2, PNTIV if ( nMinJ < nLastJ) nMinJ = nLastJ ; - // verifica se è un punto interno in comune con l'altra polyline + // verifica se è un punto interno in comune con l'altra polyline if ( i < nTotP1 - 1 && dDist < EPS_SMALL && abs( dMinDistPar - floor( dMinDistPar + 0.5)) < EPS_SMALL) bCommonInternalPoints = true ; diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 2d6d14e..c548740 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -330,9 +330,11 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, { // verifico che la linea guida sia piana Plane3d plGuide ; - if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) + if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL)) return nullptr ; - Vector3d vtNorm = plGuide.GetVersN() ; + Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ; + if ( vtNorm.IsSmall()) + vtNorm = Z_AX ; // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; // curve di offset @@ -355,7 +357,7 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, PtrOwner pSrfBot( pSrfTop->Clone()) ; if ( IsNull( pSrfBot)) return nullptr ; - pSrfBot->Translate( -dDimV * vtNorm) ; + pSrfBot->Translate( - dDimV * vtNorm) ; pSrfBot->Invert() ; PtrOwner pSrfRgt( GetSurfTriMeshByExtrusion( pCrvR, -dDimV * vtNorm, false, dLinTol)) ; if ( IsNull( pSrfRgt)) @@ -407,81 +409,131 @@ GetSurfTriMeshSharpRectSwept( double dDimH, double dDimV, const ICurve* pGuide, if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { // step di rotazione per rispettare la tolleranza double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; - // aggiungo il cap sull'inizio - Point3d ptStart ; - pGuide->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pGuide->GetStartDir( vtStart) ; - vtStart.Rotate( vtNorm, 0, 1) ; - PolyLine PLStart ; - PLStart.AddUPoint( 0, ptStart) ; - PLStart.AddUPoint( 1, ptStart + dDimH / 2 * vtStart) ; - PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dDimV * vtNorm) ; - PLStart.AddUPoint( 3, ptStart - dDimV * vtNorm) ; - PtrOwner pSci( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) - return nullptr ; - pSci->Invert() ; - // per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione - for ( int i = 0 ; i < pSci->GetFacetCount() ; ++ i) { - Vector3d vtN ; - // se la faccia ha normale parallela a vtNorm... - if ( pSci->GetFacetNormal( i, vtN) && - AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) { - // ... ricavo il loop - POLYLINEVECTOR vLoops ; - if ( ! pSci->GetFacetLoops( i, vLoops) || vLoops.empty()) - return nullptr ; - // lo semplifico - vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ; - // eseguo triangolazione e aggiungo la faccia alla Soup - PtrOwner pStmNewFace( CreateSurfTriMesh()) ; - if ( IsNull( pStmNewFace) || - ! pStmNewFace->CreateByFlatContour( vLoops[0])) - return nullptr ; - stmSoup.AddSurfTriMesh( *pStmNewFace) ; + // se l'offset interno alla guida è chiuso + if ( pCrvL->IsClosed()) { + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ; + Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ; + Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ; + Point3d ptCenter = Media( ptRight, ptLeft) ; + Vector3d vtRight = ptRight - ptCenter ; + Vector3d vtLeft = ptLeft - ptCenter ; + double dAng = ANG_STRAIGHT ; + vtRight.GetAngle( vtLeft, dAng) ; + vtRight.Normalize() ; + PolyLine plLoop ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptRight) ; // primo punto + double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptRight ; + ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza } - // altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli - else - stmSoup.AddSurfTriMesh( *pSci->CloneFacet( i)) ; + plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto + plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso + plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa + // superificie Top + PtrOwner pStmTop( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop) ; + // superificie Bottom + PtrOwner pStmBottom( CloneSurfTriMesh( pStmTop)) ; + pStmBottom->Translate( - dDimV * vtNorm) ; + pStmBottom->Invert() ; + stmSoup.AddSurfTriMesh( *pStmBottom) ; + // superificie perpendicolare + // la PolyLine che utilizzo la posso ricavare da quella calcolata sopra + plLoop.EraseLastUPoint() ; // apro il loop + plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset + PtrOwner pStmPerp( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp) || ! pStmPerp->CreateByExtrusion( plLoop, - vtNorm * dDimV) || + ! pStmPerp->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp) ; } - // aggiungo il cap sulla fine - Point3d ptEnd ; - pGuide->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pGuide->GetEndDir( vtEnd) ; - vtEnd.Rotate( vtNorm, 0, -1) ; - PolyLine PLEnd ; - PLEnd.AddUPoint( 0, ptEnd) ; - PLEnd.AddUPoint( 1, ptEnd + dDimH / 2 * vtEnd) ; - PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dDimV * vtNorm) ; - PLEnd.AddUPoint( 3, ptEnd - dDimV * vtNorm) ; - PtrOwner pSce( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) - return nullptr ; - pSce->Invert() ; - // per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione - for ( int i = 0 ; i < pSce->GetFacetCount() ; ++ i) { - Vector3d vtN ; - // se la faccia ha normale parallela a vtNorm... - if ( pSce->GetFacetNormal( i, vtN) && - AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) { - // ... ricavo il loop - POLYLINEVECTOR vLoops ; - if ( ! pSce->GetFacetLoops( i, vLoops) || vLoops.empty()) - return nullptr ; - // lo semplifico - vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ; - // eseguo triangolazione e aggiungo la faccia alla Soup - PtrOwner pStmNewFace( CreateSurfTriMesh()) ; - if ( IsNull( pStmNewFace) || - ! pStmNewFace->CreateByFlatContour( vLoops[0])) - return nullptr ; - stmSoup.AddSurfTriMesh( *pStmNewFace) ; + // se l'offset interno della guida è aperto... + else { + // aggiungo il cap sull'inizio + Point3d ptStart ; + pGuide->GetStartPoint( ptStart) ; + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ; + Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ; + Vector3d vtLeft = ptSLeft - ptStart ; + Vector3d vtRight = ptSRight - ptStart ; + double dAng = ANG_STRAIGHT ; + vtLeft.GetAngle( vtRight, dAng) ; + vtLeft.Normalize() ; + PolyLine plLoop ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptSLeft) ; // primo punto + double dAngStep = ceil( dAng / dStepRotDeg) ; + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSLeft ; + ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; } - // altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli - else - stmSoup.AddSurfTriMesh( *pSce->CloneFacet( i)) ; + plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto + plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa + // creo la superficie Top + PtrOwner pStmTop_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop_start) ; + // superificie Bottom + PtrOwner pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ; + pStmBottom_start->Translate( - dDimV * vtNorm) ; + pStmBottom_start->Invert() ; + stmSoup.AddSurfTriMesh( *pStmBottom_start) ; + // superificie perpendicolare + // la PolyLine che utilizzo la posso ricavare da quella calcolata sopra + plLoop.EraseLastUPoint() ; // apro il loop + PtrOwner pStmPerp_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp_start) || ! pStmPerp_start->CreateByExtrusion( plLoop, - vtNorm * dDimV) || + ! pStmPerp_start->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp_start) ; + // aggiungo il cap sulla fine + Point3d ptEnd ; + pGuide->GetEndPoint( ptEnd) ; + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + pCrvL->GetEndPoint( ptSLeft) ; + pCrvR->GetEndPoint( ptSRight) ; + vtLeft = ptSLeft - ptEnd ; + vtRight = ptSRight - ptEnd ; + dAng = ANG_STRAIGHT ; + vtRight.GetAngle( vtLeft, dAng) ; + vtRight.Normalize() ; + plLoop.Clear() ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptSRight) ; + dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSRight ; + ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; + } + plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto + plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa + // creo la superficie Top + PtrOwner pStmTop_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop_end) ; + // creo la superificie Bottom + PtrOwner pStmBottom_end( CloneSurfTriMesh( pStmTop_end)) ; + pStmBottom_end->Translate( - dDimV * vtNorm) ; + pStmBottom_end->Invert() ; + stmSoup.AddSurfTriMesh( *pStmBottom_end) ; + // creo la superificie perpendicolare alla guida + plLoop.EraseLastUPoint() ; // apro il loop + PtrOwner pStmPerp_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp_end) || ! pStmPerp_end->CreateByExtrusion( plLoop, - vtNorm * dDimV) || + ! pStmPerp_end->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp_end) ; } // completo unione e recupero la superficie risultante if ( ! stmSoup.End()) @@ -509,13 +561,13 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub // verifico che la linea guida sia piana Plane3d plGuide ; - if ( ! pGuide->IsFlat( plGuide, false, 10 * EPS_SMALL)) + if ( ! pGuide->IsFlat( plGuide, true, 10 * EPS_SMALL)) return nullptr ; - // assegno la normale del piano - Vector3d vtNorm = plGuide.GetVersN() ; + Vector3d vtNorm ; pGuide->GetExtrusion( vtNorm) ; + if ( vtNorm.IsSmall()) + vtNorm = Z_AX ; // determino il punto centrale della sezione - Point3d ptCen ; - pGuide->GetStartPoint( ptCen) ; + Point3d ptCen ; pGuide->GetStartPoint( ptCen) ; ptCen -= dDimV / 2 * vtNorm ; // determino se la guida è chiusa bool bGuideClosed = pGuide->IsClosed() ; @@ -544,7 +596,6 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub for ( int i = 0 ; i < NUM_OFFS && bOk ; ++ i) bOk = vOffsCrv[i].Make( pGuide, vDist[i], ICurve::OFF_FILLET) ; } - if ( ! bOk || vOffsCrv[0].GetCurveCount() == 0 || vOffsCrv[1].GetCurveCount() == 0 || vOffsCrv[2].GetCurveCount() == 0 || vOffsCrv[3].GetCurveCount() == 0) @@ -640,85 +691,235 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub else if ( ! bGuideClosed && ( nCapType == RSCAP_ROUND || nCapType == RSCAP_BEVEL)) { // step di rotazione per rispettare il tipo o la tolleranza double dStepRotDeg = ( nCapType == RSCAP_BEVEL ? ANG_STRAIGHT / 4 : sqrt( 8 * dLinTol / dDimH) * RADTODEG) ; - // aggiungo il cap sull'inizio - Point3d ptStart ; - pGuide->GetStartPoint( ptStart) ; - Vector3d vtStart ; - pGuide->GetStartDir( vtStart) ; - vtStart.Rotate( vtNorm, 0, 1) ; - PolyLine PLStart ; - PLStart.AddUPoint( 0, ptStart) ; - PLStart.AddUPoint( 1, ptStart + ( dDimH / 2 - dBevelH) * vtStart) ; - PLStart.AddUPoint( 2, ptStart + dDimH / 2 * vtStart - dBevelV * vtNorm) ; - PLStart.AddUPoint( 3, ptStart + dDimH / 2 * vtStart - ( dDimV - dBevelV) * vtNorm) ; - PLStart.AddUPoint( 4, ptStart + ( dDimH / 2 - dBevelH) * vtStart - dDimV * vtNorm) ; - PLStart.AddUPoint( 5, ptStart - dDimV * vtNorm) ; - PtrOwner pSci( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSci) || ! pSci->CreateByScrewing( PLStart, ptStart, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) - return nullptr ; - pSci->Invert() ; - // per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione - for ( int i = 0 ; i < pSci->GetFacetCount() ; ++ i) { - Vector3d vtN ; - // se la faccia ha normale parallela a vtNorm... - if ( pSci->GetFacetNormal( i, vtN) && - AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) { - // ... ricavo il loop - POLYLINEVECTOR vLoops ; - if ( ! pSci->GetFacetLoops( i, vLoops) || vLoops.empty()) - return nullptr ; - // lo semplifico - vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ; - // eseguo triangolazione e aggiungo la faccia alla Soup - PtrOwner pStmNewFace( CreateSurfTriMesh()) ; - if ( IsNull( pStmNewFace) || - ! pStmNewFace->CreateByFlatContour( vLoops[0])) - return nullptr ; - stmSoup.AddSurfTriMesh( *pStmNewFace) ; + // se l'offset interno della guida è chiuso... + if ( pCrvL->IsClosed()) { + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + Point3d ptRight ; pCrvR->GetEndPoint( ptRight) ; + Point3d ptLeft ; pCrvR->GetStartPoint( ptLeft) ; + Point3d ptJunction ; pCrvL->GetStartPoint( ptJunction) ; + Point3d ptCenter = Media( ptRight, ptLeft) ; + Vector3d vtRight = ptRight - ptCenter ; + Vector3d vtLeft = ptLeft - ptCenter ; + double dAng = ANG_STRAIGHT ; + vtRight.GetAngle( vtLeft, dAng) ; + vtRight.Normalize() ; + PolyLine plLoop ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptRight) ; // primo punto + double dAngStep = ceil( dAng / dStepRotDeg) ; // aggiusto lo step + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptRight ; + ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; // punto intermedio sulla circonferenza } - // altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli - else - stmSoup.AddSurfTriMesh( *pSci->CloneFacet( i)) ; + plLoop.AddUPoint( dAngStep ++, ptLeft) ; // ultimo punto + plLoop.AddUPoint( dAngStep ++, ptJunction) ; // punto centrale sull'offset chiuso + plLoop.AddUPoint( dAngStep, ptRight) ; // polyLine chiusa + // superificie Top + PtrOwner pStmTop( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop) || ! pStmTop->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop) ; + // superificie Bottom + PtrOwner pStmBottom( CloneSurfTriMesh( pStmTop)) ; + if ( IsNull( pStmBottom) || ! pStmBottom->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmBottom) ; + // calcolo l'angolo di rotazione per la faccia Top del bevel + // NB. Questo angolo va ricalcolato, il bevel è inclinato rispetto alla normale della guida + ptCenter.Translate( - dBevelV * vtNorm) ; + Point3d ptbRight ; pCrvRb->GetEndPoint( ptbRight) ; + Point3d ptbLeft ; pCrvRb->GetStartPoint( ptbLeft) ; + Vector3d vtbLeft = ptbLeft - ptCenter ; + Vector3d vtbRight = ptbRight - ptCenter ; + dAng = ANG_STRAIGHT ; + vtbRight.GetAngle( vtbLeft, dAng) ; + vtbRight.Normalize() ; + // la PolyLine che utilizzo la posso ricavare da quella calcolata sopra + plLoop.EraseLastUPoint() ; // apro il loop + plLoop.EraseLastUPoint() ; // tolgo il punto di contatto sull'offset + // creo il loop defininendo i punti + PolyLine plLoopB ; + plLoopB.AddUPoint( 0, ptbRight) ; + dAngStep = ceil( dAng / dStepRotDeg) ; + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptbRight ; + ptRot.Rotate( ptCenter, vtNorm, i * ( dAng / dAngStep)) ; + plLoopB.AddUPoint( i, ptRot) ; + } + plLoopB.AddUPoint( dAngStep, ptbLeft) ; + // creo la superficie Top Bevel + PtrOwner pStmbTop_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmbTop_start) || + ! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) || + ! pStmbTop_start->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbTop_start) ; + // creo la superificie Bottom Bevel + PtrOwner pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ; + if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbBottom_start) ; + // creo la superficie perpendicolare alla guida + PolyLine plLoopB1 = plLoopB ; + plLoopB1.Mirror( ptCen, vtNorm) ; + PtrOwner pStmPerp( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp) || + ! pStmPerp->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) || + ! pStmPerp->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp) ; } - // aggiungo il cap sulla fine - Point3d ptEnd ; - pGuide->GetEndPoint( ptEnd) ; - Vector3d vtEnd ; - pGuide->GetEndDir( vtEnd) ; - vtEnd.Rotate( vtNorm, 0, -1) ; - PolyLine PLEnd ; - PLEnd.AddUPoint( 0, ptEnd) ; - PLEnd.AddUPoint( 1, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd) ; - PLEnd.AddUPoint( 2, ptEnd + dDimH / 2 * vtEnd - dBevelV * vtNorm) ; - PLEnd.AddUPoint( 3, ptEnd + dDimH / 2 * vtEnd - ( dDimV - dBevelV) * vtNorm) ; - PLEnd.AddUPoint( 4, ptEnd + ( dDimH / 2 - dBevelH) * vtEnd - dDimV * vtNorm) ; - PLEnd.AddUPoint( 5, ptEnd - dDimV * vtNorm) ; - PtrOwner pSce( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSce) || ! pSce->CreateByScrewing( PLEnd, ptEnd, vtNorm, ANG_STRAIGHT, dStepRotDeg, 0)) - return nullptr ; - pSce->Invert() ; - // per le facce con normale parallela a vtNorm, evito di creare giunzioni a T sull'asse di rotazione - for ( int i = 0 ; i < pSce->GetFacetCount() ; ++ i) { - Vector3d vtN ; - // se la faccia ha normale parallela a vtNorm... - if ( pSce->GetFacetNormal( i, vtN) && - AreSameOrOppositeVectorEpsilon( vtN, vtNorm, 5 * EPS_SMALL)) { - // ... ricavo il loop - POLYLINEVECTOR vLoops ; - if ( ! pSce->GetFacetLoops( i, vLoops) || vLoops.empty()) - return nullptr ; - // lo semplifico - vLoops[0].RemoveAlignedPoints( 5 * EPS_SMALL) ; - // eseguo triangolazione e aggiungo la faccia alla Soup - PtrOwner pStmNewFace( CreateSurfTriMesh()) ; - if ( IsNull( pStmNewFace) || - ! pStmNewFace->CreateByFlatContour( vLoops[0])) - return nullptr ; - stmSoup.AddSurfTriMesh( *pStmNewFace) ; + // se l'offset interno della guida è aperto... + else { + // aggiungo il cap sull'inizio + Point3d ptStart ; + pGuide->GetStartPoint( ptStart) ; + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + Point3d ptSLeft ; pCrvL->GetStartPoint( ptSLeft) ; + Point3d ptSRight ; pCrvR->GetStartPoint( ptSRight) ; + Vector3d vtLeft = ptSLeft - ptStart ; + Vector3d vtRight = ptSRight - ptStart ; + double dAng = ANG_STRAIGHT ; + vtLeft.GetAngle( vtRight, dAng) ; + vtLeft.Normalize() ; + PolyLine plLoop ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptSLeft) ; // primo punto + double dAngStep = ceil( dAng / dStepRotDeg) ; + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSLeft ; + ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; } - // altrimenti faccia con normale non parallela a vtNorm, aggiungo tutti i triangoli - else - stmSoup.AddSurfTriMesh( *pSce->CloneFacet( i)) ; + plLoop.AddUPoint( dAngStep, ptSRight) ; // ultimo punto + plLoop.AddUPoint( dAngStep + 1, ptSLeft) ; // polyline chiusa + // creo la superficie Top + PtrOwner pStmTop_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop_start) || ! pStmTop_start->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop_start) ; + // creo la superificie Bottom + PtrOwner pStmBottom_start( CloneSurfTriMesh( pStmTop_start)) ; + if ( IsNull( pStmBottom_start) || ! pStmBottom_start->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmBottom_start) ; + // calcolo l'angolo di rotazione per la faccia Top del bevel + ptStart.Translate( - dBevelV * vtNorm) ; + Point3d ptSbLeft ; pCrvLb->GetStartPoint( ptSbLeft) ; + Point3d ptSbRight ; pCrvRb->GetStartPoint( ptSbRight) ; + Vector3d vtbLeft = ptSbLeft - ptStart ; + Vector3d vtbRight = ptSbRight - ptStart ; + dAng = ANG_STRAIGHT ; + vtbLeft.GetAngle( vtbRight, dAng) ; + vtbLeft.Normalize() ; + plLoop.EraseLastUPoint() ; // apro il loop + // creo il loop defininendo i punti + PolyLine plLoopB ; + plLoopB.AddUPoint( 0, ptSbLeft) ; + dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSbLeft ; + ptRot.Rotate( ptStart, vtNorm, i * ( dAng / dAngStep)) ; + plLoopB.AddUPoint( i, ptRot) ; + } + plLoopB.AddUPoint( dAngStep, ptSbRight) ; // ultimo punto + // creo la superficie Top Bevel + PtrOwner pStmbTop_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmbTop_start) || + ! pStmbTop_start->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) || + ! pStmbTop_start->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbTop_start) ; + // creo la superificie Bottom Bevel + PtrOwner pStmbBottom_start( CloneSurfTriMesh( pStmbTop_start)) ; + if ( IsNull( pStmbBottom_start) || ! pStmbBottom_start->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbBottom_start) ; + // creo la superficie perpendicolare alla guida + PolyLine plLoopB1 = plLoopB ; + plLoopB1.Mirror( ptCen, vtNorm) ; + PtrOwner pStmPerp_start( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp_start) || + ! pStmPerp_start->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) || + ! pStmPerp_start->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp_start) ; + // aggiungo il cap sulla fine + Point3d ptEnd ; + pGuide->GetEndPoint( ptEnd) ; + // calcolo l'angolo di rotazione per screwing faccia Top e Bottom + pCrvL->GetEndPoint( ptSLeft) ; + pCrvR->GetEndPoint( ptSRight) ; + vtLeft = ptSLeft - ptEnd ; + vtRight = ptSRight - ptEnd ; + dAng = ANG_STRAIGHT ; + vtRight.GetAngle( vtLeft, dAng) ; + vtRight.Normalize() ; + plLoop.Clear() ; + // creo il loop defininendo i punti + plLoop.AddUPoint( 0, ptSRight) ; + dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSRight ; + ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ; + plLoop.AddUPoint( i, ptRot) ; + } + plLoop.AddUPoint( dAngStep, ptSLeft) ; // ultimo punto + plLoop.AddUPoint( dAngStep + 1, ptSRight) ; // polyline chiusa + // creo la superficie Top + PtrOwner pStmTop_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmTop_end) || ! pStmTop_end->CreateByFlatContour( plLoop)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmTop_end) ; + // creo la superificie Bottom + PtrOwner pStmBottom_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmBottom_end) || + ! pStmBottom_end->CopyFrom( pStmTop_end) || + ! pStmBottom_end->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmBottom_end) ; + // calcolo l'angolo di rotazione per la faccia Top del bevel + ptEnd.Translate( - dBevelV * vtNorm) ; + pCrvLb->GetEndPoint( ptSbLeft) ; + pCrvRb->GetEndPoint( ptSbRight) ; + vtbLeft = ptSbLeft - ptEnd ; + vtbRight = ptSbRight - ptEnd ; + dAng = ANG_STRAIGHT ; + vtbRight.GetAngle( vtbLeft, dAng) ; + vtbRight.Normalize() ; + plLoop.EraseLastUPoint() ; // apro il loop + // creo il loop defininendo i punti + plLoopB.Clear() ; + plLoopB.AddUPoint( 0, ptSbRight) ; + dAngStep = ceil( dAng / dStepRotDeg) ; // primo punto + for ( int i = 1 ; i < dAngStep ; ++ i) { + Point3d ptRot = ptSbRight ; + ptRot.Rotate( ptEnd, vtNorm, i * ( dAng / dAngStep)) ; + plLoopB.AddUPoint( i, ptRot) ; + } + plLoopB.AddUPoint( dAngStep, ptSbLeft) ; // ultimo punto + // creo la superficie Top Bevel + PtrOwner pStmbTop_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmbTop_end) || + ! pStmbTop_end->CreateByTwoCurves( plLoop, plLoopB, ISurfTriMesh::RLT_MINDIST) || + ! pStmbTop_end->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbTop_end) ; + // creo la superificie Bottom Bevel + PtrOwner pStmbBottom_end( CloneSurfTriMesh( pStmbTop_end)) ; + if ( IsNull( pStmbBottom_end) || ! pStmbBottom_end->Mirror( ptCen, vtNorm)) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmbBottom_end) ; + // creo la superficie perpendicolare alla guida + plLoopB1 = plLoopB ; + plLoopB1.Mirror( ptCen, vtNorm) ; + PtrOwner pStmPerp_end( CreateSurfTriMesh()) ; + if ( IsNull( pStmPerp_end) || + ! pStmPerp_end->CreateByTwoCurves( plLoopB, plLoopB1, ISurfTriMesh::RLT_MINDIST) || + ! pStmPerp_end->Invert()) + return nullptr ; + stmSoup.AddSurfTriMesh( *pStmPerp_end) ; } // completo unione e recupero la superficie risultante if ( ! stmSoup.End()) @@ -738,6 +939,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub return Release( pSTM) ; } + //------------------------------------------------------------------------------- ISurfTriMesh* GetSurfTriMeshRectSwept( double dDimH, double dDimV, double dBevelH, double dBevelV, const ICurve* pGuide, int nCapType, double dLinTol) diff --git a/VolZmap.cpp b/VolZmap.cpp index 352d434..2eb7355 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -26,7 +26,6 @@ #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EgtNumUtils.h" #include "/EgtDev/Include/EGkIntersLineSurfTm.h" -#include "/EgtDev/Include/EGkIntersLineSurfTm.h" #include #include diff --git a/VolZmapCreation.cpp b/VolZmapCreation.cpp index b5abb62..4fefdee 100644 --- a/VolZmapCreation.cpp +++ b/VolZmapCreation.cpp @@ -647,7 +647,6 @@ VolZmap::AddMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, const } int nInt = int( IntersectionResults.size()) ; // numero di intersezioni valide - int nPos = j * m_nNx[nMap] + i ; // posizione del dexel corrente bool bInside = false ; // Flag entrata/uscita per tratto di retta Point3d ptIn ; Vector3d vtInN ;