Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: OGR
4 : * Purpose: Implements OGRAVCLayer class. This is the base class for E00
5 : * and binary coverage layer implementations. It provides some base
6 : * layer operations, and methods for transforming between OGR
7 : * features, and the in memory structures of the AVC library.
8 : * Author: Frank Warmerdam, warmerdam@pobox.com
9 : *
10 : ******************************************************************************
11 : * Copyright (c) 2002, Frank Warmerdam <warmerdam@pobox.com>
12 : *
13 : * SPDX-License-Identifier: MIT
14 : ****************************************************************************/
15 :
16 : #include "ogr_avc.h"
17 : #include "cpl_conv.h"
18 : #include "cpl_string.h"
19 :
20 : /************************************************************************/
21 : /* OGRAVCLayer() */
22 : /************************************************************************/
23 :
24 14 : OGRAVCLayer::OGRAVCLayer(AVCFileType eSectionTypeIn, OGRAVCDataSource *poDSIn)
25 14 : : poFeatureDefn(nullptr), poDS(poDSIn), eSectionType(eSectionTypeIn)
26 : {
27 14 : }
28 :
29 : /************************************************************************/
30 : /* ~OGRAVCLayer() */
31 : /************************************************************************/
32 :
33 14 : OGRAVCLayer::~OGRAVCLayer()
34 :
35 : {
36 14 : if (m_nFeaturesRead > 0 && poFeatureDefn != nullptr)
37 : {
38 16 : CPLDebug("AVC", "%d features read on layer '%s'.",
39 8 : static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
40 : }
41 :
42 14 : if (poFeatureDefn != nullptr)
43 14 : poFeatureDefn->Release();
44 14 : }
45 :
46 : /************************************************************************/
47 : /* TestCapability() */
48 : /************************************************************************/
49 :
50 0 : int OGRAVCLayer::TestCapability(const char * /* pszCap */)
51 : {
52 0 : return FALSE;
53 : }
54 :
55 : /************************************************************************/
56 : /* SetupFeatureDefinition() */
57 : /************************************************************************/
58 :
59 14 : int OGRAVCLayer::SetupFeatureDefinition(const char *pszName)
60 :
61 : {
62 14 : bool bRet = false;
63 14 : switch (eSectionType)
64 : {
65 4 : case AVCFileARC:
66 : {
67 4 : poFeatureDefn = new OGRFeatureDefn(pszName);
68 4 : poFeatureDefn->Reference();
69 4 : poFeatureDefn->SetGeomType(wkbLineString);
70 :
71 8 : OGRFieldDefn oUserId("UserId", OFTInteger);
72 8 : OGRFieldDefn oFNode("FNODE_", OFTInteger);
73 8 : OGRFieldDefn oTNode("TNODE_", OFTInteger);
74 8 : OGRFieldDefn oLPoly("LPOLY_", OFTInteger);
75 8 : OGRFieldDefn oRPoly("RPOLY_", OFTInteger);
76 :
77 4 : poFeatureDefn->AddFieldDefn(&oUserId);
78 4 : poFeatureDefn->AddFieldDefn(&oFNode);
79 4 : poFeatureDefn->AddFieldDefn(&oTNode);
80 4 : poFeatureDefn->AddFieldDefn(&oLPoly);
81 4 : poFeatureDefn->AddFieldDefn(&oRPoly);
82 :
83 4 : bRet = true;
84 4 : break;
85 : }
86 :
87 2 : case AVCFilePAL:
88 : case AVCFileRPL:
89 : {
90 2 : poFeatureDefn = new OGRFeatureDefn(pszName);
91 2 : poFeatureDefn->Reference();
92 2 : poFeatureDefn->SetGeomType(wkbPolygon);
93 :
94 4 : OGRFieldDefn oArcIds("ArcIds", OFTIntegerList);
95 2 : poFeatureDefn->AddFieldDefn(&oArcIds);
96 :
97 2 : bRet = true;
98 2 : break;
99 : }
100 :
101 2 : case AVCFileCNT:
102 : {
103 2 : poFeatureDefn = new OGRFeatureDefn(pszName);
104 2 : poFeatureDefn->Reference();
105 2 : poFeatureDefn->SetGeomType(wkbPoint);
106 :
107 4 : OGRFieldDefn oLabelIds("LabelIds", OFTIntegerList);
108 2 : poFeatureDefn->AddFieldDefn(&oLabelIds);
109 :
110 2 : bRet = true;
111 2 : break;
112 : }
113 :
114 6 : case AVCFileLAB:
115 : {
116 6 : poFeatureDefn = new OGRFeatureDefn(pszName);
117 6 : poFeatureDefn->Reference();
118 6 : poFeatureDefn->SetGeomType(wkbPoint);
119 :
120 12 : OGRFieldDefn oValueId("ValueId", OFTInteger);
121 6 : poFeatureDefn->AddFieldDefn(&oValueId);
122 :
123 12 : OGRFieldDefn oPolyId("PolyId", OFTInteger);
124 6 : poFeatureDefn->AddFieldDefn(&oPolyId);
125 :
126 6 : bRet = true;
127 6 : break;
128 : }
129 :
130 0 : case AVCFileTXT:
131 : case AVCFileTX6:
132 : {
133 0 : poFeatureDefn = new OGRFeatureDefn(pszName);
134 0 : poFeatureDefn->Reference();
135 0 : poFeatureDefn->SetGeomType(wkbPoint);
136 :
137 0 : OGRFieldDefn oUserId("UserId", OFTInteger);
138 0 : poFeatureDefn->AddFieldDefn(&oUserId);
139 :
140 0 : OGRFieldDefn oText("Text", OFTString);
141 0 : poFeatureDefn->AddFieldDefn(&oText);
142 :
143 0 : OGRFieldDefn oHeight("Height", OFTReal);
144 0 : poFeatureDefn->AddFieldDefn(&oHeight);
145 :
146 0 : OGRFieldDefn oLevel("Level", OFTInteger);
147 0 : poFeatureDefn->AddFieldDefn(&oLevel);
148 :
149 0 : bRet = true;
150 0 : break;
151 : }
152 :
153 0 : default:
154 0 : poFeatureDefn = nullptr;
155 0 : break;
156 : }
157 :
158 14 : if (poFeatureDefn && poFeatureDefn->GetGeomFieldDefn(0))
159 : {
160 14 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
161 14 : poDS->DSGetSpatialRef());
162 : }
163 :
164 14 : SetDescription(pszName);
165 14 : return bRet;
166 : }
167 :
168 : /************************************************************************/
169 : /* TranslateFeature() */
170 : /* */
171 : /* Translate the AVC structure for a feature to the */
172 : /* corresponding OGR definition. It is assumed that the passed */
173 : /* in feature is of a type matching the section type */
174 : /* established by SetupFeatureDefinition(). */
175 : /************************************************************************/
176 :
177 310 : OGRFeature *OGRAVCLayer::TranslateFeature(void *pAVCFeature)
178 :
179 : {
180 310 : m_nFeaturesRead++;
181 :
182 310 : switch (eSectionType)
183 : {
184 : /* ====================================================================
185 : */
186 : /* ARC */
187 : /* ====================================================================
188 : */
189 58 : case AVCFileARC:
190 : {
191 58 : AVCArc *psArc = static_cast<AVCArc *>(pAVCFeature);
192 :
193 : /* --------------------------------------------------------------------
194 : */
195 : /* Create feature. */
196 : /* --------------------------------------------------------------------
197 : */
198 58 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
199 58 : poOGRFeature->SetFID(psArc->nArcId);
200 :
201 : /* --------------------------------------------------------------------
202 : */
203 : /* Apply the line geometry. */
204 : /* --------------------------------------------------------------------
205 : */
206 58 : OGRLineString *poLine = new OGRLineString();
207 :
208 58 : poLine->setNumPoints(psArc->numVertices);
209 210 : for (int iVert = 0; iVert < psArc->numVertices; iVert++)
210 152 : poLine->setPoint(iVert, psArc->pasVertices[iVert].x,
211 152 : psArc->pasVertices[iVert].y);
212 :
213 58 : poLine->assignSpatialReference(GetSpatialRef());
214 58 : poOGRFeature->SetGeometryDirectly(poLine);
215 :
216 : /* --------------------------------------------------------------------
217 : */
218 : /* Apply attributes. */
219 : /* --------------------------------------------------------------------
220 : */
221 58 : poOGRFeature->SetField(0, psArc->nUserId);
222 58 : poOGRFeature->SetField(1, psArc->nFNode);
223 58 : poOGRFeature->SetField(2, psArc->nTNode);
224 58 : poOGRFeature->SetField(3, psArc->nLPoly);
225 58 : poOGRFeature->SetField(4, psArc->nRPoly);
226 58 : return poOGRFeature;
227 : }
228 :
229 : /* ====================================================================
230 : */
231 : /* PAL (Polygon) */
232 : /* RPL (Region) */
233 : /* ====================================================================
234 : */
235 12 : case AVCFilePAL:
236 : case AVCFileRPL:
237 : {
238 12 : AVCPal *psPAL = static_cast<AVCPal *>(pAVCFeature);
239 :
240 : /* --------------------------------------------------------------------
241 : */
242 : /* Create feature. */
243 : /* --------------------------------------------------------------------
244 : */
245 12 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
246 12 : poOGRFeature->SetFID(psPAL->nPolyId);
247 :
248 : /* --------------------------------------------------------------------
249 : */
250 : /* Apply attributes. */
251 : /* --------------------------------------------------------------------
252 : */
253 : // Setup ArcId list.
254 : int *panArcs =
255 12 : static_cast<int *>(CPLMalloc(sizeof(int) * psPAL->numArcs));
256 57 : for (int i = 0; i < psPAL->numArcs; i++)
257 45 : panArcs[i] = psPAL->pasArcs[i].nArcId;
258 12 : poOGRFeature->SetField(0, psPAL->numArcs, panArcs);
259 12 : CPLFree(panArcs);
260 :
261 12 : return poOGRFeature;
262 : }
263 :
264 : /* ====================================================================
265 : */
266 : /* CNT (Centroid) */
267 : /* ====================================================================
268 : */
269 0 : case AVCFileCNT:
270 : {
271 0 : AVCCnt *psCNT = (AVCCnt *)pAVCFeature;
272 :
273 : /* --------------------------------------------------------------------
274 : */
275 : /* Create feature. */
276 : /* --------------------------------------------------------------------
277 : */
278 0 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
279 0 : poOGRFeature->SetFID(psCNT->nPolyId);
280 :
281 : /* --------------------------------------------------------------------
282 : */
283 : /* Apply Geometry */
284 : /* --------------------------------------------------------------------
285 : */
286 0 : OGRPoint *poPoint = new OGRPoint(psCNT->sCoord.x, psCNT->sCoord.y);
287 0 : poPoint->assignSpatialReference(GetSpatialRef());
288 0 : poOGRFeature->SetGeometryDirectly(poPoint);
289 :
290 : /* --------------------------------------------------------------------
291 : */
292 : /* Apply attributes. */
293 : /* --------------------------------------------------------------------
294 : */
295 0 : poOGRFeature->SetField(0, psCNT->numLabels, psCNT->panLabelIds);
296 :
297 0 : return poOGRFeature;
298 : }
299 :
300 : /* ====================================================================
301 : */
302 : /* LAB (Label) */
303 : /* ====================================================================
304 : */
305 240 : case AVCFileLAB:
306 : {
307 240 : AVCLab *psLAB = static_cast<AVCLab *>(pAVCFeature);
308 :
309 : /* --------------------------------------------------------------------
310 : */
311 : /* Create feature. */
312 : /* --------------------------------------------------------------------
313 : */
314 240 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
315 240 : poOGRFeature->SetFID(psLAB->nValue);
316 :
317 : /* --------------------------------------------------------------------
318 : */
319 : /* Apply Geometry */
320 : /* --------------------------------------------------------------------
321 : */
322 : OGRPoint *poPoint =
323 240 : new OGRPoint(psLAB->sCoord1.x, psLAB->sCoord1.y);
324 240 : poPoint->assignSpatialReference(GetSpatialRef());
325 240 : poOGRFeature->SetGeometryDirectly(poPoint);
326 :
327 : /* --------------------------------------------------------------------
328 : */
329 : /* Apply attributes. */
330 : /* --------------------------------------------------------------------
331 : */
332 240 : poOGRFeature->SetField(0, psLAB->nValue);
333 240 : poOGRFeature->SetField(1, psLAB->nPolyId);
334 :
335 240 : return poOGRFeature;
336 : }
337 :
338 : /* ====================================================================
339 : */
340 : /* TXT/TX6 (Text) */
341 : /* ====================================================================
342 : */
343 0 : case AVCFileTXT:
344 : case AVCFileTX6:
345 : {
346 0 : AVCTxt *psTXT = static_cast<AVCTxt *>(pAVCFeature);
347 :
348 : /* --------------------------------------------------------------------
349 : */
350 : /* Create feature. */
351 : /* --------------------------------------------------------------------
352 : */
353 0 : OGRFeature *poOGRFeature = new OGRFeature(GetLayerDefn());
354 0 : poOGRFeature->SetFID(psTXT->nTxtId);
355 :
356 : /* --------------------------------------------------------------------
357 : */
358 : /* Apply Geometry */
359 : /* --------------------------------------------------------------------
360 : */
361 0 : if (psTXT->numVerticesLine > 0)
362 : {
363 0 : OGRPoint *poPoint = new OGRPoint(psTXT->pasVertices[0].x,
364 0 : psTXT->pasVertices[0].y);
365 0 : poPoint->assignSpatialReference(GetSpatialRef());
366 0 : poOGRFeature->SetGeometryDirectly(poPoint);
367 : }
368 :
369 : /* --------------------------------------------------------------------
370 : */
371 : /* Apply attributes. */
372 : /* --------------------------------------------------------------------
373 : */
374 0 : poOGRFeature->SetField(0, psTXT->nUserId);
375 0 : poOGRFeature->SetField(1, reinterpret_cast<char *>(psTXT->pszText));
376 0 : poOGRFeature->SetField(2, psTXT->dHeight);
377 0 : poOGRFeature->SetField(3, psTXT->nLevel);
378 :
379 0 : return poOGRFeature;
380 : }
381 :
382 0 : default:
383 0 : return nullptr;
384 : }
385 : }
386 :
387 : /************************************************************************/
388 : /* MatchesSpatialFilter() */
389 : /************************************************************************/
390 :
391 268 : bool OGRAVCLayer::MatchesSpatialFilter(void *pFeature)
392 :
393 : {
394 268 : if (m_poFilterGeom == nullptr)
395 268 : return true;
396 :
397 0 : switch (eSectionType)
398 : {
399 : /* ====================================================================
400 : */
401 : /* ARC */
402 : /* */
403 : /* Check each line segment for possible intersection. */
404 : /* ====================================================================
405 : */
406 0 : case AVCFileARC:
407 : {
408 0 : AVCArc *psArc = static_cast<AVCArc *>(pFeature);
409 :
410 0 : for (int iVert = 0; iVert < psArc->numVertices - 1; iVert++)
411 : {
412 0 : AVCVertex *psV1 = psArc->pasVertices + iVert;
413 0 : AVCVertex *psV2 = psArc->pasVertices + iVert + 1;
414 :
415 0 : if ((psV1->x < m_sFilterEnvelope.MinX &&
416 0 : psV2->x < m_sFilterEnvelope.MinX) ||
417 0 : (psV1->x > m_sFilterEnvelope.MaxX &&
418 0 : psV2->x > m_sFilterEnvelope.MaxX) ||
419 0 : (psV1->y < m_sFilterEnvelope.MinY &&
420 0 : psV2->y < m_sFilterEnvelope.MinY) ||
421 0 : (psV1->y > m_sFilterEnvelope.MaxY &&
422 0 : psV2->y > m_sFilterEnvelope.MaxY))
423 : /* This segment is completely outside extents */;
424 : else
425 0 : return true;
426 : }
427 :
428 0 : return false;
429 : }
430 :
431 : /* ====================================================================
432 : */
433 : /* PAL (Polygon) */
434 : /* RPL (Region) */
435 : /* */
436 : /* Check against the polygon bounds stored in the PAL. */
437 : /* ====================================================================
438 : */
439 0 : case AVCFilePAL:
440 : case AVCFileRPL:
441 : {
442 0 : AVCPal *psPAL = (AVCPal *)pFeature;
443 :
444 0 : if (psPAL->sMin.x > m_sFilterEnvelope.MaxX ||
445 0 : psPAL->sMax.x < m_sFilterEnvelope.MinX ||
446 0 : psPAL->sMin.y > m_sFilterEnvelope.MaxY ||
447 0 : psPAL->sMax.y < m_sFilterEnvelope.MinY)
448 0 : return false;
449 : else
450 0 : return true;
451 : }
452 :
453 : /* ====================================================================
454 : */
455 : /* CNT (Centroid) */
456 : /* ====================================================================
457 : */
458 0 : case AVCFileCNT:
459 : {
460 0 : AVCCnt *psCNT = static_cast<AVCCnt *>(pFeature);
461 :
462 0 : if (psCNT->sCoord.x < m_sFilterEnvelope.MinX ||
463 0 : psCNT->sCoord.x > m_sFilterEnvelope.MaxX ||
464 0 : psCNT->sCoord.y < m_sFilterEnvelope.MinY ||
465 0 : psCNT->sCoord.y > m_sFilterEnvelope.MaxY)
466 0 : return false;
467 : else
468 0 : return true;
469 : }
470 :
471 : /* ====================================================================
472 : */
473 : /* LAB (Label) */
474 : /* ====================================================================
475 : */
476 0 : case AVCFileLAB:
477 : {
478 0 : AVCLab *psLAB = (AVCLab *)pFeature;
479 :
480 0 : if (psLAB->sCoord1.x < m_sFilterEnvelope.MinX ||
481 0 : psLAB->sCoord1.x > m_sFilterEnvelope.MaxX ||
482 0 : psLAB->sCoord1.y < m_sFilterEnvelope.MinY ||
483 0 : psLAB->sCoord1.y > m_sFilterEnvelope.MaxY)
484 0 : return false;
485 : else
486 0 : return true;
487 : }
488 :
489 : /* ====================================================================
490 : */
491 : /* TXT/TX6 (Text) */
492 : /* ====================================================================
493 : */
494 0 : case AVCFileTXT:
495 : case AVCFileTX6:
496 : {
497 0 : AVCTxt *psTXT = static_cast<AVCTxt *>(pFeature);
498 :
499 0 : if (psTXT->numVerticesLine == 0)
500 0 : return true;
501 :
502 0 : if (psTXT->pasVertices[0].x < m_sFilterEnvelope.MinX ||
503 0 : psTXT->pasVertices[0].x > m_sFilterEnvelope.MaxX ||
504 0 : psTXT->pasVertices[0].y < m_sFilterEnvelope.MinY ||
505 0 : psTXT->pasVertices[0].y > m_sFilterEnvelope.MaxY)
506 0 : return false;
507 :
508 0 : return true;
509 : }
510 :
511 0 : default:
512 0 : return true;
513 : }
514 : }
515 :
516 : /************************************************************************/
517 : /* AppendTableDefinition() */
518 : /* */
519 : /* Add fields to this layers feature definition based on the */
520 : /* definition from the coverage. */
521 : /************************************************************************/
522 :
523 6 : bool OGRAVCLayer::AppendTableDefinition(AVCTableDef *psTableDef)
524 :
525 : {
526 32 : for (int iField = 0; iField < psTableDef->numFields; iField++)
527 : {
528 26 : AVCFieldInfo *psFInfo = psTableDef->pasFieldDef + iField;
529 : char szFieldName[128];
530 :
531 : /* Strip off white space */
532 26 : strcpy(szFieldName, psFInfo->szName);
533 26 : if (strstr(szFieldName, " ") != nullptr)
534 26 : *(strstr(szFieldName, " ")) = '\0';
535 :
536 26 : OGRFieldDefn oFDefn(szFieldName, OFTInteger);
537 :
538 26 : if (psFInfo->nIndex < 0)
539 0 : continue;
540 :
541 : // Skip FNODE#, TNODE#, LPOLY# and RPOLY# from AAT table.
542 26 : if (eSectionType == AVCFileARC && iField < 4)
543 0 : continue;
544 :
545 26 : oFDefn.SetWidth(psFInfo->nFmtWidth);
546 :
547 26 : if (psFInfo->nType1 * 10 == AVC_FT_DATE ||
548 26 : psFInfo->nType1 * 10 == AVC_FT_CHAR)
549 2 : oFDefn.SetType(OFTString);
550 :
551 24 : else if (psFInfo->nType1 * 10 == AVC_FT_FIXINT ||
552 24 : psFInfo->nType1 * 10 == AVC_FT_BININT)
553 12 : oFDefn.SetType(OFTInteger);
554 :
555 12 : else if (psFInfo->nType1 * 10 == AVC_FT_FIXNUM ||
556 12 : psFInfo->nType1 * 10 == AVC_FT_BINFLOAT)
557 : {
558 12 : oFDefn.SetType(OFTReal);
559 12 : if (psFInfo->nFmtPrec > 0)
560 12 : oFDefn.SetPrecision(psFInfo->nFmtPrec);
561 : }
562 :
563 26 : poFeatureDefn->AddFieldDefn(&oFDefn);
564 : }
565 6 : return TRUE;
566 : }
567 :
568 : /************************************************************************/
569 : /* TranslateTableFields() */
570 : /************************************************************************/
571 :
572 252 : bool OGRAVCLayer::TranslateTableFields(OGRFeature *poFeature, int nFieldBase,
573 : AVCTableDef *psTableDef,
574 : AVCField *pasFields)
575 :
576 : {
577 252 : int iOutField = nFieldBase;
578 :
579 1500 : for (int iField = 0; iField < psTableDef->numFields; iField++)
580 : {
581 1248 : AVCFieldInfo *psFInfo = psTableDef->pasFieldDef + iField;
582 1248 : int nType = psFInfo->nType1 * 10;
583 :
584 1248 : if (psFInfo->nIndex < 0)
585 0 : continue;
586 :
587 : // Skip FNODE#, TNODE#, LPOLY# and RPOLY# from AAT table.
588 1248 : if (eSectionType == AVCFileARC && iField < 4)
589 0 : continue;
590 :
591 1248 : if (nType == AVC_FT_DATE || nType == AVC_FT_CHAR ||
592 1008 : nType == AVC_FT_FIXINT || nType == AVC_FT_FIXNUM)
593 : {
594 240 : if (nType == AVC_FT_CHAR)
595 : {
596 : /* Remove trailing spaces in char fields */
597 : size_t nLen =
598 240 : strlen(reinterpret_cast<char *>(pasFields[iField].pszStr));
599 4080 : while (nLen > 0 && pasFields[iField].pszStr[nLen - 1] == ' ')
600 3840 : nLen--;
601 240 : pasFields[iField].pszStr[nLen] = '\0';
602 : }
603 240 : poFeature->SetField(iOutField++, reinterpret_cast<char *>(
604 240 : pasFields[iField].pszStr));
605 : }
606 1008 : else if (nType == AVC_FT_BININT && psFInfo->nSize == 4)
607 : {
608 504 : poFeature->SetField(iOutField++, pasFields[iField].nInt32);
609 : }
610 504 : else if (nType == AVC_FT_BININT && psFInfo->nSize == 2)
611 : {
612 0 : poFeature->SetField(iOutField++, pasFields[iField].nInt16);
613 : }
614 504 : else if (nType == AVC_FT_BINFLOAT && psFInfo->nSize == 4)
615 : {
616 504 : poFeature->SetField(iOutField++, pasFields[iField].fFloat);
617 : }
618 0 : else if (nType == AVC_FT_BINFLOAT && psFInfo->nSize == 8)
619 : {
620 0 : poFeature->SetField(iOutField++, pasFields[iField].dDouble);
621 : }
622 : else
623 : {
624 0 : CPLAssert(false);
625 : return false;
626 : }
627 : }
628 :
629 252 : return true;
630 : }
|