Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: SDTSReader
4 : * Purpose: Implements OGRSDTSLayer class.
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 "ogr_sdts.h"
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 :
33 : /************************************************************************/
34 : /* OGRSDTSLayer() */
35 : /* */
36 : /* Note that the OGRSDTSLayer assumes ownership of the passed */
37 : /* OGRFeatureDefn object. */
38 : /************************************************************************/
39 :
40 8 : OGRSDTSLayer::OGRSDTSLayer(SDTSTransfer *poTransferIn, int iLayerIn,
41 8 : OGRSDTSDataSource *poDSIn)
42 : : poFeatureDefn(nullptr), poTransfer(poTransferIn), iLayer(iLayerIn),
43 8 : poReader(poTransferIn->GetLayerIndexedReader(iLayerIn)), poDS(poDSIn)
44 : {
45 : /* -------------------------------------------------------------------- */
46 : /* Define the feature. */
47 : /* -------------------------------------------------------------------- */
48 8 : const int iCATDEntry = poTransfer->GetLayerCATDEntry(iLayer);
49 :
50 8 : poFeatureDefn =
51 8 : new OGRFeatureDefn(poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
52 8 : SetDescription(poFeatureDefn->GetName());
53 8 : poFeatureDefn->Reference();
54 8 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(poDS->DSGetSpatialRef());
55 :
56 16 : OGRFieldDefn oRecId("RCID", OFTInteger);
57 8 : poFeatureDefn->AddFieldDefn(&oRecId);
58 :
59 8 : if (poTransfer->GetLayerType(iLayer) == SLTPoint)
60 : {
61 3 : poFeatureDefn->SetGeomType(wkbPoint);
62 : }
63 5 : else if (poTransfer->GetLayerType(iLayer) == SLTLine)
64 : {
65 1 : poFeatureDefn->SetGeomType(wkbLineString);
66 :
67 1 : oRecId.SetName("SNID");
68 1 : poFeatureDefn->AddFieldDefn(&oRecId);
69 :
70 1 : oRecId.SetName("ENID");
71 1 : poFeatureDefn->AddFieldDefn(&oRecId);
72 : }
73 4 : else if (poTransfer->GetLayerType(iLayer) == SLTPoly)
74 : {
75 1 : poFeatureDefn->SetGeomType(wkbPolygon);
76 : }
77 3 : else if (poTransfer->GetLayerType(iLayer) == SLTAttr)
78 : {
79 3 : poFeatureDefn->SetGeomType(wkbNone);
80 : }
81 :
82 : /* -------------------------------------------------------------------- */
83 : /* Add schema from referenced attribute records. */
84 : /* -------------------------------------------------------------------- */
85 8 : char **papszATIDRefs = nullptr;
86 :
87 8 : if (poTransfer->GetLayerType(iLayer) != SLTAttr)
88 5 : papszATIDRefs = poReader->ScanModuleReferences();
89 : else
90 3 : papszATIDRefs = CSLAddString(
91 3 : papszATIDRefs, poTransfer->GetCATD()->GetEntryModule(iCATDEntry));
92 :
93 12 : for (int iTable = 0;
94 12 : papszATIDRefs != nullptr && papszATIDRefs[iTable] != nullptr; iTable++)
95 : {
96 : /* --------------------------------------------------------------------
97 : */
98 : /* Get the attribute table reader, and the associated user */
99 : /* attribute field. */
100 : /* --------------------------------------------------------------------
101 : */
102 4 : const int nLayerIdx = poTransfer->FindLayer(papszATIDRefs[iTable]);
103 4 : if (nLayerIdx < 0)
104 0 : continue;
105 0 : SDTSAttrReader *poAttrReader = dynamic_cast<SDTSAttrReader *>(
106 4 : poTransfer->GetLayerIndexedReader(nLayerIdx));
107 :
108 4 : if (poAttrReader == nullptr)
109 0 : continue;
110 :
111 : DDFFieldDefn *poFDefn =
112 4 : poAttrReader->GetModule()->FindFieldDefn("ATTP");
113 4 : if (poFDefn == nullptr)
114 0 : poFDefn = poAttrReader->GetModule()->FindFieldDefn("ATTS");
115 4 : if (poFDefn == nullptr)
116 0 : continue;
117 :
118 : /* --------------------------------------------------------------------
119 : */
120 : /* Process each user subfield on the attribute table into an */
121 : /* OGR field definition. */
122 : /* --------------------------------------------------------------------
123 : */
124 64 : for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++)
125 : {
126 60 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF);
127 60 : const int nWidth = poSFDefn->GetWidth();
128 :
129 : char *pszFieldName =
130 60 : poFeatureDefn->GetFieldIndex(poSFDefn->GetName()) != -1
131 60 : ? CPLStrdup(CPLSPrintf("%s_%s", papszATIDRefs[iTable],
132 : poSFDefn->GetName()))
133 60 : : CPLStrdup(poSFDefn->GetName());
134 :
135 60 : switch (poSFDefn->GetType())
136 : {
137 44 : case DDFString:
138 : {
139 88 : OGRFieldDefn oStrField(pszFieldName, OFTString);
140 :
141 44 : if (nWidth != 0)
142 44 : oStrField.SetWidth(nWidth);
143 :
144 44 : poFeatureDefn->AddFieldDefn(&oStrField);
145 : }
146 44 : break;
147 :
148 4 : case DDFInt:
149 : {
150 8 : OGRFieldDefn oIntField(pszFieldName, OFTInteger);
151 :
152 4 : if (nWidth != 0)
153 4 : oIntField.SetWidth(nWidth);
154 :
155 4 : poFeatureDefn->AddFieldDefn(&oIntField);
156 : }
157 4 : break;
158 :
159 12 : case DDFFloat:
160 : {
161 24 : OGRFieldDefn oRealField(pszFieldName, OFTReal);
162 :
163 : // We don't have a precision in DDF files, so we never even
164 : // use the width. Otherwise with a precision of zero the
165 : // result would look like an integer.
166 :
167 12 : poFeatureDefn->AddFieldDefn(&oRealField);
168 : }
169 12 : break;
170 :
171 0 : default:
172 0 : break;
173 : }
174 :
175 60 : CPLFree(pszFieldName);
176 : } /* next iSF (subfield) */
177 : } /* next iTable */
178 8 : CSLDestroy(papszATIDRefs);
179 8 : }
180 :
181 : /************************************************************************/
182 : /* ~OGRSDTSLayer() */
183 : /************************************************************************/
184 :
185 16 : OGRSDTSLayer::~OGRSDTSLayer()
186 :
187 : {
188 8 : if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
189 : {
190 16 : CPLDebug("SDTS", "%d features read on layer '%s'.",
191 8 : static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
192 : }
193 :
194 8 : if (poFeatureDefn)
195 8 : poFeatureDefn->Release();
196 16 : }
197 :
198 : /************************************************************************/
199 : /* ResetReading() */
200 : /************************************************************************/
201 :
202 16 : void OGRSDTSLayer::ResetReading()
203 :
204 : {
205 16 : poReader->Rewind();
206 16 : }
207 :
208 : /************************************************************************/
209 : /* AssignAttrRecordToFeature() */
210 : /************************************************************************/
211 :
212 195 : static void AssignAttrRecordToFeature(OGRFeature *poFeature,
213 : CPL_UNUSED SDTSTransfer *poTransfer,
214 : DDFField *poSR)
215 : {
216 : /* -------------------------------------------------------------------- */
217 : /* Process each subfield in the record. */
218 : /* -------------------------------------------------------------------- */
219 195 : DDFFieldDefn *poFDefn = poSR->GetFieldDefn();
220 :
221 3027 : for (int iSF = 0; iSF < poFDefn->GetSubfieldCount(); iSF++)
222 : {
223 2832 : DDFSubfieldDefn *poSFDefn = poFDefn->GetSubfield(iSF);
224 2832 : int nMaxBytes = 0;
225 2832 : const char *pachData = poSR->GetSubfieldData(poSFDefn, &nMaxBytes);
226 : /* --------------------------------------------------------------------
227 : */
228 : /* Identify this field on the feature. */
229 : /* --------------------------------------------------------------------
230 : */
231 2832 : const int iField = poFeature->GetFieldIndex(poSFDefn->GetName());
232 :
233 : /* --------------------------------------------------------------------
234 : */
235 : /* Handle each of the types. */
236 : /* --------------------------------------------------------------------
237 : */
238 2832 : switch (poSFDefn->GetType())
239 : {
240 2466 : case DDFString:
241 : {
242 : const char *pszValue =
243 2466 : poSFDefn->ExtractStringData(pachData, nMaxBytes, nullptr);
244 :
245 2466 : if (iField != -1)
246 2466 : poFeature->SetField(iField, pszValue);
247 2466 : break;
248 : }
249 24 : case DDFFloat:
250 : {
251 : double dfValue =
252 24 : poSFDefn->ExtractFloatData(pachData, nMaxBytes, nullptr);
253 :
254 24 : if (iField != -1)
255 24 : poFeature->SetField(iField, dfValue);
256 24 : break;
257 : }
258 342 : case DDFInt:
259 : {
260 : int nValue =
261 342 : poSFDefn->ExtractIntData(pachData, nMaxBytes, nullptr);
262 :
263 342 : if (iField != -1)
264 342 : poFeature->SetField(iField, nValue);
265 342 : break;
266 : }
267 0 : default:
268 0 : break;
269 : }
270 : } /* next subfield */
271 195 : }
272 :
273 : /************************************************************************/
274 : /* GetNextUnfilteredFeature() */
275 : /************************************************************************/
276 :
277 391 : OGRFeature *OGRSDTSLayer::GetNextUnfilteredFeature()
278 :
279 : {
280 : /* -------------------------------------------------------------------- */
281 : /* If not done before we need to assemble the geometry for a */
282 : /* polygon layer. */
283 : /* -------------------------------------------------------------------- */
284 391 : if (poTransfer->GetLayerType(iLayer) == SLTPoly)
285 : {
286 38 : ((SDTSPolygonReader *)poReader)->AssembleRings(poTransfer, iLayer);
287 : }
288 :
289 : /* -------------------------------------------------------------------- */
290 : /* Fetch the next sdts style feature object from the reader. */
291 : /* -------------------------------------------------------------------- */
292 391 : SDTSFeature *poSDTSFeature = poReader->GetNextFeature();
293 : // Retain now the IsIndexed state to determine if we must delete or
294 : // not poSDTSFeature when done with it, because later calls might cause
295 : // indexing.
296 391 : const bool bIsIndexed = CPL_TO_BOOL(poReader->IsIndexed());
297 :
298 391 : if (poSDTSFeature == nullptr)
299 8 : return nullptr;
300 :
301 : /* -------------------------------------------------------------------- */
302 : /* Create the OGR feature. */
303 : /* -------------------------------------------------------------------- */
304 383 : OGRFeature *poFeature = new OGRFeature(poFeatureDefn);
305 :
306 383 : m_nFeaturesRead++;
307 :
308 383 : switch (poTransfer->GetLayerType(iLayer))
309 : {
310 : /* --------------------------------------------------------------------
311 : */
312 : /* Translate point feature specific information and geometry.
313 : */
314 : /* --------------------------------------------------------------------
315 : */
316 129 : case SLTPoint:
317 : {
318 129 : SDTSRawPoint *poPoint = (SDTSRawPoint *)poSDTSFeature;
319 :
320 129 : poFeature->SetGeometryDirectly(
321 129 : new OGRPoint(poPoint->dfX, poPoint->dfY, poPoint->dfZ));
322 : }
323 129 : break;
324 :
325 : /* --------------------------------------------------------------------
326 : */
327 : /* Translate line feature specific information and geometry. */
328 : /* --------------------------------------------------------------------
329 : */
330 28 : case SLTLine:
331 : {
332 28 : SDTSRawLine *poLine = (SDTSRawLine *)poSDTSFeature;
333 28 : OGRLineString *poOGRLine = new OGRLineString();
334 :
335 28 : poOGRLine->setPoints(poLine->nVertices, poLine->padfX,
336 28 : poLine->padfY, poLine->padfZ);
337 28 : poFeature->SetGeometryDirectly(poOGRLine);
338 28 : poFeature->SetField("SNID", (int)poLine->oStartNode.nRecord);
339 28 : poFeature->SetField("ENID", (int)poLine->oEndNode.nRecord);
340 : }
341 28 : break;
342 :
343 : /* --------------------------------------------------------------------
344 : */
345 : /* Translate polygon feature specific information and geometry.
346 : */
347 : /* --------------------------------------------------------------------
348 : */
349 37 : case SLTPoly:
350 : {
351 37 : SDTSRawPolygon *poPoly = (SDTSRawPolygon *)poSDTSFeature;
352 37 : OGRPolygon *poOGRPoly = new OGRPolygon();
353 :
354 58 : for (int iRing = 0; iRing < poPoly->nRings; iRing++)
355 : {
356 21 : OGRLinearRing *poRing = new OGRLinearRing();
357 21 : const int nVertices =
358 21 : iRing == poPoly->nRings - 1
359 21 : ? poPoly->nVertices - poPoly->panRingStart[iRing]
360 6 : : (poPoly->panRingStart[iRing + 1] -
361 6 : poPoly->panRingStart[iRing]);
362 :
363 21 : poRing->setPoints(nVertices,
364 21 : poPoly->padfX + poPoly->panRingStart[iRing],
365 21 : poPoly->padfY + poPoly->panRingStart[iRing],
366 21 : poPoly->padfZ + poPoly->panRingStart[iRing]);
367 :
368 21 : poOGRPoly->addRingDirectly(poRing);
369 : }
370 :
371 37 : poFeature->SetGeometryDirectly(poOGRPoly);
372 : }
373 37 : break;
374 :
375 189 : default:
376 189 : break;
377 : }
378 :
379 : /* -------------------------------------------------------------------- */
380 : /* Set attributes for any indicated attribute records. */
381 : /* -------------------------------------------------------------------- */
382 389 : for (int iAttrRecord = 0; iAttrRecord < poSDTSFeature->nAttributes;
383 : iAttrRecord++)
384 : {
385 : DDFField *poSR =
386 6 : poTransfer->GetAttr(poSDTSFeature->paoATID + iAttrRecord);
387 6 : if (poSR != nullptr)
388 6 : AssignAttrRecordToFeature(poFeature, poTransfer, poSR);
389 : }
390 :
391 : /* -------------------------------------------------------------------- */
392 : /* If this record is an attribute record, attach the local */
393 : /* attributes. */
394 : /* -------------------------------------------------------------------- */
395 383 : if (poTransfer->GetLayerType(iLayer) == SLTAttr)
396 : {
397 189 : AssignAttrRecordToFeature(poFeature, poTransfer,
398 : ((SDTSAttrRecord *)poSDTSFeature)->poATTR);
399 : }
400 :
401 : /* -------------------------------------------------------------------- */
402 : /* Translate the record id. */
403 : /* -------------------------------------------------------------------- */
404 383 : poFeature->SetFID(poSDTSFeature->oModId.nRecord);
405 383 : poFeature->SetField(0, (int)poSDTSFeature->oModId.nRecord);
406 383 : if (poFeature->GetGeometryRef() != nullptr)
407 388 : poFeature->GetGeometryRef()->assignSpatialReference(
408 194 : poDS->DSGetSpatialRef());
409 :
410 383 : if (!bIsIndexed)
411 346 : delete poSDTSFeature;
412 :
413 383 : return poFeature;
414 : }
415 :
416 : /************************************************************************/
417 : /* GetNextFeature() */
418 : /************************************************************************/
419 :
420 391 : OGRFeature *OGRSDTSLayer::GetNextFeature()
421 :
422 : {
423 391 : OGRFeature *poFeature = nullptr;
424 :
425 : /* -------------------------------------------------------------------- */
426 : /* Read features till we find one that satisfies our current */
427 : /* spatial criteria. */
428 : /* -------------------------------------------------------------------- */
429 : while (true)
430 : {
431 391 : poFeature = GetNextUnfilteredFeature();
432 391 : if (poFeature == nullptr)
433 8 : break;
434 :
435 766 : if ((m_poFilterGeom == nullptr ||
436 766 : FilterGeometry(poFeature->GetGeometryRef())) &&
437 383 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
438 383 : break;
439 :
440 0 : delete poFeature;
441 : }
442 :
443 391 : return poFeature;
444 : }
445 :
446 : /************************************************************************/
447 : /* TestCapability() */
448 : /************************************************************************/
449 :
450 0 : int OGRSDTSLayer::TestCapability(const char * /* pszCap */)
451 :
452 : {
453 0 : return FALSE;
454 : }
|