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

Generated by: LCOV version 1.14