Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cfd283f26 | |||
| 1f47402215 | |||
| 55e2983991 | |||
| 7c85ea2d43 | |||
| 1c49379ee1 | |||
| 481d81a8d2 | |||
| 68e25e10e8 | |||
| 88410333e9 | |||
| 6bbedc812f | |||
| 4e6dd05aa9 | |||
| a5684b2bf3 | |||
| 119bbe0bcb | |||
| 35b903e8a0 | |||
| 979597084d | |||
| 02742ee80f | |||
| a2bcc4d682 | |||
| cbd487e4ff | |||
| 37aaa98df6 | |||
| 2dcaa57aa3 | |||
| ba7379e752 | |||
| 6646aee01c | |||
| 7f8382f1b8 | |||
| 4bcdb03598 | |||
| 68e9be7901 | |||
| 9e3bac4a68 | |||
| 1fee7b8e49 | |||
| f668d7ac11 | |||
| 4a1c13154f | |||
| 68a9848748 | |||
| f5059166ed | |||
| ad7f209fc9 | |||
| 8b5bfb6e19 | |||
| 1efd17f6ee | |||
| b8caeb49e0 | |||
| a9fc259745 | |||
| bbc98fe282 | |||
| a445ddd89b | |||
| e874b2eb36 | |||
| a45faa4793 | |||
| 344f0da7ff | |||
| cea869c6ee | |||
| 8ad2887c38 | |||
| 2b1d2a512d | |||
| a55770d702 | |||
| 2e4b1cdd40 | |||
| 3ffc0b40d8 | |||
| cd2cde40da | |||
| efc656a72c | |||
| e1eb139aee | |||
| e7d25b2d0e | |||
| ce05ce577c | |||
| ae2cac48d1 | |||
| 37e9a05347 | |||
| 02cb8a0d3c | |||
| 6942f5fc23 | |||
| 6c4bf3f05a | |||
| 4bc8590ce9 | |||
| 5b68e33d1f | |||
| a70f7ee9c9 | |||
| 95a070413a | |||
| 223489e80d | |||
| f6a535d94c | |||
| dbc3e7d2bf | |||
| a3d44261bb | |||
| 9220fd568f | |||
| 17346e1b42 | |||
| c95ef6764d | |||
| d0f2d56bdb | |||
| fb037f2f2a | |||
| 2d94dddccb | |||
| d2d025a594 | |||
| 64abf640f6 | |||
| cb2b63320a | |||
| 951d3781d6 | |||
| 27bd0e579e | |||
| ff7d564de8 | |||
| a27b9e871a | |||
| eb497cbd39 | |||
| dd3091fc13 | |||
| 69d463713c | |||
| 5e918ff3aa | |||
| b4522c712d | |||
| fa9a9e89cb | |||
| d51a0d2258 | |||
| 580230b38b | |||
| 4b24906d2e | |||
| 2094a1cc0d | |||
| b8b639699a | |||
| 0b86c4f72b | |||
| 5c93384690 | |||
| b77db4a5bc | |||
| c704d94829 | |||
| 0373021b7a | |||
| 6de856b3e1 | |||
| a231d8f26c | |||
| 745a7eb38c | |||
| 78c40ebca7 | |||
| a39af1c3a3 | |||
| c2a0f9dff1 | |||
| 6be67258d2 | |||
| 6c76943bf4 | |||
| 9306f5be9d | |||
| 944ce79776 | |||
| 313c735956 | |||
| 007ed1701c | |||
| 7385709bb4 | |||
| da4cd4c482 | |||
| dee744725c | |||
| 2aca943de4 | |||
| 25f6bae120 | |||
| c92d841011 | |||
| 398c8c430a | |||
| 79dc8f8fc2 | |||
| 1545bc07cd | |||
| 44edef378a | |||
| 679efc22e8 | |||
| 1076dc54dc | |||
| e091f253d0 | |||
| 3206961b88 | |||
| 48b2029d19 | |||
| a2ca0ac6f7 | |||
| 4155dd3e5a | |||
| 98c576afe0 | |||
| ae8f80d6e9 | |||
| 9b933bd26d | |||
| baa8736276 | |||
| c75a7e9514 | |||
| 233f64e68f | |||
| da7ebd6f61 | |||
| 8db1765505 | |||
| 5d2e1ff608 | |||
| a9f8ef2ff3 | |||
| a1c448d8dd | |||
| 25d53338c2 | |||
| b3ebb35d01 | |||
| 1ad96ce8ca | |||
| 36422c43b3 |
+2
-2
@@ -151,11 +151,11 @@ MyAdjustLoops( ICurve* pCurve, ICURVEPLIST& CrvLst)
|
||||
else {
|
||||
double dParA = vIccInfo[i].IciA[0].dU ;
|
||||
double dParB = vIccInfo[i].IciB[0].dU ;
|
||||
if ( abs( dParA - dEnd) < EPS_SMALL)
|
||||
if ( dParA > dParB)
|
||||
swap( dParA, dParB) ;
|
||||
// verifico se uno dei due intervalli dà origine ad un tratto trascurabile
|
||||
PtrOwner<ICurve> pCrv1( pMyCrv->CopyParamRange( dParA, dParB)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
PtrOwner<ICurve> pCrv2( pMyCrv->CopyParamRange( dParB, dParA)) ;
|
||||
double dArea1 = 0, dArea2 = 0 ;
|
||||
if ( ! IsNull( pCrv1))
|
||||
pCrv1->GetAreaXY( dArea1) ;
|
||||
|
||||
@@ -140,16 +140,20 @@ MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
if ( scInfoCurr.nType == SCI_LINE_LINE || scInfoCurr.nType == SCI_PNT_LINE) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
}
|
||||
else if ( dNewLenXY < dPrevLenXY) {
|
||||
m_SCollInfo = scInfoCurr ;
|
||||
m_SCollInfo.nChunkM = j ;
|
||||
m_SCollInfo.nLoopM = 0 ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = i ;
|
||||
m_SCollInfo.nLoopF = 0 ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
|
||||
@@ -30,7 +30,7 @@ class MyCAvSimpleSurfFrMove
|
||||
const SCollInfo& GetSCollInfo()
|
||||
{ return m_SCollInfo ;}
|
||||
|
||||
private :
|
||||
protected :
|
||||
bool TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2,
|
||||
const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) ;
|
||||
bool TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
@@ -40,7 +40,7 @@ class MyCAvSimpleSurfFrMove
|
||||
bool RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2,
|
||||
const Point3d& ptCen, double& dAng) ;
|
||||
|
||||
private :
|
||||
protected :
|
||||
const SurfFlatRegion* m_pRegM ;
|
||||
const SurfFlatRegion* m_pRegF ;
|
||||
SCollInfo m_SCollInfo ;
|
||||
|
||||
@@ -0,0 +1,257 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2026-2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CASurfFrMove.cpp Data : 26.03.2026 Versione : 3.1c7
|
||||
// Contenuto : Implementazione delle funzioni di movimento per SurfFlatRegion
|
||||
// senza collisione con altri oggetti dello stesso tipo e nello
|
||||
// stesso piano o in piani paralleli.
|
||||
//
|
||||
//
|
||||
// Modifiche : 26.03.2026 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "CAvSurfFrMove.h"
|
||||
#include "SurfFlatRegion.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersLineArc.h"
|
||||
#include "GeoConst.h"
|
||||
#include "/EgtDev/Include/EGkCAvSurfFrMove.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// CASurfFrMove
|
||||
//----------------------------------------------------------------------------
|
||||
CAvSurfFrMove::CAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF)
|
||||
{
|
||||
// salvo puntatori alle regioni
|
||||
m_pRegM = &SfrM ;
|
||||
m_pRegF = &SfrF ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
{
|
||||
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
|
||||
m_CollInfo.nType = SCI_NONE ;
|
||||
if ( ! ScdMove.Translate( vtDir, dLen))
|
||||
return false ;
|
||||
m_CollInfo = ScdMove.GetCollInfo() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
|
||||
{
|
||||
MyCAvSurfFrMove ScdMove( *m_pRegM, *m_pRegF) ;
|
||||
m_CollInfo.nType = SCI_NONE ;
|
||||
return ScdMove.Rotate( ptCen, dAng) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MyCAvSurfFrMove::Translate( const Vector3d& vtDir, double& dLen)
|
||||
{
|
||||
// verifico validità regioni
|
||||
if ( m_pRegM == nullptr || m_pRegF == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// reset info di collisione
|
||||
m_SCollInfo.nType = SCI_NONE ;
|
||||
|
||||
// porto il vettore di movimento nel riferimento intrinseco e ne annullo la componente Z
|
||||
Vector3d vtDirL = vtDir ;
|
||||
vtDirL.ToLoc( m_pRegM->m_frF) ;
|
||||
vtDirL.z = 0 ;
|
||||
double dLenXY = vtDirL.Len() ;
|
||||
if ( dLenXY < EPS_SMALL)
|
||||
return true ;
|
||||
vtDirL /= dLenXY ;
|
||||
dLenXY *= dLen ;
|
||||
double dNewLenXY = dLenXY ;
|
||||
|
||||
// ciclo sui chunk della seconda superficie
|
||||
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
|
||||
// ciclo sui bordi dei chunk
|
||||
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
|
||||
|
||||
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
|
||||
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
|
||||
else {
|
||||
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
|
||||
|
||||
// ciclo sui chunk della prima superficie
|
||||
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
|
||||
// ciclo sui bordi del chunk
|
||||
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
|
||||
|
||||
// per CAv non ha senso confrontare due loop interni tra di loro.
|
||||
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
|
||||
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
|
||||
if ( nLF > 0 && nLM > 0)
|
||||
continue ;
|
||||
|
||||
// curva corrente del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
|
||||
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
|
||||
|
||||
// verifico la collisione tra le entità dei loop esterni dei due chunk
|
||||
int k = 0 ;
|
||||
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
|
||||
while ( pCrv1 != nullptr) {
|
||||
int l = 0 ;
|
||||
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
|
||||
while ( pCrv2 != nullptr) {
|
||||
SCollInfo cInfoCurr ;
|
||||
double dPrevLenXY = dNewLenXY ;
|
||||
if ( ! TranslateCurveNoCollisionCurve( pCrv1, pCrv2, vtDirL, dNewLenXY, cInfoCurr))
|
||||
return false ;
|
||||
if ( abs( dNewLenXY - dPrevLenXY) < EPS_SMALL) {
|
||||
if ( cInfoCurr.nType == SCI_LINE_LINE || cInfoCurr.nType == SCI_PNT_LINE) {
|
||||
m_SCollInfo = cInfoCurr ;
|
||||
m_SCollInfo.nChunkM = nCM ;
|
||||
m_SCollInfo.nLoopM = nLM ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = nCF ;
|
||||
m_SCollInfo.nLoopF = nLF ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
}
|
||||
else if ( dNewLenXY < dPrevLenXY) {
|
||||
m_SCollInfo = cInfoCurr ;
|
||||
m_SCollInfo.nChunkM = nCM ;
|
||||
m_SCollInfo.nLoopM = nLM ;
|
||||
m_SCollInfo.nCrvM = k ;
|
||||
m_SCollInfo.nChunkF = nCF ;
|
||||
m_SCollInfo.nLoopF = nLF ;
|
||||
m_SCollInfo.nCrvF = l ;
|
||||
}
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
++ l ;
|
||||
}
|
||||
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
|
||||
++ k ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se da limitare il movimento
|
||||
if ( dNewLenXY < dLenXY - EPS_SMALL)
|
||||
dLen *= dNewLenXY / dLenXY ;
|
||||
|
||||
// porto i punti e le direzioni di SCollInfo da intrinseco a locale della prima regione
|
||||
if ( m_SCollInfo.nType != SCI_NONE) {
|
||||
m_SCollInfo.ptP1.ToGlob( m_pRegM->m_frF) ;
|
||||
m_SCollInfo.vtDirM.ToGlob( m_pRegM->m_frF) ;
|
||||
m_SCollInfo.vtDirF.ToGlob( m_pRegM->m_frF) ;
|
||||
}
|
||||
if ( m_SCollInfo.nType == SCI_LINE_LINE)
|
||||
m_SCollInfo.ptP2.ToGlob( m_pRegM->m_frF) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
MyCAvSurfFrMove::Rotate( const Point3d& ptCen, double& dAng)
|
||||
{
|
||||
// verifico validità regioni
|
||||
if ( m_pRegM == nullptr || m_pRegF == nullptr)
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_pRegM->m_frF.VersZ(), m_pRegF->m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// reset info di collisione
|
||||
m_SCollInfo.nType = SCI_NONE ;
|
||||
|
||||
// porto il centro di rotazione nel riferimento intrinseco e ne annullo la componente Z
|
||||
Point3d ptCenL = ptCen ;
|
||||
ptCenL.ToLoc( m_pRegM->m_frF) ;
|
||||
ptCenL.z = 0 ;
|
||||
if ( abs( dAng) < EPS_ANG_SMALL)
|
||||
return true ;
|
||||
double dNewAng = dAng ;
|
||||
|
||||
// ciclo sui chunk della seconda superficie
|
||||
for ( int nCF = 0 ; nCF < m_pRegF->GetChunkCount() ; ++ nCF) {
|
||||
// ciclo sui bordi del Chunk
|
||||
for ( int nLF = 0 ; nLF < m_pRegF->GetLoopCount( nCF) ; ++ nLF) {
|
||||
|
||||
// curva corrente del chunk della seconda regione in locale nel riferimento intrinseco della prima
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_pRegM->m_frF, m_pRegF->m_frF))
|
||||
pCrv2Loc = m_pRegF->GetMyLoop( nCF, nLF) ;
|
||||
else {
|
||||
pCopyCrv.Set( m_pRegF->GetMyLoop( nCF, nLF)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_pRegF->m_frF, m_pRegM->m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
const CurveComposite* pCompo2 = GetBasicCurveComposite( pCrv2Loc) ;
|
||||
|
||||
// ciclo sui chunk della prima superficie
|
||||
for ( int nCM = 0 ; nCM < m_pRegM->GetChunkCount() ; ++ nCM) {
|
||||
// ciclo sui bordi del chunk
|
||||
for ( int nLM = 0 ; nLM < m_pRegM->GetLoopCount( nCM) ; ++ nLM) {
|
||||
|
||||
// per CAv non ha senso confrontare due loop interni tra di loro.
|
||||
// posso confrontatare - due loop esterni (come per la CAvSimpleSurfFrMove)
|
||||
// - un loop esterno con uno interno (nel caso in cui un Chunk sia contenuto dentro un isola)
|
||||
if ( nLF > 0 && nLM > 0)
|
||||
continue ;
|
||||
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = m_pRegM->GetMyLoop( nCM, nLM) ;
|
||||
const CurveComposite* pCompo1 = GetBasicCurveComposite( pCrv1Loc) ;
|
||||
|
||||
// verifico la collisione tra le entità dei loop esterni dei due chunk
|
||||
const ICurve* pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetFirstCurve() : pCrv1Loc) ;
|
||||
while ( pCrv1 != nullptr) {
|
||||
const ICurve* pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetFirstCurve() : pCrv2Loc) ;
|
||||
while ( pCrv2 != nullptr) {
|
||||
if ( ! RotateCurveNoCollisionCurve( pCrv1, pCrv2, ptCenL, dNewAng))
|
||||
return false ;
|
||||
pCrv2 = ( pCompo2 != nullptr ? pCompo2->GetNextCurve() : nullptr) ;
|
||||
}
|
||||
pCrv1 = ( pCompo1 != nullptr ? pCompo1->GetNextCurve() : nullptr) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se da limitare il movimento
|
||||
if ( ( dAng > 0 && dNewAng < dAng - EPS_ANG_SMALL) ||
|
||||
( dAng < 0 && dNewAng > dAng + EPS_ANG_SMALL))
|
||||
dAng = dNewAng ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2015-2018
|
||||
//----------------------------------------------------------------------------
|
||||
// File : CAvSurfFrMove.h Data : 27.04.18 Versione : 3.1c7
|
||||
// Contenuto : Dich.ne classe privata per movimento di superfici flat region
|
||||
// nel loro piano evitando collisioni
|
||||
//
|
||||
// Modifiche : 26.03.2026 RE Creazione modulo.
|
||||
//
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "CAvSimpleSurfFrMove.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
class MyCAvSurfFrMove : public MyCAvSimpleSurfFrMove
|
||||
{
|
||||
public :
|
||||
MyCAvSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) :
|
||||
MyCAvSimpleSurfFrMove( SfrM, SfrF) {} ;
|
||||
|
||||
public :
|
||||
bool Translate( const Vector3d& vtDir, double& dLen) ;
|
||||
bool Rotate( const Point3d& ptCen, double& dAng) ;
|
||||
const SCollInfo& GetCollInfo()
|
||||
{ return m_SCollInfo ; }
|
||||
} ;
|
||||
+2
-4
@@ -2440,12 +2440,10 @@ CAvDiskTriangle( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDis
|
||||
// Allontanamento dall'interno
|
||||
double dEscapeDist = max( DiskTriaInteriorEscapeDistGenMot( ptDiskCen, vtDiskAx, dDiskRad, trTria, vtMove), 0.) ;
|
||||
// Allontanamento dalla frontiera
|
||||
Vector3d vtMoveOrt = vtMove - vtMove * vtDiskAx * vtDiskAx ;
|
||||
Vector3d vtMoveOrt = OrthoCompo( vtMove, vtDiskAx) ;
|
||||
vtMoveOrt.Normalize() ;
|
||||
Frame3d DiskFrame ;
|
||||
Vector3d vtJ = vtDiskAx ^ vtMoveOrt ;
|
||||
vtJ.Normalize() ;
|
||||
DiskFrame.Set( ptDiskCen, vtMoveOrt, vtJ, vtDiskAx) ;
|
||||
DiskFrame.Set( ptDiskCen, vtDiskAx, vtMoveOrt) ;
|
||||
Triangle3d trTriaLoc = trTria ;
|
||||
Vector3d vtMoveLoc = vtMove ;
|
||||
trTriaLoc.ToLoc( DiskFrame) ;
|
||||
|
||||
+970
-473
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -169,7 +169,7 @@ ChainCurves::GetChainFromPoint( const Point3d& ptStart, const Vector3d& vtStart,
|
||||
ptCurr = bEquiv ? m_vCrvData[nId].ptEnd : m_vCrvData[nId].ptStart ;
|
||||
vtCurr = bEquiv ? m_vCrvData[nId].vtEnd : - m_vCrvData[nId].vtStart ;
|
||||
// verifico se sono arrivato al punto di chiusura
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, m_dToler)) {
|
||||
if ( AreSamePointEpsilon( ptCurr, ptStop, 0.5 * EPS_SMALL)) {
|
||||
bStopped = true ;
|
||||
break ;
|
||||
}
|
||||
|
||||
+173
-5
@@ -25,19 +25,24 @@
|
||||
#include "IntersLineLine.h"
|
||||
#include "/EgtDev/Include/EGkDistPointCurve.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EGkUiUnits.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkCurveByInterp.h"
|
||||
#include "/EgtDev/Include/EGkChainCurves.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#define EIGEN_NO_IO
|
||||
#include "/EgtDev/Extern/Eigen/Dense"
|
||||
|
||||
#define SAVEAPPROX 0
|
||||
#define SAVECURVEPASSED 0
|
||||
#define SAVELINEARAPPROX 0
|
||||
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX
|
||||
#define SAVESYNCLINES 0
|
||||
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX || SAVESYNCLINES
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
static int nCrvPassed = 0 ;
|
||||
std::vector<IGeoObj*> VT ;
|
||||
std::vector<Color> VC ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
@@ -1595,8 +1600,10 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
|
||||
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, const Vector3d& vtStart, const Vector3d& vtEnd)
|
||||
{
|
||||
if ( pCrv == nullptr || ! pCrv->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
#if SAVECURVEPASSED
|
||||
SaveGeoObj( pCrv->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\CurveDaApprossimare\\"+ToString(nCrvPassed) + ".nge") ;
|
||||
@@ -1668,6 +1675,10 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
|
||||
VCT3DVECTOR vPrevDer ;
|
||||
VCT3DVECTOR vNextDer ;
|
||||
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
|
||||
if ( ! AreSameVectorExact(vtStart, V_NULL)) {
|
||||
vNextDer[0] = vtStart ;
|
||||
vPrevDer.back() = vtEnd ;
|
||||
}
|
||||
|
||||
int nOverSampling = ssize( vPntOverSampling) ;
|
||||
vParam.resize( nOverSampling) ;
|
||||
@@ -1718,7 +1729,11 @@ CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int
|
||||
// controllo l'errore effettivo campionando più finemente
|
||||
double dLenOri = 0 ; pCrvOri->GetLength( dLenOri) ;
|
||||
double dLenNew = 0 ; pCrvNew->GetLength( dLenNew) ;
|
||||
dErr = 0 ;
|
||||
Point3d ptStart0 ; pCrvOri->GetStartPoint( ptStart0) ;
|
||||
Point3d ptStart1 ; pCrvNew->GetStartPoint( ptStart1) ;
|
||||
Point3d ptEnd0 ; pCrvOri->GetEndPoint( ptEnd0) ;
|
||||
Point3d ptEnd1 ; pCrvNew->GetEndPoint( ptEnd1) ;
|
||||
dErr = max( Dist( ptStart1, ptStart0), Dist( ptEnd1, ptEnd0)) ;
|
||||
for ( int i = 1 ; i < nPoints ; ++i) {
|
||||
Point3d ptOri, ptNew ;
|
||||
double dParOri, dParNew ;
|
||||
@@ -2687,3 +2702,156 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2)
|
||||
{
|
||||
pCrv->GetParamAtLength( dLen, dUStep2) ;
|
||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||
pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||
double dDist = Dist( ptCurr1, ptStep2) ;
|
||||
return (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
|
||||
double dLenPrev2, double& dLenCurr2, double dLen2)
|
||||
{
|
||||
Point3d ptCurr1 ;
|
||||
Vector3d vtCurr1 ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
// --- Piano di taglio per punto a minima distanza
|
||||
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
|
||||
int nIndParCloser = - 1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo) && aInfo.Ici[0].dU > dUPrev2) {
|
||||
if ( nIndParCloser == -1)
|
||||
nIndParCloser = nInfo ;
|
||||
double dSqDist = SqDist( ptCurr1, aInfo.Ici[0].ptI) ;
|
||||
if ( dSqDist < dSqMinDist) {
|
||||
dSqMinDist = dSqDist ;
|
||||
nIndPointCloser = nInfo ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurr2 = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurr2 = ( SqDist( ptCurr1, aInfoPt.Ici[0].ptI) < SqDist( ptCurr1, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
#if SAVESYNCLINES
|
||||
VT.clear() ; VC.clear() ;
|
||||
VT.emplace_back( pCrvEdge1->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
VT.emplace_back( pCrvEdge2->Clone()) ; VC.emplace_back( Color( 0, 128, 255)) ;
|
||||
PtrOwner<IGeoPoint3d> ptCurr1Geo( CreateGeoPoint3d()) ; ptCurr1Geo->Set( ptCurr1) ;
|
||||
VT.emplace_back( Release( ptCurr1Geo)) ; VC.emplace_back( BLUE) ;
|
||||
PtrOwner<IGeoPoint3d> ptPar( CreateGeoPoint3d()) ; ptPar->Set( aInfoPar.Ici[0].ptI) ;
|
||||
PtrOwner<IGeoPoint3d> ptPt( CreateGeoPoint3d()) ; ptPt->Set( aInfoPt.Ici[0].ptI) ;
|
||||
VT.emplace_back( Release( ptPar)) ; VC.emplace_back( LIME) ;
|
||||
VT.emplace_back( Release( ptPt)) ; VC.emplace_back( FUCHSIA) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\bezier\\ruled\\TestTrimmingPlane.nge") ;
|
||||
#endif
|
||||
}
|
||||
// Verifico di non essermi allontanato troppo
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkPlane = ( dLen < dLenPrev2 + 2. * dMyDist) ;
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( ptCurr1, *pCrvEdge2) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( dUPrev2, dUCurr2, nFlag) && dUCurr2 > dUPrev2) ;
|
||||
// Verifico di non essermi allontanato troppo
|
||||
if ( bOkMinDist) {
|
||||
double dLen ; pCrvEdge2->GetLengthAtParam( dUCurr2, dLen) ;
|
||||
bOkMinDist = ( dLen < dLenPrev2 + 2. * dMyDist) ;
|
||||
}
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Aumento la distanza corrente del passo di campionamento
|
||||
double dLen = Clamp( dLenPrev2 + dMyDist, 0., dLen2) ;
|
||||
pCrvEdge2->GetParamAtLength( dLen, dUCurr2) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Recupero il punto corrente e la direzione tangente sul secondo bordo
|
||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
||||
Point3d ptCurr2 ;
|
||||
Vector3d vtCurr2 ;
|
||||
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
||||
vtCurr2.Normalize() ;
|
||||
|
||||
// Verifico se le direzioni tangenti sono tra di loro circa parallele
|
||||
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
|
||||
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
|
||||
double dSearchLen = dMyDist / 2 ;
|
||||
int NUM_STEP = 10 ;
|
||||
const double dCoeff = 0.1 ;
|
||||
double dCos = vtCurr1 * vtCurr2 ;
|
||||
double dDistCurr = Dist( ptCurr1, ptCurr2) ;
|
||||
double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ;
|
||||
double bUpdated = false ;
|
||||
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
|
||||
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
|
||||
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
|
||||
dSearchLen = dMyDist ;
|
||||
NUM_STEP = 20 ;
|
||||
}
|
||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
|
||||
|
||||
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
|
||||
DBLVECTOR vVal ;
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
||||
double dUStep2 ;
|
||||
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
|
||||
if ( vVal.back() < dMin) {
|
||||
dMin = vVal.back() ;
|
||||
dUCurr2 = dUStep2 ;
|
||||
}
|
||||
}
|
||||
DBLDBLVECTOR vInterv ;
|
||||
for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) {
|
||||
if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1])
|
||||
vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP,
|
||||
dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ;
|
||||
}
|
||||
if ( ssize( vInterv) != 0) {
|
||||
for ( int j = 0 ; j < ssize( vInterv) ; ++j) {
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ;
|
||||
double dUStep2 ;
|
||||
double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ;
|
||||
if ( dVal < dMin) {
|
||||
dUCurr2 = dUStep2 ;
|
||||
dMin = dVal ;
|
||||
bUpdated = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
|
||||
if ( bUpdated)
|
||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
||||
return true ;
|
||||
}
|
||||
+1
-1
@@ -35,4 +35,4 @@ bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ;
|
||||
ICurveBezier* ApproxCurveBezierWithSingleCubic( const ICurve* pCrv) ;
|
||||
Voronoi* GetCurveVoronoi( const ICurve& crvC) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
bool GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) ;
|
||||
+166
-1
@@ -1967,7 +1967,120 @@ CurveComposite::AddJoint( double dU)
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol)
|
||||
{
|
||||
int nCrvCount = GetCurveCount() ;
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
// salvo le vecchie curve e nel caso le ripristino
|
||||
int nPrevCrv = -1 ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
if ( nU >= 0)
|
||||
nPrevCrv = nU - 1 ;
|
||||
else if ( IsClosed())
|
||||
nPrevCrv = nCrvCount - 1 ;
|
||||
PtrOwner<CurveComposite> pOrigCrv( CreateBasicCurveComposite()) ;
|
||||
if ( nPrevCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nPrevCrv]->Clone()) ;
|
||||
// recupero il puntatore alla curva successiva (se esiste)
|
||||
int nNextCrv = -1 ;
|
||||
if ( nU < nCrvCount)
|
||||
nNextCrv = nU ;
|
||||
else if ( IsClosed())
|
||||
nNextCrv = 0 ;
|
||||
else
|
||||
nNextCrv = - 1 ;
|
||||
if ( nNextCrv >= 0)
|
||||
pOrigCrv->AddCurve( m_CrvSmplS[ nNextCrv]->Clone()) ;
|
||||
|
||||
int nCrvNmbr = GetCurveCount() ;
|
||||
int nFlagDel = DeletedCurve::NONE ;
|
||||
if ( ! ModifyJoint( nU, ptNewJoint, &nFlagDel))
|
||||
return false ;
|
||||
|
||||
bool bErasedSomeCrv = nCrvCount > GetCurveCount() ;
|
||||
bool bErasedPrev = ( nFlagDel == DeletedCurve::PREV) ;
|
||||
bool bErasedNext = ( nFlagDel == DeletedCurve::NEXT) ;
|
||||
if ( ( bErasedPrev && nNextCrv == -1) || ( bErasedNext && nPrevCrv == -1)) {
|
||||
// se sono su un estremo di una curva aperta e ho cancellato la sottocurva di estremità devo verificare che fosse più piccola della tolleranza
|
||||
if ( bErasedPrev && nNextCrv == -1) {
|
||||
Point3d ptOrigEnd ; pOrigCrv->GetEndPoint( ptOrigEnd) ;
|
||||
Point3d ptNewEnd ; GetEndPoint( ptNewEnd) ;
|
||||
if ( Dist( ptOrigEnd, ptNewEnd) > dTol)
|
||||
m_CrvSmplS.push_back( Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
if ( bErasedNext && nPrevCrv == -1) {
|
||||
Point3d ptOrigStart ; pOrigCrv->GetStartPoint( ptOrigStart) ;
|
||||
Point3d ptNewStart ; GetStartPoint( ptNewStart) ;
|
||||
if ( Dist( ptOrigStart, ptNewStart) > dTol)
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin(), Release( pOrigCrv)) ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
double dStart ;
|
||||
double dEnd ;
|
||||
if ( bErasedPrev) {
|
||||
dStart = nU ;
|
||||
dEnd = nNextCrv + 1 ;
|
||||
}
|
||||
else if ( bErasedNext) {
|
||||
dStart = nPrevCrv ;
|
||||
dEnd = nU ;
|
||||
if ( nU == 0)
|
||||
dStart -= 1 ;
|
||||
}
|
||||
else { // ! bErasedSomeCrv
|
||||
dStart = ( nPrevCrv != -1 ? nPrevCrv : 0) ;
|
||||
dEnd = ( nNextCrv != -1 ? nNextCrv + 1 : nCrvNmbr) ;
|
||||
}
|
||||
PtrOwner<ICurve> pNewCurve( CopyParamRange( dStart, dEnd)) ;
|
||||
double dErr = 0 ;
|
||||
if ( ! CalcApproxError( pOrigCrv, pNewCurve, dErr, 6) || dErr > dTol) {
|
||||
// se ho fallito il check o la variazione è superiore alla tolleranza richiesta, ripristino le curve originali
|
||||
if ( ! bErasedSomeCrv) {
|
||||
if ( nNextCrv != -1) {
|
||||
delete m_CrvSmplS[nNextCrv] ;
|
||||
m_CrvSmplS[nNextCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
if ( nPrevCrv != -1) {
|
||||
delete m_CrvSmplS[nPrevCrv] ;
|
||||
m_CrvSmplS[nPrevCrv] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ( bErasedNext) {
|
||||
int nPos = nU == 0 ? nPrevCrv - 1 : nU ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( false) ;
|
||||
nPos = 0 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
else {
|
||||
int nPos = nU == 0 ? nU : nPrevCrv ;
|
||||
delete m_CrvSmplS[nPos] ;
|
||||
if ( nU == 0) {
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
nPos = nCrvNmbr - 1 ;
|
||||
}
|
||||
else
|
||||
m_CrvSmplS[nPos] = pOrigCrv->RemoveFirstOrLastCurve( true) ;
|
||||
m_CrvSmplS.insert( m_CrvSmplS.begin() + nPos, pOrigCrv->RemoveFirstOrLastCurve( true)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel)
|
||||
{
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
@@ -1977,6 +2090,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
// verifico l'indice della giunzione
|
||||
if ( nU < 0 || nU > nCrvCount)
|
||||
return false ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NONE ;
|
||||
// recupero l'indice e il puntatore alla curva precedente (se esiste)
|
||||
int nPrevCrv = -1 ;
|
||||
if ( nU > 0)
|
||||
@@ -2005,6 +2120,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptStart, ptNewJoint)) {
|
||||
delete pPrevCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nPrevCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::PREV ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -2024,6 +2141,8 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint)
|
||||
if ( AreSamePointApprox( ptNewJoint, ptEnd)) {
|
||||
delete pNextCrv ;
|
||||
m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ;
|
||||
if ( pnFlagDel != nullptr)
|
||||
*pnFlagDel = DeletedCurve::NEXT ;
|
||||
}
|
||||
// altrimenti diventa un segmento di retta
|
||||
else {
|
||||
@@ -3858,3 +3977,49 @@ CurveComposite::GetOnlyPoint(Point3d& ptStart) const
|
||||
ptStart = m_ptStart ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
CurveComposite::ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurveToAdd, double dTolStartEnd, double dTolAlong)
|
||||
{
|
||||
// prendo il possesso e verifico la curva
|
||||
PtrOwner<ICurve> pNewCurve( pNewCurveToAdd) ;
|
||||
if ( IsNull( pNewCurve) || ! pNewCurve->IsValid())
|
||||
return false ;
|
||||
|
||||
// verifico lo stato
|
||||
if ( m_nStatus != OK)
|
||||
return false ;
|
||||
|
||||
// verifico l'indice sia sensato
|
||||
if ( nSubCrv < 0 || nSubCrv > GetCurveCount())
|
||||
return false ;
|
||||
|
||||
// verifico che start e end coincidano entro la tolleranza
|
||||
Point3d ptStart ; m_CrvSmplS[nSubCrv]->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; m_CrvSmplS[nSubCrv]->GetEndPoint( ptEnd) ;
|
||||
Point3d ptNewStart ; pNewCurve->GetStartPoint( ptNewStart) ;
|
||||
Point3d ptNewEnd ; pNewCurve->GetEndPoint( ptNewEnd) ;
|
||||
if ( ! AreSamePointApprox( ptStart, ptNewStart) || ! AreSamePointApprox( ptEnd, ptNewEnd)) {
|
||||
// se i punti di inizio e fine non sono entro EPS_SMALL ma sono entro la tolleranza passata allora modifico la curva da aggiungere
|
||||
if ( AreSamePointEpsilon( ptStart, ptNewStart, dTolStartEnd) && AreSamePointEpsilon( ptEnd, ptNewEnd, dTolStartEnd)) {
|
||||
if ( ! pNewCurve->ModifyStart( ptStart) || ! pNewCurve->ModifyEnd( ptEnd))
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
// se presente una tolleranza lungo la curva controllo che sia rispettata
|
||||
if ( dTolAlong < INFINITO) {
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( m_CrvSmplS[nSubCrv], pNewCurve, dErr, 20) ;
|
||||
if ( dErr > dTolAlong)
|
||||
return false ;
|
||||
}
|
||||
|
||||
delete m_CrvSmplS[nSubCrv] ;
|
||||
m_CrvSmplS[nSubCrv] = Release( pNewCurve) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
+8
-1
@@ -26,6 +26,9 @@ class Voronoi ;
|
||||
//----------------------------------------------------------------------------
|
||||
class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
{
|
||||
public :
|
||||
enum DeletedCurve { NONE = 0, PREV = 1, NEXT = 2 } ;
|
||||
|
||||
public : // IGeoObj
|
||||
~CurveComposite( void) override ;
|
||||
CurveComposite* Clone( void) const override ;
|
||||
@@ -156,7 +159,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool AddArc2P( const Point3d& ptOther, const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddArcTg( const Point3d& ptNew, bool bEndOrStart = true) override ;
|
||||
bool AddJoint( double dU) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint) override
|
||||
{ return ModifyJoint( nU, ptNewJoint, nullptr) ; }
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, double dTol) override ; // verifico se le curve interessate sono in tolleranza con la versione prima della modifica
|
||||
bool RemoveJoint( int nU) override ;
|
||||
bool MoveCurve( int nCrv, const Vector3d& vtMove) override ;
|
||||
bool ModifyCurveToArc( int nCrv, const Point3d& ptMid) override ;
|
||||
@@ -178,6 +183,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ;
|
||||
bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ;
|
||||
bool GetOnlyPoint( Point3d& ptStart) const override ;
|
||||
bool ReplaceSingleCurve( int nSubCrv, ICurve* pNewCurve, double dTolStartEnd, double dTolAlong = INFINITO) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
@@ -211,6 +217,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW
|
||||
bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET, double dMaxAngExt = ANG_RIGHT) ;
|
||||
bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ;
|
||||
bool CalcVoronoiObject( void) const ;
|
||||
bool ModifyJoint( int nU, const Point3d& ptNewJoint, int* pnFlagDel) ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2, IS_A_POINT = 3} ;
|
||||
|
||||
Binary file not shown.
@@ -284,6 +284,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="CalcDerivate.cpp" />
|
||||
<ClCompile Include="CAvSilhouetteSurfTm.cpp" />
|
||||
<ClCompile Include="CAvSimpleSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvSurfFrMove.cpp" />
|
||||
<ClCompile Include="CAvToolSurfTm.cpp" />
|
||||
<ClCompile Include="CAvToolTriangle.cpp" />
|
||||
<ClCompile Include="CDeBoxClosedSurfTm.cpp" />
|
||||
@@ -323,6 +324,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="OffsetCurve3d.cpp" />
|
||||
<ClCompile Include="Trimming.cpp" />
|
||||
<ClCompile Include="MultiGeomDB.cpp" />
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||
@@ -353,6 +355,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClInclude Include="..\Include\EGkSubtractProjectedFacesOnStmFace.h" />
|
||||
<ClInclude Include="..\Include\EGkSurfTriMeshAux.h" />
|
||||
<ClInclude Include="CAvSilhouetteSurfTm.h" />
|
||||
<ClInclude Include="CAvSurfFrMove.h" />
|
||||
<ClInclude Include="CDeBoxTria.h" />
|
||||
<ClInclude Include="CDeCapsTria.h" />
|
||||
<ClInclude Include="CDeConeFrustumTria.h" />
|
||||
|
||||
@@ -570,6 +570,15 @@
|
||||
<ClCompile Include="CalcDerivate.cpp">
|
||||
<Filter>File di origine\Geo</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CAvSurfFrMove.cpp">
|
||||
<Filter>File di origine\GeoCollisionAvoid</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="OffsetCurve3d.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
@@ -1256,6 +1265,9 @@
|
||||
<ClInclude Include="..\Include\EGkMultiGeomDB.h">
|
||||
<Filter>File di intestazione\Include</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CAvSurfFrMove.h">
|
||||
<Filter>File di intestazione</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="EgtGeomKernel.rc">
|
||||
|
||||
+88
-42
@@ -198,13 +198,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
// se coincidono U e ptInt tra A e B
|
||||
if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL &&
|
||||
AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) {
|
||||
// se non è alla fine di curva chiusa
|
||||
if ( ! bCrvAClosed || abs( m_Info[j].IciA[0].dU - dCrvBSpan) > EPS_SMALL)
|
||||
// elimino la seconda
|
||||
EraseOtherInfo( i, j) ;
|
||||
else
|
||||
// elimino la prima
|
||||
// se j è alla fine di curva chiusa
|
||||
// se j è alla fine di curva chiusa e la prima intersezione è di overlap con partenza dall'inizio ( compreso nel caso precedente)
|
||||
// oppure se i è all'inizio di curva chiusa e l'intersezione successiva a j è di overlap con lo stesso parametro
|
||||
if ( bCrvAClosed && (( abs( m_Info[j].IciA[0].dU - dCrvBSpan) < EPS_SMALL) ||
|
||||
( i == 0 && ssize(m_Info) > 2 && m_Info[i].IciA[0].dU < EPS_SMALL && m_Info[j+1].bOverlap && abs( m_Info[j].IciA[0].dU - m_Info[j+1].IciA[0].dU) < EPS_SMALL)))
|
||||
// elimino la prima
|
||||
EraseCurrentInfo( i, j) ;
|
||||
else
|
||||
// elimino la seconda
|
||||
EraseOtherInfo( i, j) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
@@ -394,7 +397,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
// caso NULL-NULL per corrente di prima curva
|
||||
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
|
||||
m_Info[j].IciA[kj].nNextTy = ICCT_NULL ;
|
||||
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
|
||||
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
|
||||
@@ -404,7 +406,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
// caso NULL-NULL per precedente di prima curva
|
||||
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciA[ki].nPrevTy = ICCT_NULL ;
|
||||
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
|
||||
@@ -571,7 +572,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
// caso NULL-NULL per corrente di seconda curva
|
||||
else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
|
||||
m_Info[j].IciB[kj].nNextTy = ICCT_NULL ;
|
||||
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
|
||||
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
|
||||
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
|
||||
@@ -581,7 +581,6 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
}
|
||||
// caso NULL-NULL per precedente di seconda curva
|
||||
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) {
|
||||
m_Info[i].IciB[ki].nPrevTy = ICCT_NULL ;
|
||||
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
|
||||
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
|
||||
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
|
||||
@@ -806,19 +805,36 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
INTVECTOR vNewOverlap ;
|
||||
// salvo eventuali incoerenze col precedente
|
||||
for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
|
||||
int kj = ( m_Info[j].bOverlap ? 1 : 0) ;
|
||||
bool bSpike = m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq ;
|
||||
if ( bSpike) {
|
||||
bSpike = abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ;
|
||||
}
|
||||
if ( (m_Info[j].IciA[kj].nNextTy == ICCT_NULL || m_Info[i].IciA[0].nPrevTy == ICCT_NULL || m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy) &&
|
||||
m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) {
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
if ( vIncoherenceWithPrev.empty() || vIncoherenceWithPrev.back() != i)
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
if ( bSpike) {
|
||||
// se ho uno spike sistemo anche il successivo
|
||||
int k = i == m_nNumInters - 1 ? -1 : i + 1 ;
|
||||
if ( k == -1 && bCrvAClosed)
|
||||
k = 0 ;
|
||||
|
||||
if ( k != -1)
|
||||
vIncoherenceWithPrev.push_back( k) ;
|
||||
}
|
||||
bCoherent = false ;
|
||||
}
|
||||
}
|
||||
// incoerenze sulla curva A
|
||||
if ( ! bCoherent) {
|
||||
for ( int i : vIncoherenceWithPrev) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int kj = m_Info[j].bOverlap ? 1 : 0 ;
|
||||
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
|
||||
int kj = ( m_Info[j].bOverlap ? 1 : 0) ;
|
||||
int nType = 0 ;
|
||||
CalcSide( j, i, &CCompoA, &CCompoB, true, nType) ;
|
||||
if ( nType != ICCT_ON) {
|
||||
@@ -840,21 +856,38 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
|
||||
vIncoherenceWithPrev.clear() ;
|
||||
// salvo eventuali incoerenze col precedente
|
||||
for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
|
||||
int ki = ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
|
||||
bool bSpike = m_Info[i].bOverlap && m_Info[j].bOverlap && m_Info[i].bCBOverEq != m_Info[j].bCBOverEq ;
|
||||
if ( bSpike) {
|
||||
bSpike = abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[0].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( m_Info[i].IciA[1].dU - m_Info[j].IciA[1].dU) < EPS_PARAM ;
|
||||
}
|
||||
if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[ki].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[ki].nPrevTy) &&
|
||||
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[ki].nPrevTy != ICCT_SPK) {
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
if ( vIncoherenceWithPrev.empty() || vIncoherenceWithPrev.back() != i)
|
||||
vIncoherenceWithPrev.push_back( i) ;
|
||||
if ( bSpike) {
|
||||
// se ho uno spike sistemo anche il successivo
|
||||
int k = ( i == m_nNumInters - 1 ? -1 : i + 1) ;
|
||||
if ( k == -1 && bCrvBClosed)
|
||||
k = 0 ;
|
||||
|
||||
if ( k != -1)
|
||||
vIncoherenceWithPrev.push_back( k) ;
|
||||
}
|
||||
bCoherent = false ;
|
||||
}
|
||||
}
|
||||
// incoerenze sulla curva B
|
||||
if ( ! bCoherent) {
|
||||
for ( int i : vIncoherenceWithPrev) {
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int ki = m_Info[i].bOverlap && ! m_Info[i].bCBOverEq ? 1 : 0 ;
|
||||
int kj = m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0 ;
|
||||
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
|
||||
int ki = ( m_Info[i].bOverlap && !m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
int kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
|
||||
int nType = 0 ;
|
||||
CalcSide( j, i, &CCompoB, &CCompoA, false, nType) ;
|
||||
if ( nType != ICCT_ON) {
|
||||
@@ -886,13 +919,19 @@ IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICu
|
||||
const IntCrvCrvInfo& Icci1 = m_Info[j] ;
|
||||
const IntCrvCrvInfo& Icci2 = m_Info[i] ;
|
||||
// calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori
|
||||
int kj = Icci1.bOverlap ? 1 : 0 ;
|
||||
int ki = 0 ;
|
||||
int kj = ( Icci1.bOverlap ? 1 : 0) ;
|
||||
if ( ! bCrvAOrB) {
|
||||
ki = ( m_Info[i].bOverlap && !m_Info[i].bCBOverEq ? 1 : 0) ;
|
||||
kj = ( m_Info[j].bOverlap && m_Info[j].bCBOverEq ? 1 : 0) ;
|
||||
}
|
||||
|
||||
double dU = 0 ;
|
||||
bool bPrevIsBefore = true ;
|
||||
if ( bCrvAOrB) {
|
||||
// se precedente minore del successivo faccio la media
|
||||
if ( Icci1.IciA[kj].dU < Icci2.IciA[0].dU)
|
||||
dU = ( Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ;
|
||||
if ( Icci1.IciA[kj].dU < Icci2.IciA[ki].dU)
|
||||
dU = ( Icci2.IciA[ki].dU + Icci1.IciA[kj].dU) / 2 ;
|
||||
// altrimenti guardo tra lo start e il successivo
|
||||
else {
|
||||
bPrevIsBefore = false ;
|
||||
@@ -908,8 +947,8 @@ IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICu
|
||||
}
|
||||
else {
|
||||
// se precedente minore del successivo faccio la media
|
||||
if ( Icci1.IciB[kj].dU < Icci2.IciB[0].dU)
|
||||
dU = ( Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ;
|
||||
if ( Icci1.IciB[kj].dU < Icci2.IciB[ki].dU)
|
||||
dU = ( Icci2.IciB[ki].dU + Icci1.IciB[kj].dU) / 2 ;
|
||||
// altrimenti guardi tra lo start e il successivo
|
||||
else {
|
||||
bPrevIsBefore = false ;
|
||||
@@ -937,24 +976,24 @@ IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICu
|
||||
bool bIsOn = false ;
|
||||
if ( bCrvAOrB) {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciA[0].dU + dFactor * Icci1.IciA[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[0].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciA[ki].dU + dFactor * Icci1.IciA[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[ki].dU + 2 * dFactor * Icci1.IciA[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciA[0].dU > 2 * EPS_SMALL){
|
||||
vdU[0] = ( Icci2.IciA[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciA[0].dU + 0.) * 2 * dFactor ;
|
||||
else if ( Icci2.IciA[ki].dU > 2 * EPS_SMALL){
|
||||
vdU[0] = ( Icci2.IciA[ki].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciA[ki].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
}
|
||||
else {
|
||||
if ( bPrevIsBefore) {
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciB[0].dU + dFactor * Icci1.IciB[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[0].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
|
||||
vdU[0] = ( 1 - dFactor) * Icci2.IciB[ki].dU + dFactor * Icci1.IciB[kj].dU ;
|
||||
vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[ki].dU + 2 * dFactor * Icci1.IciB[kj].dU ;
|
||||
}
|
||||
else if ( Icci2.IciB[0].dU > 2 * EPS_SMALL) {
|
||||
vdU[0] = ( Icci2.IciB[0].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciB[0].dU + 0.) * 2 * dFactor ;
|
||||
else if ( Icci2.IciB[ki].dU > 2 * EPS_SMALL) {
|
||||
vdU[0] = ( Icci2.IciB[ki].dU + 0.) * dFactor ;
|
||||
vdU[1] = ( Icci2.IciB[ki].dU + 0.) * 2 * dFactor ;
|
||||
}
|
||||
else
|
||||
bIsOn = true ;
|
||||
@@ -1023,8 +1062,11 @@ IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICu
|
||||
bool
|
||||
IntersCrvCompoCrvCompo::MergeNewOverlap( int i, bool bCrvAOrB)
|
||||
{
|
||||
if ( i >= ssize(m_Info))
|
||||
return false ;
|
||||
|
||||
// faccio il merge col precedente
|
||||
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
|
||||
int j = ( i == 0 ? m_nNumInters - 1 : i - 1) ;
|
||||
if ( m_Info[j].bOverlap) {
|
||||
m_Info[i].IciA[0] = m_Info[j].IciA[0] ;
|
||||
m_Info[i].IciB[0] = m_Info[j].IciB[0] ;
|
||||
@@ -1163,21 +1205,25 @@ SortGreaterB( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2)
|
||||
dU1 = aInfo1.IciB[0].dU ;
|
||||
if ( aInfo1.bOverlap) {
|
||||
// caso normale
|
||||
if ( aInfo1.IciB[0].dU < aInfo1.IciB[1].dU)
|
||||
if ( ( aInfo1.bCBOverEq && aInfo1.IciB[0].dU < aInfo1.IciB[1].dU) || ( ! aInfo1.bCBOverEq && aInfo1.IciB[0].dU > aInfo1.IciB[1].dU))
|
||||
dU1 = 0.5 * ( aInfo1.IciB[0].dU + aInfo1.IciB[1].dU) ;
|
||||
// a cavallo di fine / inizio
|
||||
else
|
||||
else if ( aInfo1.bCBOverEq)
|
||||
dU1 = aInfo1.IciB[0].dU + SPAN_PARAM ;
|
||||
else
|
||||
dU1 = aInfo1.IciB[1].dU + SPAN_PARAM ;
|
||||
}
|
||||
// determino il secondo termine del confronto
|
||||
dU2 = aInfo2.IciB[0].dU ;
|
||||
if ( aInfo2.bOverlap) {
|
||||
// caso normale
|
||||
if ( aInfo2.IciB[0].dU < aInfo2.IciB[1].dU)
|
||||
if ( ( aInfo2.bCBOverEq && aInfo2.IciB[0].dU < aInfo2.IciB[1].dU) || ( ! aInfo2.bCBOverEq && aInfo2.IciB[0].dU > aInfo2.IciB[1].dU))
|
||||
dU2 = 0.5 * ( aInfo2.IciB[0].dU + aInfo2.IciB[1].dU) ;
|
||||
// a cavallo di fine / inizio
|
||||
else
|
||||
else if ( aInfo2.bCBOverEq)
|
||||
dU2 = aInfo2.IciB[0].dU + SPAN_PARAM ;
|
||||
else
|
||||
dU2 = aInfo2.IciB[1].dU + SPAN_PARAM ;
|
||||
}
|
||||
|
||||
return ( dU2 > dU1 + EPS_PARAM) ;
|
||||
|
||||
+23
-3
@@ -576,9 +576,25 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
}
|
||||
}
|
||||
// costruisco il vettore delle classificazioni
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
for ( int i = 0 ; i < nNumInters ; ++ i) {
|
||||
// se è definito un tratto precedente
|
||||
double dLenU ; pCurve->GetLengthAtParam( InfoCorr[i].IciA[0].dU, dLenU) ;
|
||||
/*int j = i < nNumInters - 1 ? i + 1 : -1 ;
|
||||
if ( pCurve->IsClosed() && j == - 1)
|
||||
j = 0 ;*/
|
||||
int j = i == 0 ? -1 : i - 1 ;
|
||||
if ( pCurve->IsClosed() && j == - 1)
|
||||
j = nNumInters - 1 ;
|
||||
bool bSpike = false ;
|
||||
if ( j != -1) {
|
||||
bSpike = InfoCorr[i].bOverlap && InfoCorr[j].bOverlap && InfoCorr[i].bCBOverEq != InfoCorr[j].bCBOverEq ;
|
||||
if ( bSpike) {
|
||||
bSpike = abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[0].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[0].dU) < EPS_PARAM ||
|
||||
abs( InfoCorr[i].IciA[1].dU - InfoCorr[j].IciA[1].dU) < EPS_PARAM ;
|
||||
}
|
||||
}
|
||||
if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM && dLenU - dCurrLen > dLenMin) {
|
||||
// verifico che la definizione sul tratto sia omogenea e valida
|
||||
int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ;
|
||||
@@ -610,7 +626,11 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO
|
||||
// salvo dati correnti
|
||||
dCurrPar = InfoCorr[i].IciA[1].dU ;
|
||||
dCurrLen = dLenU ;
|
||||
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
|
||||
// se sono in un caso di spike devo trattare l'overlap in modo diverso
|
||||
if ( ! bSpike)
|
||||
nLastTy = InfoCorr[i].IciA[1].nNextTy ;
|
||||
else
|
||||
nLastTy = InfoCorr[i].IciA[0].nPrevTy ;
|
||||
}
|
||||
}
|
||||
// eventuale tratto finale rimasto
|
||||
@@ -736,7 +756,7 @@ IntersCurveCurve::GetCurveOutClass( const ICurve* pCurve, int& nClass)
|
||||
double dArea ;
|
||||
if ( ! pCurve->GetAreaXY( dArea))
|
||||
return false ;
|
||||
nClass = (( dArea > 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
nClass = (( dArea >= 0) ? CRVC_OUT : CRVC_IN) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
@@ -235,6 +235,16 @@ IntersCurvePlane::GetIntersCount( void)
|
||||
return m_nIntersCount ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetIntCrvPlnInfo( int nInd, IntCrvPlnInfo& aInfo)
|
||||
{
|
||||
if ( nInd < 0 || nInd >= m_nIntersCount)
|
||||
return false ;
|
||||
aInfo = m_Info[nInd] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersCurvePlane::GetIntersPointNearTo( const Point3d& ptNear, Point3d& ptI, double& dParam)
|
||||
|
||||
+171
-53
@@ -15,6 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -25,99 +26,176 @@ using namespace std ;
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2)
|
||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
||||
{
|
||||
// Verifico il versore
|
||||
if ( vtL.IsSmall())
|
||||
dU1 = NAN ;
|
||||
dU2 = NAN ;
|
||||
|
||||
// Verifico il versore
|
||||
if ( vtV.IsSmall())
|
||||
return false ;
|
||||
|
||||
// Verifico il cilindro
|
||||
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
|
||||
// Verifico il cilindro
|
||||
if ( dRad < EPS_SMALL || dH < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
int nBasInt = 0 ;
|
||||
if ( abs( vtL.z) > EPS_ZERO) {
|
||||
if ( abs( vtV.z) > EPS_ZERO) {
|
||||
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||
double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||
dU1 = ( ptInt1 - ptL) * vtL ;
|
||||
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
if ( bIgnoreTap)
|
||||
dEpsRad = 0. ;
|
||||
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 1 ;
|
||||
vtN1 = - Z_AX ;
|
||||
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
|
||||
}
|
||||
Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||
dU2 = ( ptInt2 - ptL) * vtL ;
|
||||
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 2 ;
|
||||
vtN2 = Z_AX ;
|
||||
dU2 = ( ( dH - ptP.z) / vtV.z) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
if ( nBasInt == 3) {
|
||||
if ( dU1 > dU2)
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad,
|
||||
2 * ( ptL.x * vtL.x + ptL.y * vtL.y),
|
||||
vtL.x * vtL.x + vtL.y * vtL.y} ;
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
||||
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
||||
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
||||
DBLVECTOR vdRoots ;
|
||||
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
// Epsilon per piani di tappo
|
||||
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
||||
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
||||
if ( bIgnoreTap) {
|
||||
dEpsLow = 0. ;
|
||||
dEpsUp = 0. ;
|
||||
}
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
if ( nRoot == 2) {
|
||||
double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ;
|
||||
if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL)
|
||||
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
||||
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
||||
-- nRoot ;
|
||||
}
|
||||
if ( nRoot >= 1) {
|
||||
double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ;
|
||||
if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) {
|
||||
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
||||
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
||||
if ( nRoot == 2)
|
||||
vdRoots[0] = vdRoots[1] ;
|
||||
-- nRoot ;
|
||||
}
|
||||
}
|
||||
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
if ( nRoot == 2) {
|
||||
// Punti di intersezione con la superficie del cilindro
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
ptInt2 = ptP + vdRoots[1] * vtV ;
|
||||
dU1 = vdRoots[0] ;
|
||||
dU2 = vdRoots[1] ;
|
||||
if ( dU1 > dU2)
|
||||
// Determino le normali
|
||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
dU1 = vdRoots[0] ;
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
dU2 = vdRoots[0] ;
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
if ( dU1 > dU2)
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
// Punto di intersezione
|
||||
dU1 = vdRoots[0] ;
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
dU2 = vdRoots[0] ;
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
||||
{
|
||||
// Porto la linea nel riferimento del cilindro
|
||||
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
||||
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
||||
if ( IntersLineCyl( ptP, vtV, dH, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap, bInvertNormals))
|
||||
{
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e cilindro sono nel medesimo riferimento.
|
||||
// Il cilindro è definito con centro della base, asse, raggio e altezza.
|
||||
@@ -133,7 +211,13 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
if ( ! frCyl.Set( ptCyl, vtCyl))
|
||||
return false ;
|
||||
// Ora eseguo i conti nel riferimento intrinseco
|
||||
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false ;
|
||||
bool bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -144,7 +228,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||
double& dU1, double& dU2)
|
||||
double& dU1, double& dU2)
|
||||
{
|
||||
// Determino asse ed altezza del cilindro
|
||||
Vector3d vtCyl = ptCyl2 - ptCyl1 ;
|
||||
@@ -157,5 +241,39 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
if ( ! frCyl.Set( ptCyl1, vtCyl))
|
||||
return false ;
|
||||
// Ora eseguo i conti nel riferimento intrinseco
|
||||
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false ;
|
||||
bool bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// linea già nel riferimento intrinseco del cilindro
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2)
|
||||
{
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
bool bTapLow = false, bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// funzione esposta per altre dll
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2)
|
||||
{
|
||||
return IntersLineCyl( ptLineSt, vtLineDir, CylFrame, dH, dRad, false, false,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true, false) ;
|
||||
}
|
||||
|
||||
+23
-4
@@ -20,17 +20,27 @@
|
||||
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
|
||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2) ;
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
||||
|
||||
// come sopra ma passo il riferimento intrinseco del cilindro in cui portare la linea
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight)
|
||||
{
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
double dU1, dU2 ;
|
||||
return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false, bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -50,3 +60,12 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||
double& dU1, double& dU2) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// // Linea e cilindro sono nel medesimo riferimento.
|
||||
// Il cilindro è definito con raggio e altezza. ( la linea è già nel riferimento intrinseco del cilindro)
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2) ;
|
||||
|
||||
+357
-19
@@ -72,14 +72,28 @@ static void
|
||||
UpdateInfoIntersLineSurfBz( const Point3d& ptL, const Vector3d& vtDir, int nILT, int nT, const Point3d& ptSP, const Point3d& ptIBz, double dCos,
|
||||
const Point3d& ptSP2, const Point3d& ptIBz2, double dCos2, ILSBIVECTOR& vInfo)
|
||||
{
|
||||
int nType = LSBT_NONE ;
|
||||
if ( dCos > EPS_ZERO)
|
||||
nType = LSBT_IN ;
|
||||
else if ( dCos < EPS_ZERO)
|
||||
nType = LSBT_OUT ;
|
||||
else
|
||||
nType = LSBT_TOUCH ;
|
||||
|
||||
if ( nILT == ILTA_IN || nILT == ILTA_EDGE || nILT == ILTA_VERT || nILT == ILTA_NO_TRIA) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
vInfo.emplace_back( nType, dU, nT, dCos, ptIBz, ptSP) ;
|
||||
}
|
||||
else if ( nILT == ILTA_SEGM || nILT == ILTA_SEGM_ON_EDGE) {
|
||||
double dU = ( ptIBz - ptL) * vtDir ;
|
||||
double dU2 = ( ptIBz2 - ptL) * vtDir ;
|
||||
vInfo.emplace_back( nILT, dU, dU2, nT, dCos2, ptIBz, ptIBz2, ptSP, ptSP2) ;
|
||||
int nType2 = LSBT_NONE ;
|
||||
if ( dCos2 > EPS_ZERO)
|
||||
nType2 = LSBT_IN ;
|
||||
else if ( dCos2 < EPS_ZERO)
|
||||
nType2 = LSBT_OUT ;
|
||||
vInfo.emplace_back( nType, dU, 0, nT, dCos, ptIBz, P_INVALID, ptSP, P_INVALID) ;
|
||||
vInfo.emplace_back( nType2, dU2, 0, nT, dCos2, ptIBz2, P_INVALID, ptSP2, P_INVALID) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,9 +107,7 @@ OrderInfoIntersLineSurfBz( ILSBIVECTOR& vInfo)
|
||||
// ordino il vettore delle intersezioni secondo il senso crescente del parametro di linea
|
||||
sort( vInfo.begin(), vInfo.end(),
|
||||
[]( const IntLinSbzInfo& a, const IntLinSbzInfo& b)
|
||||
{ double dUa = ( ( a.nILTA == ILTA_SEGM || a.nILTA == ILTA_SEGM_ON_EDGE) ? ( a.dU + a.dU2) / 2 : a.dU) ;
|
||||
double dUb = ( ( b.nILTA == ILTA_SEGM || b.nILTA == ILTA_SEGM_ON_EDGE) ? ( b.dU + b.dU2) / 2 : b.dU) ;
|
||||
return ( dUa < dUb) ; }) ;
|
||||
{ return ( a.dU < b.dU) ; }) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -181,19 +193,9 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
// ciclo sulle intersezioni
|
||||
for ( const auto& Info : vInfo) {
|
||||
// se intersezione puntuale
|
||||
if ( Info.nILTA == ILTA_VERT || Info.nILTA == ILTA_EDGE || Info.nILTA == ILTA_IN) {
|
||||
int nFlag = LSBT_TOUCH ;
|
||||
if ( Info.dCosDN > EPS_ZERO)
|
||||
nFlag = LSBT_OUT ;
|
||||
else if ( Info.dCosDN < -EPS_ZERO)
|
||||
nFlag = LSBT_IN ;
|
||||
vInters.emplace_back( nFlag, Info.dU) ;
|
||||
}
|
||||
// se altrimenti intersezione con coincidenza
|
||||
else if ( Info.nILTA == ILTA_SEGM || Info.nILTA == ILTA_SEGM_ON_EDGE) {
|
||||
vInters.emplace_back( LSBT_TG_INI, Info.dU) ;
|
||||
vInters.emplace_back( LSBT_TG_FIN, Info.dU2) ;
|
||||
}
|
||||
vInters.emplace_back( Info.nILSB, Info.dU) ;
|
||||
// se intersezione sovrapposta
|
||||
// da sviluppare
|
||||
}
|
||||
// elimino intersezioni ripetute
|
||||
for ( size_t j = 1 ; j < vInters.size() ; ) {
|
||||
@@ -239,7 +241,343 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier
|
||||
// Intersezione di una linea con una superficie di Bezier di grado 3x1 monopatch
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBzCubicLinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
|
||||
ILSBIVECTOR& vInfo, bool bFinite)
|
||||
{
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
|
||||
// funzione pensata per funzionare solo con una monopatch di grado 3x1
|
||||
if ( nDegU != 3 || nDegV != 1 || nSpanU > 1 || nSpanV > 1 || bRat)
|
||||
return false ;
|
||||
|
||||
int nInters = int( vInfo.size()) ;
|
||||
|
||||
Point3d r = ptL ;
|
||||
Vector3d q = vtL ;
|
||||
bool bNeedToRotX = AreSameVectorApprox( q, X_AX) ;
|
||||
bool bNeedToRotY = AreSameVectorApprox( q, Y_AX) ;
|
||||
bool bNeedToRot = bNeedToRotX || bNeedToRotY ;
|
||||
Frame3d frRot ;
|
||||
if ( bNeedToRotX)
|
||||
frRot.Set( ORIG, X_AX) ;
|
||||
if ( bNeedToRotY)
|
||||
frRot.Set( ORIG, Y_AX) ;
|
||||
if ( bNeedToRot) {
|
||||
r.ToLoc( frRot) ;
|
||||
q.ToLoc( frRot) ;
|
||||
}
|
||||
|
||||
PNTVECTOR vPntCtrl = pSurfBz->GetAllControlPoints() ;
|
||||
|
||||
if ( bNeedToRot) {
|
||||
for ( Point3d& pt: vPntCtrl)
|
||||
pt.ToLoc( frRot) ;
|
||||
}
|
||||
|
||||
Vector3d A = vPntCtrl[4] - vPntCtrl[0] ;
|
||||
Vector3d B = vPntCtrl[5] - vPntCtrl[1] ;
|
||||
Vector3d C = vPntCtrl[6] - vPntCtrl[2] ;
|
||||
Vector3d D = vPntCtrl[7] - vPntCtrl[3] ;
|
||||
Vector3d E = vPntCtrl[0] - ORIG ;
|
||||
Vector3d F = vPntCtrl[1] - ORIG ;
|
||||
Vector3d G = vPntCtrl[2] - ORIG ;
|
||||
Vector3d H = vPntCtrl[3] - ORIG ;
|
||||
|
||||
Vector3d a3 = -A + 3 * B - 3 * C + D ;
|
||||
Vector3d a2 = 3 * A - 6 * B + 3 * C ;
|
||||
Vector3d a1 = -3 * A + 3 * B ;
|
||||
Vector3d a0 = A ;
|
||||
|
||||
Vector3d b3 = -E + 3 * F - 3 * G + H ;
|
||||
Vector3d b2 = 3 * E - 6 * F + 3 * G ;
|
||||
Vector3d b1 = -3 * E + 3 * F ;
|
||||
Vector3d b0 = E ;
|
||||
|
||||
|
||||
|
||||
DBLVECTOR vdCoeff, vdRoots ;
|
||||
// coefficienti dal grado più basso al grado più alto
|
||||
vdCoeff = { // c0
|
||||
q.x*q.z*a0.y*b0.z - q.x*q.y*a0.z*b0.z // 3
|
||||
- r.z*q.x*q.z*a0.y + r.z*q.x*q.y*a0.z + // 3
|
||||
q.y*q.z*a0.z*b0.z - q.z*q.z*a0.y*b0.x // 4
|
||||
- r.x*q.y*q.z*a0.z + r.x*q.z*q.z*a0.y + // 4
|
||||
q.z*q.z*a0.x*b0.y - q.y*q.z*a0.x*b0.z - q.x*q.z*a0.z*b0.y + q.x*q.y*a0.z*b0.z // 5
|
||||
- r.y*q.z*q.z*a0.x + r.z*q.y*q.z*a0.x + r.y*q.x*q.z*a0.z - r.z*q.x*q.y*a0.z, // 5
|
||||
|
||||
// c1
|
||||
q.x*q.z*(a1.y*b0.z + a0.y*b1.z) - q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 3
|
||||
- r.z*q.x*q.z*a1.y + r.z*q.x*q.y*a1.z + // 3
|
||||
q.y*q.z*(a1.z*b0.x + a0.z*b1.x) - q.z*q.z*(a1.y*b0.x + a0.y*b1.x) // 4
|
||||
- r.x*q.y*q.z*a1.z + r.x*q.z*q.z*a1.y + // 4
|
||||
q.z*q.z*(a1.x*b0.y + a0.x*b1.y) - q.y*q.z*(a1.x*b0.z + a0.x*b1.z) // 5
|
||||
- q.x*q.z*(a1.z*b0.y + a0.z*b1.y) + q.x*q.y*(a1.z*b0.z + a0.z*b1.z) // 5
|
||||
- r.y*q.z*q.z*a1.x + r.z*q.y*q.z*a1.x + r.y*q.x*q.z*a1.z - r.z*q.x*q.y*a1.z, // 5
|
||||
|
||||
// c2
|
||||
q.x*q.z*(a2.y*b0.z + a1.y*b1.z + a0.y*b2.z) - q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z) // 3
|
||||
- r.z*q.x*q.z*a2.y + r.z*q.x*q.y*a2.z + // 3
|
||||
q.y*q.z*(a2.z*b0.x + a1.z*b1.x + a0.z*b2.x) - q.z*q.z*(a2.y*b0.x + a1.y*b1.x + a0.y*b2.x) // 4
|
||||
- r.x*q.y*q.z*a2.z + r.x*q.z*q.z*a2.y + // 4
|
||||
q.z*q.z*(a2.x*b0.y + a1.x*b1.y + a0.x*b2.y) - q.y*q.z*(a2.x*b0.z + a1.x*b1.z + a0.x*b2.z) // 5
|
||||
- q.x*q.z*(a2.z*b0.y + a1.z*b1.y + a0.z*b2.y) + q.x*q.y*(a2.z*b0.z + a1.z*b1.z + a0.z*b2.z)// 5
|
||||
- r.y*q.z*q.z*a2.x + r.z*q.y*q.z*a2.x + r.y*q.x*q.z*a2.z - r.z*q.x*q.y*a2.z, // 5
|
||||
|
||||
// c3
|
||||
q.x*q.z*(a3.y*b0.z + a2.y*b1.z + a1.y*b2.z + a0.y*b3.z) - q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z) // 3
|
||||
- r.z*q.x*q.z*a3.y + r.z*q.x*q.y*a3.z + // 3
|
||||
q.y*q.z*(a3.z*b0.x + a2.z*b1.x + a1.z*b2.x + a0.z*b3.x) - q.z*q.z*(a3.y*b0.x + a2.y*b1.x + a1.y*b2.x + a0.y*b3.x) // 4
|
||||
- r.x*q.y*q.z*a3.z + r.x*q.z*q.z*a3.y + // 4
|
||||
q.z*q.z*(a3.x*b0.y + a2.x*b1.y + a1.x*b2.y + a0.x*b3.y) - q.y*q.z*(a3.x*b0.z + a2.x*b1.z + a1.x*b2.z + a0.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b0.y + a2.z*b1.y + a1.z*b2.y + a0.z*b3.y) + q.x*q.y*(a3.z*b0.z + a2.z*b1.z + a1.z*b2.z + a0.z*b3.z)// 5
|
||||
- r.y*q.z*q.z*a3.x + r.z*q.y*q.z*a3.x + r.y*q.x*q.z*a3.z - r.z*q.x*q.y*a3.z, // 5
|
||||
|
||||
// c4
|
||||
q.x*q.z*(a3.y*b1.z + a2.y*b2.z + a1.y*b3.z) - q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b1.x + a2.z*b2.x + a1.z*b3.x) - q.z*q.z*(a3.y*b1.x + a2.y*b2.x + a1.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b1.y + a2.x*b2.y + a1.x*b3.y) - q.y*q.z*(a3.x*b1.z + a2.x*b2.z + a1.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b1.y + a2.z*b2.y + a1.z*b3.y) + q.x*q.y*(a3.z*b1.z + a2.z*b2.z + a1.z*b3.z), // 5
|
||||
|
||||
// c5
|
||||
q.x*q.z*(a3.y*b2.z + a2.y*b3.z) - q.x*q.y*(a3.z*b2.z + a2.z*b3.z) + // 3
|
||||
q.y*q.z*(a3.z*b2.x + a2.z*b3.x) - q.z*q.z*(a3.y*b2.x + a2.y*b3.x) + // 4
|
||||
q.z*q.z*(a3.x*b2.y + a2.x*b3.y) - q.y*q.z*(a3.x*b2.z + a2.x*b3.z) // 5
|
||||
- q.x*q.z*(a3.z*b2.y + a2.z*b3.y) + q.x*q.y*(a3.z*b2.z + a2.z*b3.z), // 5
|
||||
|
||||
// c6
|
||||
q.x*q.z*a3.y*b3.z - q.x*q.y*a3.z*b3.z + // 3
|
||||
q.y*q.z*a3.z*b3.x - q.z*q.z*a3.y*b3.x + // 4
|
||||
q.z*q.z*a3.x*b3.y - q.y*q.z*a3.x*b3.z - q.x*q.z*a3.z*b3.y + q.x*q.y*a3.z*b3.z} ; // 5
|
||||
int nRoots = PolynomialRoots( 6, vdCoeff, vdRoots) ;
|
||||
bool bFound = false ;
|
||||
for ( int w = 0 ; w < nRoots ; ++w) {
|
||||
double dU = 0, dV = 0 ;
|
||||
if ( vdRoots[w] > 0 - EPS_ZERO && vdRoots[w] < 1 + EPS_ZERO) {
|
||||
dU = vdRoots[w] ;
|
||||
// verifico che non sia una soluzione con molteplicità > 1
|
||||
bool bAlreadyFound = false ;
|
||||
for ( int k = w - 1 ; k >= 0 && ! bAlreadyFound ; --k)
|
||||
bAlreadyFound = ( abs( dU - vdRoots[k]) < EPS_PARAM) ;
|
||||
if ( ! bAlreadyFound) {
|
||||
Vector3d vAlpha = a3 * pow(dU, 3) + a2 * pow( dU, 2) + a1 * dU + a0 ;
|
||||
Vector3d vBeta = b3 * pow(dU, 3) + b2 * pow( dU, 2) + b1 * dU + b0 ;
|
||||
double dDen = ( vAlpha.x * q.z - vAlpha.z * q.x) ;
|
||||
if ( abs( dDen) > EPS_ZERO)
|
||||
dV = ( ( vBeta.z - r.z) * q.x - ( vBeta.x - r.x ) * q.z) / dDen ;
|
||||
else {
|
||||
// se la prima equazione risulta un x/0 allora uso la seconda equazione per trovare il secondo parametro
|
||||
double dDen2 = ( vAlpha.y * q.z - vAlpha.z * q.y) ;
|
||||
dV = ( ( vBeta.z - r.z) * q.y - ( vBeta.y - r.y ) * q.z) / dDen2 ;
|
||||
}
|
||||
if ( dV > - EPS_ZERO && dV < 1 + EPS_ZERO) {
|
||||
Point3d ptIBez, ptIBez2 ;
|
||||
Vector3d vtN ;
|
||||
pSurfBz->GetPointNrmD1D2(dU, dV, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez, vtN) ;
|
||||
Point3d ptSP( dU, dV, 0), ptSP2 ;
|
||||
double dCos = vtN * vtL, dCos2 = 0 ;
|
||||
int nType = ILTA_NO_TRIA ;
|
||||
UpdateInfoIntersLineSurfBz( ptL, vtL, nType, -1, ptSP, ptIBez, dCos, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//// se tutti i coefficienti sono zero allora potrei avere una linea che giace sulla superficie
|
||||
//// per trovare i punti di inizio e fine sovrapposizione trovo i punti a minima distanza tra la linea e gli edge della superficie
|
||||
//if ( ! bFound && abs( vdCoeff[0]) < EPS_ZERO && abs( vdCoeff[1]) < EPS_ZERO && abs( vdCoeff[2]) < EPS_ZERO) {
|
||||
// ICRVCOMPOPOVECTOR vCrvEdge( 4) ;
|
||||
// vCrvEdge[0].Set(pSurfBz->GetCurveOnU( 0)) ;
|
||||
// vCrvEdge[1].Set(pSurfBz->GetCurveOnV( 1)) ;
|
||||
// vCrvEdge[2].Set(pSurfBz->GetCurveOnU( 1)) ;
|
||||
// vCrvEdge[3].Set(pSurfBz->GetCurveOnV( 0)) ;
|
||||
// double dAngTolDeg = 5 ;
|
||||
// for ( int i = 0 ; i < 4 ; ++i) {
|
||||
// PolyLine plApprox ; vCrvEdge[0]->ApproxWithLines( EPS_SMALL, dAngTolDeg, ICurve::ApprLineType::APL_STD, plApprox) ;
|
||||
// //CurveComposite cCC ;
|
||||
// //cCC.FromPolyLine( plApprox) ;
|
||||
// int nClosestLine = -1 ;
|
||||
// double dMinDist = INFINITO ;
|
||||
// Point3d pt ; plApprox.GetFirstPoint( pt) ;
|
||||
// Point3d ptClosest ;
|
||||
// int c = 0 ;
|
||||
// int nTot = plApprox.GetPointNbr() ;
|
||||
// for ( int j = 0 ; j < nTot ; ++j) {
|
||||
// DistPointLine dpl( pt, ptL, vtL, dLen, bFinite) ;
|
||||
// double dDist = INFINITO ;
|
||||
// dpl.GetDist( dDist) ;
|
||||
// if ( dDist < dMinDist) {
|
||||
// nClosestLine = c ;
|
||||
// dMinDist = dDist ;
|
||||
// }
|
||||
// plApprox.GetNextPoint( pt) ;
|
||||
// ++ c ;
|
||||
// }
|
||||
|
||||
// Point3d ptInt1, ptInt2 ;
|
||||
// if ( nClosestLine < nTot - 1 && nClosestLine > 0) {
|
||||
// // tra i due tratti dell'approssimazione che arrivano al punto selezionato come più vicino, devo trovare quale si avvicina di più
|
||||
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
// Point3d ptEnd ;
|
||||
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
|
||||
// plApprox.GetNextPoint( ptStart) ;
|
||||
// plApprox.GetNextPoint( ptEnd) ;
|
||||
// // linea precedente al punto
|
||||
// Vector3d vtLinePre = ptEnd - ptStart ;
|
||||
// double dLenPre = vtLinePre.Len() ;
|
||||
// DistLineLine dllPre( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
|
||||
// double dDistPre = INFINITO ;
|
||||
// dllPre.GetDist( dDistPre) ;
|
||||
// // linea che inzia con quel punto
|
||||
// ptStart = ptEnd ;
|
||||
// plApprox.GetNextPoint( ptEnd) ;
|
||||
// Vector3d vtLineCurr = ptEnd - ptStart ;
|
||||
// double dLenCurr = vtLineCurr.Len() ;
|
||||
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
|
||||
// double dDistCurr = INFINITO ;
|
||||
// dllCurr.GetDist( dDistCurr) ;
|
||||
|
||||
// if ( dDistPre < dDistCurr)
|
||||
// dllPre.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
// else
|
||||
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
// }
|
||||
// else if ( nClosestLine == 0) {
|
||||
// // il punto più vicino è sulla prima linea
|
||||
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
// Point3d ptEnd ; plApprox.GetNextPoint( ptEnd) ;
|
||||
// Vector3d vtLineCurr = ptEnd - ptStart ;
|
||||
// double dLenCurr = vtLineCurr.Len() ;
|
||||
// DistLineLine dllCurr( ptStart, vtLineCurr, dLenCurr, ptL, vtL,dLen) ;
|
||||
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
// }
|
||||
// else if ( nClosestLine == nTot- 1) {
|
||||
// // il punto più vicino è sull'ultima linea
|
||||
// Point3d ptStart ; plApprox.GetFirstPoint( ptStart) ;
|
||||
// Point3d ptEnd ;
|
||||
// for ( int z = 1 ; z < nClosestLine - 1 ; ++z)
|
||||
// plApprox.GetNextPoint( ptStart) ;
|
||||
// plApprox.GetNextPoint( ptEnd) ;
|
||||
// Vector3d vtLinePre = ptEnd - ptStart ;
|
||||
// double dLenPre = vtLinePre.Len() ;
|
||||
// DistLineLine dllCurr( ptStart, vtLinePre, dLenPre, ptL, vtL,dLen) ;
|
||||
// dllCurr.GetMinDistPoints( ptInt1, ptInt2) ;
|
||||
// }
|
||||
//
|
||||
// double dU1 = 0, dV1 = 0, dU2 = 0, dV2 = 0 ;
|
||||
// // se ho trovato due punti vuol dire che la linea coincide con un edge e ho trovato tutto quello che serve
|
||||
// if ( ! AreSamePointExact( ptInt2, ORIG)) {
|
||||
// if ( i == 0) {
|
||||
// //dV1 = 0 ; dV2 = 0 ;
|
||||
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
// vCrvEdge[0]->GetParamAtPoint( ptInt2, dU2) ;
|
||||
// }
|
||||
// else if ( i == 1) {
|
||||
// //dU1 = 1 ; dU2 = 1 ;
|
||||
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
// vCrvEdge[1]->GetParamAtPoint( ptInt2, dV2) ;
|
||||
// }
|
||||
// else if ( i == 2){
|
||||
// //dV1 = 1 ; dV2 = 1 ;
|
||||
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
// vCrvEdge[2]->GetParamAtPoint( ptInt2, dU2) ;
|
||||
// }
|
||||
// else if ( i == 3){
|
||||
// //dU1 = 0 ; dU2 = 0 ;
|
||||
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
// vCrvEdge[3]->GetParamAtPoint( ptInt2, dV2) ;
|
||||
// }
|
||||
// Point3d ptIBez1, ptIBez2 ;
|
||||
// Vector3d vtN1, vtN2 ;
|
||||
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
|
||||
// pSurfBz->GetPointNrmD1D2(dU2, dV2, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez2, vtN2) ;
|
||||
// Point3d ptSP1( dU1, dV1, 0) ;
|
||||
// double dCos1 = vtN1 * vtL ;
|
||||
// Point3d ptSP2( dU2, dV2, 0) ;
|
||||
// double dCos2 = vtN2 * vtL ;
|
||||
// // se avevo già trovato un punto singolo che coincide col primo punto di questa intersezione sovrapposta, allora cancello l'intersezione singola che
|
||||
// // avevo salvato e aggiungo quella sovrapposto che ho trovato ora
|
||||
// if ( bFound) {
|
||||
// int nNewTot = int(vInfo.size()) ;
|
||||
// int nNewInters = nNewTot - nInters ;
|
||||
// bool bAlreadyFound = false ;
|
||||
// for ( int i = 0 ; i < nNewInters ; ++i) {
|
||||
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) || AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP2) ;
|
||||
// if ( bAlreadyFound) {
|
||||
// vInfo.erase( vInfo.begin() + nNewTot - i) ;
|
||||
// break ;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
// bFound = true ;
|
||||
// break ;
|
||||
// }
|
||||
// // se ho trovato un punto a distanza zero dalla linea allora ho trovato l'intersezione
|
||||
// else if ( dMinDist < EPS_SMALL) {
|
||||
// if ( i == 0) {
|
||||
// //dV1 = 0 ;
|
||||
// vCrvEdge[0]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
// }
|
||||
// else if ( i == 1) {
|
||||
// //dU1 = 1 ;
|
||||
// vCrvEdge[1]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
// }
|
||||
// else if ( i == 2) {
|
||||
// //dV1 = 1 ;
|
||||
// vCrvEdge[2]->GetParamAtPoint( ptInt1, dU1) ;
|
||||
// }
|
||||
// else if ( i == 3) {
|
||||
// //dU1 = 0 ;
|
||||
// vCrvEdge[3]->GetParamAtPoint( ptInt1, dV1) ;
|
||||
// }
|
||||
// Point3d ptSP1( dU1, dV1, 0), ptSP2 ;
|
||||
// // se avevo trovato già altri punti controllo di non essere esattamente su una diagonale ( e quindi avere un'intersezione con ogni edge, ma due sono doppie)
|
||||
// if ( bFound) {
|
||||
// int nNewTot = int(vInfo.size()) ;
|
||||
// int nNewInters = nNewTot - nInters ;
|
||||
// bool bAlreadyFound = false ;
|
||||
// for ( int i = 0 ; i < nNewInters ; ++i)
|
||||
// bAlreadyFound = AreSamePointApprox(vInfo[nNewTot - i].ptUV, ptSP1) ;
|
||||
// if ( bAlreadyFound)
|
||||
// continue ;
|
||||
// }
|
||||
|
||||
// Point3d ptIBez1, ptIBez2 ;
|
||||
// Vector3d vtN1, vtN2 ;
|
||||
// pSurfBz->GetPointNrmD1D2(dU1, dV1, ISurfBezier::Side::FROM_MINUS, ISurfBezier::Side::FROM_MINUS, ptIBez1, vtN1) ;
|
||||
// double dCos1 = vtN1 * vtL, dCos2 = 0 ;
|
||||
// UpdateInfoIntersLineSurfBz( ptL, vtL, ILTA_NO_TRIA, -1, ptSP1, ptIBez1, dCos1, ptSP2, ptIBez2, dCos2, vInfo) ;
|
||||
// bFound = true ;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
// se la superficie è trimmed verifico che i punti trovati siano all'interno del parametrico trimmato
|
||||
if ( bTrimmed && bFound) {
|
||||
int nNewTot = int(vInfo.size()) ;
|
||||
int nNewInters = nNewTot - nInters ;
|
||||
const ISurfFlatRegion* pFRTrim = pSurfBz->GetTrimRegion() ;
|
||||
for ( int i = 0 ; i < nNewInters ; ++i) {
|
||||
Point3d ptTest = vInfo[nNewTot - i].ptUV * SBZ_TREG_COEFF ;
|
||||
bool bInside = false ;
|
||||
double dDist = INFINITO ;
|
||||
IsPointInsideSurfFr( ptTest, pFRTrim, dDist, bInside) ;
|
||||
if ( ! bInside)
|
||||
vInfo.erase( vInfo.begin() + nNewTot - i) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Intersezione di una linea con una superficie di Bezier bilineare monopatch
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineSurfBzBilinear( const Point3d& ptL, const Vector3d& vtL, double dLen, const ISurfBezier* pSurfBz,
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
//----------------------------------------------------------------------------
|
||||
// EgalTech 2026
|
||||
//----------------------------------------------------------------------------
|
||||
// File : OffsetCurve3d.cpp Data : 10.06.26 Versione : 3.1f1
|
||||
// Contenuto : Classe per offset di Curve 3d.
|
||||
//
|
||||
//
|
||||
//
|
||||
// Modifiche : 10.06.26 DB Creazione modulo.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------- Include ----------------------------------------
|
||||
#include "stdafx.h"
|
||||
#include "GeoConst.h"
|
||||
#include "CurveLine.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "RemoveCurveDefects.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkPolyLine.h"
|
||||
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
#define SAVECVRORIG 1
|
||||
#define SAVEOFFDIR 1
|
||||
#define SAVECYL 1
|
||||
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
|
||||
#include "/EgtDev/Include/EGkColor.h"
|
||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vector<Color> vCol ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
OffsetCurve3d::~OffsetCurve3d( void)
|
||||
{
|
||||
Reset() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OffsetCurve3d::Reset( void)
|
||||
{
|
||||
for ( auto& pCrv : m_CrvLst) {
|
||||
if ( pCrv != nullptr) {
|
||||
delete pCrv ;
|
||||
pCrv = nullptr ;
|
||||
}
|
||||
}
|
||||
m_CrvLst.clear() ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType)
|
||||
{
|
||||
// pulisco tutto
|
||||
Reset() ;
|
||||
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
|
||||
if ( ! pCrv->FromPolyLine( PL))
|
||||
return false ;
|
||||
|
||||
#if SAVECVRORIG
|
||||
vGeo.push_back( pCrv->Clone()) ;
|
||||
vCol.push_back( AQUA) ;
|
||||
Point3d ptBase ; PL.GetFirstPoint( ptBase) ;
|
||||
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
|
||||
IGeoVector3d* pVec = CreateGeoVector3d() ;
|
||||
pVec->Set( vOffDir[i] * dOffDist, ptBase) ;
|
||||
PL.GetNextPoint( ptBase) ;
|
||||
vGeo.push_back( pVec) ;
|
||||
vCol.push_back( BLUE) ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// verifico se la curva è un segmento di retta
|
||||
bool bIsLine = PL.GetPointNbr() == 2 ;
|
||||
if ( bIsLine) {
|
||||
// faccio l'offset di una linea
|
||||
return true ;
|
||||
}
|
||||
|
||||
// se offset nullo, copio la curva ed esco
|
||||
if ( abs( dOffDist) < 10 * EPS_SMALL) {
|
||||
PtrOwner<CurveComposite> pCopy( CreateBasicCurveComposite()) ;
|
||||
if ( IsNull( pCopy) || ! pCopy->CopyFrom( pCrv))
|
||||
return false ;
|
||||
// unisco parti allineate (tranne gli estremi)
|
||||
pCopy->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
|
||||
// sposto in lista
|
||||
m_CrvLst.push_back( Release( pCopy)) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// elimino tratti molto corti
|
||||
if ( ! RemoveCurveSmallParts( pCrv, m_dLinTol))
|
||||
return false ;
|
||||
|
||||
bool bClosed = pCrv->IsClosed() ;
|
||||
|
||||
INTVECTOR vFlag ;
|
||||
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
|
||||
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
|
||||
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
|
||||
pSubCrv = pCrv->GetNextCurve() ;
|
||||
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
|
||||
int nFlag = vtDirCurr * vOffDir[i] > 0 ? OffsetCurve3d::AngType::ANG_SMOOTH_CONC : OffsetCurve3d::AngType::ANG_STR ;
|
||||
vFlag.push_back( nFlag) ;
|
||||
}
|
||||
|
||||
double dRadCorr ;
|
||||
Point3d ptPrev ; pCrv->GetStartPoint( ptPrev) ;
|
||||
ptPrev += vOffDir[0] * dOffDist ;
|
||||
Vector3d vtNormPrev ;
|
||||
Vector3d vtCorrPrev ;
|
||||
Vector3d vtTangPrev ;
|
||||
Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ;
|
||||
const ICurve* pCrvPrev = pCrv->GetFirstCurve() ;
|
||||
const ICurve* pCrvCurr ;
|
||||
vector<PtrOwner<ICurve>> vOffsetCrvs ;
|
||||
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
|
||||
pCrvCurr = pCrv->GetNextCurve() ;
|
||||
Vector3d vtOffDir = vOffDir[i] ;
|
||||
Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ;
|
||||
pCrvPrev->GetStartDir( vtDirPrev) ;
|
||||
Vector3d vtTang = Media( vtDirCurr, vtDirPrev) ;
|
||||
vtTang.Normalize() ;
|
||||
Vector3d vtNorm = vtOffDir ;
|
||||
vtNorm.Rotate( vtTang, -90) ;
|
||||
//Vector3d vtCorr = vtTang ^ vtNorm ; vtCorr.Normalize() ;
|
||||
// devo invertire vtCorr??? se sì, quando?/////////////////////////////////////////
|
||||
Vector3d vtCorr = vtOffDir ;
|
||||
double dCorrK = 1 ;
|
||||
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CONC) {
|
||||
double dHalfAlfa = acos( vtTang * vtTangPrev) ;
|
||||
dCorrK = 1 / sin( 90 - dHalfAlfa) ;
|
||||
}
|
||||
|
||||
Point3d ptP ; pCrvCurr->GetStartPoint( ptP) ;
|
||||
dRadCorr = dOffDist ;
|
||||
ptP = ptP + dRadCorr * dCorrK * vtCorr ;
|
||||
// se secondo punto di angolo esterno di fianco, inserisco movimenti intermedi
|
||||
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] == OffsetCurve3d::AngType::ANG_CVEX) {
|
||||
double dAlfa = acos( vtTang * vtTangPrev) ;
|
||||
double dDelta = dOffDist * tan( dAlfa / 4) ;
|
||||
Point3d ptAdd1 = ptPrev + dDelta * vtTangPrev ;
|
||||
ICurveLine* pCL1 = CreateBasicCurveLine() ;
|
||||
pCL1->Set( ptPrev, ptAdd1) ;
|
||||
vOffsetCrvs.emplace_back( pCL1) ;
|
||||
Point3d ptAdd2 = ptP - dDelta * vtTang ;
|
||||
ICurveLine* pCL2 = CreateBasicCurveLine() ;
|
||||
pCL2->Set( ptAdd1, ptAdd2) ;
|
||||
vOffsetCrvs.emplace_back( pCL2) ;
|
||||
ptPrev = ptAdd2 ;
|
||||
}
|
||||
|
||||
//// se punto di angolo interno di fianco, elimino eventuali movimenti precedenti invertiti
|
||||
//if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX == 3) {
|
||||
// local nLastId = EgtGetLastInGroup( nClPathId)
|
||||
// while nLastId do
|
||||
// local vtMlast = ptP - EgtEP( nLastId, GDB_ID.ROOT) ; vtMlast:normalize()
|
||||
// if vtMlast * vtGpre < 0.5 then
|
||||
// ptPpre = EgtSP( nLastId, GDB_ID.ROOT)
|
||||
// EgtErase( nLastId)
|
||||
// else
|
||||
// break
|
||||
// end
|
||||
// nLastId = EgtGetLastInGroup( nClPathId)
|
||||
// end
|
||||
//}
|
||||
|
||||
//// se appena dopo angolo interno di fianco, verifico se da aggiungere
|
||||
//bool bToAdd = true
|
||||
//if ( nFlpre == 3 and abs( dSideAng) > GEO.EPS_ANG_SMALL) {
|
||||
// local vtMove = ptP - ptPpre ; vtMove:normalize()
|
||||
// if vtMove * vtTang < 0.5 then
|
||||
// bToAdd = false
|
||||
// end
|
||||
//}
|
||||
|
||||
// aggiungo tratto
|
||||
ICurveLine* pCL = CreateBasicCurveLine() ;
|
||||
pCL->Set( ptPrev, ptP) ;
|
||||
vOffsetCrvs.emplace_back( pCL) ;
|
||||
// aggiorno punto precedente
|
||||
ptPrev = ptP ;
|
||||
vtNormPrev = vtNorm ;
|
||||
vtCorrPrev = vtCorr ;
|
||||
vtTangPrev = vtTang ;
|
||||
vtDirPrev = vtDirCurr ;
|
||||
}
|
||||
|
||||
//// qui faccio la correzione per gli angoli interni
|
||||
//AdjustConcavePartsInPath( pCrv, vOffsetCrvs, vFlag, dOffDist) ;
|
||||
|
||||
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
|
||||
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
|
||||
#endif
|
||||
|
||||
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
|
||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
||||
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i])))
|
||||
return false ;
|
||||
}
|
||||
m_CrvLst.push_back( Release( pCrvOffset)) ;
|
||||
|
||||
return true ;
|
||||
|
||||
|
||||
// raccordi
|
||||
|
||||
// angoli interni
|
||||
|
||||
// angoli esterni
|
||||
|
||||
// auto intersezioni
|
||||
|
||||
//// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
|
||||
|
||||
//// ottavo passo : concateno i percorsi risultanti (senza cambiare verso)
|
||||
|
||||
//// nono passo : se con smusso o estensione, sostituisco i fillet con questi
|
||||
|
||||
//// ordino le curve in ordine decrescente di lunghezza
|
||||
//if ( m_CrvLst.size() > 1) {
|
||||
// for ( auto pCrv : m_CrvLst) {
|
||||
// double dLen ;
|
||||
// if ( pCrv->GetLength( dLen))
|
||||
// pCrv->SetTempProp( int( 1000 * dLen)) ;
|
||||
// else
|
||||
// pCrv->SetTempProp( 0) ;
|
||||
// }
|
||||
// m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
|
||||
//}
|
||||
|
||||
//// se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle
|
||||
//if ( bClosed) {
|
||||
// for ( auto pCrv : m_CrvLst) {
|
||||
// CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
|
||||
// if ( pCrvCo != nullptr)
|
||||
// pCrvCo->Close() ;
|
||||
// }
|
||||
//}
|
||||
|
||||
//return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
OffsetCurve3d::GetCurve( void)
|
||||
{
|
||||
return GetLongerCurve() ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
OffsetCurve3d::GetLongerCurve( void)
|
||||
{
|
||||
if ( m_CrvLst.empty())
|
||||
return nullptr ;
|
||||
// le curve sono ordinate in senso decrescente di lunghezza
|
||||
ICurve* pCrv = m_CrvLst.front() ;
|
||||
m_CrvLst.pop_front() ;
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
ICurve*
|
||||
OffsetCurve3d::GetShorterCurve( void)
|
||||
{
|
||||
if ( m_CrvLst.empty())
|
||||
return nullptr ;
|
||||
// le curve sono ordinate in senso decrescente di lunghezza
|
||||
ICurve* pCrv = m_CrvLst.back() ;
|
||||
m_CrvLst.pop_back() ;
|
||||
return pCrv ;
|
||||
}
|
||||
|
||||
struct Cyl {
|
||||
Cyl( void): frCyl( GLOB_FRM), dH( 0.), dRad( 0.) {;} ;
|
||||
Cyl( const Frame3d& _frCyl, double _dH, double _dRad, double _dLinTol) :
|
||||
frCyl( _frCyl), dH( _dH), dRad( _dRad) { ;}
|
||||
Cyl( const Point3d& _ptBase, const Vector3d& vtZ, double _dH, double _dRad, double _dLinTol) :
|
||||
dH( _dH), dRad( _dRad){
|
||||
frCyl.Set( _ptBase, vtZ); }
|
||||
public :
|
||||
Frame3d frCyl ;
|
||||
public:
|
||||
double dH ;
|
||||
double dRad ;
|
||||
};
|
||||
|
||||
typedef vector<Cyl> CYLVECT ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsPointInsideCylinder( const Point3d& ptTest, const Cyl& offCyl)
|
||||
{
|
||||
Point3d ptTestLoc = ptTest ; ptTestLoc.ToLoc( offCyl.frCyl) ;
|
||||
if ( ptTestLoc.z > offCyl.dH || ptTestLoc.z < 0)
|
||||
return false ;
|
||||
double dDist = ptTestLoc.x * ptTestLoc.x + ptTestLoc.y * ptTestLoc.y ;
|
||||
double dRadSq = offCyl.dRad * offCyl.dRad ;
|
||||
if ( dDist > dRadSq)
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
bool
|
||||
AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad)
|
||||
{
|
||||
const double dLinTol = 5 * EPS_SMALL ;
|
||||
INTVECTOR vErase ;
|
||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
||||
int nFlag = vFlag[i] ;
|
||||
if ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
|
||||
// scorro i prossimi finchè trovo la fine della zona concava
|
||||
INTVECTOR vLines ;
|
||||
while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
|
||||
vLines.push_back( i) ;
|
||||
++i ;
|
||||
nFlag = vFlag[i] ;
|
||||
}
|
||||
CYLVECT vCyl ;
|
||||
// creo un cilindro della dimensione del raggio
|
||||
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
||||
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
|
||||
Point3d ptStart, ptEnd ;
|
||||
pSubCrv->GetStartPoint( ptStart) ;
|
||||
pSubCrv->GetEndPoint( ptEnd) ;
|
||||
Vector3d vtHeight = ptEnd - ptStart ; vtHeight.Normalize() ;
|
||||
double dHeight = vtHeight.Len() ;
|
||||
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
|
||||
}
|
||||
|
||||
// controllo l'end di ogni linea per verificare se sta nel cilindro definito da uno degli altri tratti
|
||||
// controllo tutto i punti
|
||||
bool bErasedSomePart = false ;
|
||||
bool bErasedPrev = false ;
|
||||
INTVECTOR vInters ;
|
||||
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
||||
Point3d ptStart, ptEnd ;
|
||||
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
|
||||
if ( pSubCrv == nullptr)
|
||||
return false ;
|
||||
pSubCrv->GetEndPoint( ptEnd) ;
|
||||
pSubCrv->GetStartPoint( ptStart) ;
|
||||
// se stanno in uno dei cilindri degli altri tratti della zona concava
|
||||
for ( int k = 0 ; k < ssize( vLines) ; ++k) {
|
||||
if ( j == k)
|
||||
continue ;
|
||||
bool bToErase = IsPointInsideCylinder( ptEnd, vCyl[k]) ;
|
||||
if ( bErasedPrev && ! bToErase)
|
||||
bToErase = bToErase || IsPointInsideCylinder( ptStart, vCyl[k]) ;
|
||||
if ( bToErase) {
|
||||
bErasedSomePart = true ;
|
||||
bErasedPrev = true ;
|
||||
vInters.push_back( vLines[j]) ;
|
||||
if ( j < ssize( vLines) - 1)
|
||||
vInters.push_back( vLines[j+1]) ;
|
||||
++j ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
bErasedPrev = false ;
|
||||
}
|
||||
}
|
||||
if ( bErasedSomePart) {
|
||||
// calcolo le intersezioni effettive del primo e ultimo tratto cancellati con i cilindri che li hanno cancellati
|
||||
// controllo che effettivamente tutti i tratti cancellati siano consecutivi
|
||||
for ( int j = 1 ; j < ssize( vInters) ; ++j) {
|
||||
if ( vInters[j] != vInters[j-1] + 1)
|
||||
return false ;
|
||||
}
|
||||
for ( int j = 0 ; j < ssize( vInters) ; ++j) {
|
||||
// cancello i tratti intermedi
|
||||
if ( j > 0 && j < ssize( vInters) - 1) {
|
||||
vErase.push_back( vInters[j]) ;
|
||||
continue ;
|
||||
}
|
||||
// per il primo e ultimo controllo le intersezioni con tutti i cilindri
|
||||
ICurve* pCL = vOffsetCrvs[vInters[j]] ;
|
||||
Point3d ptStart ; pCL->GetStartPoint( ptStart) ;
|
||||
Vector3d vtStart ; pCL->GetStartDir( vtStart) ;
|
||||
double dLen ; pCL->GetLength( dLen) ;
|
||||
double dUTrim = ( j == 0 ? INFINITO : 0) ;
|
||||
Point3d ptTrim = P_INVALID ;
|
||||
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
|
||||
if ( vInters[j] == k)
|
||||
continue ;
|
||||
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
|
||||
double dU1, dU2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCyl( ptStart, vtStart * dLen, vCyl[k].frCyl, vCyl[k].dH, vCyl[k].dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true)) {
|
||||
bool bUpdate = ( j == 0 ? dU1 < dUTrim : dU1 > dUTrim) ;
|
||||
bUpdate = bUpdate && ptInt1.IsValid() && dU1 > 0 && dU1 < 1 ;
|
||||
bUpdate = bUpdate && vtN1 * vtStart < 0 ;
|
||||
if ( bUpdate) {
|
||||
dUTrim = dU1 ;
|
||||
ptTrim = ptInt1 ;
|
||||
}
|
||||
bUpdate = ( j == 0 ? dU2 < dUTrim : dU2 > dUTrim) ;
|
||||
bUpdate = bUpdate && ptInt2.IsValid() && dU2 > 0 && dU2 < 1 ;
|
||||
bUpdate = bUpdate && vtN2 * vtStart > 0 ;
|
||||
if ( bUpdate) {
|
||||
dUTrim = dU2 ;
|
||||
ptTrim = ptInt2 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ptTrim.IsValid()) {
|
||||
if ( j == 0) {
|
||||
pCL->ModifyEnd( ptTrim) ;
|
||||
double dNewLen ; pCL->GetLength( dNewLen) ;
|
||||
if ( dNewLen < 0.1 && vInters[0] != 0) { // se fosse il primo allora potrei modificare il successivo
|
||||
int nPrev = vInters[0] - 1 ;
|
||||
vErase.push_back( vInters[0]) ;
|
||||
vInters[0] = nPrev ;
|
||||
ICurve* pCLPrev = vOffsetCrvs[nPrev] ;
|
||||
pCLPrev->ModifyEnd( ptTrim) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pCL->ModifyStart( ptTrim) ;
|
||||
double dNewLen ; pCL->GetLength( dNewLen) ;
|
||||
if ( dNewLen < 0.1 && vInters[j] != ssize( vOffsetCrvs) - 1) { // se fosse l'ultima curva allora potrei modificare la precedente
|
||||
int nNext = vInters[j] + 1 ;
|
||||
vErase.push_back( vInters[j]) ;
|
||||
vInters[j] = nNext ;
|
||||
ICurve* pCLNext = vOffsetCrvs[nNext] ;
|
||||
pCLNext->ModifyStart( ptTrim) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
i = vLines.back() ;
|
||||
}
|
||||
}
|
||||
|
||||
// scorro tutto il vettore delle linee di offset e unisco aggiungendo una linea dove ne ho cancellate
|
||||
for ( int i = 0 ; i < ssize( vOffsetCrvs) - 1 ; ++i) {
|
||||
Point3d ptEndCurr, ptStartNext ;
|
||||
vOffsetCrvs[i]->GetEndPoint( ptEndCurr) ;
|
||||
vOffsetCrvs[i+1]->GetStartPoint( ptStartNext) ;
|
||||
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
|
||||
ICurveLine* pCL = CreateBasicCurveLine() ;
|
||||
pCL->Set( ptEndCurr, ptStartNext) ;
|
||||
PtrOwner<ICurve> pCrvL( pCL) ;
|
||||
vOffsetCrvs.insert( vOffsetCrvs.begin() + i + 1, std::move(pCrvL)) ;
|
||||
++i ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
+2
-8
@@ -1991,17 +1991,11 @@ MatchPolyLinesAddingPoints( const PolyLine& PL1, const PolyLine& PL2, int nType,
|
||||
nAddedSpan = 0 ;
|
||||
nCrv1 = 0 ;
|
||||
nCrv2 = 0 ;
|
||||
bool bLast1 = false ;
|
||||
bool bLast2 = false ;
|
||||
while ( nAddedSpan < nPnt) {
|
||||
if ( nCrv1 >= nPnt1) {
|
||||
if ( nCrv1 >= nPnt1)
|
||||
nCrv1 = nPnt1 - 1 ;
|
||||
bLast1 = true ;
|
||||
}
|
||||
if ( nCrv2 >= nPnt2) {
|
||||
if ( nCrv2 >= nPnt2)
|
||||
nCrv2 = nPnt2 - 1 ;
|
||||
bLast2 = true ;
|
||||
}
|
||||
bool bRep1 = vbRep1[nCrv1] ;
|
||||
bool bRep2 = vbRep2[nCrv2] ;
|
||||
const ICurve* pSubCrv1 = cc1.GetCurve( nCrv1) ;
|
||||
|
||||
+213
-80
@@ -40,6 +40,7 @@ const int P5AX_CVEX = 2 ; // su angolo convesso
|
||||
const int P5AX_CONC = 3 ; // in angolo concavo
|
||||
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||
const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static double
|
||||
@@ -64,6 +65,7 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
|
||||
static bool
|
||||
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const double dSinSmallAngle = sin( 0 * DEGTORAD) ;
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
@@ -79,18 +81,24 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
bool bConvex = (vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 < 0 ;
|
||||
bool bValidInters = true ;
|
||||
if ( i > 2) {
|
||||
int k = i - 2 ;
|
||||
// verifico la concavità anche tornando indietro lungo la linea
|
||||
if ( ( ( vPt5ax[k].ptP - vPt5ax[j].ptP) * vPt5ax[i].vtDir1 < 0) != bConvex) {
|
||||
LOG_WARN( GetEGkLogger(), "La superficie su cui si sta proiettando la curva ha delle normali incoerenti")
|
||||
return false ;
|
||||
}
|
||||
// verifico che l'intersezione sia tra i e j e non prima di j
|
||||
bValidInters = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[j].ptP - vPt5ax[k].ptP) > 0 ;
|
||||
}
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
if ( dLen1 > 10 * EPS_SMALL && bValidInters) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
||||
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
|
||||
@@ -102,9 +110,14 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
}
|
||||
else
|
||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
if ( dLen2 > 10 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
if ( bValidInters)
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
else {
|
||||
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
|
||||
Pt5ax.ptP = vPt5ax[j].ptP + vtNewLine * 2 * EPS_SMALL ;
|
||||
}
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
||||
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
|
||||
@@ -133,6 +146,21 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth)
|
||||
Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ;
|
||||
vtDirNext.Normalize() ;
|
||||
if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) {
|
||||
// se concavo senza spigolo netto segnalo zona concava smooth
|
||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// riscorro tutto il vettore per vedere se ho creato delle zone concave smooth frammentate (separate solo da un tratto non classificato concavo), che quindi uniformo
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) - 1 ; ++ i) {
|
||||
if ( vPt5ax[i].nFlag != P5AX_SMOOTH_CONC && vPt5ax[i-1].nFlag == P5AX_SMOOTH_CONC && vPt5ax[i+1].nFlag == P5AX_SMOOTH_CONC)
|
||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -377,8 +405,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
if ( bSharpEdges) {
|
||||
if ( ! AddPointsOnCorners( vPt5ax))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
@@ -393,7 +423,7 @@ typedef std::vector<IntersParLinesSurfTm*> INTPARLINESTMPVECTOR ;
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame3d& frRefLine, const INTPARLINESTMPVECTOR& vpIntPLSTM,
|
||||
double dPar, Point5ax& Pt5ax)
|
||||
double dPar, bool bFromVsTo, Point5ax& Pt5ax)
|
||||
{
|
||||
// intersezione retta di proiezione con superfici (conservo l'intersezione più alta)
|
||||
Point3d ptL = GetToLoc( ptP, frRefLine) ;
|
||||
@@ -402,23 +432,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
for ( int i = 0 ; i < ssize( vpIntPLSTM) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( vpIntPLSTM[i]->GetInters( ptL, 1, vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla direzione
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la direzione
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -455,7 +510,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vector3d& vtDir,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -521,7 +576,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, frRefLine, vpIntPLSTM, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -543,7 +598,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const Vect
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoPoint3d& gpRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto di riferimento
|
||||
Point3d ptMin = gpRef.GetPoint() ;
|
||||
@@ -558,23 +614,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dal punto
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso il punto
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -612,7 +693,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeoPoint3d& gpRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -663,7 +744,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, gpRef, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -681,7 +762,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const IGeo
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurve& crRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto a minima distanza
|
||||
DistPointCurve dPC( ptP, crRef) ;
|
||||
@@ -699,23 +781,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla curva
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la curva
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -738,7 +845,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
// assegno valori al punto 5assi
|
||||
Pt5ax.ptP = ptInt ;
|
||||
Pt5ax.vtDir1 = vtN ;
|
||||
Pt5ax.vtDir2 = vtLine ;
|
||||
Pt5ax.vtDir2 = ( bFromVsTo ? vtLine : -vtLine) ;
|
||||
Pt5ax.vtDirU = V_NULL ;
|
||||
Pt5ax.vtDirV = V_NULL ;
|
||||
Pt5ax.dPar = dPar ;
|
||||
@@ -754,7 +861,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICurve& crRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// Sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -805,7 +912,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, crRef, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
@@ -823,7 +930,8 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ICur
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, Point5ax& Pt5ax)
|
||||
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfTriMesh& stmRef, double dPar, bool bFromVsTo,
|
||||
Point5ax& Pt5ax)
|
||||
{
|
||||
// punto sulla superficie guida a minima distanza
|
||||
DistPointSurfTm dPS( ptP, stmRef) ;
|
||||
@@ -850,23 +958,48 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
|
||||
ILSIVECTOR vIntRes ;
|
||||
if ( IntersLineSurfTm( ptP, vtLine, dLineLen, *vpStm[i], vIntRes, false)) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
// se dalla superficie
|
||||
if ( bFromVsTo) {
|
||||
// cerco la prima intersezione valida a partire dall'ultima (è la più alta)
|
||||
int nI = ssize( vIntRes) - 1 ;
|
||||
while ( nI >= 0 && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
--nI ;
|
||||
// se trovata
|
||||
if ( nI >= 0) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU2 : IntRes.dU) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU2 : vIntRes[nI].dU) ;
|
||||
if ( dU > dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti verso la superficie
|
||||
else {
|
||||
// cerco la prima intersezione valida a partire dalla prima (è la più alta)
|
||||
int nI = 0 ;
|
||||
while ( nI < ssize( vIntRes) && abs( vIntRes[nI].dCosDN) < COS_ANG_LIM)
|
||||
++nI ;
|
||||
// se trovata
|
||||
if ( nI < ssize( vIntRes)) {
|
||||
if ( nInd < 0) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
else {
|
||||
double dUref = (( IntRes.nILTT == ILTT_SEGM || IntRes.nILTT == ILTT_SEGM_ON_EDGE) ? IntRes.dU : IntRes.dU2) ;
|
||||
double dU = (( vIntRes[nI].nILTT == ILTT_SEGM || vIntRes[nI].nILTT == ILTT_SEGM_ON_EDGE) ? vIntRes[nI].dU : vIntRes[nI].dU2) ;
|
||||
if ( dU < dUref) {
|
||||
IntRes = vIntRes[nI] ;
|
||||
nInd = i ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -911,7 +1044,7 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISurf& sfRef,
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
|
||||
double dLinTol, double dMaxSegmLen, bool bSharpEdges, bool bFromVsTo, PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
// sistemazioni per tipo di superficie
|
||||
CISRFTMPVECTOR vpSurfTm ;
|
||||
@@ -983,7 +1116,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf, const ISur
|
||||
while ( bFound) {
|
||||
// se trovo proiezione, la salvo
|
||||
Point5ax Pt5ax ;
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, Pt5ax))
|
||||
if ( ProjectPointOnSurf( ptP, vpSurfTm, *pRefTm, dPar, bFromVsTo, Pt5ax))
|
||||
vPt5ax.emplace_back( Pt5ax) ;
|
||||
// passo al successivo
|
||||
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
|
||||
|
||||
@@ -92,11 +92,18 @@ RotationMinimizingFrame::GetFrameAtParam( const Frame3d& frAct, const double dPa
|
||||
Vector3d vtCurrR = frAct.VersX() ;
|
||||
Vector3d vtCurrT = frAct.VersZ() ;
|
||||
|
||||
// punto i-esimo sulla curva e suo vettore tangente
|
||||
// punto i-esimo sulla curva e suo vettore tangente medio
|
||||
Point3d ptNextM, ptNextP ;
|
||||
Vector3d vtNextM, vtNextP ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNextM, &vtNextM) ||
|
||||
! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_PLUS, ptNextP, &vtNextP) ||
|
||||
! vtNextM.Normalize() || ! vtNextP.Normalize())
|
||||
return false ;
|
||||
Point3d ptNext ;
|
||||
Vector3d vtNextT ;
|
||||
if ( ! m_pCrv->GetPointD1D2( dParNext, ICurve::FROM_MINUS, ptNext, &vtNextT) ||
|
||||
! vtNextT.Normalize())
|
||||
ptNext = Media( ptNextM, ptNextP) ;
|
||||
vtNextT = Media( vtNextM, vtNextP) ;
|
||||
if ( ! vtNextT.Normalize())
|
||||
return false ;
|
||||
|
||||
// controllo per casi degeneri
|
||||
|
||||
@@ -733,6 +733,42 @@ GetSurfBezierRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, dou
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledSmooth( const ICurve* pCurve1, const ICurve* pCurve2, BIPNTVECTOR& vSyncLines, double dSampleLen)
|
||||
{
|
||||
// verifica parametri
|
||||
if ( pCurve1 == nullptr || pCurve2 == nullptr)
|
||||
return nullptr ;
|
||||
|
||||
// dLinTol servirà quando ci sarà la funzione ApproxWithCurveBezier
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
if ( pCurve1->GetType() != CRV_BEZIER)
|
||||
pCC1->AddCurve( CurveToBezierCurve( pCurve1, 3, false)) ;
|
||||
else
|
||||
pCC1->AddCurve( pCurve1->Clone()) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// se la curva è già una bezier singola la tengo, sennò la converto
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
if ( pCurve2->GetType() != CRV_BEZIER)
|
||||
pCC2->AddCurve( CurveToBezierCurve( pCurve2, 3, false)) ;
|
||||
else
|
||||
pCC2->AddCurve( pCurve2->Clone()) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// creo e setto la superficie trimesh
|
||||
PtrOwner<SurfBezier> pSbz( CreateBasicSurfBezier()) ;
|
||||
if ( IsNull( pSbz) || ! pSbz->CreateSmoothRuledByTwoCurves( pCC1, pCC2, dSampleLen, vSyncLines))
|
||||
return nullptr ;
|
||||
|
||||
// restituisco la superficie
|
||||
return Release( pSbz) ;
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
ISurfBezier*
|
||||
GetSurfBezierRuledGuided( const ICurve* pCurve1, const ICurve* pCurve2, const BIPNTVECTOR& vCrv, double dLinTol)
|
||||
|
||||
+1120
-541
File diff suppressed because it is too large
Load Diff
+110
-22
@@ -29,6 +29,7 @@
|
||||
|
||||
#define SAVEMKUNIF_CRVS 0
|
||||
#if SAVEMKUNIF_CRVS
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
@@ -618,7 +619,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vLoop); ++i){
|
||||
vGeo.push_back(vLoop[i]->Clone()) ;
|
||||
}
|
||||
@@ -632,7 +633,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
nDir == 0 ? bRescaledU = true : bRescaledV = true ;
|
||||
// creo il vettore delle curve all'interno di una striscia
|
||||
ICRVCOMPOPOVECTOR vCrvStrip ;
|
||||
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
|
||||
for ( int p = 0 ; p < ssize(vU) - 1 ; ++p) {
|
||||
double dLenStrip = abs( vU[p+1] - vU[p]) ;
|
||||
if ( dLenStrip < EPS_SMALL)
|
||||
continue ;
|
||||
@@ -654,24 +655,85 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
for ( int l = 0 ; l < ssize( vLoop); ++l) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.clear() ;
|
||||
vGeo.push_back(pTrimMask->Clone()) ;
|
||||
vGeo.push_back(vLoop[l]->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
IntersCurveCurve icc( *pTrimMask, *vLoop[l]) ;
|
||||
CRVCVECTOR vCurveClass ;
|
||||
icc.GetCurveClassification( 1, 10 * EPS_SMALL, vCurveClass) ;
|
||||
for( int i = 0 ; i < ssize( vCurveClass); ++i) {
|
||||
if( vCurveClass[i].nClass == CRVC_IN || vCurveClass[i].nClass == CRVC_ON_P)
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCurveClass[i].dParS, vCurveClass[i].dParE))) ;
|
||||
IntersCurveCurve icc( *vLoop[l], *pTrimMask) ;
|
||||
int nInters = icc.GetIntersCount() ;
|
||||
ICCIVECTOR vICCI ;
|
||||
for ( int i = 0 ; i < nInters ; ++i) {
|
||||
IntCrvCrvInfo icci ; icc.GetIntCrvCrvInfo( i, icci) ;
|
||||
vICCI.push_back( std::move( icci)) ;
|
||||
}
|
||||
CRVCVECTOR vCrvClass, vMaskClass ;
|
||||
icc.GetCurveClassification( 0, EPS_SMALL, vCrvClass) ;
|
||||
icc.GetCurveClassification( 1, EPS_SMALL, vMaskClass) ;
|
||||
// se dei pezzi di trim risultano esterni allo spazio parametrico tengo il bordo della maschera di trim
|
||||
double dLastParam1 = 0 ;
|
||||
double dStartA = 0, dEndA = 0 ; vLoop[l]->GetDomain( dStartA, dEndA) ;
|
||||
double dEndB = 4 ;
|
||||
for ( int i = 0 ; i < ssize( vCrvClass); ++i) {
|
||||
if ( vCrvClass[i].nClass == CRVC_IN || vCrvClass[i].nClass == CRVC_ON_P) {
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCrvClass[i].dParS, vCrvClass[i].dParE))) ;
|
||||
|
||||
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
|
||||
int k = vICCI[j].bOverlap ? 1 : 0 ;
|
||||
if ( abs( vICCI[j].IciA[k].dU - vCrvClass[i].dParE) < EPS_PARAM) {
|
||||
dLastParam1 = vICCI[j].IciB[k].dU ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( vCrvClass[i].nClass == CRVC_OUT && ( p == 0 || p == ssize(vU) - 2)){
|
||||
double dMin, dMax ;
|
||||
if ( p == 0) {
|
||||
dMin = nDir == 0 ? 3 : 0 ;
|
||||
dMax = nDir == 0 ? 4 : 1 ;
|
||||
}
|
||||
else {
|
||||
dMin = nDir == 0 ? 1 : 2 ;
|
||||
dMax = nDir == 0 ? 2 : 3 ;
|
||||
}
|
||||
// aggiungo la parte di curva di edge al posto della parte di curva che esce dal parametrico
|
||||
// se non ho ancora aggiunto un tratto parto dal primo punto di intersezione
|
||||
if ( ssize( vCrvStrip) == 0) {
|
||||
double dPar0 = vCrvClass[i].dParS ;
|
||||
for ( int j = 0 ; j < ssize( vICCI) ; ++j) {
|
||||
int k = vICCI[j].bOverlap ? 1 : 0 ;
|
||||
if ( abs(vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM ||
|
||||
( abs( dEndA - vICCI[j].IciA[k].dU - dPar0) < EPS_PARAM)) {
|
||||
if ( abs( dEndB - vICCI[j].IciB[k].dU) < EPS_PARAM)
|
||||
dLastParam1 = 0 ;
|
||||
else
|
||||
dLastParam1 = vICCI[j].IciB[k].dU ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
int c = 0 ;
|
||||
while ( c < ssize( vMaskClass) - 1 && abs( vMaskClass[c].dParS - dLastParam1) > EPS_PARAM)
|
||||
++c ;
|
||||
|
||||
if ( vMaskClass[c].nClass == CRVC_IN && vMaskClass[c].dParS < dMax && vMaskClass[c].dParS >= dMin) {
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
|
||||
dLastParam1 = vMaskClass[c].dParE ;
|
||||
// se sono alla fine curva verifico se devo aggiungere anche un pezzo di inizio
|
||||
if ( dLastParam1 == dEndB && vMaskClass[0].nClass == CRVC_IN) {
|
||||
c = 0 ;
|
||||
vCrvStrip.emplace_back( ConvertCurveToComposite( pTrimMask->CopyParamRange( vMaskClass[c].dParS, vMaskClass[c].dParE))) ;
|
||||
dLastParam1 = vMaskClass[c].dParE ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
|
||||
vGeo.push_back(vCrvStrip[i]->Clone()) ;
|
||||
}
|
||||
@@ -694,25 +756,27 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
return false ;
|
||||
}
|
||||
|
||||
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo
|
||||
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo (nDir == 0)
|
||||
// oppure sul bordo superiore ( nDir == 1)
|
||||
Point3d pt ;
|
||||
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
|
||||
if ( nDir == 0)
|
||||
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
else
|
||||
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
|
||||
Vector3d vtJoin ;
|
||||
if ( nDir == 0)
|
||||
if ( nDir == 0) {
|
||||
pt.Set( abs( vU[p] - vU.front()), 0, 0) ;
|
||||
pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
|
||||
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
|
||||
else
|
||||
}
|
||||
else {
|
||||
pt.Set( 0, abs(vU[p] - vU.front()), 0) ;
|
||||
pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
|
||||
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
|
||||
}
|
||||
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i)
|
||||
vCrvStrip[i]->Translate( vtJoin) ;
|
||||
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
|
||||
vGeo.push_back(vCrvStrip[i]->Clone()) ;
|
||||
}
|
||||
@@ -725,7 +789,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vector<IGeoObj*> vGeo ;
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
|
||||
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
|
||||
}
|
||||
@@ -758,6 +822,20 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
ICRVCOMPOPOVECTOR vNewCrv ;
|
||||
int nCrvPrec = ssize( vUniformedCurves) ;
|
||||
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) {
|
||||
// se ho una solo curva piccola allora la salto
|
||||
if ( ssize(vIds) == 1) {
|
||||
double dLen = 0 ;
|
||||
int nId = vIds[0] - 1 ;
|
||||
bool bSkip = false ;
|
||||
if ( nId < nCrvPrec)
|
||||
bSkip = vUniformedCurves[nId]->GetLength( dLen) && dLen < dChainTol ;
|
||||
else
|
||||
bSkip = vCrvStrip[nId - ssize(vUniformedCurves)]->GetLength(dLen) && dLen < dChainTol ;
|
||||
|
||||
if ( bSkip)
|
||||
continue ;
|
||||
}
|
||||
|
||||
vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
|
||||
for ( int nId : vIds) {
|
||||
nId -= 1 ;
|
||||
@@ -767,6 +845,16 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ;
|
||||
}
|
||||
}
|
||||
#if SAVEMKUNIF_CRVS
|
||||
//debug
|
||||
vGeo.clear() ;
|
||||
for( int i = 0 ; i < ssize( vNewCrv); ++i){
|
||||
vGeo.push_back(vNewCrv[i]->Clone()) ;
|
||||
}
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\trim_crv_unif_AFTERchain.nge") ;
|
||||
//debug
|
||||
#endif
|
||||
|
||||
// aggiorno le curve
|
||||
vUniformedCurves.clear() ;
|
||||
vUniformedCurves.swap( vNewCrv) ;
|
||||
@@ -799,7 +887,7 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
|
||||
|
||||
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni
|
||||
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
|
||||
if ( ! vUniformedCurves[i]->IsClosed())
|
||||
if ( ! vUniformedCurves[i]->IsClosed() && ! vUniformedCurves[i]->Close())
|
||||
return false ;
|
||||
}
|
||||
|
||||
|
||||
+1322
-288
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -148,11 +148,14 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
|
||||
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
|
||||
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
|
||||
bool CreateBySetOfCurves( const ICURVEPOVECTOR& vCrvBez, bool bReduceToDeg3) override ;
|
||||
PNTVECTOR GetAllControlPoints( void) const ;
|
||||
PNTVECTOR GetAllControlPoints( void) const override ;
|
||||
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
|
||||
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
|
||||
bool RemoveCollapsedSpans( void) override ;
|
||||
bool SwapParameters( void) ;
|
||||
bool LimitSurfToTrimmedRegion( void) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen) override ;
|
||||
bool CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, double dSampleLen, BIPNTVECTOR& vSyncLines) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
int GetNgeId( void) const override ;
|
||||
|
||||
+175
-36
@@ -29,7 +29,9 @@
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVECLASSCRV 0
|
||||
#if SAVECLASSCRV
|
||||
#define SAVEADJUSTCRV 0
|
||||
#if SAVECLASSCRV || SAVEADJUSTCRV
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
@@ -112,8 +114,20 @@ SurfFlatRegion::AddExtLoop( ICurve* pCrv)
|
||||
pMyCrv->SetThickness( 0) ;
|
||||
// rimuovo eventuali sovrapposizioni (calcolate nel suo piano)
|
||||
ICURVEPLIST CrvLst ;
|
||||
|
||||
#if SAVEADJUSTCRV
|
||||
SaveGeoObj( pMyCrv->Clone(), "D:\\Temp\\inters\\CrvCrvInters\\before_adjust.nge") ;
|
||||
#endif
|
||||
|
||||
if ( ! AdjustLoops( Release( pMyCrv), CrvLst, true))
|
||||
return false ;
|
||||
|
||||
#if SAVEADJUSTCRV
|
||||
for ( auto& pSingCrv : CrvLst)
|
||||
vGeo.push_back( pSingCrv->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\after_adjust.nge") ;
|
||||
#endif
|
||||
|
||||
// aggiungo le singole curve
|
||||
int nExtAdded = 0 ;
|
||||
bool bOk = true ;
|
||||
@@ -174,14 +188,18 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
Vector3d vtExtr ;
|
||||
if ( pMyCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall())
|
||||
pMyCrv->SetExtrusion( Z_AX) ;
|
||||
// verifico non abbia auto-intersezioni che si attraversano o si sovrappongano
|
||||
SelfIntersCurve sInt( *pMyCrv) ;
|
||||
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
||||
return false ;
|
||||
|
||||
// verifico che sia esterna alle curve esterne degli altri chunk
|
||||
bool bOk = true ;
|
||||
CRVCVECTOR ccClass ;
|
||||
for ( auto i : m_vExtInd) {
|
||||
#if SAVEADJUSTCRV
|
||||
vGeo.clear() ;
|
||||
vGeo.push_back( pMyCrv->Clone()) ;
|
||||
vGeo.push_back( m_vpLoop[i]->Clone()) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\during_add_simpleExt.nge") ;
|
||||
#endif
|
||||
|
||||
IntersCurveCurve ccInt( *pMyCrv, *m_vpLoop[i]) ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 0, EPS_SMALL, ccClass) ||
|
||||
@@ -221,14 +239,9 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv, bool& bAdded)
|
||||
bool
|
||||
SurfFlatRegion::MyAddExtLoop( ICurve* pCrv)
|
||||
{
|
||||
try {
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
}
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
m_vExtInd.push_back( int( m_vpLoop.size()) - 1) ;
|
||||
m_nStatus = OK ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -309,10 +322,7 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
// sistemo il senso di rotazione (deve essere CW -> se N==Z+ area < 0, se N==Z- area > 0)
|
||||
if ( ( plPlane.GetVersN().z > 0 && dArea > 0) || ( plPlane.GetVersN().z < 0 && dArea < 0))
|
||||
pMyCrv->Invert() ;
|
||||
// verifico non abbia auto-intersezioni
|
||||
SelfIntersCurve sInt( *pMyCrv) ;
|
||||
if ( sInt.GetCrossOrOverlapIntersCount() > 0)
|
||||
return false ;
|
||||
|
||||
// ricerca del chunk in cui andrebbe inserito
|
||||
int nChunk = -1 ;
|
||||
for ( int i = 0 ; i < int( m_vExtInd.size()) ; ++ i) {
|
||||
@@ -359,23 +369,18 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv)
|
||||
bool
|
||||
SurfFlatRegion::MyAddIntLoop( ICurve* pCrv, int nChunk)
|
||||
{
|
||||
try {
|
||||
// se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
// altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
}
|
||||
catch (...) {
|
||||
return false ;
|
||||
//se da aggiungere all'ultimo chunk
|
||||
if ( nChunk == -1)
|
||||
m_vpLoop.push_back( pCrv) ;
|
||||
//altrimenti aggiungo al chunck indicato
|
||||
else {
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
if ( nLoopCnt == 0)
|
||||
return false ;
|
||||
int nOffset = m_vExtInd[nChunk] + nLoopCnt ;
|
||||
m_vpLoop.insert( m_vpLoop.begin() + nOffset, pCrv) ;
|
||||
for ( int i = nChunk + 1 ; i < int( m_vExtInd.size()) ; ++ i)
|
||||
++ m_vExtInd[i] ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -1551,7 +1556,7 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
||||
int nClass = ccInt.GetRegionCurveClassification() ;
|
||||
switch ( nClass){
|
||||
switch ( nClass) {
|
||||
default : // CCREGC_NULL
|
||||
return REGC_NULL ;
|
||||
case CCREGC_IN1 :
|
||||
@@ -1564,7 +1569,141 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion&
|
||||
return REGC_OUT ;
|
||||
case CCREGC_INTERS :
|
||||
return REGC_INTERS ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfFlatRegion::CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const
|
||||
{
|
||||
bInterference = false ;
|
||||
// verifico lo stato e il numero di chunk
|
||||
if ( m_nStatus != OK || m_vpLoop.empty() || nChunk >= GetChunkCount())
|
||||
return false ;
|
||||
// recupero rappresentazione base dell'altra regione
|
||||
const SurfFlatRegion& Reg2 = *GetBasicSurfFlatRegion( &Other) ;
|
||||
// verifico lo stato e il numero di chunk dell'altra regione
|
||||
if ( Reg2.m_nStatus != OK || Reg2.m_vpLoop.empty() || nOthChunk >= Reg2.GetChunkCount())
|
||||
return false ;
|
||||
|
||||
// verifico che le due regioni giacciano in piani paralleli
|
||||
if ( ! AreSameVectorApprox( m_frF.VersZ(), Reg2.m_frF.VersZ()))
|
||||
return false ;
|
||||
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
int nClass = GetChunkSimpleClassification( nChunk, Other, nOthChunk) ;
|
||||
if ( nClass == REGC_NULL)
|
||||
return false ;
|
||||
// se le regioni non hanno isole, allora ho già identificato se i Chunks fanno interferenza
|
||||
int nLoopCnt = GetLoopCount( nChunk) ;
|
||||
int nOtherLoopCnt = Other.GetLoopCount( nOthChunk) ;
|
||||
if ( nLoopCnt == 1 && nOtherLoopCnt == 1) {
|
||||
bInterference = ( nClass != REGC_OUT) ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
// --- a prescindere dalle isole presenti nei 2 Chunks in esame :
|
||||
// se i due loop esterni si intersecano tra loro o sono gli stessi, allora fanno per forza interferenza
|
||||
if ( nClass == REGC_INTERS || nClass == CCREGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// se invece sono esterni tra loro, allora non c'è interferenza
|
||||
else if ( nClass == REGC_OUT)
|
||||
return true ;
|
||||
// --- Analisi del loop interni :
|
||||
// se la curva esterna corrente è interna alla curva esterna dell'altro chunk
|
||||
else if ( nClass == REGC_IN1) {
|
||||
// se l'altro chunk non ha isole, c'è interferenza (a prescinere da numero di loop interni del primo chunk)
|
||||
if ( nOtherLoopCnt == 1) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv1Loc = GetMyLoop( nChunk, 0) ;
|
||||
// per ogni loop interno (isole)
|
||||
for ( int i = 1 ; i < nOtherLoopCnt ; ++ i) {
|
||||
const ICurve* pCrv2Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( m_frF, Reg2.m_frF))
|
||||
pCrv2Loc = Reg2.GetMyLoop( nOthChunk, i) ;
|
||||
else {
|
||||
pCopyCrv.Set( Reg2.GetMyLoop( nOthChunk, i)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( Reg2.m_frF, m_frF) ;
|
||||
pCrv2Loc = pCopyCrv ;
|
||||
}
|
||||
// classifico il loop esterno del chunk della prima regione rispetto all'interno corrente del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv1Loc, *pCrv2Loc) ;
|
||||
int nInternalClass = ccInt.GetRegionCurveClassification() ;
|
||||
// se le curve non sono classificabili, errore
|
||||
if ( nInternalClass == REGC_NULL)
|
||||
return false ;
|
||||
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
|
||||
else if ( nInternalClass == REGC_IN1)
|
||||
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
|
||||
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
|
||||
else if ( nInternalClass == REGC_OUT)
|
||||
return true ;
|
||||
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
|
||||
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// negli altri casi ho un orientamento errato dei loop o delle regioni
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
// se la curva esterna dell'altro chunk è interna alla curva esterna corrente
|
||||
else if ( nClass == REGC_IN2) {
|
||||
// se l'altro chunk non ha isole, c'è interferenza
|
||||
if ( nLoopCnt == 1) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// curva esterna del chunk della prima regione (ovviamente già in locale al riferimento intrinseco)
|
||||
const ICurve* pCrv2Loc = Reg2.GetMyLoop( nChunk, 0) ;
|
||||
// per ogni loop interno (isole)
|
||||
for ( int i = 1 ; i < nLoopCnt ; ++ i) {
|
||||
const ICurve* pCrv1Loc = nullptr ;
|
||||
PtrOwner<ICurve> pCopyCrv ;
|
||||
if ( AreSameFrame( Reg2.m_frF, m_frF))
|
||||
pCrv1Loc = GetMyLoop( nOthChunk, i) ;
|
||||
else {
|
||||
pCopyCrv.Set( GetMyLoop( nOthChunk, i)->Clone()) ;
|
||||
if ( IsNull( pCopyCrv))
|
||||
return false ;
|
||||
pCopyCrv->LocToLoc( m_frF, Reg2.m_frF) ;
|
||||
pCrv1Loc = pCopyCrv ;
|
||||
}
|
||||
// classifico il loop esterno del chunk della prima regione rispetto a quello del chunk della seconda
|
||||
IntersCurveCurve ccInt( *pCrv2Loc, *pCrv1Loc) ;
|
||||
int nInternalClass = ccInt.GetRegionCurveClassification() ;
|
||||
// se le curve non sono classificabili, errore
|
||||
if ( nInternalClass == REGC_NULL)
|
||||
return false ;
|
||||
// se la curva di bordo corrente è interna (le isole girano al contrario) all'isola corrente
|
||||
else if ( nInternalClass == REGC_IN1)
|
||||
; // non faccio nulla, potrebbe non essere l'isola adatta per la classificazione
|
||||
// se la curva di bordo corrente è esterna (le isole girano al contrario) all'isola corrente, allora non ho interferenza
|
||||
else if ( nInternalClass == REGC_OUT)
|
||||
return true ;
|
||||
// se la curva di bordo corrente interseca l'isola o coincide con essa allora c'è interferenza
|
||||
else if ( nInternalClass == REGC_INTERS || nInternalClass == REGC_SAME) {
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
// negli altri casi ho un orientamento errato dei loop o delle regioni
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
// in questo la curva di bordo è interna ad ogni isola ma interna anche al loop esterno, quindi esiste interferenza
|
||||
bInterference = true ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -107,6 +107,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
bool GetChunkArea( int nChunk, double& dArea) const override ;
|
||||
bool GetChunkPerimeter( int nChunk, double& dLen) const override ;
|
||||
int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides
|
||||
bool CheckChunkInterference( int nChunk, const ISurfFlatRegion& Other, int nOthChunk, bool& bInterference) const override ; // compare alls
|
||||
bool GetChunkMaxOffset( int nChunk, double& dOffs) const override ;
|
||||
int GetLoopCount( int nChunk) const override ;
|
||||
int GetLoopCurveCount( int nChunk, int nLoop) const override ;
|
||||
@@ -139,6 +140,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW
|
||||
SurfTriMesh* CalcAuxSurf( double dLinTol, double dAngTolDeg) const ;
|
||||
|
||||
friend class MyCAvSimpleSurfFrMove ;
|
||||
friend class MyCAvSurfFrMove ;
|
||||
|
||||
private :
|
||||
enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
|
||||
#define SAVELOOPS 0
|
||||
#if SAVELOOPS
|
||||
std::vector<IGeoObj*> vGeo ;
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -172,6 +178,13 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other)
|
||||
pSfr.Set( new( nothrow) SurfFlatRegion) ;
|
||||
else
|
||||
pSfr.Set( MyNewSurfFromLoops( vpLoop)) ;
|
||||
|
||||
#if SAVELOOPS
|
||||
for (int i = 0 ; i < ssize( vpLoop) ; ++i)
|
||||
vGeo.push_back( vpLoop[i]) ;
|
||||
SaveGeoObj( vGeo, "D:\\Temp\\inters\\CrvCrvInters\\NewLoops.nge") ;
|
||||
#endif
|
||||
|
||||
if ( IsNull( pSfr)) {
|
||||
MyTestAndDelete( vpCurve) ;
|
||||
MyTestAndDelete( vpLoop) ;
|
||||
|
||||
+37
-13
@@ -1188,8 +1188,10 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
else {
|
||||
if ( ! pSfr->Add( *pSfrTria))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
@@ -1201,14 +1203,18 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
return false ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||
PolyLine PL ;
|
||||
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
vPL.emplace_back( PL) ;
|
||||
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
||||
vPL.clear() ;
|
||||
return false ;
|
||||
}
|
||||
vPL.emplace_back( PL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1259,8 +1265,10 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
else {
|
||||
if ( ! pSfr->Add( *pSfrTria))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1274,14 +1282,18 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
return true ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||
PolyLine PL ;
|
||||
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
vPL.emplace_back( PL) ;
|
||||
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
||||
vPL.clear() ;
|
||||
return false ;
|
||||
}
|
||||
vPL.emplace_back( PL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3810,12 +3822,19 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
||||
BBox3d b3Box ;
|
||||
PtrOwner<ISurfTriMesh> pStmShell ;
|
||||
} ;
|
||||
// vettore di shell con vettori dei propri triangoli (per accelerare nei casi degeneri)
|
||||
INTMATRIX mShellTria( m_nShells) ;
|
||||
for ( int i = 0 ; i < ssize( m_vTria) ; ++ i) {
|
||||
if ( m_vTria[i].nShell < m_nShells)
|
||||
mShellTria[m_vTria[i].nShell].push_back( i) ;
|
||||
}
|
||||
// classificazione delle shell
|
||||
vector<SHELLINFO> vOuterShells ;
|
||||
vector<SHELLINFO> vInnerShells ;
|
||||
INTVECTOR vOpenShells ;
|
||||
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
|
||||
// se la shell è chiusa
|
||||
if ( IsShellClosed( nSh)) {
|
||||
if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) {
|
||||
// creo una superficie clonata dalla shell
|
||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
|
||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||
@@ -3827,7 +3846,9 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
||||
BBox3d b3Box ;
|
||||
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
|
||||
// la inserisco nel vettore opportuno
|
||||
if ( dVol > 0)
|
||||
if ( abs( dVol) < 1 * 1 * EPS_SMALL)
|
||||
vOpenShells.push_back( nSh) ;
|
||||
else if ( dVol > 0)
|
||||
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
else
|
||||
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
@@ -3979,6 +4000,7 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
||||
return false ;
|
||||
// ciclo sui triangoli della shell
|
||||
bool bClosed = true ;
|
||||
int nTriaCnt = 0 ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// se triangolo non cancellato e della shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
@@ -3989,10 +4011,12 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
||||
bClosed = false ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
++ nTriaCnt ;
|
||||
}
|
||||
}
|
||||
// restituisco il risultato
|
||||
return bClosed ;
|
||||
return ( bClosed && nTriaCnt >= 4) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -352,10 +352,6 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
|
||||
}
|
||||
// se ho fatto solo 1 split orizzontale e ho due celle foglie nId = 0 e nId = 1
|
||||
if ( m_mTree.size() == 3 && ! m_mTree.at(-1).IsSplitVert()) {
|
||||
m_mTree[0].m_nLeft = -1 ;
|
||||
m_mTree[0].m_nRight = -1 ;
|
||||
m_mTree[1].m_nLeft = -1 ;
|
||||
m_mTree[1].m_nRight = -1 ;
|
||||
m_mTree[0].SetSplitDirVert( true) ;
|
||||
Split( 0) ;
|
||||
m_mTree[1].SetSplitDirVert( true) ;
|
||||
|
||||
+706
-66
@@ -36,13 +36,13 @@
|
||||
#include "/EgtDev/Include/EGkIntersLineBox.h"
|
||||
#include "/EgtDev/Include/EGkIntersCurvePlane.h"
|
||||
#include "/EgtDev/Include/EGkSurfTriMeshAux.h"
|
||||
#include "/EgtDev/Include/EGkRotationMinimizingFrame.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <numeric>
|
||||
|
||||
// -------------------------- Debug --------------------------------------------
|
||||
#define DEBUG 0
|
||||
#define DEBUG_BASIC_BORDERS 0
|
||||
#define DEBUG_CHAIN_CURVES 0
|
||||
#define DEBUG_ANG_APPROX 0
|
||||
@@ -63,11 +63,12 @@
|
||||
#define DEBUG_EDGES 0
|
||||
#define DEBUG_SHAPE_STM 0
|
||||
#define DEBUG_HOLES 0
|
||||
#define DEBUG_SMOOTH_CURVATURE 0
|
||||
#if DEBUG_BASIC_BORDERS || DEBUG_CHAIN_CURVES || DEBUG_ANG_APPROX || DEBUG_BEZIER_INTERP || \
|
||||
DEBUG_FACE_SEARCH || DEBUG_FACE_SEARCH_TRIA_MODIF || DEBUG_BRK_POINTS || DEBUG_BRK_THICK || \
|
||||
DEBUG_BRK || DEBUG_BORDERS_BY_NORMALS || DEBUG_SYNC_POINTS || DEBUG_SYNC_INTERPOLATION || \
|
||||
DEBUG_BEZIER_RULED || DEBUG_CURVATURE || DEBUG_SIMPLE_PATCHES || DEBUG_SURF_PATCHES || \
|
||||
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG
|
||||
DEBUG_RAW_EDGES || DEBUG_EDGES || DEBUG_SHAPE_STM || DEBUG_HOLES || DEBUG_SMOOTH_CURVATURE
|
||||
#include "CurveLine.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
@@ -284,6 +285,63 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL)
|
||||
return true ;
|
||||
}
|
||||
|
||||
////-----------------------------------------------------------------------------
|
||||
//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
|
||||
//// Patches di curve di Bezier
|
||||
//static bool
|
||||
//ApproxBorder( ICurveComposite* pCrvCompo, double dLinTol, double dAngTol, double dAngTolSplit)
|
||||
//{
|
||||
// // N.B.:in futuro bisognerebbe fare l'approssimazione direttamente con le bezier.
|
||||
//
|
||||
// // Controllo dei parametri
|
||||
// if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid())
|
||||
// return false ;
|
||||
//
|
||||
// // splitto la curva considerando la tolleranza angolare
|
||||
// ICRVCOMPOPOVECTOR vCC ;
|
||||
// SplitCurveCompoByAngTol( pCrvCompo, dAngTolSplit, vCC) ;
|
||||
// #if DEBUG_BEZIER_INTERP
|
||||
// VT.clear() ;
|
||||
// for( int i = 0 ; i < ssize(vCC) ; ++i)
|
||||
// VT.push_back( vCC[i]->Clone()) ;
|
||||
// SaveGeoObj( VT, "D:\\Temp\\trimming\\AngBorderApprox.nge") ;
|
||||
// VT.clear() ;
|
||||
// #endif
|
||||
//
|
||||
// pCrvCompo->Clear() ;
|
||||
//
|
||||
// // Ogni PolyLine ricavata viene approssimata con un tratto di Bezier
|
||||
// const double MAXLEN = 1.5 ;
|
||||
// for ( ICurveComposite* pCC : vCC) {
|
||||
// // Se meno di due curve, non la considero ( non dovrebbe mai capitare )
|
||||
// if ( pCC->GetCurveCount() < 2)
|
||||
// continue ;
|
||||
// PolyArc PA ;
|
||||
// if ( ! pCC->ApproxWithArcs( dLinTol, dAngTol, PA))
|
||||
// return false ;
|
||||
// CurveComposite CrvTemp ;
|
||||
// if ( ! CrvTemp.FromPolyArc( PA) || ! CrvTemp.MergeCurves( dLinTol, dAngTol))
|
||||
// return false ;
|
||||
// #if DEBUG_BEZIER_INTERP
|
||||
// VT.emplace_back( CrvTemp->Clone()) ;
|
||||
// #endif
|
||||
// // Converto in Bezier
|
||||
// PtrOwner<ICurve> pCrvBz( CurveToBezierCurve( &CrvTemp)) ;
|
||||
// if ( IsNull( pCrvBz) || ! pCrvBz->IsValid()) {
|
||||
// LOG_ERROR( GetEGkLogger(), "Error : converrting curve to bezier") ;
|
||||
// return false ;
|
||||
// }
|
||||
// // Aggiungo il tratto approssimato alla curva finale complessiva
|
||||
// if ( ! pCrvCompo->AddCurve( Release( pCrvBz)))
|
||||
// return false ;
|
||||
// }
|
||||
// #if DEBUG_BEZIER_INTERP
|
||||
// SaveGeoObj( VT, VC, "D:\\Temp\\trimming\\bezier_edge.nge") ;
|
||||
// #endif
|
||||
//
|
||||
// return ( pCrvCompo->IsValid()) ;
|
||||
//}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
|
||||
// Patches di curve di Bezier
|
||||
@@ -3475,10 +3533,11 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool
|
||||
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
|
||||
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol,
|
||||
BIPNTVECTOR& vBiPts)
|
||||
const Plane3d& plStart, const Plane3d& plEnd, const Vector3d vtAuxStart, const Vector3d vtAuxEnd,
|
||||
double dLinTol, BIPNTVECTOR& vBiPts)
|
||||
{
|
||||
vBiPts.clear() ;
|
||||
const double dLinAngTol = 15 * EPS_SMALL ; // tolleranza sulla lunghezza della corda dell'angolo di tolleranza
|
||||
|
||||
// Verifico che le curve siano valide
|
||||
if ( pGuide == nullptr || ! pGuide->IsValid() ||
|
||||
@@ -3508,52 +3567,134 @@ InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICur
|
||||
// Interpolo le normali dei piani rispetto a tale valore
|
||||
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
|
||||
vtN.Normalize() ;
|
||||
Vector3d vtAux = Media( vtAuxStart, vtAuxEnd, dInterPar) ; vtAux.Normalize() ;
|
||||
// Definisco il piano di intersezione
|
||||
Point3d ptCurr ;
|
||||
if ( ! pCrv->GetEndPoint( ptCurr))
|
||||
return false ;
|
||||
|
||||
// con i piani
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
|
||||
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
|
||||
VT.emplace_back( Release( frCurr)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
// Recupero il parametro di intersezione tra la curva e il piano
|
||||
#if 0
|
||||
VT.clear() ; VC.clear() ;
|
||||
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
||||
VT.emplace_back( Release( PT)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
||||
VECT->ChangeBase( ptCurr) ;
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
||||
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
||||
VT.emplace_back( Release( pSfrPlane)) ;
|
||||
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
||||
VT.emplace_back( Release( VECT)) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
||||
if ( IntCP.GetIntersCount() == 0)
|
||||
return false ; // ambiguità
|
||||
// Recupero il punto della prima intersezione trovata
|
||||
Point3d ptInt ;
|
||||
double dPar ;
|
||||
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
|
||||
return false ;
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ;
|
||||
VT.emplace_back( Release( ptG)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
if ( false) {
|
||||
VT.clear() ; VC.clear() ;
|
||||
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
||||
VT.emplace_back( Release( PT)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
||||
VECT->ChangeBase( ptCurr) ;
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
||||
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
||||
VT.emplace_back( Release( pSfrPlane)) ;
|
||||
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
||||
VT.emplace_back( Release( VECT)) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
}
|
||||
#endif
|
||||
// Memorizzo tale punto
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ;
|
||||
|
||||
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
||||
bool bFound = false ;
|
||||
if ( IntCP.GetIntersCount() != 0) {
|
||||
// Recupero il punto della prima intersezione trovata
|
||||
Point3d ptIntClosest ;
|
||||
double dPar ;
|
||||
IntCP.GetIntersPointNearTo( ptCurr, ptIntClosest, dPar) ;
|
||||
// verifico che sia allineato con la direzione che dovrebbe avere
|
||||
Vector3d vtDir = ptIntClosest - ptCurr ;
|
||||
vtDir.Normalize() ;
|
||||
double dDiff = (vtDir - vtAux).Len() ;
|
||||
if ( dDiff < dLinAngTol) {
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptIntClosest) ;
|
||||
VT.emplace_back( Release( ptG)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
//Memorizzo tale punto
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptIntClosest)) ;
|
||||
bFound = true ;
|
||||
}
|
||||
else if ( IntCP.GetIntersCount() > 1) {
|
||||
double dMinDiff = INFINITO ;
|
||||
Point3d ptBest ;
|
||||
for ( int j = 0 ; j < IntCP.GetIntersCount() ; ++j) {
|
||||
IntCrvPlnInfo icpi ; IntCP.GetIntCrvPlnInfo( j, icpi) ;
|
||||
Point3d ptInt = icpi.Ici->ptI ;
|
||||
double dDiff = ( ptInt - ptCurr).Len() ;
|
||||
if ( dDiff < dMinDiff) {
|
||||
dMinDiff = dDiff ;
|
||||
ptBest = ptInt ;
|
||||
}
|
||||
}
|
||||
if ( dMinDiff < dLinAngTol)
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFound) {
|
||||
// applico la direzione desiderata nel punto corrente della guida
|
||||
// calcolo la lunghezza dell'isocurva in quella zona
|
||||
Point3d ptS1, ptS2 ;
|
||||
pGuide->GetStartPoint( ptS1) ;
|
||||
pOtherGuide->GetStartPoint( ptS2);
|
||||
double dDistRef = Dist( ptS1, ptS2) ;
|
||||
double dParamOther = -1. ;
|
||||
int nFlag = -1 ;
|
||||
Point3d ptEnd = ptCurr + (vtAux * dDistRef) ;
|
||||
if ( ! DistPointCurve( ptEnd, *pOtherGuide).GetParamAtMinDistPoint( 0, dParamOther, nFlag))
|
||||
return false ;
|
||||
|
||||
// nell'intorno del più vicino, cerco l'isocurva più vicina alla direzione desiderata
|
||||
Point3d ptBest ;
|
||||
double dMinDiff = INFINITO ;
|
||||
double dSearchLen = 3. ;
|
||||
double dStepLen = 0.1 ;
|
||||
double dCurrLenOther ; pOtherGuide->GetLengthAtParam( dParamOther, dCurrLenOther) ;
|
||||
double dLenOther ; pOtherGuide->GetLength( dLenOther) ;
|
||||
dCurrLenOther -= dSearchLen ;
|
||||
dCurrLenOther = Clamp( dCurrLenOther, 0., dLenOther) ;
|
||||
for ( int j = 0 ; j < 2 * dSearchLen / dStepLen ; ++j) {
|
||||
dCurrLenOther += j * dStepLen ;
|
||||
if ( dCurrLenOther > dLenOther)
|
||||
break ;
|
||||
double dCurrParOther = 0 ; pOtherGuide->GetParamAtLength( dCurrLenOther, dCurrParOther) ;
|
||||
Point3d ptCurrOther ; pOtherGuide->GetPointD1D2( dCurrParOther, ICurve::FROM_MINUS, ptCurrOther) ;
|
||||
Vector3d vtDir = ptCurrOther - ptCurr ; vtDir.Normalize() ;
|
||||
double dDiff = ( vtDir - vtAux).Len() ;
|
||||
if ( dDiff < dMinDiff) {
|
||||
dMinDiff = dDiff ;
|
||||
ptBest = ptCurrOther ;
|
||||
}
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
VT.clear() ;
|
||||
VC.clear() ;
|
||||
VT.emplace_back( pGuide->Clone()) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
PtrOwner<IGeoVector3d> vtFirst( CreateGeoVector3d()) ; vtFirst->Set( -vtN * 12, ptCurrOther) ;
|
||||
VT.emplace_back( Release( vtFirst)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> vtCurr( CreateGeoVector3d()) ; vtCurr->Set( -vtDir * 12, ptCurrOther) ;
|
||||
VT.emplace_back( Release( vtCurr)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
}
|
||||
if ( dMinDiff < 2 * dLinAngTol)
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptBest)) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -3838,8 +3979,8 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
! pCompoEdge1->IsValid() || ! pCompoEdge2->IsValid())
|
||||
return false ;
|
||||
|
||||
// Controllo sulla tolleranza lineare
|
||||
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
//// Controllo sulla tolleranza lineare
|
||||
//double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
|
||||
#if DEBUG_SYNC_POINTS
|
||||
VT.clear() ; VC.clear() ;
|
||||
@@ -3850,26 +3991,26 @@ GetTrimmingSurfBzSyncPoints( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
#endif
|
||||
|
||||
// Definisco la superficie di Bezier rigata
|
||||
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol))) ;
|
||||
PtrOwner<SurfBezier> pSBzRuled( GetBasicSurfBezier( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncPoints, 20.0))) ;
|
||||
if ( IsNull( pSBzRuled) || ! pSBzRuled->IsValid())
|
||||
return false ;
|
||||
|
||||
// Recupero i punti di sincronizzazione e li restituisco
|
||||
ICURVEPOVECTOR vCrv ;
|
||||
pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
|
||||
vSyncPoints.reserve( vCrv.size()) ;
|
||||
for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
|
||||
if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
|
||||
#if DEBUG_SYNC_POINTS
|
||||
VT.emplace_back( vCrv[i]->Clone()) ;
|
||||
VC.emplace_back( LIME) ;
|
||||
#endif
|
||||
Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
|
||||
if ( ! AreSamePointApprox( ptStart, ptEnd))
|
||||
vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
|
||||
}
|
||||
}
|
||||
//// Recupero i punti di sincronizzazione e li restituisco
|
||||
// ICURVEPOVECTOR vCrv ;
|
||||
// pSBzRuled->GetAllPatchesIsocurves( false, vCrv) ;
|
||||
// vSyncPoints.reserve( vCrv.size()) ;
|
||||
// for ( int i = 0 ; i < ssize( vCrv) ; ++ i) {
|
||||
// if ( ! IsNull( vCrv[i]) && vCrv[i]->IsValid()) {
|
||||
// #if DEBUG_SYNC_POINTS
|
||||
// VT.emplace_back( vCrv[i]->Clone()) ;
|
||||
// VC.emplace_back( LIME) ;
|
||||
// #endif
|
||||
// Point3d ptStart ; vCrv[i]->GetStartPoint( ptStart) ;
|
||||
// Point3d ptEnd ; vCrv[i]->GetEndPoint( ptEnd) ;
|
||||
// if ( ! AreSamePointApprox( ptStart, ptEnd))
|
||||
// vSyncPoints.emplace_back( make_pair( ptStart, ptEnd)) ;
|
||||
// }
|
||||
// }
|
||||
|
||||
#if DEBUG_SYNC_POINTS
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\BorderSyncPoints.nge") ;
|
||||
@@ -3900,7 +4041,7 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
|
||||
// Verifico i valori delle tolleranze
|
||||
double dMyLinTol = Clamp( dLinTol, EPS_SMALL, 1e5 * EPS_SMALL) ;
|
||||
double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
|
||||
//double dMyAngTol = Clamp( dAngTol, EPS_ANG_SMALL, 60.) ;
|
||||
|
||||
// Verifico le due curve di sincronizzazione abbiano gli estremi sulle due curve di bordo
|
||||
Point3d ptS1 ; pSync1->GetStartPoint( ptS1) ;
|
||||
@@ -4008,18 +4149,18 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
Vector3d vtStart1, vtStart2 ;
|
||||
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
|
||||
return false ;
|
||||
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ;
|
||||
Vector3d vtAuxStart = ptE1 - ptS1 ; vtAuxStart.Normalize() ;
|
||||
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
|
||||
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||
Vector3d vtN = OrthoCompo( vtMTan, vtAuxStart) ; vtN.Normalize() ;
|
||||
Plane3d plStart ;
|
||||
if ( ! plStart.Set( ptS1, vtN))
|
||||
return false ;
|
||||
Vector3d vtEnd1, vtEnd2 ;
|
||||
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
|
||||
return false ;
|
||||
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ;
|
||||
Vector3d vtAuxEnd = ptE2 - ptS2 ; vtAuxEnd.Normalize() ;
|
||||
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
|
||||
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||
vtN = OrthoCompo( vtMTan, vtAuxEnd) ; vtN.Normalize() ;
|
||||
Plane3d plEnd ;
|
||||
if ( ! plEnd.Set( ptS2, vtN))
|
||||
return false ;
|
||||
@@ -4038,13 +4179,15 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
|
||||
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
|
||||
BIPNTVECTOR vBiPts1 ;
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1))
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts1))
|
||||
return false ;
|
||||
|
||||
vtAuxStart *= -1 ;
|
||||
vtAuxEnd *= -1 ;
|
||||
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
|
||||
BIPNTVECTOR vBiPts2 ;
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2))
|
||||
return false ;
|
||||
//if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts2))
|
||||
// return false ;
|
||||
|
||||
// Restituisco le Curve di Sincronizzazione
|
||||
// [Da Bordo 1 a Bordo 2 originale]
|
||||
@@ -4110,7 +4253,8 @@ GetTrimmingRuledBezier( const CISURFPVECTOR& vSurf, const ICurve* pCrvEdge1,
|
||||
|
||||
// Se non ho punti di controllo forzati
|
||||
if ( vSyncPoints.empty()) {
|
||||
pSurfBz.Set( GetSurfBezierRuled( pCompoEdge1, pCompoEdge2, ISurfBezier::RLT_B_MINDIST_PLUS, dMyLinTol)) ;
|
||||
BIPNTVECTOR vSyncLines ;
|
||||
pSurfBz.Set( GetSurfBezierRuledSmooth( pCompoEdge1, pCompoEdge2, vSyncLines, 20.0)) ;
|
||||
if ( IsNull( pSurfBz) || ! pSurfBz->IsValid()) {
|
||||
LOG_ERROR( GetEGkLogger(), "Error in Trimming : Ruled Bezier invalid") ;
|
||||
return nullptr ;
|
||||
@@ -4746,7 +4890,7 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
|
||||
// Scorro le curve successive
|
||||
for ( int j = i + 1 ; nIndJ == -1 && j < ssize( vHoles) ; ++ j) {
|
||||
// Recupero la curva corrente, se non presente allora passo alla successiva
|
||||
if ( IsNull( vHoles[i].pCompoHole))
|
||||
if ( IsNull( vHoles[j].pCompoHole))
|
||||
continue ;
|
||||
// Se il tipo è differente non possono essere in coppia
|
||||
if ( vHoles[i].nType != vHoles[j].nType)
|
||||
@@ -4841,3 +4985,499 @@ GetTrimmingHoleBorders( const CISURFPVECTOR& vpSurf, const Point3d& ptRef, doubl
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
struct PntInfo{
|
||||
Point3d pt ;
|
||||
double dDist ;
|
||||
Vector3d vtPos ;
|
||||
PntInfo( const Point3d& _pt, double _dDist, const Vector3d& _vtPos) :
|
||||
pt( _pt), dDist( _dDist), vtPos( _vtPos) {;}
|
||||
};
|
||||
typedef vector<PntInfo> PNTINFOVECTOR ;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool
|
||||
FillPntInfo( const PNTVECTOR& vPnt, const ICurveComposite* pCC, PNTINFOVECTOR& vPntInfo)
|
||||
{
|
||||
for ( int i = 0 ; i < ssize( vPnt) - 3 ; i+=3) {
|
||||
bool bOk = false ;
|
||||
const ICurveBezier* pSubCrv = GetCurveBezier( pCC->GetCurve( i / 3)) ;
|
||||
for ( int j = i == 0 ? 0 : 1 ; j <= 3 ; ++j) {
|
||||
Point3d pt = pSubCrv->GetControlPoint( j, &bOk) ;
|
||||
double dDist = 0 ;
|
||||
Vector3d vtPos = V_NULL ;
|
||||
if ( j > 0 && j < 3){
|
||||
DistPointCurve dpc( pt, *pSubCrv) ;
|
||||
dpc.GetDist( dDist) ;
|
||||
int nFlag = - 1 ;
|
||||
Point3d ptMinDist ;
|
||||
dpc.GetMinDistPoint( 0., ptMinDist, nFlag) ;
|
||||
vtPos = pt - ptMinDist ;
|
||||
}
|
||||
vPntInfo.emplace_back( pt, dDist, vtPos) ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
static bool
|
||||
RemoveInflexionPoints( PNTVECTOR& vPnt, PNTINFOVECTOR& vPntInfo, PNTINFOVECTOR& vPntRefInfo)
|
||||
{
|
||||
// se trovo tre punti di fila che sono dallo stesso lato, opposto a quello degli altri punti attorno, allora cerco di spostarli lungo la
|
||||
// normale alla superficie in modo da evitare cambi di concavità
|
||||
bool bSameSideAsPrev = true ;
|
||||
double dSmallDist = 5 * EPS_SMALL ;
|
||||
for ( int i = 2 ; i < ssize( vPntInfo) - 2 ; ++i) {
|
||||
// se è un punto di split o sta sulla curva vado avanti
|
||||
if ( vPntInfo[i].dDist < dSmallDist)
|
||||
continue ;
|
||||
int nPrev = vPntInfo[i-1].dDist < EPS_ZERO ? i - 2 : i - 1 ;
|
||||
double dProj = vPntInfo[i].vtPos * vPntInfo[nPrev].vtPos ;
|
||||
bSameSideAsPrev = dProj > EPS_ZERO ;
|
||||
if ( abs(dProj) < EPS_ZERO){
|
||||
int nPrevPrev = nPrev - 1 ;
|
||||
dProj = vPntInfo[i].vtPos * vPntInfo[nPrevPrev].vtPos ;
|
||||
bSameSideAsPrev = dProj > EPS_ZERO ;
|
||||
}
|
||||
if ( ! bSameSideAsPrev) {
|
||||
// devo verificare anche che sia diverso anche dal successivo ( o dal quello dopo ancora, se il successivo sta sulla curva)
|
||||
bool bCurrOrPrev = vPntInfo[i+1].dDist < EPS_ZERO ;
|
||||
int nFirst, nSecond, nThird ;
|
||||
if ( bCurrOrPrev) {
|
||||
nFirst = i ;
|
||||
nSecond = i + 1 ;
|
||||
nThird = i + 2 ;
|
||||
}
|
||||
else {
|
||||
nFirst = i - 2 ;
|
||||
nSecond = i - 1 ;
|
||||
nThird = i ;
|
||||
}
|
||||
int nNext = bCurrOrPrev ? i + 2 : i + 1 ;
|
||||
// se il successivo è diverso ho un terzetto anomalo da aggiustare
|
||||
// altrimenti ho un cambio naturale di concavità
|
||||
if ( vPntInfo[i].vtPos * vPntInfo[nNext].vtPos < 0 || vPntInfo[nNext].dDist < dSmallDist) {
|
||||
// ruoto il terzetto fino a matchare la tangente sull'altra curva
|
||||
// ruoto il punto solo se non stava già esattamente sulla SubCrv ( che suppongo essere un tratto rettilineo)
|
||||
if ( vPntInfo[nFirst].dDist > dSmallDist) {
|
||||
Vector3d vtCurr = vPntInfo[nSecond].pt - vPntInfo[nFirst].pt ;
|
||||
Vector3d vtRef = vPntRefInfo[nSecond].pt - vPntRefInfo[nFirst].pt ;
|
||||
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
|
||||
bool bDet = false ;
|
||||
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
|
||||
if ( abs(dAng) > 170)
|
||||
dAng = 180 - dAng ;
|
||||
vPnt[nFirst].Rotate( vPnt[nSecond], vtAx, dAng) ;
|
||||
}
|
||||
if ( vPntInfo[nThird].dDist > dSmallDist) {
|
||||
Vector3d vtCurr = vPntInfo[nThird].pt - vPntInfo[nSecond].pt ;
|
||||
Vector3d vtRef = vPntRefInfo[nThird].pt - vPntRefInfo[nSecond].pt ;
|
||||
Vector3d vtAx = vPntRefInfo[nSecond].pt - vPntInfo[nSecond].pt ;
|
||||
bool bDet = false ;
|
||||
double dAng = 0 ; vtCurr.GetRotation(vtRef, vtAx, dAng, bDet) ;
|
||||
if ( abs(dAng) > 170)
|
||||
dAng = 180 - dAng ;
|
||||
vPnt[nThird].Rotate( vPnt[nSecond], vtAx, dAng) ;
|
||||
}
|
||||
if ( bCurrOrPrev)
|
||||
i += 2 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
|
||||
// Le curve vengono modificate entro una data tolleranza, in modo che
|
||||
ISurfBezier*
|
||||
RegolarizeBordersLocallyRMF( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol)
|
||||
{
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
#endif
|
||||
|
||||
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
|
||||
Point3d ptS1 = bpIsoStart.first ;
|
||||
Point3d ptS2 = bpIsoEnd.first ;
|
||||
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
|
||||
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
|
||||
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
if ( nDegU != 3)
|
||||
return nullptr ;
|
||||
// individuo quali isocurve sono state indicate come inizio e fine
|
||||
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
|
||||
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
|
||||
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
|
||||
pCrv2->Invert() ;
|
||||
double dParS1 = -1 ; double dParS2 = -1 ;
|
||||
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
|
||||
return nullptr ;
|
||||
int nUS1 = int ( dParS1) * nDegU ;
|
||||
int nUS2 = int ( dParS2) * nDegU ;
|
||||
if ( nUS1 > nUS2) {
|
||||
swap( nUS1, nUS2) ;
|
||||
swap( dParS1, dParS2) ;
|
||||
swap( ptS1, ptS2) ;
|
||||
swap( vtDir1, vtDir2) ;
|
||||
}
|
||||
PtrOwner<ICurveComposite> pCrvOrig1( ConvertCurveToComposite( pCrv1->CopyParamRange( dParS1, dParS2))) ;
|
||||
PtrOwner<ICurveComposite> pCrvOrig2( ConvertCurveToComposite( pCrv2->CopyParamRange( dParS1, dParS2))) ;
|
||||
|
||||
/////////////////////// versione con RMF
|
||||
// campiono finemente la prima curva e ottengo il punto che dovrebbe stare sull'altra curva
|
||||
Vector3d vtTang1 ; pCrvOrig1->GetStartDir( vtTang1) ;
|
||||
Frame3d frStart1 ; frStart1.Set( ptS1, vtTang1, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
|
||||
RotationMinimizingFrame rmf ; rmf.Set( pCrvOrig1, frStart1) ;
|
||||
double dLenTot = 0. ; pCrvOrig1->GetLength( dLenTot) ;
|
||||
double dStep = dLenTot / ceil( dLenTot) ;
|
||||
FRAME3DVECTOR vRMF ;
|
||||
rmf.GetFramesByStep( dStep, true, vRMF) ;
|
||||
PNTVECTOR vPnt1 ;
|
||||
PolyLine PL2 ;
|
||||
double dLenCurr = 0. ;
|
||||
double dWidth = vtDir1.Len() ;
|
||||
for ( int i = 0 ; i < ssize( vRMF) ; ++i) {
|
||||
double dPar ; pCrvOrig1->GetParamAtLength( dLenCurr, dPar) ;
|
||||
Point3d pt0 ; pCrvOrig1->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt0) ;
|
||||
Point3d pt1 = pt0 + vRMF[i].VersX() * dWidth ;
|
||||
vPnt1.push_back( pt1) ;
|
||||
PL2.AddUPoint( i, pt1) ;
|
||||
|
||||
dLenCurr += dStep ;
|
||||
}
|
||||
|
||||
CurveComposite CCToApprox2 ; CCToApprox2.FromPolyLine( PL2) ;
|
||||
Vector3d vtStart2 ; pCrvOrig2->GetStartDir( vtStart2) ;
|
||||
Vector3d vtEnd2 ; pCrvOrig2->GetEndDir( vtEnd2) ;
|
||||
PtrOwner<ICurveComposite> pCC2( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox2, 0.05, vtStart2, vtEnd2))) ;
|
||||
if ( IsNull( pCC2) || ! pCC2->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
// dalla seconda ricostruisco la prima
|
||||
Vector3d vtTang2 ; pCC2->GetStartDir( vtTang2) ;
|
||||
Frame3d frStart2 ; frStart2.Set( bpIsoStart.second, vtTang2, vtDir1) ; // uso la tangente (come z) e l'isocurva in V (come x) per il frame iniziale
|
||||
RotationMinimizingFrame rmf2 ; rmf2.Set( pCC2, frStart2) ;
|
||||
double dLenTot2 = 0. ; pCC2->GetLength( dLenTot2) ;
|
||||
double dStep2 = dLenTot2 / ceil( dLenTot2) ;
|
||||
FRAME3DVECTOR vRMF2 ;
|
||||
rmf2.GetFramesByStep( dStep2, true, vRMF2) ;
|
||||
PNTVECTOR vPnt0 ;
|
||||
PolyLine PL1 ;
|
||||
double dLenCurr2 = 0. ;
|
||||
for ( int i = 0 ; i < ssize( vRMF2) ; ++i) {
|
||||
double dPar ; pCC2->GetParamAtLength( dLenCurr2, dPar) ;
|
||||
Point3d pt1 ; pCC2->GetPointD1D2( dPar, ICurve::FROM_MINUS, pt1) ;
|
||||
Point3d pt0 = pt1 - vRMF2[i].VersX() * dWidth ;
|
||||
vPnt0.push_back( pt0) ;
|
||||
PL1.AddUPoint( i, pt0) ;
|
||||
|
||||
dLenCurr2 += dStep2 ;
|
||||
}
|
||||
|
||||
CurveComposite CCToApprox1 ; CCToApprox1.FromPolyLine( PL1) ;
|
||||
Vector3d vtStart1 ; pCrvOrig1->GetStartDir( vtStart1) ;
|
||||
Vector3d vtEnd1 ; pCrvOrig1->GetEndDir( vtEnd1) ;
|
||||
PtrOwner<ICurveComposite> pCC1( ConvertCurveToComposite( ApproxCurveWithBezier( &CCToApprox1, 0.05, vtStart1, vtEnd1))) ;
|
||||
if ( IsNull( pCC1) || ! pCC1->IsValid())
|
||||
return nullptr ;
|
||||
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
for( int i = 0 ; i < ssize( vPnt1) ; ++i) {
|
||||
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt1[i]) ;
|
||||
VT.push_back( Release( pPT)) ;
|
||||
}
|
||||
for( int i = 0 ; i < ssize( vPnt0) ; ++i) {
|
||||
PtrOwner<IGeoPoint3d> pPT( CreateGeoPoint3d()) ; pPT->Set( vPnt0[i]) ;
|
||||
VT.push_back( Release( pPT)) ;
|
||||
}
|
||||
VT.push_back( pCC1->Clone()) ;
|
||||
VT.push_back( pCC2->Clone()) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_RMF.nge") ;
|
||||
#endif
|
||||
|
||||
// controllo di essere rimasto in tolleranza
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
|
||||
// creo una surf di bezier uguale a quella di partenza, ma a cui cambio la parte da modificare
|
||||
PtrOwner<SurfBezier> pNewSurf( CreateBasicSurfBezier()) ;
|
||||
int nNewCrvs = pCC1->GetCurveCount() ;
|
||||
if ( pCC2->GetCurveCount() != nNewCrvs)
|
||||
return nullptr ;
|
||||
int nDiff = nNewCrvs - pCrvOrig1->GetCurveCount() ;
|
||||
pNewSurf->Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
// copio la parte uguale
|
||||
for ( int i = 0 ; i < nSpanU * nDegU + 1 ; ++i) {
|
||||
if ( i > nUS1 && i < nUS2)
|
||||
continue ;
|
||||
bool bOk = false ;
|
||||
Point3d pt = pSurfBz->GetControlPoint( i, 0, &bOk) ;
|
||||
int nNewI = i ;
|
||||
if ( i > nUS2)
|
||||
nNewI = i + nDiff ;
|
||||
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
|
||||
pt = pSurfBz->GetControlPoint( i, 1, &bOk) ;
|
||||
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
|
||||
}
|
||||
// aggiungo la parte diversa
|
||||
for ( int i = 0 ; i < nNewCrvs * nDegU + 1 ; ++i) {
|
||||
int nSub = i / 3 ;
|
||||
int nPnt = i % 3 ;
|
||||
if ( nSub == nNewCrvs) {
|
||||
--nSub ;
|
||||
nPnt = 3 ;
|
||||
}
|
||||
const ICurveBezier* pSubCrv1 = GetCurveBezier( pCC1->GetCurve( nSub)) ;
|
||||
Point3d pt = pSubCrv1->GetControlPoint( nPnt) ;
|
||||
int nNewI = i + nUS1 ;
|
||||
pNewSurf->SetControlPoint( nNewI, 0, pt) ;
|
||||
const ICurveBezier* pSubCrv2 = GetCurveBezier( pCC2->GetCurve( nSub)) ;
|
||||
pt = pSubCrv2->GetControlPoint( nPnt) ;
|
||||
pNewSurf->SetControlPoint( nNewI, 1, pt) ;
|
||||
}
|
||||
|
||||
return Release( pNewSurf) ;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Funzione per la regolarizzazione delle curve di bordo di una lavorazione di trim
|
||||
// Le curve vengono modificate entro una data tolleranza, in modo che
|
||||
ISurfBezier*
|
||||
RegolarizeBordersLocally( const ISurfBezier* pSurfBz, const BIPOINT& bpIsoStart, const BIPOINT& bpIsoEnd, double dTol, int nType)
|
||||
{
|
||||
if ( nType == RegolarizeType::RMF)
|
||||
return RegolarizeBordersLocallyRMF( pSurfBz, bpIsoStart, bpIsoEnd, dTol) ;
|
||||
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
#endif
|
||||
|
||||
// prendo per buone le isocurve di inizio e fine tratto e devo identificare tra loro le isocurve che creano troppo twist e che sono da raddrizzare
|
||||
Point3d ptS1 = bpIsoStart.first ;
|
||||
Point3d ptS2 = bpIsoEnd.first ;
|
||||
Vector3d vtDir1 = bpIsoStart.second - ptS1 ;
|
||||
Vector3d vtDir2 = bpIsoEnd.second - ptS2 ;
|
||||
//double dInterpolateAngTol = 4 ;
|
||||
//double dAngInterp = 0 ;
|
||||
//vtDir1.GetAngle( vtDir2, dAngInterp) ;
|
||||
//bool bInterpolate = dAngInterp > dInterpolateAngTol ;
|
||||
|
||||
int nDegU, nDegV, nSpanU, nSpanV ;
|
||||
bool bRat, bTrimmed ;
|
||||
pSurfBz->GetInfo( nDegU, nDegV, nSpanU, nSpanV, bRat, bTrimmed) ;
|
||||
if ( nDegU != 3)
|
||||
return nullptr ;
|
||||
// individuo quali isocurve sono state indicate come inizio e fine
|
||||
PtrOwner<ICurveComposite> pCrv1( pSurfBz->GetSingleEdge3D( false, 2)) ;
|
||||
PtrOwner<ICurveComposite> pCrv2( pSurfBz->GetSingleEdge3D( false, 0)) ;
|
||||
// inverto la curva corrispondente al bordo 2 della bezier per avere le due guide concordi
|
||||
pCrv2->Invert() ;
|
||||
double dParS1 = -1 ; double dParS2 = -1 ;
|
||||
if ( ! pCrv1->GetParamAtPoint( ptS1, dParS1) || ! pCrv1->GetParamAtPoint( ptS2, dParS2))
|
||||
return nullptr ;
|
||||
int nUS1 = int ( dParS1) * nDegU ;
|
||||
int nUS2 = int ( dParS2) * nDegU ;
|
||||
bool bInverted = false ;
|
||||
if ( nUS1 > nUS2) {
|
||||
swap( nUS1, nUS2) ;
|
||||
swap( dParS1, dParS2) ;
|
||||
swap( ptS1, ptS2) ;
|
||||
swap( vtDir1, vtDir2) ;
|
||||
bInverted = true ;
|
||||
}
|
||||
PtrOwner<ICurve> pCrvOrig1( pCrv1->CopyParamRange( dParS1, dParS2)) ;
|
||||
PtrOwner<ICurve> pCrvOrig2( pCrv2->CopyParamRange( dParS1, dParS2)) ;
|
||||
double dLen = 0 ; pCrvOrig1->GetLength( dLen) ;
|
||||
|
||||
///// versione con correzioni a mano
|
||||
Point3d ptPrevS = ptS1 ;
|
||||
Point3d ptPrevE = ! bInverted ? bpIsoStart.second : bpIsoEnd.second ;
|
||||
Vector3d vtIsoPrev = ptPrevE - ptPrevS ; vtIsoPrev.Normalize() ;
|
||||
Point3d ptBez ; Vector3d vtNCurr ;
|
||||
pSurfBz->GetPointNrmD1D2( dParS1, 0.5, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez, vtNCurr) ;
|
||||
int nPoints = ( nUS2 - nUS1) * nDegU + 1 ;
|
||||
PNTVECTOR vPnt0 ; vPnt0.reserve( nPoints) ; vPnt0.push_back( ptPrevS) ;
|
||||
PNTVECTOR vPnt1 ; vPnt1.reserve( nPoints) ; vPnt1.push_back( ptPrevE) ;
|
||||
// salvo il secondo punto di controllo della patch
|
||||
bool bOk = false ;
|
||||
Point3d ptSecond1Curr = pSurfBz->GetControlPoint( nUS1 + 1, 0, &bOk) ;
|
||||
vPnt0.push_back( ptSecond1Curr) ;
|
||||
Point3d ptSecond2Curr = pSurfBz->GetControlPoint( nUS1 + 1, 1, &bOk) ;
|
||||
vPnt1.push_back( ptSecond2Curr) ;
|
||||
// scorro le isocurve di separazione tra patch
|
||||
for ( int i = nUS1 + 3 ; i < nUS2 ; i +=3) {
|
||||
// recupero precedente e successivo
|
||||
Point3d ptThird1Prev = pSurfBz->GetControlPoint( i - 1, 0, &bOk) ;
|
||||
Point3d ptThird2Prev = pSurfBz->GetControlPoint( i - 1, 1, &bOk) ;
|
||||
Point3d ptSecond1Next = pSurfBz->GetControlPoint( i + 1, 0, &bOk) ;
|
||||
Point3d ptSecond2Next = pSurfBz->GetControlPoint( i + 1, 1, &bOk) ;
|
||||
// recupero corrente e verifico la torsione
|
||||
Point3d ptCurr1 = pSurfBz->GetControlPoint( i, 0, &bOk) ;
|
||||
Point3d ptCurr2 = pSurfBz->GetControlPoint( i, 1, &bOk) ;
|
||||
Vector3d vtIsoCurr = ptCurr2 - ptCurr1 ;
|
||||
double dDist = vtIsoCurr.Len() ;
|
||||
vtIsoCurr.Normalize() ;
|
||||
//Vector3d vtDirPrev = vtIsoPrev ^ vtNPrev ;
|
||||
Vector3d vtDirCurr = ptSecond1Next - ptCurr1 ; vtDirCurr.Normalize() ;
|
||||
double dLenCurr = 0 ; pCrvOrig1->GetLengthAtParam( i, dLenCurr) ;
|
||||
double dCoeff = dLenCurr / dLen ;
|
||||
Vector3d vtIsoInterp = Media( vtDir1, vtDir2, dCoeff) ; vtIsoInterp.Normalize() ;
|
||||
bool bDet = false ;
|
||||
//double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoPrev, vtDirPrev, dAng, bDet) ;
|
||||
double dAng = 0 ; vtIsoCurr.GetRotation( vtIsoInterp, vtDirCurr, dAng, bDet) ;
|
||||
vtNCurr = vtDirCurr ^ vtIsoCurr ; vtNCurr.Rotate( vtDirCurr, dAng) ;
|
||||
double dSinAngTol = sin( 5 * DEGTORAD) ;
|
||||
Vector3d vtPrev1 = ptCurr1 - ptThird1Prev ; vtPrev1.Normalize() ;
|
||||
Vector3d vtNext1 = ptSecond1Next - ptCurr1 ; vtNext1.Normalize() ;
|
||||
bool bAngularPoint1 = ! AreSameVectorEpsilon( vtPrev1, vtNext1, dSinAngTol) ;
|
||||
Vector3d vtPrev2 = ptCurr2 - ptThird2Prev ; vtPrev2.Normalize() ;
|
||||
Vector3d vtNext2 = ptSecond2Next - ptCurr2 ; vtNext2.Normalize() ;
|
||||
bool bAngularPoint2 = ! AreSameVectorEpsilon( vtPrev2, vtNext2, dSinAngTol) ;
|
||||
if ( abs( dAng) > 0) {
|
||||
// se l'isocurva di separazione dalla patch successiva è torta rispetto alla precedente
|
||||
// allora prendo il penultimo punto della curva precedente, il punto di joint e il secondo della prossima e li sposto lungo la normale della superficie
|
||||
dDist *= dAng * DEGTORAD / 2 ;
|
||||
if ( ! bAngularPoint1) {
|
||||
// se non ho un punto angoloso muovo tutto il terzetto insieme
|
||||
ptThird1Prev -= vtNCurr * dDist ;
|
||||
ptSecond1Next -= vtNCurr * dDist ;
|
||||
ptCurr1 -= vtNCurr * dDist ;
|
||||
}
|
||||
else {
|
||||
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
|
||||
DistPointLine dpl( ptCurr1, ptThird1Prev, ptSecond1Next, true) ;
|
||||
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
|
||||
Vector3d vtCorrDir = ptMinDist - ptCurr1 ; vtCorrDir.Normalize() ;
|
||||
double dProjDir = vtNCurr * vtCorrDir ;
|
||||
if ( dProjDir < 0)
|
||||
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv0 near an angular point") ;
|
||||
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr1)) ;
|
||||
ptCurr1 -= vtCorrDir * dDistCorr ;
|
||||
}
|
||||
if ( ! bAngularPoint2) {
|
||||
ptThird2Prev += vtNCurr * dDist ;
|
||||
ptSecond2Next += vtNCurr * dDist ;
|
||||
ptCurr2 += vtNCurr * dDist ;
|
||||
}
|
||||
else {
|
||||
// altrimenti sposto solo il punto corrente verso la congiungente tra il precedente e il successivo
|
||||
DistPointLine dpl( ptCurr2, ptThird2Prev, ptSecond2Next, true) ;
|
||||
Point3d ptMinDist ; dpl.GetMinDistPoint( ptMinDist) ;
|
||||
Vector3d vtCorrDir = ptMinDist - ptCurr2 ; vtCorrDir.Normalize() ;
|
||||
double dProjDir = vtNCurr * vtCorrDir ;
|
||||
if ( dProjDir < 0)
|
||||
LOG_ERROR( GetEGkLogger(), "Error : regolarizing crv1 near an angular point") ;
|
||||
double dDistCorr = min( dDist, Dist( ptMinDist, ptCurr2)) ;
|
||||
ptCurr2 += vtCorrDir * dDistCorr ;
|
||||
}
|
||||
}
|
||||
vPnt0.push_back( ptThird1Prev) ;
|
||||
vPnt0.push_back( ptCurr1) ;
|
||||
vPnt0.push_back( ptSecond1Next) ;
|
||||
|
||||
vPnt1.push_back( ptThird2Prev) ;
|
||||
vPnt1.push_back( ptCurr2) ;
|
||||
vPnt1.push_back( ptSecond2Next) ;
|
||||
|
||||
//vtIsoPrev = ptCurr2 - ptCurr1 ; vtIsoPrev.Normalize() ;
|
||||
//vtNPrev = ( ptSecond1Next - ptCurr1) ^ vtIsoPrev ; vtNPrev.Normalize() ;
|
||||
}
|
||||
// aggiungo gli ultimi due punti
|
||||
Point3d ptThird1Prev = pSurfBz->GetControlPoint( nUS2 - 1, 0, &bOk) ;
|
||||
vPnt0.push_back( ptThird1Prev) ;
|
||||
Point3d ptFourth1Curr = pSurfBz->GetControlPoint( nUS2, 0, &bOk) ;
|
||||
vPnt0.push_back( ptFourth1Curr) ;
|
||||
Point3d ptThird2Prev = pSurfBz->GetControlPoint( nUS2 - 1, 1, &bOk) ;
|
||||
vPnt1.push_back( ptThird2Prev) ;
|
||||
Point3d ptFourth2Curr = pSurfBz->GetControlPoint( nUS2, 1, &bOk) ;
|
||||
vPnt1.push_back( ptFourth2Curr) ;
|
||||
|
||||
PtrOwner<ICurveComposite> pCC1( CreateCurveComposite()) ;
|
||||
PtrOwner<ICurveComposite> pCC2( CreateCurveComposite()) ;
|
||||
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
|
||||
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
|
||||
cb1->SetControlPoint( 0, vPnt0[i]) ;
|
||||
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
|
||||
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
|
||||
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
|
||||
pCC1->AddCurve( Release( cb1)) ;
|
||||
|
||||
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
|
||||
cb2->SetControlPoint( 0, vPnt1[i]) ;
|
||||
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
|
||||
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
|
||||
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
|
||||
pCC2->AddCurve( Release( cb2)) ;
|
||||
}
|
||||
|
||||
////// N.B.:dovrei tener conto anche della patch PRECEDENTE e SUCCESSIVA a quelle indicate, altrimenti non vedo se ho creato flessi al bordo della zona
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.push_back( pCC1->Clone()) ;
|
||||
VT.push_back( pCC2->Clone()) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized_first_step.nge") ;
|
||||
#endif
|
||||
|
||||
// ora verifico l'eventuale presenza di cambi di concavità non desiderati
|
||||
// se ne trovo su una curva e non sull'altra allora ruoto il terzetto di punti della curva con flesso in modo
|
||||
// da matchare la tangente dell'altra curva
|
||||
PNTINFOVECTOR vPntInfo1, vPntInfo2 ;
|
||||
FillPntInfo( vPnt0, pCC1, vPntInfo1) ;
|
||||
FillPntInfo( vPnt1, pCC2, vPntInfo2) ;
|
||||
|
||||
RemoveInflexionPoints( vPnt0, vPntInfo1, vPntInfo2) ;
|
||||
RemoveInflexionPoints( vPnt1, vPntInfo2, vPntInfo1) ;
|
||||
|
||||
pCC1->Clear() ;
|
||||
pCC2->Clear() ;
|
||||
for ( int i = 0 ; i < ssize( vPnt0) - 3 ; i+=3) {
|
||||
PtrOwner<ICurveBezier> cb1( CreateCurveBezier()) ; cb1->Init( 3, false) ;
|
||||
cb1->SetControlPoint( 0, vPnt0[i]) ;
|
||||
cb1->SetControlPoint( 1, vPnt0[i+1]) ;
|
||||
cb1->SetControlPoint( 2, vPnt0[i+2]) ;
|
||||
cb1->SetControlPoint( 3, vPnt0[i+3]) ;
|
||||
pCC1->AddCurve( Release( cb1)) ;
|
||||
|
||||
PtrOwner<ICurveBezier> cb2( CreateCurveBezier()) ; cb2->Init( 3, false) ;
|
||||
cb2->SetControlPoint( 0, vPnt1[i]) ;
|
||||
cb2->SetControlPoint( 1, vPnt1[i+1]) ;
|
||||
cb2->SetControlPoint( 2, vPnt1[i+2]) ;
|
||||
cb2->SetControlPoint( 3, vPnt1[i+3]) ;
|
||||
pCC2->AddCurve( Release( cb2)) ;
|
||||
}
|
||||
|
||||
// controllo di essere rimasto in tolleranza
|
||||
double dErr = 0 ;
|
||||
CalcApproxError( pCrvOrig1, pCC1, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
CalcApproxError( pCrvOrig2, pCC2, dErr, 20) ;
|
||||
if ( dErr > dTol)
|
||||
return nullptr ;
|
||||
|
||||
PtrOwner<ISurfBezier> pNewSurf( pSurfBz->Clone()) ;
|
||||
// aggiorno i punti di controllo della superficie di bezier
|
||||
for ( int i = 0 ; i < ssize( vPnt0) ; ++i) {
|
||||
pNewSurf->SetControlPoint( nUS1 + i, 0, vPnt0[i]) ;
|
||||
pNewSurf->SetControlPoint( nUS1 + i, 1, vPnt1[i]) ;
|
||||
}
|
||||
#if DEBUG_SMOOTH_CURVATURE
|
||||
VT.clear() ;
|
||||
VT.push_back( Release(pCC1)) ;
|
||||
VT.push_back( Release(pCC2)) ;
|
||||
SaveGeoObj( VT, "C:\\Temp\\bezier\\ruled\\smoothness\\regolarized.nge") ;
|
||||
#endif
|
||||
|
||||
return Release( pNewSurf) ;
|
||||
}
|
||||
+208
@@ -29,8 +29,21 @@
|
||||
#include <thread>
|
||||
#include <future>
|
||||
|
||||
#define DEBUG_REMOVE_FINS 0
|
||||
#if DEBUG_REMOVE_FINS
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include "/EgtDev/Include/EGkGeoPoint3d.h"
|
||||
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
||||
std::vector<IGeoObj*> VT ;
|
||||
std::vector<Color> VC ;
|
||||
#endif
|
||||
|
||||
using namespace std ;
|
||||
|
||||
#if !defined(_WIN64)
|
||||
int VolZmap::m_nDexelNbr = 0 ;
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ;
|
||||
|
||||
@@ -55,6 +68,13 @@ VolZmap::VolZmap(void)
|
||||
//----------------------------------------------------------------------------
|
||||
VolZmap::~VolZmap( void)
|
||||
{
|
||||
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
|
||||
#if !defined(_WIN64)
|
||||
int nDexelNbr = 0 ;
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
nDexelNbr += m_nDim[i] ;
|
||||
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
|
||||
#endif
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -75,6 +95,13 @@ VolZmap::Clear( void)
|
||||
m_nNumBlock = 0 ;
|
||||
m_nConnectedCompoCount = 0 ;
|
||||
m_MapFrame.Reset() ;
|
||||
// Se versione 32-bit aggiorno il numero di Dexel complessivi rimuovendo il numero dei correnti
|
||||
#if !defined(_WIN64)
|
||||
int nDexelNbr = 0 ;
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
nDexelNbr += m_nDim[i] ;
|
||||
m_nDexelNbr = max( 0, m_nDexelNbr - nDexelNbr) ;
|
||||
#endif
|
||||
for ( int i = 0 ; i < N_MAPS ; ++ i) {
|
||||
m_nNx[i] = 0 ;
|
||||
m_nNy[i] = 0 ;
|
||||
@@ -1864,6 +1891,187 @@ VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::RemoveFins( const Vector3d& vtDir, double dThick)
|
||||
{
|
||||
// Verifico la Validità dello ZMap
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Per sicurezza normalizzo la direzione
|
||||
Vector3d vtMyDir = vtDir ;
|
||||
if ( ! vtMyDir.Normalize())
|
||||
return false ;
|
||||
double dMyThick = max( 10. * EPS_SMALL, dThick) ;
|
||||
|
||||
// Creo lo ZMap per i riferimenti degli intervalli sulle griglie
|
||||
PtrOwner<VolZmap> pZMapCopy( CloneBasicVolZmap( this)) ;
|
||||
if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid())
|
||||
return false ;
|
||||
|
||||
// Creo uno ZMap per gli intervalli da aggiungere e successivamente da rimuovere
|
||||
VolZmap ZMapExtra ;
|
||||
if ( ! ZMapExtra.CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0],
|
||||
m_dStep, IsTriDexel()))
|
||||
return false ;
|
||||
|
||||
const double FIN_ANG_DEG_TOL = 55. ; // Approssimazione per eccesso dell'angolo massimo possibile tra una direzione generica
|
||||
// e un versore della terna globale ( arccos( 1 / sqrt( 3) ~ 54.375)
|
||||
const double COS_FIN_ANG_DEG_TOL = cos( FIN_ANG_DEG_TOL * DEGTORAD) ;
|
||||
const int NUM_TOOL = 1000 ; // Identificativo Utensile per riconoscere le parti rimosse
|
||||
|
||||
// NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente
|
||||
// Ciclo sulle griglie
|
||||
DBLVECTOR vdThicks ;
|
||||
if ( IsTriDexel())
|
||||
vdThicks = { dThick, dThick, dThick} ;
|
||||
else
|
||||
vdThicks = { dThick} ;
|
||||
for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) {
|
||||
// Verifico se l'angolo tra la direzione degli spilloni della griglia corrente è sotto alla tolleranza rispetto alla direzione
|
||||
double dCosDir = ( nGrid == 0 ? vtMyDir.z :
|
||||
( nGrid == 1 ? vtMyDir.x :
|
||||
vtMyDir.y)) ;
|
||||
if ( abs( dCosDir) < COS_FIN_ANG_DEG_TOL + EPS_ANG_SMALL)
|
||||
continue ;
|
||||
// Aggiorno l'effettivo valore dello spessore da considerare
|
||||
double dCurrThick = dMyThick / abs( dCosDir) ; // (sicuramente esiste, essendo 55deg il limite)
|
||||
vdThicks[nGrid] = dCurrThick ;
|
||||
// Ciclo sul numero di dexel presenti nella Copia
|
||||
for ( int nDex = 0 ; nDex < ssize( pZMapCopy->m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se il dexel corrente non ha sotto-intervalli passo al successivo
|
||||
if ( pZMapCopy->m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Indici del dexel
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// Scorro gli intervalli presenti
|
||||
for ( int nInfo = 0 ; nInfo < ssize( pZMapCopy->m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
// Recupero l'intervallo corrente
|
||||
Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ;
|
||||
// Se entrambi gli estremi dell'intervallo non sono stati toccati dall'utensile, allora passo al successivo
|
||||
bool bAnalyze = ( ( Interval.nToolMin == 1 && Interval.nToolMax == 1) ||
|
||||
( Interval.dMax > m_dMaxZ[nGrid] - EPS_SMALL || Interval.dMin < m_dMinZ[nGrid] + EPS_SMALL)) ;
|
||||
if ( ! bAnalyze)
|
||||
continue ;
|
||||
// Se la lunghezza dell'intervallo è superiore allo spessore richiesto, non faccio nulla
|
||||
double dLen = Interval.dMax - Interval.dMin ;
|
||||
if ( dLen > dCurrThick + EPS_ZERO)
|
||||
continue ;
|
||||
// Se ZMap composto da una sola griglia, elimino il contributo lungo la direzione corrente
|
||||
if ( ! IsTriDexel()) {
|
||||
SubtractIntervals( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL,
|
||||
- Interval.vtMinN, - Interval.vtMaxN, NUM_TOOL, true) ;
|
||||
}
|
||||
// Se Tridexel, aggiungo il contributo del cubetto corrente allo ZMap Extra
|
||||
else
|
||||
ZMapExtra.AddStripInterval( nGrid, nI, nJ, Interval.dMin - EPS_SMALL, Interval.dMax + EPS_SMALL, NUM_TOOL) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Se non ho aggiunto alcun elemento allo ZMap Extra, non devo fare nulla
|
||||
if ( ! ZMapExtra.IsValid())
|
||||
return true ;
|
||||
#if DEBUG_REMOVE_FINS
|
||||
SaveGeoObj( ZMapExtra.Clone(), "C:\\Temp\\VolZMapSubt0.nge") ;
|
||||
#endif
|
||||
|
||||
// Ciclo sulle griglie dello ZMap Extra
|
||||
for ( int nGrid = 0 ; nGrid < ZMapExtra.m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < ssize( ZMapExtra.m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se l'intervallo è vuoto, non faccio nulla
|
||||
if ( ZMapExtra.m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Indici del dexel
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// Scorro i gli Intervalli dello Spillone corrente
|
||||
for ( int nInfo = 0 ; nInfo < ssize( ZMapExtra.m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
double dMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMin ;
|
||||
double dMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].dMax ;
|
||||
Vector3d vtNMin = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMinN ;
|
||||
Vector3d vtNMax = ZMapExtra.m_Values[nGrid][nDex][nInfo].vtMaxN ;
|
||||
// sottraggo tali contributi
|
||||
SubtractIntervals( nGrid, nI, nJ, dMin, dMax, - vtNMin, - vtNMax, NUM_TOOL, true) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! IsValid())
|
||||
return true ;
|
||||
#if DEBUG_REMOVE_FINS
|
||||
SaveGeoObj( this->Clone(), "C:\\Temp\\VolZMapSubt1.nge") ;
|
||||
#endif
|
||||
|
||||
// Sistemo le Normali sullo ZMap ricavato
|
||||
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se l'Intervallo è vuoto non faccio nulla
|
||||
if ( m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Indici del dexel
|
||||
int nI = nDex % m_nNx[nGrid] ;
|
||||
int nJ = nDex / m_nNx[nGrid] ;
|
||||
// Scorro gli intervalli dello spillone corrente
|
||||
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
// Se intervallo con estremo minimo derivante dalla sottrazione con ZMapExtra, medio le normali
|
||||
int nToolMin = m_Values[nGrid][nDex][nInfo].nToolMin ;
|
||||
if ( nToolMin == NUM_TOOL) {
|
||||
// Recupero il valore minimo, se sul bordo dello ZMap corrente non faccio nulla
|
||||
double dMin = m_Values[nGrid][nDex][nInfo].dMin ;
|
||||
if ( dMin > m_dMinZ[nGrid] + EPS_SMALL) {
|
||||
Vector3d vtMinN = V_NULL ;
|
||||
double dZMin = INFINITO ;
|
||||
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMin, vtMyDir, dThick, true, 1, vtMinN, dZMin)) {
|
||||
vtMinN = - ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
|
||||
dZMin = dMin ;
|
||||
}
|
||||
m_Values[nGrid][nDex][nInfo].vtMinN = vtMinN ;
|
||||
m_Values[nGrid][nDex][nInfo].dMin = dZMin ;
|
||||
}
|
||||
}
|
||||
// Se intervallo con estremo massimo derivante dalla sottrazione con ZMapExtra, medio le normali
|
||||
int nToolMax = m_Values[nGrid][nDex][nInfo].nToolMax ;
|
||||
if ( nToolMax == NUM_TOOL) {
|
||||
// Recupero il valore massimo, se sul bordo dello ZMap corrente non faccio nulla
|
||||
double dMax = m_Values[nGrid][nDex][nInfo].dMax ;
|
||||
if ( dMax < m_dMaxZ[nGrid] - EPS_SMALL) {
|
||||
Vector3d vtMaxN = V_NULL ;
|
||||
double dZMax = INFINITO ;
|
||||
if ( ! pZMapCopy->ComputePointAndNormalForRemovingFins( nGrid, nI, nJ, dMax, vtMyDir, dThick, false, 1, vtMaxN, dZMax)) {
|
||||
vtMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() : nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY()) ;
|
||||
dZMax = dMax ;
|
||||
}
|
||||
m_Values[nGrid][nDex][nInfo].vtMaxN = vtMaxN ;
|
||||
m_Values[nGrid][nDex][nInfo].dMax = dZMax ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Riassegno il Tool dell'utensile alle nuove parti
|
||||
for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) {
|
||||
// Ciclo sul numero di dexel presenti
|
||||
for ( int nDex = 0 ; nDex < ssize( m_Values[nGrid]) ; ++ nDex) {
|
||||
// Se l'Intervallo è vuoto non faccio nulla
|
||||
if ( m_Values[nGrid][nDex].empty())
|
||||
continue ;
|
||||
// Scorro gli intervalli dello spillone corrente
|
||||
for ( int nInfo = 0 ; nInfo < ssize( m_Values[nGrid][nDex]) ; ++ nInfo) {
|
||||
if ( m_Values[nGrid][nDex][nInfo].nToolMin == NUM_TOOL)
|
||||
m_Values[nGrid][nDex][nInfo].nToolMin = 1 ;
|
||||
if ( m_Values[nGrid][nDex][nInfo].nToolMax == NUM_TOOL)
|
||||
m_Values[nGrid][nDex][nInfo].nToolMax = 1 ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt)
|
||||
|
||||
@@ -81,10 +81,10 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
public : // IVolZmap
|
||||
bool CopyFrom( const IGeoObj* pGObjSrc) override ;
|
||||
bool Clear( void) override ;
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0) override ;
|
||||
bool Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError = nullptr) override ;
|
||||
bool CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox = 0, int* nError = nullptr) override ;
|
||||
int GetBlockCount( void) const override ;
|
||||
int GetBlockUpdatingCounter( int nBlock) const override ;
|
||||
bool GetBlockTriangles( int nBlock, TRIA3DEXVECTOR& vTria) const override ;
|
||||
@@ -151,6 +151,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool AddSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool SubtractSurfTm( const ISurfTriMesh* pStm) override ;
|
||||
bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ;
|
||||
bool RemoveFins( const Vector3d& vtDir, double dThick) override ;
|
||||
bool Offset( double dOffs, int nType) override ;
|
||||
|
||||
public : // IGeoObjRW
|
||||
@@ -226,7 +227,16 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
typedef std::unordered_map<int, Voxel> VoxelContainer ;
|
||||
// Unordered map per la coerenza topologica
|
||||
typedef std::unordered_map<int, bool> InterVoxMatter ;
|
||||
|
||||
#if !defined(_WIN64)
|
||||
// Numero massimo approssimativo di Dexel per versione 32-bit per evitare Crash con memoria
|
||||
#if defined(_DEBUG)
|
||||
static const int MAX_DEXEL_32_BIT = 3000000 + 1 ;
|
||||
#else
|
||||
static const int MAX_DEXEL_32_BIT = 5000000 + 1 ;
|
||||
#endif
|
||||
static int m_nDexelNbr ; // numero corrente di Dexel presenti
|
||||
#endif
|
||||
|
||||
private :
|
||||
bool CopyFrom( const VolZmap& clSrc) ;
|
||||
bool ResetGraphics( void) ;
|
||||
@@ -262,6 +272,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax,
|
||||
double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin,
|
||||
const Vector3d& vtToolMax) ;
|
||||
bool AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum) ;
|
||||
bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax,
|
||||
Vector3d& vtMin, Vector3d& vtMax) ;
|
||||
// Spostamenti utensile
|
||||
@@ -382,9 +393,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
double& dU1, double& dU2) const ;
|
||||
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
|
||||
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
|
||||
bool bTapLow, bool bTapUp,
|
||||
@@ -486,6 +494,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
// Funzioni per Offset di Zmap
|
||||
bool OffsetFillet( double dOffs) ;
|
||||
bool OffsetSharped( double dOffs, int nType) ;
|
||||
// Funzione analisi punti/Normali per Alette
|
||||
bool GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc) ;
|
||||
bool ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
|
||||
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
|
||||
Vector3d& vtN, double& dNewZ) ;
|
||||
|
||||
private :
|
||||
enum Move5Axis {
|
||||
|
||||
@@ -2071,127 +2071,6 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
|
||||
{
|
||||
// Porto la linea nel riferimento del cilindro
|
||||
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
||||
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
||||
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
int nBasInt = 0 ;
|
||||
if ( abs( vtV.z) > EPS_ZERO) {
|
||||
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 1 ;
|
||||
vtN1 = Z_AX ;
|
||||
}
|
||||
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 2 ;
|
||||
vtN2 = - Z_AX ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
if ( nBasInt == 3) {
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
||||
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
||||
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
||||
DBLVECTOR vdRoots ;
|
||||
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
|
||||
// Epsilon per piani di tappo
|
||||
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
||||
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
if ( nRoot == 2) {
|
||||
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
||||
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
||||
-- nRoot ;
|
||||
}
|
||||
if ( nRoot >= 1) {
|
||||
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
||||
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
||||
if ( nRoot == 2)
|
||||
vdRoots[0] = vdRoots[1] ;
|
||||
-- nRoot ;
|
||||
}
|
||||
}
|
||||
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
if ( nRoot == 2) {
|
||||
// Punti di intersezione con la superficie del cilindro
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
ptInt2 = ptP + vdRoots[1] * vtV ;
|
||||
// Determino le normali
|
||||
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
// Punto di intersezione
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
|
||||
+79
-14
@@ -27,8 +27,8 @@ using namespace std ;
|
||||
// ------------------------- CREAZIONE MAPPA --------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
bool
|
||||
VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -51,7 +51,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[0] = max( int( ( dDimX + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
m_nNy[0] = max( int( ( dDimY + EPS_SMALL) / m_dStep + 0.5), 1) ;
|
||||
|
||||
// Numero di componenti connesse
|
||||
// Numero di componenti connesse
|
||||
m_nConnectedCompoCount = 1 ;
|
||||
|
||||
// Se tridexel
|
||||
@@ -67,7 +67,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nNx[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
m_nNy[2] = 0 ;
|
||||
}
|
||||
|
||||
// Definisco il numero di blocchi lungo x,y e z
|
||||
@@ -81,12 +81,24 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
|
||||
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Creazione delle celle per ogni mappa
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
|
||||
// Riempimento delle celle
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i) {
|
||||
for ( int j = 0 ; j < m_nDim[i] ; ++ j) {
|
||||
|
||||
// Aggiungo il tratto al dexel vuoto
|
||||
@@ -98,7 +110,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
switch ( i) {
|
||||
case 0 :
|
||||
m_Values[i][j][0].vtMinN = - Z_AX ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].dMax = dDimZ ;
|
||||
m_Values[i][j][0].vtMaxN = Z_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
@@ -113,9 +125,10 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
m_Values[i][j][0].dMax = dDimY ;
|
||||
m_Values[i][j][0].vtMaxN = Y_AX ;
|
||||
m_Values[i][j][0].nToolMax = 0 ;
|
||||
break ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Definizione delle limitazioni iniziali in Z per ogni mappa
|
||||
m_dMinZ[0] = 0 ;
|
||||
@@ -136,7 +149,7 @@ VolZmap::Create( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, d
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Controlli sull'ammissibilità delle dimensioni lineari del grezzo e del passo
|
||||
if ( dStep < EPS_SMALL || dDimX < EPS_SMALL || dDimY < EPS_SMALL || dDimZ < EPS_SMALL)
|
||||
@@ -187,6 +200,18 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_nDim[i] = m_nNx[i] * m_nNy[i] ;
|
||||
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Creazione delle celle per ogni mappa
|
||||
for ( int i = 0 ; i < m_nMapNum ; ++ i)
|
||||
m_Values[i].resize( m_nDim[i]) ;
|
||||
@@ -210,7 +235,7 @@ VolZmap::CreateEmpty( const Point3d& ptO, double dDimX, double dDimY, double dDi
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex)
|
||||
VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double dStep, bool bTriDex, int* nError)
|
||||
{
|
||||
// Aggiorno la dimensione della mappa 1 o 3
|
||||
m_nMapNum = ( bTriDex ? 3 : 1) ;
|
||||
@@ -250,14 +275,35 @@ VolZmap::CreateFromFlatRegion( const ISurfFlatRegion& Surf, double dDimZ, double
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( dDimZ + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_Values[2].resize( m_nDim[2]) ;
|
||||
}
|
||||
|
||||
// Se dimensione singola
|
||||
else {
|
||||
// Se versione 32-bit controllo di non superare il numero di Dexel massimo
|
||||
#if !defined(_WIN64)
|
||||
m_nDexelNbr += m_nDim[0] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
@@ -788,7 +834,7 @@ VolZmap::SubtractMapPart( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ,
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox)
|
||||
VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex, double dExtraBox, int* nError)
|
||||
{
|
||||
// Se la superficie non è chiusa oppure orientata al contrario non ha senso continuare
|
||||
double dVol ;
|
||||
@@ -838,14 +884,33 @@ VolZmap::CreateFromTriMesh( const ISurfTriMesh& Surf, double dStep, bool bTriDex
|
||||
m_nNx[1] = m_nNy[0] ;
|
||||
m_nNy[1] = int( ( vtLen.z + EPS_SMALL) / m_dStep + 0.5) ;
|
||||
m_nDim[1] = m_nNx[1] * m_nNy[1] ;
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_nNx[2] = m_nNy[1] ;
|
||||
m_nNy[2] = m_nNx[0] ;
|
||||
m_nDim[2] = m_nNx[2] * m_nNy[2] ;
|
||||
#if !defined(_WIN64)
|
||||
for ( int i = 0 ; i < ssize( m_nDim) ; ++ i)
|
||||
m_nDexelNbr += m_nDim[i] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_Values[1].resize( m_nDim[1]) ;
|
||||
m_Values[2].resize( m_nDim[2]) ;
|
||||
}
|
||||
|
||||
// Se a dimensione singola
|
||||
else {
|
||||
#if !defined(_WIN64)
|
||||
m_nDexelNbr += m_nDim[0] ;
|
||||
if ( m_nDexelNbr >= MAX_DEXEL_32_BIT) {
|
||||
Clear() ;
|
||||
if ( nError != nullptr)
|
||||
*nError = 1 ;
|
||||
return false ;
|
||||
}
|
||||
#endif
|
||||
m_nNx[1] = 0 ;
|
||||
m_nNy[1] = 0 ;
|
||||
m_nDim[1] = 0 ;
|
||||
|
||||
+6
-4
@@ -21,6 +21,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "GeoConst.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
@@ -968,12 +969,13 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d
|
||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ;
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+242
-38
@@ -21,6 +21,7 @@
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
@@ -845,6 +846,183 @@ VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin,
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::AddStripInterval( int nGrid, int nI, int nJ, double dZMin, double dZMax, int nToolNum)
|
||||
{
|
||||
// Se non Tridex, esco
|
||||
if ( ! IsTriDexel())
|
||||
return true ;
|
||||
|
||||
// Controllo che il numero di griglia sia entro i limiti
|
||||
if ( nGrid < 0 || nGrid > 2)
|
||||
return false ;
|
||||
|
||||
// Controllo che indici nI, nJ siano entro i limiti
|
||||
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
|
||||
return false ;
|
||||
|
||||
// Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia)
|
||||
int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio +
|
||||
( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ;
|
||||
|
||||
// Scorro i Voxel correnti
|
||||
for ( int nVox = - 1 ; nVox < nVoxNum - 1 ; ++ nVox) {
|
||||
// Considero solo i Voxel interni all'intervallo corrente
|
||||
if ( ( nVox + 1) * m_dStep > dZMin && ( nVox - 1) * m_dStep < dZMax) {
|
||||
// Recupero gli indici per la griglia successiva
|
||||
int nMyGrid = ( nGrid + 1) % 3 ;
|
||||
int nMyI = nJ ;
|
||||
int nMyJ = nVox ;
|
||||
int nMyK = nI ;
|
||||
double dMyMinZ = nMyK * m_dStep ;
|
||||
double dMyMaxZ = ( nMyK + 1) * m_dStep ;
|
||||
Vector3d vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
|
||||
nMyGrid == 1 ? m_MapFrame.VersX() :
|
||||
m_MapFrame.VersY()) ;
|
||||
Vector3d vtMyMinN = - vtMyMaxN ;
|
||||
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
||||
// Recupero gli indici della griglia precedente
|
||||
nMyGrid = ( nGrid + 2) % 3 ;
|
||||
nMyI = nVox ;
|
||||
nMyJ = nI ;
|
||||
nMyK = nJ ;
|
||||
dMyMinZ = nMyK * m_dStep ;
|
||||
dMyMaxZ = ( nMyK + 1) * m_dStep ;
|
||||
vtMyMaxN = ( nMyGrid == 0 ? m_MapFrame.VersZ() :
|
||||
nMyGrid == 1 ? m_MapFrame.VersX() :
|
||||
m_MapFrame.VersY()) ;
|
||||
vtMyMinN = - vtMyMaxN ;
|
||||
AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ - EPS_SMALL, dMyMaxZ + EPS_SMALL, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
||||
}
|
||||
}
|
||||
// Aggiungo l'intervallo corrente
|
||||
Vector3d vtMyMaxN = ( nGrid == 0 ? m_MapFrame.VersZ() :
|
||||
nGrid == 1 ? m_MapFrame.VersX() :
|
||||
m_MapFrame.VersY()) ;
|
||||
Vector3d vtMyMinN = - vtMyMaxN ;
|
||||
AddIntervals( nGrid, nI, nJ, dZMin, dZMax, vtMyMinN, vtMyMaxN, nToolNum, true) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::GetLocalPoint( int nGrid, int nI, int nJ, double dZ, Point3d& ptLoc)
|
||||
{
|
||||
// Verifico che lo ZMap corrente sia valido
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Controllo che il numero di griglia sia entro i limiti
|
||||
if ( nGrid < 0 || nGrid > 2)
|
||||
return false ;
|
||||
|
||||
// Controllo che indici nI, nJ siano entro i limiti
|
||||
if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid])
|
||||
return false ;
|
||||
|
||||
// Calcolo il punto
|
||||
ptLoc = m_MapFrame.Orig() ;
|
||||
if ( nGrid == 0)
|
||||
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersX() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersY() + dZ * m_MapFrame.VersZ()) ;
|
||||
else if ( nGrid == 1)
|
||||
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersY() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersZ() + dZ * m_MapFrame.VersX()) ;
|
||||
else
|
||||
ptLoc += ( ( nI + 0.5) * m_dStep * m_MapFrame.VersZ() + ( nJ + 0.5) * m_dStep * m_MapFrame.VersX() + dZ * m_MapFrame.VersY()) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::ComputePointAndNormalForRemovingFins( int nGrid, int nI, int nJ, double dZ,
|
||||
const Vector3d& vtDir, double dThick, bool bMinVsMax, int nTool,
|
||||
Vector3d& vtN, double& dNewZ)
|
||||
{
|
||||
// Verifico che lo ZMap corrente sia valido
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// Controllo che il numero di griglia sia entro i limiti
|
||||
if ( nGrid < 0 || nGrid > 2)
|
||||
return false ;
|
||||
|
||||
// Inizializzo il vettore da restituire
|
||||
vtN = V_NULL ;
|
||||
dNewZ = INFINITO ;
|
||||
|
||||
// Proietto la direzione lungo la mappa della griglia corrente
|
||||
Vector3d vtDirProj = OrthoCompo( vtDir, ( nGrid == 0 ? m_MapFrame.VersZ() :
|
||||
nGrid == 1 ? m_MapFrame.VersX() :
|
||||
m_MapFrame.VersY())) ;
|
||||
// Sposto il punto corrente nella direzione opposta a quella trovata
|
||||
Point3d ptLoc ;
|
||||
if ( ! GetLocalPoint( nGrid, nI, nJ, dZ, ptLoc))
|
||||
return false ;
|
||||
Point3d ptCenterLoc = ptLoc ;
|
||||
ptCenterLoc.Translate( - vtDirProj * dThick) ;
|
||||
|
||||
// Recupero il Box nel punto
|
||||
BBox3d BBoxLoc ; BBoxLoc.Add( ptCenterLoc) ;
|
||||
double dExpandX = ( m_MapFrame.VersX() * X_AX) * dThick * ( vtDirProj * X_AX) ;
|
||||
double dExpandY = ( m_MapFrame.VersY() * Y_AX) * dThick * ( vtDirProj * Y_AX) ;
|
||||
double dExpandZ = ( m_MapFrame.VersZ() * Z_AX) * dThick * ( vtDirProj * Z_AX) ;
|
||||
BBoxLoc.Expand( max( ( m_dStep + EPS_SMALL), dExpandX),
|
||||
max( ( m_dStep + EPS_SMALL), dExpandY),
|
||||
max( ( m_dStep + EPS_SMALL), dExpandZ)) ;
|
||||
|
||||
// Porto il Box nel Frame della Mappa corrente
|
||||
BBox3d BBoxInGrid = GetToLoc( BBoxLoc, m_MapFrame) ;
|
||||
// Recupero i suoi estremi
|
||||
Point3d ptBoxLocMax = BBoxInGrid.GetMax() ;
|
||||
Point3d ptBoxLocMin = BBoxInGrid.GetMin() ;
|
||||
// Determino gli intervalli locali in X e Y locali alla Griglia correnti
|
||||
double dMinXLoc = ( nGrid == 0 ? ptBoxLocMin.x : nGrid == 1 ? ptBoxLocMin.y : ptBoxLocMin.z) ;
|
||||
double dMinYLoc = ( nGrid == 0 ? ptBoxLocMin.y : nGrid == 1 ? ptBoxLocMin.z : ptBoxLocMin.x) ;
|
||||
double dMaxXLoc = ( nGrid == 0 ? ptBoxLocMax.x : nGrid == 1 ? ptBoxLocMax.y : ptBoxLocMax.z) ;
|
||||
double dMaxYLoc = ( nGrid == 0 ? ptBoxLocMax.y : nGrid == 1 ? ptBoxLocMax.z : ptBoxLocMax.x) ;
|
||||
|
||||
// Recupero gli Spilloni coinvolti nel Box
|
||||
int nStartI = max( 0, int( dMinXLoc / m_dStep)) ;
|
||||
int nEndI = min( m_nNx[nGrid] - 1, int( dMaxXLoc / m_dStep)) ;
|
||||
int nStartJ = max( 0, int( dMinYLoc / m_dStep)) ;
|
||||
int nEndJ = min( m_nNy[nGrid] - 1, int( dMaxYLoc / m_dStep)) ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int i = nStartI ; i <= nEndI ; ++ i) {
|
||||
for ( int j = nStartJ ; j <= nEndJ ; ++ j) {
|
||||
// Determino la posizione corrente dello Spillone
|
||||
int nPos = j * m_nNx[nGrid] + i ;
|
||||
vector<Data>& vDexel = m_Values[nGrid][nPos] ;
|
||||
// Scorro i suoi Intervalli
|
||||
for ( int nInterval = 0 ; nInterval < ssize( vDexel) ; ++ nInterval) {
|
||||
// Se l'Intervallo presenta un indice del Tool da evitare, passo al successivo
|
||||
if ( ( bMinVsMax && vDexel[nInterval].nToolMin != nTool) ||
|
||||
( ! bMinVsMax && vDexel[nInterval].nToolMax != nTool))
|
||||
continue ;
|
||||
// Recupero l'estremo da analizzare
|
||||
double dZInterval = ( bMinVsMax ? vDexel[nInterval].dMin : vDexel[nInterval].dMax) ;
|
||||
// Recupero il punto associato
|
||||
Point3d ptInterval ;
|
||||
if ( ! GetLocalPoint( nGrid, i, j, dZInterval, ptInterval))
|
||||
return false ;
|
||||
// Se il punto è dentro nel Box, aggiungo il contributo della normale presente
|
||||
if ( BBoxLoc.Encloses( ptInterval)) {
|
||||
double dCurrSqDist = ( SqDist( ptInterval, ptLoc)) ;
|
||||
if ( dCurrSqDist < dSqMinDist) {
|
||||
dSqMinDist = dCurrSqDist ;
|
||||
vtN = ( bMinVsMax ? vDexel[nInterval].vtMinN : vDexel[nInterval].vtMaxN) ;
|
||||
dNewZ = dZInterval ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ( ! vtN.IsSmall() && dZ < INFINITO - 1) ;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1588,10 +1766,13 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
Vector3d vtDirTip = ptP2T - ptP1T ;
|
||||
bool bTopIsPivot = vtDirTop.IsSmall() ;
|
||||
bool bTipIsPivot = vtDirTip.IsSmall() ;
|
||||
bool bSmallMovement = vtDirTop.Len() < 10 * EPS_SMALL && vtDirTip.Len() < 10 * EPS_SMALL ;
|
||||
bool bInverse = ! (bTopIsPivot || bTipIsPivot) && vtDirTop * vtDirTip < 0 ;
|
||||
|
||||
if ( bInverse)
|
||||
nTotSurf += 4 ;
|
||||
if ( bSmallMovement)
|
||||
nTotSurf += 2 ;
|
||||
|
||||
int nSurfInd = 0 ;
|
||||
vector<SurfBezForInters> vSurfBez( nTotSurf) ;
|
||||
@@ -1680,26 +1861,44 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
}
|
||||
|
||||
vector<PNTVECTOR> vvPtCtrl ;
|
||||
// superficie laterale sinistra
|
||||
CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ;
|
||||
if ( bInverse)
|
||||
cLineLeftBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ;
|
||||
CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ;
|
||||
PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
|
||||
// superficie laterale destra
|
||||
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
|
||||
if ( bInverse)
|
||||
cLineRightBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
|
||||
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
|
||||
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
|
||||
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
|
||||
if ( ! bSmallMovement) {
|
||||
// superficie laterale sinistra
|
||||
CurveLine cLineLeftBottom ; cLineLeftBottom.Set( vPntTipEndFront.back(), vPntTipStartFront.back()) ;
|
||||
if ( ! cLineLeftBottom.IsValid())
|
||||
return false ;
|
||||
if ( bInverse)
|
||||
cLineLeftBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezLeftBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftBottom, nDegU, bRat))) ;
|
||||
if ( IsNull( cBezLeftBottom))
|
||||
return false ;
|
||||
CurveLine cLineLeftTop ; cLineLeftTop.Set( vPntTopEndFront.back(), vPntTopStartFront.back()) ;
|
||||
if ( ! cLineLeftTop.IsValid())
|
||||
return false ;
|
||||
PtrOwner<CurveBezier> cBezLeftTop( GetBasicCurveBezier( LineToBezierCurve( &cLineLeftTop, nDegU, bRat))) ;
|
||||
if ( IsNull( cBezLeftTop))
|
||||
return false ;
|
||||
vvPtCtrl.emplace_back( cBezLeftBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntLeft = cBezLeftTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntLeft.begin(), vPntLeft.end()) ;
|
||||
// superficie laterale destra
|
||||
CurveLine cLineRightBottom ; cLineRightBottom.Set( vPntTipStartFront.front(), vPntTipEndFront.front()) ;
|
||||
if ( ! cLineRightBottom.IsValid())
|
||||
return false ;
|
||||
if ( bInverse)
|
||||
cLineRightBottom.Invert() ;
|
||||
PtrOwner<CurveBezier> cBezRightBottom( GetBasicCurveBezier( LineToBezierCurve( &cLineRightBottom, nDegU, bRat))) ;
|
||||
if ( IsNull( cBezRightBottom))
|
||||
return false ;
|
||||
CurveLine cLineRightTop ; cLineRightTop.Set( vPntTopStartFront.front(), vPntTopEndFront.front()) ;
|
||||
if ( ! cLineRightTop.IsValid())
|
||||
return false ;
|
||||
PtrOwner<CurveBezier> cBezRightTop( GetBasicCurveBezier( LineToBezierCurve( &cLineRightTop, nDegU, bRat))) ;
|
||||
if ( IsNull( cBezRightTop))
|
||||
return false ;
|
||||
vvPtCtrl.emplace_back( cBezRightBottom->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntRight = cBezRightTop->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntRight.begin(), vPntRight.end()) ;
|
||||
}
|
||||
if ( nSub == 1) {
|
||||
// superficie inferiore
|
||||
vvPtCtrl.emplace_back( PNTVECTOR( { vPntTipStartFront.front(), vPntTipStartFront.back(), vPntTipEndFront.front(), vPntTipEndFront.back() })) ;
|
||||
@@ -1939,7 +2138,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
vvPtCtrl.emplace_back( cBezTipEndF2->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntEndF2 = cBezTopEndF2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntEndF2.begin(), vPntEndF2.end()) ;
|
||||
if ( bInverse) {
|
||||
if ( bInverse || bSmallMovement) {
|
||||
// chiudo il volume con le superici verticali end back 1
|
||||
vvPtCtrl.emplace_back( cBezTipEndB1->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntEndB1 = cBezTopEndB1->GetAllControlPoints() ;
|
||||
@@ -1958,7 +2157,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
vvPtCtrl.emplace_back( cBezTipStartB2->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntStartB2 = cBezTopStartB2->GetAllControlPoints() ;
|
||||
vvPtCtrl.back().insert( vvPtCtrl.back().end(), vPntStartB2.begin(), vPntStartB2.end()) ;
|
||||
if ( bInverse) {
|
||||
if ( bInverse || bSmallMovement) {
|
||||
// chiudo il volume con le superici verticali start front 1
|
||||
vvPtCtrl.emplace_back( cBezTipStartF1->GetAllControlPoints()) ;
|
||||
PNTVECTOR vPntStartF1 = cBezTopStartF1->GetAllControlPoints() ;
|
||||
@@ -2038,7 +2237,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
|
||||
}
|
||||
|
||||
// inizializzo le superfici bilineari e i parametri per le intersezioni
|
||||
for ( int z = 0 ; z < int( vvPtCtrl.size()) ; ++z) {
|
||||
for ( int z = 0 ; z < ssize( vvPtCtrl) ; ++z) {
|
||||
vSurfBez[nSurfInd].sBez.Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 0, vvPtCtrl[z][0]) ;
|
||||
vSurfBez[nSurfInd].sBez.SetControlPoint( 1, vvPtCtrl[z][1]) ;
|
||||
@@ -6051,7 +6250,8 @@ VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, co
|
||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
}
|
||||
@@ -6096,8 +6296,9 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
Vector3d vtN1, vtN2 ;
|
||||
|
||||
// Cilindro
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -6276,7 +6477,8 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
|
||||
// Cilindro iniziale
|
||||
CylFrame.ChangeOrig( ptITip) ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -6284,7 +6486,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
|
||||
// il vettore che congiunge le due origini.
|
||||
CylFrame.ChangeOrig( ptITip + vtMove) ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -6871,7 +7073,8 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
|
||||
// Cilindro inviluppo della sfera
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
}
|
||||
@@ -7019,15 +7222,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
|
||||
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
|
||||
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
|
||||
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
|
||||
@@ -7423,8 +7626,9 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
|
||||
// Cilindro inviluppo della sfera
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-3
@@ -828,10 +828,19 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
Point3d ptTemp ;
|
||||
Vector3d vtDir ;
|
||||
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||
return false ;
|
||||
continue ;
|
||||
vtDir.Normalize() ;
|
||||
|
||||
vResult.emplace_back( pt, vtDir) ;
|
||||
// verifico che il punto non sia già stato trovato
|
||||
bool bAdd = true ;
|
||||
for ( int j = 0 ; j < ssize( vResult) ; j ++) {
|
||||
if ( AreSamePointApprox( vResult[j].first, pt)) {
|
||||
bAdd = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bAdd)
|
||||
vResult.emplace_back( pt, vtDir) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,8 +1023,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
RemoveCurveSmallParts( pCrvOffs, 5 * EPS_SMALL) ;
|
||||
|
||||
// aggiungo la curva alla lista degli offset
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0)
|
||||
if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid() && pCrvOffs->GetCurveCount() > 0) {
|
||||
// forzo chiusura
|
||||
if ( ! pCrvOffs->IsClosed()) {
|
||||
Point3d ptS ; pCrvOffs->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pCrvOffs->GetEndPoint( ptE) ;
|
||||
if ( SqDist( ptS, ptE) > 100. * SQ_EPS_SMALL)
|
||||
return false ;
|
||||
pCrvOffs->Close() ;
|
||||
}
|
||||
OffsList.push_back( Release( pCrvOffs)) ;
|
||||
}
|
||||
}
|
||||
|
||||
// libero la memoria di vroni dedicata agli offset
|
||||
|
||||
Reference in New Issue
Block a user