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