Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: S-57 Translator
4 : * Purpose: Implements OGRS57Layer class.
5 : * Author: Frank Warmerdam, warmerdam@pobox.com
6 : *
7 : ******************************************************************************
8 : * Copyright (c) 1999, Frank Warmerdam
9 : * Copyright (c) 2009-2014, 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_s57.h"
33 :
34 : /************************************************************************/
35 : /* OGRS57Layer() */
36 : /* */
37 : /* Note that the OGRS57Layer assumes ownership of the passed */
38 : /* OGRFeatureDefn object. */
39 : /************************************************************************/
40 :
41 5402 : OGRS57Layer::OGRS57Layer(OGRS57DataSource *poDSIn, OGRFeatureDefn *poDefnIn,
42 5402 : int nFeatureCountIn, int nOBJLIn)
43 : : poDS(poDSIn), poFeatureDefn(poDefnIn), nCurrentModule(-1),
44 : nRCNM(100), // Default to feature.
45 5402 : nOBJL(nOBJLIn), nNextFEIndex(0), nFeatureCount(nFeatureCountIn)
46 : {
47 5402 : SetDescription(poFeatureDefn->GetName());
48 5402 : if (poFeatureDefn->GetGeomFieldCount() > 0)
49 10442 : poFeatureDefn->GetGeomFieldDefn(0)->SetSpatialRef(
50 5221 : poDS->DSGetSpatialRef());
51 :
52 5402 : if (EQUAL(poDefnIn->GetName(), OGRN_VI))
53 21 : nRCNM = RCNM_VI;
54 5381 : else if (EQUAL(poDefnIn->GetName(), OGRN_VC))
55 21 : nRCNM = RCNM_VC;
56 5360 : else if (EQUAL(poDefnIn->GetName(), OGRN_VE))
57 21 : nRCNM = RCNM_VE;
58 5339 : else if (EQUAL(poDefnIn->GetName(), OGRN_VF))
59 21 : nRCNM = RCNM_VF;
60 5318 : else if (EQUAL(poDefnIn->GetName(), "DSID"))
61 37 : nRCNM = RCNM_DSID;
62 : // Leave as feature.
63 5402 : }
64 :
65 : /************************************************************************/
66 : /* ~OGRS57Layer() */
67 : /************************************************************************/
68 :
69 10804 : OGRS57Layer::~OGRS57Layer()
70 :
71 : {
72 5402 : if (m_nFeaturesRead > 0)
73 : {
74 98 : CPLDebug("S57", "%d features read on layer '%s'.",
75 49 : static_cast<int>(m_nFeaturesRead), poFeatureDefn->GetName());
76 : }
77 :
78 5402 : poFeatureDefn->Release();
79 10804 : }
80 :
81 : /************************************************************************/
82 : /* ResetReading() */
83 : /************************************************************************/
84 :
85 1093 : void OGRS57Layer::ResetReading()
86 :
87 : {
88 1093 : nNextFEIndex = 0;
89 1093 : nCurrentModule = -1;
90 1093 : }
91 :
92 : /************************************************************************/
93 : /* GetNextUnfilteredFeature() */
94 : /************************************************************************/
95 :
96 2010 : OGRFeature *OGRS57Layer::GetNextUnfilteredFeature()
97 :
98 : {
99 : /* -------------------------------------------------------------------- */
100 : /* Are we out of modules to request features from? */
101 : /* -------------------------------------------------------------------- */
102 2010 : if (nCurrentModule >= poDS->GetModuleCount())
103 361 : return nullptr;
104 :
105 : /* -------------------------------------------------------------------- */
106 : /* Set the current position on the current module and fetch a */
107 : /* feature. */
108 : /* -------------------------------------------------------------------- */
109 1649 : S57Reader *poReader = poDS->GetModule(nCurrentModule);
110 1649 : OGRFeature *poFeature = nullptr;
111 :
112 1649 : if (poReader != nullptr)
113 : {
114 1159 : poReader->SetNextFEIndex(nNextFEIndex, nRCNM);
115 1159 : poFeature = poReader->ReadNextFeature(poFeatureDefn);
116 1159 : nNextFEIndex = poReader->GetNextFEIndex(nRCNM);
117 : }
118 :
119 : /* -------------------------------------------------------------------- */
120 : /* If we didn't get a feature we need to move onto the next file. */
121 : /* -------------------------------------------------------------------- */
122 1649 : if (poFeature == nullptr)
123 : {
124 838 : nCurrentModule++;
125 838 : poReader = poDS->GetModule(nCurrentModule);
126 :
127 838 : if (poReader != nullptr && poReader->GetModule() == nullptr)
128 : {
129 0 : if (!poReader->Open(FALSE))
130 0 : return nullptr;
131 : }
132 :
133 838 : return GetNextUnfilteredFeature();
134 : }
135 : else
136 : {
137 811 : m_nFeaturesRead++;
138 811 : if (poFeature->GetGeometryRef() != nullptr)
139 772 : poFeature->GetGeometryRef()->assignSpatialReference(
140 772 : GetSpatialRef());
141 : }
142 :
143 811 : return poFeature;
144 : }
145 :
146 : /************************************************************************/
147 : /* GetNextFeature() */
148 : /************************************************************************/
149 :
150 945 : OGRFeature *OGRS57Layer::GetNextFeature()
151 :
152 : {
153 945 : OGRFeature *poFeature = nullptr;
154 :
155 : /* -------------------------------------------------------------------- */
156 : /* Read features till we find one that satisfies our current */
157 : /* spatial criteria. */
158 : /* -------------------------------------------------------------------- */
159 : while (true)
160 : {
161 1172 : poFeature = GetNextUnfilteredFeature();
162 1172 : if (poFeature == nullptr)
163 361 : break;
164 :
165 1853 : if ((m_poFilterGeom == nullptr ||
166 1528 : FilterGeometry(poFeature->GetGeometryRef())) &&
167 717 : (m_poAttrQuery == nullptr || m_poAttrQuery->Evaluate(poFeature)))
168 584 : break;
169 :
170 227 : delete poFeature;
171 : }
172 :
173 945 : return poFeature;
174 : }
175 :
176 : /************************************************************************/
177 : /* TestCapability() */
178 : /************************************************************************/
179 :
180 759 : int OGRS57Layer::TestCapability(const char *pszCap)
181 :
182 : {
183 759 : if (EQUAL(pszCap, OLCRandomRead))
184 0 : return false;
185 :
186 759 : if (EQUAL(pszCap, OLCSequentialWrite))
187 13 : return true;
188 :
189 746 : if (EQUAL(pszCap, OLCRandomWrite))
190 13 : return false;
191 :
192 733 : if (EQUAL(pszCap, OLCFastFeatureCount))
193 231 : return !(
194 231 : m_poFilterGeom != nullptr || m_poAttrQuery != nullptr ||
195 157 : nFeatureCount == -1 ||
196 144 : (EQUAL(poFeatureDefn->GetName(), "SOUNDG") &&
197 12 : poDS->GetModule(0) != nullptr &&
198 243 : (poDS->GetModule(0)->GetOptionFlags() & S57M_SPLIT_MULTIPOINT)));
199 :
200 502 : if (EQUAL(pszCap, OLCFastGetExtent))
201 : {
202 24 : OGREnvelope oEnvelope;
203 :
204 24 : return GetExtent(&oEnvelope, FALSE) == OGRERR_NONE;
205 : }
206 :
207 478 : if (EQUAL(pszCap, OLCFastSpatialFilter))
208 0 : return false;
209 :
210 478 : if (EQUAL(pszCap, OLCStringsAsUTF8))
211 : {
212 306 : return poDS->GetModule(0) != nullptr &&
213 306 : (poDS->GetModule(0)->GetOptionFlags() & S57M_RECODE_BY_DSSI);
214 : }
215 :
216 325 : if (EQUAL(pszCap, OLCZGeometries))
217 39 : return true;
218 :
219 286 : return false;
220 : }
221 :
222 : /************************************************************************/
223 : /* GetExtent() */
224 : /************************************************************************/
225 :
226 73 : OGRErr OGRS57Layer::GetExtent(OGREnvelope *psExtent, int bForce)
227 :
228 : {
229 73 : if (GetGeomType() == wkbNone)
230 1 : return OGRERR_FAILURE;
231 :
232 72 : return poDS->GetDSExtent(psExtent, bForce);
233 : }
234 :
235 : /************************************************************************/
236 : /* GetFeatureCount() */
237 : /************************************************************************/
238 231 : GIntBig OGRS57Layer::GetFeatureCount(int bForce)
239 : {
240 :
241 231 : if (!TestCapability(OLCFastFeatureCount))
242 87 : return OGRLayer::GetFeatureCount(bForce);
243 :
244 144 : return nFeatureCount;
245 : }
246 :
247 : /************************************************************************/
248 : /* GetFeature() */
249 : /************************************************************************/
250 :
251 64 : OGRFeature *OGRS57Layer::GetFeature(GIntBig nFeatureId)
252 :
253 : {
254 64 : S57Reader *poReader = poDS->GetModule(0); // not multi-reader aware
255 :
256 64 : if (poReader != nullptr && nFeatureId <= INT_MAX)
257 : {
258 : OGRFeature *poFeature =
259 51 : poReader->ReadFeature(static_cast<int>(nFeatureId), poFeatureDefn);
260 :
261 51 : if (poFeature != nullptr && poFeature->GetGeometryRef() != nullptr)
262 24 : poFeature->GetGeometryRef()->assignSpatialReference(
263 24 : GetSpatialRef());
264 51 : return poFeature;
265 : }
266 :
267 13 : return nullptr;
268 : }
269 :
270 : /************************************************************************/
271 : /* ICreateFeature() */
272 : /************************************************************************/
273 :
274 118 : OGRErr OGRS57Layer::ICreateFeature(OGRFeature *poFeature)
275 :
276 : {
277 : /* -------------------------------------------------------------------- */
278 : /* Set RCNM if not already set. */
279 : /* -------------------------------------------------------------------- */
280 118 : const int iRCNMFld = poFeature->GetFieldIndex("RCNM");
281 :
282 118 : if (iRCNMFld != -1)
283 : {
284 94 : if (!poFeature->IsFieldSetAndNotNull(iRCNMFld))
285 0 : poFeature->SetField(iRCNMFld, nRCNM);
286 : else
287 : {
288 94 : CPLAssert(poFeature->GetFieldAsInteger(iRCNMFld) == nRCNM);
289 : }
290 : }
291 :
292 : /* -------------------------------------------------------------------- */
293 : /* Set OBJL if not already set. */
294 : /* -------------------------------------------------------------------- */
295 118 : if (nOBJL != -1)
296 : {
297 24 : const int iOBJLFld = poFeature->GetFieldIndex("OBJL");
298 :
299 24 : if (!poFeature->IsFieldSetAndNotNull(iOBJLFld))
300 0 : poFeature->SetField(iOBJLFld, nOBJL);
301 : else
302 : {
303 24 : CPLAssert(poFeature->GetFieldAsInteger(iOBJLFld) == nOBJL);
304 : }
305 : }
306 :
307 : /* -------------------------------------------------------------------- */
308 : /* Create the isolated node feature. */
309 : /* -------------------------------------------------------------------- */
310 118 : if (poDS->GetWriter()->WriteCompleteFeature(poFeature))
311 118 : return OGRERR_NONE;
312 :
313 0 : return OGRERR_FAILURE;
314 : }
|