Merge remote-tracking branch 'origin/HEAD' into MoreBezier
This commit is contained in:
Binary file not shown.
+101
-205
@@ -594,18 +594,12 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
// verifico se curve sono coerenti per calcolo dell'offset
|
||||
if ( ! VerifyCurvesValidityForOffset())
|
||||
return false ;
|
||||
|
||||
// se offset nullo restituisco direttamente le curve
|
||||
if ( abs( dOffs) < EPS_SMALL) {
|
||||
for ( auto pCrv : m_vpCrvs)
|
||||
vOffs.emplace_back( pCrv->Clone()) ;
|
||||
}
|
||||
|
||||
bool bClosed = m_vpCrvs[0]->IsClosed() ;
|
||||
|
||||
// calcolo offset
|
||||
ICRVCOMPOPLIST OffsList ;
|
||||
if ( ! CalcVroniOffset( OffsList, abs( dOffs)))
|
||||
@@ -614,39 +608,34 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType)
|
||||
// sistemo le curve di offset calcolate con vroni
|
||||
for ( auto pCrv : OffsList) {
|
||||
|
||||
// seleziono le curve di offset corrette in base al segno dell'offset
|
||||
if ( bClosed)
|
||||
AdjustClosedOffsetCurve( *pCrv, dOffs) ;
|
||||
else
|
||||
AdjustOpenOffsetCurve( *pCrv, dOffs) ;
|
||||
|
||||
if ( pCrv->IsValid()) {
|
||||
// eventuale inversione
|
||||
if ( dOffs > EPS_SMALL)
|
||||
pCrv->Invert() ;
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
IdentifyFillets( pCrv, dOffs) ;
|
||||
AdjustCurveFillets( pCrv, dOffs, nType) ;
|
||||
}
|
||||
// seleziono le porzioni dell'offset che si trovano dal lato richiesto
|
||||
ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ;
|
||||
|
||||
for ( int i = 0 ; i < int( vResult.size()) ; ++ i) {
|
||||
|
||||
if ( bClosed) {
|
||||
// forzo chiusura della curva per evitare piccole imprecisioni
|
||||
pCrv->Close() ;
|
||||
// sistemo il punto di inizio
|
||||
AdjustOffsetStart( *pCrv) ;
|
||||
}
|
||||
|
||||
// porto nel frame globale
|
||||
pCrv->ToGlob( m_Frame) ;
|
||||
// unisco le parti allineate
|
||||
pCrv->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ;
|
||||
// aggiungo al vettore finale
|
||||
vOffs.emplace_back( pCrv) ;
|
||||
// eventuale inversione
|
||||
if ( dOffs > EPS_SMALL)
|
||||
vResult[i]->Invert() ;
|
||||
|
||||
// sistemo il punto di inizio
|
||||
if ( vResult[i]->IsClosed())
|
||||
AdjustOffsetStart( vResult[i]) ;
|
||||
|
||||
// sistemo i raccordi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
IdentifyFillets( vResult[i], dOffs) ;
|
||||
AdjustCurveFillets( vResult[i], dOffs, nType) ;
|
||||
}
|
||||
|
||||
// porto nel frame globale
|
||||
vResult[i]->ToGlob( m_Frame) ;
|
||||
// unisco le parti allineate
|
||||
vResult[i]->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ;
|
||||
// aggiungo al vettore finale
|
||||
vOffs.emplace_back( Release( vResult[i])) ;
|
||||
}
|
||||
else
|
||||
delete pCrv ;
|
||||
// dealloco curva
|
||||
delete( pCrv) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -717,14 +706,6 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
if ( ! IsValid())
|
||||
return false ;
|
||||
|
||||
int nOrigCrvCnt = 1 ;
|
||||
if ( m_vpCrvs[0]->GetType() == CRV_COMPO) {
|
||||
const CurveComposite * pOrigCompo = GetBasicCurveComposite( m_vpCrvs[0]) ;
|
||||
if ( pOrigCompo == nullptr)
|
||||
return false ;
|
||||
nOrigCrvCnt = pOrigCompo->GetCurveCount() ;
|
||||
}
|
||||
|
||||
try {
|
||||
// reset di eventuali offset precedenti
|
||||
m_vroni->apiResetOffsetData() ;
|
||||
@@ -772,9 +753,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs)
|
||||
int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ;
|
||||
pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ;
|
||||
// verifico se è raccordo relativo agli estremi della curva
|
||||
if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt))
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ;
|
||||
// verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva
|
||||
// aperta e chiusa)
|
||||
if ( nOrigCrv == -1) {
|
||||
int nOrigCrvCnt = 1 ;
|
||||
if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO)
|
||||
nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ;
|
||||
if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) {
|
||||
double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ;
|
||||
pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -814,169 +803,76 @@ Voronoi::UpdateVoronoi( double dOffs)
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::VerifyCurvesValidityForOffset()
|
||||
{
|
||||
if ( m_vpCrvs.size() == 1)
|
||||
return true ;
|
||||
|
||||
// se ho più curve, devono essere tutte chiuse
|
||||
for ( auto pCrv : m_vpCrvs) {
|
||||
if ( ! pCrv->IsClosed())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// verifico se gli orientamenti delle curve sono coerenti
|
||||
DBLVECTOR vArea( m_vpCrvs.size()) ;
|
||||
double dRefArea = 0.0 ;
|
||||
for ( int i = 0 ; i < ( int)m_vpCrvs.size() ; i ++) {
|
||||
m_vpCrvs[i]->GetAreaXY( vArea[i]) ;
|
||||
if ( abs( vArea[i]) > abs( dRefArea))
|
||||
dRefArea = vArea[i] ;
|
||||
}
|
||||
bool bRefCCW = ( dRefArea > EPS_SMALL) ;
|
||||
|
||||
for ( int i = 0 ; i < ( int)vArea.size() ; i++) {
|
||||
|
||||
// se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale
|
||||
if ( vArea[i] * dRefArea > EPS_SMALL) {
|
||||
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS)
|
||||
return false ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) {
|
||||
// se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento
|
||||
// diverso dal principale
|
||||
bool bFound = false ;
|
||||
for ( int k = 0 ; k < ( int)vArea.size() ; k++) {
|
||||
if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) {
|
||||
bFound = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bFound)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se curva con orientamento diverso dal principale verifico sia contenuta in una curva con orientamento principale
|
||||
else if ( vArea[i] * dRefArea < - EPS_SMALL) {
|
||||
bool bInside = false ;
|
||||
for ( int j = 0 ; j < ( int)vArea.size() ; j++) {
|
||||
if ( j != i && vArea[j] * dRefArea > EPS_SMALL) {
|
||||
IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ;
|
||||
int nRes = ccInt.GetRegionCurveClassification() ;
|
||||
if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_OUT)) {
|
||||
bInside = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! bInside)
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AdjustClosedOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
{
|
||||
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
|
||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
if ( nSide != nSideRef)
|
||||
// se lato errato, tutta la curva va cancellata
|
||||
pCompo.Clear() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs)
|
||||
ICRVCOMPOPOVECTOR
|
||||
Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const
|
||||
{
|
||||
ICRVCOMPOPOVECTOR vResult ;
|
||||
int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ;
|
||||
|
||||
// recupero i raccordi relativi agli estremi della curva aperta
|
||||
INTVECTOR vJunctions ;
|
||||
for ( int i = 0 ; i < pCompo.GetCurveCount() ; i++) {
|
||||
double dParTmp ;
|
||||
pCompo.GetCurveTempParam( i, dParTmp) ;
|
||||
if ( dParTmp > EPS_SMALL)
|
||||
vJunctions.push_back( i) ;
|
||||
// verifico se presenti giunzioni
|
||||
bool bJunctions = false ;
|
||||
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
|
||||
double dParam ; pCompo->GetCurveTempParam( i, dParam) ;
|
||||
if ( abs( dParam - VRONI_JUNCTION_OPEN) < EPS_SMALL) {
|
||||
bJunctions = true ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vJunctions.size() == 0) {
|
||||
// verifico se si trova dal lato corretto
|
||||
if ( ! bJunctions) {
|
||||
// controllo la curva complessiva
|
||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
if ( nSide != nSideRef)
|
||||
// se lato errato, tutta la curva va cancellata
|
||||
pCompo.Clear() ;
|
||||
if ( nSide == nSideRef)
|
||||
vResult.emplace_back( pCompo->Clone()) ;
|
||||
}
|
||||
else if ( vJunctions.size() == 2) {
|
||||
// recupero i due tratti di curva
|
||||
PtrOwner<CurveComposite> pCompo1( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[0] + 1, vJunctions[1]))) ;
|
||||
PtrOwner<CurveComposite> pCompo2( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[1] + 1, vJunctions[0]))) ;
|
||||
pCompo.Clear() ;
|
||||
if ( ! IsNull( pCompo1) && pCompo1->IsValid()) {
|
||||
int nSide = GetOffsetCurveSide( *pCompo1, 0) ;
|
||||
if ( nSide == nSideRef)
|
||||
pCompo.CopyFrom( pCompo1) ;
|
||||
else if ( ! IsNull( pCompo2) && pCompo2->IsValid())
|
||||
pCompo.CopyFrom( pCompo2) ;
|
||||
}
|
||||
else if ( ! IsNull( pCompo2) && pCompo2->IsValid()) {
|
||||
int nSide = GetOffsetCurveSide( *pCompo2, 0) ;
|
||||
if ( nSide == nSideRef)
|
||||
pCompo.CopyFrom( pCompo2) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// mi posiziono dopo la junction
|
||||
pCompo.ChangeStartPoint( vJunctions[0] + 1) ;
|
||||
delete( pCompo.RemoveFirstOrLastCurve()) ;
|
||||
// verifico validità della curva
|
||||
int nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
if ( nSide == nSideRef) {
|
||||
// scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine
|
||||
for ( int i = 1 ; i < pCompo.GetCurveCount() ; i++) {
|
||||
else {
|
||||
// scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato
|
||||
PtrOwner<CurveComposite> pCompoCurr( CreateBasicCurveComposite()) ;
|
||||
for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) {
|
||||
bool bKeep = true ;
|
||||
double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ;
|
||||
if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL)
|
||||
bKeep = false ;
|
||||
else {
|
||||
int nSide = GetOffsetCurveSide( pCompo, i) ;
|
||||
if ( nSide != nSideRef)
|
||||
pCompo.TrimEndAtParam( i) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// elimino finchè non trovo una curva valida
|
||||
while( nSide != nSideRef && pCompo.IsValid()) {
|
||||
delete( pCompo.RemoveFirstOrLastCurve( false)) ;
|
||||
if ( pCompo.IsValid())
|
||||
nSide = GetOffsetCurveSide( pCompo, 0) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bKeep = ( nSide == nSideRef) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
if ( bKeep)
|
||||
pCompoCurr->AddCurve( pCompo->GetCurve( i)->Clone()) ;
|
||||
else {
|
||||
// salvo la curva ottenuta fino ad ora e resetto per i prossimi tratti validi
|
||||
if ( pCompoCurr->IsValid()) {
|
||||
vResult.emplace_back( Release( pCompoCurr)) ;
|
||||
pCompoCurr.Set( CreateBasicCurveComposite()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// salvo eventuale ultima curva
|
||||
if ( pCompoCurr->IsValid())
|
||||
vResult.emplace_back( Release( pCompoCurr)) ;
|
||||
|
||||
// verifico se posso concatenare prima e ultima curva
|
||||
if ( vResult.size() > 1) {
|
||||
Point3d ptStart ; vResult.front()->GetStartPoint( ptStart) ;
|
||||
Point3d ptEnd ; vResult.back()->GetEndPoint( ptEnd) ;
|
||||
if ( AreSamePointApprox( ptStart, ptEnd) && vResult.front()->AddCurve( vResult.back()->Clone(), false))
|
||||
vResult.pop_back() ;
|
||||
}
|
||||
}
|
||||
|
||||
return vResult ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
int
|
||||
Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv)
|
||||
Voronoi::GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const
|
||||
{
|
||||
Point3d ptM ; pOffs.GetCurve( nCrv)->GetMidPoint( ptM) ;
|
||||
Point3d ptM ; pOffs->GetCurve( nCrv)->GetMidPoint( ptM) ;
|
||||
|
||||
// recupero curva e sottocurva di riferimento
|
||||
int nOrigSubCrv ; pOffs.GetCurveTempProp( nCrv, nOrigSubCrv) ;
|
||||
int nOrigCrv ; pOffs.GetCurveTempProp( nCrv, nOrigCrv, 1) ;
|
||||
int nOrigSubCrv ; pOffs->GetCurveTempProp( nCrv, nOrigSubCrv) ;
|
||||
int nOrigCrv ; pOffs->GetCurveTempProp( nCrv, nOrigCrv, 1) ;
|
||||
const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ;
|
||||
if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) {
|
||||
const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ;
|
||||
@@ -992,19 +888,19 @@ Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Voronoi::AdjustOffsetStart( ICurveComposite& pCrv)
|
||||
Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const
|
||||
{
|
||||
for ( int i = 0 ; i < pCrv.GetCurveCount() ; i++) {
|
||||
// cerco il tratto associato alla prima curva originale
|
||||
int nProp ; pCrv.GetCurveTempProp( i, nProp) ;
|
||||
if ( nProp == 1) {
|
||||
pCrv.ChangeStartPoint( i) ;
|
||||
for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) {
|
||||
// cerco il tratto associato alla prima sottocurva originale
|
||||
int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ;
|
||||
if ( nOrigCrv == 1) {
|
||||
pCrv->ChangeStartPoint( i) ;
|
||||
break ;
|
||||
}
|
||||
// oppure un raccordo di junction
|
||||
double dParam ; pCrv.GetCurveTempParam( i, dParam) ;
|
||||
if ( abs( dParam - 1) < EPS_SMALL) {
|
||||
pCrv.ChangeStartPoint( i + 1) ;
|
||||
// oppure associato ad una giunzione
|
||||
double dParam ; pCrv->GetCurveTempParam( i, dParam) ;
|
||||
if ( abs( dParam - VRONI_JUNCTION_CLOSED) < EPS_SMALL) {
|
||||
pCrv->ChangeStartPoint( i + 1) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@
|
||||
static const bool USE_VORONOI = true ;
|
||||
static const int VORONOI_STD_BOUND = 3 ;
|
||||
static const double VRONI_OFFS_TOL = 1e-9 ;
|
||||
static const double VRONI_JUNCTION_OPEN = 1.0 ;
|
||||
static const double VRONI_JUNCTION_CLOSED = 2.0 ;
|
||||
|
||||
//-------------------------- Forward Definitions -------------------------------
|
||||
class ISurfFlatRegion ;
|
||||
@@ -77,11 +79,9 @@ class Voronoi
|
||||
bool CalcVoronoi( int nBound = VORONOI_STD_BOUND) ;
|
||||
bool CalcVroniOffset( ICRVCOMPOPLIST& vOffs, double dOffs) ;
|
||||
bool UpdateVoronoi( double dOffs) ;
|
||||
bool VerifyCurvesValidityForOffset( void) ;
|
||||
bool AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs) ;
|
||||
bool AdjustClosedOffsetCurve( ICurveComposite& pCompo, double dOffs) ;
|
||||
bool AdjustOffsetStart( ICurveComposite& pCompo) ;
|
||||
int GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) ;
|
||||
ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ;
|
||||
bool AdjustOffsetStart( ICurveComposite* pCompo) const ;
|
||||
int GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const ;
|
||||
ICurve* GetBisectorCurve( int i) ;
|
||||
|
||||
private :
|
||||
|
||||
Reference in New Issue
Block a user