1 /******************************************************************************
2 *
3 * Project: SDTS Translator
4 * Purpose: Implementation of SDTS_IREF class for reading IREF module.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
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 "sdts_al.h"
30
31 CPL_CVSID("$Id: sdtsiref.cpp e13dcd4dc171dfeed63f912ba06b9374ce4f3bb2 2018-03-18 21:37:41Z Even Rouault $")
32
33 /************************************************************************/
34 /* SDTS_IREF() */
35 /************************************************************************/
36
SDTS_IREF()37 SDTS_IREF::SDTS_IREF() :
38 nDefaultSADRFormat(0),
39 pszXAxisName(CPLStrdup("")),
40 pszYAxisName(CPLStrdup("")),
41 dfXScale(1.0),
42 dfYScale(1.0),
43 dfXOffset(0.0),
44 dfYOffset(0.0),
45 dfXRes(1.0),
46 dfYRes(1.0),
47 pszCoordinateFormat(CPLStrdup(""))
48 {}
49
50 /************************************************************************/
51 /* ~SDTS_IREF() */
52 /************************************************************************/
53
~SDTS_IREF()54 SDTS_IREF::~SDTS_IREF()
55 {
56 CPLFree( pszXAxisName );
57 CPLFree( pszYAxisName );
58 CPLFree( pszCoordinateFormat );
59 }
60
61 /************************************************************************/
62 /* Read() */
63 /* */
64 /* Read the named file to initialize this structure. */
65 /************************************************************************/
66
Read(const char * pszFilename)67 int SDTS_IREF::Read( const char * pszFilename )
68
69 {
70 /* -------------------------------------------------------------------- */
71 /* Open the file, and read the header. */
72 /* -------------------------------------------------------------------- */
73 DDFModule oIREFFile;
74 if( !oIREFFile.Open( pszFilename ) )
75 return FALSE;
76
77 /* -------------------------------------------------------------------- */
78 /* Read the first record, and verify that this is an IREF record. */
79 /* -------------------------------------------------------------------- */
80 DDFRecord *poRecord = oIREFFile.ReadRecord();
81 if( poRecord == nullptr )
82 return FALSE;
83
84 if( poRecord->GetStringSubfield( "IREF", 0, "MODN", 0 ) == nullptr )
85 return FALSE;
86
87 /* -------------------------------------------------------------------- */
88 /* Get the labels. */
89 /* -------------------------------------------------------------------- */
90 CPLFree( pszXAxisName );
91 pszXAxisName = CPLStrdup( poRecord->GetStringSubfield( "IREF", 0,
92 "XLBL", 0 ) );
93 CPLFree( pszYAxisName );
94 pszYAxisName = CPLStrdup( poRecord->GetStringSubfield( "IREF", 0,
95 "YLBL", 0 ) );
96
97 /* -------------------------------------------------------------------- */
98 /* Get the coordinate encoding. */
99 /* -------------------------------------------------------------------- */
100 CPLFree( pszCoordinateFormat );
101 pszCoordinateFormat =
102 CPLStrdup( poRecord->GetStringSubfield( "IREF", 0, "HFMT", 0 ) );
103
104 /* -------------------------------------------------------------------- */
105 /* Get the transformation information, and resolution. */
106 /* -------------------------------------------------------------------- */
107 dfXScale = poRecord->GetFloatSubfield( "IREF", 0, "SFAX", 0 );
108 dfYScale = poRecord->GetFloatSubfield( "IREF", 0, "SFAY", 0 );
109
110 dfXOffset = poRecord->GetFloatSubfield( "IREF", 0, "XORG", 0 );
111 dfYOffset = poRecord->GetFloatSubfield( "IREF", 0, "YORG", 0 );
112
113 dfXRes = poRecord->GetFloatSubfield( "IREF", 0, "XHRS", 0 );
114 dfYRes = poRecord->GetFloatSubfield( "IREF", 0, "YHRS", 0 );
115
116 nDefaultSADRFormat = EQUAL(pszCoordinateFormat,"BI32");
117
118 return TRUE;
119 }
120
121 /************************************************************************/
122 /* GetSADRCount() */
123 /* */
124 /* Return the number of SADR'es in the passed field. */
125 /************************************************************************/
126
GetSADRCount(DDFField * poField) const127 int SDTS_IREF::GetSADRCount( DDFField * poField ) const
128
129 {
130 if( nDefaultSADRFormat )
131 return poField->GetDataSize() / SDTS_SIZEOF_SADR;
132
133 return poField->GetRepeatCount();
134 }
135
136 /************************************************************************/
137 /* GetSADR() */
138 /************************************************************************/
139
GetSADR(DDFField * poField,int nVertices,double * padfX,double * padfY,double * padfZ)140 int SDTS_IREF::GetSADR( DDFField * poField, int nVertices,
141 double *padfX, double * padfY, double * padfZ )
142
143 {
144 /* -------------------------------------------------------------------- */
145 /* For the sake of efficiency we depend on our knowledge that */
146 /* the SADR field is a series of bigendian int32's and decode */
147 /* them directly. */
148 /* -------------------------------------------------------------------- */
149 if( nDefaultSADRFormat
150 && poField->GetFieldDefn()->GetSubfieldCount() == 2 )
151 {
152 if( poField->GetDataSize() < nVertices * SDTS_SIZEOF_SADR )
153 {
154 return FALSE;
155 }
156
157 GInt32 anXY[2];
158 const char *pachRawData = poField->GetData();
159
160 for( int iVertex = 0; iVertex < nVertices; iVertex++ )
161 {
162 // we copy to a temp buffer to ensure it is world aligned.
163 memcpy( anXY, pachRawData, 8 );
164 pachRawData += 8;
165
166 // possibly byte swap, and always apply scale factor
167 padfX[iVertex] = dfXOffset
168 + dfXScale * static_cast<int>( CPL_MSBWORD32( anXY[0] ) );
169 padfY[iVertex] = dfYOffset
170 + dfYScale * static_cast<int>( CPL_MSBWORD32( anXY[1] ) );
171
172 padfZ[iVertex] = 0.0;
173 }
174 }
175
176 /* -------------------------------------------------------------------- */
177 /* This is the generic case. We assume either two or three */
178 /* subfields, and treat these as X, Y and Z regardless of */
179 /* name. */
180 /* -------------------------------------------------------------------- */
181 else
182 {
183 DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
184 int nBytesRemaining = poField->GetDataSize();
185 const char *pachFieldData = poField->GetData();
186
187 if( poFieldDefn->GetSubfieldCount() != 2 &&
188 poFieldDefn->GetSubfieldCount() != 3 )
189 {
190 return FALSE;
191 }
192
193 for( int iVertex = 0; iVertex < nVertices; iVertex++ )
194 {
195 double adfXYZ[3] = { 0.0, 0.0, 0.0 };
196
197 for( int iEntry = 0;
198 nBytesRemaining > 0 &&
199 iEntry < poFieldDefn->GetSubfieldCount();
200 iEntry++ )
201 {
202 int nBytesConsumed = 0;
203 DDFSubfieldDefn *poSF = poFieldDefn->GetSubfield(iEntry);
204
205 switch( poSF->GetType() )
206 {
207 case DDFInt:
208 adfXYZ[iEntry] =
209 poSF->ExtractIntData( pachFieldData,
210 nBytesRemaining,
211 &nBytesConsumed );
212 break;
213
214 case DDFFloat:
215 adfXYZ[iEntry] =
216 poSF->ExtractFloatData( pachFieldData,
217 nBytesRemaining,
218 &nBytesConsumed );
219 break;
220
221 case DDFBinaryString:
222 {
223 GByte *pabyBString = reinterpret_cast<GByte *> (
224 const_cast<char *>(
225 poSF->ExtractStringData( pachFieldData,
226 nBytesRemaining,
227 &nBytesConsumed ) ) );
228
229 if( EQUAL(pszCoordinateFormat,"BI32") )
230 {
231 if( nBytesConsumed < 4 )
232 return FALSE;
233 GInt32 nValue;
234 memcpy( &nValue, pabyBString, 4 );
235 adfXYZ[iEntry]
236 = static_cast<int>( CPL_MSBWORD32( nValue ) );
237 }
238 else if( EQUAL(pszCoordinateFormat,"BI16") )
239 {
240 if( nBytesConsumed < 2 )
241 return FALSE;
242 GInt16 nValue;
243 memcpy( &nValue, pabyBString, 2 );
244 adfXYZ[iEntry]
245 = static_cast<int>( CPL_MSBWORD16( nValue ) );
246 }
247 else if( EQUAL(pszCoordinateFormat,"BU32") )
248 {
249 if( nBytesConsumed < 4 )
250 return FALSE;
251 GUInt32 nValue;
252 memcpy( &nValue, pabyBString, 4 );
253 adfXYZ[iEntry]
254 = static_cast<GUInt32>( CPL_MSBWORD32( nValue ) );
255 }
256 else if( EQUAL(pszCoordinateFormat,"BU16") )
257 {
258 if( nBytesConsumed < 2 )
259 return FALSE;
260 GUInt16 nValue;
261 memcpy( &nValue, pabyBString, 2 );
262 adfXYZ[iEntry]
263 = static_cast<GUInt16>( CPL_MSBWORD16( nValue ) );
264 }
265 else if( EQUAL(pszCoordinateFormat,"BFP32") )
266 {
267 if( nBytesConsumed < 4 )
268 return FALSE;
269 float fValue;
270
271 memcpy( &fValue, pabyBString, 4 );
272 CPL_MSBPTR32( &fValue );
273 adfXYZ[iEntry] = fValue;
274 }
275 else if( EQUAL(pszCoordinateFormat,"BFP64") )
276 {
277 if( nBytesConsumed < 8 )
278 return FALSE;
279 double dfValue;
280
281 memcpy( &dfValue, pabyBString, 8 );
282 CPL_MSBPTR64( &dfValue );
283 adfXYZ[iEntry] = dfValue;
284 }
285 }
286 break;
287
288 default:
289 adfXYZ[iEntry] = 0.0;
290 break;
291 }
292
293 pachFieldData += nBytesConsumed;
294 nBytesRemaining -= nBytesConsumed;
295 } /* next iEntry */
296
297 padfX[iVertex] = dfXOffset + adfXYZ[0] * dfXScale;
298 padfY[iVertex] = dfYOffset + adfXYZ[1] * dfYScale;
299 padfZ[iVertex] = adfXYZ[2];
300 } /* next iVertex */
301 }
302
303 return TRUE;
304 }
305