1 /******************************************************************************
2 *
3 * Project: DWG Translator
4 * Purpose: Implements BlockMap reading and management portion of
5 * OGRDWGDataSource class
6 * Author: Frank Warmerdam, warmerdam@pobox.com
7 *
8 ******************************************************************************
9 * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.com>
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice shall be included
19 * in all copies or substantial portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 * DEALINGS IN THE SOFTWARE.
28 ****************************************************************************/
29
30 #include "ogr_dwg.h"
31 #include "cpl_conv.h"
32 #include "cpl_string.h"
33 #include "cpl_csv.h"
34
35 CPL_CVSID("$Id: ogrdwg_blockmap.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
36
37 /************************************************************************/
38 /* ReadBlockSection() */
39 /************************************************************************/
40
ReadBlocksSection()41 void OGRDWGDataSource::ReadBlocksSection()
42
43 {
44 OGRDWGLayer *poReaderLayer = (OGRDWGLayer *) GetLayerByName( "Entities" );
45 int bMergeBlockGeometries = CPLTestBool(
46 CPLGetConfigOption( "DWG_MERGE_BLOCK_GEOMETRIES", "TRUE" ) );
47
48 /* -------------------------------------------------------------------- */
49 /* Loop over all the block tables, skipping *Model_Space which */
50 /* we assume is primary entities. */
51 /* -------------------------------------------------------------------- */
52 OdDbBlockTableRecordPtr poModelSpace, poBlock;
53 OdDbBlockTablePtr pTable = GetDB()->getBlockTableId().safeOpenObject();
54 OdDbSymbolTableIteratorPtr pBlkIter = pTable->newIterator();
55
56 for (pBlkIter->start(); ! pBlkIter->done(); pBlkIter->step())
57 {
58 poBlock = pBlkIter->getRecordId().safeOpenObject();
59 CPLString osBlockName = (const char *) poBlock->getName();
60
61 if( EQUAL(osBlockName,"*Model_Space") )
62 {
63 poModelSpace = poBlock;
64 continue;
65 }
66
67 poReaderLayer->SetBlockTable( poBlock );
68
69 // Now we will process entities till we run out.
70 // We aggregate the geometries of the features into a multi-geometry,
71 // but throw away other stuff attached to the features.
72
73 OGRFeature *poFeature = nullptr;
74 OGRGeometryCollection *poColl = new OGRGeometryCollection();
75 std::vector<OGRFeature*> apoFeatures;
76
77 while( (poFeature = poReaderLayer->GetNextUnfilteredFeature()) != nullptr )
78 {
79 if( (poFeature->GetStyleString() != nullptr
80 && strstr(poFeature->GetStyleString(),"LABEL") != nullptr)
81 || !bMergeBlockGeometries )
82 {
83 apoFeatures.push_back( poFeature );
84 }
85 else
86 {
87 poColl->addGeometryDirectly( poFeature->StealGeometry() );
88 delete poFeature;
89 }
90 }
91
92 if( poColl->getNumGeometries() == 0 )
93 delete poColl;
94 else
95 oBlockMap[osBlockName].poGeometry = SimplifyBlockGeometry(poColl);
96
97 if( !apoFeatures.empty() )
98 oBlockMap[osBlockName].apoFeatures = apoFeatures;
99 }
100
101 CPLDebug( "DWG", "Read %d blocks with meaningful geometry.",
102 (int) oBlockMap.size() );
103
104 poReaderLayer->SetBlockTable( poModelSpace );
105 }
106
107 /************************************************************************/
108 /* SimplifyBlockGeometry() */
109 /************************************************************************/
110
SimplifyBlockGeometry(OGRGeometryCollection * poCollection)111 OGRGeometry *OGRDWGDataSource::SimplifyBlockGeometry(
112 OGRGeometryCollection *poCollection )
113
114 {
115 /* -------------------------------------------------------------------- */
116 /* If there is only one geometry in the collection, just return */
117 /* it. */
118 /* -------------------------------------------------------------------- */
119 if( poCollection->getNumGeometries() == 1 )
120 {
121 OGRGeometry *poReturn = poCollection->getGeometryRef(0);
122 poCollection->removeGeometry(0,FALSE);
123 delete poCollection;
124 return poReturn;
125 }
126
127 /* -------------------------------------------------------------------- */
128 /* Eventually we likely ought to have logic to convert to */
129 /* polygon, multipolygon, multilinestring or multipoint but */
130 /* I'll put that off till it would be meaningful. */
131 /* -------------------------------------------------------------------- */
132
133 return poCollection;
134 }
135
136 /************************************************************************/
137 /* LookupBlock() */
138 /* */
139 /* Find the geometry collection corresponding to a name if it */
140 /* exists. Note that the returned geometry pointer is to a */
141 /* geometry that continues to be owned by the datasource. It */
142 /* should be cloned for use. */
143 /************************************************************************/
144
LookupBlock(const char * pszName)145 DWGBlockDefinition *OGRDWGDataSource::LookupBlock( const char *pszName )
146
147 {
148 CPLString osName = pszName;
149
150 if( oBlockMap.count( osName ) == 0 )
151 return nullptr;
152 else
153 return &(oBlockMap[osName]);
154 }
155
156 /************************************************************************/
157 /* ~DWGBlockDefinition() */
158 /* */
159 /* Safe cleanup of a block definition. */
160 /************************************************************************/
161
~DWGBlockDefinition()162 DWGBlockDefinition::~DWGBlockDefinition()
163
164 {
165 delete poGeometry;
166
167 while( !apoFeatures.empty() )
168 {
169 delete apoFeatures.back();
170 apoFeatures.pop_back();
171 }
172 }
173