diff --git a/CurveArc.cpp b/CurveArc.cpp index e33aebf..3629384 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -61,13 +61,14 @@ class ArcApproxer //---------------------------------------------------------------------------- CurveArc::CurveArc( void) : m_nStatus( TO_VERIFY), m_PtCen(), m_VtN(), m_VtS(), m_dRad(), - m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick(), m_nTempProp{0,0} + m_dAngCenDeg(), m_dDeltaN(), m_VtExtr(), m_dThick(), m_nTempProp{0,0}, m_dTempParam{0.0, 0.0}, m_pVoronoiObj( nullptr) { } //---------------------------------------------------------------------------- CurveArc::~CurveArc( void) { + ResetVoronoiObject() ; } //---------------------------------------------------------------------------- @@ -89,7 +90,9 @@ CurveArc::Set( const Point3d& ptCen, const Vector3d& vtN, double dRad, // sistemo i versori m_VtN.Normalize() ; m_VtS.Normalize() ; - + + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -115,6 +118,8 @@ CurveArc::Set( const Point3d& ptCen, const Vector3d& vtN, double dRad) m_dDeltaN = 0 ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -136,6 +141,8 @@ CurveArc::SetXY( const Point3d& ptCen, double dRad, double dAngIniDeg, double dA m_dDeltaN = dDeltaZ ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -157,6 +164,8 @@ CurveArc::SetXY( const Point3d& ptCen, double dRad) m_dDeltaN = 0 ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -219,6 +228,8 @@ CurveArc::Set3P( const Point3d& ptStart, const Point3d& ptOther, const Point3d& // non c'è DeltaN m_dDeltaN = 0 ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -266,6 +277,8 @@ CurveArc::Set2PNB( const Point3d& ptIni, const Point3d& ptFin, const Vector3d& v // calcolo l'angolo al centro m_dAngCenDeg = 4 * atan( dBulge) * RADTODEG ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -322,6 +335,8 @@ CurveArc::Set2PD( const Point3d& ptStart, const Point3d& ptEnd, double dDirStart m_dDeltaN = - m_dDeltaN ; } + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -404,6 +419,8 @@ CurveArc::Set2PRS( const Point3d& ptStart, const Point3d& ptEnd, double dRad, bo ( ! bCCW && m_dAngCenDeg > 0))) m_dAngCenDeg = - m_dAngCenDeg ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -458,6 +475,8 @@ CurveArc::SetCPA( const Point3d& ptCen, const Point3d& ptStart, double dAngCenDe // assegno l'angolo al centro m_dAngCenDeg = dAngCenDeg ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -513,7 +532,8 @@ CurveArc::SetC2P( const Point3d& ptCen, const Point3d& ptStart, const Point3d& p bool bDet ; if ( ! m_VtS.GetRotation( ( ptNearEnd - m_PtCen), m_VtN, m_dAngCenDeg, bDet) || ! bDet) return false ; - + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -582,6 +602,8 @@ CurveArc::CopyFrom( const CurveArc& caSrc) m_dThick = caSrc.m_dThick ; m_nTempProp[0] = caSrc.m_nTempProp[0] ; m_nTempProp[1] = caSrc.m_nTempProp[1] ; + m_dTempParam[0] = caSrc.m_dTempParam[0] ; + m_dTempParam[1] = caSrc.m_dTempParam[1] ; return Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad, caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ; } @@ -1259,7 +1281,9 @@ CurveArc::Invert( void) m_dAngCenDeg = - m_dAngCenDeg ; // l'incremento sulla normale inverte il segno m_dDeltaN = - m_dDeltaN ; - + + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1293,6 +1317,8 @@ CurveArc::SimpleOffset( double dDist, int nType) // aggiorno il raggio m_dRad = dNewRad ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1337,6 +1363,8 @@ CurveArc::MyExtendedOffset( double dDist, bool bAll, int nType) // aggiorno il raggio m_dRad = dNewRad ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1409,6 +1437,8 @@ CurveArc::ModifyEnd( const Point3d& ptNewEnd) m_dDeltaN = arcAux.m_dDeltaN ; } + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1494,6 +1524,8 @@ CurveArc::TrimStartAtLen( double dLenTrim) } } + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1521,6 +1553,8 @@ CurveArc::TrimEndAtLen( double dLenTrim) m_dDeltaN *= dLenTrim / dLen ; } + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1564,6 +1598,8 @@ CurveArc::ExtendEndByLen( double dLenExt) else if ( abs( m_dAngCenDeg) > ANG_FULL) m_dAngCenDeg = _copysign( ANG_FULL, m_dAngCenDeg) ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1578,6 +1614,8 @@ CurveArc::Translate( const Vector3d& vtMove) if ( m_nStatus != OK) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1599,6 +1637,8 @@ CurveArc::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, dou if ( vtAx.IsSmall()) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1628,6 +1668,8 @@ CurveArc::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dC // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO || m_dRad * abs( dCoeffX) <= EPS_SMALL) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; // scalo il centro e le dimensioni lineari @@ -1655,6 +1697,8 @@ CurveArc::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dC // verifico non sia nulla if ( abs( dCoeffY) < EPS_ZERO || m_dRad * abs( dCoeffY) <= EPS_SMALL) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; // scalo il centro e le dimensioni lineari @@ -1682,6 +1726,8 @@ CurveArc::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dC // verifico non sia nulla if ( abs( dCoeffZ) < EPS_ZERO || m_dRad * abs( dCoeffZ) <= EPS_SMALL) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; // scalo il centro e le dimensioni lineari @@ -1709,6 +1755,8 @@ CurveArc::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dC // verifico non sia nulla if ( abs( dCoeffX) < EPS_ZERO || m_dRad * abs( dCoeffX) <= EPS_SMALL) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; // scalo il centro e le dimensioni lineari @@ -1742,6 +1790,8 @@ CurveArc::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1773,6 +1823,8 @@ CurveArc::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vt ! AreSameOrOppositeVectorExact( m_VtN, vtNorm)) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1804,6 +1856,8 @@ CurveArc::ToGlob( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1829,6 +1883,8 @@ CurveArc::ToLoc( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1854,6 +1910,8 @@ CurveArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1877,6 +1935,8 @@ CurveArc::InvertN( void) m_dAngCenDeg = - m_dAngCenDeg ; m_dDeltaN = - m_dDeltaN ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1957,6 +2017,8 @@ CurveArc::ChangeRadius( double dNewRadius) // cambio il raggio m_dRad = dNewRadius ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1976,6 +2038,8 @@ CurveArc::ChangeDeltaN( double dNewDeltaN) // cambio il parametro m_dDeltaN = dNewDeltaN ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1999,6 +2063,8 @@ CurveArc::ChangeAngCenter( double dNewAngCenDeg) // cambio il parametro m_dAngCenDeg = dNewAngCenDeg ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2023,6 +2089,8 @@ CurveArc::ChangeStartPoint( double dU) if ( ! vtDir.Normalize()) return false ; m_VtS = vtDir ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; @@ -2042,6 +2110,8 @@ CurveArc::ToExplementary( void) // basta prendere l'angolo al centro che completa il giro m_dAngCenDeg = - _copysign( ANG_FULL, m_dAngCenDeg) + m_dAngCenDeg ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2071,6 +2141,8 @@ CurveArc::Flip( void) m_VtS.Normalize() ; m_dAngCenDeg = - m_dAngCenDeg ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2185,3 +2257,42 @@ ArcApproxer::GetPoint( double& dU, Point3d& ptP) return true ; } + +//---------------------------------------------------------------------------- +bool +CurveArc::CalcVoronoiObject() const +{ + if ( m_nStatus != OK) + return false ; + + // creo oggetto vroni con la curva + m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ; + if ( m_pVoronoiObj == nullptr) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +Voronoi* +CurveArc::GetVoronoiObject() const +{ + if ( m_nStatus != OK) + return nullptr ; + + // se non è stato calcolato, lo calcolo + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // restituisco Voronoi + return m_pVoronoiObj ; +} + +//---------------------------------------------------------------------------- +void +CurveArc::ResetVoronoiObject() const +{ + if ( m_pVoronoiObj != nullptr) + delete m_pVoronoiObj ; + m_pVoronoiObj = nullptr ; +} \ No newline at end of file diff --git a/CurveArc.h b/CurveArc.h index 02eba06..6e4fbcc 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -18,6 +18,7 @@ #include "DllMain.h" #include "GeoObjRW.h" #include "/EgtDev/Include/EGkCurveArc.h" +#include "/EgtDev/Include/EGkVoronoi.h" //---------------------------------------------------------------------------- class CurveArc : public ICurveArc, public IGeoObjRW @@ -54,6 +55,11 @@ class CurveArc : public ICurveArc, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ICurve bool IsSimple( void) const override @@ -123,6 +129,13 @@ class CurveArc : public ICurveArc, public IGeoObjRW bool TrimEndAtLen( double dLenTrim) override ; bool ExtendStartByLen( double dLenExt) override ; bool ExtendEndByLen( double dLenExt) override ; + Voronoi* GetVoronoiObject( void) const override ; + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override + { return CalcCurveVoronoiDiagram( *this, vCrvs, nBound) ; } + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override + { return CalcCurveMedialAxis( *this, vCrvs, nSide) ; } + bool CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) const override + { return CalcCurveFatCurve( *this, vCrvs, dRadius, bSquareEnds, bSquareMids) ; } public : // ICurveArc bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -183,7 +196,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW public : CurveArc( void) ; - CurveArc( const CurveArc& caSrc) + CurveArc( const CurveArc& caSrc) : m_pVoronoiObj( nullptr) { if ( ! CopyFrom( caSrc)) LOG_ERROR( GetEGkLogger(), "CurveArc : copy constructor error")} CurveArc& operator =( const CurveArc& caSrc) @@ -196,7 +209,9 @@ class CurveArc : public ICurveArc, public IGeoObjRW private : bool CopyFrom( const CurveArc& caSrc) ; bool Validate( void) ; - bool GetDir( double dU, Vector3d& vtDir) const ; + bool GetDir( double dU, Vector3d& vtDir) const ; + bool CalcVoronoiObject( void) const ; + void ResetVoronoiObject( void) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; @@ -212,7 +227,9 @@ class CurveArc : public ICurveArc, public IGeoObjRW double m_dDeltaN ; // variazione di quota lungo VtN della fine rispetto all'inizio Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) double m_dThick ; // spessore - int m_nTempProp[2] ; // vettore proprietà temporanee + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei + mutable Voronoi* m_pVoronoiObj ; // Voronoi } ; //----------------------------------------------------------------------------- diff --git a/CurveAux.cpp b/CurveAux.cpp index 52b6b10..5f61726 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -23,6 +23,7 @@ #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkVoronoi.h" using namespace std ; @@ -1045,3 +1046,37 @@ AdjustCurveSlope( ICurveComposite* pCrv, double dNini, double dNfin) pCrv->ModifyEnd( ptFin) ; return true ; } + +//---------------------------------------------------------------------------- +bool +CalcCurveVoronoiDiagram( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nBound) +{ + Voronoi* pVoronoiObj = crvC.GetVoronoiObject() ; + if ( pVoronoiObj == nullptr) + return false ; + + return pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ; +} + +//---------------------------------------------------------------------------- +bool +CalcCurveMedialAxis( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nSide) +{ + Voronoi* pVoronoiObj = crvC.GetVoronoiObject() ; + if ( pVoronoiObj == nullptr) + return false ; + + return pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ; +} + +//---------------------------------------------------------------------------- +bool +CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) +{ + Voronoi* pVoronoiObj = crvC.GetVoronoiObject() ; + if ( pVoronoiObj == nullptr) + return false ; + + return pVoronoiObj->CalcFatCurve( vCrvs, dRadius, bSquareEnds, bSquareMids) ; +} + diff --git a/CurveAux.h b/CurveAux.h index 18bab55..109535a 100644 --- a/CurveAux.h +++ b/CurveAux.h @@ -31,3 +31,6 @@ bool CurveGetArea( const ICurve& crvC, Plane3d& plPlane, double& dArea) ; bool CurveDump( const ICurve& crvC, std::string& sOut, bool bMM, const char* szNewLine) ; bool CopyExtrusion( const ICurve* pSouCrv, ICurve* pDestCrv) ; bool CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv) ; +bool CalcCurveVoronoiDiagram( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nBound) ; +bool CalcCurveMedialAxis( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, int nSide) ; +bool CalcCurveFatCurve( const ICurve& crvC, ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 383ecdf..b683665 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -45,13 +45,14 @@ GEOOBJ_REGISTER( CRV_BEZIER, NGE_C_BEZ, CurveBezier) ; //---------------------------------------------------------------------------- CurveBezier::CurveBezier( void) : m_nStatus( TO_VERIFY), m_nDeg(), m_bRat( false), m_dParSing( -2), - m_VtExtr(), m_dThick(), m_nTempProp{0,0} + m_VtExtr(), m_dThick(), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_pVoronoiObj( nullptr) { } //---------------------------------------------------------------------------- CurveBezier::~CurveBezier( void) { + ResetVoronoiObject() ; } //---------------------------------------------------------------------------- @@ -75,6 +76,8 @@ CurveBezier::Init( int nDeg, bool bIsRational) m_vWeCtrl.clear() ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -99,6 +102,8 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) // annullo analisi presenza singolarità m_dParSing = - 2 ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -124,6 +129,8 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) // annullo analisi presenza singolarità m_dParSing = - 2 ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -285,6 +292,8 @@ CurveBezier::CopyFrom( const CurveBezier& cbSrc) m_dThick = cbSrc.m_dThick ; m_nTempProp[0] = cbSrc.m_nTempProp[0] ; m_nTempProp[1] = cbSrc.m_nTempProp[1] ; + m_dTempParam[0] = cbSrc.m_dTempParam[0] ; + m_dTempParam[1] = cbSrc.m_dTempParam[1] ; return true ; } @@ -1604,6 +1613,8 @@ CurveBezier::Invert( void) for ( int i = 0 ; i < nMid ; ++ i) swap( m_vPtCtrl[i], m_vPtCtrl[m_nDeg-i]) ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1621,6 +1632,8 @@ CurveBezier::ModifyStart( const Point3d& ptNewStart) // modifico il primo punto di controllo m_vPtCtrl[0] = ptNewStart ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1638,6 +1651,8 @@ CurveBezier::ModifyEnd( const Point3d& ptNewEnd) // modifico l'ultimo punto di controllo m_vPtCtrl[m_nDeg] = ptNewEnd ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1662,6 +1677,8 @@ CurveBezier::TrimStartAtParam( double dUTrim) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1686,6 +1703,8 @@ CurveBezier::TrimEndAtParam( double dUTrim) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -1786,6 +1805,9 @@ CurveBezier::ExtendStartByLen( double dLenExt) m_vWeCtrl[i] = vWeCtrl[i] ; } } + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; return true ; @@ -1834,6 +1856,9 @@ CurveBezier::ExtendEndByLen( double dLenExt) m_vWeCtrl[i] = vWeCtrl[i] ; } } + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; return true ; @@ -1847,6 +1872,8 @@ CurveBezier::Translate( const Vector3d& vtMove) if ( m_nStatus != OK) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1869,6 +1896,8 @@ CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, if ( vtAx.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1911,6 +1940,8 @@ CurveBezier::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double if ( ! bOk) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1940,6 +1971,8 @@ CurveBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1964,6 +1997,8 @@ CurveBezier::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1996,6 +2031,8 @@ CurveBezier::ToGlob( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2023,6 +2060,8 @@ CurveBezier::ToLoc( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2050,6 +2089,8 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2061,3 +2102,42 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) return true ; } + +//---------------------------------------------------------------------------- +bool +CurveBezier::CalcVoronoiObject() const +{ + if ( m_nStatus != OK) + return false ; + + // creo oggetto vroni con la curva + m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ; + if ( m_pVoronoiObj == nullptr) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +Voronoi* +CurveBezier::GetVoronoiObject() const +{ + if ( m_nStatus != OK) + return nullptr ; + + // se non è stato calcolato, lo calcolo + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // restituisco Voronoi + return m_pVoronoiObj ; +} + +//---------------------------------------------------------------------------- +void +CurveBezier::ResetVoronoiObject() const +{ + if ( m_pVoronoiObj != nullptr) + delete m_pVoronoiObj ; + m_pVoronoiObj = nullptr ; +} \ No newline at end of file diff --git a/CurveBezier.h b/CurveBezier.h index ade321d..15923d7 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -20,6 +20,7 @@ #include "GeoObjRW.h" #include "/EgtDev/Include/EGkCurveBezier.h" #include "/EgtDev/Include/EgtNumCollection.h" +#include "/EgtDev/Include/EGkVoronoi.h" //---------------------------------------------------------------------------- class CurveBezier : public ICurveBezier, public IGeoObjRW @@ -56,6 +57,11 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ICurve bool IsSimple( void) const override { return true ; } @@ -125,6 +131,13 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW bool TrimEndAtLen( double dLenTrim) override ; bool ExtendStartByLen( double dLenExt) override ; bool ExtendEndByLen( double dLenExt) override ; + Voronoi* GetVoronoiObject( void) const override ; + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override + { return CalcCurveVoronoiDiagram( *this, vCrvs, nBound) ; } + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override + { return CalcCurveMedialAxis( *this, vCrvs, nSide) ; } + bool CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) const override + { return CalcCurveFatCurve( *this, vCrvs, dRadius, bSquareEnds, bSquareMids) ; } public : // ICurveBezier bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -149,7 +162,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW public : CurveBezier( void) ; - CurveBezier( const CurveBezier& cbSrc) + CurveBezier( const CurveBezier& cbSrc) : m_pVoronoiObj( nullptr) { if ( ! CopyFrom( cbSrc)) LOG_ERROR( GetEGkLogger(), "CurveBezier : copy constructor error")} CurveBezier& operator =( const CurveBezier& cbSrc) @@ -174,23 +187,27 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW bool ApproxWithArcsXY(double dLinTol, double dAngTolDeg, PolyArc& PA) const; bool BiArcOrSplit(int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const; bool ToPowerBase( PolynomialPoint3d& pol3P) const ; - bool ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const ; + bool ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const ; + bool CalcVoronoiObject( void) const ; + void ResetVoronoiObject( void) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; static const int MAXDEG = 11 ; private : - ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto - Status m_nStatus ; // stato - int m_nDeg ; // grado - bool m_bRat ; // flag di razionale/polinomiale - mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare) - PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo - DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo - Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) - double m_dThick ; // spessore - int m_nTempProp[2] ; // vettore proprietà temporanee + ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto + Status m_nStatus ; // stato + int m_nDeg ; // grado + bool m_bRat ; // flag di razionale/polinomiale + mutable double m_dParSing ; // eventuale parametro della singolarità (-1=no, -2=da calcolare) + PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo + DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo + Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) + double m_dThick ; // spessore + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei + mutable Voronoi* m_pVoronoiObj ; // Voronoi } ; //----------------------------------------------------------------------------- diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 4dd3b6e..9cd0b45 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -42,7 +42,8 @@ GEOOBJ_REGISTER( CRV_COMPO, NGE_C_CMP, CurveComposite) ; //---------------------------------------------------------------------------- CurveComposite::CurveComposite( void) - : m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), m_Iter( m_CrvSmplS.end()), m_nTempProp{0,0} + : m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_ptStart(), + m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_pVoronoiObj( nullptr), m_Iter( m_CrvSmplS.end()) { } @@ -67,8 +68,12 @@ CurveComposite::Clear( void) m_ptStart = ORIG ; m_nTempProp[0] = 0 ; m_nTempProp[1] = 0 ; + m_dTempParam[0] = 0.0 ; + m_dTempParam[1] = 0.0 ; m_Iter = m_CrvSmplS.end() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -112,6 +117,8 @@ CurveComposite::AddCurve( const ICurve& cCrv, bool bEndOrStart, double dLinTol) } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -139,6 +146,8 @@ CurveComposite::AddCurve( ICurve* pCrv, bool bEndOrStart, double dLinTol) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -161,6 +170,8 @@ CurveComposite::AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart, dou return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -253,6 +264,8 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT // aggiorno lo stato m_nStatus = OK ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -285,6 +298,9 @@ CurveComposite::Close( void) ! AddSimpleCurve( Release( pLine))) return false ; } + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -328,6 +344,8 @@ CurveComposite::FromSplit( const ICurve& cCrv, int nParts) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -569,6 +587,8 @@ CurveComposite::CopyFrom( const CurveComposite& ccSrc) m_dThick = ccSrc.m_dThick ; m_nTempProp[0] = ccSrc.m_nTempProp[0] ; m_nTempProp[1] = ccSrc.m_nTempProp[1] ; + m_dTempParam[0] = ccSrc.m_dTempParam[0] ; + m_dTempParam[1] = ccSrc.m_dTempParam[1] ; for ( auto& pCrv : ccSrc.m_CrvSmplS) { if ( ! AddCurve( *pCrv)) return false ; @@ -587,6 +607,8 @@ CurveComposite::RelocateFrom( CurveComposite& ccSrc) m_dThick = ccSrc.m_dThick ; m_nTempProp[0] = ccSrc.m_nTempProp[0] ; m_nTempProp[1] = ccSrc.m_nTempProp[1] ; + m_dTempParam[0] = ccSrc.m_dTempParam[0] ; + m_dTempParam[1] = ccSrc.m_dTempParam[1] ; for ( ICurve* pCrv = ccSrc.RemoveFirstOrLastCurve( false) ; pCrv != nullptr ; pCrv = ccSrc.RemoveFirstOrLastCurve( false)) { @@ -1623,6 +1645,8 @@ CurveComposite::Invert( void) // inverto l'ordine della lista reverse( m_CrvSmplS.begin(), m_CrvSmplS.end()) ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1677,6 +1701,8 @@ CurveComposite::ModifyStart( const Point3d& ptNewStart) if ( ! pCrv->ModifyStart( ptNewStart)) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1698,6 +1724,8 @@ CurveComposite::ModifyEnd( const Point3d& ptNewEnd) if ( ! pCrv->ModifyEnd( ptNewEnd)) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1948,8 +1976,10 @@ CurveComposite::ModifyJoint( int nU, const Point3d& ptNewJoint) // elimino la curva originale delete( pNextCrv) ; } - } + } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2011,6 +2041,8 @@ CurveComposite::RemoveJoint( int nU) m_CrvSmplS.erase( m_CrvSmplS.begin() + nNextCrv) ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2096,6 +2128,8 @@ CurveComposite::MoveCurve( int nCrv, const Vector3d& vtMove) // traslo la curva corrente pCrv->Translate( vtMove) ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2129,6 +2163,8 @@ CurveComposite::ModifyCurveToArc( int nCrv, const Point3d& ptMid) // elimino la curva originale delete( pCrv) ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2165,6 +2201,8 @@ CurveComposite::ModifyCurveToLine( int nCrv) // elimino la curva originale delete( pCrv) ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2180,6 +2218,8 @@ CurveComposite::TrimStartAtParam( double dUTrim) if ( dUTrim < -EPS_PARAM || dUTrim > dMaxU - EPS_PARAM) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2221,6 +2261,8 @@ CurveComposite::TrimEndAtParam( double dUTrim) if ( dUTrim < EPS_PARAM || dUTrim > dMaxU + EPS_PARAM) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2365,6 +2407,8 @@ CurveComposite::TrimStartAtLen( double dLenTrim) } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2428,6 +2472,8 @@ CurveComposite::TrimEndAtLen( double dLenTrim) } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2451,6 +2497,8 @@ CurveComposite::ExtendStartByLen( double dLenExt) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; @@ -2478,6 +2526,8 @@ CurveComposite::ExtendEndByLen( double dLenExt) return false ; } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; @@ -2490,6 +2540,9 @@ CurveComposite::Translate( const Vector3d& vtMove) // la curva deve essere validata if ( m_nStatus != OK) return false ; + + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2511,6 +2564,8 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn if ( vtAx.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2552,6 +2607,8 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou abs( vtDelta.z * dCoeffZ) < EPS_SMALL) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2622,6 +2679,8 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2646,6 +2705,8 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2683,6 +2744,8 @@ CurveComposite::ToGlob( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2711,6 +2774,8 @@ CurveComposite::ToLoc( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2739,6 +2804,8 @@ CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2852,6 +2919,8 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast) // la curva composita deve essere validata if ( m_nStatus != OK) return nullptr ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // recupero la curva semplice iniziale o finale e la tolgo dalla lista if ( ! m_CrvSmplS.empty()) { @@ -2942,6 +3011,8 @@ CurveComposite::ArcsToBezierCurves( void) } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -2988,6 +3059,8 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -3021,6 +3094,8 @@ CurveComposite::StraightArcsToLines( double dLinTol, double dAngTolDeg) } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -3031,6 +3106,14 @@ CurveComposite::StraightArcsToLines( double dLinTol, double dAngTolDeg) static int MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAngTol, bool bNeedSameProp) { + // verifico compatibilità delle proprietà + int nTpr0P = pCrvP->GetTempProp( 0) ; + int nTpr0C = pCrvC->GetTempProp( 0) ; + int nTpr1P = pCrvP->GetTempProp( 1) ; + int nTpr1C = pCrvC->GetTempProp( 1) ; + if ( bNeedSameProp && ( nTpr0P != nTpr0C || nTpr1P != nTpr1C)) + return 0 ; + // se precedente molto corta double dLenP ; if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) { @@ -3050,14 +3133,7 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn Point3d ptEnd ; return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ; } - } - // verifico compatibilità delle proprietà - int nTpr0P = pCrvP->GetTempProp( 0) ; - int nTpr0C = pCrvC->GetTempProp( 0) ; - int nTpr1P = pCrvP->GetTempProp( 1) ; - int nTpr1C = pCrvC->GetTempProp( 1) ; - if ( bNeedSameProp && ( nTpr0P != nTpr0C || nTpr1P != nTpr1C)) - return 0 ; + } // coefficiente deduzione tolleranza const double COEFF_TOL = 0.7 ; // se entrambe rette @@ -3225,6 +3301,8 @@ CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd, } } + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -3565,7 +3643,7 @@ CurveComposite::IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vect //---------------------------------------------------------------------------- bool -CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum) +CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropInd) { // la curva deve essere validata if ( m_nStatus != OK) @@ -3574,13 +3652,13 @@ CurveComposite::SetCurveTempProp( int nCrv, int nProp, int nPropNum) if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size())) return false ; // eseguo assegnazione - m_CrvSmplS[nCrv]->SetTempProp( nProp, nPropNum) ; + m_CrvSmplS[nCrv]->SetTempProp( nProp, nPropInd) ; return true ; } //---------------------------------------------------------------------------- bool -CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropNum) const +CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropInd) const { // la curva deve essere validata if ( m_nStatus != OK) @@ -3589,6 +3667,75 @@ CurveComposite::GetCurveTempProp( int nCrv, int& nProp, int nPropNum) const if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size())) return false ; // eseguo recupero - nProp = m_CrvSmplS[nCrv]->GetTempProp( nPropNum) ; + nProp = m_CrvSmplS[nCrv]->GetTempProp( nPropInd) ; return true ; } + +//---------------------------------------------------------------------------- +bool +CurveComposite::SetCurveTempParam( int nCrv, double dParam, int nParamInd) +{ + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; + // verifico che l'indice sia nei limiti + if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size())) + return false ; + // eseguo assegnazione + m_CrvSmplS[nCrv]->SetTempParam( dParam, nParamInd) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::GetCurveTempParam( int nCrv, double& dParam, int nParamInd) const +{ + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; + // verifico che l'indice sia nei limiti + if ( nCrv < 0 || nCrv >= int( m_CrvSmplS.size())) + return false ; + // eseguo recupero + dParam = m_CrvSmplS[nCrv]->GetTempParam( nParamInd) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::CalcVoronoiObject() const +{ + if ( m_nStatus != OK) + return false ; + + // creo oggetto vroni con la curva + m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ; + if ( m_pVoronoiObj == nullptr) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +Voronoi* +CurveComposite::GetVoronoiObject() const +{ + if ( m_nStatus != OK) + return nullptr ; + + // se non è stato calcolato, lo calcolo + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // restituisco Voronoi + return m_pVoronoiObj ; +} + +//---------------------------------------------------------------------------- +void +CurveComposite::ResetVoronoiObject() const +{ + if ( m_pVoronoiObj != nullptr) + delete m_pVoronoiObj ; + m_pVoronoiObj = nullptr ; +} diff --git a/CurveComposite.h b/CurveComposite.h index bd280a0..263bab6 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -19,6 +19,7 @@ #include "DllMain.h" #include "GeoObjRW.h" #include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkVoronoi.h" #include //---------------------------------------------------------------------------- @@ -53,9 +54,14 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW { return m_OGrMgr.GetObjGraphics() ; } void SetTempProp( int nProp, int nPropInd = 0) override { if ( nPropInd >= 0 && nPropInd < 2) - m_nTempProp[nPropInd] = nProp ; } + m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ICurve bool IsSimple( void) const override @@ -120,6 +126,13 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool TrimEndAtLen( double dLenTrim) override ; bool ExtendStartByLen( double dLenExt) override ; bool ExtendEndByLen( double dLenExt) override ; + Voronoi* GetVoronoiObject( void) const override ; + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override + { return CalcCurveVoronoiDiagram( *this, vCrvs, nBound) ; } + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override + { return CalcCurveMedialAxis( *this, vCrvs, nSide) ; } + bool CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) const override + { return CalcCurveFatCurve( *this, vCrvs, dRadius, bSquareEnds, bSquareMids) ; } public : // ICurveComposite bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -166,9 +179,11 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool IsACircle( double dLinTol, Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const override ; bool IsARectangle( double dLinTol, Point3d& ptP, Vector3d& vtL1, Vector3d& vtL2) const override ; bool IsATrapezoid( double dLinTol, Point3d& ptP, Vector3d& vtB1, Vector3d& vtL1, Vector3d& vtB2) const override ; - bool SetCurveTempProp( int nCrv, int nProp, int nPropNum = 0) override ; - bool GetCurveTempProp( int nCrv, int& nProp, int nPropNum = 0) const override ; - + bool SetCurveTempProp( int nCrv, int nProp, int nPropInd = 0) override ; + bool GetCurveTempProp( int nCrv, int& nProp, int nPropInd = 0) const override ; + bool SetCurveTempParam( int nCrv, double dParam, int nParamInd = 0) override ; + bool GetCurveTempParam( int nCrv, double& dParam, int nParamInd = 0) const override ; + public : // IGeoObjRW int GetNgeId( void) const override ; bool Save( NgeWriter& ngeOut) const override ; @@ -176,7 +191,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW public : CurveComposite( void) ; - CurveComposite( const CurveComposite& ccSrc) + CurveComposite( const CurveComposite& ccSrc) : m_pVoronoiObj( nullptr) { if ( ! CopyFrom( ccSrc)) LOG_ERROR( GetEGkLogger(), "CurveComposite : copy constructor error") } CurveComposite& operator =( const CurveComposite& ccSrc) @@ -193,7 +208,9 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ; bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ; bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ; - bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ; + bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ; + bool CalcVoronoiObject( void) const ; + void ResetVoronoiObject( void) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; @@ -204,14 +221,16 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW typedef PCRVSMPL_DEQUE::const_iterator PCSD_CONST_ITER ; private : - ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto - Status m_nStatus ; // stato - PCRVSMPL_DEQUE m_CrvSmplS ; // deque di curve semplici - Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) - double m_dThick ; // spessore - Point3d m_ptStart ; // punto iniziale per composita vuota per Add di linee o archi - int m_nTempProp[2] ; // vettore proprietà temporanee - mutable PCSD_CONST_ITER m_Iter ; // iteratore + ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto + Status m_nStatus ; // stato + PCRVSMPL_DEQUE m_CrvSmplS ; // deque di curve semplici + Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) + double m_dThick ; // spessore + Point3d m_ptStart ; // punto iniziale per composita vuota per Add di linee o archi + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei + mutable Voronoi* m_pVoronoiObj ; // Voronoi + mutable PCSD_CONST_ITER m_Iter ; // iteratore } ; //----------------------------------------------------------------------------- @@ -251,6 +270,11 @@ inline CurveComposite* ConvertCurveToBasicComposite( IGeoObj* pGObj) if ( nProp != 0) pCrvCo->SetTempProp( nProp, i) ; } + for ( int i = 0 ; i < 2 ; ++ i) { + double dParam = pCrv->GetTempParam( i) ; + if ( abs( dParam) > EPS_SMALL) + pCrvCo->SetTempParam( dParam, i) ; + } pCrvCo->AddCurve( pCrv) ; return pCrvCo ; } diff --git a/CurveLine.cpp b/CurveLine.cpp index bd098c8..72fafd6 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -30,13 +30,15 @@ GEOOBJ_REGISTER( CRV_LINE, NGE_C_LIN, CurveLine) ; //---------------------------------------------------------------------------- CurveLine::CurveLine( void) - : m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick(), m_nTempProp{0,0} + : m_nStatus( TO_VERIFY), m_PtStart(), m_PtEnd(), m_VtExtr(), m_dThick(), + m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_pVoronoiObj( nullptr) { } //---------------------------------------------------------------------------- CurveLine::~CurveLine( void) { + ResetVoronoiObject() ; } //---------------------------------------------------------------------------- @@ -48,6 +50,8 @@ CurveLine::Set( const Point3d& ptStart, const Point3d& ptEnd) m_PtEnd = ptEnd ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -67,6 +71,8 @@ CurveLine::SetPVL( const Point3d& ptStart, const Vector3d& vtDir, double dLen) m_PtEnd = ptStart + vtDelta ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -84,6 +90,8 @@ CurveLine::SetPDL( const Point3d& ptStart, double dDirAngDeg, double dLen) m_PtEnd = ptStart + vtDelta ; m_nStatus = TO_VERIFY ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -126,6 +134,8 @@ CurveLine::CopyFrom( const CurveLine& clSrc) m_dThick = clSrc.m_dThick ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; + m_dTempParam[0] = clSrc.m_dTempParam[0] ; + m_dTempParam[1] = clSrc.m_dTempParam[1] ; return Set( clSrc.m_PtStart, clSrc.m_PtEnd) ; } @@ -556,6 +566,8 @@ CurveLine::Invert( void) // inverto i punti estremi swap( m_PtStart, m_PtEnd) ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -587,6 +599,8 @@ CurveLine::SimpleOffset( double dDist, int nType) m_PtStart += vtDir * dDist ; m_PtEnd += vtDir * dDist ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -607,6 +621,8 @@ CurveLine::ModifyStart( const Point3d& ptNewStart) // assegno il nuovo inizio m_PtStart = ptNewStart ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -627,6 +643,8 @@ CurveLine::ModifyEnd( const Point3d& ptNewEnd) // assegno la nuova fine m_PtEnd = ptNewEnd ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -702,6 +720,8 @@ CurveLine::TrimStartAtLen( double dLenTrim) if ( dLenTrim > EPS_ZERO) m_PtStart = Media( m_PtStart, m_PtEnd, ( dLenTrim / dLen)) ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -726,6 +746,8 @@ CurveLine::TrimEndAtLen( double dLenTrim) if ( ( dLen - dLenTrim) > EPS_ZERO) m_PtEnd = Media( m_PtStart, m_PtEnd, ( dLenTrim / dLen)) ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -748,6 +770,8 @@ CurveLine::ExtendStartByLen( double dLenExt) // sposto il punto iniziale m_PtStart -= vtDir * dLenExt ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -770,6 +794,8 @@ CurveLine::ExtendEndByLen( double dLenExt) // sposto il punto finale m_PtEnd += vtDir * dLenExt ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata m_OGrMgr.Reset() ; @@ -784,6 +810,8 @@ CurveLine::Translate( const Vector3d& vtMove) if ( m_nStatus != OK) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -805,6 +833,8 @@ CurveLine::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, do if ( vtAx.IsSmall()) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -836,6 +866,8 @@ CurveLine::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double d if ( AreSamePointApprox( ptNewStart, ptNewEnd)) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -865,6 +897,8 @@ CurveLine::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( vtNorm.IsSmall()) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -888,6 +922,8 @@ CurveLine::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& v if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -920,6 +956,8 @@ CurveLine::ToGlob( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -942,6 +980,8 @@ CurveLine::ToLoc( const Frame3d& frRef) if ( IsGlobFrame( frRef)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -964,6 +1004,8 @@ CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) if ( AreSameFrame( frOri, frDest)) return true ; + // imposto ricalcolo di Voronoi + ResetVoronoiObject() ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -999,3 +1041,42 @@ CurveLine::CalcPointParamPosiz( const Point3d& ptP, bool bOnXY, double& dU, int& nPos = ICurve::PP_MID ; // nell'interno return true ; } + +//---------------------------------------------------------------------------- +bool +CurveLine::CalcVoronoiObject() const +{ + if ( m_nStatus != OK) + return false ; + + // creo oggetto vroni con la curva + m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ; + if ( m_pVoronoiObj == nullptr) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +Voronoi* +CurveLine::GetVoronoiObject() const +{ + if ( m_nStatus != OK) + return nullptr ; + + // se non è stato calcolato, lo calcolo + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // restituisco Voronoi + return m_pVoronoiObj ; +} + +//---------------------------------------------------------------------------- +void +CurveLine::ResetVoronoiObject() const +{ + if ( m_pVoronoiObj != nullptr) + delete m_pVoronoiObj ; + m_pVoronoiObj = nullptr ; +} \ No newline at end of file diff --git a/CurveLine.h b/CurveLine.h index 53d4fd6..a11fd18 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -18,6 +18,7 @@ #include "DllMain.h" #include "GeoObjRW.h" #include "/EgtDev/Include/EGkCurveLine.h" +#include "/EgtDev/Include/EGkVoronoi.h" //---------------------------------------------------------------------------- class CurveLine : public ICurveLine, public IGeoObjRW @@ -54,6 +55,11 @@ class CurveLine : public ICurveLine, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ICurve bool IsSimple( void) const override @@ -124,6 +130,13 @@ class CurveLine : public ICurveLine, public IGeoObjRW bool TrimEndAtLen( double dLenTrim) override ; bool ExtendStartByLen( double dLenExt) override ; bool ExtendEndByLen( double dLenExt) override ; + Voronoi* GetVoronoiObject( void) const override ; + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override + { return CalcCurveVoronoiDiagram( *this, vCrvs, nBound) ; } + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override + { return CalcCurveMedialAxis( *this, vCrvs, nSide) ; } + bool CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dRadius, bool bSquareEnds, bool bSquareMids) const override + { return CalcCurveFatCurve( *this, vCrvs, dRadius, bSquareEnds, bSquareMids) ; } public : // ICurveLine bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -143,7 +156,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW public : CurveLine( void) ; - CurveLine( const CurveLine& clSrc) + CurveLine( const CurveLine& clSrc) : m_pVoronoiObj( nullptr) { if ( ! CopyFrom( clSrc)) LOG_ERROR( GetEGkLogger(), "CurveLine : copy constructor error") } CurveLine& operator =( const CurveLine& clSrc) @@ -153,19 +166,23 @@ class CurveLine : public ICurveLine, public IGeoObjRW private : bool CopyFrom( const CurveLine& clSrc) ; - bool Validate( void) ; + bool Validate( void) ; + bool CalcVoronoiObject( void) const ; + void ResetVoronoiObject( void) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; private : - ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto - Status m_nStatus ; // stato - Point3d m_PtStart ; // punto iniziale - Point3d m_PtEnd ; // punto finale - Vector3d m_VtExtr ; // vettore estrusione - double m_dThick ; // spessore - int m_nTempProp[2] ; // vettore proprietà temporanee + ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto + Status m_nStatus ; // stato + Point3d m_PtStart ; // punto iniziale + Point3d m_PtEnd ; // punto finale + Vector3d m_VtExtr ; // vettore estrusione + double m_dThick ; // spessore + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei + mutable Voronoi* m_pVoronoiObj ; // Voronoi } ; //----------------------------------------------------------------------------- diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 0ddc02e..f8d2ef9 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index eadab1e..2778ff7 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -309,6 +309,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -343,6 +344,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -614,6 +616,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 4370f17..d101d64 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -498,6 +498,12 @@ File di origine\GeoOffset + + File di origine\GeoOffset + + + File di origine\Base + @@ -1148,6 +1154,9 @@ File di intestazione + + File di intestazione + diff --git a/ExtDimension.cpp b/ExtDimension.cpp index d190c54..25a533a 100644 --- a/ExtDimension.cpp +++ b/ExtDimension.cpp @@ -50,10 +50,9 @@ GEOOBJ_REGISTER( EXT_DIMENSION, NGE_E_DIM, ExtDimension) ; //---------------------------------------------------------------------------- ExtDimension::ExtDimension( void) : m_dExtLineLen( STD_EXTLINELEN), m_dArrowLen( STD_ARROWLEN), m_dTextDist( STD_TEXTDIST), - m_bLenIsMM( true), m_nDecDigit( STD_DECDIGIT), m_sFont( STD_FONT), m_dTextHeight( STD_TEXTHEIGHT) + m_bLenIsMM( true), m_nDecDigit( STD_DECDIGIT), m_sFont( STD_FONT), m_dTextHeight( STD_TEXTHEIGHT), + m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -344,6 +343,8 @@ ExtDimension::CopyFrom( const ExtDimension& clSrc) m_dTextHeight = clSrc.m_dTextHeight ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; + m_dTempParam[0] = clSrc.m_dTempParam[0] ; + m_dTempParam[1] = clSrc.m_dTempParam[1] ; return true ; } diff --git a/ExtDimension.h b/ExtDimension.h index f8ccc70..f896fcc 100644 --- a/ExtDimension.h +++ b/ExtDimension.h @@ -55,6 +55,11 @@ class ExtDimension : public IExtDimension, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IExtDimension bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -157,7 +162,8 @@ class ExtDimension : public IExtDimension, public IGeoObjRW int m_nDecDigit ; // numero di cifre decimali std::string m_sFont ; // font del testo double m_dTextHeight ; // altezza del testo - int m_nTempProp[2] ; // vettore proprietà temporanee + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/ExtText.cpp b/ExtText.cpp index 150a6dc..4e90304 100644 --- a/ExtText.cpp +++ b/ExtText.cpp @@ -35,10 +35,9 @@ GEOOBJ_REGISTER( EXT_TEXT, NGE_E_TXT, ExtText) ; //---------------------------------------------------------------------------- ExtText::ExtText( void) : m_pSTM( nullptr), m_bNoSTM( false), m_ptP(), m_vtN( 0, 0, 1), m_vtD( 1, 0, 0), m_sFont(), - m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0) -{ - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; + m_nWeight( 400), m_bItalic( false), m_dHeight( 10), m_dRatio( 1), m_dAddAdvance( 0), + m_nTempProp{0,0}, m_dTempParam{0.0,0.0} +{ } //---------------------------------------------------------------------------- @@ -188,6 +187,8 @@ ExtText::CopyFrom( const ExtText& clSrc) m_nInsPos = clSrc.m_nInsPos ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; + m_dTempParam[0] = clSrc.m_dTempParam[0] ; + m_dTempParam[1] = clSrc.m_dTempParam[1] ; return true ; } diff --git a/ExtText.h b/ExtText.h index 4b56bff..df50ff3 100644 --- a/ExtText.h +++ b/ExtText.h @@ -55,6 +55,11 @@ class ExtText : public IExtText, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IExtText bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -144,7 +149,8 @@ class ExtText : public IExtText, public IGeoObjRW double m_dRatio ; // rapporto tra larghezza e altezza double m_dAddAdvance ; // avanzamento addizionale tra caratteri int m_nInsPos ; // posizione del punto di inserimento rispetto al testo - int m_nTempProp[2] ; // vettore proprietà temporanee + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/GeoFrame3d.cpp b/GeoFrame3d.cpp index e3ca1f0..e4ce3e3 100644 --- a/GeoFrame3d.cpp +++ b/GeoFrame3d.cpp @@ -29,10 +29,8 @@ GEOOBJ_REGISTER( GEO_FRAME3D, NGE_G_FRM, GeoFrame3d) ; //---------------------------------------------------------------------------- GeoFrame3d::GeoFrame3d( void) - : m_frF() + : m_frF(), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -118,6 +116,8 @@ GeoFrame3d::CopyFrom( const GeoFrame3d& gfSrc) return true ; m_nTempProp[0] = gfSrc.m_nTempProp[0] ; m_nTempProp[1] = gfSrc.m_nTempProp[1] ; + m_dTempParam[0] = gfSrc.m_dTempParam[0] ; + m_dTempParam[1] = gfSrc.m_dTempParam[1] ; return Set( gfSrc.m_frF) ; } diff --git a/GeoFrame3d.h b/GeoFrame3d.h index 850a0a1..f4333a4 100644 --- a/GeoFrame3d.h +++ b/GeoFrame3d.h @@ -62,6 +62,11 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IGeoFrame3d bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -97,6 +102,7 @@ class GeoFrame3d : public IGeoFrame3d, public IGeoObjRW ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Frame3d m_frF ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/GeoPoint3d.cpp b/GeoPoint3d.cpp index 6f02969..bb602dd 100644 --- a/GeoPoint3d.cpp +++ b/GeoPoint3d.cpp @@ -28,10 +28,8 @@ GEOOBJ_REGISTER( GEO_PNT3D, NGE_G_PNT, GeoPoint3d) ; //---------------------------------------------------------------------------- GeoPoint3d::GeoPoint3d( void) - : m_ptP() + : m_ptP(), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -86,6 +84,8 @@ GeoPoint3d::CopyFrom( const GeoPoint3d& clSrc) return true ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; + m_dTempParam[0] = clSrc.m_dTempParam[0] ; + m_dTempParam[1] = clSrc.m_dTempParam[1] ; return Set( clSrc.m_ptP) ; } diff --git a/GeoPoint3d.h b/GeoPoint3d.h index 532d6a4..7b52970 100644 --- a/GeoPoint3d.h +++ b/GeoPoint3d.h @@ -62,6 +62,11 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IGeoPoint3d bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -91,6 +96,7 @@ class GeoPoint3d : public IGeoPoint3d, public IGeoObjRW ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Point3d m_ptP ; // oggetto int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/GeoVector3d.cpp b/GeoVector3d.cpp index 2a9d94d..4cc8ff1 100644 --- a/GeoVector3d.cpp +++ b/GeoVector3d.cpp @@ -29,10 +29,8 @@ GEOOBJ_REGISTER( GEO_VECT3D, NGE_G_VEC, GeoVector3d) ; //---------------------------------------------------------------------------- GeoVector3d::GeoVector3d( void) - : m_vtV(), m_ptBase() + : m_vtV(), m_ptBase(), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -102,6 +100,8 @@ GeoVector3d::CopyFrom( const GeoVector3d& clSrc) return true ; m_nTempProp[0] = clSrc.m_nTempProp[0] ; m_nTempProp[1] = clSrc.m_nTempProp[1] ; + m_dTempParam[0] = clSrc.m_dTempParam[0] ; + m_dTempParam[1] = clSrc.m_dTempParam[1] ; return Set( clSrc.m_vtV, clSrc.m_ptBase) ; } diff --git a/GeoVector3d.h b/GeoVector3d.h index b824f2e..34e8106 100644 --- a/GeoVector3d.h +++ b/GeoVector3d.h @@ -70,6 +70,11 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IGeoVector3d bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -106,6 +111,7 @@ class GeoVector3d : public IGeoVector3d, public IGeoObjRW Vector3d m_vtV ; // oggetto Point3d m_ptBase ; // punto base da cui tracciare il vettore int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/OffsetAux.cpp b/OffsetAux.cpp new file mode 100644 index 0000000..b84bfd8 --- /dev/null +++ b/OffsetAux.cpp @@ -0,0 +1,177 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2013 +//---------------------------------------------------------------------------- +// File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5 +// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve. +// +// +// +// Modifiche : 23.11.23 SP Creazione modulo spostando alcune funzioni da OffsetCurve.cpp. +// +// +//---------------------------------------------------------------------------- + +#include "stdafx.h" +#include "OffsetAux.h" +#include "CurveArc.h" +#include "CurveLine.h" +#include "GeoConst.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +IdentifyFillets( ICurveComposite* pCrvCo, double dDist) +{ + // identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets + for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) { + // recupero la curva + PtrOwner pCrv( pCrvCo->GetCurve(i)->Clone()) ; + if ( IsNull( pCrv)) + return false ; + if ( IsFillet( pCrv, dDist)) + pCrvCo->SetCurveTempParam( i, 1.0) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +IsFillet( ICurve* pCrv, double dDist) +{ + // deve essere un arco + if ( pCrv->GetType() != CRV_ARC) + return false ; + CurveArc* pArc = GetBasicCurveArc( pCrv) ; + // deve avere raggio uguale alla distanza di offset + if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL) + return false ; + // deve essere CCW se offset a destra e CW se offset a sinistra + return ( pArc->GetAngCenter() * dDist > 0) ; +} + +//---------------------------------------------------------------------------- +bool +AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) +{ + ICURVEPLIST CrvLst ; + PtrOwner pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv)) { + // se identificato come fillet lo trasformo in smusso o estensione + if ( pCrv->GetTempParam() > EPS_SMALL) { + CurveComposite ccTemp ; + ModifyFillet( pCrv, dDist, nType, ccTemp) ; + // metto in lista le curve risultanti + if ( ccTemp.GetCurveCount() > 0) { + PtrOwner pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv2)) { + CrvLst.push_back( Release( pCrv2)) ; + pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; + } + } + } + // altrimenti salvo in lista + else + CrvLst.push_back( Release( pCrv)) ; + // passo alla curva successiva + pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ; + } + // rimetto le curve nella composita + for ( auto pCrv : CrvLst) { + pCrvCo->AddCurve( pCrv) ; + } + // unisco tratti allineati + pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) +{ + // la curva deve essere un arco + CurveArc* pArc = GetBasicCurveArc( pCrv) ; + if ( pArc == nullptr) + return false ; + + // angolo al centro dell'arco + double dAngDeg = pArc->GetAngCenter() ; + + // elimino dal tipo le parti estranee all'angolo esterno + nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ; + + // se l'angolo esterno supera il retto, offset extend diventa offset chamfer + if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL) + nType = ICurve::OFF_CHAMFER ; + + // se angolo esterno molto piccolo, semplifico tutto + const double SMALL_EXT_ANG = 1.0 ; + bool bAngSmall = ( abs( dAngDeg) < SMALL_EXT_ANG) ; + if ( bAngSmall) + nType = ICurve::OFF_EXTEND ; + + switch ( nType) { + case ICurve::OFF_CHAMFER : + { + // lunghezza aggiuntiva in tangenza + double dLen = abs( dDist) * tan( abs( dAngDeg) / 4 * DEGTORAD) ; + // punti di costruzione smusso + Point3d ptP1, ptP1a, ptP2a, ptP2 ; + if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) + return false ; + Vector3d vtDir1, vtDir2 ; + if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) + return false ; + ptP1a = ptP1 + vtDir1 * dLen ; + ptP2a = ptP2 - vtDir2 * dLen ; + // aggiungo una nuova linea + PtrOwner pLine1( CreateBasicCurveLine()) ; + if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptP1a)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine1))) + return false ; + // tratto intermedio + PtrOwner pLine2( CreateBasicCurveLine()) ; + if ( IsNull( pLine2) || ! pLine2->Set( ptP1a, ptP2a)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine2))) + return false ; + // aggiungo una nuova linea + PtrOwner pLine3( CreateBasicCurveLine()) ; + if ( IsNull( pLine3) || ! pLine3->Set( ptP2a, ptP2)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine3))) + return false ; + return true ; + } + break ; + case ICurve::OFF_EXTEND : + { + // lunghezza aggiuntiva in tangenza + double dLen = abs( dDist) * tan( abs( dAngDeg) / 2 * DEGTORAD) ; + // punti di costruzione estensione + Point3d ptP1, ptPc, ptP2 ; + if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) + return false ; + Vector3d vtDir1, vtDir2 ; + if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) + return false ; + ptPc = ptP1 + vtDir1 * dLen ; + // aggiungo una nuova linea + PtrOwner pLine1( CreateBasicCurveLine()) ; + if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptPc)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine1))) + return false ; + // aggiungo una nuova linea + PtrOwner pLine2( CreateBasicCurveLine()) ; + if ( IsNull( pLine2) || ! pLine2->Set( ptPc, ptP2)) + return false ; + if ( ! ccAux.AddCurve( Release( pLine2))) + return false ; + return true ; + } + } + return false ; +} diff --git a/OffsetAux.h b/OffsetAux.h new file mode 100644 index 0000000..6564059 --- /dev/null +++ b/OffsetAux.h @@ -0,0 +1,21 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2013 +//---------------------------------------------------------------------------- +// File : OffsetAux.h Data : 23.11.23 Versione : 2.5k5 +// Contenuto : Dichiarazione di alcune funzioni di utilità per gli offset delle curve. +// +// +// +// Modifiche : 23.11.23 SP Creazione modulo spostando alcune funzioni da OffsetCurve.cpp. +// +// +//---------------------------------------------------------------------------- + +#pragma once +#include "CurveComposite.h" + +//---------------------------------------------------------------------------- +bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ; +bool IsFillet( ICurve* pCrv, double dDist) ; +bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ; +bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ; diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index f304224..7c19400 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -20,6 +20,7 @@ #include "CurveArc.h" #include "CurveComposite.h" #include "RemoveCurveDefects.h" +#include "OffsetAux.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkIntersCurves.h" #include "/EgtDev/Include/EGkDistPointCurve.h" @@ -40,9 +41,6 @@ static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRe static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, double dDist, int nType, CurveComposite& ccAux) ; static double GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) ; -static bool IsFillet( ICurve* pCrv, double dDist) ; -static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux) ; - //---------------------------------------------------------------------------- OffsetCurve::~OffsetCurve( void) @@ -66,7 +64,7 @@ OffsetCurve::Reset( void) //---------------------------------------------------------------------------- bool -OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) +OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType, bool bUseVoronoi) { // pulisco tutto Reset() ; @@ -154,552 +152,553 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) ccCopy.ToLoc( frCopy) ; } - // verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+) - if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG)) - return false ; - - // verifico se curva chiusa e non forzata aperta - bool bClosed = ccCopy.IsClosed() && ( nType & ICurve::OFF_FORCE_OPEN) == 0 ; - - // elimino eventuali piccole Z - if ( ! RemoveCurveSmallZs( &ccCopy, 10 * EPS_SMALL)) - return false ; - - // elimino tratti molto corti - if ( ! RemoveCurveSmallParts( &ccCopy, 10 * EPS_SMALL)) - return false ; - - // converto archi diritti in segmenti di retta - const double ANG_CEN_MAX = 0.5 ; - if ( ! ccCopy.StraightArcsToLines( 2 * EPS_SMALL, ANG_CEN_MAX)) - return false ; - // recupero punto iniziale Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ; - // unisco parti allineate - if ( ! ccCopy.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, bClosed)) - return false ; + // verifico se curva chiusa e non forzata aperta + bool bClosed = ccCopy.IsClosed() && ( nType & ICurve::OFF_FORCE_OPEN) == 0 ; - // verifico se il punto iniziale è stato modificato - Point3d ptNewStart ; ccCopy.GetStartPoint( ptNewStart) ; - bool bChangeStart = ( ! AreSamePointApprox( ptNewStart, ptStart)) ; + bool bChangeStart = true ; - // calcolo le lunghezze delle diverse entità - DBLVECTOR vLens ; - { - const ICurve* pCrv1 = ccCopy.GetFirstCurve() ; - while ( pCrv1 != nullptr) { - double dLen ; - if ( ! pCrv1->GetLength( dLen)) - return false ; - vLens.push_back( dLen) ; - pCrv1 = ccCopy.GetNextCurve() ; - } - } - // calcolo gli angoli tra le diverse entità - DBLVECTOR vAngs ; - { - vAngs.push_back( 0) ; - const ICurve* pCrv1 = ccCopy.GetFirstCurve() ; - const ICurve* pCrv2 = ccCopy.GetNextCurve() ; - while ( pCrv2 != nullptr) { - double dAngDeg ; - if ( ! CalcAngle( pCrv1, pCrv2, dAngDeg)) - return false ; - vAngs.push_back( dAngDeg) ; - pCrv1 = pCrv2 ; - pCrv2 = ccCopy.GetNextCurve() ; - } - // se chiusa, calcolo angolo da ultima a prima - if ( bClosed) { - pCrv2 = ccCopy.GetFirstCurve() ; - double dAngDeg ; - if ( ! CalcAngle( pCrv1, pCrv2, dAngDeg)) - return false ; - vAngs.push_back( dAngDeg) ; - vAngs[0] = dAngDeg ; - } - else - vAngs.push_back( 0) ; - } + // -------------------- OFFSET STANDARD --------------------------------- + if ( ! bUseVoronoi) { - // primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet) - CurveComposite ccCopy2 ; - if ( ! ccCopy2.CopyFrom( &ccCopy)) - return false ; - // indice della prima curva (1-based, per poter assegnare un significato al segno) - int nInd1 = 1 ; - // recupero la prima curva e la offsetto - PtrOwner pCrv1( ccCopy2.RemoveFirstOrLastCurve( false)) ; - if ( IsNull( pCrv1)) - return false ; - pCrv1->SetTempProp( nInd1) ; - if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET)) { - CurveArc* pArc = GetBasicCurveArc( pCrv1) ; - if ( pArc == nullptr) + // verifico se il punto iniziale è stato modificato + Point3d ptNewStart ; ccCopy.GetStartPoint( ptNewStart) ; + bChangeStart = ( ! AreSamePointApprox( ptNewStart, ptStart)) ; + + // verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+) + if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG)) return false ; - if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET)) - pCrv1->SetTempProp( - nInd1) ; - } - // curve successive - PtrOwner pCrv2( ccCopy2.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv2)) { - // eseguo semplice offset - pCrv2->SetTempProp( nInd1 + 1) ; - if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET)) { - CurveArc* pArc = GetBasicCurveArc( pCrv2) ; + + // elimino eventuali piccole Z + if ( ! RemoveCurveSmallZs( &ccCopy, 10 * EPS_SMALL)) + return false ; + + // elimino tratti molto corti + if ( ! RemoveCurveSmallParts( &ccCopy, 10 * EPS_SMALL)) + return false ; + + // converto archi diritti in segmenti di retta + const double ANG_CEN_MAX = 0.5 ; + if ( ! ccCopy.StraightArcsToLines( 2 * EPS_SMALL, ANG_CEN_MAX)) + return false ; + // unisco parti allineate + if ( ! ccCopy.MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, bClosed)) + return false ; + + // calcolo le lunghezze delle diverse entità + DBLVECTOR vLens ; + { + const ICurve* pCrv1 = ccCopy.GetFirstCurve() ; + while ( pCrv1 != nullptr) { + double dLen ; + if ( ! pCrv1->GetLength( dLen)) + return false ; + vLens.push_back( dLen) ; + pCrv1 = ccCopy.GetNextCurve() ; + } + } + // calcolo gli angoli tra le diverse entità + DBLVECTOR vAngs ; + { + vAngs.push_back( 0) ; + const ICurve* pCrv1 = ccCopy.GetFirstCurve() ; + const ICurve* pCrv2 = ccCopy.GetNextCurve() ; + while ( pCrv2 != nullptr) { + double dAngDeg ; + if ( ! CalcAngle( pCrv1, pCrv2, dAngDeg)) + return false ; + vAngs.push_back( dAngDeg) ; + pCrv1 = pCrv2 ; + pCrv2 = ccCopy.GetNextCurve() ; + } + // se chiusa, calcolo angolo da ultima a prima + if ( bClosed) { + pCrv2 = ccCopy.GetFirstCurve() ; + double dAngDeg ; + if ( ! CalcAngle( pCrv1, pCrv2, dAngDeg)) + return false ; + vAngs.push_back( dAngDeg) ; + vAngs[0] = dAngDeg ; + } + else + vAngs.push_back( 0) ; + } + + // primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet) + CurveComposite ccCopy2 ; + if ( ! ccCopy2.CopyFrom( &ccCopy)) + return false ; + // indice della prima curva (1-based, per poter assegnare un significato al segno) + int nInd1 = 1 ; + // recupero la prima curva e la offsetto + PtrOwner pCrv1( ccCopy2.RemoveFirstOrLastCurve( false)) ; + if ( IsNull( pCrv1)) + return false ; + pCrv1->SetTempProp( nInd1) ; + if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET)) { + CurveArc* pArc = GetBasicCurveArc( pCrv1) ; if ( pArc == nullptr) return false ; if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET)) - pCrv2->SetTempProp( - ( nInd1 + 1)) ; - } - // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie - CurveComposite ccTemp ; - VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; - // metto in lista curva precedente - m_CrvLst.push_back( Release( pCrv1)) ; - // se aggiunto qualcosa, lo metto in lista - if ( ccTemp.GetCurveCount() > 0) { - PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv3)) { - m_CrvLst.push_back( Release( pCrv3)) ; - pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; - } - } - // aggiorno curva precedente - ++ nInd1 ; - pCrv1.Set( pCrv2) ; - // passo alla curva successiva - pCrv2.Set( ccCopy2.RemoveFirstOrLastCurve( false)) ; - } - // Metto in lista l'ultima curva rimasta - if ( ! IsNull( pCrv1)) - m_CrvLst.push_back( Release( pCrv1)) ; - - // se originale chiuso, devo confrontare anche ultima e prima curva - if ( bClosed && m_CrvLst.size() >= 2) { - // la curva precedente è l'ultima dell'offset - ICurve* pCrv1 = m_CrvLst.back() ; - // la curva successiva ora è la prima dell'offset - ICurve* pCrv2 = m_CrvLst.front() ; - // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie - CurveComposite ccTemp ; - VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; - // se aggiunto qualcosa, lo metto in lista - if ( ccTemp.GetCurveCount() > 0) { - PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv3)) { - m_CrvLst.push_back( Release( pCrv3)) ; - pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; - } - } - } - - // aggiorno lunghezza segmenti di retta (possono essere stati allungati) - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { - const ICurve* pCrv = *iIter ; - if ( pCrv->GetType() == CRV_LINE) { - double dLen ; pCrv->GetLength( dLen) ; - int nInd = abs( pCrv->GetTempProp()) - 1 ; - if ( nInd >= 0 && nInd < int( vLens.size())) - vLens[nInd] = dLen ; - } - } - - // secondo passo : eliminazione archi invertiti e rette impossibili - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - ICurve* pCrv = *iIter ; - // controllo e rimuovo archi invertiti o nulli - if ( pCrv->GetTempProp() < 0 || - ( pCrv->GetType() == CRV_ARC && GetBasicCurveArc(pCrv)->GetRadius() < EPS_SMALL)) { - delete pCrv ; - pCrv = nullptr ; - iIter = m_CrvLst.erase( iIter) ; - continue ; - } - // controllo e rimuovo rette destinate all'eliminazione (da Voronoi con adiacenti) - if ( pCrv->GetType() == CRV_LINE) { - int nInd1 = abs( pCrv->GetTempProp()) ; - // verifico se angoli precedente e successivo interni con rette di lunghezza non inferiore - bool bPrevInt = PreviousIsLine( iIter, m_CrvLst, bClosed) && - PreviousIsLonger( nInd1, vLens, bClosed) && - ( ( dDist < 0 && vAngs[nInd1-1] > 0) || ( dDist > 0 && vAngs[nInd1-1] < 0)) ; - bool bNextInt = NextIsLine( iIter, m_CrvLst, bClosed) && - NextIsLonger( nInd1, vLens, bClosed) && - ( ( dDist < 0 && vAngs[nInd1] > 0) || ( dDist > 0 && vAngs[nInd1] < 0)) ; - // calcolo la massima estensione di offset (Voronoi con entità adiacenti) - double dMaxDist = INFINITO ; - if ( bPrevInt && bNextInt) { - double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ; - double dTgB = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1])) * DEGTORAD) ; - dMaxDist = dTgA * dTgB / ( dTgA + dTgB) * vLens[nInd1-1] ; - } - else if ( bPrevInt) { - double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ; - dMaxDist = dTgA * vLens[nInd1-1] ; - } - else if ( bNextInt) { - double dTgB = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1])) * DEGTORAD) ; - dMaxDist = dTgB * vLens[nInd1-1] ; - } - if ( abs( dDist) > dMaxDist + 5 * EPS_SMALL) { - delete pCrv ; - iIter = m_CrvLst.erase( iIter) ; - continue ; - } - } - // passo al successivo - ++ iIter ; - } - - // terzo passo : taglio angoli interni - ICurve* pPrev = nullptr ; - if ( bClosed && ! m_CrvLst.empty()) - pPrev = m_CrvLst.back() ; - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - ICurve* pCrv = *iIter ; - // gestione e verifica di estremi quasi coincidenti ed angoli interni - if ( pPrev != nullptr) { - int nRes ; - if ( VerifyAndAdjustSamePoint( pPrev, pCrv, nRes)) { - if ( nRes == 4) - VerifyAndAdjustInternalAngle( pPrev, pCrv, nRes) ; - // precedente da cancellare - if ( ( nRes & 1) != 0) { - auto iErase = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ; - delete pPrev ; - pPrev = nullptr ; - m_CrvLst.erase( iErase) ; - if ( m_CrvLst.empty()) - break ; - auto iPrev = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ; - pPrev = *iPrev ; - } - // corrente da cancellare - if ( ( nRes & 2) != 0) { - delete pCrv ; - pCrv = nullptr ; - iIter = m_CrvLst.erase( iIter) ; - } - // se eseguita una cancellazione, non devo incrementare - if ( ( nRes & 3) != 0) - continue ; - } - } - // passo al successivo - pPrev = pCrv ; - ++ iIter ; - } - - // quarto passo : conversione in curva composita chiudendo gli eventuali buchi con rette - PtrOwner pCrvCompo( CreateBasicCurveComposite()) ; - if ( IsNull( pCrvCompo)) - return false ; - Point3d ptPrec ; - if ( ! m_CrvLst.empty()) - m_CrvLst.front()->GetStartPoint( ptPrec) ; - for ( auto& pCrv : m_CrvLst) { - // se curva troppo piccola la salto - double dCrvLen ; - if ( ! pCrv->GetLength( dCrvLen)) { - delete( pCrv) ; - pCrv = nullptr ; - continue ; - } - // se punto iniziale diverso da precedente, inserisco segmento di collegamento - Point3d ptStart ; - pCrv->GetStartPoint( ptStart) ; - if ( ! AreSamePointApprox( ptPrec, ptStart)) { - CurveLine crvLine ; - crvLine.Set( ptPrec, ptStart) ; - pCrvCompo->AddCurve( crvLine) ; - } - // salvo punto finale come nuovo precedente - pCrv->GetEndPoint( ptPrec) ; - // aggiungo la curva alla composita - pCrvCompo->AddCurve( pCrv) ; - pCrv = nullptr ; - } - m_CrvLst.clear() ; - // se curva chiusa, verifico anche gap tra inizio e fine - if ( bClosed) - pCrvCompo->Close() ; - - // se non rimasto nulla, esco - double dLen ; - if ( ! pCrvCompo->IsValid() || ! pCrvCompo->GetLength( dLen) || dLen < 10 * EPS_SMALL) - return true ; - // inserisco la curva nella lista - m_CrvLst.push_back( Release( pCrvCompo)) ; - CurveComposite* pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; - - // quinto passo : spezzatura della curva composita negli eventuali punti di auto-intersezione - // calcolo le auto-intersezioni - SelfIntersCurve sintC( *pCompo1) ; - DBLVECTOR vU ; - IntCrvCrvInfo iccInfo ; - for ( int i = 0 ; sintC.GetIntCrvCrvInfo( i, iccInfo) ; ++ i) { - if ( ! iccInfo.bOverlap) { - vU.push_back( iccInfo.IciA[0].dU) ; - vU.push_back( iccInfo.IciB[0].dU) ; - } - else { - vU.push_back( iccInfo.IciA[0].dU) ; - vU.push_back( iccInfo.IciA[1].dU) ; - vU.push_back( iccInfo.IciB[0].dU) ; - vU.push_back( iccInfo.IciB[1].dU) ; - } - } - // ordino il vettore in senso crescente - sort( vU.begin(), vU.end(), less()) ; - // calcolo il vettore delle lunghezze di ogni parte di curva - DBLVECTOR vLen ; - for ( const auto& dU : vU) { - double dULen ; - pCompo1->GetLengthAtParam( dU, dULen) ; - vLen.push_back( dULen) ; - } - // se ultima parte molto piccola, la elimino - while ( ! vU.empty() && ( dLen - vLen.back()) < 2 * EPS_SMALL) { - vU.pop_back() ; - vLen.pop_back() ; - } - // eseguo la divisione - double dUPrev = 0 ; - double dLenPrev = 0 ; - for ( int i = 0 ; i < int( vU.size()) ; ++ i) { - // se lunghezza della curva risulta piccola, salto - if ( ( vLen[i] - dLenPrev) < 2 * EPS_SMALL) - continue ; - // copio la curva - PtrOwner pCopy( pCompo1->Clone()) ; - if ( IsNull( pCopy)) - return false ; - m_CrvLst.push_back( Release( pCopy)) ; - // trimmo l'originale - pCompo1->TrimStartEndAtParam( dUPrev, vU[i]) ; - // la copia diventa il nuovo corrente - pCompo1 = GetBasicCurveComposite( m_CrvLst.back()) ; - dUPrev = vU[i] ; - dLenPrev = vLen[i] ; - } - // se fatta almeno una suddivisione - bool bFirstLastSame = false ; - if ( dUPrev > EPS_PARAM) { - // trimmo l'ultima parte - pCompo1->TrimStartAtParam( dUPrev) ; - // rilevo le curve chiuse con due parti di una stessa curva all'inizio e alla fine - if ( bClosed && vU[0] > EPS_PARAM && vLen[0] >= 2 * EPS_SMALL) - bFirstLastSame = true ; - } - - // sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi - if ( ! bClosed) { - // ciconferenza sull'estremità iniziale - Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ; - PtrOwner pCircS( CreateBasicCurveArc()) ; - if ( IsNull( pCircS) || ! pCircS->Set( ptStart, Z_AX, abs( dDist))) - return false ; - // elimino le parti di offset interne a questa circonferenza - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - // recupero la curva e il suo dominio - ICurve* pCrv = *iIter ; - double dStart, dEnd ; - if ( ! pCrv->GetDomain( dStart, dEnd)) - return false ; - // determino gli intervalli da conservare (inizializzo come tutta la curva per poi rimuovere la parte finale) - Intervals inOk( EPS_PARAM) ; - inOk.Set( dStart, dEnd) ; - IntersCurveCurve ccInt( *pCrv, *pCircS) ; - CRVCVECTOR ccPart ; - if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart)) - return false ; - for ( auto& ccOne : ccPart) { - switch ( ccOne.nClass) { - case CRVC_IN : - // intervallo standard - if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) - inOk.Subtract( ccOne.dParS, ccOne.dParE) ; - // intervallo che attraversa punto di chiusura della curva - else { - inOk.Subtract( ccOne.dParS, dEnd) ; - inOk.Subtract( dStart, ccOne.dParE) ; - } - break ; - case CRVC_NULL : + pCrv1->SetTempProp( - nInd1) ; + } + // curve successive + PtrOwner pCrv2( ccCopy2.RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv2)) { + // eseguo semplice offset + pCrv2->SetTempProp( nInd1 + 1) ; + if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET)) { + CurveArc* pArc = GetBasicCurveArc( pCrv2) ; + if ( pArc == nullptr) return false ; + if ( pArc->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET)) + pCrv2->SetTempProp( - ( nInd1 + 1)) ; + } + // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie + CurveComposite ccTemp ; + VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; + // metto in lista curva precedente + m_CrvLst.push_back( Release( pCrv1)) ; + // se aggiunto qualcosa, lo metto in lista + if ( ccTemp.GetCurveCount() > 0) { + PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv3)) { + m_CrvLst.push_back( Release( pCrv3)) ; + pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; } } - // eseguo trim (solo della parte iniziale) - double dMin, dMax ; - if ( inOk.GetLast( dMin, dMax)) { - if ( dMin > dStart + 100 * EPS_PARAM) - pCrv->TrimStartAtParam( dMin) ; - } - else { - delete pCrv ; - iIter = m_CrvLst.erase( iIter) ; - continue ; - } - // passo alla successiva - ++ iIter ; + // aggiorno curva precedente + ++ nInd1 ; + pCrv1.Set( pCrv2) ; + // passo alla curva successiva + pCrv2.Set( ccCopy2.RemoveFirstOrLastCurve( false)) ; } - // circonferenza sull'estremità finale - Point3d ptEnd ; ccCopy.GetEndPoint( ptEnd) ; - PtrOwner pCircE( CreateBasicCurveArc()) ; - if ( IsNull( pCircE) || ! pCircE->Set( ptEnd, Z_AX, abs( dDist))) - return false ; - // elimino le parti di offset interna a questa circonferenza - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - // recupero la curva e il suo dominio - ICurve* pCrv = *iIter ; - double dStart, dEnd ; - if ( ! pCrv->GetDomain( dStart, dEnd)) - return false ; - // determino gli intervalli da conservare (inizializzo come tutta la curva per poi poter rimuovere parti) - Intervals inOk( EPS_PARAM) ; - inOk.Set( dStart, dEnd) ; - IntersCurveCurve ccInt( *pCrv, *pCircE) ; - CRVCVECTOR ccPart ; - if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart)) - return false ; - for ( auto& ccOne : ccPart) { - switch ( ccOne.nClass) { - case CRVC_IN : - // intervallo standard - if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) - inOk.Subtract( ccOne.dParS, ccOne.dParE) ; - // intervallo che attraversa punto di chiusura della curva - else { - inOk.Subtract( ccOne.dParS, dEnd) ; - inOk.Subtract( dStart, ccOne.dParE) ; - } - break ; - case CRVC_NULL : - return false ; + // Metto in lista l'ultima curva rimasta + if ( ! IsNull( pCrv1)) + m_CrvLst.push_back( Release( pCrv1)) ; + + // se originale chiuso, devo confrontare anche ultima e prima curva + if ( bClosed && m_CrvLst.size() >= 2) { + // la curva precedente è l'ultima dell'offset + ICurve* pCrv1 = m_CrvLst.back() ; + // la curva successiva ora è la prima dell'offset + ICurve* pCrv2 = m_CrvLst.front() ; + // verifico relazione con la curva precedente e aggiungo eventuali curve intermedie + CurveComposite ccTemp ; + VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ; + // se aggiunto qualcosa, lo metto in lista + if ( ccTemp.GetCurveCount() > 0) { + PtrOwner pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ; + while ( ! IsNull( pCrv3)) { + m_CrvLst.push_back( Release( pCrv3)) ; + pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; } } - // eseguo trim (solo della parte finale) - double dMin, dMax ; - if ( inOk.GetFirst( dMin, dMax)) { - if ( dMax < dEnd - 100 * EPS_PARAM) - pCrv->TrimEndAtParam( dMax) ; - } - else { - delete pCrv ; - iIter = m_CrvLst.erase( iIter) ; - continue ; - } - // passo alla successiva - ++ iIter ; } - } - // settimo passo : elimino le parti che sono troppo vicine al percorso originale - bool bFirstLastDeleted = false ; - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - ICurve* pCrv = *iIter ; - // distanza minima di alcuni punti interni della curva dalla curva originale - if ( GetMinDist( 0.5, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.25, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.75, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.125, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.875, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.0625, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || - GetMinDist( 0.9375, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL) { - // se prima e ultima sono la stessa curva e non ancora cancellate e prima da cancellare - if ( bFirstLastSame && ! bFirstLastDeleted && iIter == m_CrvLst.begin()) { - bFirstLastDeleted = true ; - // cancello ultima - delete *prev( m_CrvLst.end()) ; - m_CrvLst.pop_back() ; - } - // se prima e ultima sono la stessa curva e non ancora cancellate e ultima da cancellare - if ( bFirstLastSame && ! bFirstLastDeleted && iIter == prev( m_CrvLst.end())) { - bFirstLastDeleted = true ; - // cancello prima - delete *m_CrvLst.begin() ; - m_CrvLst.pop_front() ; - } - // cancello la corrente - delete pCrv ; - iIter = m_CrvLst.erase( iIter) ; - // evito incremento - continue ; - } - // passo alla successiva - ++ iIter ; - } - - // ottavo passo : concateno i percorsi risultanti (senza cambiare verso) - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { - CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; - // recupero punti iniziale e finale della curva - Point3d ptStart, ptEnd ; - pCrvCo->GetStartPoint( ptStart) ; - pCrvCo->GetEndPoint( ptEnd) ; - // ciclo sulle curve successive per verificare se possibile concatenamento - for ( auto iIter2 = next( iIter) ; iIter2 != m_CrvLst.end() ;) { - CurveComposite* pCrvCo2 = GetBasicCurveComposite( *iIter2) ; - // recupero punti iniziale e finale della curva - Point3d ptStart2, ptEnd2 ; - pCrvCo2->GetStartPoint( ptStart2) ; - pCrvCo2->GetEndPoint( ptEnd2) ; - // verifiche di concatenamento - if ( AreSamePointEpsilon( ptEnd, ptStart2, 10 * EPS_SMALL)) { - if ( pCrvCo->AddCurve( pCrvCo2, true, 10 * EPS_SMALL)) - ptEnd = ptEnd2 ; - m_CrvLst.erase( iIter2) ; - iIter2 = next( iIter) ; - } - else if ( AreSamePointEpsilon( ptEnd2, ptStart, 10 * EPS_SMALL)) { - if ( pCrvCo->AddCurve( pCrvCo2, false, 10 * EPS_SMALL)) - ptStart = ptStart2 ; - m_CrvLst.erase( iIter2) ; - iIter2 = next( iIter) ; - } - else - ++ iIter2 ; - } - ++ iIter ; - } - - // nono passo : se con smusso o estensione, sostituisco i fillet con questi - if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + // aggiorno lunghezza segmenti di retta (possono essere stati allungati) for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { - // processo le curve semplici della composita - CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; - ICURVEPLIST CrvLst ; - PtrOwner pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv)) { - // se fillet lo trasformo in smusso o estensione - if ( IsFillet( pCrv, dDist)) { - CurveComposite ccTemp ; - ModifyFillet( pCrv, dDist, nType, ccTemp) ; - // metto in lista le curve risultanti - if ( ccTemp.GetCurveCount() > 0) { - PtrOwner pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv2)) { - CrvLst.push_back( Release( pCrv2)) ; - pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; + const ICurve* pCrv = *iIter ; + if ( pCrv->GetType() == CRV_LINE) { + double dLen ; pCrv->GetLength( dLen) ; + int nInd = abs( pCrv->GetTempProp()) - 1 ; + if ( nInd >= 0 && nInd < int( vLens.size())) + vLens[nInd] = dLen ; + } + } + + // secondo passo : eliminazione archi invertiti e rette impossibili + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + ICurve* pCrv = *iIter ; + // controllo e rimuovo archi invertiti o nulli + if ( pCrv->GetTempProp() < 0 || + ( pCrv->GetType() == CRV_ARC && GetBasicCurveArc(pCrv)->GetRadius() < EPS_SMALL)) { + delete pCrv ; + pCrv = nullptr ; + iIter = m_CrvLst.erase( iIter) ; + continue ; + } + // controllo e rimuovo rette destinate all'eliminazione (da Voronoi con adiacenti) + if ( pCrv->GetType() == CRV_LINE) { + int nInd1 = abs( pCrv->GetTempProp()) ; + // verifico se angoli precedente e successivo interni con rette di lunghezza non inferiore + bool bPrevInt = PreviousIsLine( iIter, m_CrvLst, bClosed) && + PreviousIsLonger( nInd1, vLens, bClosed) && + ( ( dDist < 0 && vAngs[nInd1-1] > 0) || ( dDist > 0 && vAngs[nInd1-1] < 0)) ; + bool bNextInt = NextIsLine( iIter, m_CrvLst, bClosed) && + NextIsLonger( nInd1, vLens, bClosed) && + ( ( dDist < 0 && vAngs[nInd1] > 0) || ( dDist > 0 && vAngs[nInd1] < 0)) ; + // calcolo la massima estensione di offset (Voronoi con entità adiacenti) + double dMaxDist = INFINITO ; + if ( bPrevInt && bNextInt) { + double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ; + double dTgB = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1])) * DEGTORAD) ; + dMaxDist = dTgA * dTgB / ( dTgA + dTgB) * vLens[nInd1-1] ; + } + else if ( bPrevInt) { + double dTgA = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1-1])) * DEGTORAD) ; + dMaxDist = dTgA * vLens[nInd1-1] ; + } + else if ( bNextInt) { + double dTgB = tan( 0.5 * ( ANG_STRAIGHT - abs( vAngs[nInd1])) * DEGTORAD) ; + dMaxDist = dTgB * vLens[nInd1-1] ; + } + if ( abs( dDist) > dMaxDist + 5 * EPS_SMALL) { + delete pCrv ; + iIter = m_CrvLst.erase( iIter) ; + continue ; + } + } + // passo al successivo + ++ iIter ; + } + + // terzo passo : taglio angoli interni + ICurve* pPrev = nullptr ; + if ( bClosed && ! m_CrvLst.empty()) + pPrev = m_CrvLst.back() ; + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + ICurve* pCrv = *iIter ; + // gestione e verifica di estremi quasi coincidenti ed angoli interni + if ( pPrev != nullptr) { + int nRes ; + if ( VerifyAndAdjustSamePoint( pPrev, pCrv, nRes)) { + if ( nRes == 4) + VerifyAndAdjustInternalAngle( pPrev, pCrv, nRes) ; + // precedente da cancellare + if ( ( nRes & 1) != 0) { + auto iErase = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ; + delete pPrev ; + pPrev = nullptr ; + m_CrvLst.erase( iErase) ; + if ( m_CrvLst.empty()) + break ; + auto iPrev = prev( iIter != m_CrvLst.begin() ? iIter : m_CrvLst.end()) ; + pPrev = *iPrev ; + } + // corrente da cancellare + if ( ( nRes & 2) != 0) { + delete pCrv ; + pCrv = nullptr ; + iIter = m_CrvLst.erase( iIter) ; + } + // se eseguita una cancellazione, non devo incrementare + if ( ( nRes & 3) != 0) + continue ; + } + } + // passo al successivo + pPrev = pCrv ; + ++ iIter ; + } + + // quarto passo : conversione in curva composita chiudendo gli eventuali buchi con rette + PtrOwner pCrvCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCrvCompo)) + return false ; + Point3d ptPrec ; + if ( ! m_CrvLst.empty()) + m_CrvLst.front()->GetStartPoint( ptPrec) ; + for ( auto& pCrv : m_CrvLst) { + // se curva troppo piccola la salto + double dCrvLen ; + if ( ! pCrv->GetLength( dCrvLen)) { + delete( pCrv) ; + pCrv = nullptr ; + continue ; + } + // se punto iniziale diverso da precedente, inserisco segmento di collegamento + Point3d ptStart ; + pCrv->GetStartPoint( ptStart) ; + if ( ! AreSamePointApprox( ptPrec, ptStart)) { + CurveLine crvLine ; + crvLine.Set( ptPrec, ptStart) ; + pCrvCompo->AddCurve( crvLine) ; + } + // salvo punto finale come nuovo precedente + pCrv->GetEndPoint( ptPrec) ; + // aggiungo la curva alla composita + pCrvCompo->AddCurve( pCrv) ; + pCrv = nullptr ; + } + m_CrvLst.clear() ; + // se curva chiusa, verifico anche gap tra inizio e fine + if ( bClosed) + pCrvCompo->Close() ; + + // se non rimasto nulla, esco + double dLen ; + if ( ! pCrvCompo->IsValid() || ! pCrvCompo->GetLength( dLen) || dLen < 10 * EPS_SMALL) + return true ; + // inserisco la curva nella lista + m_CrvLst.push_back( Release( pCrvCompo)) ; + CurveComposite* pCompo1 = GetBasicCurveComposite( m_CrvLst.front()) ; + + // quinto passo : spezzatura della curva composita negli eventuali punti di auto-intersezione + // calcolo le auto-intersezioni + SelfIntersCurve sintC( *pCompo1) ; + DBLVECTOR vU ; + IntCrvCrvInfo iccInfo ; + for ( int i = 0 ; sintC.GetIntCrvCrvInfo( i, iccInfo) ; ++ i) { + if ( ! iccInfo.bOverlap) { + vU.push_back( iccInfo.IciA[0].dU) ; + vU.push_back( iccInfo.IciB[0].dU) ; + } + else { + vU.push_back( iccInfo.IciA[0].dU) ; + vU.push_back( iccInfo.IciA[1].dU) ; + vU.push_back( iccInfo.IciB[0].dU) ; + vU.push_back( iccInfo.IciB[1].dU) ; + } + } + // ordino il vettore in senso crescente + sort( vU.begin(), vU.end(), less()) ; + // calcolo il vettore delle lunghezze di ogni parte di curva + DBLVECTOR vLen ; + for ( const auto& dU : vU) { + double dULen ; + pCompo1->GetLengthAtParam( dU, dULen) ; + vLen.push_back( dULen) ; + } + // se ultima parte molto piccola, la elimino + while ( ! vU.empty() && ( dLen - vLen.back()) < 2 * EPS_SMALL) { + vU.pop_back() ; + vLen.pop_back() ; + } + // eseguo la divisione + double dUPrev = 0 ; + double dLenPrev = 0 ; + for ( int i = 0 ; i < int( vU.size()) ; ++ i) { + // se lunghezza della curva risulta piccola, salto + if ( ( vLen[i] - dLenPrev) < 2 * EPS_SMALL) + continue ; + // copio la curva + PtrOwner pCopy( pCompo1->Clone()) ; + if ( IsNull( pCopy)) + return false ; + m_CrvLst.push_back( Release( pCopy)) ; + // trimmo l'originale + pCompo1->TrimStartEndAtParam( dUPrev, vU[i]) ; + // la copia diventa il nuovo corrente + pCompo1 = GetBasicCurveComposite( m_CrvLst.back()) ; + dUPrev = vU[i] ; + dLenPrev = vLen[i] ; + } + // se fatta almeno una suddivisione + bool bFirstLastSame = false ; + if ( dUPrev > EPS_PARAM) { + // trimmo l'ultima parte + pCompo1->TrimStartAtParam( dUPrev) ; + // rilevo le curve chiuse con due parti di una stessa curva all'inizio e alla fine + if ( bClosed && vU[0] > EPS_PARAM && vLen[0] >= 2 * EPS_SMALL) + bFirstLastSame = true ; + } + + // sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi + if ( ! bClosed) { + // ciconferenza sull'estremità iniziale + Point3d ptStart ; ccCopy.GetStartPoint( ptStart) ; + PtrOwner pCircS( CreateBasicCurveArc()) ; + if ( IsNull( pCircS) || ! pCircS->Set( ptStart, Z_AX, abs( dDist))) + return false ; + // elimino le parti di offset interne a questa circonferenza + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + // recupero la curva e il suo dominio + ICurve* pCrv = *iIter ; + double dStart, dEnd ; + if ( ! pCrv->GetDomain( dStart, dEnd)) + return false ; + // determino gli intervalli da conservare (inizializzo come tutta la curva per poi rimuovere la parte finale) + Intervals inOk( EPS_PARAM) ; + inOk.Set( dStart, dEnd) ; + IntersCurveCurve ccInt( *pCrv, *pCircS) ; + CRVCVECTOR ccPart ; + if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart)) + return false ; + for ( auto& ccOne : ccPart) { + switch ( ccOne.nClass) { + case CRVC_IN : + // intervallo standard + if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) + inOk.Subtract( ccOne.dParS, ccOne.dParE) ; + // intervallo che attraversa punto di chiusura della curva + else { + inOk.Subtract( ccOne.dParS, dEnd) ; + inOk.Subtract( dStart, ccOne.dParE) ; } + break ; + case CRVC_NULL : + return false ; } } - // altrimenti salvo in lista - else - CrvLst.push_back( Release( pCrv)) ; - // passo alla curva successiva - pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ; + // eseguo trim (solo della parte iniziale) + double dMin, dMax ; + if ( inOk.GetLast( dMin, dMax)) { + if ( dMin > dStart + 100 * EPS_PARAM) + pCrv->TrimStartAtParam( dMin) ; + } + else { + delete pCrv ; + iIter = m_CrvLst.erase( iIter) ; + continue ; + } + // passo alla successiva + ++ iIter ; } - // rimetto le curve nella composita - for ( auto pCrv : CrvLst) { - pCrvCo->AddCurve( pCrv) ; + // circonferenza sull'estremità finale + Point3d ptEnd ; ccCopy.GetEndPoint( ptEnd) ; + PtrOwner pCircE( CreateBasicCurveArc()) ; + if ( IsNull( pCircE) || ! pCircE->Set( ptEnd, Z_AX, abs( dDist))) + return false ; + // elimino le parti di offset interna a questa circonferenza + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + // recupero la curva e il suo dominio + ICurve* pCrv = *iIter ; + double dStart, dEnd ; + if ( ! pCrv->GetDomain( dStart, dEnd)) + return false ; + // determino gli intervalli da conservare (inizializzo come tutta la curva per poi poter rimuovere parti) + Intervals inOk( EPS_PARAM) ; + inOk.Set( dStart, dEnd) ; + IntersCurveCurve ccInt( *pCrv, *pCircE) ; + CRVCVECTOR ccPart ; + if ( ! ccInt.GetCurveClassification( 0, EPS_SMALL, ccPart)) + return false ; + for ( auto& ccOne : ccPart) { + switch ( ccOne.nClass) { + case CRVC_IN : + // intervallo standard + if ( ccOne.dParS < ccOne.dParE - EPS_PARAM) + inOk.Subtract( ccOne.dParS, ccOne.dParE) ; + // intervallo che attraversa punto di chiusura della curva + else { + inOk.Subtract( ccOne.dParS, dEnd) ; + inOk.Subtract( dStart, ccOne.dParE) ; + } + break ; + case CRVC_NULL : + return false ; + } + } + // eseguo trim (solo della parte finale) + double dMin, dMax ; + if ( inOk.GetFirst( dMin, dMax)) { + if ( dMax < dEnd - 100 * EPS_PARAM) + pCrv->TrimEndAtParam( dMax) ; + } + else { + delete pCrv ; + iIter = m_CrvLst.erase( iIter) ; + continue ; + } + // passo alla successiva + ++ iIter ; } - // unisco tratti allineati - pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; } + + // settimo passo : elimino le parti che sono troppo vicine al percorso originale + bool bFirstLastDeleted = false ; + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + ICurve* pCrv = *iIter ; + // distanza minima di alcuni punti interni della curva dalla curva originale + if ( GetMinDist( 0.5, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.25, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.75, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.125, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.875, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.0625, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL || + GetMinDist( 0.9375, pCrv, &ccCopy) < abs( dDist) - 5 * EPS_SMALL) { + // se prima e ultima sono la stessa curva e non ancora cancellate e prima da cancellare + if ( bFirstLastSame && ! bFirstLastDeleted && iIter == m_CrvLst.begin()) { + bFirstLastDeleted = true ; + // cancello ultima + delete *prev( m_CrvLst.end()) ; + m_CrvLst.pop_back() ; + } + // se prima e ultima sono la stessa curva e non ancora cancellate e ultima da cancellare + if ( bFirstLastSame && ! bFirstLastDeleted && iIter == prev( m_CrvLst.end())) { + bFirstLastDeleted = true ; + // cancello prima + delete *m_CrvLst.begin() ; + m_CrvLst.pop_front() ; + } + // cancello la corrente + delete pCrv ; + iIter = m_CrvLst.erase( iIter) ; + // evito incremento + continue ; + } + // passo alla successiva + ++ iIter ; + } + + // ottavo passo : concateno i percorsi risultanti (senza cambiare verso) + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ;) { + CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; + // recupero punti iniziale e finale della curva + Point3d ptStart, ptEnd ; + pCrvCo->GetStartPoint( ptStart) ; + pCrvCo->GetEndPoint( ptEnd) ; + // ciclo sulle curve successive per verificare se possibile concatenamento + for ( auto iIter2 = next( iIter) ; iIter2 != m_CrvLst.end() ;) { + CurveComposite* pCrvCo2 = GetBasicCurveComposite( *iIter2) ; + // recupero punti iniziale e finale della curva + Point3d ptStart2, ptEnd2 ; + pCrvCo2->GetStartPoint( ptStart2) ; + pCrvCo2->GetEndPoint( ptEnd2) ; + // verifiche di concatenamento + if ( AreSamePointEpsilon( ptEnd, ptStart2, 10 * EPS_SMALL)) { + if ( pCrvCo->AddCurve( pCrvCo2, true, 10 * EPS_SMALL)) + ptEnd = ptEnd2 ; + m_CrvLst.erase( iIter2) ; + iIter2 = next( iIter) ; + } + else if ( AreSamePointEpsilon( ptEnd2, ptStart, 10 * EPS_SMALL)) { + if ( pCrvCo->AddCurve( pCrvCo2, false, 10 * EPS_SMALL)) + ptStart = ptStart2 ; + m_CrvLst.erase( iIter2) ; + iIter2 = next( iIter) ; + } + else + ++ iIter2 ; + } + ++ iIter ; + } + + // nono passo : se con smusso o estensione, sostituisco i fillet con questi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { + CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; + IdentifyFillets( pCrvCo, dDist) ; + AdjustCurveFillets( pCrvCo, dDist, nType) ; + } + } + } + + // -------------------- OFFSET CON VORONOI --------------------------------- + else { + + // recupero Voronoi associato alla curva + Voronoi* voronoiObj ; + if ( bNeedRef || bNeedScale) + voronoiObj = ccCopy.GetVoronoiObject() ; + else + voronoiObj = pCrv->GetVoronoiObject() ; + + if ( voronoiObj == nullptr) + return false ; + + // calcolo offset con Voronoi + ICURVEPOVECTOR vOffs ; + voronoiObj->CalcOffset( vOffs, dDist, nType) ; + for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) + m_CrvLst.emplace_back( Release( vOffs[i])) ; + + // cambio lo start solo se di tipo fillet + bChangeStart = ( nType & ICurve::OFF_CHAMFER) == 0 && ( nType & ICurve::OFF_EXTEND) == 0 ; } // eventuale ripristino del punto iniziale @@ -714,7 +713,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) pCrvCo->ChangeStartPoint(dPar) ; } } - } + } // riporto il risultato nel riferimento originale if ( bNeedScale) { @@ -1146,107 +1145,4 @@ GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) return dMinDist ; } -//---------------------------------------------------------------------------- -bool -IsFillet( ICurve* pCrv, double dDist) -{ - // deve essere un arco - if ( pCrv->GetType() != CRV_ARC) - return false ; - CurveArc* pArc = GetBasicCurveArc( pCrv) ; - // deve avere raggio uguale alla distanza di offset - if ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL) - return false ; - // deve essere CCW se offset a destra e CW se offset a sinistra - return ( pArc->GetAngCenter() * dDist > 0) ; -} -//---------------------------------------------------------------------------- -bool -ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux) -{ - // la curva deve essere un arco - CurveArc* pArc = GetBasicCurveArc( pCrv) ; - if ( pArc == nullptr) - return false ; - - // angolo al centro dell'arco - double dAngDeg = pArc->GetAngCenter() ; - - // elimino dal tipo le parti estranee all'angolo esterno - nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ; - - // se l'angolo esterno supera il retto, offset extend diventa offset chamfer - if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL) - nType = ICurve::OFF_CHAMFER ; - - // se angolo esterno molto piccolo, semplifico tutto - const double SMALL_EXT_ANG = 1.0 ; - bool bAngSmall = ( abs( dAngDeg) < SMALL_EXT_ANG) ; - if ( bAngSmall) - nType = ICurve::OFF_EXTEND ; - - switch ( nType) { - case ICurve::OFF_CHAMFER : - { - // lunghezza aggiuntiva in tangenza - double dLen = abs( dDist) * tan( abs( dAngDeg) / 4 * DEGTORAD) ; - // punti di costruzione smusso - Point3d ptP1, ptP1a, ptP2a, ptP2 ; - if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) - return false ; - Vector3d vtDir1, vtDir2 ; - if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) - return false ; - ptP1a = ptP1 + vtDir1 * dLen ; - ptP2a = ptP2 - vtDir2 * dLen ; - // aggiungo una nuova linea - PtrOwner pLine1( CreateBasicCurveLine()) ; - if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptP1a)) - return false ; - if ( ! ccAux.AddCurve( Release( pLine1))) - return false ; - // tratto intermedio - PtrOwner pLine2( CreateBasicCurveLine()) ; - if ( IsNull( pLine2) || ! pLine2->Set( ptP1a, ptP2a)) - return false ; - if ( ! ccAux.AddCurve( Release( pLine2))) - return false ; - // aggiungo una nuova linea - PtrOwner pLine3( CreateBasicCurveLine()) ; - if ( IsNull( pLine3) || ! pLine3->Set( ptP2a, ptP2)) - return false ; - if ( ! ccAux.AddCurve( Release( pLine3))) - return false ; - return true ; - } - break ; - case ICurve::OFF_EXTEND : - { - // lunghezza aggiuntiva in tangenza - double dLen = abs( dDist) * tan( abs( dAngDeg) / 2 * DEGTORAD) ; - // punti di costruzione estensione - Point3d ptP1, ptPc, ptP2 ; - if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2)) - return false ; - Vector3d vtDir1, vtDir2 ; - if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2)) - return false ; - ptPc = ptP1 + vtDir1 * dLen ; - // aggiungo una nuova linea - PtrOwner pLine1( CreateBasicCurveLine()) ; - if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptPc)) - return false ; - if ( ! ccAux.AddCurve( Release( pLine1))) - return false ; - // aggiungo una nuova linea - PtrOwner pLine2( CreateBasicCurveLine()) ; - if ( IsNull( pLine2) || ! pLine2->Set( ptPc, ptP2)) - return false ; - if ( ! ccAux.AddCurve( Release( pLine2))) - return false ; - return true ; - } - } - return false ; -} diff --git a/PolyLine.cpp b/PolyLine.cpp index d10bed7..85242fc 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -28,7 +28,7 @@ using namespace std ; //---------------------------------------------------------------------------- PolyLine::PolyLine( void) - : m_nRejected( 0), m_iter( m_lUPoints.end()), m_nTempProp{0,0} + : m_nRejected( 0), m_nTempProp{0,0}, m_iter( m_lUPoints.end()) { } diff --git a/SfrCreate.cpp b/SfrCreate.cpp index 00392cf..58bac09 100644 --- a/SfrCreate.cpp +++ b/SfrCreate.cpp @@ -114,7 +114,7 @@ GetSurfFlatRegionDisk( double dRadius) //------------------------------------------------------------------------------- ISurfFlatRegion* -GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids) +GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, bool bSquareMids, bool bUseVoronoi) { // mi impossesso della curva PtrOwner pCurve( pCrv) ; @@ -124,200 +124,219 @@ GetSurfFlatRegionFromFatCurve( ICurve* pCrv, double dRadius, bool bSquareEnds, b Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; if ( vtExtr.IsSmall()) vtExtr = Z_AX ; - PtrOwner pCompo1 ; - if ( ! pCompo1.Set( ConvertCurveToBasicComposite( Release( pCurve)))) - return nullptr ; - pCompo1->SetExtrusion( vtExtr) ; - // se distanza tra gli estremi minore di due volte il raggio la chiudo, purchè curva abbastanza lunga - Point3d ptStart, ptEnd, ptMid ; - Vector3d vtStart, vtEnd ; - pCompo1->GetStartPoint( ptStart) ; - pCompo1->GetStartDir( vtStart) ; - pCompo1->GetEndPoint( ptEnd) ; - pCompo1->GetEndDir( vtEnd) ; - pCompo1->GetMidPoint( ptMid) ; - if ( AreSamePointEpsilon( ptStart, ptEnd, 2 * dRadius) && Dist( ptStart, ptMid) > 2 * dRadius && Dist( ptEnd, ptMid) > 2 * dRadius) { - if ( AreSamePointEpsilon( ptStart, ptEnd, max( 0.1 * dRadius, 10 * EPS_SMALL))) { - Point3d ptNew = Media( ptStart, ptEnd) ; - pCompo1->ModifyStart( ptNew) ; - pCompo1->ModifyEnd( ptNew) ; - } - else { - // piano della curva - Frame3d frLoc ; - if ( ! AreSameVectorApprox( vtExtr, Z_AX)) - frLoc.Set( ptStart, vtExtr) ; - // costruisco il biarco nel piano della curva - ptStart.ToLoc( frLoc) ; - ptEnd.ToLoc( frLoc) ; - Vector3d vtELoc( vtEnd) ; vtELoc.ToLoc( frLoc) ; - Vector3d vtSLoc( vtStart) ; vtSLoc.ToLoc( frLoc) ; - double dAngEnd ; vtELoc.ToSpherical( nullptr, nullptr, &dAngEnd) ; - double dAngStart ; vtSLoc.ToSpherical( nullptr, nullptr, &dAngStart) ; - PtrOwner pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ; - // aggiungo il biarco - if ( ! IsNull( pClose)) { - // porto il biarco in globale - pClose->ToGlob( frLoc) ; - pCompo1->AddCurve( Release( pClose)) ; - } - else - pCompo1->Close() ; - } - } - // tipo di offset - int nOffsType = ( bSquareMids ? ICurve::OFF_EXTEND : ICurve::OFF_FILLET) ; - // se curva chiusa - if ( pCompo1->IsClosed()) { - // fondo le curve allineate - pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ; - // ne faccio una copia e la inverto - PtrOwner pCompo2( pCompo1->Clone()) ; - if ( IsNull( pCompo2) || ! pCompo2->Invert()) - return nullptr ; - // per creare la regione - SurfFlatRegionByContours SfrCntr( false, false) ; - // offset della prima curva a destra del raggio - OffsetCurve OffsCrv1 ; - if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType)) - return nullptr ; - ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ; - while ( pOffs1 != nullptr) { - SfrCntr.AddCurve( pOffs1) ; - pOffs1 = OffsCrv1.GetLongerCurve() ; - } - // offset della seconda curva a destra del raggio (è invertita rispetto alla precedente) - OffsetCurve OffsCrv2 ; - if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType)) + // ----------------- CALCOLO STANDARD -------------------------------- + if ( ! bUseVoronoi) { + PtrOwner pCompo1 ; + if ( ! pCompo1.Set( ConvertCurveToBasicComposite( Release( pCurve)))) return nullptr ; - ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ; - while ( pOffs2 != nullptr) { - SfrCntr.AddCurve( pOffs2) ; - pOffs2 = OffsCrv2.GetLongerCurve() ; + pCompo1->SetExtrusion( vtExtr) ; + // se distanza tra gli estremi minore di due volte il raggio la chiudo, purchè curva abbastanza lunga + Point3d ptStart, ptEnd, ptMid ; + Vector3d vtStart, vtEnd ; + pCompo1->GetStartPoint( ptStart) ; + pCompo1->GetStartDir( vtStart) ; + pCompo1->GetEndPoint( ptEnd) ; + pCompo1->GetEndDir( vtEnd) ; + pCompo1->GetMidPoint( ptMid) ; + if ( AreSamePointEpsilon( ptStart, ptEnd, 2 * dRadius) && Dist( ptStart, ptMid) > 2 * dRadius && Dist( ptEnd, ptMid) > 2 * dRadius) { + if ( AreSamePointEpsilon( ptStart, ptEnd, max( 0.1 * dRadius, 10 * EPS_SMALL))) { + Point3d ptNew = Media( ptStart, ptEnd) ; + pCompo1->ModifyStart( ptNew) ; + pCompo1->ModifyEnd( ptNew) ; + } + else { + // piano della curva + Frame3d frLoc ; + if ( ! AreSameVectorApprox( vtExtr, Z_AX)) + frLoc.Set( ptStart, vtExtr) ; + // costruisco il biarco nel piano della curva + ptStart.ToLoc( frLoc) ; + ptEnd.ToLoc( frLoc) ; + Vector3d vtELoc( vtEnd) ; vtELoc.ToLoc( frLoc) ; + Vector3d vtSLoc( vtStart) ; vtSLoc.ToLoc( frLoc) ; + double dAngEnd ; vtELoc.ToSpherical( nullptr, nullptr, &dAngEnd) ; + double dAngStart ; vtSLoc.ToSpherical( nullptr, nullptr, &dAngStart) ; + PtrOwner pClose( GetBiArc( ptEnd, dAngEnd, ptStart, dAngStart, 0.5)) ; + // aggiungo il biarco + if ( ! IsNull( pClose)) { + // porto il biarco in globale + pClose->ToGlob( frLoc) ; + pCompo1->AddCurve( Release( pClose)) ; + } + else + pCompo1->Close() ; + } } - - // creo la regione - return SfrCntr.GetSurf() ; - } - // altrimenti - else { - // se richiesti estremi squadrati, la allungo del raggio alle due estremità - if ( bSquareEnds) { - pCompo1->ExtendStartByLen( dRadius) ; - pCompo1->ExtendEndByLen( dRadius) ; - } - // fondo le curve allineate - pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ; - // ne faccio una copia e la inverto - PtrOwner pCompo2( pCompo1->Clone()) ; - if ( IsNull( pCompo2) || ! pCompo2->Invert()) - return nullptr ; - - // creo la regione - SurfFlatRegionByContours SfrCntr( false, false) ; - - // offset della prima curva a destra del raggio - OffsetCurve OffsCrv1 ; - if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType)) - return nullptr ; - ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ; - if ( pOffs1 == nullptr) - return nullptr ; - pCompo1->Clear() ; - while ( pOffs1 != nullptr) { - if ( pOffs1->IsClosed()) + // tipo di offset + int nOffsType = ( bSquareMids ? ICurve::OFF_EXTEND : ICurve::OFF_FILLET) ; + // se curva chiusa + if ( pCompo1->IsClosed()) { + // fondo le curve allineate + pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ; + // ne faccio una copia e la inverto + PtrOwner pCompo2( pCompo1->Clone()) ; + if ( IsNull( pCompo2) || ! pCompo2->Invert()) + return nullptr ; + // per creare la regione + SurfFlatRegionByContours SfrCntr( false, false) ; + // offset della prima curva a destra del raggio + OffsetCurve OffsCrv1 ; + if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType)) + return nullptr ; + ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ; + while ( pOffs1 != nullptr) { SfrCntr.AddCurve( pOffs1) ; - else - pCompo1->AddCurve( pOffs1) ; - pOffs1 = OffsCrv1.GetLongerCurve() ; - } - - // offset della seconda curva a destra del raggio - OffsetCurve OffsCrv2 ; - if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType)) - return nullptr ; - ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ; - if ( pOffs2 == nullptr) - return nullptr ; - pCompo2->Clear() ; - while ( pOffs2 != nullptr) { - if ( pOffs2->IsClosed()) + pOffs1 = OffsCrv1.GetLongerCurve() ; + } + + // offset della seconda curva a destra del raggio (è invertita rispetto alla precedente) + OffsetCurve OffsCrv2 ; + if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType)) + return nullptr ; + ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ; + while ( pOffs2 != nullptr) { SfrCntr.AddCurve( pOffs2) ; - else - pCompo2->AddCurve( pOffs2) ; - pOffs2 = OffsCrv2.GetLongerCurve() ; + pOffs2 = OffsCrv2.GetLongerCurve() ; + } + + // creo la regione + return SfrCntr.GetSurf() ; } - - // se estremi squadrati - if ( bSquareEnds) { - // aggiungo alla prima curva una linea che la unisca alla seconda - PtrOwner pLine( CreateBasicCurveLine()) ; - Point3d ptEnd1, ptStart2 ; - if ( IsNull( pLine) || - ! pCompo1->GetEndPoint( ptEnd1) || - ! pCompo2->GetStartPoint( ptStart2) || - ! pLine->Set( ptEnd1, ptStart2) || - ! pCompo1->AddCurve( Release( pLine))) - return nullptr ; - // unisco le due curve composite e le chiudo - if ( ! pCompo1->AddCurve( Release( pCompo2)) || ! pCompo1->Close()) - return nullptr ; - } - // altrimenti estremi arrotondati + // altrimenti else { - // aggiungo alla prima curva un arco che la unisca alla seconda - PtrOwner pArc1( CreateBasicCurveArc()) ; - Point3d ptEnd1, ptStart2 ; - Vector3d vtEnd1, vtStart2 ; - if ( IsNull( pArc1) || - ! pCompo1->GetEndPoint( ptEnd1) || - ! pCompo1->GetEndDir( vtEnd1) || - ! pCompo2->GetStartPoint( ptStart2) || - ! pCompo2->GetStartDir( vtStart2)) + // se richiesti estremi squadrati, la allungo del raggio alle due estremità + if ( bSquareEnds) { + pCompo1->ExtendStartByLen( dRadius) ; + pCompo1->ExtendEndByLen( dRadius) ; + } + // fondo le curve allineate + pCompo1->MergeCurves( LIN_TOL_FINE, ANG_TOL_STD_DEG) ; + // ne faccio una copia e la inverto + PtrOwner pCompo2( pCompo1->Clone()) ; + if ( IsNull( pCompo2) || ! pCompo2->Invert()) return nullptr ; - // verifico se arco tangente alla prima o alla seconda curva - if ( AreSameVectorApprox( vtEnd1, vtEnd)) { - if ( ! pArc1->Set2PVN( ptEnd1, ptStart2, vtEnd1, vtExtr) || - ! pCompo1->AddCurve( Release( pArc1))) + + // creo la regione + SurfFlatRegionByContours SfrCntr( false, false) ; + + // offset della prima curva a destra del raggio + OffsetCurve OffsCrv1 ; + if ( ! OffsCrv1.Make( pCompo1, dRadius, nOffsType)) + return nullptr ; + ICurve* pOffs1 = OffsCrv1.GetLongerCurve() ; + if ( pOffs1 == nullptr) + return nullptr ; + pCompo1->Clear() ; + while ( pOffs1 != nullptr) { + if ( pOffs1->IsClosed()) + SfrCntr.AddCurve( pOffs1) ; + else + pCompo1->AddCurve( pOffs1) ; + pOffs1 = OffsCrv1.GetLongerCurve() ; + } + + // offset della seconda curva a destra del raggio + OffsetCurve OffsCrv2 ; + if ( ! OffsCrv2.Make( pCompo2, dRadius, nOffsType)) + return nullptr ; + ICurve* pOffs2 = OffsCrv2.GetLongerCurve() ; + if ( pOffs2 == nullptr) + return nullptr ; + pCompo2->Clear() ; + while ( pOffs2 != nullptr) { + if ( pOffs2->IsClosed()) + SfrCntr.AddCurve( pOffs2) ; + else + pCompo2->AddCurve( pOffs2) ; + pOffs2 = OffsCrv2.GetLongerCurve() ; + } + + // se estremi squadrati + if ( bSquareEnds) { + // aggiungo alla prima curva una linea che la unisca alla seconda + PtrOwner pLine( CreateBasicCurveLine()) ; + Point3d ptEnd1, ptStart2 ; + if ( IsNull( pLine) || + ! pCompo1->GetEndPoint( ptEnd1) || + ! pCompo2->GetStartPoint( ptStart2) || + ! pLine->Set( ptEnd1, ptStart2) || + ! pCompo1->AddCurve( Release( pLine))) + return nullptr ; + // unisco le due curve composite e le chiudo + if ( ! pCompo1->AddCurve( Release( pCompo2)) || ! pCompo1->Close()) return nullptr ; } + // altrimenti estremi arrotondati else { - if ( ! pArc1->Set2PVN( ptStart2, ptEnd1, -vtStart2, vtExtr) || - ! pArc1->Invert() || - ! pCompo1->AddCurve( Release( pArc1))) + // aggiungo alla prima curva un arco che la unisca alla seconda + PtrOwner pArc1( CreateBasicCurveArc()) ; + Point3d ptEnd1, ptStart2 ; + Vector3d vtEnd1, vtStart2 ; + if ( IsNull( pArc1) || + ! pCompo1->GetEndPoint( ptEnd1) || + ! pCompo1->GetEndDir( vtEnd1) || + ! pCompo2->GetStartPoint( ptStart2) || + ! pCompo2->GetStartDir( vtStart2)) + return nullptr ; + // verifico se arco tangente alla prima o alla seconda curva + if ( AreSameVectorApprox( vtEnd1, vtEnd)) { + if ( ! pArc1->Set2PVN( ptEnd1, ptStart2, vtEnd1, vtExtr) || + ! pCompo1->AddCurve( Release( pArc1))) + return nullptr ; + } + else { + if ( ! pArc1->Set2PVN( ptStart2, ptEnd1, -vtStart2, vtExtr) || + ! pArc1->Invert() || + ! pCompo1->AddCurve( Release( pArc1))) + return nullptr ; + } + // aggiungo alla seconda curva un arco che la unisca alla prima + PtrOwner pArc2( CreateBasicCurveArc()) ; + Point3d ptEnd2, ptStart1 ; + Vector3d vtEnd2, vtStart1 ; + if ( IsNull( pArc2) || + ! pCompo2->GetEndPoint( ptEnd2) || + ! pCompo2->GetEndDir( vtEnd2) || + ! pCompo1->GetStartPoint( ptStart1) || + ! pCompo1->GetStartDir( vtStart1)) + return nullptr ; + // verifico se arco tangente alla seconda o alla prima curva + if ( AreOppositeVectorApprox( vtEnd2, vtStart)) { + if ( ! pArc2->Set2PVN( ptEnd2, ptStart1, vtEnd2, vtExtr) || + ! pCompo2->AddCurve( Release( pArc2))) + return nullptr ; + } + else { + if ( ! pArc2->Set2PVN( ptStart1, ptEnd2, -vtStart1, vtExtr) || + ! pArc2->Invert() || + ! pCompo2->AddCurve( Release( pArc2))) + return nullptr ; + } + // unisco le due curve composite + if ( ! pCompo1->AddCurve( Release( pCompo2))) return nullptr ; } - // aggiungo alla seconda curva un arco che la unisca alla prima - PtrOwner pArc2( CreateBasicCurveArc()) ; - Point3d ptEnd2, ptStart1 ; - Vector3d vtEnd2, vtStart1 ; - if ( IsNull( pArc2) || - ! pCompo2->GetEndPoint( ptEnd2) || - ! pCompo2->GetEndDir( vtEnd2) || - ! pCompo1->GetStartPoint( ptStart1) || - ! pCompo1->GetStartDir( vtStart1)) - return nullptr ; - // verifico se arco tangente alla seconda o alla prima curva - if ( AreOppositeVectorApprox( vtEnd2, vtStart)) { - if ( ! pArc2->Set2PVN( ptEnd2, ptStart1, vtEnd2, vtExtr) || - ! pCompo2->AddCurve( Release( pArc2))) - return nullptr ; - } - else { - if ( ! pArc2->Set2PVN( ptStart1, ptEnd2, -vtStart1, vtExtr) || - ! pArc2->Invert() || - ! pCompo2->AddCurve( Release( pArc2))) - return nullptr ; - } - // unisco le due curve composite - if ( ! pCompo1->AddCurve( Release( pCompo2))) - return nullptr ; + + SfrCntr.AddCurve( Release( pCompo1)) ; + return SfrCntr.GetSurf() ; } - - SfrCntr.AddCurve( Release( pCompo1)) ; - return SfrCntr.GetSurf() ; } + + // ---------------------- CALCOLO CON VORONOI ------------------------------------ + else { + // calcolo la fat curve con Voronoi + ICURVEPOVECTOR vFatCurves ; + if ( ! pCurve->CalcFatCurve( vFatCurves, dRadius, bSquareEnds, bSquareMids)) + return nullptr ; + + // costruisco la superficie a partire dalle curve + SurfFlatRegionByContours SfrCntr( false, false) ; + for ( int i = 0 ; i < ( int)vFatCurves.size() ; i++) + SfrCntr.AddCurve( Release( vFatCurves[i])) ; + + return SfrCntr.GetSurf() ; + } } //---------------------------------------------------------------------------- diff --git a/StmFromCurves.cpp b/StmFromCurves.cpp index 1f47f22..bedd2b6 100644 --- a/StmFromCurves.cpp +++ b/StmFromCurves.cpp @@ -458,7 +458,7 @@ GetSurfTriMeshBeveledRectSwept( double dDimH, double dDimV, double dBevelH, doub double vDist[NUM_OFFS] = { dDimH / 2 - dBevelH, -dDimH / 2 + dBevelH, dDimH / 2, -dDimH / 2} ; future vRes[NUM_OFFS] ; for ( int i = 0 ; i < NUM_OFFS ; ++ i) - vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET) ; + vRes[i] = async( launch::async, &OffsetCurve::Make, &vOffsCrv[i], pGuide, vDist[i], ICurve::OFF_FILLET, false) ; bool bOk = true ; int nFin = 0 ; while ( nFin < NUM_OFFS) { diff --git a/SurfBezier.cpp b/SurfBezier.cpp index e43e74c..7dc3474 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -38,11 +38,8 @@ GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ; //---------------------------------------------------------------------------- SurfBezier::SurfBezier( void) : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_nSpanU(), m_nSpanV(), m_bRat( false), - m_bTrimmed( false), m_pTrimReg( nullptr) + m_bTrimmed( false), m_pTrimReg( nullptr), m_nTempProp{0,0}, m_dTempParam{0.0,0.0} { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; - } //---------------------------------------------------------------------------- @@ -589,6 +586,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc) } m_nTempProp[0] = sbSrc.m_nTempProp[0] ; m_nTempProp[1] = sbSrc.m_nTempProp[1] ; + m_dTempParam[0] = sbSrc.m_dTempParam[0] ; + m_dTempParam[1] = sbSrc.m_dTempParam[1] ; return true ; } diff --git a/SurfBezier.h b/SurfBezier.h index 92e8dea..9f357d1 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -58,6 +58,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ISurf bool IsSimple( void) const override @@ -169,6 +174,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo SurfFlatRegion* m_pTrimReg ; // eventuale regione di trim int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei } ; //----------------------------------------------------------------------------- diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index da62396..60c1e08 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -34,10 +34,8 @@ GEOOBJ_REGISTER( SRF_FLATRGN, NGE_S_FRG, SurfFlatRegion) ; //---------------------------------------------------------------------------- SurfFlatRegion::SurfFlatRegion( void) - : m_pSTM( nullptr), m_nStatus( TO_VERIFY) + : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_pVoronoiObj( nullptr) { - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -60,10 +58,14 @@ SurfFlatRegion::Clear( void) m_nTempProp[0] = 0 ; m_nTempProp[1] = 0 ; + m_dTempParam[0] = 0.0 ; + m_dTempParam[1] = 0.0 ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; ResetAuxSurf() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -193,6 +195,8 @@ SurfFlatRegion::AddSimpleExtLoop( ICurve* pCrv) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -329,6 +333,8 @@ SurfFlatRegion::AddSimpleIntLoop( ICurve* pCrv) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -403,6 +409,8 @@ SurfFlatRegion::CopyFrom( const SurfFlatRegion& sfrSrc) m_vExtInd = sfrSrc.m_vExtInd ; m_nTempProp[0] = sfrSrc.m_nTempProp[0] ; m_nTempProp[1] = sfrSrc.m_nTempProp[1] ; + m_dTempParam[0] = sfrSrc.m_dTempParam[0] ; + m_dTempParam[1] = sfrSrc.m_dTempParam[1] ; m_nStatus = sfrSrc.m_nStatus ; return ( m_nStatus == OK && ! m_vpLoop.empty()) ; } @@ -613,6 +621,8 @@ SurfFlatRegion::Translate( const Vector3d& vtMove) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // traslo il riferimento m_frF.Translate( vtMove) ; return true ; @@ -632,6 +642,8 @@ SurfFlatRegion::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // ruoto il riferimento return m_frF.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; @@ -651,6 +663,8 @@ SurfFlatRegion::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // se scalatura non uniforme, sostituisco eventuali archi con curve di Bezier if ( abs( dCoeffX - dCoeffY) > EPS_SMALL || abs( dCoeffX - dCoeffZ) > EPS_SMALL) { @@ -704,6 +718,8 @@ SurfFlatRegion::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // parziale mirror del riferimento (non può essere completa) Frame3d frTrasf = m_frF ; @@ -752,6 +768,8 @@ SurfFlatRegion::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // se il piano di scorrimento non coincide con XY intrinseco, converto eventuali archi in curve di Bezier if ( ! AreSameOrOppositeVectorExact( m_frF.VersZ(), vtNorm)) { @@ -824,6 +842,8 @@ SurfFlatRegion::ToGlob( const Frame3d& frRef) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // trasformo il riferimento return m_frF.ToGlob( frRef) ; ; @@ -847,6 +867,8 @@ SurfFlatRegion::ToLoc( const Frame3d& frRef) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // trasformo il riferimento return m_frF.ToLoc( frRef) ; ; @@ -870,6 +892,8 @@ SurfFlatRegion::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; // trasformo il riferimento return m_frF.LocToLoc( frOri, frDest) ; ; @@ -1646,4 +1670,67 @@ SurfFlatRegion::GetZigZagInfill( double dStep, bool bStepCorrection, bool bInver } return true ; -} \ No newline at end of file +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::CalcVoronoiObject() const +{ + if ( m_nStatus != OK) + return false ; + + // creo oggetto vroni con la superficie + m_pVoronoiObj = new( std::nothrow) Voronoi( this, false) ; + if ( m_pVoronoiObj == nullptr) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +Voronoi* +SurfFlatRegion::GetVoronoiObject() const +{ + if ( m_nStatus != OK) + return nullptr ; + + // se non è stato calcolato, lo calcolo + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // restituisco Voronoi + return m_pVoronoiObj ; +} + +//---------------------------------------------------------------------------- +void +SurfFlatRegion::ResetVoronoiObject() const +{ + if ( m_pVoronoiObj != nullptr) + delete m_pVoronoiObj ; + m_pVoronoiObj = nullptr ; +} + +//--------------------------------------------------------------------------- +bool +SurfFlatRegion::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) const +{ + // verifico se è stato calcolato + if ( m_pVoronoiObj == nullptr) + if ( ! CalcVoronoiObject()) + return false ; + + return m_pVoronoiObj->CalcVoronoiDiagram( vCrvs, nBound) ; +} + +//---------------------------------------------------------------------------- +bool +SurfFlatRegion::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const +{ + // verifico se è stato calcolato + if ( m_pVoronoiObj == nullptr) + if ( ! CalcVoronoiObject()) + return false ; + + return m_pVoronoiObj->CalcMedialAxis( vCrvs, nSide) ; +} diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index eb29c2d..b88f7cb 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -57,6 +57,11 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ISurf bool IsSimple( void) const override @@ -80,7 +85,8 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW bool Add( const ISurfFlatRegion& Other) override ; bool Subtract( const ISurfFlatRegion& Other) override ; bool Intersect( const ISurfFlatRegion& Other) override ; - bool Offset( double dDist, int nType) override ; + bool Offset( double dDist, int nType, bool bUseVoronoi = false) override ; + ISurfFlatRegion* CreateOffsetSurf( double dDist, int nType, bool bUseVoronoi = false) const override ; bool GetGrossArea( double& dArea) const override ; const Point3d& GetPlanePoint( void) const override { return m_frF.Orig() ; } @@ -96,6 +102,9 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ; int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides bool GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const override ; + Voronoi* GetVoronoiObject( void) const override ; + bool CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound = VORONOI_STD_BOUND) const override ; + bool CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -104,7 +113,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW public : SurfFlatRegion( void) ; - SurfFlatRegion( const SurfFlatRegion& stSrc) : m_pSTM( nullptr) + SurfFlatRegion( const SurfFlatRegion& stSrc) : m_pSTM( nullptr), m_pVoronoiObj( nullptr) { if ( ! CopyFrom( stSrc)) LOG_ERROR( GetEGkLogger(), "SurfFlatRegion : copy constructor error") } SurfFlatRegion& operator =( const SurfFlatRegion& stSrc) @@ -138,7 +147,9 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ; static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ; static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ; - static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ; + static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ; + bool CalcVoronoiObject( void) const ; + void ResetVoronoiObject( void) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -147,7 +158,10 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW Frame3d m_frF ; // riferimento intrinseco PCRV_DEQUE m_vpLoop ; // deque delle curve che formano i loop INTVECTOR m_vExtInd ; // indice dei loop esterni nel precedente vettore - int m_nTempProp[2] ; // vettore proprietà temporanee + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei + mutable Voronoi* m_pVoronoiObj ; // Voronoi + } ; //----------------------------------------------------------------------------- diff --git a/SurfFlatRegionBooleans.cpp b/SurfFlatRegionBooleans.cpp index c2c3bf4..1d70bc0 100644 --- a/SurfFlatRegionBooleans.cpp +++ b/SurfFlatRegionBooleans.cpp @@ -103,6 +103,8 @@ SurfFlatRegion::Add( const ISurfFlatRegion& Other) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -191,6 +193,8 @@ SurfFlatRegion::Subtract( const ISurfFlatRegion& Other) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } @@ -279,6 +283,8 @@ SurfFlatRegion::Intersect( const ISurfFlatRegion& Other) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + // imposto ricalcolo Voronoi + ResetVoronoiObject() ; return true ; } diff --git a/SurfFlatRegionOffset.cpp b/SurfFlatRegionOffset.cpp index 92846c9..9cf40b2 100644 --- a/SurfFlatRegionOffset.cpp +++ b/SurfFlatRegionOffset.cpp @@ -17,111 +17,202 @@ #include "CurveComposite.h" #include "SurfFlatRegion.h" #include "/EgtDev/Include/EGkOffsetCurve.h" +#include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; +//---------------------------------------------------------------------------- +ISurfFlatRegion* +SurfFlatRegion::CreateOffsetSurf( double dDist, int nType, bool bUseVoronoi) const +{ + // restituisce la superficie offsettata senza modificare la superficie corrente. In caso di errore restituisce nullptr + + // recupero il numero dei chunk + int nChunk = GetChunkCount() ; + if ( nChunk == 0) + return nullptr ; + + // se offset nullo, la nuova regione è la copia di quella attuale + if ( abs( dDist) < 10 * EPS_SMALL) + return this->Clone() ; + + // creo una nuova regione + PtrOwner pSfr( CreateBasicSurfFlatRegion()) ; + if ( IsNull( pSfr)) + return nullptr ; + + // -------------------- OFFSET STANDARD ------------------------------------- + if ( ! bUseVoronoi) { + bool bFirstRegion = true ; + // ciclo sui chunk + for ( int i = 0 ; i < nChunk ; ++ i) { + // creo la regione del chunk + PtrOwner pSfrChk( new( nothrow) SurfFlatRegion) ; + if ( IsNull( pSfrChk)) + return nullptr ; + bool bFirstCurve = true ; + // ciclo sui loop di ogni chunk + int nLoop = GetLoopCount( i) ; + for ( int j = 0 ; j < nLoop ; ++ j) { + // recupero il loop + ICurve* pLoop = GetMyLoop( i, j) ; + if ( pLoop == nullptr) + return nullptr ; + // ne eseguo l'offset + OffsetCurve OffsCrv ; + bool bOk = OffsCrv.Make( pLoop, dDist, nType) ; + // recupero le curve di offset + PtrOwner pOffs( OffsCrv.GetLongerCurve()) ; + while ( bOk && ! IsNull( pOffs)) { + if ( pOffs->GetType() == CRV_COMPO) { + CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ; + // assegno proprietà + pOffsCompo->SetTempProp( j, 1) ; + for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k) + pOffsCompo->SetCurveTempProp( k, j, 1) ; + // unisco parti allineate + if ( ! pOffsCompo->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, true)) + return nullptr ; + } + else + pOffs->SetTempProp( j, 1) ; + // se prima curva esterna, è il primo contorno esterno della nuova regione + if ( j == 0 && bFirstCurve) { + if ( ! pSfrChk->AddExtLoop( Release( pOffs))) + return nullptr ; + bFirstCurve = false ; + } + // altrimenti aggiungo o sottraggo la regione della curva alla nuova regione + else if ( ! bFirstCurve) { + // verifico se loop interno o esterno + double dArea ; + if ( ! pOffs->GetAreaXY( dArea)) + return nullptr ; + bool bExtLoop = ( dArea > 0) ; + // se loop interno, inverto la curva + if ( ! bExtLoop) + pOffs->Invert() ; + // creo la regione + PtrOwner pSfr2( new( nothrow) SurfFlatRegion) ; + if ( IsNull( pSfr2) || ! pSfr2->AddExtLoop( Release( pOffs))) + return nullptr ; + // se era loop esterno, lo aggiungo alla nuova regione + if ( bExtLoop) { + if ( ! pSfrChk->Add( *pSfr2)) + return nullptr ; + } + // altrimenti loop interno, lo sottraggo alla nuova regione + else { + if ( ! pSfrChk->Subtract( *pSfr2)) + return nullptr ; + } + } + // passo alla successiva + pOffs.Set( OffsCrv.GetLongerCurve()) ; + } + } + // se regione di chunk valida + if ( ! bFirstCurve) { + // se prima regione di chunk, ne sposto i dati nella nuova regione + if ( bFirstRegion) { + pSfr->m_vExtInd = pSfrChk->m_vExtInd ; + pSfr->m_vpLoop = pSfrChk->m_vpLoop ; + for ( auto& pLoop : pSfrChk->m_vpLoop) + pLoop = nullptr ; + pSfr->m_nStatus = pSfrChk->m_nStatus ; + bFirstRegion = false ; + } + // altrimenti la aggiungo alla nuova regione + else { + if ( ! pSfr->Add( *pSfrChk)) + return nullptr ; + } + } + } + } + + // -------------------- OFFSET CON VORONOI ------------------------------------- + else { + // verifico se oggetto Voronoi della superficie è definito + if ( m_pVoronoiObj == nullptr) + CalcVoronoiObject() ; + + // calcolo offset + ICURVEPOVECTOR vOffs ; + if ( ! m_pVoronoiObj->CalcOffset( vOffs, dDist, nType)) + return nullptr ; + + if ( vOffs.size() > 0) { + BOOLVECTOR vbAddOrSub( vOffs.size(), true) ; + int nFirstId = -1 ; + for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) { + // porto nel frame della flat region + vOffs[i]->ToLoc( m_frF) ; + // calcolo orientamento della curva + double dAreaXY ; + if ( ! vOffs[i]->GetAreaXY( dAreaXY)) + return nullptr ; + vbAddOrSub[i] = ( dAreaXY > SQ_EPS_SMALL) ; + // verifico se è il primo loop esterno + if ( nFirstId == -1 && vbAddOrSub[i]) + nFirstId = i ; + } + + // inizializzo la superficie + if ( nFirstId != -1 && ! pSfr->AddExtLoop( Release( vOffs[nFirstId]))) + return nullptr ; + if ( pSfr->IsValid()) { + + for ( int i = 0 ; i < ( int)vOffs.size() ; i ++) { + // verifico non sia il primo loop esterno + if ( i == nFirstId) + continue ; + // costruisco la superficie associata + PtrOwner pSrfCrv( CreateBasicSurfFlatRegion()) ; + if ( IsNull( pSrfCrv) || ! pSrfCrv->AddExtLoop( Release( vOffs[i]))) + return nullptr ; + if ( ! pSrfCrv->IsValid()) + continue ; + + // aggiungo o sottraggo + if ( vbAddOrSub[i]) { + if ( ! pSfr->Add( *pSrfCrv)) + return nullptr ; + } + else { + pSrfCrv->Invert() ; + if ( ! pSfr->Subtract( *pSrfCrv)) + return nullptr ; + } + } + } + } + } + + return Release( pSfr) ; +} + //---------------------------------------------------------------------------- bool -SurfFlatRegion::Offset( double dDist, int nType) +SurfFlatRegion::Offset( double dDist, int nType, bool bUseVoronoi) { // recupero il numero dei chunk int nChunk = GetChunkCount() ; if ( nChunk == 0) return false ; - // se offset nullo, non devo fare alcunché + + // se offset nullo, non devo fare alcunchè if ( abs( dDist) < 10 * EPS_SMALL) - return true ; - // creo una nuova regione - PtrOwner pSfr( new( nothrow) SurfFlatRegion) ; + return this->Clone() ; + + // calcolo la superficie di offset + ISurfFlatRegion* pSfrOrig = CreateOffsetSurf( dDist, nType, bUseVoronoi) ; + if ( pSfrOrig == nullptr) + return false ; + PtrOwner pSfr( GetBasicSurfFlatRegion( pSfrOrig)) ; if ( IsNull( pSfr)) return false ; - bool bFirstRegion = true ; - // ciclo sui chunk - for ( int i = 0 ; i < nChunk ; ++ i) { - // creo la regione del chunk - PtrOwner pSfrChk( new( nothrow) SurfFlatRegion) ; - if ( IsNull( pSfrChk)) - return false ; - bool bFirstCurve = true ; - // ciclo sui loop di ogni chunk - int nLoop = GetLoopCount( i) ; - for ( int j = 0 ; j < nLoop ; ++ j) { - // recupero il loop - ICurve* pLoop = GetMyLoop( i, j) ; - if ( pLoop == nullptr) - return false ; - // ne eseguo l'offset - OffsetCurve OffsCrv ; - bool bOk = OffsCrv.Make( pLoop, dDist, nType) ; - // recupero le curve di offset - PtrOwner pOffs( OffsCrv.GetLongerCurve()) ; - while ( bOk && ! IsNull( pOffs)) { - if ( pOffs->GetType() == CRV_COMPO) { - CurveComposite* pOffsCompo = GetBasicCurveComposite( pOffs) ; - // assegno proprietà - pOffsCompo->SetTempProp( j, 1) ; - for ( int k = 0 ; k < pOffsCompo->GetCurveCount() ; ++k) - pOffsCompo->SetCurveTempProp( k, j, 1) ; - // unisco parti allineate - if ( ! pOffsCompo->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, true)) - return false ; - } - else - pOffs->SetTempProp( j, 1) ; - // se prima curva esterna, è il primo contorno esterno della nuova regione - if ( j == 0 && bFirstCurve) { - if ( ! pSfrChk->AddExtLoop( Release( pOffs))) - return false ; - bFirstCurve = false ; - } - // altrimenti aggiungo o sottraggo la regione della curva alla nuova regione - else if ( ! bFirstCurve) { - // verifico se loop interno o esterno - double dArea ; - if ( ! pOffs->GetAreaXY( dArea)) - return false ; - bool bExtLoop = ( dArea > 0) ; - // se loop interno, inverto la curva - if ( ! bExtLoop) - pOffs->Invert() ; - // creo la regione - PtrOwner pSfr2( new( nothrow) SurfFlatRegion) ; - if ( IsNull( pSfr2) || ! pSfr2->AddExtLoop( Release( pOffs))) - return false ; - // se era loop esterno, lo aggiungo alla nuova regione - if ( bExtLoop) { - if ( ! pSfrChk->Add( *pSfr2)) - return false ; - } - // altrimenti loop interno, lo sottraggo alla nuova regione - else { - if ( ! pSfrChk->Subtract( *pSfr2)) - return false ; - } - } - // passo alla successiva - pOffs.Set( OffsCrv.GetLongerCurve()) ; - } - } - // se regione di chunk valida - if ( ! bFirstCurve) { - // se prima regione di chunk, ne sposto i dati nella nuova regione - if ( bFirstRegion) { - pSfr->m_vExtInd = pSfrChk->m_vExtInd ; - pSfr->m_vpLoop = pSfrChk->m_vpLoop ; - for ( auto& pLoop : pSfrChk->m_vpLoop) - pLoop = nullptr ; - pSfr->m_nStatus = pSfrChk->m_nStatus ; - bFirstRegion = false ; - } - // altrimenti la aggiungo alla nuova regione - else { - if ( ! pSfr->Add( *pSfrChk)) - return false ; - } - } - } // pulisco la superficie corrente for ( auto& pLoop : m_vpLoop) @@ -138,5 +229,6 @@ SurfFlatRegion::Offset( double dDist, int nType) // imposto ricalcolo della grafica ResetAuxSurf() ; m_OGrMgr.Reset() ; + ResetVoronoiObject() ; return true ; -} \ No newline at end of file +} diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 71aeb41..d0b7568 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -42,12 +42,10 @@ GEOOBJ_REGISTER( SRF_TRIMESH, NGE_S_TRM, SurfTriMesh) ; SurfTriMesh::SurfTriMesh( void) : m_nStatus( TO_VERIFY), m_dLinTol( STM_STD_LIN_TOL), m_dBoundaryAng( STM_STD_BOUNDARY_ANG), m_dSmoothAng( STM_STD_SMOOTH_ANG), m_bOriented( false), m_bClosed( false), m_bFaceted( false), - m_nTimeStamp( 0), m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr) + m_nTimeStamp( 0), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_nMaxTFlag( 0), m_nParts( -1), m_pHGrd3d( nullptr) { m_dCosBndAng = cos( m_dBoundaryAng * DEGTORAD) ; m_dCosSmAng = cos( m_dSmoothAng * DEGTORAD) ; - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; } //---------------------------------------------------------------------------- @@ -1297,6 +1295,8 @@ SurfTriMesh::CopyFrom( const SurfTriMesh& stmSrc) m_nTempProp[1] = stmSrc.m_nTempProp[1] ; m_nMaxTFlag = stmSrc.m_nMaxTFlag ; m_nParts = stmSrc.m_nParts ; + m_dTempParam[0] = stmSrc.m_dTempParam[0] ; + m_dTempParam[1] = stmSrc.m_dTempParam[1] ; return true ; } diff --git a/SurfTriMesh.h b/SurfTriMesh.h index e972ad2..116c966 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -195,6 +195,11 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // ISurf bool IsSimple( void) const override @@ -399,14 +404,15 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW double m_dCosBndAng ; // coseno dell'angolo limite per considerare un lato un contorno double m_dSmoothAng ; // angolo limite per mediare le normali (in gradi) double m_dCosSmAng ; // coseno dell'angolo limite per mediare le normali - bool m_bOriented ; // la superficie � orientata consistentemente in tutte le sue parti + bool m_bOriented ; // la superficie è orientata consistentemente in tutte le sue parti bool m_bClosed ; // la superficie racchiude un volume - bool m_bFaceted ; // flag di validit� della sfaccettatura + bool m_bFaceted ; // flag di validità della sfaccettatura VERTVECTOR m_vVert ; // vettore dei vertici TRIAVECTOR m_vTria ; // vettore dei triangoli INTVECTOR m_vFacet ; // vettore delle sfaccettature mutable int m_nTimeStamp ; // orologio locale - int m_nTempProp[2] ; // vettore propriet� temporanee + int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei int m_nMaxTFlag ; // massimo valore dei TFlag dei triangoli mutable int m_nParts ; // numero di parti connesse (-1 se da calcolare) mutable HashGrids3d* m_pHGrd3d ; // Hash Grid 3d nel suo riferimento diff --git a/VolZmap.cpp b/VolZmap.cpp index 481095d..eb6e225 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -34,7 +34,7 @@ GEOOBJ_REGISTER( VOL_ZMAP, NGE_V_ZMP, VolZmap) ; //---------------------------------------------------------------------------- VolZmap::VolZmap(void) - : m_nStatus( TO_VERIFY), m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK), + : m_nStatus( TO_VERIFY), m_nTempProp{0,0}, m_dTempParam{0.0,0.0}, m_dStep( 10.0), m_nMapNum( 0), m_nShape( GENERIC), m_nVoxNumPerBlock( N_VOXBLOCK), m_nDexVoxRatio( 1), m_nNumBlock( 0), m_nConnectedCompoCount( 0), m_nCurrTool( -1), m_dToolLinTol( LIN_TOL_STD), m_dToolAngTolDeg( ANG_TOL_APPROX_DEG) { @@ -46,8 +46,6 @@ VolZmap::VolZmap(void) m_dMaxZ[i] = 0 ; m_nFracLin[i] = 0 ; } - m_nTempProp[0] = 0 ; - m_nTempProp[1] = 0 ; m_vTool.resize( 1) ; m_nCurrTool = 0 ; } @@ -78,6 +76,8 @@ VolZmap::Clear( void) m_dStep = EPS_SMALL ; m_nTempProp[0] = 0 ; m_nTempProp[1] = 0 ; + m_dTempParam[0] = 0.0 ; + m_dTempParam[1] = 0.0 ; m_vTool.resize( 1) ; m_nCurrTool = 0 ; m_dToolLinTol = LIN_TOL_STD ; @@ -148,6 +148,8 @@ VolZmap::CopyFrom( const VolZmap& vzmSrc) m_nStatus = vzmSrc.m_nStatus ; m_nTempProp[0] = vzmSrc.m_nTempProp[0] ; m_nTempProp[1] = vzmSrc.m_nTempProp[1] ; + m_dTempParam[0] = vzmSrc.m_dTempParam[0] ; + m_dTempParam[1] = vzmSrc.m_dTempParam[1] ; // dimensiono membri legati ai blocchi m_BlockToUpdate = vzmSrc.m_BlockToUpdate ; @@ -208,7 +210,7 @@ VolZmap::Dump( string& sOut, bool bMM, const char* szNewLine) const } sOut += szNewLine ; // passo - sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 6) + szNewLine ; + sOut += "Step=" + ToString( GetInUiUnits( m_dStep, bMM), 6) + szNewLine ; // dimensioni if ( m_nMapNum == 1) sOut += "Dim=" + ToString( m_nDim[0]) + diff --git a/VolZmap.h b/VolZmap.h index 8361860..7719ab7 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -65,6 +65,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW m_nTempProp[nPropInd] = nProp ; } int GetTempProp( int nPropInd = 0) const override { return (( nPropInd >= 0 && nPropInd < 2) ? m_nTempProp[nPropInd] : 0) ; } + void SetTempParam( double dParam, int nParamInd = 0) override + { if ( nParamInd >= 0 && nParamInd < 2) + m_dTempParam[nParamInd] = dParam ; } + double GetTempParam( int nParamInd = 0) const override + { return (( nParamInd >= 0 && nParamInd < 2) ? m_dTempParam[nParamInd] : 0.0) ; } public : // IVolZmap bool CopyFrom( const IGeoObj* pGObjSrc) override ; @@ -410,6 +415,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Status m_nStatus ; // stato int m_nTempProp[2] ; // vettore proprietà temporanee + double m_dTempParam[2] ; // vettore parametri temporanei double m_dStep ; // passo delle griglie int m_nMapNum ; // numero di griglie ( 1 o 3) Frame3d m_MapFrame ; // riferimento intrinseco dello Zmap diff --git a/Voronoi.cpp b/Voronoi.cpp new file mode 100644 index 0000000..7f6e93e --- /dev/null +++ b/Voronoi.cpp @@ -0,0 +1,868 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2023 +//---------------------------------------------------------------------------- +// File : Voronoi.cpp Data : 23.11.23 Versione : 2.5k5 +// Contenuto : Classe per Voronoi con libreria VRONI. +// +// +// +// Modifiche : 23.11.23 SP Creazione modulo. + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "GeoConst.h" +#include "CurveComposite.h" +#include "CurveArc.h" +#include "CurveLine.h" +#include "CurveBezier.h" +#include "SurfFlatRegion.h" +#include "OffsetAux.h" +#include "/EgtDev/Include/EGkVoronoi.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +Voronoi::Voronoi( const ICurve* pCrv, bool bAllowAdd) + : m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true) +{ + // tento di aggiungere la curva + if ( ! AddCurve( pCrv)) + Clear() ; + m_bAllowAdd = bAllowAdd ; +} + +//---------------------------------------------------------------------------- +Voronoi::Voronoi( const ISurfFlatRegion* pSfr, bool bAllowAdd) + : m_vroni( nullptr), m_nBound( VORONOI_STD_BOUND), m_bVDComputed( false), m_bAllowAdd( true) +{ + // tento di aggiungere la superficie + if ( ! AddSurfFlatRegion( pSfr)) + Clear() ; + m_bAllowAdd = bAllowAdd ; +} + +//---------------------------------------------------------------------------- +Voronoi::~Voronoi( void) +{ + Clear() ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::Clear( void) +{ + // pulizia oggetto vroni + if ( m_vroni != nullptr) + delete m_vroni ; + m_vroni = nullptr ; + + // ciclo di pulizia delle curve associate + for ( auto pCrv : m_vpCrvs) + delete pCrv ; + m_vpCrvs.clear() ; + + m_nBound = VORONOI_STD_BOUND ; + m_bVDComputed = false ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddCurve( const ICurve* pCrv) +{ + if ( ! m_bAllowAdd) + return false ; + + if ( pCrv == nullptr) + return false ; + + // verifico se è una linea + int nType = pCrv->GetType() ; + bool bIsLine = ( nType == CRV_LINE) ; + if ( nType == CRV_COMPO) { + const CurveComposite* pCompo = GetBasicCurveComposite( pCrv) ; + Point3d ptStart, ptEnd ; + if ( pCompo != nullptr && pCompo->IsALine( 10 * EPS_SMALL, ptStart, ptEnd)) + bIsLine = true ; + } + + // verifico sia piana e trovo piano su cui giace + Plane3d plPlane ; + if ( bIsLine) { + // linea è sicuramente piana. Scelgo piano definito dall'estrusione ( se definita) + Point3d ptS ; pCrv->GetStartPoint( ptS) ; + Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ; + if ( ! vtExtr.IsSmall()) + plPlane.Set( ptS, vtExtr) ; + else + plPlane.Set( ptS, Z_AX) ; + } + else { + if ( ! pCrv->IsFlat( plPlane, false, 10 * EPS_SMALL)) + return false ; + } + + if ( m_vpCrvs.size() == 0) { + // se prima curva considerata assegno il frame al Voronoi + m_Frame.Set( plPlane.GetPoint(), plPlane.GetVersN()) ; + } + else { + // altrimenti verifico sia complanare ad eventuali curve già presenti + if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), plPlane.GetVersN()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane)) + return false ; + } + + // verifico se oggetto vroni è stato inizializzato + if ( m_vroni == nullptr) { + m_vroni = new( nothrow) vroniObject() ; + m_vroni->apiInitializeProgram() ; + } + + // creo una copia della curva e la porto in locale + PtrOwner pCrvLoc( pCrv->Clone()) ; + pCrvLoc->ToLoc( m_Frame) ; + + // aggiungo la curva in locale all'oggetto vroni + if ( ! AddCurveToVroni( pCrvLoc)) + return false ; + + // aggiorno il box complessivo + BBox3d bBox ; + pCrvLoc->GetLocalBBox( bBox) ; + m_bBox.Add( bBox) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddSurfFlatRegion( const ISurfFlatRegion* pSfr) +{ + if ( ! m_bAllowAdd) + return false ; + + if ( pSfr == nullptr) + return false ; + + // recupero il piano + Point3d ptCen ; pSfr->GetCentroid( ptCen) ; + Vector3d vtN = pSfr->GetNormVersor() ; + if ( m_vpCrvs.size() == 0) { + // assegno il frame al Voronoi + m_Frame.Set( ptCen, vtN) ; + } + else { + // verifico sia complanare ad eventuali curve già presenti + Plane3d plPlane ; + plPlane.Set( ptCen, pSfr->GetNormVersor()) ; + if ( ! AreSameOrOppositeVectorApprox( m_Frame.VersZ(), pSfr->GetNormVersor()) || ! PointInPlaneApprox( m_Frame.Orig(), plPlane)) + return false ; + } + + // verifico se oggetto vroni è stato inizializzato + if ( m_vroni == nullptr) { + m_vroni = new( nothrow) vroniObject() ; + m_vroni->apiInitializeProgram() ; + } + + // aggiungo le curve di loop + for ( int i = 0 ; i < pSfr->GetChunkCount() ; i ++) { + for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; j ++) { + PtrOwner pCrvLoc( pSfr->GetLoop( i, j)) ; + pCrvLoc->ToLoc( m_Frame) ; + if ( ! AddCurveToVroni( pCrvLoc)) + return false ; + } + } + + // aggiorno il box complessivo + BBox3d bBox ; + Frame3d frSrf = m_Frame ; + frSrf.Invert() ; + pSfr->GetBBox( frSrf, bBox) ; + m_bBox.Add( bBox) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddCurveToVroni( const ICurve* pCrv) +{ + int nLoopId = m_vpCrvs.size() ; + + // aggiungo il punto iniziale + Point3d ptStart ; + if ( ! pCrv->GetStartPoint( ptStart)) + return false ; + int nCrv = m_vroni->HandlePnt( ptStart.x, ptStart.y, {nLoopId, 0}) ; + + // aggiungo la parte rimanente della curva + switch ( pCrv->GetType()) { + case CRV_LINE : + m_vpCrvs.emplace_back( pCrv->Clone()) ; + return AddLineToVroni( GetCurveLine( pCrv), nCrv, nLoopId) ; + case CRV_ARC : + m_vpCrvs.emplace_back( pCrv->Clone()) ; + return AddArcToVroni( GetCurveArc( pCrv), nCrv, nLoopId) ; + case CRV_COMPO : + return AddCompoToVroni( GetCurveComposite( pCrv), nCrv, nLoopId) ; + case CRV_BEZIER : + return AddBezierToVroni( GetCurveBezier( pCrv), nCrv, nLoopId) ; + default : + return false ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddLineToVroni( const ICurveLine* pLine, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd) +{ + if ( pLine == nullptr) + return false ; + if ( ! ptEnd.IsValid()) { + // recupero end point + if ( ! pLine->GetEndPoint( ptEnd)) + return false ; + } + + m_vroni->AddSeg( &nVroniCrv, ptEnd.x, ptEnd.y, {nLoopId, nCrvId}) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddArcToVroni( const ICurveArc* pArc, int& nVroniCrv, int nLoopId, int nCrvId, Point3d ptEnd) +{ + if ( pArc == nullptr) + return false ; + + Point3d ptCen = pArc->GetCenter() ; + if ( ! ptEnd.IsValid()) { + // recupero end point dalla curva + if ( ! pArc->GetEndPoint( ptEnd)) + return false ; + } + + double dAngCen = pArc->GetAngCenter() ; + int nArcSiteType = ( dAngCen > EPS_SMALL ? ARC : -ARC) ; + + if ( pArc->IsACircle()) { + // spezzo arco in due parti + Point3d ptM ; + if ( ! pArc->GetMidPoint( ptM)) + return false ; + m_vroni->AddArc( &nVroniCrv, ptM.x, ptM.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ; + m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ; + } + else + m_vroni->AddArc( &nVroniCrv, ptEnd.x, ptEnd.y, ptCen.x, ptCen.y, nArcSiteType, {nLoopId, nCrvId}) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddCompoToVroni( const ICurveComposite* pCompo, int& nVroniCrv, int nLoopId) +{ + if ( pCompo == nullptr) + return false ; + + PtrOwner pCopy( CloneBasicCurveComposite( pCompo)) ; + if ( IsNull( pCopy)) + return false ; + + // verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY ( estrusione deve essere Z+) + Vector3d vtExtr ; pCopy->GetExtrusion( vtExtr) ; + pCopy->SetExtrusion( Z_AX) ; + if ( ! pCopy->ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG)) + return false ; + pCopy->SetExtrusion( vtExtr) ; + + // aggiungo tutte le sottocurve + bool bClosed = pCopy->IsClosed() ; + for ( int i = 0 ; i < pCopy->GetCurveCount() ; i++) { + Point3d ptForcedEnd = P_INVALID ; + + // se curva è chiusa, forzo l'end point a coincidere con lo start ( per le tolleranze di vroni) + if ( i == pCopy->GetCurveCount() - 1 && bClosed) + pCopy->GetStartPoint( ptForcedEnd) ; + + // aggiungo + const ICurve* pCrv = pCopy->GetCurve( i) ; + int nType = pCrv->GetType() ; + if ( nType == CRV_LINE) + AddLineToVroni( GetCurveLine( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ; + else if ( nType == CRV_ARC) + AddArcToVroni( GetCurveArc( pCrv), nVroniCrv, nLoopId, i, ptForcedEnd) ; + } + + // aggiungo al vettore di curve + m_vpCrvs.emplace_back( Release( pCopy)) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::AddBezierToVroni( const ICurveBezier* pBezier, int& nVroniCrv, int nLoopId) +{ + if ( pBezier == nullptr) + return false ; + + // riconduco al caso di curva composita + PtrOwner pCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCompo)) + return false ; + PolyArc PA ; + if ( ! pBezier->ApproxWithArcsEx( LIN_TOL_STD, ANG_TOL_STD_DEG, LIN_FEA_LEN_STD, PA) || ! pCompo->FromPolyArc( PA)) + return false ; + + Vector3d vtExtr ; pBezier->GetExtrusion( vtExtr) ; + pCompo->SetExtrusion( vtExtr) ; + + return AddCompoToVroni( pCompo, nVroniCrv, nLoopId) ; +} + +//---------------------------------------------------------------------------- +ICurve* +Voronoi::GetCurve( int nId) +{ + // verifico validità indice + if ( nId < 0 || nId > ( int)m_vpCrvs.size() - 1) + return nullptr ; + // ne faccio una copia + ICurve* pCrv = m_vpCrvs[nId]->Clone() ; + if ( pCrv == nullptr) + return nullptr ; + // la porto nel riferimento globale + pCrv->ToGlob( m_Frame) ; + return pCrv ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcVoronoi( int nBound) +{ + // se già stato calcolato con lo stesso bound non devo fare nulla + if ( m_bVDComputed && nBound == m_nBound) + return true ; + + // se già stato calcolato reset dei dati + if ( m_bVDComputed) + m_vroni->ResetVoronoiDiagram() ; + + // calcolo + m_nBound = nBound ; + m_bVDComputed = true ; + string sTmp = "" ; + m_vroni->apiComputeVD( false, true, false, m_nBound, 0, 0, &sTmp[0], false, false, false, &sTmp[0], true) ; + + return true ; +} + +//---------------------------------------------------------------------------- +ICurve* +Voronoi::GetBisectorCurve( int i) +{ + if ( i >= m_vroni->GetNumberOfEdges()) + return nullptr ; + + // recupero estremi del bisettore + Point3d ptS, ptE ; + m_vroni->GetVDBisectorPoints( i, ptS.v, ptE.v) ; + if ( AreSamePointApprox( ptS, ptE)) + return nullptr ; + + // recupero parametri del bisettore + double dParS, dParE ; + m_vroni->GetVDBisectorParams( i, dParS, dParE) ; + + // eventuale inversione + if ( dParS > dParE + EPS_SMALL) { + swap( dParS, dParE) ; + swap( ptS, ptE) ; + } + + // costruisco la curva + int nType = m_vroni->GetVDBisectorType( i) ; + if ( nType == LINE) { + CurveLine* pLine = CreateBasicCurveLine() ; + if ( pLine == nullptr) + return nullptr ; + pLine->Set( ptS, ptE) ; + pLine->ToGlob( m_Frame) ; + // salvo le distanze nei suoi estremi come TempParam + pLine->SetTempParam( dParS, 0) ; + pLine->SetTempParam( dParE, 1) ; + return pLine ; + } + else if ( nType != NONE) { + // creo una composita campionando il bisettore + CurveComposite* pCompo = CreateBasicCurveComposite() ; + if ( pCompo == nullptr) + return nullptr ; + int nMaxPnts = 100 ; + double dDelta = ( dParE - dParS) / nMaxPnts ; + pCompo->AddPoint( ptS) ; + for ( int j = 1 ; j < nMaxPnts ; j ++) { + Point3d ptP ; + m_vroni->GetVDBisectorPointAtParam( i, dParS + j * dDelta, ptP.v) ; + if ( pCompo->AddLine( ptP)) { + // salvo le distanze dalla curva nei suoi estremi come temp param + pCompo->SetCurveTempParam( pCompo->GetCurveCount() - 1, dParS + ( j - 1) * dDelta, 0) ; + pCompo->SetCurveTempParam( pCompo->GetCurveCount() - 1, dParS + j * dDelta, 1) ; + } + } + // ultimo punto + if ( pCompo->AddLine( ptE)) { + pCompo->SetCurveTempParam( pCompo->GetCurveCount() - 1, dParS + ( nMaxPnts - 1) * dDelta, 0) ; + pCompo->SetCurveTempParam( pCompo->GetCurveCount() - 1, dParE, 1) ; + } + pCompo->SetTempParam( dParS, 0) ; + pCompo->SetTempParam( dParE, 1) ; + pCompo->ToGlob( m_Frame) ; + return pCompo ; + } + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcVoronoiDiagram( ICURVEPOVECTOR& vCrvs, int nBound) +{ + vCrvs.clear() ; + + if ( ! IsValid()) + return false ; + + // verifico se necessario calcolo Voronoi + if ( ! m_bVDComputed || nBound != m_nBound) + CalcVoronoi( nBound) ; + + for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { + // recupero la curva del bisettore + PtrOwner pCrv( GetBisectorCurve( i)) ; + if ( ! IsNull( pCrv)) + vCrvs.emplace_back( Release( pCrv)) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcMedialAxis( ICURVEPOVECTOR& vCrvs, int nSide) +{ + vCrvs.clear() ; + + if ( ! IsValid()) + return false ; + + if ( ! m_bVDComputed) + CalcVoronoi() ; + + // lato per il medial axis + bool bLeft = true ; + bool bRight = true ; + if ( nSide == WMAT_LEFT) + bRight = false ; + else if ( nSide == WMAT_RIGHT) + bLeft = false ; + + // calcolo medial axis + m_vroni->apiComputeWMAT( false, 0.0, 0.0, false, bLeft, bRight) ; + + for ( int i = 4 ; i < m_vroni->GetNumberOfEdges() ; i ++) { + // verifico se il lato appartiene al medial axis + if ( m_vroni->IsWMATEdge( i)) { + PtrOwner pCrv( GetBisectorCurve( i)) ; + if ( ! IsNull( pCrv)) + vCrvs.emplace_back( Release( pCrv)) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) +{ + vOffs.clear() ; + + 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() ; + + // stabilisco lato offset + bool bRightOffs = true ; + bool bLeftOffs = true ; + if ( bClosed) { + bRightOffs = ( dOffs > EPS_SMALL ? true : false) ; + bLeftOffs = ( dOffs < - EPS_SMALL ? true : false) ; + } + + // calcolo offset + ICRVCOMPOPLIST OffsList ; + if ( ! CalcVroniOffset( OffsList, abs( dOffs), bRightOffs, bLeftOffs)) + return false ; + + // sistemo le curve di offset calcolate con vroni + for ( auto pCrv : OffsList) { + + // aggiustamento per curva aperta + if ( ! bClosed) + AdjustOpenOffsetCurve( *pCrv, dOffs) ; + + if ( pCrv->IsValid()) { + // eventuale inversione + if ( dOffs > EPS_SMALL) + pCrv->Invert() ; + // sistemo il punto di inizio + if ( bClosed) + AdjustOffsetStart( *pCrv) ; + // sistemo i raccordi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + IdentifyFillets( pCrv, dOffs) ; + AdjustCurveFillets( pCrv, dOffs, nType) ; + } + // 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) ; + } + else + delete pCrv ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bool bSquareMids) +{ + vCrvs.clear() ; + + if ( ! IsValid()) + return false ; + + // se offset nullo errore + if ( abs( dOffs) < EPS_SMALL) + return false ; + + ICRVCOMPOPLIST OffsList ; + if ( ! CalcVroniOffset( OffsList, abs( dOffs), true, true)) + return false ; + + // sistemo le curve di offset calcolate con vroni + bool bClosed = m_vpCrvs[0]->IsClosed() ; + for ( auto pCrvOffs : OffsList) { + + // eventuale inversione + if ( dOffs > EPS_SMALL) + pCrvOffs->Invert() ; + + // sistemo i raccordi + if ( bClosed && bSquareMids) { + // se curva è chiusa tutti i raccordi rispondono a bSquareMids + IdentifyFillets( pCrvOffs, dOffs) ; + AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ; + } + else if ( ! bClosed && ( bSquareMids || bSquareEnds)) { + // se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e + // modificare solo quelli richiesti + for ( int j = 0 ; j < pCrvOffs->GetCurveCount() ; j ++) { + int nOrigCrv ; pCrvOffs->GetCurveTempProp( j, nOrigCrv) ; + double dTmpParam ; pCrvOffs->GetCurveTempParam( j, dTmpParam) ; + if ( nOrigCrv == 0 && ( ( bSquareMids && dTmpParam < EPS_SMALL) || ( bSquareEnds && dTmpParam > EPS_SMALL))) + pCrvOffs->SetCurveTempParam( j, 1) ; + else + pCrvOffs->SetCurveTempParam( j, 0) ; + } + AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ; + } + + // porto nel frame globale + pCrvOffs->ToGlob( m_Frame) ; + // unisco le parti allineate + pCrvOffs->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; + // aggiungo al vettore finale + vCrvs.emplace_back( pCrvOffs) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs, bool bRightOffs, bool bLeftOffs) +{ + OffsList.clear() ; + + 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() ; + } + + // reset di eventuali offset precedenti + m_vroni->apiResetOffsetData() ; + + // verifico necessario calcolo o ricalcolo di Voronoi + UpdateVoronoi( dOffs) ; + + string sTmp = "" ; + m_vroni->apiComputeOff( false, &sTmp[0], false, false, dOffs - VRONI_OFFS_TOL, 0.0, false, bLeftOffs, bRightOffs) ; + + // recupero le curve di offset da vroni + int nOffsCnt = m_vroni->GetOffsetCount() ; // numero curve di offset + for ( int i = 0 ; i < nOffsCnt ; i++) { + PtrOwner pCrvOffs ( CreateBasicCurveComposite()) ; + int nCrvCnt = m_vroni->GetOffsetCurveCount( i) ; // numero di sottocurve + + for ( int j = 0 ; j < nCrvCnt ; j ++) { + // recupero la sottocurva da vroni + Point3d ptS, ptE, ptC ; + int nType ; + int nOrigCrv, nOrigLoop, nOrigPnt ; // sito + m_vroni->GetOffsetCurve( i, j, nType, ptS.v, ptE.v, ptC.v, nOrigLoop, nOrigCrv, nOrigPnt) ; + + if ( j == 0) + pCrvOffs->AddPoint( ptS) ; + + bool bOk = false ; + if ( nType == t_site::SEG) + bOk = pCrvOffs->AddLine( ptE) ; + else { + PtrOwner pArc( CreateBasicCurveArc()) ; + pArc->Set2PRS( ptS, ptE, Dist( ptC, ptS), nType == CCW) ; + bOk = pCrvOffs->AddCurve( Release( pArc)) ; + } + + // se la curva è stata aggiunta + if ( bOk) { + // setto come info la sottocurva da cui si è generata + 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) ; + } + } + + // aggiungo la curva alla lista degli offset + if ( ! IsNull( pCrvOffs) && pCrvOffs->IsValid()) + OffsList.push_back( Release( pCrvOffs)) ; + } + + return true ; +} + + +//---------------------------------------------------------------------------- +bool +Voronoi::UpdateVoronoi( double dOffs) +{ + double dNeededBound = abs( dOffs) / 0.49 / sqrt( m_bBox.GetDimX() * m_bBox.GetDimX() + m_bBox.GetDimY() * m_bBox.GetDimY()) ; + if ( ! m_bVDComputed || dNeededBound > m_nBound) { + // aggiorno il valore del bound + int nBound = ( int)( ceil( dNeededBound) + 0.5) ; + // calcolo il nuovo diagramma + CalcVoronoi( nBound) ; + } + + return true ; + +} + +//---------------------------------------------------------------------------- +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 = i + 1 ; j < ( int)vArea.size() ; j++) { + if ( vArea[i] * vArea[j] > EPS_SMALL) { + IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ; + int nRes = ccInt.GetRegionCurveClassification() ; + if ( ( bRefCCW && nRes != CCREGC_OUT) || ( ! bRefCCW && nRes != CCREGC_IN1)) + 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::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs) +{ + 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) ; + } + + if ( vJunctions.size() == 0) { + // verifico se si trova dal lato corretto + int nSide = GetOffsetCurveSide( pCompo, 0) ; + if ( nSide != nSideRef) + // se lato errato, tutta la curva va cancellata + pCompo.Clear() ; + } + else if ( vJunctions.size() == 2) { + // recupero i due tratti di curva + PtrOwner pCompo1( ConvertCurveToComposite( pCompo.CopyParamRange( vJunctions[0] + 1, vJunctions[1]))) ; + PtrOwner pCompo2( ConvertCurveToComposite( 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++) { + 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) ; + } + } + } + + return true ; +} + +//--------------------------------------------------------------------------- +int +Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) +{ + Point3d ptM ; pOffs.GetCurve( nCrv)->GetMidPoint(ptM) ; + int nOrigCrv ; pOffs.GetCurveTempProp( nCrv, nOrigCrv) ; + + const ICurve* pCrvRef = m_vpCrvs[0] ; + // se ha una sottocurva di riferimento + if ( nOrigCrv != 0 && m_vpCrvs[0]->GetType() == CRV_COMPO) { + const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[0]) ; + if ( pCompoOrig != nullptr) + pCrvRef = pCompoOrig->GetCurve( nOrigCrv - 1) ; + } + + DistPointCurve distPC( ptM, *pCrvRef) ; + int nSide = MDS_ON ; + distPC.GetSideAtMinDistPoint( 0, Z_AX, nSide) ; + return nSide ; +} + +//--------------------------------------------------------------------------- +bool +Voronoi::AdjustOffsetStart( ICurveComposite& pCrv) +{ + 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) ; + break ; + } + // oppure un raccordo di junction + double dParam ; pCrv.GetCurveTempParam( i, dParam) ; + if ( abs( dParam - 1) < EPS_SMALL) { + pCrv.ChangeStartPoint( i + 1) ; + break ; + } + } + return true ; +} diff --git a/stdafx.h b/stdafx.h index 1e1d867..74264f5 100644 --- a/stdafx.h +++ b/stdafx.h @@ -29,6 +29,7 @@ #include "/EgtDev/Include/EgtLibVer.h" #pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib") +#pragma comment(lib, EGTEXTDIR "vroni/Lib/vroni" EGTLIBVER ".lib") #pragma comment(lib, EGTLIBDIR "EgtGeneral" EGTLIBVER ".lib") #pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib") #pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")