/src/gdal/ogr/ogrsf_frmts/cad/libopencad/cadtables.cpp
Line | Count | Source |
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 | | CADTables::CADTables() |
26 | 6.66k | { |
27 | 6.66k | } |
28 | | |
29 | | void CADTables::AddTable( TableType eType, const CADHandle& hHandle ) |
30 | 116k | { |
31 | 116k | mapTables[eType] = hHandle; |
32 | 116k | } |
33 | | |
34 | | int CADTables::ReadTable( CADFile * const pCADFile, CADTables::TableType eType ) |
35 | 6.13k | { |
36 | 6.13k | auto iterAskedTable = mapTables.find( eType ); |
37 | 6.13k | if( iterAskedTable == mapTables.end() ) |
38 | 0 | return CADErrorCodes::TABLE_READ_FAILED; |
39 | | |
40 | | // TODO: read different tables |
41 | 6.13k | switch( eType ) |
42 | 6.13k | { |
43 | 6.13k | case LayersTable: |
44 | 6.13k | return ReadLayersTable( pCADFile, iterAskedTable->second.getAsLong() ); |
45 | 0 | default: |
46 | 0 | std::cerr << "Unsupported table."; |
47 | 0 | break; |
48 | 6.13k | } |
49 | | |
50 | 0 | return CADErrorCodes::SUCCESS; |
51 | 6.13k | } |
52 | | |
53 | | size_t CADTables::GetLayerCount() const |
54 | 13.9k | { |
55 | 13.9k | return aLayers.size(); |
56 | 13.9k | } |
57 | | |
58 | | CADLayer& CADTables::GetLayer( size_t iIndex ) |
59 | 11.5k | { |
60 | 11.5k | return aLayers[iIndex]; |
61 | 11.5k | } |
62 | | |
63 | | CADHandle CADTables::GetTableHandle( enum TableType eType ) |
64 | 1.49k | { |
65 | | // FIXME: need to add try/catch to prevent crashes on not found elem. |
66 | 1.49k | return mapTables[eType]; |
67 | 1.49k | } |
68 | | |
69 | | int CADTables::ReadLayersTable( CADFile * const pCADFile, long dLayerControlHandle ) |
70 | 6.13k | { |
71 | | // Reading Layer Control obj, and aLayers. |
72 | 6.13k | unique_ptr<CADObject> pCADObject( pCADFile->GetObject( dLayerControlHandle ) ); |
73 | | |
74 | 6.13k | CADLayerControlObject* spLayerControl = |
75 | 6.13k | dynamic_cast<CADLayerControlObject *>(pCADObject.get()); |
76 | 6.13k | if( !spLayerControl ) |
77 | 2.73k | { |
78 | 2.73k | return CADErrorCodes::TABLE_READ_FAILED; |
79 | 2.73k | } |
80 | | |
81 | 795k | for( size_t i = 0; i < spLayerControl->hLayers.size(); ++i ) |
82 | 792k | { |
83 | 792k | if( !spLayerControl->hLayers[i].isNull() ) |
84 | 383k | { |
85 | 383k | CADLayer oCADLayer( pCADFile ); |
86 | | |
87 | | // Init CADLayer from CADLayerObject properties |
88 | 383k | CADObject* pCADLayerObject = pCADFile->GetObject( |
89 | 383k | spLayerControl->hLayers[i].getAsLong() ); |
90 | 383k | unique_ptr<CADLayerObject> oCADLayerObj( |
91 | 383k | dynamic_cast<CADLayerObject *>( pCADLayerObject ) ); |
92 | | |
93 | 383k | if(oCADLayerObj) |
94 | 12.2k | { |
95 | 12.2k | oCADLayer.setName( oCADLayerObj->sLayerName ); |
96 | 12.2k | oCADLayer.setFrozen( oCADLayerObj->bFrozen ); |
97 | 12.2k | oCADLayer.setOn( oCADLayerObj->bOn ); |
98 | 12.2k | oCADLayer.setFrozenByDefault( oCADLayerObj->bFrozenInNewVPORT ); |
99 | 12.2k | oCADLayer.setLocked( oCADLayerObj->bLocked ); |
100 | 12.2k | oCADLayer.setLineWeight( oCADLayerObj->dLineWeight ); |
101 | 12.2k | oCADLayer.setColor( oCADLayerObj->dCMColor ); |
102 | 12.2k | oCADLayer.setId( aLayers.size() + 1 ); |
103 | 12.2k | oCADLayer.setHandle( oCADLayerObj->hObjectHandle.getAsLong() ); |
104 | | |
105 | 12.2k | aLayers.push_back( std::move(oCADLayer) ); |
106 | 12.2k | } |
107 | 371k | else |
108 | 371k | { |
109 | 371k | delete pCADLayerObject; |
110 | 371k | } |
111 | 383k | } |
112 | 792k | } |
113 | | |
114 | 3.39k | auto iterBlockMS = mapTables.find( BlockRecordModelSpace ); |
115 | 3.39k | if( iterBlockMS == mapTables.end() ) |
116 | 0 | return CADErrorCodes::TABLE_READ_FAILED; |
117 | | |
118 | 3.39k | CADObject* pCADBlockObject = pCADFile->GetObject( |
119 | 3.39k | iterBlockMS->second.getAsLong() ); |
120 | 3.39k | unique_ptr<CADBlockHeaderObject> spModelSpace( |
121 | 3.39k | dynamic_cast<CADBlockHeaderObject *>( pCADBlockObject ) ); |
122 | 3.39k | if(!spModelSpace) |
123 | 1.90k | { |
124 | 1.90k | delete pCADBlockObject; |
125 | 1.90k | return CADErrorCodes::TABLE_READ_FAILED; |
126 | 1.90k | } |
127 | | |
128 | 1.49k | if(spModelSpace->hEntities.size() < 2) |
129 | 1 | { |
130 | 1 | return CADErrorCodes::TABLE_READ_FAILED; |
131 | 1 | } |
132 | | |
133 | 1.49k | auto dCurrentEntHandle = spModelSpace->hEntities[0].getAsLong(); |
134 | 1.49k | auto dLastEntHandle = spModelSpace->hEntities[1].getAsLong(); |
135 | | // To avoid infinite loops |
136 | 1.49k | std::set<long> oVisitedHandles; |
137 | 3.89k | while( dCurrentEntHandle != 0 && |
138 | 3.29k | oVisitedHandles.find(dCurrentEntHandle) == oVisitedHandles.end() ) |
139 | 3.24k | { |
140 | 3.24k | oVisitedHandles.insert(dCurrentEntHandle); |
141 | | |
142 | 3.24k | CADObject* pCADEntityObject = pCADFile->GetObject( dCurrentEntHandle, true ); |
143 | 3.24k | unique_ptr<CADEntityObject> spEntityObj( |
144 | 3.24k | dynamic_cast<CADEntityObject *>( pCADEntityObject ) ); |
145 | | |
146 | 3.24k | if( !spEntityObj ) |
147 | 687 | { |
148 | 687 | delete pCADEntityObject; |
149 | 687 | DebugMsg( "Entity object is null\n" ); |
150 | 687 | break; |
151 | 687 | } |
152 | 2.55k | else if ( dCurrentEntHandle == dLastEntHandle ) |
153 | 154 | { |
154 | 154 | FillLayer( spEntityObj.get() ); |
155 | 154 | break; |
156 | 154 | } |
157 | | |
158 | 2.40k | FillLayer( spEntityObj.get() ); |
159 | | |
160 | 2.40k | if( spEntityObj->stCed.bNoLinks ) |
161 | 1.27k | { |
162 | 1.27k | ++dCurrentEntHandle; |
163 | 1.27k | } |
164 | 1.12k | else |
165 | 1.12k | { |
166 | 1.12k | dCurrentEntHandle = spEntityObj->stChed.hNextEntity.getAsLong( spEntityObj->stCed.hObjectHandle ); |
167 | 1.12k | } |
168 | 2.40k | } |
169 | | |
170 | 1.49k | DebugMsg( "Read aLayers using LayerControl object count: %d\n", |
171 | 1.49k | static_cast<int>(aLayers.size()) ); |
172 | | |
173 | 1.49k | return CADErrorCodes::SUCCESS; |
174 | 1.49k | } |
175 | | |
176 | | void CADTables::FillLayer( const CADEntityObject * pEntityObject ) |
177 | 2.55k | { |
178 | 2.55k | if(nullptr == pEntityObject) |
179 | 0 | { |
180 | 0 | return; |
181 | 0 | } |
182 | | |
183 | 2.55k | for( CADLayer& oLayer : aLayers ) |
184 | 8.76k | { |
185 | 8.76k | if( pEntityObject->stChed.hLayer.getAsLong( |
186 | 8.76k | pEntityObject->stCed.hObjectHandle ) == oLayer.getHandle() ) |
187 | 2.14k | { |
188 | 2.14k | DebugMsg( "Object with type: %s is attached to layer named: %s\n", |
189 | 2.14k | getNameByType( pEntityObject->getType() ).c_str(), |
190 | 2.14k | oLayer.getName().c_str() ); |
191 | | |
192 | 2.14k | oLayer.addHandle( pEntityObject->stCed.hObjectHandle.getAsLong(), |
193 | 2.14k | pEntityObject->getType() ); |
194 | 2.14k | break; |
195 | 2.14k | } |
196 | 8.76k | } |
197 | 2.55k | } |