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