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 : * Permission is hereby granted, free of charge, to any person obtaining a copy 14 : * of this software and associated documentation files (the "Software"), to deal 15 : * in the Software without restriction, including without limitation the rights 16 : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 : * copies of the Software, and to permit persons to whom the Software is 18 : * furnished to do so, subject to the following conditions: 19 : * 20 : * The above copyright notice and this permission notice shall be included in all 21 : * copies or substantial portions of the Software. 22 : * 23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 : * SOFTWARE. 30 : *******************************************************************************/ 31 : #include "cadtables.h" 32 : #include "opencad_api.h" 33 : 34 : #include <cassert> 35 : #include <iostream> 36 : #include <memory> 37 : #include <set> 38 : 39 : using namespace std; 40 : 41 8 : CADTables::CADTables() 42 : { 43 8 : } 44 : 45 144 : void CADTables::AddTable( TableType eType, const CADHandle& hHandle ) 46 : { 47 144 : mapTables[eType] = hHandle; 48 144 : } 49 : 50 8 : int CADTables::ReadTable( CADFile * const pCADFile, CADTables::TableType eType ) 51 : { 52 8 : auto iterAskedTable = mapTables.find( eType ); 53 8 : if( iterAskedTable == mapTables.end() ) 54 0 : return CADErrorCodes::TABLE_READ_FAILED; 55 : 56 : // TODO: read different tables 57 8 : switch( eType ) 58 : { 59 8 : case LayersTable: 60 8 : return ReadLayersTable( pCADFile, iterAskedTable->second.getAsLong() ); 61 0 : default: 62 0 : std::cerr << "Unsupported table."; 63 0 : break; 64 : } 65 : 66 0 : return CADErrorCodes::SUCCESS; 67 : } 68 : 69 26 : size_t CADTables::GetLayerCount() const 70 : { 71 26 : return aLayers.size(); 72 : } 73 : 74 27 : CADLayer& CADTables::GetLayer( size_t iIndex ) 75 : { 76 27 : return aLayers[iIndex]; 77 : } 78 : 79 8 : CADHandle CADTables::GetTableHandle( enum TableType eType ) 80 : { 81 : // FIXME: need to add try/catch to prevent crashes on not found elem. 82 8 : return mapTables[eType]; 83 : } 84 : 85 8 : int CADTables::ReadLayersTable( CADFile * const pCADFile, long dLayerControlHandle ) 86 : { 87 : // Reading Layer Control obj, and aLayers. 88 16 : unique_ptr<CADObject> pCADObject( pCADFile->GetObject( dLayerControlHandle ) ); 89 : 90 : CADLayerControlObject* spLayerControl = 91 8 : dynamic_cast<CADLayerControlObject *>(pCADObject.get()); 92 8 : if( !spLayerControl ) 93 : { 94 0 : return CADErrorCodes::TABLE_READ_FAILED; 95 : } 96 : 97 18 : for( size_t i = 0; i < spLayerControl->hLayers.size(); ++i ) 98 : { 99 10 : if( !spLayerControl->hLayers[i].isNull() ) 100 : { 101 20 : CADLayer oCADLayer( pCADFile ); 102 : 103 : // Init CADLayer from CADLayerObject properties 104 10 : CADObject* pCADLayerObject = pCADFile->GetObject( 105 10 : spLayerControl->hLayers[i].getAsLong() ); 106 : unique_ptr<CADLayerObject> oCADLayerObj( 107 20 : dynamic_cast<CADLayerObject *>( pCADLayerObject ) ); 108 : 109 10 : if(oCADLayerObj) 110 : { 111 10 : oCADLayer.setName( oCADLayerObj->sLayerName ); 112 10 : oCADLayer.setFrozen( oCADLayerObj->bFrozen ); 113 10 : oCADLayer.setOn( oCADLayerObj->bOn ); 114 10 : oCADLayer.setFrozenByDefault( oCADLayerObj->bFrozenInNewVPORT ); 115 10 : oCADLayer.setLocked( oCADLayerObj->bLocked ); 116 10 : oCADLayer.setLineWeight( oCADLayerObj->dLineWeight ); 117 10 : oCADLayer.setColor( oCADLayerObj->dCMColor ); 118 10 : oCADLayer.setId( aLayers.size() + 1 ); 119 10 : oCADLayer.setHandle( oCADLayerObj->hObjectHandle.getAsLong() ); 120 : 121 10 : aLayers.push_back( oCADLayer ); 122 : } 123 : else 124 : { 125 0 : delete pCADLayerObject; 126 : } 127 : } 128 : } 129 : 130 8 : auto iterBlockMS = mapTables.find( BlockRecordModelSpace ); 131 8 : if( iterBlockMS == mapTables.end() ) 132 0 : return CADErrorCodes::TABLE_READ_FAILED; 133 : 134 8 : CADObject* pCADBlockObject = pCADFile->GetObject( 135 8 : iterBlockMS->second.getAsLong() ); 136 : unique_ptr<CADBlockHeaderObject> spModelSpace( 137 16 : dynamic_cast<CADBlockHeaderObject *>( pCADBlockObject ) ); 138 8 : if(!spModelSpace) 139 : { 140 0 : delete pCADBlockObject; 141 0 : return CADErrorCodes::TABLE_READ_FAILED; 142 : } 143 : 144 8 : if(spModelSpace->hEntities.size() < 2) 145 : { 146 0 : return CADErrorCodes::TABLE_READ_FAILED; 147 : } 148 : 149 8 : auto dCurrentEntHandle = spModelSpace->hEntities[0].getAsLong(); 150 8 : auto dLastEntHandle = spModelSpace->hEntities[1].getAsLong(); 151 : // To avoid infinite loops 152 8 : std::set<long> oVisitedHandles; 153 36 : while( dCurrentEntHandle != 0 && 154 36 : oVisitedHandles.find(dCurrentEntHandle) == oVisitedHandles.end() ) 155 : { 156 18 : oVisitedHandles.insert(dCurrentEntHandle); 157 : 158 18 : CADObject* pCADEntityObject = pCADFile->GetObject( dCurrentEntHandle, true ); 159 : unique_ptr<CADEntityObject> spEntityObj( 160 18 : dynamic_cast<CADEntityObject *>( pCADEntityObject ) ); 161 : 162 18 : if( !spEntityObj ) 163 : { 164 0 : delete pCADEntityObject; 165 0 : DebugMsg( "Entity object is null\n" ); 166 0 : break; 167 : } 168 18 : else if ( dCurrentEntHandle == dLastEntHandle ) 169 : { 170 8 : FillLayer( spEntityObj.get() ); 171 8 : break; 172 : } 173 : 174 10 : FillLayer( spEntityObj.get() ); 175 : 176 10 : if( spEntityObj->stCed.bNoLinks ) 177 : { 178 5 : ++dCurrentEntHandle; 179 : } 180 : else 181 : { 182 5 : dCurrentEntHandle = spEntityObj->stChed.hNextEntity.getAsLong( spEntityObj->stCed.hObjectHandle ); 183 : } 184 : } 185 : 186 8 : DebugMsg( "Read aLayers using LayerControl object count: %d\n", 187 8 : static_cast<int>(aLayers.size()) ); 188 : 189 8 : return CADErrorCodes::SUCCESS; 190 : } 191 : 192 18 : void CADTables::FillLayer( const CADEntityObject * pEntityObject ) 193 : { 194 18 : if(nullptr == pEntityObject) 195 : { 196 0 : return; 197 : } 198 : 199 21 : for( CADLayer& oLayer : aLayers ) 200 : { 201 63 : if( pEntityObject->stChed.hLayer.getAsLong( 202 21 : pEntityObject->stCed.hObjectHandle ) == oLayer.getHandle() ) 203 : { 204 36 : DebugMsg( "Object with type: %s is attached to layer named: %s\n", 205 36 : getNameByType( pEntityObject->getType() ).c_str(), 206 36 : oLayer.getName().c_str() ); 207 : 208 18 : oLayer.addHandle( pEntityObject->stCed.hObjectHandle.getAsLong(), 209 : pEntityObject->getType() ); 210 18 : break; 211 : } 212 : } 213 : }