Coverage Report

Created: 2026-08-14 09:29

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