1 /******************************************************************************
2 *
3 * Project: SDTS Translator
4 * Purpose: Implementation of SDTSLineReader and SDTSRawLine classes.
5 * Author: Frank Warmerdam, warmerdam@pobox.com
6 *
7 ******************************************************************************
8 * Copyright (c) 1999, Frank Warmerdam
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a
11 * copy of this software and associated documentation files (the "Software"),
12 * to deal in the Software without restriction, including without limitation
13 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14 * and/or sell copies of the Software, and to permit persons to whom the
15 * Software is furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included
18 * in all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 ****************************************************************************/
28
29 #include "sdts_al.h"
30
31 CPL_CVSID("$Id: sdtslinereader.cpp 7e07230bbff24eb333608de4dbd460b7312839d0 2017-12-11 19:08:47Z Even Rouault $")
32
33 /************************************************************************/
34 /* ==================================================================== */
35 /* SDTSRawLine */
36 /* */
37 /* This is a simple class for holding the data related with a */
38 /* line feature. */
39 /* ==================================================================== */
40 /************************************************************************/
41
42 /************************************************************************/
43 /* SDTSRawLine() */
44 /************************************************************************/
45
SDTSRawLine()46 SDTSRawLine::SDTSRawLine() :
47 nVertices(0),
48 padfX(nullptr),
49 padfY(nullptr),
50 padfZ(nullptr)
51 {
52 nAttributes = 0;
53 }
54
55 /************************************************************************/
56 /* ~STDSRawLine() */
57 /************************************************************************/
58
~SDTSRawLine()59 SDTSRawLine::~SDTSRawLine()
60
61 {
62 CPLFree( padfX );
63 }
64
65 /************************************************************************/
66 /* Read() */
67 /* */
68 /* Read a record from the passed SDTSLineReader, and assign the */
69 /* values from that record to this line. This is the bulk of */
70 /* the work in this whole file. */
71 /************************************************************************/
72
Read(SDTS_IREF * poIREF,DDFRecord * poRecord)73 int SDTSRawLine::Read( SDTS_IREF * poIREF, DDFRecord * poRecord )
74
75 {
76 // E.Rouault: Not sure if this test is really useful
77 if( poRecord->GetStringSubfield( "LINE", 0, "MODN", 0 ) == nullptr )
78 return FALSE;
79
80 /* ==================================================================== */
81 /* Loop over fields in this record, looking for those we */
82 /* recognise, and need. I don't use the getSubfield() */
83 /* interface on the record in order to retain some slight bit */
84 /* of efficiency. */
85 /* ==================================================================== */
86 for( int iField = 0; iField < poRecord->GetFieldCount(); iField++ )
87 {
88 DDFField *poField = poRecord->GetField( iField );
89 if( poField == nullptr )
90 return FALSE;
91 DDFFieldDefn* poFieldDefn = poField->GetFieldDefn();
92 if( poFieldDefn == nullptr )
93 return FALSE;
94
95 const char *pszFieldName = poFieldDefn->GetName();
96
97 if( EQUAL(pszFieldName,"LINE") )
98 oModId.Set( poField );
99
100 else if( EQUAL(pszFieldName,"ATID") )
101 ApplyATID( poField );
102
103 else if( EQUAL(pszFieldName,"PIDL") )
104 oLeftPoly.Set( poField );
105
106 else if( EQUAL(pszFieldName,"PIDR") )
107 oRightPoly.Set( poField );
108
109 else if( EQUAL(pszFieldName,"SNID") )
110 oStartNode.Set( poField );
111
112 else if( EQUAL(pszFieldName,"ENID") )
113 oEndNode.Set( poField );
114
115 else if( EQUAL(pszFieldName,"SADR") )
116 {
117 nVertices = poIREF->GetSADRCount( poField );
118
119 padfX = reinterpret_cast<double *>(
120 CPLRealloc( padfX, sizeof(double) * nVertices*3 ) );
121 padfY = padfX + nVertices;
122 padfZ = padfX + 2*nVertices;
123
124 if( !poIREF->GetSADR( poField, nVertices, padfX, padfY, padfZ ) )
125 {
126 return FALSE;
127 }
128 }
129 }
130
131 return TRUE;
132 }
133
134 /************************************************************************/
135 /* Dump() */
136 /* */
137 /* Write info about this object to a text file. */
138 /************************************************************************/
139
Dump(FILE * fp)140 void SDTSRawLine::Dump( FILE * fp )
141
142 {
143 fprintf( fp, "SDTSRawLine\n" );
144 fprintf( fp, " Module=%s, Record#=%d\n",
145 oModId.szModule, oModId.nRecord );
146 if( oLeftPoly.nRecord != -1 )
147 fprintf( fp, " LeftPoly (Module=%s, Record=%d)\n",
148 oLeftPoly.szModule, oLeftPoly.nRecord );
149 if( oRightPoly.nRecord != -1 )
150 fprintf( fp, " RightPoly (Module=%s, Record=%d)\n",
151 oRightPoly.szModule, oRightPoly.nRecord );
152 if( oStartNode.nRecord != -1 )
153 fprintf( fp, " StartNode (Module=%s, Record=%d)\n",
154 oStartNode.szModule, oStartNode.nRecord );
155 if( oEndNode.nRecord != -1 )
156 fprintf( fp, " EndNode (Module=%s, Record=%d)\n",
157 oEndNode.szModule, oEndNode.nRecord );
158 for( int i = 0; i < nAttributes; i++ )
159 fprintf( fp, " Attribute (Module=%s, Record=%d)\n",
160 paoATID[i].szModule, paoATID[i].nRecord );
161
162 for( int i = 0; i < nVertices; i++ )
163 {
164 fprintf( fp, " Vertex[%3d] = (%.2f,%.2f,%.2f)\n",
165 i, padfX[i], padfY[i], padfZ[i] );
166 }
167 }
168
169 /************************************************************************/
170 /* ==================================================================== */
171 /* SDTSLineReader */
172 /* */
173 /* This is the class used to read a line module. */
174 /* ==================================================================== */
175 /************************************************************************/
176
177 /************************************************************************/
178 /* SDTSLineReader() */
179 /************************************************************************/
180
SDTSLineReader(SDTS_IREF * poIREFIn)181 SDTSLineReader::SDTSLineReader( SDTS_IREF * poIREFIn ) :
182 poIREF(poIREFIn)
183 {}
184
185 /************************************************************************/
186 /* ~SDTSLineReader() */
187 /************************************************************************/
188
~SDTSLineReader()189 SDTSLineReader::~SDTSLineReader()
190 {
191 Close();
192 }
193
194 /************************************************************************/
195 /* Close() */
196 /************************************************************************/
197
Close()198 void SDTSLineReader::Close()
199
200 {
201 oDDFModule.Close();
202 }
203
204 /************************************************************************/
205 /* Open() */
206 /* */
207 /* Open the requested line file, and prepare to start reading */
208 /* data records. */
209 /************************************************************************/
210
Open(const char * pszFilename)211 int SDTSLineReader::Open( const char * pszFilename )
212
213 {
214 return oDDFModule.Open( pszFilename );
215 }
216
217 /************************************************************************/
218 /* GetNextLine() */
219 /* */
220 /* Fetch the next line feature as an STDSRawLine. */
221 /************************************************************************/
222
GetNextLine()223 SDTSRawLine *SDTSLineReader::GetNextLine()
224
225 {
226 /* -------------------------------------------------------------------- */
227 /* Are we initialized? */
228 /* -------------------------------------------------------------------- */
229 if( oDDFModule.GetFP() == nullptr )
230 return nullptr;
231
232 /* -------------------------------------------------------------------- */
233 /* Read the record. */
234 /* -------------------------------------------------------------------- */
235 DDFRecord *poRecord = oDDFModule.ReadRecord();
236
237 if( poRecord == nullptr )
238 return nullptr;
239
240 /* -------------------------------------------------------------------- */
241 /* Transform into a line feature. */
242 /* -------------------------------------------------------------------- */
243 SDTSRawLine *poRawLine = new SDTSRawLine();
244
245 if( poRawLine->Read( poIREF, poRecord ) )
246 {
247 return poRawLine;
248 }
249
250 delete poRawLine;
251 return nullptr;
252 }
253
254 /************************************************************************/
255 /* AttachToPolygons() */
256 /* */
257 /* Attach line features to all the polygon features they relate */
258 /* to. */
259 /************************************************************************/
260
261 /**
262 Attach lines in this module to their polygons as the first step in
263 polygon formation.
264
265 See also the SDTSRawPolygon::AssembleRings() method.
266
267 @param poTransfer the SDTSTransfer of this SDTSLineReader, and from
268 which the related SDTSPolygonReader will be instantiated.
269 @param iTargetPolyLayer the polygon reader instance number, used to avoid
270 processing lines for other layers.
271
272 */
273
AttachToPolygons(SDTSTransfer * poTransfer,int iTargetPolyLayer)274 void SDTSLineReader::AttachToPolygons( SDTSTransfer * poTransfer,
275 int iTargetPolyLayer )
276
277 {
278 if( !IsIndexed() )
279 return;
280
281 /* -------------------------------------------------------------------- */
282 /* We force a filling of the index because when we attach the */
283 /* lines we are just providing a pointer back to the line */
284 /* features in this readers index. If they aren't cached in */
285 /* the index then the pointer will be invalid. */
286 /* -------------------------------------------------------------------- */
287 FillIndex();
288
289 /* ==================================================================== */
290 /* Loop over all lines, attaching them to the polygons they */
291 /* have as right and left faces. */
292 /* ==================================================================== */
293 Rewind();
294 SDTSRawLine *poLine = nullptr;
295 SDTSPolygonReader *poPolyReader = nullptr;
296 while( (poLine = reinterpret_cast<SDTSRawLine *>( GetNextFeature()) )
297 != nullptr )
298 {
299 /* -------------------------------------------------------------------- */
300 /* Skip lines with the same left and right polygon face. These */
301 /* are dangles, and will not contribute in any useful fashion */
302 /* to the resulting polygon. */
303 /* -------------------------------------------------------------------- */
304 if( poLine->oLeftPoly.nRecord == poLine->oRightPoly.nRecord )
305 continue;
306
307 /* -------------------------------------------------------------------- */
308 /* If we don't have our indexed polygon reader yet, try to get */
309 /* it now. */
310 /* -------------------------------------------------------------------- */
311 if( poPolyReader == nullptr )
312 {
313 int iPolyLayer = -1;
314
315 if( poLine->oLeftPoly.nRecord != -1 )
316 {
317 iPolyLayer = poTransfer->FindLayer(poLine->oLeftPoly.szModule);
318 }
319 else if( poLine->oRightPoly.nRecord != -1 )
320 {
321 iPolyLayer = poTransfer->FindLayer(poLine->oRightPoly.szModule);
322 }
323
324 if( iPolyLayer == -1 )
325 continue;
326
327 if( iPolyLayer != iTargetPolyLayer )
328 continue;
329
330 poPolyReader = reinterpret_cast<SDTSPolygonReader *>(
331 poTransfer->GetLayerIndexedReader(iPolyLayer) );
332
333 if( poPolyReader == nullptr )
334 return;
335 }
336
337 /* -------------------------------------------------------------------- */
338 /* Attach line to right and/or left polygons. */
339 /* -------------------------------------------------------------------- */
340 if( poLine->oLeftPoly.nRecord != -1 )
341 {
342 SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
343 poPolyReader->GetIndexedFeatureRef( poLine->oLeftPoly.nRecord ) );
344 if( poPoly != nullptr )
345 poPoly->AddEdge( poLine );
346 }
347
348 if( poLine->oRightPoly.nRecord != -1 )
349 {
350 SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
351 poPolyReader->GetIndexedFeatureRef(
352 poLine->oRightPoly.nRecord ) );
353
354 if( poPoly != nullptr )
355 poPoly->AddEdge( poLine );
356 }
357 }
358 }
359