1 /******************************************************************************
2 *
3 * Project: OpenGIS Simple Features Reference Implementation
4 * Purpose: OGR Driver for DGNv8
5 * Author: Even Rouault <even.rouault at spatialys.com>
6 *
7 ******************************************************************************
8 * Copyright (c) 2017, Even Rouault <even.rouault at spatialys.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "ogr_dgnv8.h"
30 #include "cpl_conv.h"
31 #include "ogrteigha.h"
32
33 CPL_CVSID("$Id: ogrdgnv8driver.cpp 1761acd90777d5bcc49eddbc13c193098f0ed40b 2020-10-01 12:12:00 +0200 Even Rouault $")
34
35 /************************************************************************/
36 /* OGRDGNV8DriverUnload() */
37 /************************************************************************/
38
OGRDGNV8DriverUnload(GDALDriver *)39 static void OGRDGNV8DriverUnload( GDALDriver* )
40 {
41 CPLDebug("DGNv8", "Driver cleanup");
42 OGRTEIGHADeinitialize();
43 }
44
45 /************************************************************************/
46 /* OGRDGNV8DriverIdentify() */
47 /************************************************************************/
48
OGRDGNV8DriverIdentify(GDALOpenInfo * poOpenInfo)49 static int OGRDGNV8DriverIdentify( GDALOpenInfo* poOpenInfo )
50
51 {
52 VSIStatBuf sStat;
53 if( poOpenInfo->fpL != nullptr &&
54 poOpenInfo->nHeaderBytes >= 512 )
55 {
56 // Is it a DGN v7 cell library?
57 if( poOpenInfo->pabyHeader[0] == 0x08
58 && poOpenInfo->pabyHeader[1] == 0x05
59 && poOpenInfo->pabyHeader[2] == 0x17
60 && poOpenInfo->pabyHeader[3] == 0x00 )
61 {
62 return GDALGetDriverByName("DGN") == nullptr &&
63 VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
64 }
65
66 // Is it a DGN v7 regular 2D or 3D file?
67 if( (poOpenInfo->pabyHeader[0] == 0x08 ||
68 poOpenInfo->pabyHeader[0] == 0xC8)
69 && poOpenInfo->pabyHeader[1] == 0x09
70 && poOpenInfo->pabyHeader[2] == 0xFE
71 && poOpenInfo->pabyHeader[3] == 0x02 )
72 {
73 return GDALGetDriverByName("DGN") == nullptr &&
74 VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
75 }
76 }
77
78 return poOpenInfo->fpL != nullptr &&
79 poOpenInfo->nHeaderBytes >= 512 &&
80 EQUAL( CPLGetExtension(poOpenInfo->pszFilename), "DGN" ) &&
81 memcmp(poOpenInfo->pabyHeader,
82 "\xD0\xCF\x11\xE0\xA1\xB1\x1A\xE1", 8) == 0 &&
83 VSIStat(poOpenInfo->pszFilename, &sStat) == 0;
84 }
85
86 /************************************************************************/
87 /* Open() */
88 /************************************************************************/
89
OGRDGNV8DriverOpen(GDALOpenInfo * poOpenInfo)90 static GDALDataset *OGRDGNV8DriverOpen( GDALOpenInfo* poOpenInfo )
91
92 {
93 if( !OGRDGNV8DriverIdentify(poOpenInfo))
94 return nullptr;
95
96 if( !OGRTEIGHAInitialize() )
97 return nullptr;
98
99 OGRDGNV8DataSource *poDS = new OGRDGNV8DataSource(OGRDGNV8GetServices());
100 if( !poDS->Open( poOpenInfo->pszFilename,
101 poOpenInfo->eAccess == GA_Update) )
102 {
103 delete poDS;
104 return nullptr;
105 }
106
107 return poDS;
108 }
109
110 /************************************************************************/
111 /* Create() */
112 /************************************************************************/
113
OGRDGNV8DriverCreate(const char * pszName,int,int,int,GDALDataType,char ** papszOptions)114 static GDALDataset *OGRDGNV8DriverCreate( const char * pszName,
115 int /* nBands */,
116 int /* nXSize */,
117 int /* nYSize */,
118 GDALDataType /* eDT */,
119 char **papszOptions )
120 {
121 if( !OGRTEIGHAInitialize() )
122 return nullptr;
123
124 OGRDGNV8DataSource *poDS = new OGRDGNV8DataSource(OGRDGNV8GetServices());
125 if( !poDS->PreCreate( pszName, papszOptions ) )
126 {
127 delete poDS;
128 return nullptr;
129 }
130
131 return poDS;
132 }
133
134 /************************************************************************/
135 /* RegisterOGRDGNV8() */
136 /************************************************************************/
137
RegisterOGRDGNV8()138 void RegisterOGRDGNV8()
139
140 {
141 if( GDALGetDriverByName( "DGNV8" ) != nullptr )
142 return;
143
144 GDALDriver *poDriver = new GDALDriver();
145
146 poDriver->SetDescription( "DGNV8" );
147 poDriver->SetMetadataItem( GDAL_DCAP_VECTOR, "YES" );
148 poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, "Microstation DGNv8" );
149 poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "dgn" );
150 poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC, "drivers/vector/dgnv8.html" );
151 poDriver->SetMetadataItem( GDAL_DCAP_FEATURE_STYLES, "YES" );
152
153 poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
154 "<CreationOptionList>"
155 " <Option name='SEED' type='string' "
156 "description='Filename of seed file to use'/>"
157 " <Option name='COPY_SEED_FILE_COLOR_TABLE' type='boolean' "
158 "description='whether the color table should be copied from the "
159 "seed file.' default='NO'/>"
160 " <Option name='COPY_SEED_FILE_MODEL' type='boolean' "
161 "description='whether the existing models (without their graphic "
162 "contents) should be copied from the seed file.' default='YES'/>"
163 " <Option name='COPY_SEED_FILE_MODEL_CONTROL_ELEMENTS' type='boolean' "
164 "description='whether the existing control elements of models should be "
165 "copied from the seed file.' default='YES'/>"
166 " <Option name='APPLICATION' type='string' "
167 "description='Set Application field in header'/>"
168 " <Option name='TITLE' type='string' "
169 "description='Set Title field in header'/>"
170 " <Option name='SUBJECT' type='string' "
171 "description='Set Subject field in header'/>"
172 " <Option name='AUTHOR' type='string' "
173 "description='Set Author field in header'/>"
174 " <Option name='KEYWORDS' type='string' "
175 "description='Set Keywords field in header'/>"
176 " <Option name='TEMPLATE' type='string' "
177 "description='Set Template field in header'/>"
178 " <Option name='COMMENTS' type='string' "
179 "description='Set Comments field in header'/>"
180 " <Option name='LAST_SAVED_BY' type='string' "
181 "description='Set LastSavedBy field in header'/>"
182 " <Option name='REVISION_NUMBER' type='string' "
183 "description='Set RevisionNumber field in header'/>"
184 " <Option name='CATEGORY' type='string' "
185 "description='Set Category field in header'/>"
186 " <Option name='MANAGER' type='string' "
187 "description='Set Manager field in header'/>"
188 " <Option name='COMPANY' type='string' "
189 "description='Set Company field in header'/>"
190 "</CreationOptionList>");
191
192 poDriver->SetMetadataItem( GDAL_DS_LAYER_CREATIONOPTIONLIST,
193 "<LayerCreationOptionList>"
194 " <Option name='DESCRIPTION' type='string' "
195 "description='Description of the layer/model'/>"
196 " <Option name='DIM' type='int' "
197 "description='Dimension (2 or 3) of the layer/model'/>"
198 "</LayerCreationOptionList>" );
199
200 poDriver->pfnOpen = OGRDGNV8DriverOpen;
201 poDriver->pfnIdentify = OGRDGNV8DriverIdentify;
202 poDriver->pfnCreate = OGRDGNV8DriverCreate;
203 poDriver->pfnUnloadDriver = OGRDGNV8DriverUnload;
204
205 GetGDALDriverManager()->RegisterDriver( poDriver );
206 }
207