Line data Source code
1 : /******************************************************************************* 2 : * Project: libopencad 3 : * Purpose: OpenSource CAD formats support library 4 : * Author: Alexandr Borzykh, mush3d at gmail.com 5 : * Author: Dmitry Baryshnikov, bishop.dev@gmail.com 6 : * Language: C++ 7 : ******************************************************************************* 8 : * The MIT License (MIT) 9 : * 10 : * Copyright (c) 2016 Alexandr Borzykh 11 : * Copyright (c) 2016-2018 NextGIS, <info@nextgis.com> 12 : * 13 : * SPDX-License-Identifier: MIT 14 : *******************************************************************************/ 15 : #include "cadtables.h" 16 : #include "opencad_api.h" 17 : 18 : #include <cassert> 19 : #include <iostream> 20 : #include <memory> 21 : #include <set> 22 : 23 : using namespace std; 24 : 25 8 : CADTables::CADTables() 26 : { 27 8 : } 28 : 29 144 : void CADTables::AddTable( TableType eType, const CADHandle& hHandle ) 30 : { 31 144 : mapTables[eType] = hHandle; 32 144 : } 33 : 34 8 : int CADTables::ReadTable( CADFile * const pCADFile, CADTables::TableType eType ) 35 : { 36 8 : auto iterAskedTable = mapTables.find( eType ); 37 8 : if( iterAskedTable == mapTables.end() ) 38 0 : return CADErrorCodes::TABLE_READ_FAILED; 39 : 40 : // TODO: read different tables 41 8 : switch( eType ) 42 : { 43 8 : case LayersTable: 44 8 : return ReadLayersTable( pCADFile, iterAskedTable->second.getAsLong() ); 45 0 : default: 46 0 : std::cerr << "Unsupported table."; 47 0 : break; 48 : } 49 : 50 0 : return CADErrorCodes::SUCCESS; 51 : } 52 : 53 26 : size_t CADTables::GetLayerCount() const 54 : { 55 26 : return aLayers.size(); 56 : } 57 : 58 27 : CADLayer& CADTables::GetLayer( size_t iIndex ) 59 : { 60 27 : return aLayers[iIndex]; 61 : } 62 : 63 8 : CADHandle CADTables::GetTableHandle( enum TableType eType ) 64 : { 65 : // FIXME: need to add try/catch to prevent crashes on not found elem. 66 8 : return mapTables[eType]; 67 : } 68 : 69 8 : int CADTables::ReadLayersTable( CADFile * const pCADFile, long dLayerControlHandle ) 70 : { 71 : // Reading Layer Control obj, and aLayers. 72 16 : unique_ptr<CADObject> pCADObject( pCADFile->GetObject( dLayerControlHandle ) ); 73 : 74 : CADLayerControlObject* spLayerControl = 75 8 : dynamic_cast<CADLayerControlObject *>(pCADObject.get()); 76 8 : if( !spLayerControl ) 77 : { 78 0 : return CADErrorCodes::TABLE_READ_FAILED; 79 : } 80 : 81 18 : for( size_t i = 0; i < spLayerControl->hLayers.size(); ++i ) 82 : { 83 10 : if( !spLayerControl->hLayers[i].isNull() ) 84 : { 85 20 : CADLayer oCADLayer( pCADFile ); 86 : 87 : // Init CADLayer from CADLayerObject properties 88 10 : CADObject* pCADLayerObject = pCADFile->GetObject( 89 10 : spLayerControl->hLayers[i].getAsLong() ); 90 : unique_ptr<CADLayerObject> oCADLayerObj( 91 20 : dynamic_cast<CADLayerObject *>( pCADLayerObject ) ); 92 : 93 10 : if(oCADLayerObj) 94 : { 95 10 : oCADLayer.setName( oCADLayerObj->sLayerName ); 96 10 : oCADLayer.setFrozen( oCADLayerObj->bFrozen ); 97 10 : oCADLayer.setOn( oCADLayerObj->bOn ); 98 10 : oCADLayer.setFrozenByDefault( oCADLayerObj->bFrozenInNewVPORT ); 99 10 : oCADLayer.setLocked( oCADLayerObj->bLocked ); 100 10 : oCADLayer.setLineWeight( oCADLayerObj->dLineWeight ); 101 10 : oCADLayer.setColor( oCADLayerObj->dCMColor ); 102 10 : oCADLayer.setId( aLayers.size() + 1 ); 103 10 : oCADLayer.setHandle( oCADLayerObj->hObjectHandle.getAsLong() ); 104 : 105 10 : aLayers.push_back( oCADLayer ); 106 : } 107 : else 108 : { 109 0 : delete pCADLayerObject; 110 : } 111 : } 112 : } 113 : 114 8 : auto iterBlockMS = mapTables.find( BlockRecordModelSpace ); 115 8 : if( iterBlockMS == mapTables.end() ) 116 0 : return CADErrorCodes::TABLE_READ_FAILED; 117 : 118 8 : CADObject* pCADBlockObject = pCADFile->GetObject( 119 8 : iterBlockMS->second.getAsLong() ); 120 : unique_ptr<CADBlockHeaderObject> spModelSpace( 121 16 : dynamic_cast<CADBlockHeaderObject *>( pCADBlockObject ) ); 122 8 : if(!spModelSpace) 123 : { 124 0 : delete pCADBlockObject; 125 0 : return CADErrorCodes::TABLE_READ_FAILED; 126 : } 127 : 128 8 : if(spModelSpace->hEntities.size() < 2) 129 : { 130 0 : return CADErrorCodes::TABLE_READ_FAILED; 131 : } 132 : 133 8 : auto dCurrentEntHandle = spModelSpace->hEntities[0].getAsLong(); 134 8 : auto dLastEntHandle = spModelSpace->hEntities[1].getAsLong(); 135 : // To avoid infinite loops 136 8 : std::set<long> oVisitedHandles; 137 36 : while( dCurrentEntHandle != 0 && 138 36 : oVisitedHandles.find(dCurrentEntHandle) == oVisitedHandles.end() ) 139 : { 140 18 : oVisitedHandles.insert(dCurrentEntHandle); 141 : 142 18 : CADObject* pCADEntityObject = pCADFile->GetObject( dCurrentEntHandle, true ); 143 : unique_ptr<CADEntityObject> spEntityObj( 144 18 : dynamic_cast<CADEntityObject *>( pCADEntityObject ) ); 145 : 146 18 : if( !spEntityObj ) 147 : { 148 0 : delete pCADEntityObject; 149 0 : DebugMsg( "Entity object is null\n" ); 150 0 : break; 151 : } 152 18 : else if ( dCurrentEntHandle == dLastEntHandle ) 153 : { 154 8 : FillLayer( spEntityObj.get() ); 155 8 : break; 156 : } 157 : 158 10 : FillLayer( spEntityObj.get() ); 159 : 160 10 : if( spEntityObj->stCed.bNoLinks ) 161 : { 162 5 : ++dCurrentEntHandle; 163 : } 164 : else 165 : { 166 5 : dCurrentEntHandle = spEntityObj->stChed.hNextEntity.getAsLong( spEntityObj->stCed.hObjectHandle ); 167 : } 168 : } 169 : 170 8 : DebugMsg( "Read aLayers using LayerControl object count: %d\n", 171 8 : static_cast<int>(aLayers.size()) ); 172 : 173 8 : return CADErrorCodes::SUCCESS; 174 : } 175 : 176 18 : void CADTables::FillLayer( const CADEntityObject * pEntityObject ) 177 : { 178 18 : if(nullptr == pEntityObject) 179 : { 180 0 : return; 181 : } 182 : 183 21 : for( CADLayer& oLayer : aLayers ) 184 : { 185 63 : if( pEntityObject->stChed.hLayer.getAsLong( 186 21 : pEntityObject->stCed.hObjectHandle ) == oLayer.getHandle() ) 187 : { 188 36 : DebugMsg( "Object with type: %s is attached to layer named: %s\n", 189 36 : getNameByType( pEntityObject->getType() ).c_str(), 190 36 : oLayer.getName().c_str() ); 191 : 192 18 : oLayer.addHandle( pEntityObject->stCed.hObjectHandle.getAsLong(), 193 : pEntityObject->getType() ); 194 18 : break; 195 : } 196 : } 197 : }