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 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "cpl_conv.h"
31 : #include "cpl_string.h"
32 : #include "ogr_ili2.h"
33 :
34 : /************************************************************************/
35 : /* OGRILI2Layer() */
36 : /************************************************************************/
37 :
38 46 : OGRILI2Layer::OGRILI2Layer(OGRFeatureDefn *poFeatureDefnIn,
39 : const GeomFieldInfos &oGeomFieldInfosIn,
40 46 : OGRILI2DataSource *poDSIn)
41 : : poFeatureDefn(poFeatureDefnIn), oGeomFieldInfos(oGeomFieldInfosIn),
42 46 : poDS(poDSIn)
43 : {
44 46 : SetDescription(poFeatureDefn->GetName());
45 46 : poFeatureDefn->Reference();
46 :
47 46 : listFeatureIt = listFeature.begin();
48 46 : }
49 :
50 : /************************************************************************/
51 : /* ~OGRILI2Layer() */
52 : /************************************************************************/
53 :
54 92 : OGRILI2Layer::~OGRILI2Layer()
55 : {
56 46 : if (poFeatureDefn)
57 46 : poFeatureDefn->Release();
58 :
59 46 : listFeatureIt = listFeature.begin();
60 568 : while (listFeatureIt != listFeature.end())
61 : {
62 522 : OGRFeature *poFeature = *(listFeatureIt++);
63 522 : delete poFeature;
64 : }
65 92 : }
66 :
67 : /************************************************************************/
68 : /* AddFeature() */
69 : /************************************************************************/
70 :
71 522 : void OGRILI2Layer::AddFeature(OGRFeature *poFeature)
72 : {
73 522 : poFeature->SetFID(static_cast<GIntBig>(1 + listFeature.size()));
74 522 : listFeature.push_back(poFeature);
75 522 : }
76 :
77 : /************************************************************************/
78 : /* ResetReading() */
79 : /************************************************************************/
80 :
81 44 : void OGRILI2Layer::ResetReading()
82 : {
83 44 : listFeatureIt = listFeature.begin();
84 44 : }
85 :
86 : /************************************************************************/
87 : /* GetNextFeature() */
88 : /************************************************************************/
89 :
90 6 : OGRFeature *OGRILI2Layer::GetNextFeature()
91 : {
92 6 : while (listFeatureIt != listFeature.end())
93 : {
94 6 : OGRFeature *poFeature = *(listFeatureIt++);
95 : // apply filters
96 12 : if ((m_poFilterGeom == nullptr ||
97 12 : FilterGeometry(poFeature->GetGeometryRef())) &&
98 6 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
99 6 : return poFeature->Clone();
100 : }
101 0 : return nullptr;
102 : }
103 :
104 : /************************************************************************/
105 : /* GetFeatureCount() */
106 : /************************************************************************/
107 :
108 4 : GIntBig OGRILI2Layer::GetFeatureCount(int bForce)
109 : {
110 4 : if (m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
111 : {
112 4 : return listFeature.size();
113 : }
114 : else
115 : {
116 0 : return OGRLayer::GetFeatureCount(bForce);
117 : }
118 : }
119 :
120 : #ifndef d2str_defined
121 : #define d2str_defined
122 :
123 40 : static const char *d2str(double val)
124 : {
125 40 : if (val == (int)val)
126 0 : return CPLSPrintf("%d", (int)val);
127 40 : if (fabs(val) < 370)
128 40 : return CPLSPrintf("%.16g", val);
129 0 : if (fabs(val) > 100000000.0)
130 0 : return CPLSPrintf("%.16g", val);
131 :
132 0 : return CPLSPrintf("%.3f", val);
133 : }
134 : #endif
135 :
136 1 : static void AppendCoordinateList(const OGRLineString *poLine, VSILFILE *fp)
137 : {
138 1 : const bool b3D = CPL_TO_BOOL(wkbHasZ(poLine->getGeometryType()));
139 :
140 20 : for (int iPoint = 0; iPoint < poLine->getNumPoints(); iPoint++)
141 : {
142 19 : VSIFPrintfL(fp, "<COORD>");
143 19 : VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poLine->getX(iPoint)));
144 19 : VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poLine->getY(iPoint)));
145 19 : if (b3D)
146 0 : VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poLine->getZ(iPoint)));
147 19 : VSIFPrintfL(fp, "</COORD>\n");
148 : }
149 1 : }
150 :
151 3 : static int OGR2ILIGeometryAppend(const OGRGeometry *poGeometry, VSILFILE *fp,
152 : const char *attrname,
153 : const CPLString &iliGeomType)
154 : {
155 : #ifdef DEBUG_VERBOSE
156 : CPLDebug("OGR_ILI",
157 : "OGR2ILIGeometryAppend getGeometryType %s iliGeomType %s",
158 : poGeometry->getGeometryName(), iliGeomType.c_str());
159 : #endif
160 : /* -------------------------------------------------------------------- */
161 : /* 2D/3D Point */
162 : /* -------------------------------------------------------------------- */
163 5 : if (poGeometry->getGeometryType() == wkbPoint ||
164 2 : poGeometry->getGeometryType() == wkbPoint25D)
165 : {
166 1 : const OGRPoint *poPoint = poGeometry->toPoint();
167 :
168 1 : VSIFPrintfL(fp, "<%s>\n", attrname);
169 1 : VSIFPrintfL(fp, "<COORD>");
170 1 : VSIFPrintfL(fp, "<C1>%s</C1>", d2str(poPoint->getX()));
171 1 : VSIFPrintfL(fp, "<C2>%s</C2>", d2str(poPoint->getY()));
172 1 : if (poGeometry->getGeometryType() == wkbPoint25D)
173 0 : VSIFPrintfL(fp, "<C3>%s</C3>", d2str(poPoint->getZ()));
174 1 : VSIFPrintfL(fp, "</COORD>\n");
175 1 : VSIFPrintfL(fp, "</%s>\n", attrname);
176 : }
177 :
178 : /* -------------------------------------------------------------------- */
179 : /* LineString and LinearRing */
180 : /* -------------------------------------------------------------------- */
181 3 : else if (poGeometry->getGeometryType() == wkbLineString ||
182 1 : poGeometry->getGeometryType() == wkbLineString25D)
183 : {
184 1 : if (attrname)
185 0 : VSIFPrintfL(fp, "<%s>\n", attrname);
186 1 : VSIFPrintfL(fp, "<POLYLINE>\n");
187 : // unclipped polyline, add one sequence
188 : // VSIFPrintfL(fp, "<SEGMENTS>\n");
189 1 : AppendCoordinateList(poGeometry->toLineString(), fp);
190 : // VSIFPrintfL(fp, "</SEGMENTS>\n");
191 1 : VSIFPrintfL(fp, "</POLYLINE>\n");
192 1 : if (attrname)
193 0 : VSIFPrintfL(fp, "</%s>\n", attrname);
194 : }
195 :
196 : /* -------------------------------------------------------------------- */
197 : /* Polygon */
198 : /* -------------------------------------------------------------------- */
199 1 : else if (poGeometry->getGeometryType() == wkbPolygon ||
200 0 : poGeometry->getGeometryType() == wkbPolygon25D)
201 : {
202 1 : const OGRPolygon *poPolygon = poGeometry->toPolygon();
203 :
204 1 : if (attrname)
205 1 : VSIFPrintfL(fp, "<%s>\n", attrname);
206 1 : if (iliGeomType == "Surface" || iliGeomType == "Area")
207 : {
208 : // VSIFPrintfL(fp, "<MULTISURFACE>\n");
209 1 : VSIFPrintfL(fp, "<SURFACE>\n");
210 1 : VSIFPrintfL(fp, "<BOUNDARY>\n");
211 : }
212 :
213 2 : for (auto &&poRing : *poPolygon)
214 : {
215 1 : if (!OGR2ILIGeometryAppend(poRing, fp, nullptr, ""))
216 0 : return FALSE;
217 : }
218 1 : if (iliGeomType == "Surface" || iliGeomType == "Area")
219 : {
220 1 : VSIFPrintfL(fp, "</BOUNDARY>\n");
221 1 : VSIFPrintfL(fp, "</SURFACE>\n");
222 : // VSIFPrintfL(fp, "</MULTISURFACE>\n");
223 : }
224 1 : if (attrname)
225 1 : VSIFPrintfL(fp, "</%s>\n", attrname);
226 : }
227 :
228 : /* -------------------------------------------------------------------- */
229 : /* MultiPolygon */
230 : /* -------------------------------------------------------------------- */
231 0 : else if (wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon ||
232 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString ||
233 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint ||
234 0 : wkbFlatten(poGeometry->getGeometryType()) == wkbGeometryCollection)
235 : {
236 0 : const OGRGeometryCollection *poGC = poGeometry->toGeometryCollection();
237 :
238 : #if 0
239 : // TODO: Why were these all blank?
240 : if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPolygon )
241 : {
242 : }
243 : else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiLineString )
244 : {
245 : }
246 : else if( wkbFlatten(poGeometry->getGeometryType()) == wkbMultiPoint )
247 : {
248 : }
249 : else
250 : {
251 : }
252 : #endif
253 0 : for (auto &&poMember : *poGC)
254 : {
255 0 : if (!OGR2ILIGeometryAppend(poMember, fp, nullptr, ""))
256 0 : return FALSE;
257 : }
258 : }
259 :
260 : else
261 0 : return FALSE;
262 :
263 3 : return TRUE;
264 : }
265 :
266 : /************************************************************************/
267 : /* ICreateFeature() */
268 : /************************************************************************/
269 :
270 2 : OGRErr OGRILI2Layer::ICreateFeature(OGRFeature *poFeature)
271 : {
272 : char szTempBuffer[80];
273 2 : const char *tid = nullptr;
274 2 : int iField = 0;
275 4 : if (poFeatureDefn->GetFieldCount() &&
276 2 : EQUAL(poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), "TID"))
277 : {
278 2 : tid = poFeature->GetFieldAsString(0);
279 2 : ++iField;
280 : }
281 : else
282 : {
283 0 : snprintf(szTempBuffer, sizeof(szTempBuffer), CPL_FRMT_GIB,
284 : poFeature->GetFID());
285 0 : tid = szTempBuffer;
286 : }
287 :
288 2 : VSILFILE *fp = poDS->GetOutputFP();
289 2 : if (fp == nullptr)
290 0 : return OGRERR_FAILURE;
291 :
292 2 : VSIFPrintfL(fp, "<%s TID=\"%s\">\n", poFeatureDefn->GetName(), tid);
293 :
294 : // Write out Geometries
295 4 : for (int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount();
296 : iGeomField++)
297 : {
298 : OGRGeomFieldDefn *poFieldDefn =
299 2 : poFeatureDefn->GetGeomFieldDefn(iGeomField);
300 2 : OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
301 2 : if (poGeom != nullptr)
302 : {
303 4 : CPLString iliGeomType = GetIliGeomType(poFieldDefn->GetNameRef());
304 2 : OGR2ILIGeometryAppend(poGeom, fp, poFieldDefn->GetNameRef(),
305 : iliGeomType);
306 : }
307 : }
308 :
309 : // Write all "set" fields.
310 4 : for (; iField < poFeatureDefn->GetFieldCount(); iField++)
311 : {
312 :
313 2 : OGRFieldDefn *poField = poFeatureDefn->GetFieldDefn(iField);
314 :
315 2 : if (poFeature->IsFieldSetAndNotNull(iField))
316 : {
317 2 : const char *pszRaw = poFeature->GetFieldAsString(iField);
318 2 : VSIFPrintfL(fp, "<%s>%s</%s>\n", poField->GetNameRef(), pszRaw,
319 : poField->GetNameRef());
320 : }
321 : }
322 :
323 2 : VSIFPrintfL(fp, "</%s>\n", poFeatureDefn->GetName());
324 :
325 2 : return OGRERR_NONE;
326 : }
327 :
328 : /************************************************************************/
329 : /* TestCapability() */
330 : /************************************************************************/
331 :
332 4 : int OGRILI2Layer::TestCapability(CPL_UNUSED const char *pszCap)
333 : {
334 4 : if (EQUAL(pszCap, OLCCurveGeometries))
335 2 : return TRUE;
336 2 : else if (EQUAL(pszCap, OLCZGeometries))
337 0 : return TRUE;
338 :
339 2 : return FALSE;
340 : }
341 :
342 : /************************************************************************/
343 : /* CreateField() */
344 : /************************************************************************/
345 :
346 0 : OGRErr OGRILI2Layer::CreateField(const OGRFieldDefn *poField,
347 : int /* bApproxOK */)
348 : {
349 0 : poFeatureDefn->AddFieldDefn(poField);
350 0 : return OGRERR_NONE;
351 : }
352 :
353 : /************************************************************************/
354 : /* GetDataset() */
355 : /************************************************************************/
356 :
357 1 : GDALDataset *OGRILI2Layer::GetDataset()
358 : {
359 1 : return poDS;
360 : }
|