7c6ddf2a6f
- aggiunto controllo validità coordinate di punti e vettori (isfinite).
996 lines
27 KiB
C++
996 lines
27 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2014-2014
|
|
//----------------------------------------------------------------------------
|
|
// File : CurveLine.cpp Data : 06.05.14 Versione : 1.5e3
|
|
// Contenuto : Implementazione della classe Segmento di Linea.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 16.04.13 DS Creazione modulo.
|
|
// 06.05.14 DS Aggiunta Set per Pini, vtDir, Len e per Pini, AngDir, Len.
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CurveLine.h"
|
|
#include "DistPointLine.h"
|
|
#include "GeoObjFactory.h"
|
|
#include "NgeWriter.h"
|
|
#include "NgeReader.h"
|
|
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
#include <new>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
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_nTempProp[0] = 0 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveLine::~CurveLine( void)
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Set( const Point3d& ptStart, const Point3d& ptEnd)
|
|
{
|
|
// assegno i dati
|
|
m_PtStart = ptStart ;
|
|
m_PtEnd = ptEnd ;
|
|
m_nStatus = TO_VERIFY ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::SetPVL( const Point3d& ptStart, const Vector3d& vtDir, double dLen)
|
|
{
|
|
// assegno i dati
|
|
m_PtStart = ptStart ;
|
|
Vector3d vtDelta = vtDir ;
|
|
if ( ! vtDelta.Normalize())
|
|
return false ;
|
|
vtDelta *= dLen ;
|
|
m_PtEnd = ptStart + vtDelta ;
|
|
m_nStatus = TO_VERIFY ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::SetPDL( const Point3d& ptStart, double dDirAngDeg, double dLen)
|
|
{
|
|
// assegno i dati
|
|
m_PtStart = ptStart ;
|
|
Vector3d vtDelta ;
|
|
vtDelta = FromPolar( dLen, dDirAngDeg) ;
|
|
m_PtEnd = ptStart + vtDelta ;
|
|
m_nStatus = TO_VERIFY ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
CurveLine*
|
|
CurveLine::Clone( void) const
|
|
{
|
|
// alloco oggetto
|
|
CurveLine* pCrv = new( nothrow) CurveLine ;
|
|
if ( pCrv != nullptr) {
|
|
if ( ! pCrv->CopyFrom( *this)) {
|
|
delete pCrv ;
|
|
return nullptr ;
|
|
}
|
|
}
|
|
|
|
return pCrv ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::CopyFrom( const IGeoObj* pGObjSrc)
|
|
{
|
|
const CurveLine* pCL = dynamic_cast<const CurveLine*>( pGObjSrc) ;
|
|
if ( pCL == nullptr)
|
|
return false ;
|
|
return CopyFrom( *pCL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::CopyFrom( const CurveLine& clSrc)
|
|
{
|
|
if ( &clSrc == this)
|
|
return true ;
|
|
m_VtExtr = clSrc.m_VtExtr ;
|
|
m_dThick = clSrc.m_dThick ;
|
|
m_nTempProp[0] = clSrc.m_nTempProp[0] ;
|
|
m_nTempProp[1] = clSrc.m_nTempProp[1] ;
|
|
return Set( clSrc.m_PtStart, clSrc.m_PtEnd) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
GeoObjType
|
|
CurveLine::GetType( void) const
|
|
{
|
|
return static_cast<GeoObjType>( GEOOBJ_GETTYPE( CurveLine)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
const string&
|
|
CurveLine::GetTitle( void) const
|
|
{
|
|
static const string sTitle = "Line" ;
|
|
return sTitle ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Dump( string& sOut, bool bMM, const char* szNewLine) const
|
|
{
|
|
// dati generali di una curva
|
|
if ( ! CurveDump( *this, sOut, bMM, szNewLine))
|
|
return false ;
|
|
// parametri : sono già compresi nei dati generali (PS e PE)
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
CurveLine::GetNgeId( void) const
|
|
{
|
|
return GEOOBJ_GETNGEID( CurveLine) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Save( NgeWriter& ngeOut) const
|
|
{
|
|
// parametri : punti iniziale e finale
|
|
if ( ! ngeOut.WritePoint( m_PtStart, ";"))
|
|
return false ;
|
|
if ( ! ngeOut.WritePoint( m_PtEnd, ";", true))
|
|
return false ;
|
|
// da versione 1008 : linea con VtEstrusione e Spessore
|
|
if ( ! ngeOut.WriteVector( m_VtExtr, ";"))
|
|
return false ;
|
|
if ( ! ngeOut.WriteDouble( m_dThick, ";", true))
|
|
return false ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Load( NgeReader& ngeIn)
|
|
{
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
// leggo la prossima linea
|
|
if ( ! ngeIn.ReadPoint( m_PtStart, ";"))
|
|
return false ;
|
|
if ( ! ngeIn.ReadPoint( m_PtEnd, ";", true))
|
|
return false ;
|
|
// da versione 1008 : linea con VtEstrusione e Spessore
|
|
if ( ngeIn.GetFileVersion() >= NGE_VER_1008) {
|
|
if ( ! ngeIn.ReadVector( m_VtExtr, ";"))
|
|
return false ;
|
|
if ( ! ngeIn.ReadDouble( m_dThick, ";", true))
|
|
return false ;
|
|
}
|
|
// eseguo validazione
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetLocalBBox( BBox3d& b3Loc, int nFlag) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// assegno il box in locale
|
|
b3Loc.Set( m_PtStart, m_PtEnd) ;
|
|
// se c'è estrusione, devo tenerne conto
|
|
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
|
Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ;
|
|
Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ;
|
|
b3Loc.Add( ptMinExtr) ;
|
|
b3Loc.Add( ptMaxExtr) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
// porto gli estremi nel riferimento passato
|
|
Point3d ptFrStart = m_PtStart ;
|
|
ptFrStart.ToGlob( frRef) ;
|
|
Point3d ptFrEnd = m_PtEnd ;
|
|
ptFrEnd.ToGlob( frRef) ;
|
|
// assegno il box nel riferimento
|
|
b3Ref.Set( ptFrStart, ptFrEnd) ;
|
|
// se c'è estrusione, devo tenerne conto
|
|
if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) {
|
|
Vector3d vtFrExtr = m_VtExtr ;
|
|
vtFrExtr.ToGlob( frRef) ;
|
|
Point3d ptMinExtr = b3Ref.GetMin() + vtFrExtr * m_dThick ;
|
|
Point3d ptMaxExtr = b3Ref.GetMax() + vtFrExtr * m_dThick ;
|
|
b3Ref.Add( ptMinExtr) ;
|
|
b3Ref.Add( ptMaxExtr) ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Validate( void)
|
|
{
|
|
if ( m_nStatus == TO_VERIFY)
|
|
m_nStatus = ( m_PtStart.IsValid() && m_PtEnd.IsValid() && ! AreSamePointApprox( m_PtStart, m_PtEnd) ? OK : ERR) ;
|
|
|
|
return ( m_nStatus == OK) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::IsFlat( Plane3d& plPlane, bool bUseExtrusion, double dToler) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno dati piano
|
|
bool bFlat ;
|
|
Vector3d vtN ;
|
|
if ( ! bUseExtrusion || m_VtExtr.IsSmall()) {
|
|
vtN = FromUprightOrtho( m_PtEnd - m_PtStart) ;
|
|
bFlat = true ;
|
|
}
|
|
else {
|
|
Vector3d vtDir ; GetStartDir( vtDir) ;
|
|
vtN = m_VtExtr - ( m_VtExtr * vtDir) * vtDir ;
|
|
if ( ! vtN.Normalize())
|
|
vtN = FromUprightOrtho( vtDir) ;
|
|
bFlat = ( AreSameOrOppositeVectorApprox( m_VtExtr, vtN)) ;
|
|
}
|
|
plPlane.Set( 0.5 * ( m_PtStart + m_PtEnd), vtN) ;
|
|
|
|
// ritorno conferma
|
|
return bFlat ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetStartPoint( Point3d& ptStart) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno il punto
|
|
ptStart = m_PtStart ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetEndPoint( Point3d& ptEnd) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno il punto
|
|
ptEnd = m_PtEnd ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetMidPoint( Point3d& ptMid) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// assegno il punto
|
|
ptMid = Media( m_PtStart, m_PtEnd, 0.5) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetStartDir( Vector3d& vtDir) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// calcolo la direzione
|
|
vtDir = m_PtEnd - m_PtStart ;
|
|
return vtDir.Normalize() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// il parametro U deve essere compreso tra 0 e 1
|
|
if ( dU < 0)
|
|
dU = 0 ;
|
|
else if ( dU > 1)
|
|
dU = 1 ;
|
|
|
|
// calcolo del punto
|
|
ptPos = Media( m_PtStart, m_PtEnd, dU) ;
|
|
|
|
// calcolo della derivata prima
|
|
if ( pvtDer1 != nullptr)
|
|
*pvtDer1 = m_PtEnd - m_PtStart ;
|
|
|
|
// derivata seconda nulla
|
|
if ( pvtDer2 != nullptr && pvtDer1 != nullptr)
|
|
pvtDer2->Set( 0, 0, 0) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetLength( double& dLen) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// la lunghezza è la distanza tra gli estremi
|
|
dLen = Dist( m_PtStart, m_PtEnd) ;
|
|
|
|
return ( dLen > EPS_SMALL) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetLengthAtParam( double dU, double& dLen) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// fuori dominio del parametro -> errore
|
|
if ( dU < 0 - EPS_PARAM)
|
|
return false ;
|
|
if ( dU > ( 1 + EPS_PARAM))
|
|
return false ;
|
|
|
|
// inizio
|
|
if ( dU < 0 + EPS_PARAM) {
|
|
dLen = 0 ;
|
|
return true ;
|
|
}
|
|
|
|
// la lunghezza totale è la distanza tra gli estremi
|
|
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
|
|
|
|
// fine
|
|
if ( dU > 1 - EPS_PARAM) {
|
|
dLen = dTotLen ;
|
|
return true ;
|
|
}
|
|
|
|
// posizione intermedia
|
|
dLen = dU * dTotLen ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetParamAtLength( double dLen, double& dU) const
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// se prima di inizio, errore
|
|
if ( dLen < - EPS_SMALL)
|
|
return false ;
|
|
|
|
// inizio
|
|
if ( dLen < EPS_SMALL) {
|
|
dU = 0 ;
|
|
return true ;
|
|
}
|
|
|
|
// la lunghezza totale è la distanza tra gli estremi
|
|
double dTotLen = Dist( m_PtStart, m_PtEnd) ;
|
|
|
|
// se dopo fine, errore
|
|
if ( dLen > dTotLen + EPS_SMALL)
|
|
return false ;
|
|
|
|
// fine
|
|
if ( dLen > dTotLen - EPS_SMALL) {
|
|
dU = 1 ;
|
|
return true ;
|
|
}
|
|
|
|
// posizione intermedia
|
|
dU = dLen / dTotLen ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::IsPointOn( const Point3d& ptP, double dTol) const
|
|
{
|
|
double dSqDist ;
|
|
dTol = max( dTol, EPS_ZERO) ;
|
|
return ( DistPointLine( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetParamAtPoint( const Point3d& ptP, double& dPar, double dTol) const
|
|
{
|
|
double dSqDist ;
|
|
dTol = max( dTol, EPS_ZERO) ;
|
|
DistPointLine DPL( ptP, *this) ;
|
|
if ( ! DPL.GetSqDist( dSqDist) || dSqDist > dTol * dTol)
|
|
return false ;
|
|
return DPL.GetParamAtMinDistPoint( dPar) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::GetLengthAtPoint( const Point3d& ptP, double& dLen, double dTol) const
|
|
{
|
|
double dU ;
|
|
if ( ! GetParamAtPoint( ptP, dU, dTol))
|
|
return false ;
|
|
return GetLengthAtParam( dU, dLen) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const
|
|
{
|
|
// pulisco la polilinea
|
|
PL.Clear() ;
|
|
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// inserisco gli estremi
|
|
PL.AddUPoint( 0, m_PtStart) ;
|
|
PL.AddUPoint( 1, m_PtEnd) ;
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const
|
|
{
|
|
// pulisco la polilinea
|
|
PA.Clear() ;
|
|
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// determinazione versore normale al piano di riferimento
|
|
Vector3d vtNref = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ;
|
|
|
|
// assegno estrusione al poliarco
|
|
PA.SetExtrusion( vtNref) ;
|
|
|
|
// inserisco gli estremi
|
|
return ( PA.AddUPoint( 0, m_PtStart, 0) && PA.AddUPoint( 1, m_PtEnd, 0)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
ICurve*
|
|
CurveLine::CopyParamRange( double dUStart, double dUEnd) const
|
|
{
|
|
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
|
if ( dUStart < - EPS_PARAM || dUStart > 1 + EPS_PARAM ||
|
|
dUEnd < - EPS_PARAM || dUEnd > 1 + EPS_PARAM)
|
|
return nullptr ;
|
|
// se il parametro start supera quello di end, essendo la linea una curva aperta, errore
|
|
if ( dUStart > dUEnd - EPS_PARAM)
|
|
return nullptr ;
|
|
// creo la linea copia
|
|
PtrOwner<CurveLine> pCopy( Clone()) ;
|
|
if ( IsNull( pCopy))
|
|
return nullptr ;
|
|
// eseguo il trim
|
|
if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd))
|
|
return nullptr ;
|
|
return ( ::Release( pCopy)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Invert( void)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// inverto i punti estremi
|
|
swap( m_PtStart, m_PtEnd) ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::SimpleOffset( double dDist, int nType)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// determinazione versore normale al piano di offset
|
|
Vector3d vtNorm = Z_AX ;
|
|
if ( ! m_VtExtr.IsSmall())
|
|
vtNorm = m_VtExtr ;
|
|
|
|
// calcolo il versore direzione linea nel piano perpendicolare alla normale
|
|
Vector3d vtDir = m_PtEnd - m_PtStart ;
|
|
vtDir -= vtDir * vtNorm * vtNorm ;
|
|
if ( ! vtDir.Normalize())
|
|
return false ;
|
|
// calcolo il versore ortogonale dal lato destro (offset positivo)
|
|
vtDir.Rotate( vtNorm, 0, -1) ; // rotazione CW di 90 deg
|
|
|
|
// sposto i punti
|
|
m_PtStart += vtDir * dDist ;
|
|
m_PtEnd += vtDir * dDist ;
|
|
|
|
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ModifyStart( const Point3d& ptNewStart)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// la linea modificata deve essere ancora valida
|
|
if ( AreSamePointApprox( ptNewStart, m_PtEnd))
|
|
return false ;
|
|
// assegno il nuovo inizio
|
|
m_PtStart = ptNewStart ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ModifyEnd( const Point3d& ptNewEnd)
|
|
{
|
|
// verifico lo stato
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
|
|
// la linea modificata deve essere ancora valida
|
|
if ( AreSamePointApprox( m_PtStart, ptNewEnd))
|
|
return false ;
|
|
// assegno la nuova fine
|
|
m_PtEnd = ptNewEnd ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::TrimStartAtParam( double dUTrim)
|
|
{
|
|
// riporto i parametri nel loro range
|
|
dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ;
|
|
|
|
// recupero lunghezza
|
|
double dLen ;
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
|
|
// utilizzo il trim sulle lunghezze
|
|
return TrimStartAtLen( dUTrim * dLen) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::TrimEndAtParam( double dUTrim)
|
|
{
|
|
// riporto i parametri nel loro range
|
|
dUTrim = ( ( dUTrim < 0) ? 0 : (( dUTrim > 1) ? 1 : dUTrim)) ;
|
|
|
|
// recupero lunghezza
|
|
double dLen ;
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
|
|
// utilizzo il trim sulle lunghezze
|
|
return TrimEndAtLen( dUTrim * dLen) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim)
|
|
{
|
|
// i parametri start ed end devono essere compresi nel dominio parametrico della curva
|
|
if ( dUStartTrim < - EPS_PARAM || dUStartTrim > 1 + EPS_PARAM ||
|
|
dUEndTrim < - EPS_PARAM || dUEndTrim > 1 + EPS_PARAM)
|
|
return false ;
|
|
// verifico che i trim non cancellino interamente la curva
|
|
if ( dUStartTrim > dUEndTrim - EPS_PARAM)
|
|
return false ;
|
|
// trim finale
|
|
if ( ! TrimEndAtParam( dUEndTrim))
|
|
return false ;
|
|
// trim iniziale con il parametro opportunamente ricalcolato
|
|
double dNewUStartTrim = dUStartTrim / dUEndTrim ;
|
|
return TrimStartAtParam( dNewUStartTrim) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::TrimStartAtLen( double dLenTrim)
|
|
{
|
|
// lunghezze negative vengono considerate nulle
|
|
dLenTrim = max( dLenTrim, 0.) ;
|
|
|
|
// verifico che sia abbastanza lunga
|
|
double dLen ;
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
if ( ( dLen - dLenTrim) < EPS_SMALL)
|
|
return false ;
|
|
|
|
// eseguo il trim
|
|
if ( dLenTrim > EPS_ZERO)
|
|
m_PtStart = Media( m_PtStart, m_PtEnd, ( dLenTrim / dLen)) ;
|
|
|
|
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::TrimEndAtLen( double dLenTrim)
|
|
{
|
|
// lunghezze negative vengono considerate nulle
|
|
dLenTrim = max( dLenTrim, 0.) ;
|
|
|
|
// verifico che sia abbastanza lunga
|
|
double dLen ;
|
|
if ( ! GetLength( dLen))
|
|
return false ;
|
|
if ( dLenTrim < EPS_SMALL)
|
|
return false ;
|
|
|
|
// eseguo il trim
|
|
if ( ( dLen - dLenTrim) > EPS_ZERO)
|
|
m_PtEnd = Media( m_PtStart, m_PtEnd, ( dLenTrim / dLen)) ;
|
|
|
|
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ExtendStartByLen( double dLenExt)
|
|
{
|
|
// la lunghezza deve essere positiva
|
|
if ( dLenExt < - EPS_ZERO)
|
|
return false ;
|
|
|
|
// versore della linea
|
|
Vector3d vtDir ;
|
|
if ( ! GetStartDir( vtDir))
|
|
return false ;
|
|
|
|
// sposto il punto iniziale
|
|
m_PtStart -= vtDir * dLenExt ;
|
|
|
|
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ExtendEndByLen( double dLenExt)
|
|
{
|
|
// la lunghezza deve essere positiva
|
|
if ( dLenExt < - EPS_ZERO)
|
|
return false ;
|
|
|
|
// versore della linea
|
|
Vector3d vtDir ;
|
|
if ( ! GetEndDir( vtDir))
|
|
return false ;
|
|
|
|
// sposto il punto finale
|
|
m_PtEnd += vtDir * dLenExt ;
|
|
|
|
// con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata
|
|
m_OGrMgr.Reset() ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Translate( const Vector3d& vtMove)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// traslo i punti estremi
|
|
m_PtStart.Translate( vtMove) ;
|
|
m_PtEnd.Translate( vtMove) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, double dSinAng)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità dell'asse di rotazione
|
|
if ( vtAx.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// ruoto i punti estremi
|
|
m_PtStart.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
m_PtEnd.Rotate( ptAx, vtAx, dCosAng, dSinAng) ;
|
|
// ruoto il vettore estrusione
|
|
m_VtExtr.Rotate( vtAx, dCosAng, dSinAng) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double dCoeffZ)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico non sia nulla
|
|
if ( abs( dCoeffX) < EPS_ZERO && abs( dCoeffY) < EPS_ZERO && abs( dCoeffZ) < EPS_ZERO)
|
|
return false ;
|
|
|
|
// verifico che la scalatura dei punti non li porti a coincidere
|
|
Point3d ptNewStart = m_PtStart ;
|
|
ptNewStart.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
Point3d ptNewEnd = m_PtEnd ;
|
|
ptNewEnd.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
if ( AreSamePointApprox( ptNewStart, ptNewEnd))
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// uso i punti estremi
|
|
m_PtStart = ptNewStart ;
|
|
m_PtEnd = ptNewEnd ;
|
|
// scalo vettore estrusione, lo normalizzo e aggiusto spessore
|
|
m_VtExtr.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ;
|
|
double dLen = m_VtExtr.Len() ;
|
|
if ( dLen > EPS_ZERO) {
|
|
m_VtExtr /= dLen ;
|
|
m_dThick *= dLen ;
|
|
}
|
|
m_nStatus = TO_VERIFY ;
|
|
|
|
return Validate() ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Mirror( const Point3d& ptOn, const Vector3d& vtNorm)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del piano di specchiatura
|
|
if ( vtNorm.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// specchio i punti estremi
|
|
m_PtStart.Mirror( ptOn, vtNorm) ;
|
|
m_PtEnd.Mirror( ptOn, vtNorm) ;
|
|
// specchio il vettore estrusione
|
|
m_VtExtr.Mirror( vtNorm) ;
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtDir, double dCoeff)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità dei parametri
|
|
if ( vtNorm.IsSmall() || vtDir.IsSmall())
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// eseguo scorrimento dei punti estremi
|
|
m_PtStart.Shear( ptOn, vtNorm, vtDir, dCoeff) ;
|
|
m_PtEnd.Shear( ptOn, vtNorm, vtDir, dCoeff) ;
|
|
// eseguo scorrimento del vettore estrusione, lo normalizzo e aggiusto spessore
|
|
m_VtExtr.Shear( vtNorm, vtDir, dCoeff) ;
|
|
double dLen = m_VtExtr.Len() ;
|
|
if ( dLen > EPS_ZERO) {
|
|
m_VtExtr /= dLen ;
|
|
m_dThick *= dLen ;
|
|
}
|
|
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ToGlob( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo i punti estremi e il vettore estrusione
|
|
return ( m_PtStart.ToGlob( frRef) && m_PtEnd.ToGlob( frRef) && m_VtExtr.ToGlob( frRef)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::ToLoc( const Frame3d& frRef)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità del frame
|
|
if ( frRef.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo i punti estremi e il vettore estrusione
|
|
return ( m_PtStart.ToLoc( frRef) && m_PtEnd.ToLoc( frRef) && m_VtExtr.ToLoc( frRef)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest)
|
|
{
|
|
// la curva deve essere validata
|
|
if ( m_nStatus != OK)
|
|
return false ;
|
|
// verifico validità dei frame
|
|
if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR)
|
|
return false ;
|
|
// se i due riferimenti coincidono, non devo fare alcunché
|
|
if ( AreSameFrame( frOri, frDest))
|
|
return true ;
|
|
|
|
// imposto ricalcolo della grafica
|
|
m_OGrMgr.Reset() ;
|
|
|
|
// trasformo i punti estremi e il vettore estrusione
|
|
return ( m_PtStart.LocToLoc( frOri, frDest) &&
|
|
m_PtEnd.LocToLoc( frOri, frDest) &&
|
|
m_VtExtr.LocToLoc( frOri, frDest)) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveLine::CalcPointParamPosiz( const Point3d& ptP, bool bOnXY, double& dU, int& nPos) const
|
|
{
|
|
// vettore linea nel piano XY
|
|
Vector3d vtDir = m_PtEnd - m_PtStart ;
|
|
if ( bOnXY)
|
|
vtDir.z = 0 ;
|
|
if ( vtDir.IsSmall())
|
|
return false ;
|
|
// calcolo parametro
|
|
dU = ( ptP - m_PtStart) * vtDir / vtDir.SqLen() ;
|
|
// verifica posizione intersezione su linea
|
|
nPos = ICurve::PP_NULL ; // fuori
|
|
if ( ( dU * vtDir).IsSmall()) {
|
|
nPos = ICurve::PP_START ; // vicino a inizio
|
|
dU = max( dU, 0.) ;
|
|
}
|
|
else if ( (( 1 - dU) * vtDir).IsSmall()) {
|
|
nPos = ICurve::PP_END ; // vicino a fine
|
|
dU = min( dU, 1.) ;
|
|
}
|
|
else if ( dU > 0 && dU < 1)
|
|
nPos = ICurve::PP_MID ; // nell'interno
|
|
return true ;
|
|
}
|