LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/cad/libopencad - cadlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 73 146 50.0 %
Date: 2024-11-21 22:18:42 Functions: 20 29 69.0 %

          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 "cadlayer.h"
      16             : #include "cadfile.h"
      17             : 
      18             : #include <cassert>
      19             : #include <iostream>
      20             : #include <algorithm>
      21             : 
      22          10 : CADLayer::CADLayer( CADFile * file ) :
      23             :     frozen( false ),
      24             :     on( true ),
      25             :     frozenByDefault( false ),
      26             :     locked( false ),
      27             :     plotting( false ),
      28             :     lineWeight( 1 ),
      29             :     color( 0 ),
      30             :     layerId( 0 ),
      31             :     layer_handle( 0 ),
      32          10 :     pCADFile( file )
      33             : {
      34          10 : }
      35             : 
      36          28 : std::string CADLayer::getName() const
      37             : {
      38          28 :     return layerName;
      39             : }
      40             : 
      41          10 : void CADLayer::setName( const std::string& value )
      42             : {
      43          10 :     layerName = value;
      44          10 : }
      45             : 
      46           0 : bool CADLayer::getFrozen() const
      47             : {
      48           0 :     return frozen;
      49             : }
      50             : 
      51          10 : void CADLayer::setFrozen( bool value )
      52             : {
      53          10 :     frozen = value;
      54          10 : }
      55             : 
      56           0 : bool CADLayer::getOn() const
      57             : {
      58           0 :     return on;
      59             : }
      60             : 
      61          10 : void CADLayer::setOn( bool value )
      62             : {
      63          10 :     on = value;
      64          10 : }
      65             : 
      66           0 : bool CADLayer::getFrozenByDefault() const
      67             : {
      68           0 :     return frozenByDefault;
      69             : }
      70             : 
      71          10 : void CADLayer::setFrozenByDefault( bool value )
      72             : {
      73          10 :     frozenByDefault = value;
      74          10 : }
      75             : 
      76           0 : bool CADLayer::getLocked() const
      77             : {
      78           0 :     return locked;
      79             : }
      80             : 
      81          10 : void CADLayer::setLocked( bool value )
      82             : {
      83          10 :     locked = value;
      84          10 : }
      85             : 
      86           0 : bool CADLayer::getPlotting() const
      87             : {
      88           0 :     return plotting;
      89             : }
      90             : 
      91           0 : void CADLayer::setPlotting( bool value )
      92             : {
      93           0 :     plotting = value;
      94           0 : }
      95             : 
      96           0 : short CADLayer::getLineWeight() const
      97             : {
      98           0 :     return lineWeight;
      99             : }
     100             : 
     101          10 : void CADLayer::setLineWeight( short value )
     102             : {
     103          10 :     lineWeight = value;
     104          10 : }
     105             : 
     106          17 : short CADLayer::getColor() const
     107             : {
     108          17 :     return color;
     109             : }
     110             : 
     111          10 : void CADLayer::setColor( short value )
     112             : {
     113          10 :     color = value;
     114          10 : }
     115             : 
     116          17 : size_t CADLayer::getId() const
     117             : {
     118          17 :     return layerId;
     119             : }
     120             : 
     121          10 : void CADLayer::setId( const size_t& value )
     122             : {
     123          10 :     layerId = value;
     124          10 : }
     125             : 
     126          21 : long CADLayer::getHandle() const
     127             : {
     128          21 :     return layer_handle;
     129             : }
     130             : 
     131          10 : void CADLayer::setHandle( long value )
     132             : {
     133          10 :     layer_handle = value;
     134          10 : }
     135             : 
     136          18 : void CADLayer::addHandle( long handle, CADObject::ObjectType type, long cadinserthandle )
     137             : {
     138             : #ifdef _DEBUG
     139             :     std::cout << "addHandle: " << handle << " type: " << type << "\n";
     140             : #endif //_DEBUG
     141          18 :     if( type == CADObject::ATTRIB || type == CADObject::ATTDEF )
     142             :     {
     143           4 :         auto pCADGeometryPtr = pCADFile->GetGeometry( getId() - 1, handle );
     144           8 :         std::unique_ptr<CADGeometry> pCADGeometry( pCADGeometryPtr );
     145           4 :         CADAttdef* attdef = dynamic_cast<CADAttdef*>(pCADGeometry.get());
     146           4 :         if(attdef)
     147             :         {
     148           4 :             attributesNames.insert( attdef->getTag() );
     149             :         }
     150             :     }
     151             : 
     152          18 :     if( type == CADObject::INSERT )
     153             :     {
     154             :         // TODO: transform insert to block of objects (do we need to transform
     155             :         // coordinates according to insert point)?
     156           0 :         auto insertPtr = pCADFile->GetObject( handle, false );
     157           0 :         std::unique_ptr<CADObject> insert( insertPtr );
     158           0 :         CADInsertObject * pInsert = dynamic_cast<CADInsertObject *>(insert.get());
     159           0 :         if( nullptr != pInsert )
     160             :         {
     161           0 :             std::unique_ptr<CADObject> blockHeader( pCADFile->GetObject(
     162           0 :                                     pInsert->hBlockHeader.getAsLong(), false ) );
     163             :             CADBlockHeaderObject * pBlockHeader =
     164           0 :                           dynamic_cast<CADBlockHeaderObject *>(blockHeader.get());
     165           0 :             if( nullptr != pBlockHeader )
     166             :             {
     167             : #ifdef _DEBUG
     168             :                 if( pBlockHeader->bBlkisXRef )
     169             :                 {
     170             :                     assert( 0 );
     171             :                 }
     172             : #endif //_DEBUG
     173           0 :                 if( pBlockHeader->hEntities.empty() )
     174             :                 {
     175           0 :                     return;
     176             :                 }
     177           0 :                 auto dCurrentEntHandle = pBlockHeader->hEntities[0].getAsLong();
     178           0 :                 auto dLastEntHandle    = pBlockHeader->hEntities.back().getAsLong(); // FIXME: in 2000+ entities probably has no links to each other.
     179             : 
     180           0 :                 if( dCurrentEntHandle == dLastEntHandle ) // Blocks can be empty (contain no objects)
     181             :                 {
     182           0 :                     return;
     183             :                 }
     184             : 
     185             :                 while( true )
     186             :                 {
     187           0 :                     std::unique_ptr<CADObject> entity(pCADFile->GetObject(
     188           0 :                                                        dCurrentEntHandle, true ));
     189             :                     CADEntityObject* pEntity =
     190           0 :                             dynamic_cast<CADEntityObject *>( entity.get() );
     191             : 
     192           0 :                     if( nullptr == pEntity )
     193             :                     {
     194             :                         // shouldn't happen on a valid file, but can happen
     195             :                         // on broken ones
     196           0 :                         break;
     197             :                     }
     198             : 
     199           0 :                     if( dCurrentEntHandle == handle && type == pEntity->getType() )
     200             :                     {
     201             :                         // If the above condition is true, infinite recursion
     202             :                         // would occur in the following addHandle() call.
     203             :                         // Shouldn't happen on a valid file, but can happen
     204             :                         // on broken ones, such as in https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=46887
     205           0 :                         break;
     206             :                     }
     207             : 
     208           0 :                     addHandle( dCurrentEntHandle, pEntity->getType(), handle );
     209           0 :                     Matrix mat;
     210           0 :                     mat.translate( pInsert->vertInsertionPoint );
     211           0 :                     mat.scale( pInsert->vertScales );
     212           0 :                     mat.rotate( pInsert->dfRotation );
     213           0 :                     transformations[dCurrentEntHandle] = mat;
     214             : 
     215           0 :                     if( dCurrentEntHandle == dLastEntHandle )
     216             :                     {
     217           0 :                         break;
     218             :                     }
     219             :                     else
     220             :                     {
     221           0 :                         if( pEntity->stCed.bNoLinks )
     222             :                         {
     223           0 :                             ++dCurrentEntHandle;
     224             :                         }
     225             :                         else
     226             :                         {
     227           0 :                             dCurrentEntHandle =
     228           0 :                                 pEntity->stChed.hNextEntity.getAsLong(
     229           0 :                                     pEntity->stCed.hObjectHandle );
     230             :                         }
     231             :                     }
     232           0 :                 }
     233             :             }
     234             :         }
     235           0 :         return;
     236             :     }
     237             : 
     238          18 :     if( isCommonEntityType( type ) )
     239             :     {
     240          18 :         if( type == CADObject::IMAGE )
     241             :         {
     242           0 :             imageHandles.push_back( handle );
     243             :         }
     244             :         else
     245             :         {
     246          18 :             if( pCADFile->isReadingUnsupportedGeometries() == false )
     247             :             {
     248          18 :                 if( isSupportedGeometryType( type ) )
     249             :                 {
     250          18 :                     if( geometryTypes.empty() )
     251             :                     {
     252          10 :                         geometryTypes.push_back( type );
     253             :                     }
     254             : 
     255          18 :                     if( find( geometryTypes.begin(), geometryTypes.end(), type ) ==
     256          36 :                         geometryTypes.end() )
     257             :                     {
     258           8 :                         geometryTypes.push_back( type );
     259             :                     }
     260          18 :                     geometryHandles.push_back(
     261          36 :                                 std::make_pair( handle, cadinserthandle ) );
     262             :                 }
     263             :             }
     264             :             else
     265             :             {
     266           0 :                 if( geometryTypes.empty() )
     267             :                 {
     268           0 :                     geometryTypes.push_back( type );
     269             :                 }
     270             : 
     271           0 :                 if( find( geometryTypes.begin(), geometryTypes.end(), type ) ==
     272           0 :                     geometryTypes.end() )
     273             :                 {
     274           0 :                     geometryTypes.push_back( type );
     275             :                 }
     276           0 :                 geometryHandles.push_back(
     277           0 :                             std::make_pair( handle, cadinserthandle ) );
     278             :             }
     279             :         }
     280             :     }
     281             : }
     282             : 
     283          30 : size_t CADLayer::getGeometryCount() const
     284             : {
     285          30 :     return geometryHandles.size();
     286             : }
     287             : 
     288          13 : CADGeometry * CADLayer::getGeometry( size_t index )
     289             : {
     290          13 :     auto handleBlockRefPair = geometryHandles[index];
     291          13 :     CADGeometry * pGeom = pCADFile->GetGeometry( this->getId() - 1,
     292          13 :                         handleBlockRefPair.first, handleBlockRefPair.second );
     293          13 :     if( nullptr == pGeom )
     294           0 :         return nullptr;
     295          13 :     auto iter = transformations.find( handleBlockRefPair.first );
     296          13 :     if( iter != transformations.end() )
     297             :     {
     298             :         // transform geometry if nHandle is in transformations
     299           0 :         pGeom->transform( iter->second );
     300             :     }
     301          13 :     return pGeom;
     302             : }
     303             : 
     304          10 : size_t CADLayer::getImageCount() const
     305             : {
     306          10 :     return imageHandles.size();
     307             : }
     308             : 
     309           0 : CADImage * CADLayer::getImage( size_t index )
     310             : {
     311           0 :     return static_cast<CADImage *>(pCADFile->GetGeometry( this->getId() - 1,
     312           0 :                                                             imageHandles[index] ));
     313             : }
     314             : 
     315           0 : bool CADLayer::addAttribute( const CADObject * pObject )
     316             : {
     317           0 :     if( nullptr == pObject )
     318           0 :         return true;
     319             : 
     320           0 :     auto attrib = static_cast<const CADAttribObject *>(pObject);
     321           0 :     for( auto i = geometryAttributes.begin(); i != geometryAttributes.end(); ++i )
     322             :     {
     323           0 :         if( i->first == attrib->stChed.hOwner.getAsLong() )
     324             :         {
     325           0 :             i->second.insert( make_pair( attrib->sTag, layer_handle ) );
     326           0 :             return true;
     327             :         }
     328             :     }
     329             : 
     330           0 :     return false;
     331             : }
     332             : 
     333          10 : std::vector<CADObject::ObjectType> CADLayer::getGeometryTypes()
     334             : {
     335          10 :     return geometryTypes;
     336             : }
     337             : 
     338          10 : std::unordered_set<std::string> CADLayer::getAttributesTags()
     339             : {
     340          10 :     return attributesNames;
     341             : }

Generated by: LCOV version 1.14