Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: Interlis 2 Translator
4 : * Purpose: Implements OGRILI2Layer class.
5 : * Author: Markus Schnider, Sourcepole AG
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 2004, Pirmin Kalberer, Sourcepole AG
9 : * Copyright (c) 2008-2012, Even Rouault <even dot rouault at spatialys.com>
10 : *
11 : * SPDX-License-Identifier: MIT
12 : ****************************************************************************/
13 :
14 : #include "cpl_conv.h"
15 : #include "cpl_string.h"
16 : #include "ogr_ili2.h"
17 :
18 : /************************************************************************/
19 : /* OGRILI2Layer() */
20 : /************************************************************************/
21 :
22 46 : OGRILI2Layer::OGRILI2Layer(OGRFeatureDefn *poFeatureDefnIn,
23 : const GeomFieldInfos &oGeomFieldInfosIn,
24 46 : OGRILI2DataSource *poDSIn)
25 : : poFeatureDefn(poFeatureDefnIn), oGeomFieldInfos(oGeomFieldInfosIn),
26 46 : poDS(poDSIn)
27 : {
28 46 : SetDescription(poFeatureDefn->GetName());
29 46 : poFeatureDefn->Reference();
30 :
31 46 : listFeatureIt = listFeature.begin();
32 46 : }
33 :
34 : /************************************************************************/
35 : /* ~OGRILI2Layer() */
36 : /************************************************************************/
37 :
38 92 : OGRILI2Layer::~OGRILI2Layer()
39 : {
40 46 : if (poFeatureDefn)
41 46 : poFeatureDefn->Release();
42 :
43 46 : listFeatureIt = listFeature.begin();
44 568 : while (listFeatureIt != listFeature.end())
45 : {
46 522 : OGRFeature *poFeature = *(listFeatureIt++);
47 522 : delete poFeature;
48 : }
49 92 : }
50 :
51 : /************************************************************************/
52 : /* AddFeature() */
53 : /************************************************************************/
54 :
55 522 : void OGRILI2Layer::AddFeature(OGRFeature *poFeature)
56 : {
57 522 : poFeature->SetFID(static_cast<GIntBig>(1 + listFeature.size()));
58 522 : listFeature.push_back(poFeature);
59 522 : }
60 :
61 : /************************************************************************/
62 : /* ResetReading() */
63 : /************************************************************************/
64 :
65 44 : void OGRILI2Layer::ResetReading()
66 : {
67 44 : listFeatureIt = listFeature.begin();
68 44 : }
69 :
70 : /************************************************************************/
71 : /* GetNextFeature() */
72 : /************************************************************************/
73 :
74 6 : OGRFeature *OGRILI2Layer::GetNextFeature()
75 : {
76 6 : while (listFeatureIt != listFeature.end())
77 : {
78 6 : OGRFeature *poFeature = *(listFeatureIt++);
79 : // apply filters
80 12 : if ((m_poFilterGeom == nullptr ||
81 12 : FilterGeometry(poFeature->GetGeometryRef())) &&
82 6 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
83 6 : return poFeature->Clone();
84 : }
85 0 : return nullptr;
86 : }
87 :
88 : /************************************************************************/
89 : /* GetFeatureCount() */
90 : /************************************************************************/
91 :
92 4 : GIntBig OGRILI2Layer::GetFeatureCount(int bForce)
93 : {
94 4 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
95 : {
96 4 : return listFeature.size();
97 : }
98 : else
99 : {
100 0 : return OGRLayer::GetFeatureCount(bForce);
101 : }
102 : }
103 :
104 : #ifndef d2str_defined
105 : #define d2str_defined
106 :
107 40 : static const char *d2str(double val)
108 : {
109 40 : if (val == (int)val)
110 0 : return CPLSPrintf("%d", (int)val);
111 40 : if (fabs(val) < 370)
112 40 : return CPLSPrintf("%.16g", val);
113 0 : if (fabs(val) > 100000000.0)
114 0 : return CPLSPrintf("%.16g", val);
115 :
116 0 : return CPLSPrintf("%.3f", val);
117 : }
118 : #endif
119 :
120 1 : static void AppendCoordinateList(const OGRLineString *poLine, VSILFILE *fp)
121 : {
122 1 : const bool b3D = CPL_TO_BOOL(wkbHasZ(poLine->getGeometryType()));
123 :
124 20 : for (int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++)
125 : {
126 19 : VSIFPrintfL(fp, "<COORD>");
127 19 : VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poLine->getX(iPoint)));
128 19 : VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poLine->getY(iPoint)));
129 19 : if (b3D)
130 0 : VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poLine->getZ(iPoint)));
131 19 : VSIFPrintfL(fp, "</COORD>\n");
132 : }
133 1 : }
134 :
135 3 : static int OGR2ILIGeometryAppend(const OGRGeometry *poGeometry, VSILFILE *fp,
136 : const char *attrname,
137 : const CPLString &iliGeomType)
138 : {
139 : #ifdef DEBUG_VERBOSE
140 : CPLDebug("OGR_ILI",
141 : "OGR2ILIGeometryAppend getGeometryType %s iliGeomType %s",
142 : poGeometry->getGeometryName(), iliGeomType.c_str());
143 : #endif
144 : /* -------------------------------------------------------------------- */
145 : /* 2D/3D Point */
146 : /* -------------------------------------------------------------------- */
147 5 : if (poGeometry->getGeometryType() == wkbPoint ||
148 2 : poGeometry->getGeometryType() == wkbPoint25D)
149 : {
150 1 : const OGRPoint *poPoint = poGeometry->toPoint();
151 :
152 1 : VSIFPrintfL(fp, "<%s>\n", attrname);
153 1 : VSIFPrintfL(fp, "<COORD>");
154 1 : VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poPoint->getX()));
155 1 : VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poPoint->getY()));
156 1 : if (poGeometry->getGeometryType() == wkbPoint25D)
157 0 : VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poPoint->getZ()));
158 1 : VSIFPrintfL(fp, "</COORD>\n");
159 1 : VSIFPrintfL(fp, "</%s>\n", attrname);
160 : }
161 :
162 : /* -------------------------------------------------------------------- */
163 : /* LineString and LinearRing */
164 : /* -------------------------------------------------------------------- */
165 3 : else if (poGeometry->getGeometryType() == wkbLineString ||
166 1 : poGeometry->getGeometryType() == wkbLineString25D)
167 : {
168 1 : if (attrname)
169 0 : VSIFPrintfL(fp, "<%s>\n", attrname);
170 1 : VSIFPrintfL(fp, "<POLYLINE>\n");
171 : // unclipped polyline, add one sequence
172 : // VSIFPrintfL(fp, "<SEGMENTS>\n");
173 1 : AppendCoordinateList(poGeometry->toLineString(), fp);
174 : // VSIFPrintfL(fp, "</SEGMENTS>\n");
175 1 : VSIFPrintfL(fp, "</POLYLINE>\n");
176 1 : if (attrname)
177 0 : VSIFPrintfL(fp, "</%s>\n", attrname);
178 : }
179 :
180 : /* -------------------------------------------------------------------- */
181 : /* Polygon */
182 : /* -------------------------------------------------------------------- */
183 1 : else if (poGeometry->getGeometryType() == wkbPolygon ||
184 0 : poGeometry->getGeometryType() == wkbPolygon25D)
185 : {
186 1 : const OGRPolygon *poPolygon = poGeometry->toPolygon();
187 :
188 1 : if (attrname)
189 1 : VSIFPrintfL(fp, "<%s>\n", attrname);
190 1 : if (iliGeomType == "Surface" || iliGeomType == "Area")
191 : {
192 : // VSIFPrintfL(fp, "<MULTISURFACE>\n");
193 1 : VSIFPrintfL(fp, "<SURFACE>\n");
194 1 : VSIFPrintfL(fp, "<BOUNDARY>\n");
195 : }
196 :
197 2 : for (auto &&poRing : *poPolygon)
198 : {
199 1 : if (!OGR2ILIGeometryAppend(poRing, fp, nullptr, ""))
200 0 : return FALSE;
201 : }
202 1 : if (iliGeomType == "Surface" || iliGeomType == "Area")
203 : {
204 1 : VSIFPrintfL(fp, "</BOUNDARY>\n");
205 1 : VSIFPrintfL(fp, "</SURFACE>\n");
206 : // VSIFPrintfL(fp, "</MULTISURFACE>\n");
207 : }
208 1 : if (attrname)
209 1 : VSIFPrintfL(fp, "</%s>\n", attrname);
210 : }
211 :
212 : /* -------------------------------------------------------------------- */
213 : /* MultiPolygon */
214 : /* -------------------------------------------------------------------- */
215 0 : else if (wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon ||
216 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString ||
217 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint ||
218 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection)
219 : {
220 0 : const OGRGeometryCollection *poGC = poGeometry->toGeometryCollection();
221 :
222 : #if 0
223 : // TODO: Why were these all blank?
224 : if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
225 : {
226 : }
227 : else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
228 : {
229 : }
230 : else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
231 : {
232 : }
233 : else
234 : {
235 : }
236 : #endif
237 0 : for (auto &&poMember : *poGC)
238 : {
239 0 : if (!OGR2ILIGeometryAppend(poMember, fp, nullptr, ""))
240 0 : return FALSE;
241 : }
242 : }
243 :
244 : else
245 0 : return FALSE;
246 :
247 3 : return TRUE;
248 : }
249 :
250 : /************************************************************************/
251 : /* ICreateFeature() */
252 : /************************************************************************/
253 :
254 2 : OGRErr OGRILI2Layer::ICreateFeature(OGRFeature *poFeature)
255 : {
256 : char szTempBuffer[80];
257 2 : const char *tid = nullptr;
258 2 : int iField = 0;
259 4 : if (poFeatureDefn->GetFieldCount() &&
260 2 : EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "TID"))
261 : {
262 2 : tid = poFeature->GetFieldAsString(0);
263 2 : ++iField;
264 : }
265 : else
266 : {
267 0 : snprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB,
268 : poFeature->GetFID());
269 0 : tid = szTempBuffer;
270 : }
271 :
272 2 : VSILFILE *fp = poDS->GetOutputFP();
273 2 : if (fp == nullptr)
274 0 : return OGRERR_FAILURE;
275 :
276 2 : VSIFPrintfL(fp, "<%s TID=\"%s\">\n", poFeatureDefn->GetName(), tid);
277 :
278 : // Write out Geometries
279 4 : for (int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount();
280 : iGeomField++)
281 : {
282 : OGRGeomFieldDefn *poFieldDefn =
283 2 : poFeatureDefn->GetGeomFieldDefn(iGeomField);
284 2 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
285 2 : if (poGeom != nullptr)
286 : {
287 4 : CPLString iliGeomType = GetIliGeomType(poFieldDefn->GetNameRef());
288 2 : OGR2ILIGeometryAppend(poGeom, fp, poFieldDefn->GetNameRef(),
289 : iliGeomType);
290 : }
291 : }
292 :
293 : // Write all "set" fields.
294 4 : for (; iField < poFeatureDefn->GetFieldCount(); iField++)
295 : {
296 :
297 2 : OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn(iField);
298 :
299 2 : if (poFeature->IsFieldSetAndNotNull(iField))
300 : {
301 2 : const char *pszRaw = poFeature->GetFieldAsString(iField);
302 2 : VSIFPrintfL(fp, "<%s>%s</%s>\n", poField->GetNameRef(), pszRaw,
303 : poField->GetNameRef());
304 : }
305 : }
306 :
307 2 : VSIFPrintfL(fp, "</%s>\n", poFeatureDefn->GetName());
308 :
309 2 : return OGRERR_NONE;
310 : }
311 :
312 : /************************************************************************/
313 : /* TestCapability() */
314 : /************************************************************************/
315 :
316 4 : int OGRILI2Layer::TestCapability(CPL_UNUSED const char *pszCap)
317 : {
318 4 : if (EQUAL(pszCap, OLCCurveGeometries))
319 2 : return TRUE;
320 2 : else if (EQUAL(pszCap, OLCZGeometries))
321 0 : return TRUE;
322 :
323 2 : return FALSE;
324 : }
325 :
326 : /************************************************************************/
327 : /* CreateField() */
328 : /************************************************************************/
329 :
330 0 : OGRErr OGRILI2Layer::CreateField(const OGRFieldDefn *poField,
331 : int /* bApproxOK */)
332 : {
333 0 : poFeatureDefn->AddFieldDefn(poField);
334 0 : return OGRERR_NONE;
335 : }
336 :
337 : /************************************************************************/
338 : /* GetDataset() */
339 : /************************************************************************/
340 :
341 1 : GDALDataset *OGRILI2Layer::GetDataset()
342 : {
343 1 : return poDS;
344 : }
|