//---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- // File : ImportDxfEnts.cpp Data : 11.05.14 Versione : 1.5e2 // Contenuto : Implementazione di ImportDxf : gestione delle entità. // // // // Modifiche : 17.04.14 DS Creazione modulo. // 11.05.14 DS Agg. lettura SOLID. // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ImportDxf.h" #include "DxfColors.h" #include "DxfConst.h" #include "DllMain.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoVector3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkCurveAux.h" #include "/EgtDev/Include/EGkCurveByInterp.h" #include "/EgtDev/Include/EGkSurfTriMesh.h" #include "/EgtDev/Include/EGkExtText.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGnStringKeyVal.h" #include "/EgtDev/Include/EgtStringEncoder.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //---------------------------------------------------------------------------- const double RAY_LEN = 1000 ; //---------------------------------------------------------------------------- bool ImportDxf::ReadEntities( bool& bFileEnd) { // ciclo di lettura bool bOk = true ; bool bSectEnd = false ; string sEntName ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bSectEnd, bFileEnd) ; if ( bOkLoc && ! bSectEnd) { // se Entità if ( ReadOneEntity( sEntName, bOkLoc, bFileEnd)) ; // altrimenti ... else { string sOut = "ImportDxf : Skip entity " + sEntName + " at line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_WARN( GetEExLogger(), sOut.c_str()) if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; } } // gestisco eventuale errore if ( ! bOkLoc) { bOk = false ; string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) } } while ( ! bSectEnd) ; return bOk ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadOneEntity( string& sEntName, bool& bOk, bool& bFileEnd) { // se Faccia 3d if ( sEntName == "3DFACE") { if ( ! Read3dFace( bFileEnd)) bOk = false ; } // se Arco else if ( sEntName == "ARC") { if ( ! ReadArc( bFileEnd)) bOk = false ; } // se AttDef (da saltare) else if ( sEntName == "ATTDEF") { if ( ! SkipEntity( bFileEnd)) bOk = false ; } // se Cerchio else if ( sEntName == "CIRCLE") { if ( ! ReadCircle( bFileEnd)) bOk = false ; } // se Ellisse else if ( sEntName == "ELLIPSE") { if ( ! ReadEllipse( bFileEnd)) bOk = false ; } // se Insert di Blocco else if ( sEntName == "INSERT") { if ( ! ReadInsert( bFileEnd)) bOk = false ; } // se Linea else if ( sEntName == "LINE" || sEntName == "3DLINE") { if ( ! ReadLine( bFileEnd)) bOk = false ; } // se LwPolyLine else if ( sEntName == "LWPOLYLINE") { if ( ! ReadLwPolyLine( bFileEnd)) bOk = false ; } // se MText else if ( sEntName == "MTEXT") { if ( ! ReadMText( bFileEnd)) bOk = false ; } // se Punto else if ( sEntName == "POINT") { if ( ! ReadPoint( bFileEnd)) bOk = false ; } // se PolyLine else if ( sEntName == "POLYLINE") { if ( ! ReadPolyLine( bFileEnd)) bOk = false ; } // se Ray (semiretta) else if ( sEntName == "RAY") { if ( ! ReadRayXline( true, bFileEnd)) bOk = false ; } // se 2D filled outline else if ( sEntName == "SOLID") { if ( ! ReadSolid( bFileEnd)) bOk = false ; } // se Spline else if ( sEntName == "SPLINE") { if ( ! ReadSpline( bFileEnd)) bOk = false ; } // se Text else if ( sEntName == "TEXT") { if ( ! ReadText( GDB_ID_NULL, bFileEnd)) bOk = false ; } // se XLINE (linea infinita) else if ( sEntName == "XLINE") { if ( ! ReadRayXline( false, bFileEnd)) bOk = false ; } // altrimenti else { return false ; } return true ; } //---------------------------------------------------------------------------- bool ImportDxf::GetEntityName( string& sEntName, bool& bSectEnd, bool& bFileEnd) { // inizializzo sEntName.clear() ; bSectEnd = false ; bFileEnd = false ; // leggo il primo Item (mi aspetto 0 -> NomeEntità) int nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bSectEnd = true ; bFileEnd = true ; return false ; } if ( nCode != 0) return false ; if ( m_sCurrItem == "SECTION") { UngetItem() ; bSectEnd = true ; return true ; } if ( m_sCurrItem == "ENDSEC") { bSectEnd = true ; return true ; } if ( m_sCurrItem == "EOF") { bSectEnd = true ; bFileEnd = true ; return true ; } sEntName = m_sCurrItem ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::SkipEntity( bool& bFileEnd) { bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item ( cerco 0 -> qualcosa) nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } } while ( nCode != 0) ; UngetItem() ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::SetColor( int nId, int nColor, const string& sLayer) { Color cCol ; if ( ColorFromACI( nColor, cCol)) { if ( ! m_pGDB->SetMaterial( nId, cCol)) return false ; } else if ( BlockReading() && nColor == COL_BYLAYER && sLayer != "0") { if ( m_pGDB->GetMaterial( GetLayerId( sLayer), cCol)) { if ( ! m_pGDB->SetMaterial( nId, cCol)) return false ; } } return true ; } //---------------------------------------------------------------------------- bool ImportDxf::SetColorForInsert( int nId, int nIdS, const string& sLayer) { Color cCol ; if ( m_pGDB->GetMaterial( nIdS, cCol)) { if ( ! m_pGDB->SetMaterial( nId, cCol)) return false ; } else if ( sLayer != "0") { if ( m_pGDB->GetMaterial( GetLayerId( sLayer), cCol)) { if ( ! m_pGDB->SetMaterial( nId, cCol)) return false ; } } return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ColorFromACI( int nColor, Color& cCol) { // controllo i limiti dell'indice di colore ACI if ( nColor < 1 || nColor > 255) return false ; // assegno il colore cCol.Set( DxfColors[nColor][0], DxfColors[nColor][1], DxfColors[nColor][2]) ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::Read3dFace( bool& bFileEnd) { Point3d ptP0 ; Point3d ptP1 ; Point3d ptP2 ; Point3d ptP3 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item di 3dFace bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP0.x) ; break ; case 20 : FromString( m_sCurrItem, ptP0.y) ; break ; case 30 : FromString( m_sCurrItem, ptP0.z) ; break ; case 11 : FromString( m_sCurrItem, ptP1.x) ; break ; case 21 : FromString( m_sCurrItem, ptP1.y) ; break ; case 31 : FromString( m_sCurrItem, ptP1.z) ; break ; case 12 : FromString( m_sCurrItem, ptP2.x) ; break ; case 22 : FromString( m_sCurrItem, ptP2.y) ; break ; case 32 : FromString( m_sCurrItem, ptP2.z) ; break ; case 13 : FromString( m_sCurrItem, ptP3.x) ; break ; case 23 : FromString( m_sCurrItem, ptP3.y) ; break ; case 33 : FromString( m_sCurrItem, ptP3.z) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptP0 *= m_dScaleFactor ; ptP1 *= m_dScaleFactor ; ptP2 *= m_dScaleFactor ; ptP3 *= m_dScaleFactor ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptP0.ToLoc( m_frGroup) ; ptP1.ToLoc( m_frGroup) ; ptP2.ToLoc( m_frGroup) ; ptP3.ToLoc( m_frGroup) ; } // verifico se 3 o 4 punti bool bQuad = ! AreSamePointApprox( ptP2, ptP3) ; // inserisco la faccia nel DB geometrico // creo la trimesh PtrOwner pSTM( CreateSurfTriMesh()) ; if ( IsNull( pSTM)) return false ; // costruisco la geometria della trimesh if ( ! pSTM->Init( 4, 2)) return false ; if ( pSTM->AddVertex( ptP0) == SVT_NULL || pSTM->AddVertex( ptP1) == SVT_NULL || pSTM->AddVertex( ptP2) == SVT_NULL || ( bQuad && pSTM->AddVertex( ptP3) == SVT_NULL)) return false ; int nIdVertT0[3] = { 0, 1, 2} ; int nIdVertT1[3] = { 2, 3, 0} ; if ( pSTM->AddTriangle( nIdVertT0) == SVT_NULL || ( bQuad && pSTM->AddTriangle( nIdVertT1) == SVT_NULL)) return false ; if ( ! pSTM->AdjustTopology()) return false ; // se non ci sono triangoli, non inserisco la trimesh e proseguo senza errore if ( pSTM->GetTriangleCount() == 0) return true ; // inserisco la trimesh nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pSTM)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadArc( bool& bFileEnd) { Point3d ptCen ; double dRadius ; double dStartAng ; double dEndAng ; Vector3d vtExtr = Z_AX ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item dell' arco bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptCen.x) ; break ; case 20 : FromString( m_sCurrItem, ptCen.y) ; break ; case 30 : FromString( m_sCurrItem, ptCen.z) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 40 : FromString( m_sCurrItem, dRadius) ; break ; case 50 : FromString( m_sCurrItem, dStartAng) ; break ; case 51 : FromString( m_sCurrItem, dEndAng) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptCen *= m_dScaleFactor ; dRadius *= m_dScaleFactor ; dThick *= m_dScaleFactor ; // calcolo l'angolo al centro (archi sempre CCW in DXF) double dCentAng ; if ( abs( dEndAng - dStartAng) > ( 360. - EPS_ANG_SMALL)) dCentAng = 360. ; else if ( dEndAng > dStartAng) dCentAng = dEndAng - dStartAng ; else dCentAng = dEndAng - dStartAng + 360. ; // se l'arco è nullo, non lo inserisco ma proseguo senza errore if ( dRadius < EPS_SMALL || abs( dCentAng) < EPS_ANG_SMALL) return true ; // versore iniziale Vector3d vtStart = FromPolar( 1, dStartAng) ; // gestisco eventuale OCS if ( ! AreSameVectorExact( vtExtr, Z_AX)) { Frame3d frOCS ; if ( ! frOCS.Set( ORIG, vtExtr)) return false ; // trasformo il centro e il versore iniziale ptCen.ToGlob( frOCS) ; vtStart.ToGlob( frOCS) ; } // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptCen.ToLoc( m_frGroup) ; vtStart.ToLoc( m_frGroup) ; vtExtr.ToLoc( m_frGroup) ; } // inserisco l'arco nel DB geometrico // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set( ptCen, vtExtr, dRadius, vtStart, dCentAng, 0)) return false ; // eventuale impostazione vettore estrusione e spessore if ( abs( dThick) > EPS_SMALL) { pCrvArc->SetExtrusion( vtExtr) ; pCrvArc->SetThickness( dThick) ; } // inserisco l'arco nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadCircle( bool& bFileEnd) { Point3d ptCen ; double dRadius ; Vector3d vtExtr = Z_AX ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item della circonferenza bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptCen.x) ; break ; case 20 : FromString( m_sCurrItem, ptCen.y) ; break ; case 30 : FromString( m_sCurrItem, ptCen.z) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 40 : FromString( m_sCurrItem, dRadius) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptCen *= m_dScaleFactor ; dRadius *= m_dScaleFactor ; dThick *= m_dScaleFactor ; // se il cerchio è nullo, non lo inserisco ma proseguo senza errore if ( dRadius < EPS_SMALL) return true ; // gestisco eventuale OCS if ( ! AreSameVectorExact( vtExtr, Z_AX)) { Frame3d frOCS ; if ( ! frOCS.Set( ORIG, vtExtr)) return false ; ptCen.ToGlob( frOCS) ; } // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptCen.ToLoc( m_frGroup) ; vtExtr.ToLoc( m_frGroup) ; } // inserisco il cerchio nel DB geometrico // creo il cerchio PtrOwner pCrvArc( CreateCurveArc()) ; if ( IsNull( pCrvArc)) return false ; // setto il cerchio if ( ! pCrvArc->Set( ptCen, vtExtr, dRadius)) return false ; // eventuale impostazione vettore estrusione e spessore if ( abs( dThick) > EPS_SMALL) { pCrvArc->SetExtrusion( vtExtr) ; pCrvArc->SetThickness( dThick) ; } // inserisco il cerchio nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadEllipse( bool& bFileEnd) { Point3d ptCen ; Vector3d vtMajorAx ; double dRatMinMaj = 1 ; double dStartPar = 0 ; double dEndPar = 2 * PIGRECO ; Vector3d vtExtr = Z_AX ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item dell' arco bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptCen.x) ; break ; case 20 : FromString( m_sCurrItem, ptCen.y) ; break ; case 30 : FromString( m_sCurrItem, ptCen.z) ; break ; case 11 : FromString( m_sCurrItem, vtMajorAx.x) ; break ; case 21 : FromString( m_sCurrItem, vtMajorAx.y) ; break ; case 31 : FromString( m_sCurrItem, vtMajorAx.z) ; break ; case 40 : FromString( m_sCurrItem, dRatMinMaj) ; break ; case 41 : FromString( m_sCurrItem, dStartPar) ; break ; case 42 : FromString( m_sCurrItem, dEndPar) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptCen *= m_dScaleFactor ; vtMajorAx *= m_dScaleFactor ; // calcolo il semiasse maggiore double dMajorAx = vtMajorAx.Len() ; vtMajorAx.Normalize() ; // calcolo l'angolo al centro (ellisse sempre CCW in DXF) double dCentAng = ( dEndPar - dStartPar) * RADTODEG ; // se l'arco è nullo, non lo inserisco ma proseguo senza errore if ( dMajorAx < EPS_SMALL || abs( dCentAng) < EPS_ANG_SMALL) return true ; // versore iniziale Vector3d vtStart = vtMajorAx ; vtStart.Rotate( vtExtr, dStartPar * RADTODEG) ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptCen.ToLoc( m_frGroup) ; vtMajorAx.ToLoc( m_frGroup) ; vtStart.ToLoc( m_frGroup) ; vtExtr.ToLoc( m_frGroup) ; } // inserisco l'arco nel DB geometrico // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set( ptCen, vtExtr, dMajorAx, vtStart, dCentAng, 0)) return false ; // inserisco l'arco nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvArc)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale scalatura if ( abs( dRatMinMaj - 1) > EPS_ZERO) { Frame3d frSca ; Vector3d vtY = vtExtr ^ vtMajorAx ; vtY.Normalize() ; if ( frSca.Set( ptCen, vtMajorAx, vtY, vtExtr)) m_pGDB->Scale( nId, frSca, 1, dRatMinMaj, 1) ; } // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadInsert( bool& bFileEnd) { InsertData insData ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; bool bAttribs = false ; // ciclo di lettura degli item del punto bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 2 : insData.sName = m_sCurrItem ; break ; case 8 : insData.sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, insData.ptP.x) ; break ; case 20 : FromString( m_sCurrItem, insData.ptP.y) ; break ; case 30 : FromString( m_sCurrItem, insData.ptP.z) ; break ; case 41 : FromString( m_sCurrItem, insData.vtScale.x) ; break ; case 42 : FromString( m_sCurrItem, insData.vtScale.y) ; break ; case 43 : FromString( m_sCurrItem, insData.vtScale.z) ; break ; case 50 : FromString( m_sCurrItem, insData.dRotAngDeg) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 66 : FromString( m_sCurrItem, bAttribs) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, insData.vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, insData.vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, insData.vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) { if ( bAttribs) return ReadInsertAttribs( false, GDB_ID_NULL, bFileEnd) ; return true ; } // eventuale aggiustamento del nome del blocco per caratteri non ammessi ValidateVal( insData.sName) ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( insData.sLayer) ; // aggiusto per il fattore di scala insData.ptP *= m_dScaleFactor ; // calcolo riferimento di inserimento Frame3d frOCS ; if ( ! AreSameVectorExact( insData.vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, insData.vtExtr)) return false ; } // recupero l'identificativo del blocco int nIdBlock = GetBlockId( insData.sName) ; // se blocco non trovato o non risolto if ( nIdBlock == GDB_ID_NULL || ! m_pGDB->ExistsInfo( nIdBlock, BLKOK_INFO)) { // se sono in lettura blocchi if ( BlockReading()) { // incremento contatore blocchi inseriti ma non risolti ++ m_nNumNotBokInCurrBlock ; // salvo un gruppo con i dati di inserimento int nId = m_pGDB->AddGroup( GDB_ID_NULL, GetGroupId( insData.sLayer), GLOB_FRM) ; if ( nId == GDB_ID_NULL || ! SaveInsertInfo( nId, insData)) return false ; // se previsto, leggo eventuali attributi dipendenti dall'inserimento del blocco if ( bAttribs) return ReadInsertAttribs( true, GetGroupId( insData.sLayer), bFileEnd) ; return true ; } // altrimenti errore else return false ; } // recupero il punto base del blocco per determinare lo spostamento Point3d ptBase ; m_pGDB->GetInfo( nIdBlock, POINT_INFO, ptBase) ; Vector3d vtMove = insData.ptP - ptBase ; // copio tutte le entità del blocco, trasformandole opportunamente PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; if ( IsNull( pIter)) return false ; bool bFound = pIter->GoToFirstInGroup( nIdBlock) ; while ( bFound) { // copio l'entità geometrica IGeoObj* pGeoS = pIter->GetGeoObj() ; if ( pGeoS == nullptr) return false ; PtrOwner pGeo( pGeoS->Clone()) ; if ( IsNull( pGeo)) return false ; // inserisco l'entità nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( insData.sLayer), Release( pGeo)) ; if ( nId == GDB_ID_NULL) return false ; // eseguo le opportune trasformazioni m_pGDB->Scale( nId, Frame3d( ptBase), insData.vtScale.x, insData.vtScale.y, insData.vtScale.z) ; m_pGDB->Rotate( nId, ptBase, Z_AX, insData.dRotAngDeg) ; m_pGDB->Translate( nId, vtMove) ; m_pGDB->GetGeoObj( nId)->ToGlob( frOCS) ; if ( ! BlockReading()) m_pGDB->GetGeoObj( nId)->ToLoc( m_frGroup) ; // recupero il colore if ( ! SetColorForInsert( nId, pIter->GetId(), insData.sLayer)) return false ; // passo alla successiva bFound = pIter->GoToNext() ; } // se previsto, leggo eventuali attributi dipendenti dall'inserimento del blocco if ( bAttribs) return ReadInsertAttribs( true, GetGroupId( insData.sLayer), bFileEnd) ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadInsertAttribs( bool bSave, int nGroupId, bool& bFileEnd) { // Ciclo sugli Attrib, termino con SEQEND o errore bFileEnd = false ; bool bAttribsEnd = false ; string sEntName ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bAttribsEnd, bFileEnd) ; if ( bOkLoc && ! bAttribsEnd) { // se Attrib if ( sEntName == "ATTRIB") { if ( bSave) { if ( ! ReadText( nGroupId, bFileEnd)) bOkLoc = false ; } else { if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; } } // se SeqEnd else if ( sEntName == "SEQEND") { if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; bAttribsEnd = true ; } // altrimenti errore else { UngetItem() ; return false ; } } // gestisco eventuale errore if ( ! bOkLoc) { string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) return false ; } } while( ! bAttribsEnd) ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadLine( bool& bFileEnd) { Point3d ptStart ; Point3d ptEnd ; Vector3d vtExtr = Z_AX ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item della linea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptStart.x) ; break ; case 20 : FromString( m_sCurrItem, ptStart.y) ; break ; case 30 : FromString( m_sCurrItem, ptStart.z) ; break ; case 11 : FromString( m_sCurrItem, ptEnd.x) ; break ; case 21 : FromString( m_sCurrItem, ptEnd.y) ; break ; case 31 : FromString( m_sCurrItem, ptEnd.z) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptStart *= m_dScaleFactor ; ptEnd *= m_dScaleFactor ; dThick *= m_dScaleFactor ; // se la linea è nulla, non la inserisco ma proseguo senza errore if ( AreSamePointEpsilon( ptStart, ptEnd, 2 * EPS_SMALL)) return true ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptStart.ToLoc( m_frGroup) ; ptEnd.ToLoc( m_frGroup) ; } // inserisco la linea nel DB geometrico // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->Set( ptStart, ptEnd)) return false ; // eventuale impostazione vettore estrusione e spessore if ( abs( dThick) > EPS_SMALL) { pCrvLine->SetExtrusion( vtExtr) ; pCrvLine->SetThickness( dThick) ; } // inserisco la linea nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvLine)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadRayXline( bool bIsRay, bool& bFileEnd) { Point3d ptRef ; Vector3d vtDir ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item della Xlinea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptRef.x) ; break ; case 20 : FromString( m_sCurrItem, ptRef.y) ; break ; case 30 : FromString( m_sCurrItem, ptRef.z) ; break ; case 11 : FromString( m_sCurrItem, vtDir.x) ; break ; case 21 : FromString( m_sCurrItem, vtDir.y) ; break ; case 31 : FromString( m_sCurrItem, vtDir.z) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptRef *= m_dScaleFactor ; // se la linea è nulla, non la inserisco ma proseguo senza errore if ( vtDir.IsSmall()) return true ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptRef.ToLoc( m_frGroup) ; vtDir.ToLoc( m_frGroup) ; } // inserisco la linea nel DB geometrico // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; if ( IsNull( pCrvLine)) return false ; // setto la linea Point3d ptStart = ptRef ; if ( ! bIsRay) ptStart -= RAY_LEN * vtDir ; Point3d ptEnd = ptRef + RAY_LEN * vtDir ; if ( ! pCrvLine->Set( ptStart, ptEnd)) return false ; // inserisco la linea nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvLine)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadLwPolyLine( bool& bFileEnd) { PolyArc PA ; Vector3d vtExtr = Z_AX ; double dElevation = 0 ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; int nNumVert = 0 ; int nFlag = 0 ; Point3d ptV ; double dBulge = 0 ; // ciclo di lettura degli item della LwPolyLine bFileEnd = false ; int nContX = 0 ; int nContY = 0 ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptV.x) ; ++ nContX ; if ( nContX == nContY) PA.AddUPoint( 0, ptV, 0) ; break ; case 20 : FromString( m_sCurrItem, ptV.y) ; ++ nContY ; if ( nContX == nContY) PA.AddUPoint( 0, ptV, 0) ; break ; case 38 : FromString( m_sCurrItem, dElevation) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 42 : FromString( m_sCurrItem, dBulge) ; PA.ModifyLastBulge( dBulge) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 70 : FromString( m_sCurrItem, nFlag) ; break ; case 90 : FromString( m_sCurrItem, nNumVert) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // Verifico il numero di vertici if ( ( PA.GetPointNbr() + PA.GetRejectedNbr()) != nNumVert) return false ; if ( PA.GetPointNbr() < 2) return true ; // Se chiusa, aggiungo un punto uguale al primo in coda if ( nFlag & 1) { if ( PA.Close()) ++ nNumVert ; } // aggiusto per il fattore di scala dElevation *= m_dScaleFactor ; dThick *= m_dScaleFactor ; PA.Scale( GLOB_FRM, m_dScaleFactor) ; // aggiusto i punti per elevazione, eventuale OCS e riferimento del gruppo di inserimento Frame3d frOCS ; if ( ! AreSameVectorExact( vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, vtExtr)) return false ; } PA.SetElevation( dElevation) ; PA.ToGlob( frOCS) ; if ( ! BlockReading()) PA.ToLoc( m_frGroup) ; // Creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return false ; // Inserisco i punti con bulge nella curva composita come linee e archi if ( ! pCrvCompo->FromPolyArc( PA)) return false ; // Se non sono state inserite curve, esco senza errore if ( pCrvCompo->GetCurveCount() == 0) return true ; // eventuale impostazione vettore estrusione e spessore if ( abs( dThick) > EPS_SMALL) { pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; } // Inserisco la curva composita nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvCompo)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadPoint( bool& bFileEnd) { Point3d ptP ; Vector3d vtExtr = Z_AX ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item del punto bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; dThick *= m_dScaleFactor ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) ptP.ToLoc( m_frGroup) ; // inserisco l'entità nel DB geometrico PtrOwner pGeoObj ; ; if ( abs( dThick) < EPS_SMALL) { // creo il punto PtrOwner pGeoPnt( CreateGeoPoint3d()) ; if ( IsNull( pGeoPnt)) return false ; // setto il punto if ( ! pGeoPnt->Set( ptP)) return false ; // lo passo all'oggetto geometrico generico pGeoObj.Set( pGeoPnt) ; } else { // creo il vettore con punto base PtrOwner pGeoVect( CreateGeoVector3d()) ; if ( IsNull( pGeoVect)) return false ; // setto il punto if ( ! pGeoVect->Set( dThick * vtExtr, ptP)) return false ; // lo passo all'oggetto geometrico generico pGeoObj.Set( pGeoVect) ; } // inserisco l'entità nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pGeoObj)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadPolyLine( bool& bFileEnd) { Vector3d vtExtr = Z_AX ; double dElevation = 0 ; double dThick = 0 ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; int nFlag = 0 ; int nNumVertM = 0 ; int nNumVertN = 0 ; // ciclo di lettura degli item della PolyLine bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 30 : FromString( m_sCurrItem, dElevation) ; break ; case 39 : FromString( m_sCurrItem, dThick) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 70 : FromString( m_sCurrItem, nFlag) ; break ; case 71 : FromString( m_sCurrItem, nNumVertM) ; break ; case 72 : FromString( m_sCurrItem, nNumVertN) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto bool bToSave = true ; if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) bToSave = false ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // Se Polygon Mesh if ( ( nFlag & 16) != 0) return CompletePolygonMesh( sLayer, nColor, nFlag, bToSave, dElevation, vtExtr, nNumVertM, nNumVertN, bFileEnd) ; // se Polyface Mesh else if ( ( nFlag & 64) != 0) return CompletePolyfaceMesh( sLayer, nColor, nFlag, bToSave, dElevation, vtExtr, bFileEnd) ; // altrimenti PolyLine vera e propria else return CompletePolyLine( sLayer, nColor, nFlag, bToSave, dElevation, dThick, vtExtr, bFileEnd) ; } //---------------------------------------------------------------------------- bool ImportDxf::CompletePolyLine( const string& sLayer, int nColor, int nFlag, bool bToSave, double dElevation, double dThick, const Vector3d& vtExtr, bool& bFileEnd) { int nNumVert = 0 ; PolyArc PA ; Point3d ptV ; double dBulge = 0 ; // Ciclo sui Vertex, termino con SEQEND o errore bFileEnd = false ; bool bIs3d = (( nFlag & 8) != 0) ; bool bPolyEnd = false ; string sEntName ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bPolyEnd, bFileEnd) ; if ( bOkLoc && ! bPolyEnd) { // se Vertex if ( sEntName == "VERTEX") { if ( ! ReadPolyLineVertex( ptV, dBulge, bFileEnd)) bOkLoc = false ; // se polilinea 3d non sono ammessi archi (bulge = 0) if ( bIs3d) dBulge = 0 ; // altrimenti polilinea 2d quindi z = 0 else ptV.z = 0 ; PA.AddUPoint( 0, ptV, dBulge) ; nNumVert ++ ; } // se SeqEnd else if ( sEntName == "SEQEND") { if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; bPolyEnd = true ; } // altrimenti errore else { UngetItem() ; return false ; } } // gestisco eventuale errore if ( ! bOkLoc) { string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) return false ; } } while( ! bPolyEnd) ; // se entità da saltare, esco if ( ! bToSave) return true ; // Verifico il numero di vertici if ( ( PA.GetPointNbr() + PA.GetRejectedNbr()) != nNumVert) return false ; if ( PA.GetPointNbr() < 2) return true ; // Se chiusa, aggiungo un punto uguale al primo in coda if ( nFlag & 1) { if ( PA.Close()) ++ nNumVert ; } // aggiusto per il fattore di scala dElevation *= m_dScaleFactor ; dThick *= m_dScaleFactor ; PA.Scale( GLOB_FRM, m_dScaleFactor) ; // aggiusto i punti per elevazione, eventuale OCS e riferimento del gruppo di inserimento Frame3d frOCS ; if ( ! bIs3d && ! AreSameVectorExact( vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, vtExtr)) return false ; } PA.AddElevation( dElevation) ; PA.ToGlob( frOCS) ; if ( ! BlockReading()) PA.ToLoc( m_frGroup) ; // Creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return false ; // Inserisco i punti con bulge nella curva composita come linee e archi if ( ! pCrvCompo->FromPolyArc( PA)) return false ; // Se non sono state inserite curve, esco senza errore if ( pCrvCompo->GetCurveCount() == 0) return true ; // eventuale impostazione vettore estrusione e spessore if ( abs( dThick) > EPS_SMALL) { pCrvCompo->SetExtrusion( vtExtr) ; pCrvCompo->SetThickness( dThick) ; } // Inserisco la curva composita nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrvCompo)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadPolyLineVertex( Point3d& ptP, double& dBulge, bool& bFileEnd) { // inizializzo il punto con bulge ptP.Set( 0, 0, 0) ; dBulge = 0 ; // ciclo di lettura degli item della linea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 42 : FromString( m_sCurrItem, dBulge) ; break ; } } while ( nCode != 0) ; UngetItem() ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::CompletePolygonMesh( const string& sLayer, int nColor, int nFlag, bool bToSave, double dElevation, const Vector3d& vtExtr, int nNumVertM, int nNumVertN, bool& bFileEnd) { // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; if ( IsNull( pSTM)) return false ; // la inizializzo int nNumVert = nNumVertM * nNumVertN ; bool bClosedM = (( nFlag & 1) != 0) ; bool bClosedN = (( nFlag & 32) != 0) ; int nNumTria = 0 ; if ( bClosedM && bClosedN) nNumTria = 2 * nNumVertM * nNumVertN ; else if ( bClosedM) nNumTria = 2 * nNumVertM * ( nNumVertN - 1) ; else if ( bClosedN) nNumTria = 2 * ( nNumVertM - 1) * nNumVertN ; else nNumTria = 2 * ( nNumVertM - 1) * ( nNumVertN - 1) ; if ( ! pSTM->Init( nNumVert, nNumTria)) return false ; // determino eventuale OCS Frame3d frOCS ; if ( ! ( nFlag & 8) && ! AreSameVectorExact( vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, vtExtr)) return false ; } // Ciclo sui Vertex, termino con SEQEND o errore bFileEnd = false ; bool bPolyEnd = false ; int nReadVert = 0 ; string sEntName ; Point3d ptP ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bPolyEnd, bFileEnd) ; if ( bOkLoc && ! bPolyEnd) { // se Vertex if ( sEntName == "VERTEX") { // leggo il punto if ( ! ReadPolygonMeshVertex( ptP, bFileEnd)) bOkLoc = false ; // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; // sistemazioni per elevazione, eventuale OCS e riferimento del gruppo di inserimento ptP.z += dElevation ; ptP.ToGlob( frOCS) ; if ( ! BlockReading()) ptP.ToLoc( m_frGroup) ; // inserimento del vertice nella trimesh if ( pSTM->AddVertex( ptP) == SVT_NULL) return false ; nReadVert ++ ; } // se SeqEnd else if ( sEntName == "SEQEND") { if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; bPolyEnd = true ; } // altrimenti errore else { UngetItem() ; return false ; } } // gestisco eventuale errore if ( ! bOkLoc) { string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) return false ; } } while( ! bPolyEnd) ; // Se entità da saltare, esco if ( ! bToSave) return true ; // Verifico il numero di vertici if ( nNumVert != nReadVert) return false ; // Definisco i triangoli int nMmax = ( bClosedM ? nNumVertM : ( nNumVertM - 1)) ; int nNmax = ( bClosedN ? nNumVertN : ( nNumVertN - 1)) ; int nIdVT1[3] ; int nIdVT2[3] ; for ( int i = 0 ; i < nMmax ; ++ i) { for ( int j = 0 ; j < nNmax ; ++ j) { // primo triangolo nIdVT1[0] = i * nNumVertN + j ; nIdVT1[1] = (( j < nNumVertN - 1) ? ( nIdVT1[0] + 1) : ( i * nNumVertN)) ; nIdVT1[2] = (( i < nNumVertM - 1) ? ( nIdVT1[1] + nNumVertN) : ( j + 1)) ; // secondo triangolo nIdVT2[0] = nIdVT1[0] ; nIdVT2[1] = nIdVT1[2] ; nIdVT2[2] = (( i < nNumVertM - 1) ? ( nIdVT2[0] + nNumVertN) : j) ; // inserisco i triangoli nella trimesh if ( pSTM->AddTriangle( nIdVT1) == SVT_NULL || pSTM->AddTriangle( nIdVT2) == SVT_NULL) return false ; } } // valido la superficie e calcolo le adiacenze if ( ! pSTM->AdjustTopology()) return false ; // se non ci sono triangoli, non inserisco la trimesh e proseguo senza errore if ( pSTM->GetTriangleCount() == 0) return true ; // inserisco la trimesh nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pSTM)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadPolygonMeshVertex( Point3d& ptP, bool& bFileEnd) { // inizializzo il punto ptP.Set( 0, 0, 0) ; // ciclo di lettura degli item della linea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::CompletePolyfaceMesh( const string& sLayer, int nColor, int nFlag, bool bToSave, double dElevation, const Vector3d& vtExtr, bool& bFileEnd) { // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; if ( IsNull( pSTM)) return false ; // la inizializzo if ( ! pSTM->Init( 3, 1)) return false ; // determino eventuale OCS Frame3d frOCS ; if ( ! ( nFlag & 8) && ! AreSameVectorExact( vtExtr, Z_AX)) { if ( ! frOCS.Set( ORIG, vtExtr)) return false ; } // Ciclo sui Vertex, termino con SEQEND o errore bFileEnd = false ; bool bPolyEnd = false ; string sEntName ; int nStat ; Point3d ptP ; int nIdVT1[3], nIdVT2[3] ; do { // leggo intestazione entità, per avere il tipo bool bOkLoc = GetEntityName( sEntName, bPolyEnd, bFileEnd) ; if ( bOkLoc && ! bPolyEnd) { // se Vertex if ( sEntName == "VERTEX") { // leggo il punto if ( ! ReadPolyfaceMeshVertex( nStat, ptP, nIdVT1, nIdVT2, bFileEnd)) bOkLoc = false ; switch ( nStat) { case 0 : // è un vertice // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; // sistemazioni per elevazione, eventuale OCS e riferimento del gruppo di inserimento ptP.z += dElevation ; ptP.ToGlob( frOCS) ; if ( ! BlockReading()) ptP.ToLoc( m_frGroup) ; // inserimento del vertice nella trimesh if ( pSTM->AddVertex( ptP) == SVT_NULL) return false ; break ; case 1 : // è un triangolo // inserimento del triangolo nella trimesh if ( pSTM->AddTriangle( nIdVT1) == SVT_NULL) return false ; break ; case 2 : // sono due triangoli // inserimento dei triangoli nella trimesh if ( pSTM->AddTriangle( nIdVT1) == SVT_NULL || pSTM->AddTriangle( nIdVT2) == SVT_NULL) return false ; } } // se SeqEnd else if ( sEntName == "SEQEND") { if ( ! SkipEntity( bFileEnd)) bOkLoc = false ; bPolyEnd = true ; } // altrimenti errore else { UngetItem() ; return false ; } } // gestisco eventuale errore if ( ! bOkLoc) { string sOut = "ImportDxf : Error on line " + ToString( m_theScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEExLogger(), sOut.c_str()) return false ; } } while( ! bPolyEnd) ; // se entità da saltare, esco if ( ! bToSave) return true ; // valido la superficie e calcolo le adiacenze if ( ! pSTM->AdjustTopology()) return false ; // se non ci sono triangoli, non inserisco la trimesh e proseguo senza errore if ( pSTM->GetTriangleCount() == 0) return true ; // inserisco la trimesh nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pSTM)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadPolyfaceMeshVertex( int& nStat, Point3d& ptP, int nIdVT1[3], int nIdVT2[3], bool& bFileEnd) { // inizializzo il punto e gli indici ptP.Set( 0, 0, 0) ; nIdVT1[0] = - 1 ; nIdVT1[1] = - 1 ; nIdVT1[2] = - 1 ; nIdVT2[0] = - 1 ; nIdVT2[1] = - 1 ; nIdVT2[2] = - 1 ; // ciclo di lettura degli item della linea bFileEnd = false ; int nFlag = 0 ; int nVal = 0 ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 70 : FromString( m_sCurrItem, nFlag) ; break ; case 71 : FromString( m_sCurrItem, nVal) ; nIdVT1[0] = abs( nVal) - 1 ; // in DXF indici 1 based, in STM 0 based break ; // (negativi indicano edge nascosto) case 72 : FromString( m_sCurrItem, nVal) ; nIdVT1[1] = abs( nVal) - 1 ; break ; case 73 : FromString( m_sCurrItem, nVal) ; nIdVT1[2] = abs( nVal) - 1 ; break ; case 74 : FromString( m_sCurrItem, nVal) ; nIdVT2[2] = abs( nVal) - 1 ; break ; } } while ( nCode != 0) ; UngetItem() ; // se è un vertice if ( ( nFlag & 128) != 0 && ( nFlag & 64) != 0) nStat = 0 ; // se è una faccia (formata da uno o due triangoli) else if ( ( nFlag & 128) != 0) { // se non c'è il secondo triangolo if ( nIdVT2[2] == - 1) nStat = 1 ; else { nStat = 2 ; nIdVT2[0] = nIdVT1[0] ; nIdVT2[1] = nIdVT1[2] ; } } // altrimenti nulla else nStat = - 1 ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadSolid( bool& bFileEnd) { Point3d ptP0 ; Point3d ptP1 ; Point3d ptP2 ; Point3d ptP3 ; Vector3d vtExtr = Z_AX ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item di SOLID bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP0.x) ; break ; case 20 : FromString( m_sCurrItem, ptP0.y) ; break ; case 30 : FromString( m_sCurrItem, ptP0.z) ; break ; case 11 : FromString( m_sCurrItem, ptP1.x) ; break ; case 21 : FromString( m_sCurrItem, ptP1.y) ; break ; case 31 : FromString( m_sCurrItem, ptP1.z) ; break ; case 12 : FromString( m_sCurrItem, ptP2.x) ; break ; case 22 : FromString( m_sCurrItem, ptP2.y) ; break ; case 32 : FromString( m_sCurrItem, ptP2.z) ; break ; case 13 : FromString( m_sCurrItem, ptP3.x) ; break ; case 23 : FromString( m_sCurrItem, ptP3.y) ; break ; case 33 : FromString( m_sCurrItem, ptP3.z) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // aggiusto per il fattore di scala ptP0 *= m_dScaleFactor ; ptP1 *= m_dScaleFactor ; ptP2 *= m_dScaleFactor ; ptP3 *= m_dScaleFactor ; // gestisco eventuale OCS if ( ! AreSameVectorExact( vtExtr, Z_AX)) { Frame3d frOCS ; if ( ! frOCS.Set( ORIG, vtExtr)) return false ; // trasformo i punti ptP0.ToGlob( frOCS) ; ptP1.ToGlob( frOCS) ; ptP2.ToGlob( frOCS) ; ptP3.ToGlob( frOCS) ; } // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptP0.ToLoc( m_frGroup) ; ptP1.ToLoc( m_frGroup) ; ptP2.ToLoc( m_frGroup) ; ptP3.ToLoc( m_frGroup) ; } // verifico se 3 o 4 punti bool bQuad = ! AreSamePointApprox( ptP2, ptP3) ; // inserisco la faccia nel DB geometrico // creo la trimesh PtrOwner pSTM( CreateSurfTriMesh()) ; if ( IsNull( pSTM)) return false ; // costruisco la geometria della trimesh if ( ! pSTM->Init( 4, 2)) return false ; if ( pSTM->AddVertex( ptP0) == SVT_NULL || pSTM->AddVertex( ptP1) == SVT_NULL || pSTM->AddVertex( ptP2) == SVT_NULL || ( bQuad && pSTM->AddVertex( ptP3) == SVT_NULL)) return false ; int nIdVertT0[3] = { 0, 1, 2} ; int nIdT0 = pSTM->AddTriangle( nIdVertT0) ; int nIdVertT1[3] = { 2, 1, 3} ; int nIdT1 = ( bQuad ? pSTM->AddTriangle( nIdVertT1) : SVT_DEL) ; if ( nIdT0 == SVT_NULL || nIdT1 == SVT_NULL) return false ; if ( nIdT0 == SVT_DEL && nIdT1 == SVT_DEL) return true ; if ( ! pSTM->AdjustTopology()) return false ; // se non ci sono triangoli, non inserisco la trimesh e proseguo senza errore if ( pSTM->GetTriangleCount() == 0) return true ; // inserisco la trimesh nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pSTM)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadSpline( bool& bFileEnd) { CNurbsData cnData ; cnData.vU.reserve( 16) ; cnData.vCP.reserve( 16) ; cnData.vW.reserve( 16) ; PNTVECTOR vIntPnt ; double dTemp ; Point3d ptP ; Point3d ptInt ; string sLayer ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; int nKnotNbr = 0 ; int nCPntNbr = 0 ; int nIPntNbr = 0 ; int nFlag = 0 ; // ciclo di lettura degli item della linea bFileEnd = false ; int nContX = 0 ; int nContY = 0 ; int nContZ = 0 ; int nIntX = 0 ; int nIntY = 0 ; int nIntZ = 0 ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP.x) ; ++ nContX ; if ( nContX == nContY && nContY == nContZ) cnData.vCP.push_back( ptP) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; ++ nContY ; if ( nContX == nContY && nContY == nContZ) cnData.vCP.push_back( ptP) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; ++ nContZ ; if ( nContX == nContY && nContY == nContZ) cnData.vCP.push_back( ptP) ; break ; case 11 : FromString( m_sCurrItem, ptInt.x) ; ++ nIntX ; if ( nIntX == nIntY && nIntY == nIntZ) vIntPnt.push_back( ptInt) ; break ; case 21 : FromString( m_sCurrItem, ptInt.y) ; ++ nIntY ; if ( nIntX == nIntY && nIntY == nIntZ) vIntPnt.push_back( ptInt) ; break ; case 31 : FromString( m_sCurrItem, ptInt.z) ; ++ nIntZ ; if ( nIntX == nIntY && nIntY == nIntZ) vIntPnt.push_back( ptInt) ; break ; case 40 : FromString( m_sCurrItem, dTemp) ; cnData.vU.push_back( dTemp) ; break; case 41 : FromString( m_sCurrItem, dTemp) ; cnData.vW.push_back( dTemp) ; break; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 70 : FromString( m_sCurrItem, nFlag) ; break ; case 71 : FromString( m_sCurrItem, cnData.nDeg) ; break ; case 72 : FromString( m_sCurrItem, nKnotNbr) ; break ; case 73 : FromString( m_sCurrItem, nCPntNbr) ; break ; case 74 : FromString( m_sCurrItem, nIPntNbr) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // se spline con soli punti di interpolazione if ( ( cnData.vU.size() == 0 || cnData.vCP.size() == 0) && vIntPnt.size() == nIPntNbr && nIPntNbr >= 2) { // se curva chiusa e l'ultimo punto non uguaglia il primo, copio il primo in coda if ( (( nFlag & SPL_CLOSED) != 0) && ! AreSamePointApprox( vIntPnt.front(), vIntPnt.back())) vIntPnt.push_back( vIntPnt.front()) ; // aggiusto per il fattore di scala for ( int i = 0 ; i < nIPntNbr ; ++i) vIntPnt[i] *= m_dScaleFactor ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { for ( int i = 0 ; i < nIPntNbr ; ++i) vIntPnt[i].ToLoc( m_frGroup) ; } // calcolo la curva interpolata CurveByInterp crvByInterp ; for ( int i = 0 ; i < int( vIntPnt.size()) ; ++ i) crvByInterp.AddPoint( vIntPnt[i]) ; PtrOwner pCrv( crvByInterp.GetCurve( CurveByInterp::BESSEL, CurveByInterp::CUBIC_BEZIERS)) ; if ( IsNull( pCrv)) return false ; // Inserisco la curva nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrv)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } // assegnazione flag cnData.bRat = (( nFlag & SPL_RATIONAL) != 0) ; cnData.bPeriodic = (( nFlag & SPL_PERIODIC) != 0 && ( nKnotNbr != nCPntNbr + cnData.nDeg + 1)) ; cnData.bClosed = (( nFlag & SPL_CLOSED) != 0) ; cnData.bClamped = true ; cnData.bExtraKnotes = true ; // Verifico il numero di nodi if ( cnData.vU.size() != nKnotNbr || nKnotNbr < 4) return false ; // Verifico il numero di punti di controllo if ( cnData.vCP.size() != nCPntNbr || nCPntNbr < 2) return false ; // Verifico il numero dei pesi if ( cnData.bRat && cnData.vW.size() != nCPntNbr) return false ; // aggiusto per il fattore di scala for ( int i = 0 ; i < nCPntNbr ; ++i) cnData.vCP[i] *= m_dScaleFactor ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { for ( int i = 0 ; i < nCPntNbr ; ++i) cnData.vCP[i].ToLoc( m_frGroup) ; } // rendo canonica la rappresentazione della curva Nurbs if ( ! NurbsCurveCanonicalize( cnData)) return false ; // creo la curva equivalente alla Nurbs PtrOwner pCrv( NurbsToBezierCurve( cnData)) ; if ( IsNull( pCrv)) return false ; if ( ! pCrv->IsValid()) return true ; // Inserisco la curva composita nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pCrv)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadText( int nGroupId, bool& bFileEnd) { Point3d ptP ; Vector3d vtExtr = Z_AX ; string sText ; string sLayer ; string sStyle = "STANDARD" ; double dH ; double dAngDeg = 0 ; double dRat = 1 ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item della linea bFileEnd = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // eventuale gestione switch ( nCode) { case 1 : sText = m_sCurrItem ; break ; case 7 : sStyle = m_sCurrItem ; break ; case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 40 : FromString( m_sCurrItem, dH) ; break ; case 41 : FromString( m_sCurrItem, dRat) ; break ; case 50 : FromString( m_sCurrItem, dAngDeg) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // eventuale aggiustamento dello stile per caratteri non ammessi e trasformazione in maiuscolo ValidateVal( sStyle) ; ToUpper( sStyle) ; // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; dH *= m_dScaleFactor ; // versore iniziale Vector3d vtDir = FromPolar( 1, dAngDeg) ; // gestisco eventuale OCS if ( ! AreSameVectorExact( vtExtr, Z_AX)) { Frame3d frOCS ; if ( ! frOCS.Set( ORIG, vtExtr)) return false ; // trasformo il centro e il versore iniziale ptP.ToGlob( frOCS) ; vtDir.ToGlob( frOCS) ; } // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptP.ToLoc( m_frGroup) ; vtExtr.ToLoc( m_frGroup) ; vtDir.ToLoc( m_frGroup) ; } // aggiusto i caratteri AdjustText( sText) ; // se testo è nullo, non lo inserisco ma proseguo senza errore if ( sText.empty()) return true ; // recupero lo stile string sFont ; double dHStyle ; double dRatStyle ; GetStyleData( sStyle, sFont, dHStyle, dRatStyle) ; if ( abs( dH) < EPS_SMALL) dH = dHStyle ; if ( abs( dRat) < EPS_SMALL) dRat = dRatStyle ; // il punto di inserimento è sempre ETXT_IPBL // inserisco il testo nel DB geometrico // creo il testo PtrOwner pTXT( CreateExtText()) ; if ( IsNull( pTXT)) return false ; // setto il testo if ( ! pTXT->Set( ptP, vtExtr, vtDir, sText, sFont, 400, false, dH, dRat, 0, ETXT_IPBL)) return false ; // inserisco il testo nel DB if ( nGroupId == GDB_ID_NULL) nGroupId = GetGroupId( sLayer) ; int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, nGroupId, Release( pTXT)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::AdjustText( string& sText) { // se non è testo UTF-8, tento di convertirlo secondo codepage dichiarata nel DXF if ( ! IsTextUtf8( sText.c_str())) { sText = LPSTR( WtoA( LPWSTR( AtoW( sText.c_str(), m_nCodePage)))) ; } // converto la codifica Unicode di AutoCad ( "\\U+NNNN") size_t nPos ; while ( ( nPos = sText.find( "\\U+")) != string::npos) { string sCode = (( sText.size() > nPos + 3) ? sText.substr( nPos+3, 4) : "") ; unsigned int nCode = 127 ; sscanf_s( sCode.c_str(), "%x", &nCode) ; // converto diametro in O maiuscolo barrato if ( nCode == 8709) nCode = 216 ; string sVal ; if ( ! SetCodePoint( nCode, sVal)) sVal = "\7F" ; // carattere di errore 127 ReplaceString( sText, "\\U+" + sCode, sVal) ; } // trasformazione caratteri di controllo (per ora solo alcuni) ReplaceString( sText, "^I", " ") ; ReplaceString( sText, "^J", " ") ; ReplaceString( sText, "^ ", "^") ; // se non ci sono "%%" posso uscire if ( sText.find( "%%") == string::npos) return true ; // salvo codifica di singoli '%' ReplaceString( sText, "%%%", "§§") ; // elimino segnalazioni overscore e underscore ReplaceString( sText, "%%o", "") ; ReplaceString( sText, "%%O", "") ; ReplaceString( sText, "%%u", "") ; ReplaceString( sText, "%%U", "") ; // per gradi, più o meno e diametro ReplaceString( sText, "%%d", LPSTR( WtoA( L"°"))) ; ReplaceString( sText, "%%D", LPSTR( WtoA( L"°"))) ; ReplaceString( sText, "%%p", LPSTR( WtoA( L"±"))) ; ReplaceString( sText, "%%P", LPSTR( WtoA( L"±"))) ; ReplaceString( sText, "%%c", LPSTR( WtoA( L"Ø"))) ; ReplaceString( sText, "%%C", LPSTR( WtoA( L"Ø"))) ; // eventuali "%%" rimasti vanno eliminati ReplaceString( sText, "%%", "") ; // ripristino singoli '%' ReplaceString( sText, "§§", "%") ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::ReadMText( bool& bFileEnd) { Point3d ptP ; Vector3d vtExtr = Z_AX ; Vector3d vtDirG = V_NULL ; string sText ; string sLayer ; string sStyle = "STANDARD" ; double dH ; double dTextMaxWidth = 0 ; double dAngRad = 0 ; int nInsPos = ETXT_IPBL ; int nSpace = ENT_MODELSPACE ; int nColor = COL_BYLAYER ; int nHide = ENT_SHOW ; // ciclo di lettura degli item della linea bFileEnd = false ; bool bEmbObj = false ; int nCode = CODE_NULL ; do { // leggo un Item nCode = ReadNextItem() ; if ( nCode == CODE_NULL) { bFileEnd = true ; return false ; } // se Embedded Obj da saltare if ( bEmbObj) continue ; // eventuale gestione switch ( nCode) { case 1 : sText += m_sCurrItem ; break ; case 3 : sText += m_sCurrItem ; break ; case 7 : sStyle = m_sCurrItem ; break ; case 8 : sLayer = m_sCurrItem ; break ; case 10 : FromString( m_sCurrItem, ptP.x) ; break ; case 20 : FromString( m_sCurrItem, ptP.y) ; break ; case 30 : FromString( m_sCurrItem, ptP.z) ; break ; case 11 : FromString( m_sCurrItem, vtDirG.x) ; break ; case 21 : FromString( m_sCurrItem, vtDirG.y) ; break ; case 31 : FromString( m_sCurrItem, vtDirG.z) ; break ; case 40 : FromString( m_sCurrItem, dH) ; break ; case 41 : FromString( m_sCurrItem, dTextMaxWidth) ; break ; case 50 : FromString( m_sCurrItem, dAngRad) ; break ; case 60 : FromString( m_sCurrItem, nSpace) ; break ; case 62 : FromString( m_sCurrItem, nColor) ; break ; case 67 : FromString( m_sCurrItem, nHide) ; break ; case 71 : FromString( m_sCurrItem, nInsPos) ; break ; case 210 : FromString( m_sCurrItem, vtExtr.x) ; break ; case 220 : FromString( m_sCurrItem, vtExtr.y) ; break ; case 230 : FromString( m_sCurrItem, vtExtr.z) ; break ; case 101 : // per saltare gli Embedded Objects di DXF 2018 (sembra siano solo negli MTEXT) bEmbObj = true ; break ; } } while ( nCode != 0) ; UngetItem() ; // se entità in paperspace o nascosta, la salto if ( nSpace == ENT_PAPERSPACE || nHide == ENT_HIDE) return true ; // eventuale aggiustamento del nome del layer per caratteri non ammessi ValidateVal( sLayer) ; // eventuale aggiustamento dello stile per caratteri non ammessi e trasformazione in maiuscolo ValidateVal( sStyle) ; ToUpper( sStyle) ; // aggiusto per il fattore di scala ptP *= m_dScaleFactor ; dH *= m_dScaleFactor ; // versore iniziale (da angolo) Vector3d vtDir = FromPolar( 1, dAngRad * RADTODEG) ; // gestisco eventuale OCS if ( ! AreSameVectorExact( vtExtr, Z_AX)) { Frame3d frOCS ; if ( ! frOCS.Set( ORIG, vtExtr)) return false ; // il punto è già in globale // trasformo solo il versore iniziale dato come angolo vtDir.ToGlob( frOCS) ; } // scelgo direzione if ( vtDirG.IsSmall()) vtDirG = vtDir ; // gestisco il riferimento del gruppo di inserimento if ( ! BlockReading()) { ptP.ToLoc( m_frGroup) ; vtExtr.ToLoc( m_frGroup) ; vtDirG.ToLoc( m_frGroup) ; } // recupero lo stile ( utilizzo font e aspect-ratio) string sFont ; double dHStyle ; double dRatStyle ; GetStyleData( sStyle, sFont, dHStyle, dRatStyle) ; if ( dRatStyle < EPS_SMALL) dRatStyle = 1 ; // aggiusto i caratteri AdjustMText( sText, dTextMaxWidth, dH * dRatStyle) ; // se testo è nullo, non lo inserisco ma proseguo senza errore if ( sText.empty()) return true ; // inserisco il testo nel DB geometrico // creo il testo PtrOwner pTXT( CreateExtText()) ; if ( IsNull( pTXT)) return false ; // setto il testo if ( ! pTXT->Set( ptP, vtExtr, vtDirG, sText, sFont, 400, false, dH, dRatStyle, 0, nInsPos)) return false ; // inserisco il testo nel DB int nId = m_pGDB->AddGeoObj( GDB_ID_NULL, GetGroupId( sLayer), Release( pTXT)) ; if ( nId == GDB_ID_NULL) return false ; // eventuale assegnazione del colore if ( ! SetColor( nId, nColor, sLayer)) return false ; return true ; } //---------------------------------------------------------------------------- bool ImportDxf::AdjustMText( string& sText, double dTextMaxWidth, double dW) { // sostituzioni valide anche per testi semplici if ( ! AdjustText( sText)) return false ; // gestione "\\\\" ReplaceString( sText, "\\\\", "çç") ; // elimino \L \k sText = regex_replace( sText, regex( "\\\\[LlOoKk]"), string( "")) ; // elimino \p...; \T...; sText = regex_replace( sText, regex( "\\\\[pQHWFfACT][^;]*;"), string( "")) ; // trasformo \Sxxx; in xxx sText = regex_replace( sText, regex( "\\\\[S]([^;]*);"), string( "$1")) ; // traformo "\~" in ' ' ReplaceString( sText, "\\~", " ") ; // trasformo "\P" in "\n" ReplaceString( sText, "\\P", "\n") ; // cancello '{' e '}' trasformo "\{" in '{' e "\}" in'}' ReplaceString( sText, "\\{", "§§") ; ReplaceString( sText, "{", "") ; ReplaceString( sText, "§§", "{") ; ReplaceString( sText, "\\}", "§§") ; ReplaceString( sText, "}", "") ; ReplaceString( sText, "§§", "}") ; // trasformo "\\" in '\' ReplaceString( sText, "çç", "\\") ; // se richiesto controllo lunghezza massima if ( dTextMaxWidth > EPS_SMALL) { // ATT : NON SONO GESTITI I CODICI UNICODE !!! // coefficiente empirico che in generale migliora l'adattamento const double COEFF_LARGH = 1.2 ; // gestione max lunghezza riga di testo size_t nLastSp = - 1 ; double dCurrWidth = 0 ; for ( size_t i = 0 ; i < sText.size() ; ++ i) { // posso dividere solo sugli spazi if ( sText[i] == ' ') nLastSp = i ; // se c'è già un a capo if ( sText[i] == '\n') { dCurrWidth = 0 ; nLastSp = - 1 ; } // se supera il limite else if ( dCurrWidth > COEFF_LARGH * dTextMaxWidth) { // se nella riga c'è già uno spazio if ( nLastSp != - 1) { sText.replace( nLastSp, 1, ETXT_LINEBREAK) ; dCurrWidth = ( i - nLastSp) * dW ; i += ETXT_LINEBREAK.size() - 1 ; nLastSp = - 1 ; } } // incremento la larghezza corrente else // larghezza con compensazione empirica if ( sText[i] == ' ' || sText[i] == '"') dCurrWidth += 0.6 * dW ; else if ( sText[i] == 'i' || sText[i] == 'l' || sText[i] == '!' || sText[i] == '.' || sText[i] == ',' || sText[i] == ':' || sText[i] == ';' || sText[i] == '\'') dCurrWidth += 0.3 * dW ; else dCurrWidth += dW ; } } // sostituzione finale di eventuali line break da utente ReplaceString( sText, "\n", ETXT_LINEBREAK) ; return true ; }