Line data Source code
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 : /************************************************************************/
32 : /* ==================================================================== */
33 : /* SDTSRawLine */
34 : /* */
35 : /* This is a simple class for holding the data related with a */
36 : /* line feature. */
37 : /* ==================================================================== */
38 : /************************************************************************/
39 :
40 : /************************************************************************/
41 : /* SDTSRawLine() */
42 : /************************************************************************/
43 :
44 55 : SDTSRawLine::SDTSRawLine()
45 55 : : nVertices(0), padfX(nullptr), padfY(nullptr), padfZ(nullptr)
46 : {
47 55 : nAttributes = 0;
48 55 : }
49 :
50 : /************************************************************************/
51 : /* ~STDSRawLine() */
52 : /************************************************************************/
53 :
54 110 : SDTSRawLine::~SDTSRawLine()
55 :
56 : {
57 55 : CPLFree(padfX);
58 110 : }
59 :
60 : /************************************************************************/
61 : /* Read() */
62 : /* */
63 : /* Read a record from the passed SDTSLineReader, and assign the */
64 : /* values from that record to this line. This is the bulk of */
65 : /* the work in this whole file. */
66 : /************************************************************************/
67 :
68 55 : int SDTSRawLine::Read(SDTS_IREF *poIREF, DDFRecord *poRecord)
69 :
70 : {
71 : // E.Rouault: Not sure if this test is really useful
72 55 : if (poRecord->GetStringSubfield("LINE", 0, "MODN", 0) == nullptr)
73 0 : return FALSE;
74 :
75 : /* ==================================================================== */
76 : /* Loop over fields in this record, looking for those we */
77 : /* recognise, and need. I don't use the getSubfield() */
78 : /* interface on the record in order to retain some slight bit */
79 : /* of efficiency. */
80 : /* ==================================================================== */
81 452 : for (int iField = 0; iField < poRecord->GetFieldCount(); iField++)
82 : {
83 397 : DDFField *poField = poRecord->GetField(iField);
84 397 : if (poField == nullptr)
85 0 : return FALSE;
86 397 : DDFFieldDefn *poFieldDefn = poField->GetFieldDefn();
87 397 : if (poFieldDefn == nullptr)
88 0 : return FALSE;
89 :
90 397 : const char *pszFieldName = poFieldDefn->GetName();
91 :
92 397 : if (EQUAL(pszFieldName, "LINE"))
93 55 : oModId.Set(poField);
94 :
95 342 : else if (EQUAL(pszFieldName, "ATID"))
96 12 : ApplyATID(poField);
97 :
98 330 : else if (EQUAL(pszFieldName, "PIDL"))
99 55 : oLeftPoly.Set(poField);
100 :
101 275 : else if (EQUAL(pszFieldName, "PIDR"))
102 55 : oRightPoly.Set(poField);
103 :
104 220 : else if (EQUAL(pszFieldName, "SNID"))
105 55 : oStartNode.Set(poField);
106 :
107 165 : else if (EQUAL(pszFieldName, "ENID"))
108 55 : oEndNode.Set(poField);
109 :
110 110 : else if (EQUAL(pszFieldName, "SADR"))
111 : {
112 55 : nVertices = poIREF->GetSADRCount(poField);
113 :
114 55 : padfX = reinterpret_cast<double *>(
115 55 : CPLRealloc(padfX, sizeof(double) * nVertices * 3));
116 55 : padfY = padfX + nVertices;
117 55 : padfZ = padfX + 2 * nVertices;
118 :
119 55 : if (!poIREF->GetSADR(poField, nVertices, padfX, padfY, padfZ))
120 : {
121 0 : return FALSE;
122 : }
123 : }
124 : }
125 :
126 55 : return TRUE;
127 : }
128 :
129 : /************************************************************************/
130 : /* Dump() */
131 : /* */
132 : /* Write info about this object to a text file. */
133 : /************************************************************************/
134 :
135 0 : void SDTSRawLine::Dump(FILE *fp)
136 :
137 : {
138 0 : fprintf(fp, "SDTSRawLine\n");
139 0 : fprintf(fp, " Module=%s, Record#=%d\n", oModId.szModule, oModId.nRecord);
140 0 : if (oLeftPoly.nRecord != -1)
141 0 : fprintf(fp, " LeftPoly (Module=%s, Record=%d)\n", oLeftPoly.szModule,
142 : oLeftPoly.nRecord);
143 0 : if (oRightPoly.nRecord != -1)
144 0 : fprintf(fp, " RightPoly (Module=%s, Record=%d)\n", oRightPoly.szModule,
145 : oRightPoly.nRecord);
146 0 : if (oStartNode.nRecord != -1)
147 0 : fprintf(fp, " StartNode (Module=%s, Record=%d)\n", oStartNode.szModule,
148 : oStartNode.nRecord);
149 0 : if (oEndNode.nRecord != -1)
150 0 : fprintf(fp, " EndNode (Module=%s, Record=%d)\n", oEndNode.szModule,
151 : oEndNode.nRecord);
152 0 : for (int i = 0; i < nAttributes; i++)
153 0 : fprintf(fp, " Attribute (Module=%s, Record=%d)\n", paoATID[i].szModule,
154 0 : paoATID[i].nRecord);
155 :
156 0 : for (int i = 0; i < nVertices; i++)
157 : {
158 0 : fprintf(fp, " Vertex[%3d] = (%.2f,%.2f,%.2f)\n", i, padfX[i], padfY[i],
159 0 : padfZ[i]);
160 : }
161 0 : }
162 :
163 : /************************************************************************/
164 : /* ==================================================================== */
165 : /* SDTSLineReader */
166 : /* */
167 : /* This is the class used to read a line module. */
168 : /* ==================================================================== */
169 : /************************************************************************/
170 :
171 : /************************************************************************/
172 : /* SDTSLineReader() */
173 : /************************************************************************/
174 :
175 1 : SDTSLineReader::SDTSLineReader(SDTS_IREF *poIREFIn) : poIREF(poIREFIn)
176 : {
177 1 : }
178 :
179 : /************************************************************************/
180 : /* ~SDTSLineReader() */
181 : /************************************************************************/
182 :
183 2 : SDTSLineReader::~SDTSLineReader()
184 : {
185 1 : Close();
186 2 : }
187 :
188 : /************************************************************************/
189 : /* Close() */
190 : /************************************************************************/
191 :
192 1 : void SDTSLineReader::Close()
193 :
194 : {
195 1 : oDDFModule.Close();
196 1 : }
197 :
198 : /************************************************************************/
199 : /* Open() */
200 : /* */
201 : /* Open the requested line file, and prepare to start reading */
202 : /* data records. */
203 : /************************************************************************/
204 :
205 1 : int SDTSLineReader::Open(const char *pszFilename)
206 :
207 : {
208 1 : return oDDFModule.Open(pszFilename);
209 : }
210 :
211 : /************************************************************************/
212 : /* GetNextLine() */
213 : /* */
214 : /* Fetch the next line feature as an STDSRawLine. */
215 : /************************************************************************/
216 :
217 57 : SDTSRawLine *SDTSLineReader::GetNextLine()
218 :
219 : {
220 : /* -------------------------------------------------------------------- */
221 : /* Are we initialized? */
222 : /* -------------------------------------------------------------------- */
223 57 : if (oDDFModule.GetFP() == nullptr)
224 0 : return nullptr;
225 :
226 : /* -------------------------------------------------------------------- */
227 : /* Read the record. */
228 : /* -------------------------------------------------------------------- */
229 57 : DDFRecord *poRecord = oDDFModule.ReadRecord();
230 :
231 57 : if (poRecord == nullptr)
232 2 : return nullptr;
233 :
234 : /* -------------------------------------------------------------------- */
235 : /* Transform into a line feature. */
236 : /* -------------------------------------------------------------------- */
237 55 : SDTSRawLine *poRawLine = new SDTSRawLine();
238 :
239 55 : if (poRawLine->Read(poIREF, poRecord))
240 : {
241 55 : return poRawLine;
242 : }
243 :
244 0 : delete poRawLine;
245 0 : return nullptr;
246 : }
247 :
248 : /************************************************************************/
249 : /* AttachToPolygons() */
250 : /* */
251 : /* Attach line features to all the polygon features they relate */
252 : /* to. */
253 : /************************************************************************/
254 :
255 : /**
256 : Attach lines in this module to their polygons as the first step in
257 : polygon formation.
258 :
259 : See also the SDTSRawPolygon::AssembleRings() method.
260 :
261 : @param poTransfer the SDTSTransfer of this SDTSLineReader, and from
262 : which the related SDTSPolygonReader will be instantiated.
263 : @param iTargetPolyLayer the polygon reader instance number, used to avoid
264 : processing lines for other layers.
265 :
266 : */
267 :
268 1 : void SDTSLineReader::AttachToPolygons(SDTSTransfer *poTransfer,
269 : int iTargetPolyLayer)
270 :
271 : {
272 : /* -------------------------------------------------------------------- */
273 : /* We force a filling of the index because when we attach the */
274 : /* lines we are just providing a pointer back to the line */
275 : /* features in this readers index. If they aren't cached in */
276 : /* the index then the pointer will be invalid. */
277 : /* -------------------------------------------------------------------- */
278 1 : FillIndex();
279 :
280 : /* ==================================================================== */
281 : /* Loop over all lines, attaching them to the polygons they */
282 : /* have as right and left faces. */
283 : /* ==================================================================== */
284 1 : Rewind();
285 1 : SDTSRawLine *poLine = nullptr;
286 1 : SDTSPolygonReader *poPolyReader = nullptr;
287 28 : while ((poLine = reinterpret_cast<SDTSRawLine *>(GetNextFeature())) !=
288 : nullptr)
289 : {
290 : /* --------------------------------------------------------------------
291 : */
292 : /* Skip lines with the same left and right polygon face. These */
293 : /* are dangles, and will not contribute in any useful fashion */
294 : /* to the resulting polygon. */
295 : /* --------------------------------------------------------------------
296 : */
297 27 : if (poLine->oLeftPoly.nRecord == poLine->oRightPoly.nRecord)
298 2 : continue;
299 :
300 : /* --------------------------------------------------------------------
301 : */
302 : /* If we don't have our indexed polygon reader yet, try to get */
303 : /* it now. */
304 : /* --------------------------------------------------------------------
305 : */
306 25 : if (poPolyReader == nullptr)
307 : {
308 : int iPolyLayer;
309 :
310 1 : if (poLine->oLeftPoly.nRecord != -1)
311 : {
312 1 : iPolyLayer = poTransfer->FindLayer(poLine->oLeftPoly.szModule);
313 : }
314 : else /* if( poLine->oRightPoly.nRecord != -1 ) */
315 : {
316 0 : iPolyLayer = poTransfer->FindLayer(poLine->oRightPoly.szModule);
317 : }
318 :
319 1 : if (iPolyLayer == -1)
320 0 : continue;
321 :
322 1 : if (iPolyLayer != iTargetPolyLayer)
323 0 : continue;
324 :
325 : poPolyReader = reinterpret_cast<SDTSPolygonReader *>(
326 1 : poTransfer->GetLayerIndexedReader(iPolyLayer));
327 :
328 1 : if (poPolyReader == nullptr)
329 0 : return;
330 : }
331 :
332 : /* --------------------------------------------------------------------
333 : */
334 : /* Attach line to right and/or left polygons. */
335 : /* --------------------------------------------------------------------
336 : */
337 25 : if (poLine->oLeftPoly.nRecord != -1)
338 : {
339 : SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
340 25 : poPolyReader->GetIndexedFeatureRef(poLine->oLeftPoly.nRecord));
341 25 : if (poPoly != nullptr)
342 25 : poPoly->AddEdge(poLine);
343 : }
344 :
345 25 : if (poLine->oRightPoly.nRecord != -1)
346 : {
347 : SDTSRawPolygon *poPoly = reinterpret_cast<SDTSRawPolygon *>(
348 25 : poPolyReader->GetIndexedFeatureRef(poLine->oRightPoly.nRecord));
349 :
350 25 : if (poPoly != nullptr)
351 25 : poPoly->AddEdge(poLine);
352 : }
353 : }
354 : }
|