1 : /******************************************************************************
2 : * $Id: ogrcsvlayer.cpp 17496 2009-08-02 11:54:23Z rouault $
3 : *
4 : * Project: PCIDSK Translator
5 : * Purpose: Implements OGRPCIDSKLayer class.
6 : * Author: Frank Warmerdam <warmerdam@pobox.com>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2009, Frank Warmerdam <warmerdam@pobox.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 "ogr_pcidsk.h"
31 :
32 : CPL_CVSID("$Id: ogrcsvlayer.cpp 17496 2009-08-02 11:54:23Z rouault $");
33 :
34 : /************************************************************************/
35 : /* OGRPCIDSKLayer() */
36 : /************************************************************************/
37 :
38 0 : OGRPCIDSKLayer::OGRPCIDSKLayer( PCIDSK::PCIDSKSegment *poSegIn )
39 :
40 : {
41 0 : poSeg = poSegIn;
42 0 : poVecSeg = dynamic_cast<PCIDSK::PCIDSKVectorSegment*>( poSeg );
43 :
44 0 : poFeatureDefn = new OGRFeatureDefn( poSeg->GetName().c_str() );
45 0 : poFeatureDefn->Reference();
46 : //poFeatureDefn->SetGeomType( wkbNone );
47 :
48 0 : hLastShapeId = PCIDSK::NullShapeId;
49 :
50 : /* -------------------------------------------------------------------- */
51 : /* Attempt to assign a geometry type. */
52 : /* -------------------------------------------------------------------- */
53 : try {
54 0 : std::string osLayerType = poSeg->GetMetadataValue( "LAYER_TYPE" );
55 :
56 0 : if( osLayerType == "WHOLE_POLYGONS" )
57 0 : poFeatureDefn->SetGeomType( wkbPolygon25D );
58 0 : else if( osLayerType == "ARCS" || osLayerType == "TOPO_ARCS" )
59 0 : poFeatureDefn->SetGeomType( wkbLineString25D );
60 0 : else if( osLayerType == "POINTS" || osLayerType == "TOPO_NODES" )
61 0 : poFeatureDefn->SetGeomType( wkbPoint25D );
62 0 : else if( osLayerType == "TABLE" )
63 0 : poFeatureDefn->SetGeomType( wkbNone );
64 0 : } catch(...) {}
65 :
66 : /* -------------------------------------------------------------------- */
67 : /* Build field definitions. */
68 : /* -------------------------------------------------------------------- */
69 0 : iRingStartField = -1;
70 :
71 0 : for( int iField = 0; iField < poVecSeg->GetFieldCount(); iField++ )
72 : {
73 0 : OGRFieldDefn oField( poVecSeg->GetFieldName(iField).c_str(), OFTString);
74 :
75 0 : switch( poVecSeg->GetFieldType(iField) )
76 : {
77 : case PCIDSK::FieldTypeFloat:
78 : case PCIDSK::FieldTypeDouble:
79 0 : oField.SetType( OFTReal );
80 0 : break;
81 :
82 : case PCIDSK::FieldTypeInteger:
83 0 : oField.SetType( OFTInteger );
84 0 : break;
85 :
86 : case PCIDSK::FieldTypeString:
87 0 : oField.SetType( OFTString );
88 0 : break;
89 :
90 : case PCIDSK::FieldTypeCountedInt:
91 0 : oField.SetType( OFTIntegerList );
92 : break;
93 :
94 : default:
95 : CPLAssert( FALSE );
96 : break;
97 : }
98 :
99 : // we ought to try and extract some width/precision information
100 : // from the format string at some point.
101 :
102 : // If the last field is named RingStart we treat it specially.
103 0 : if( EQUAL(oField.GetNameRef(),"RingStart")
104 : && oField.GetType() == OFTIntegerList
105 0 : && iField == poVecSeg->GetFieldCount()-1 )
106 0 : iRingStartField = iField;
107 : else
108 0 : poFeatureDefn->AddFieldDefn( &oField );
109 : }
110 0 : }
111 :
112 : /************************************************************************/
113 : /* ~OGRPCIDSKLayer() */
114 : /************************************************************************/
115 :
116 0 : OGRPCIDSKLayer::~OGRPCIDSKLayer()
117 :
118 : {
119 0 : if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
120 : {
121 : CPLDebug( "PCIDSK", "%d features read on layer '%s'.",
122 : (int) m_nFeaturesRead,
123 0 : poFeatureDefn->GetName() );
124 : }
125 :
126 0 : poFeatureDefn->Release();
127 0 : }
128 :
129 : /************************************************************************/
130 : /* ResetReading() */
131 : /************************************************************************/
132 :
133 0 : void OGRPCIDSKLayer::ResetReading()
134 :
135 : {
136 0 : hLastShapeId = PCIDSK::NullShapeId;
137 0 : }
138 :
139 : /************************************************************************/
140 : /* GetNextUnfilteredFeature() */
141 : /************************************************************************/
142 :
143 0 : OGRFeature * OGRPCIDSKLayer::GetNextUnfilteredFeature()
144 :
145 : {
146 : unsigned int i;
147 :
148 : /* -------------------------------------------------------------------- */
149 : /* Get the next shapeid. */
150 : /* -------------------------------------------------------------------- */
151 0 : if( hLastShapeId == PCIDSK::NullShapeId )
152 0 : hLastShapeId = poVecSeg->FindFirst();
153 : else
154 0 : hLastShapeId = poVecSeg->FindNext( hLastShapeId );
155 :
156 0 : if( hLastShapeId == PCIDSK::NullShapeId )
157 0 : return NULL;
158 :
159 : /* -------------------------------------------------------------------- */
160 : /* Create the OGR feature. */
161 : /* -------------------------------------------------------------------- */
162 : OGRFeature *poFeature;
163 :
164 0 : poFeature = new OGRFeature( poFeatureDefn );
165 0 : poFeature->SetFID( (int) hLastShapeId );
166 :
167 : /* -------------------------------------------------------------------- */
168 : /* Set attributes for any indicated attribute records. */
169 : /* -------------------------------------------------------------------- */
170 0 : std::vector<PCIDSK::ShapeField> aoFields;
171 :
172 0 : poVecSeg->GetFields( hLastShapeId, aoFields );
173 0 : for( i=0; i < aoFields.size(); i++ )
174 : {
175 0 : if( (int) i == iRingStartField )
176 0 : continue;
177 :
178 0 : switch( aoFields[i].GetType() )
179 : {
180 : case PCIDSK::FieldTypeNone:
181 : // null field value.
182 0 : break;
183 :
184 : case PCIDSK::FieldTypeInteger:
185 0 : poFeature->SetField( i, aoFields[i].GetValueInteger() );
186 0 : break;
187 :
188 : case PCIDSK::FieldTypeFloat:
189 0 : poFeature->SetField( i, aoFields[i].GetValueFloat() );
190 0 : break;
191 :
192 : case PCIDSK::FieldTypeDouble:
193 0 : poFeature->SetField( i, aoFields[i].GetValueDouble() );
194 0 : break;
195 :
196 : case PCIDSK::FieldTypeString:
197 0 : poFeature->SetField( i, aoFields[i].GetValueString().c_str() );
198 0 : break;
199 :
200 : case PCIDSK::FieldTypeCountedInt:
201 0 : std::vector<PCIDSK::int32> list = aoFields[i].GetValueCountedInt();
202 :
203 0 : poFeature->SetField( i, list.size(), &(list[0]) );
204 0 : break;
205 : }
206 : }
207 :
208 : /* -------------------------------------------------------------------- */
209 : /* Translate the geometry. */
210 : /* -------------------------------------------------------------------- */
211 0 : std::vector<PCIDSK::ShapeVertex> aoVertices;
212 :
213 0 : poVecSeg->GetVertices( hLastShapeId, aoVertices );
214 :
215 : /* -------------------------------------------------------------------- */
216 : /* Point */
217 : /* -------------------------------------------------------------------- */
218 0 : if( poFeatureDefn->GetGeomType() == wkbPoint25D
219 : || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown
220 : && aoVertices.size() == 1) )
221 : {
222 0 : if( aoVertices.size() == 1 )
223 : {
224 : poFeature->SetGeometryDirectly(
225 : new OGRPoint( aoVertices[0].x,
226 : aoVertices[0].y,
227 0 : aoVertices[0].z ) );
228 : }
229 : else
230 : {
231 : // report issue?
232 : }
233 : }
234 :
235 : /* -------------------------------------------------------------------- */
236 : /* LineString */
237 : /* -------------------------------------------------------------------- */
238 0 : else if( poFeatureDefn->GetGeomType() == wkbLineString25D
239 : || (wkbFlatten(poFeatureDefn->GetGeomType()) == wkbUnknown
240 : && aoVertices.size() > 1) )
241 : {
242 : // We should likely be applying ringstart to break things into
243 : // a multilinestring in some cases.
244 0 : if( aoVertices.size() > 1 )
245 : {
246 0 : OGRLineString *poLS = new OGRLineString();
247 :
248 0 : poLS->setNumPoints( aoVertices.size() );
249 :
250 0 : for( i = 0; i < aoVertices.size(); i++ )
251 : poLS->setPoint( i,
252 : aoVertices[i].x,
253 : aoVertices[i].y,
254 0 : aoVertices[i].z );
255 :
256 0 : poFeature->SetGeometryDirectly( poLS );
257 : }
258 : else
259 : {
260 : // report issue?
261 : }
262 : }
263 :
264 : /* -------------------------------------------------------------------- */
265 : /* Polygon - Currently we have no way to recognise if we are */
266 : /* dealing with a multipolygon when we have more than one */
267 : /* ring. Also, PCIDSK allows the rings to be in arbitrary */
268 : /* order, not necessarily outside first which we are not yet */
269 : /* ready to address in the following code. */
270 : /* -------------------------------------------------------------------- */
271 0 : else if( poFeatureDefn->GetGeomType() == wkbPolygon25D )
272 : {
273 0 : std::vector<PCIDSK::int32> anRingStart;
274 0 : OGRPolygon *poPoly = new OGRPolygon();
275 : unsigned int iRing;
276 :
277 0 : if( iRingStartField != -1 )
278 0 : anRingStart = aoFields[iRingStartField].GetValueCountedInt();
279 :
280 0 : for( iRing = 0; iRing < anRingStart.size()+1; iRing++ )
281 : {
282 : unsigned int iStartVertex, iEndVertex, iVertex;
283 0 : OGRLinearRing *poRing = new OGRLinearRing();
284 :
285 0 : if( iRing == 0 )
286 0 : iStartVertex = 0;
287 : else
288 0 : iStartVertex = anRingStart[iRing-1];
289 :
290 0 : if( iRing == anRingStart.size() )
291 0 : iEndVertex = aoVertices.size() - 1;
292 : else
293 0 : iEndVertex = anRingStart[iRing] - 1;
294 :
295 0 : poRing->setNumPoints( iEndVertex - iStartVertex + 1 );
296 0 : for( iVertex = iStartVertex; iVertex <= iEndVertex; iVertex++ )
297 : {
298 : poRing->setPoint( iVertex - iStartVertex,
299 : aoVertices[iVertex].x,
300 : aoVertices[iVertex].y,
301 0 : aoVertices[iVertex].z );
302 : }
303 :
304 0 : poPoly->addRingDirectly( poRing );
305 : }
306 :
307 0 : poFeature->SetGeometryDirectly( poPoly );
308 : }
309 :
310 0 : m_nFeaturesRead++;
311 :
312 0 : return poFeature;
313 : }
314 :
315 :
316 : /************************************************************************/
317 : /* GetNextFeature() */
318 : /************************************************************************/
319 :
320 0 : OGRFeature *OGRPCIDSKLayer::GetNextFeature()
321 :
322 : {
323 0 : OGRFeature *poFeature = NULL;
324 :
325 : /* -------------------------------------------------------------------- */
326 : /* Read features till we find one that satisfies our current */
327 : /* spatial criteria. */
328 : /* -------------------------------------------------------------------- */
329 0 : while( TRUE )
330 : {
331 0 : poFeature = GetNextUnfilteredFeature();
332 0 : if( poFeature == NULL )
333 0 : break;
334 :
335 0 : if( (m_poFilterGeom == NULL
336 : || FilterGeometry( poFeature->GetGeometryRef() ) )
337 : && (m_poAttrQuery == NULL
338 : || m_poAttrQuery->Evaluate( poFeature )) )
339 0 : break;
340 :
341 0 : delete poFeature;
342 : }
343 :
344 0 : return poFeature;
345 : }
346 :
347 : /************************************************************************/
348 : /* TestCapability() */
349 : /************************************************************************/
350 :
351 0 : int OGRPCIDSKLayer::TestCapability( const char * pszCap )
352 :
353 : {
354 0 : return FALSE;
355 : }
356 :
|