1 : /**********************************************************************
2 : * $Id: mitab_feature_mif.cpp,v 1.39 2010-09-07 16:07:53 aboudreault Exp $
3 : *
4 : * Name: mitab_feature.cpp
5 : * Project: MapInfo TAB Read/Write library
6 : * Language: C++
7 : * Purpose: Implementation of R/W Fcts for (Mid/Mif) in feature classes
8 : * specific to MapInfo files.
9 : * Author: Stephane Villeneuve, stephane.v@videotron.ca
10 : *
11 : **********************************************************************
12 : * Copyright (c) 1999-2002, Stephane Villeneuve
13 : *
14 : * Permission is hereby granted, free of charge, to any person obtaining a
15 : * copy of this software and associated documentation files (the "Software"),
16 : * to deal in the Software without restriction, including without limitation
17 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 : * and/or sell copies of the Software, and to permit persons to whom the
19 : * Software is furnished to do so, subject to the following conditions:
20 : *
21 : * The above copyright notice and this permission notice shall be included
22 : * in all copies or substantial portions of the Software.
23 : *
24 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
29 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
30 : * DEALINGS IN THE SOFTWARE.
31 : **********************************************************************
32 : *
33 : * $Log: mitab_feature_mif.cpp,v $
34 : * Revision 1.39 2010-09-07 16:07:53 aboudreault
35 : * Added the use of OGRGeometryFactory::organizePolygons for mif features
36 : *
37 : * Revision 1.38 2010-07-07 19:00:15 aboudreault
38 : * Cleanup Win32 Compile Warnings (GDAL bug #2930)
39 : *
40 : * Revision 1.37 2008-12-17 14:55:20 aboudreault
41 : * Fixed mitab mif/mid importer fails when a Text geometry have an empty
42 : * text value (bug 1978)
43 : *
44 : * Revision 1.36 2008-11-27 20:50:22 aboudreault
45 : * Improved support for OGR date/time types. New Read/Write methods (bug 1948)
46 : * Added support of OGR date/time types for MIF features.
47 : *
48 : * Revision 1.35 2008/09/23 14:56:03 aboudreault
49 : * Fixed an error related to the " character when converting mif to tab file.
50 : *
51 : * Revision 1.34 2008/09/23 13:45:03 aboudreault
52 : * Fixed bug with the characters ",\n in the tab2tab application. (bug 1945)
53 : *
54 : * Revision 1.33 2008/02/01 20:30:59 dmorissette
55 : * Use %.15g instead of %.16g as number precision in .MIF output
56 : *
57 : * Revision 1.32 2007/06/07 20:27:21 dmorissette
58 : * Fixed memory leaks when reading multipoint objects from .MIF files
59 : *
60 : * Revision 1.31 2006/01/27 13:44:44 fwarmerdam
61 : * fixed Mills.mif reading, crash at file end
62 : *
63 : * Revision 1.30 2006/01/26 21:26:36 fwarmerdam
64 : * fixed bug with multi character delimeters in .mid file
65 : *
66 : * Revision 1.29 2005/10/04 19:36:10 dmorissette
67 : * Added support for reading collections from MIF files (bug 1126)
68 : *
69 : * Revision 1.28 2005/10/04 15:44:31 dmorissette
70 : * First round of support for Collection objects. Currently supports reading
71 : * from .TAB/.MAP and writing to .MIF. Still lacks symbol support and write
72 : * support. (Based in part on patch and docs from Jim Hope, bug 1126)
73 : *
74 : * Revision 1.27 2005/10/04 15:35:52 dmorissette
75 : * Fixed an instance of hardcoded delimiter (",") in WriteRecordToMIDFile()
76 : * (patch by KB Kieron, bug 1126)
77 : *
78 : * Revision 1.26 2005/07/14 16:15:05 jlacroix
79 : * \n and \ are now unescaped internally.
80 : *
81 : * Revision 1.25 2003/12/19 07:52:34 fwarmerdam
82 : * write 3d as 2d
83 : *
84 : * Revision 1.24 2002/11/27 22:51:52 daniel
85 : * Bug 1631:Do not produce an error if .mid data records end with a stray ','
86 : * Treat tabs (\t) as a blank space delimiter when reading .mif coordinates
87 : *
88 : * Revision 1.23 2002/10/29 21:09:20 warmerda
89 : * Ensure that a blank line in a mid file is treated as one field containing
90 : * an empty string.
91 : *
92 : * Revision 1.22 2002/04/26 14:16:49 julien
93 : * Finishing the implementation of Multipoint (support for MIF)
94 : *
95 : * Revision 1.21 2002/03/26 01:48:40 daniel
96 : * Added Multipoint object type (V650)
97 : *
98 : * Revision 1.20 2002/01/23 20:31:21 daniel
99 : * Fixed warning produced by CPLAssert() in non-DEBUG mode.
100 : *
101 : * Revision 1.19 2001/06/25 01:50:42 daniel
102 : * Fixed MIF Text object output: negative text angles were lost. Also use
103 : * TABText::SetTextAngle() when reading MIF instead of setting class members
104 : * directly so that negative angles get converted to the [0..360] range.
105 : *
106 : * Revision 1.18 2001/02/28 07:15:09 daniel
107 : * Added support for text label line end point
108 : *
109 : * Revision 1.17 2001/01/22 16:03:58 warmerda
110 : * expanded tabs
111 : *
112 : * Revision 1.16 2000/10/03 19:29:51 daniel
113 : * Include OGR StyleString stuff (implemented by Stephane)
114 : *
115 : * Revision 1.15 2000/09/28 16:39:44 warmerda
116 : * avoid warnings for unused, and unitialized variables
117 : *
118 : * Revision 1.14 2000/09/19 17:23:53 daniel
119 : * Maintain and/or compute valid region and polyline center/label point
120 : *
121 : * Revision 1.13 2000/03/27 03:33:45 daniel
122 : * Treat SYMBOL line as optional when reading TABPoint
123 : *
124 : * Revision 1.12 2000/02/28 16:56:32 daniel
125 : * Support pen width in points (width values 11 to 2047)
126 : *
127 : * Revision 1.11 2000/01/15 22:30:44 daniel
128 : * Switch to MIT/X-Consortium OpenSource license
129 : *
130 : * Revision 1.10 2000/01/14 23:51:37 daniel
131 : * Fixed handling of "\n" in TABText strings... now the external interface
132 : * of the lib returns and expects escaped "\"+"n" as described in MIF specs
133 : *
134 : * Revision 1.9 1999/12/19 17:37:14 daniel
135 : * Fixed memory leaks
136 : *
137 : * Revision 1.8 1999/12/19 01:02:50 stephane
138 : * Add a test on the CENTER information
139 : *
140 : * Revision 1.7 1999/12/18 23:23:23 stephane
141 : * Change the format of the output double from %g to %.16g
142 : *
143 : * Revision 1.6 1999/12/18 08:22:57 daniel
144 : * Removed stray break statement in PLINE MULTIPLE write code
145 : *
146 : * Revision 1.5 1999/12/18 07:21:30 daniel
147 : * Fixed test on geometry type when writing OGRMultiLineStrings
148 : *
149 : * Revision 1.4 1999/12/18 07:11:57 daniel
150 : * Return regions as OGRMultiPolygons instead of multiple rings OGRPolygons
151 : *
152 : * Revision 1.3 1999/12/16 17:16:44 daniel
153 : * Use addRing/GeometryDirectly() (prevents leak), and rounded rectangles
154 : * always return real corner radius from file even if it is bigger than MBR
155 : *
156 : * Revision 1.2 1999/11/11 01:22:05 stephane
157 : * Remove DebugFeature call, Point Reading error, add IsValidFeature() to
158 : * test correctly if we are on a feature
159 : *
160 : * Revision 1.1 1999/11/08 19:20:30 stephane
161 : * First version
162 : *
163 : * Revision 1.1 1999/11/08 04:16:07 stephane
164 : * First Revision
165 : *
166 : *
167 : **********************************************************************/
168 :
169 : #include "mitab.h"
170 : #include "mitab_utils.h"
171 : #include <ctype.h>
172 :
173 : /*=====================================================================
174 : * class TABFeature
175 : *====================================================================*/
176 :
177 : /************************************************************************/
178 : /* MIDTokenize() */
179 : /* */
180 : /* We implement a special tokenize function so we can handle */
181 : /* multibyte delimeters (ie. MITAB bug 1266). */
182 : /* */
183 : /* http://bugzilla.maptools.org/show_bug.cgi?id=1266 */
184 : /************************************************************************/
185 44 : static char **MIDTokenize( const char *pszLine, const char *pszDelim )
186 :
187 : {
188 44 : char **papszResult = NULL;
189 44 : int iChar, iTokenChar = 0, bInQuotes = FALSE;
190 44 : char *pszToken = (char *) CPLMalloc(strlen(pszLine)+1);
191 44 : int nDelimLen = strlen(pszDelim);
192 :
193 1174 : for( iChar = 0; pszLine[iChar] != '\0'; iChar++ )
194 : {
195 1138 : if( bInQuotes && pszLine[iChar] == '"' && pszLine[iChar+1] == '"' )
196 : {
197 8 : pszToken[iTokenChar++] = '"';
198 8 : iChar++;
199 : }
200 1122 : else if( pszLine[iChar] == '"' )
201 : {
202 104 : bInQuotes = !bInQuotes;
203 : }
204 1110 : else if( !bInQuotes && strncmp(pszLine+iChar,pszDelim,nDelimLen) == 0 )
205 : {
206 92 : pszToken[iTokenChar++] = '\0';
207 92 : papszResult = CSLAddString( papszResult, pszToken );
208 :
209 92 : iChar += strlen(pszDelim) - 1;
210 92 : iTokenChar = 0;
211 : }
212 : else
213 : {
214 926 : pszToken[iTokenChar++] = pszLine[iChar];
215 : }
216 : }
217 :
218 44 : pszToken[iTokenChar++] = '\0';
219 44 : papszResult = CSLAddString( papszResult, pszToken );
220 :
221 44 : CPLFree( pszToken );
222 :
223 44 : return papszResult;
224 : }
225 :
226 : /**********************************************************************
227 : * TABFeature::ReadRecordFromMIDFile()
228 : *
229 : * This method is used to read the Record (Attributs) for all type of
230 : * feature included in a mid/mif file.
231 : *
232 : * Returns 0 on success, -1 on error, in which case CPLError() will have
233 : * been called.
234 : **********************************************************************/
235 44 : int TABFeature::ReadRecordFromMIDFile(MIDDATAFile *fp)
236 : {
237 : const char *pszLine;
238 : char **papszToken;
239 : int nFields,i;
240 44 : OGRFieldDefn *poFDefn = NULL;
241 : #ifdef MITAB_USE_OFTDATETIME
242 : int nYear, nMonth, nDay, nHour, nMin, nSec, nMS, nTZFlag;
243 44 : nYear = nMonth = nDay = nHour = nMin = nSec = nMS = nTZFlag = 0;
244 : #endif
245 :
246 44 : nFields = GetFieldCount();
247 :
248 44 : pszLine = fp->GetLastLine();
249 :
250 44 : if (pszLine == NULL)
251 : {
252 : CPLError(CE_Failure, CPLE_FileIO,
253 0 : "Unexpected EOF while reading attribute record from MID file.");
254 0 : return -1;
255 : }
256 :
257 44 : papszToken = MIDTokenize( pszLine, fp->GetDelimiter() );
258 :
259 : // Ensure that a blank line in a mid file is treated as one field
260 : // containing an empty string.
261 44 : if( nFields == 1 && CSLCount(papszToken) == 0 && pszLine[0] == '\0' )
262 0 : papszToken = CSLAddString(papszToken,"");
263 :
264 : // Make sure we found at least the expected number of field values.
265 : // Note that it is possible to have a stray delimiter at the end of
266 : // the line (mif/mid files from Geomedia), so don't produce an error
267 : // if we find more tokens than expected.
268 44 : if (CSLCount(papszToken) < nFields)
269 : {
270 0 : CSLDestroy(papszToken);
271 0 : return -1;
272 : }
273 :
274 180 : for (i=0;i<nFields;i++)
275 : {
276 136 : poFDefn = GetFieldDefnRef(i);
277 136 : switch(poFDefn->GetType())
278 : {
279 : #ifdef MITAB_USE_OFTDATETIME
280 : case OFTTime:
281 : {
282 0 : if (strlen(papszToken[i]) == 9)
283 : {
284 0 : sscanf(papszToken[i],"%2d%2d%2d%3d",&nHour, &nMin, &nSec, &nMS);
285 0 : SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec, 0);
286 : }
287 0 : break;
288 : }
289 : case OFTDate:
290 : {
291 0 : if (strlen(papszToken[i]) == 8)
292 : {
293 0 : sscanf(papszToken[i], "%4d%2d%2d", &nYear, &nMonth, &nDay);
294 0 : SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec, 0);
295 : }
296 0 : break;
297 : }
298 : case OFTDateTime:
299 : {
300 0 : if (strlen(papszToken[i]) == 17)
301 : {
302 0 : sscanf(papszToken[i], "%4d%2d%2d%2d%2d%2d%3d",
303 0 : &nYear, &nMonth, &nDay, &nHour, &nMin, &nSec, &nMS);
304 0 : SetField(i, nYear, nMonth, nDay, nHour, nMin, nSec, 0);
305 : }
306 0 : break;
307 : }
308 : #endif
309 :
310 : default:
311 136 : SetField(i,papszToken[i]);
312 : }
313 : }
314 :
315 44 : fp->GetLine();
316 :
317 44 : CSLDestroy(papszToken);
318 :
319 44 : return 0;
320 : }
321 :
322 : /**********************************************************************
323 : * TABFeature::WriteRecordToMIDFile()
324 : *
325 : * This methode is used to write the Record (Attributs) for all type
326 : * of feature included in a mid file.
327 : *
328 : * Return 0 on success, -1 on error
329 : **********************************************************************/
330 21 : int TABFeature::WriteRecordToMIDFile(MIDDATAFile *fp)
331 : {
332 : int iField, numFields;
333 21 : OGRFieldDefn *poFDefn = NULL;
334 : #ifdef MITAB_USE_OFTDATETIME
335 : char szBuffer[20];
336 : int nYear, nMonth, nDay, nHour, nMin, nSec, nMS, nTZFlag;
337 21 : nYear = nMonth = nDay = nHour = nMin = nSec = nMS = nTZFlag = 0;
338 : #endif
339 :
340 21 : CPLAssert(fp);
341 :
342 21 : const char *delimiter = fp->GetDelimiter();
343 :
344 21 : numFields = GetFieldCount();
345 :
346 69 : for(iField=0; iField<numFields; iField++)
347 : {
348 48 : if (iField != 0)
349 27 : fp->WriteLine(delimiter);
350 48 : poFDefn = GetFieldDefnRef( iField );
351 :
352 48 : switch(poFDefn->GetType())
353 : {
354 : case OFTString:
355 : {
356 18 : int nStringLen = strlen(GetFieldAsString(iField));
357 18 : char *pszString = (char*)CPLMalloc((nStringLen+1)*sizeof(char));
358 18 : strcpy(pszString, GetFieldAsString(iField));
359 18 : char *pszWorkString = (char*)CPLMalloc((2*(nStringLen)+1)*sizeof(char));
360 18 : int j = 0;
361 142 : for (int i =0; i < nStringLen; ++i)
362 : {
363 124 : if (pszString[i] == '"')
364 : {
365 0 : pszWorkString[j] = pszString[i];
366 0 : ++j;
367 0 : pszWorkString[j] = pszString[i];
368 : }
369 124 : else if (pszString[i] == '\n')
370 : {
371 0 : pszWorkString[j] = '\\';
372 0 : ++j;
373 0 : pszWorkString[j] = 'n';
374 : }
375 : else
376 124 : pszWorkString[j] = pszString[i];
377 124 : ++j;
378 : }
379 :
380 18 : pszWorkString[j] = '\0';
381 18 : CPLFree(pszString);
382 18 : pszString = (char*)CPLMalloc((strlen(pszWorkString)+1)*sizeof(char));
383 18 : strcpy(pszString, pszWorkString);
384 18 : CPLFree(pszWorkString);
385 18 : fp->WriteLine("\"%s\"",pszString);
386 18 : CPLFree(pszString);
387 18 : break;
388 : }
389 : #ifdef MITAB_USE_OFTDATETIME
390 : case OFTTime:
391 : {
392 0 : if (!IsFieldSet(iField))
393 : {
394 0 : szBuffer[0] = '\0';
395 : }
396 : else
397 : {
398 : GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
399 0 : &nHour, &nMin, &nSec, &nTZFlag);
400 0 : sprintf(szBuffer, "%2.2d%2.2d%2.2d%3.3d", nHour, nMin, nSec, nMS);
401 : }
402 0 : fp->WriteLine("%s",szBuffer);
403 0 : break;
404 : }
405 : case OFTDate:
406 : {
407 0 : if (!IsFieldSet(iField))
408 : {
409 0 : szBuffer[0] = '\0';
410 : }
411 : else
412 : {
413 : GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
414 0 : &nHour, &nMin, &nSec, &nTZFlag);
415 0 : sprintf(szBuffer, "%4.4d%2.2d%2.2d", nYear, nMonth, nDay);
416 : }
417 0 : fp->WriteLine("%s",szBuffer);
418 0 : break;
419 : }
420 : case OFTDateTime:
421 : {
422 0 : if (!IsFieldSet(iField))
423 : {
424 0 : szBuffer[0] = '\0';
425 : }
426 : else
427 : {
428 : GetFieldAsDateTime(iField, &nYear, &nMonth, &nDay,
429 0 : &nHour, &nMin, &nSec, &nTZFlag);
430 : sprintf(szBuffer, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d%3.3d",
431 0 : nYear, nMonth, nDay, nHour, nMin, nSec, nMS);
432 : }
433 0 : fp->WriteLine("%s",szBuffer);
434 0 : break;
435 : }
436 : #endif
437 : default:
438 30 : fp->WriteLine("%s",GetFieldAsString(iField));
439 : }
440 : }
441 :
442 21 : fp->WriteLine("\n");
443 :
444 21 : return 0;
445 : }
446 :
447 : /**********************************************************************
448 : * TABFeature::ReadGeometryFromMIFFile()
449 : *
450 : * In derived classes, this method should be reimplemented to
451 : * fill the geometry and representation (color, etc...) part of the
452 : * feature from the contents of the .MAP object pointed to by poMAPFile.
453 : *
454 : * It is assumed that before calling ReadGeometryFromMAPFile(), poMAPFile
455 : * currently points to the beginning of a map object.
456 : *
457 : * The current implementation does nothing since instances of TABFeature
458 : * objects contain no geometry (i.e. TAB_GEOM_NONE).
459 : *
460 : * Returns 0 on success, -1 on error, in which case CPLError() will have
461 : * been called.
462 : **********************************************************************/
463 12 : int TABFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
464 : {
465 : const char *pszLine;
466 :
467 : /* Go to the first line of the next feature */
468 :
469 12 : while (((pszLine = fp->GetLine()) != NULL) &&
470 : fp->IsValidFeature(pszLine) == FALSE)
471 : ;
472 :
473 12 : return 0;
474 : }
475 :
476 : /**********************************************************************
477 : * TABFeature::WriteGeometryToMIFFile()
478 : *
479 : *
480 : * In derived classes, this method should be reimplemented to
481 : * write the geometry and representation (color, etc...) part of the
482 : * feature to the .MAP object pointed to by poMAPFile.
483 : *
484 : * It is assumed that before calling WriteGeometryToMAPFile(), poMAPFile
485 : * currently points to a valid map object.
486 : *
487 : * The current implementation does nothing since instances of TABFeature
488 : * objects contain no geometry.
489 : *
490 : * Returns 0 on success, -1 on error, in which case CPLError() will have
491 : * been called.
492 : **********************************************************************/
493 7 : int TABFeature::WriteGeometryToMIFFile(MIDDATAFile *fp)
494 : {
495 7 : fp->WriteLine("NONE\n");
496 7 : return 0;
497 : }
498 :
499 : /**********************************************************************
500 : *
501 : **********************************************************************/
502 4 : int TABPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
503 : {
504 : OGRGeometry *poGeometry;
505 :
506 : char **papszToken;
507 : const char *pszLine;
508 : double dfX,dfY;
509 : papszToken = CSLTokenizeString2(fp->GetSavedLine(),
510 4 : " \t", CSLT_HONOURSTRINGS);
511 :
512 4 : if (CSLCount(papszToken) !=3)
513 : {
514 0 : CSLDestroy(papszToken);
515 0 : return -1;
516 : }
517 :
518 4 : dfX = fp->GetXTrans(atof(papszToken[1]));
519 4 : dfY = fp->GetYTrans(atof(papszToken[2]));
520 :
521 4 : CSLDestroy(papszToken);
522 4 : papszToken = NULL;
523 :
524 : // Read optional SYMBOL line...
525 4 : pszLine = fp->GetLastLine();
526 4 : if( pszLine != NULL )
527 : papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
528 4 : TRUE,FALSE);
529 4 : if (CSLCount(papszToken) == 4 && EQUAL(papszToken[0], "SYMBOL") )
530 : {
531 4 : SetSymbolNo((GInt16)atoi(papszToken[1]));
532 4 : SetSymbolColor((GInt32)atoi(papszToken[2]));
533 4 : SetSymbolSize((GInt16)atoi(papszToken[3]));
534 : }
535 :
536 4 : CSLDestroy(papszToken);
537 4 : papszToken = NULL;
538 :
539 : // scan until we reach 1st line of next feature
540 : // Since SYMBOL is optional, we have to test IsValidFeature() on that
541 : // line as well.
542 12 : while (pszLine && fp->IsValidFeature(pszLine) == FALSE)
543 : {
544 4 : pszLine = fp->GetLine();
545 : }
546 :
547 4 : poGeometry = new OGRPoint(dfX, dfY);
548 :
549 4 : SetGeometryDirectly(poGeometry);
550 :
551 4 : SetMBR(dfX, dfY, dfX, dfY);
552 :
553 :
554 4 : return 0;
555 : }
556 :
557 : /**********************************************************************
558 : *
559 : **********************************************************************/
560 4 : int TABPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
561 : {
562 : OGRGeometry *poGeom;
563 : OGRPoint *poPoint;
564 :
565 : /*-----------------------------------------------------------------
566 : * Fetch and validate geometry
567 : *----------------------------------------------------------------*/
568 4 : poGeom = GetGeometryRef();
569 4 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
570 4 : poPoint = (OGRPoint*)poGeom;
571 : else
572 : {
573 : CPLError(CE_Failure, CPLE_AssertionFailed,
574 0 : "TABPoint: Missing or Invalid Geometry!");
575 0 : return -1;
576 : }
577 :
578 4 : fp->WriteLine("Point %.15g %.15g\n",poPoint->getX(),poPoint->getY());
579 : fp->WriteLine(" Symbol (%d,%d,%d)\n",GetSymbolNo(),GetSymbolColor(),
580 4 : GetSymbolSize());
581 :
582 4 : return 0;
583 : }
584 :
585 : /**********************************************************************
586 : *
587 : **********************************************************************/
588 0 : int TABFontPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
589 : {
590 : OGRGeometry *poGeometry;
591 :
592 : char **papszToken;
593 : const char *pszLine;
594 : double dfX,dfY;
595 : papszToken = CSLTokenizeString2(fp->GetSavedLine(),
596 0 : " \t", CSLT_HONOURSTRINGS);
597 :
598 0 : if (CSLCount(papszToken) !=3)
599 : {
600 0 : CSLDestroy(papszToken);
601 0 : return -1;
602 : }
603 :
604 0 : dfX = fp->GetXTrans(atof(papszToken[1]));
605 0 : dfY = fp->GetYTrans(atof(papszToken[2]));
606 :
607 0 : CSLDestroy(papszToken);
608 :
609 : papszToken = CSLTokenizeStringComplex(fp->GetLastLine()," ,()\t",
610 0 : TRUE,FALSE);
611 :
612 0 : if (CSLCount(papszToken) !=7)
613 : {
614 0 : CSLDestroy(papszToken);
615 0 : return -1;
616 : }
617 :
618 0 : SetSymbolNo((GInt16)atoi(papszToken[1]));
619 0 : SetSymbolColor((GInt32)atoi(papszToken[2]));
620 0 : SetSymbolSize((GInt16)atoi(papszToken[3]));
621 0 : SetFontName(papszToken[4]);
622 0 : SetFontStyleMIFValue(atoi(papszToken[5]));
623 0 : SetSymbolAngle(atof(papszToken[6]));
624 :
625 0 : CSLDestroy(papszToken);
626 :
627 0 : poGeometry = new OGRPoint(dfX, dfY);
628 :
629 0 : SetGeometryDirectly(poGeometry);
630 :
631 0 : SetMBR(dfX, dfY, dfX, dfY);
632 :
633 : /* Go to the first line of the next feature */
634 :
635 0 : while (((pszLine = fp->GetLine()) != NULL) &&
636 : fp->IsValidFeature(pszLine) == FALSE)
637 : ;
638 0 : return 0;
639 : }
640 :
641 : /**********************************************************************
642 : *
643 : **********************************************************************/
644 0 : int TABFontPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
645 : {
646 : OGRGeometry *poGeom;
647 : OGRPoint *poPoint;
648 :
649 : /*-----------------------------------------------------------------
650 : * Fetch and validate geometry
651 : *----------------------------------------------------------------*/
652 0 : poGeom = GetGeometryRef();
653 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
654 0 : poPoint = (OGRPoint*)poGeom;
655 : else
656 : {
657 : CPLError(CE_Failure, CPLE_AssertionFailed,
658 0 : "TABFontPoint: Missing or Invalid Geometry!");
659 0 : return -1;
660 : }
661 :
662 0 : fp->WriteLine("Point %.15g %.15g\n",poPoint->getX(),poPoint->getY());
663 : fp->WriteLine(" Symbol (%d,%d,%d,\"%s\",%d,%.15g)\n",
664 : GetSymbolNo(),GetSymbolColor(),
665 : GetSymbolSize(),GetFontNameRef(),GetFontStyleMIFValue(),
666 0 : GetSymbolAngle());
667 :
668 0 : return 0;
669 : }
670 :
671 : /**********************************************************************
672 : *
673 : **********************************************************************/
674 0 : int TABCustomPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
675 : {
676 : OGRGeometry *poGeometry;
677 :
678 : char **papszToken;
679 : const char *pszLine;
680 : double dfX,dfY;
681 :
682 : papszToken = CSLTokenizeString2(fp->GetSavedLine(),
683 0 : " \t", CSLT_HONOURSTRINGS);
684 :
685 :
686 0 : if (CSLCount(papszToken) !=3)
687 : {
688 0 : CSLDestroy(papszToken);
689 0 : return -1;
690 : }
691 :
692 0 : dfX = fp->GetXTrans(atof(papszToken[1]));
693 0 : dfY = fp->GetYTrans(atof(papszToken[2]));
694 :
695 0 : CSLDestroy(papszToken);
696 :
697 : papszToken = CSLTokenizeStringComplex(fp->GetLastLine()," ,()\t",
698 0 : TRUE,FALSE);
699 0 : if (CSLCount(papszToken) !=5)
700 : {
701 :
702 0 : CSLDestroy(papszToken);
703 0 : return -1;
704 : }
705 :
706 0 : SetFontName(papszToken[1]);
707 0 : SetSymbolColor((GInt32)atoi(papszToken[2]));
708 0 : SetSymbolSize((GInt16)atoi(papszToken[3]));
709 0 : m_nCustomStyle = (GByte)atoi(papszToken[4]);
710 :
711 0 : CSLDestroy(papszToken);
712 :
713 0 : poGeometry = new OGRPoint(dfX, dfY);
714 :
715 0 : SetGeometryDirectly(poGeometry);
716 :
717 0 : SetMBR(dfX, dfY, dfX, dfY);
718 :
719 : /* Go to the first line of the next feature */
720 :
721 0 : while (((pszLine = fp->GetLine()) != NULL) &&
722 : fp->IsValidFeature(pszLine) == FALSE)
723 : ;
724 :
725 0 : return 0;
726 :
727 : }
728 :
729 : /**********************************************************************
730 : *
731 : **********************************************************************/
732 0 : int TABCustomPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
733 : {
734 : OGRGeometry *poGeom;
735 : OGRPoint *poPoint;
736 :
737 : /*-----------------------------------------------------------------
738 : * Fetch and validate geometry
739 : *----------------------------------------------------------------*/
740 0 : poGeom = GetGeometryRef();
741 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
742 0 : poPoint = (OGRPoint*)poGeom;
743 : else
744 : {
745 : CPLError(CE_Failure, CPLE_AssertionFailed,
746 0 : "TABCustomPoint: Missing or Invalid Geometry!");
747 0 : return -1;
748 : }
749 :
750 :
751 0 : fp->WriteLine("Point %.15g %.15g\n",poPoint->getX(),poPoint->getY());
752 : fp->WriteLine(" Symbol (\"%s\",%d,%d,%d)\n",GetFontNameRef(),
753 0 : GetSymbolColor(), GetSymbolSize(),m_nCustomStyle);
754 :
755 0 : return 0;
756 : }
757 :
758 : /**********************************************************************
759 : *
760 : **********************************************************************/
761 0 : int TABPolyline::ReadGeometryFromMIFFile(MIDDATAFile *fp)
762 : {
763 : const char *pszLine;
764 : char **papszToken;
765 : OGRLineString *poLine;
766 : OGRMultiLineString *poMultiLine;
767 0 : GBool bMultiple = FALSE;
768 0 : int nNumPoints,nNumSec=0,i,j;
769 0 : OGREnvelope sEnvelope;
770 :
771 :
772 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
773 0 : " \t", CSLT_HONOURSTRINGS);
774 :
775 0 : if (CSLCount(papszToken) < 1)
776 : {
777 0 : CSLDestroy(papszToken);
778 0 : return -1;
779 : }
780 :
781 0 : if (EQUALN(papszToken[0],"LINE",4))
782 : {
783 0 : if (CSLCount(papszToken) != 5)
784 0 : return -1;
785 :
786 0 : poLine = new OGRLineString();
787 0 : poLine->setNumPoints(2);
788 0 : poLine->setPoint(0, fp->GetXTrans(atof(papszToken[1])),
789 0 : fp->GetYTrans(atof(papszToken[2])));
790 0 : poLine->setPoint(1, fp->GetXTrans(atof(papszToken[3])),
791 0 : fp->GetYTrans(atof(papszToken[4])));
792 0 : SetGeometryDirectly(poLine);
793 0 : poLine->getEnvelope(&sEnvelope);
794 0 : SetMBR(sEnvelope.MinX, sEnvelope.MinY,sEnvelope.MaxX,sEnvelope.MaxY);
795 : }
796 0 : else if (EQUALN(papszToken[0],"PLINE",5))
797 : {
798 0 : switch (CSLCount(papszToken))
799 : {
800 : case 1:
801 0 : bMultiple = FALSE;
802 0 : pszLine = fp->GetLine();
803 0 : nNumPoints = atoi(pszLine);
804 0 : break;
805 : case 2:
806 0 : bMultiple = FALSE;
807 0 : nNumPoints = atoi(papszToken[1]);
808 0 : break;
809 : case 3:
810 0 : if (EQUALN(papszToken[1],"MULTIPLE",8))
811 : {
812 0 : bMultiple = TRUE;
813 0 : nNumSec = atoi(papszToken[2]);
814 0 : pszLine = fp->GetLine();
815 0 : nNumPoints = atoi(pszLine);
816 0 : break;
817 : }
818 : else
819 : {
820 0 : CSLDestroy(papszToken);
821 0 : return -1;
822 : }
823 : break;
824 : case 4:
825 0 : if (EQUALN(papszToken[1],"MULTIPLE",8))
826 : {
827 0 : bMultiple = TRUE;
828 0 : nNumSec = atoi(papszToken[2]);
829 0 : nNumPoints = atoi(papszToken[3]);
830 0 : break;
831 : }
832 : else
833 : {
834 0 : CSLDestroy(papszToken);
835 0 : return -1;
836 : }
837 : break;
838 : default:
839 0 : CSLDestroy(papszToken);
840 0 : return -1;
841 : break;
842 : }
843 :
844 0 : if (bMultiple)
845 : {
846 0 : poMultiLine = new OGRMultiLineString();
847 0 : for (j=0;j<nNumSec;j++)
848 : {
849 0 : poLine = new OGRLineString();
850 0 : if (j != 0)
851 0 : nNumPoints = atoi(fp->GetLine());
852 0 : if (nNumPoints < 2)
853 : {
854 : CPLError(CE_Failure, CPLE_FileIO,
855 : "Invalid number of vertices (%d) in PLINE "
856 0 : "MULTIPLE segment.", nNumPoints);
857 0 : return -1;
858 : }
859 0 : poLine->setNumPoints(nNumPoints);
860 0 : for (i=0;i<nNumPoints;i++)
861 : {
862 0 : CSLDestroy(papszToken);
863 : papszToken = CSLTokenizeString2(fp->GetLine(),
864 0 : " \t", CSLT_HONOURSTRINGS);
865 0 : poLine->setPoint(i,fp->GetXTrans(atof(papszToken[0])),
866 0 : fp->GetYTrans(atof(papszToken[1])));
867 : }
868 0 : if (poMultiLine->addGeometryDirectly(poLine) != OGRERR_NONE)
869 : {
870 0 : CPLAssert(FALSE); // Just in case OGR is modified
871 : }
872 : }
873 0 : if (SetGeometryDirectly(poMultiLine) != OGRERR_NONE)
874 : {
875 0 : CPLAssert(FALSE); // Just in case OGR is modified
876 : }
877 0 : poMultiLine->getEnvelope(&sEnvelope);
878 : SetMBR(sEnvelope.MinX, sEnvelope.MinY,
879 0 : sEnvelope.MaxX,sEnvelope.MaxY);
880 : }
881 : else
882 : {
883 0 : poLine = new OGRLineString();
884 0 : poLine->setNumPoints(nNumPoints);
885 0 : for (i=0;i<nNumPoints;i++)
886 : {
887 0 : CSLDestroy(papszToken);
888 : papszToken = CSLTokenizeString2(fp->GetLine(),
889 0 : " \t", CSLT_HONOURSTRINGS);
890 :
891 0 : if (CSLCount(papszToken) != 2)
892 0 : return -1;
893 0 : poLine->setPoint(i,fp->GetXTrans(atof(papszToken[0])),
894 0 : fp->GetYTrans(atof(papszToken[1])));
895 : }
896 0 : SetGeometryDirectly(poLine);
897 0 : poLine->getEnvelope(&sEnvelope);
898 : SetMBR(sEnvelope.MinX, sEnvelope.MinY,
899 0 : sEnvelope.MaxX,sEnvelope.MaxY);
900 : }
901 : }
902 :
903 0 : CSLDestroy(papszToken);
904 0 : papszToken = NULL;
905 :
906 0 : while (((pszLine = fp->GetLine()) != NULL) &&
907 : fp->IsValidFeature(pszLine) == FALSE)
908 : {
909 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
910 0 : TRUE,FALSE);
911 :
912 0 : if (CSLCount(papszToken) >= 1)
913 : {
914 0 : if (EQUALN(papszToken[0],"PEN",3))
915 : {
916 :
917 0 : if (CSLCount(papszToken) == 4)
918 : {
919 0 : SetPenWidthMIF(atoi(papszToken[1]));
920 0 : SetPenPattern((GByte)atoi(papszToken[2]));
921 0 : SetPenColor((GInt32)atoi(papszToken[3]));
922 : }
923 :
924 : }
925 0 : else if (EQUALN(papszToken[0],"SMOOTH",6))
926 : {
927 0 : m_bSmooth = TRUE;
928 : }
929 : }
930 0 : CSLDestroy(papszToken);
931 : }
932 0 : return 0;
933 : }
934 :
935 : /**********************************************************************
936 : *
937 : **********************************************************************/
938 0 : int TABPolyline::WriteGeometryToMIFFile(MIDDATAFile *fp)
939 : {
940 : OGRGeometry *poGeom;
941 0 : OGRMultiLineString *poMultiLine = NULL;
942 0 : OGRLineString *poLine = NULL;
943 : int nNumPoints,i;
944 :
945 :
946 : /*-----------------------------------------------------------------
947 : * Fetch and validate geometry
948 : *----------------------------------------------------------------*/
949 0 : poGeom = GetGeometryRef();
950 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
951 : {
952 : /*-------------------------------------------------------------
953 : * Simple polyline
954 : *------------------------------------------------------------*/
955 0 : poLine = (OGRLineString*)poGeom;
956 0 : nNumPoints = poLine->getNumPoints();
957 0 : if (nNumPoints == 2)
958 : {
959 : fp->WriteLine("Line %.15g %.15g %.15g %.15g\n",poLine->getX(0),poLine->getY(0),
960 0 : poLine->getX(1),poLine->getY(1));
961 : }
962 : else
963 : {
964 :
965 0 : fp->WriteLine("Pline %d\n",nNumPoints);
966 0 : for (i=0;i<nNumPoints;i++)
967 : {
968 0 : fp->WriteLine("%.15g %.15g\n",poLine->getX(i),poLine->getY(i));
969 : }
970 : }
971 : }
972 0 : else if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiLineString)
973 : {
974 : /*-------------------------------------------------------------
975 : * Multiple polyline... validate all components
976 : *------------------------------------------------------------*/
977 : int iLine, numLines;
978 0 : poMultiLine = (OGRMultiLineString*)poGeom;
979 0 : numLines = poMultiLine->getNumGeometries();
980 :
981 0 : fp->WriteLine("PLINE MULTIPLE %d\n", numLines);
982 :
983 0 : for(iLine=0; iLine < numLines; iLine++)
984 : {
985 0 : poGeom = poMultiLine->getGeometryRef(iLine);
986 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbLineString)
987 : {
988 0 : poLine = (OGRLineString*)poGeom;
989 0 : nNumPoints = poLine->getNumPoints();
990 :
991 0 : fp->WriteLine(" %d\n",nNumPoints);
992 0 : for (i=0;i<nNumPoints;i++)
993 : {
994 0 : fp->WriteLine("%.15g %.15g\n",poLine->getX(i),poLine->getY(i));
995 : }
996 : }
997 : else
998 : {
999 : CPLError(CE_Failure, CPLE_AssertionFailed,
1000 0 : "TABPolyline: Object contains an invalid Geometry!");
1001 : }
1002 : }
1003 : }
1004 : else
1005 : {
1006 : CPLError(CE_Failure, CPLE_AssertionFailed,
1007 0 : "TABPolyline: Missing or Invalid Geometry!");
1008 : }
1009 :
1010 0 : if (GetPenPattern())
1011 : fp->WriteLine(" Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
1012 0 : GetPenColor());
1013 0 : if (m_bSmooth)
1014 0 : fp->WriteLine(" Smooth\n");
1015 :
1016 0 : return 0;
1017 :
1018 : }
1019 :
1020 : /**********************************************************************
1021 : * TABRegion::ReadGeometryFromMIFFile()
1022 : *
1023 : * Fill the geometry and representation (color, etc...) part of the
1024 : * feature from the contents of the .MIF file
1025 : *
1026 : * Returns 0 on success, -1 on error, in which case CPLError() will have
1027 : * been called.
1028 : **********************************************************************/
1029 28 : int TABRegion::ReadGeometryFromMIFFile(MIDDATAFile *fp)
1030 : {
1031 : double dX, dY;
1032 : OGRLinearRing *poRing;
1033 28 : OGRGeometry *poGeometry = NULL;
1034 28 : OGRPolygon **tabPolygons = NULL;
1035 28 : int i,iSection, numLineSections=0;
1036 : char **papszToken;
1037 : const char *pszLine;
1038 28 : OGREnvelope sEnvelope;
1039 :
1040 28 : m_bSmooth = FALSE;
1041 : /*=============================================================
1042 : * REGION (Similar to PLINE MULTIPLE)
1043 : *============================================================*/
1044 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
1045 28 : " \t", CSLT_HONOURSTRINGS);
1046 :
1047 28 : if (CSLCount(papszToken) ==2)
1048 28 : numLineSections = atoi(papszToken[1]);
1049 28 : CSLDestroy(papszToken);
1050 28 : papszToken = NULL;
1051 :
1052 28 : if (numLineSections > 0)
1053 28 : tabPolygons = new OGRPolygon*[numLineSections];
1054 :
1055 56 : for(iSection=0; iSection<numLineSections; iSection++)
1056 : {
1057 28 : int numSectionVertices = 0;
1058 :
1059 28 : tabPolygons[iSection] = new OGRPolygon();
1060 :
1061 28 : if ((pszLine = fp->GetLine()) != NULL)
1062 : {
1063 28 : numSectionVertices = atoi(pszLine);
1064 : }
1065 :
1066 28 : poRing = new OGRLinearRing();
1067 28 : poRing->setNumPoints(numSectionVertices);
1068 :
1069 566 : for(i=0; i<numSectionVertices; i++)
1070 : {
1071 538 : pszLine = fp->GetLine();
1072 538 : if (pszLine)
1073 : {
1074 : papszToken = CSLTokenizeStringComplex(pszLine," ,\t",
1075 538 : TRUE,FALSE);
1076 538 : if (CSLCount(papszToken) == 2)
1077 : {
1078 538 : dX = fp->GetXTrans(atof(papszToken[0]));
1079 538 : dY = fp->GetYTrans(atof(papszToken[1]));
1080 538 : poRing->setPoint(i, dX, dY);
1081 : }
1082 538 : CSLDestroy(papszToken);
1083 538 : papszToken = NULL;
1084 : }
1085 : }
1086 :
1087 28 : tabPolygons[iSection]->addRingDirectly(poRing);
1088 :
1089 28 : if (numLineSections == 1)
1090 28 : poGeometry = tabPolygons[iSection];
1091 :
1092 28 : poRing = NULL;
1093 : }
1094 :
1095 28 : if (numLineSections > 1)
1096 : {
1097 : int isValidGeometry;
1098 0 : const char* papszOptions[] = { "METHOD=DEFAULT", NULL };
1099 : poGeometry = OGRGeometryFactory::organizePolygons(
1100 0 : (OGRGeometry**)tabPolygons, numLineSections, &isValidGeometry, papszOptions );
1101 :
1102 0 : if (!isValidGeometry)
1103 : {
1104 : CPLError(CE_Warning, CPLE_AppDefined,
1105 : "Geometry of polygon cannot be translated to Simple Geometry. "
1106 0 : "All polygons will be contained in a multipolygon.\n");
1107 : }
1108 : }
1109 :
1110 28 : if (tabPolygons)
1111 28 : delete[] tabPolygons;
1112 :
1113 28 : SetGeometryDirectly(poGeometry);
1114 28 : poGeometry->getEnvelope(&sEnvelope);
1115 :
1116 28 : SetMBR(sEnvelope.MinX, sEnvelope.MinY, sEnvelope.MaxX, sEnvelope.MaxY);
1117 :
1118 112 : while (((pszLine = fp->GetLine()) != NULL) &&
1119 : fp->IsValidFeature(pszLine) == FALSE)
1120 : {
1121 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
1122 56 : TRUE,FALSE);
1123 :
1124 56 : if (CSLCount(papszToken) > 1)
1125 : {
1126 56 : if (EQUALN(papszToken[0],"PEN",3))
1127 : {
1128 :
1129 28 : if (CSLCount(papszToken) == 4)
1130 : {
1131 28 : SetPenWidthMIF(atoi(papszToken[1]));
1132 28 : SetPenPattern((GByte)atoi(papszToken[2]));
1133 28 : SetPenColor((GInt32)atoi(papszToken[3]));
1134 : }
1135 :
1136 : }
1137 28 : else if (EQUALN(papszToken[0],"BRUSH", 5))
1138 : {
1139 28 : if (CSLCount(papszToken) >= 3)
1140 : {
1141 28 : SetBrushFGColor((GInt32)atoi(papszToken[2]));
1142 28 : SetBrushPattern((GByte)atoi(papszToken[1]));
1143 :
1144 28 : if (CSLCount(papszToken) == 4)
1145 28 : SetBrushBGColor(atoi(papszToken[3]));
1146 : else
1147 0 : SetBrushTransparent(TRUE);
1148 : }
1149 :
1150 : }
1151 0 : else if (EQUALN(papszToken[0],"CENTER",6))
1152 : {
1153 0 : if (CSLCount(papszToken) == 3)
1154 : {
1155 0 : SetCenter(fp->GetXTrans(atof(papszToken[1])),
1156 0 : fp->GetYTrans(atof(papszToken[2])) );
1157 : }
1158 : }
1159 : }
1160 56 : CSLDestroy(papszToken);
1161 56 : papszToken = NULL;
1162 : }
1163 :
1164 :
1165 28 : return 0;
1166 : }
1167 :
1168 : /**********************************************************************
1169 : * TABRegion::WriteGeometryToMIFFile()
1170 : *
1171 : * Write the geometry and representation (color, etc...) part of the
1172 : * feature to the .MIF file
1173 : *
1174 : * Returns 0 on success, -1 on error, in which case CPLError() will have
1175 : * been called.
1176 : **********************************************************************/
1177 10 : int TABRegion::WriteGeometryToMIFFile(MIDDATAFile *fp)
1178 : {
1179 : OGRGeometry *poGeom;
1180 :
1181 10 : poGeom = GetGeometryRef();
1182 :
1183 10 : if (poGeom && (wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ||
1184 0 : wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon ) )
1185 : {
1186 : /*=============================================================
1187 : * REGIONs are similar to PLINE MULTIPLE
1188 : *
1189 : * We accept both OGRPolygons (with one or multiple rings) and
1190 : * OGRMultiPolygons as input.
1191 : *============================================================*/
1192 : int i, iRing, numRingsTotal, numPoints;
1193 :
1194 10 : numRingsTotal = GetNumRings();
1195 :
1196 10 : fp->WriteLine("Region %d\n",numRingsTotal);
1197 :
1198 20 : for(iRing=0; iRing < numRingsTotal; iRing++)
1199 : {
1200 : OGRLinearRing *poRing;
1201 :
1202 10 : poRing = GetRingRef(iRing);
1203 10 : if (poRing == NULL)
1204 : {
1205 : CPLError(CE_Failure, CPLE_AssertionFailed,
1206 0 : "TABRegion: Object Geometry contains NULL rings!");
1207 0 : return -1;
1208 : }
1209 :
1210 10 : numPoints = poRing->getNumPoints();
1211 :
1212 10 : fp->WriteLine(" %d\n",numPoints);
1213 255 : for(i=0; i<numPoints; i++)
1214 : {
1215 245 : fp->WriteLine("%.15g %.15g\n",poRing->getX(i), poRing->getY(i));
1216 : }
1217 : }
1218 :
1219 10 : if (GetPenPattern())
1220 : fp->WriteLine(" Pen (%d,%d,%d)\n",
1221 : GetPenWidthMIF(),GetPenPattern(),
1222 10 : GetPenColor());
1223 :
1224 :
1225 10 : if (GetBrushPattern())
1226 : {
1227 10 : if (GetBrushTransparent() == 0)
1228 : fp->WriteLine(" Brush (%d,%d,%d)\n",GetBrushPattern(),
1229 10 : GetBrushFGColor(),GetBrushBGColor());
1230 : else
1231 : fp->WriteLine(" Brush (%d,%d)\n",GetBrushPattern(),
1232 0 : GetBrushFGColor());
1233 : }
1234 :
1235 10 : if (m_bCenterIsSet)
1236 : {
1237 0 : fp->WriteLine(" Center %.15g %.15g\n", m_dCenterX, m_dCenterY);
1238 : }
1239 :
1240 :
1241 : }
1242 : else
1243 : {
1244 : CPLError(CE_Failure, CPLE_AssertionFailed,
1245 0 : "TABRegion: Object contains an invalid Geometry!");
1246 0 : return -1;
1247 : }
1248 :
1249 10 : return 0;
1250 : }
1251 :
1252 : /**********************************************************************
1253 : *
1254 : **********************************************************************/
1255 0 : int TABRectangle::ReadGeometryFromMIFFile(MIDDATAFile *fp)
1256 : {
1257 : const char *pszLine;
1258 : char **papszToken;
1259 : double dXMin, dYMin, dXMax, dYMax;
1260 : OGRPolygon *poPolygon;
1261 : OGRLinearRing *poRing;
1262 :
1263 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
1264 0 : " \t", CSLT_HONOURSTRINGS);
1265 :
1266 0 : if (CSLCount(papszToken) < 5)
1267 : {
1268 0 : CSLDestroy(papszToken);
1269 0 : return -1;
1270 : }
1271 :
1272 0 : dXMin = fp->GetXTrans(atof(papszToken[1]));
1273 0 : dXMax = fp->GetXTrans(atof(papszToken[3]));
1274 0 : dYMin = fp->GetYTrans(atof(papszToken[2]));
1275 0 : dYMax = fp->GetYTrans(atof(papszToken[4]));
1276 :
1277 : /*-----------------------------------------------------------------
1278 : * Call SetMBR() and GetMBR() now to make sure that min values are
1279 : * really smaller than max values.
1280 : *----------------------------------------------------------------*/
1281 0 : SetMBR(dXMin, dYMin, dXMax, dYMax);
1282 0 : GetMBR(dXMin, dYMin, dXMax, dYMax);
1283 :
1284 0 : m_bRoundCorners = FALSE;
1285 0 : m_dRoundXRadius = 0.0;
1286 0 : m_dRoundYRadius = 0.0;
1287 :
1288 0 : if (EQUALN(papszToken[0],"ROUNDRECT",9))
1289 : {
1290 0 : m_bRoundCorners = TRUE;
1291 0 : if (CSLCount(papszToken) == 6)
1292 0 : m_dRoundXRadius = m_dRoundYRadius = atof(papszToken[5])/2.0;
1293 : else
1294 : {
1295 0 : CSLDestroy(papszToken);
1296 : papszToken = CSLTokenizeString2(fp->GetLine(),
1297 0 : " \t", CSLT_HONOURSTRINGS);
1298 0 : if (CSLCount(papszToken) !=1 )
1299 0 : m_dRoundXRadius = m_dRoundYRadius = atof(papszToken[1])/2.0;
1300 : }
1301 : }
1302 0 : CSLDestroy(papszToken);
1303 0 : papszToken = NULL;
1304 :
1305 : /*-----------------------------------------------------------------
1306 : * Create and fill geometry object
1307 : *----------------------------------------------------------------*/
1308 :
1309 0 : poPolygon = new OGRPolygon;
1310 0 : poRing = new OGRLinearRing();
1311 0 : if (m_bRoundCorners && m_dRoundXRadius != 0.0 && m_dRoundYRadius != 0.0)
1312 : {
1313 : /*-------------------------------------------------------------
1314 : * For rounded rectangles, we generate arcs with 45 line
1315 : * segments for each corner. We start with lower-left corner
1316 : * and proceed counterclockwise
1317 : * We also have to make sure that rounding radius is not too
1318 : * large for the MBR however, we
1319 : * always return the true X/Y radius (not adjusted) since this
1320 : * is the way MapInfo seems to do it when a radius bigger than
1321 : * the MBR is passed from TBA to MIF.
1322 : *------------------------------------------------------------*/
1323 0 : double dXRadius = MIN(m_dRoundXRadius, (dXMax-dXMin)/2.0);
1324 0 : double dYRadius = MIN(m_dRoundYRadius, (dYMax-dYMin)/2.0);
1325 : TABGenerateArc(poRing, 45,
1326 : dXMin + dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
1327 0 : PI, 3.0*PI/2.0);
1328 : TABGenerateArc(poRing, 45,
1329 : dXMax - dXRadius, dYMin + dYRadius, dXRadius, dYRadius,
1330 0 : 3.0*PI/2.0, 2.0*PI);
1331 : TABGenerateArc(poRing, 45,
1332 : dXMax - dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
1333 0 : 0.0, PI/2.0);
1334 : TABGenerateArc(poRing, 45,
1335 : dXMin + dXRadius, dYMax - dYRadius, dXRadius, dYRadius,
1336 0 : PI/2.0, PI);
1337 :
1338 0 : TABCloseRing(poRing);
1339 : }
1340 : else
1341 : {
1342 0 : poRing->addPoint(dXMin, dYMin);
1343 0 : poRing->addPoint(dXMax, dYMin);
1344 0 : poRing->addPoint(dXMax, dYMax);
1345 0 : poRing->addPoint(dXMin, dYMax);
1346 0 : poRing->addPoint(dXMin, dYMin);
1347 : }
1348 :
1349 0 : poPolygon->addRingDirectly(poRing);
1350 0 : SetGeometryDirectly(poPolygon);
1351 :
1352 :
1353 0 : while (((pszLine = fp->GetLine()) != NULL) &&
1354 : fp->IsValidFeature(pszLine) == FALSE)
1355 : {
1356 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
1357 0 : TRUE,FALSE);
1358 :
1359 0 : if (CSLCount(papszToken) > 1)
1360 : {
1361 0 : if (EQUALN(papszToken[0],"PEN",3))
1362 : {
1363 0 : if (CSLCount(papszToken) == 4)
1364 : {
1365 0 : SetPenWidthMIF(atoi(papszToken[1]));
1366 0 : SetPenPattern((GByte)atoi(papszToken[2]));
1367 0 : SetPenColor((GInt32)atoi(papszToken[3]));
1368 : }
1369 :
1370 : }
1371 0 : else if (EQUALN(papszToken[0],"BRUSH", 5))
1372 : {
1373 0 : if (CSLCount(papszToken) >=3)
1374 : {
1375 0 : SetBrushFGColor((GInt32)atoi(papszToken[2]));
1376 0 : SetBrushPattern((GByte)atoi(papszToken[1]));
1377 :
1378 0 : if (CSLCount(papszToken) == 4)
1379 0 : SetBrushBGColor(atoi(papszToken[3]));
1380 : else
1381 0 : SetBrushTransparent(TRUE);
1382 : }
1383 :
1384 : }
1385 : }
1386 0 : CSLDestroy(papszToken);
1387 0 : papszToken = NULL;
1388 : }
1389 :
1390 0 : return 0;
1391 :
1392 : }
1393 :
1394 :
1395 : /**********************************************************************
1396 : *
1397 : **********************************************************************/
1398 0 : int TABRectangle::WriteGeometryToMIFFile(MIDDATAFile *fp)
1399 : {
1400 : OGRGeometry *poGeom;
1401 : OGRPolygon *poPolygon;
1402 0 : OGREnvelope sEnvelope;
1403 :
1404 : /*-----------------------------------------------------------------
1405 : * Fetch and validate geometry
1406 : *----------------------------------------------------------------*/
1407 0 : poGeom = GetGeometryRef();
1408 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
1409 0 : poPolygon = (OGRPolygon*)poGeom;
1410 : else
1411 : {
1412 : CPLError(CE_Failure, CPLE_AssertionFailed,
1413 0 : "TABRectangle: Missing or Invalid Geometry!");
1414 0 : return -1;
1415 : }
1416 : /*-----------------------------------------------------------------
1417 : * Note that we will simply use the rectangle's MBR and don't really
1418 : * read the polygon geometry... this should be OK unless the
1419 : * polygon geometry was not really a rectangle.
1420 : *----------------------------------------------------------------*/
1421 0 : poPolygon->getEnvelope(&sEnvelope);
1422 :
1423 0 : if (m_bRoundCorners == TRUE)
1424 : {
1425 : fp->WriteLine("Roundrect %.15g %.15g %.15g %.15g %.15g\n",
1426 : sEnvelope.MinX, sEnvelope.MinY,
1427 0 : sEnvelope.MaxX, sEnvelope.MaxY, m_dRoundXRadius*2.0);
1428 : }
1429 : else
1430 : {
1431 : fp->WriteLine("Rect %.15g %.15g %.15g %.15g\n",
1432 : sEnvelope.MinX, sEnvelope.MinY,
1433 0 : sEnvelope.MaxX, sEnvelope.MaxY);
1434 : }
1435 :
1436 0 : if (GetPenPattern())
1437 : fp->WriteLine(" Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
1438 0 : GetPenColor());
1439 :
1440 0 : if (GetBrushPattern())
1441 : {
1442 0 : if (GetBrushTransparent() == 0)
1443 : fp->WriteLine(" Brush (%d,%d,%d)\n",GetBrushPattern(),
1444 0 : GetBrushFGColor(),GetBrushBGColor());
1445 : else
1446 : fp->WriteLine(" Brush (%d,%d)\n",GetBrushPattern(),
1447 0 : GetBrushFGColor());
1448 : }
1449 0 : return 0;
1450 : }
1451 :
1452 : /**********************************************************************
1453 : *
1454 : **********************************************************************/
1455 0 : int TABEllipse::ReadGeometryFromMIFFile(MIDDATAFile *fp)
1456 : {
1457 : const char *pszLine;
1458 : char **papszToken;
1459 : double dXMin, dYMin, dXMax, dYMax;
1460 : OGRPolygon *poPolygon;
1461 : OGRLinearRing *poRing;
1462 :
1463 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
1464 0 : " \t", CSLT_HONOURSTRINGS);
1465 :
1466 0 : if (CSLCount(papszToken) != 5)
1467 : {
1468 0 : CSLDestroy(papszToken);
1469 0 : return -1;
1470 : }
1471 :
1472 0 : dXMin = fp->GetXTrans(atof(papszToken[1]));
1473 0 : dXMax = fp->GetXTrans(atof(papszToken[3]));
1474 0 : dYMin = fp->GetYTrans(atof(papszToken[2]));
1475 0 : dYMax = fp->GetYTrans(atof(papszToken[4]));
1476 :
1477 0 : CSLDestroy(papszToken);
1478 0 : papszToken = NULL;
1479 :
1480 : /*-----------------------------------------------------------------
1481 : * Save info about the ellipse def. inside class members
1482 : *----------------------------------------------------------------*/
1483 0 : m_dCenterX = (dXMin + dXMax) / 2.0;
1484 0 : m_dCenterY = (dYMin + dYMax) / 2.0;
1485 0 : m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
1486 0 : m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
1487 :
1488 0 : SetMBR(dXMin, dYMin, dXMax, dYMax);
1489 :
1490 : /*-----------------------------------------------------------------
1491 : * Create and fill geometry object
1492 : *----------------------------------------------------------------*/
1493 0 : poPolygon = new OGRPolygon;
1494 0 : poRing = new OGRLinearRing();
1495 :
1496 : /*-----------------------------------------------------------------
1497 : * For the OGR geometry, we generate an ellipse with 2 degrees line
1498 : * segments.
1499 : *----------------------------------------------------------------*/
1500 : TABGenerateArc(poRing, 180,
1501 : m_dCenterX, m_dCenterY,
1502 : m_dXRadius, m_dYRadius,
1503 0 : 0.0, 2.0*PI);
1504 0 : TABCloseRing(poRing);
1505 :
1506 0 : poPolygon->addRingDirectly(poRing);
1507 0 : SetGeometryDirectly(poPolygon);
1508 :
1509 0 : while (((pszLine = fp->GetLine()) != NULL) &&
1510 : fp->IsValidFeature(pszLine) == FALSE)
1511 : {
1512 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
1513 0 : TRUE,FALSE);
1514 :
1515 0 : if (CSLCount(papszToken) > 1)
1516 : {
1517 0 : if (EQUALN(papszToken[0],"PEN",3))
1518 : {
1519 0 : if (CSLCount(papszToken) == 4)
1520 : {
1521 0 : SetPenWidthMIF(atoi(papszToken[1]));
1522 0 : SetPenPattern((GByte)atoi(papszToken[2]));
1523 0 : SetPenColor((GInt32)atoi(papszToken[3]));
1524 : }
1525 :
1526 : }
1527 0 : else if (EQUALN(papszToken[0],"BRUSH", 5))
1528 : {
1529 0 : if (CSLCount(papszToken) >= 3)
1530 : {
1531 0 : SetBrushFGColor((GInt32)atoi(papszToken[2]));
1532 0 : SetBrushPattern((GByte)atoi(papszToken[1]));
1533 :
1534 0 : if (CSLCount(papszToken) == 4)
1535 0 : SetBrushBGColor(atoi(papszToken[3]));
1536 : else
1537 0 : SetBrushTransparent(TRUE);
1538 :
1539 : }
1540 :
1541 : }
1542 : }
1543 0 : CSLDestroy(papszToken);
1544 0 : papszToken = NULL;
1545 : }
1546 0 : return 0;
1547 : }
1548 :
1549 : /**********************************************************************
1550 : *
1551 : **********************************************************************/
1552 0 : int TABEllipse::WriteGeometryToMIFFile(MIDDATAFile *fp)
1553 : {
1554 : OGRGeometry *poGeom;
1555 0 : OGREnvelope sEnvelope;
1556 :
1557 0 : poGeom = GetGeometryRef();
1558 0 : if ( (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon ) ||
1559 0 : (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint ) )
1560 0 : poGeom->getEnvelope(&sEnvelope);
1561 : else
1562 : {
1563 : CPLError(CE_Failure, CPLE_AssertionFailed,
1564 0 : "TABEllipse: Missing or Invalid Geometry!");
1565 0 : return -1;
1566 : }
1567 :
1568 : fp->WriteLine("Ellipse %.15g %.15g %.15g %.15g\n",sEnvelope.MinX, sEnvelope.MinY,
1569 0 : sEnvelope.MaxX,sEnvelope.MaxY);
1570 :
1571 0 : if (GetPenPattern())
1572 : fp->WriteLine(" Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
1573 0 : GetPenColor());
1574 :
1575 0 : if (GetBrushPattern())
1576 : {
1577 0 : if (GetBrushTransparent() == 0)
1578 : fp->WriteLine(" Brush (%d,%d,%d)\n",GetBrushPattern(),
1579 0 : GetBrushFGColor(),GetBrushBGColor());
1580 : else
1581 : fp->WriteLine(" Brush (%d,%d)\n",GetBrushPattern(),
1582 0 : GetBrushFGColor());
1583 : }
1584 0 : return 0;
1585 : }
1586 :
1587 : /**********************************************************************
1588 : *
1589 : **********************************************************************/
1590 0 : int TABArc::ReadGeometryFromMIFFile(MIDDATAFile *fp)
1591 : {
1592 : const char *pszLine;
1593 : OGRLineString *poLine;
1594 : char **papszToken;
1595 : double dXMin,dXMax, dYMin,dYMax;
1596 : int numPts;
1597 :
1598 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
1599 0 : " \t", CSLT_HONOURSTRINGS);
1600 :
1601 0 : if (CSLCount(papszToken) == 5)
1602 : {
1603 0 : dXMin = fp->GetXTrans(atof(papszToken[1]));
1604 0 : dXMax = fp->GetXTrans(atof(papszToken[3]));
1605 0 : dYMin = fp->GetYTrans(atof(papszToken[2]));
1606 0 : dYMax = fp->GetYTrans(atof(papszToken[4]));
1607 :
1608 0 : CSLDestroy(papszToken);
1609 : papszToken = CSLTokenizeString2(fp->GetLine(),
1610 0 : " \t", CSLT_HONOURSTRINGS);
1611 0 : if (CSLCount(papszToken) != 2)
1612 : {
1613 0 : CSLDestroy(papszToken);
1614 0 : return -1;
1615 : }
1616 :
1617 0 : m_dStartAngle = atof(papszToken[0]);
1618 0 : m_dEndAngle = atof(papszToken[1]);
1619 : }
1620 0 : else if (CSLCount(papszToken) == 7)
1621 : {
1622 0 : dXMin = fp->GetXTrans(atof(papszToken[1]));
1623 0 : dXMax = fp->GetXTrans(atof(papszToken[3]));
1624 0 : dYMin = fp->GetYTrans(atof(papszToken[2]));
1625 0 : dYMax = fp->GetYTrans(atof(papszToken[4]));
1626 0 : m_dStartAngle = atof(papszToken[5]);
1627 0 : m_dEndAngle = atof(papszToken[6]);
1628 : }
1629 : else
1630 : {
1631 0 : CSLDestroy(papszToken);
1632 0 : return -1;
1633 : }
1634 :
1635 0 : CSLDestroy(papszToken);
1636 0 : papszToken = NULL;
1637 :
1638 : /*-------------------------------------------------------------
1639 : * Start/End angles
1640 : * Since the angles are specified for integer coordinates, and
1641 : * that these coordinates can have the X axis reversed, we have to
1642 : * adjust the angle values for the change in the X axis
1643 : * direction.
1644 : *
1645 : * This should be necessary only when X axis is flipped.
1646 : * __TODO__ Why is order of start/end values reversed as well???
1647 : *------------------------------------------------------------*/
1648 :
1649 0 : if (fp->GetXMultiplier() <= 0.0)
1650 : {
1651 0 : m_dStartAngle = 360.0 - m_dStartAngle;
1652 0 : m_dEndAngle = 360.0 - m_dEndAngle;
1653 : }
1654 :
1655 0 : m_dCenterX = (dXMin + dXMax) / 2.0;
1656 0 : m_dCenterY = (dYMin + dYMax) / 2.0;
1657 0 : m_dXRadius = ABS( (dXMax - dXMin) / 2.0 );
1658 0 : m_dYRadius = ABS( (dYMax - dYMin) / 2.0 );
1659 :
1660 : /*-----------------------------------------------------------------
1661 : * Create and fill geometry object
1662 : * For the OGR geometry, we generate an arc with 2 degrees line
1663 : * segments.
1664 : *----------------------------------------------------------------*/
1665 0 : poLine = new OGRLineString;
1666 :
1667 0 : if (m_dEndAngle < m_dStartAngle)
1668 0 : numPts = (int) ABS( ((m_dEndAngle+360.0)-m_dStartAngle)/2.0 ) + 1;
1669 : else
1670 0 : numPts = (int) ABS( (m_dEndAngle-m_dStartAngle)/2.0 ) + 1;
1671 0 : numPts = MAX(2, numPts);
1672 :
1673 : TABGenerateArc(poLine, numPts,
1674 : m_dCenterX, m_dCenterY,
1675 : m_dXRadius, m_dYRadius,
1676 0 : m_dStartAngle*PI/180.0, m_dEndAngle*PI/180.0);
1677 :
1678 0 : SetMBR(dXMin, dYMin, dXMax, dYMax);
1679 0 : SetGeometryDirectly(poLine);
1680 :
1681 0 : while (((pszLine = fp->GetLine()) != NULL) &&
1682 : fp->IsValidFeature(pszLine) == FALSE)
1683 : {
1684 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
1685 0 : TRUE,FALSE);
1686 :
1687 0 : if (CSLCount(papszToken) > 1)
1688 : {
1689 0 : if (EQUALN(papszToken[0],"PEN",3))
1690 : {
1691 :
1692 0 : if (CSLCount(papszToken) == 4)
1693 : {
1694 0 : SetPenWidthMIF(atoi(papszToken[1]));
1695 0 : SetPenPattern((GByte)atoi(papszToken[2]));
1696 0 : SetPenColor((GInt32)atoi(papszToken[3]));
1697 : }
1698 :
1699 : }
1700 : }
1701 0 : CSLDestroy(papszToken);
1702 0 : papszToken = NULL;
1703 : }
1704 0 : return 0;
1705 : }
1706 :
1707 : /**********************************************************************
1708 : *
1709 : **********************************************************************/
1710 0 : int TABArc::WriteGeometryToMIFFile(MIDDATAFile *fp)
1711 : {
1712 : /*-------------------------------------------------------------
1713 : * Start/End angles
1714 : * Since we ALWAYS produce files in quadrant 1 then we can
1715 : * ignore the special angle conversion required by flipped axis.
1716 : *------------------------------------------------------------*/
1717 :
1718 :
1719 : // Write the Arc's actual MBR
1720 : fp->WriteLine("Arc %.15g %.15g %.15g %.15g\n", m_dCenterX-m_dXRadius,
1721 : m_dCenterY-m_dYRadius, m_dCenterX+m_dXRadius,
1722 0 : m_dCenterY+m_dYRadius);
1723 :
1724 0 : fp->WriteLine(" %.15g %.15g\n",m_dStartAngle,m_dEndAngle);
1725 :
1726 0 : if (GetPenPattern())
1727 : fp->WriteLine(" Pen (%d,%d,%d)\n",GetPenWidthMIF(),GetPenPattern(),
1728 0 : GetPenColor());
1729 :
1730 :
1731 0 : return 0;
1732 :
1733 : }
1734 :
1735 : /**********************************************************************
1736 : *
1737 : **********************************************************************/
1738 0 : int TABText::ReadGeometryFromMIFFile(MIDDATAFile *fp)
1739 : {
1740 : double dXMin, dYMin, dXMax, dYMax;
1741 : OGRGeometry *poGeometry;
1742 : const char *pszLine;
1743 : char **papszToken;
1744 : const char *pszString;
1745 : char *pszTmpString;
1746 0 : int bXYBoxRead = 0;
1747 : int tokenLen;
1748 :
1749 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
1750 0 : " \t", CSLT_HONOURSTRINGS);
1751 0 : if (CSLCount(papszToken) == 1)
1752 : {
1753 0 : CSLDestroy(papszToken);
1754 : papszToken = CSLTokenizeString2(fp->GetLine(),
1755 0 : " \t", CSLT_HONOURSTRINGS);
1756 0 : tokenLen = CSLCount(papszToken);
1757 0 : if (tokenLen == 4)
1758 : {
1759 0 : pszString = NULL;
1760 0 : bXYBoxRead = 1;
1761 : }
1762 0 : else if (tokenLen == 0)
1763 : {
1764 0 : pszString = NULL;
1765 : }
1766 0 : else if (tokenLen != 1)
1767 : {
1768 0 : CSLDestroy(papszToken);
1769 0 : return -1;
1770 : }
1771 : else
1772 : {
1773 0 : pszString = papszToken[0];
1774 : }
1775 : }
1776 0 : else if (CSLCount(papszToken) == 2)
1777 : {
1778 0 : pszString = papszToken[1];
1779 : }
1780 : else
1781 : {
1782 0 : CSLDestroy(papszToken);
1783 0 : return -1;
1784 : }
1785 :
1786 : /*-------------------------------------------------------------
1787 : * Note: The text string may contain escaped "\n" chars, and we
1788 : * sstore them in memory in the UnEscaped form to be OGR
1789 : * compliant. See Maptools bug 1107 for more details.
1790 : *------------------------------------------------------------*/
1791 0 : pszTmpString = CPLStrdup(pszString);
1792 0 : m_pszString = TABUnEscapeString(pszTmpString, TRUE);
1793 0 : if (pszTmpString != m_pszString)
1794 0 : CPLFree(pszTmpString);
1795 :
1796 0 : if (!bXYBoxRead)
1797 : {
1798 0 : CSLDestroy(papszToken);
1799 : papszToken = CSLTokenizeString2(fp->GetLine(),
1800 0 : " \t", CSLT_HONOURSTRINGS);
1801 : }
1802 :
1803 0 : if (CSLCount(papszToken) != 4)
1804 : {
1805 0 : CSLDestroy(papszToken);
1806 0 : return -1;
1807 : }
1808 : else
1809 : {
1810 0 : dXMin = fp->GetXTrans(atof(papszToken[0]));
1811 0 : dXMax = fp->GetXTrans(atof(papszToken[2]));
1812 0 : dYMin = fp->GetYTrans(atof(papszToken[1]));
1813 0 : dYMax = fp->GetYTrans(atof(papszToken[3]));
1814 :
1815 0 : m_dHeight = dYMax - dYMin; //SetTextBoxHeight(dYMax - dYMin);
1816 0 : m_dWidth = dXMax - dXMin; //SetTextBoxWidth(dXMax - dXMin);
1817 :
1818 0 : if (m_dHeight <0.0)
1819 0 : m_dHeight*=-1.0;
1820 0 : if (m_dWidth <0.0)
1821 0 : m_dWidth*=-1.0;
1822 : }
1823 :
1824 0 : CSLDestroy(papszToken);
1825 0 : papszToken = NULL;
1826 :
1827 : /* Set/retrieve the MBR to make sure Mins are smaller than Maxs
1828 : */
1829 :
1830 0 : SetMBR(dXMin, dYMin, dXMax, dYMax);
1831 0 : GetMBR(dXMin, dYMin, dXMax, dYMax);
1832 :
1833 0 : while (((pszLine = fp->GetLine()) != NULL) &&
1834 : fp->IsValidFeature(pszLine) == FALSE)
1835 : {
1836 : papszToken = CSLTokenizeStringComplex(pszLine,"() ,",
1837 0 : TRUE,FALSE);
1838 :
1839 0 : if (CSLCount(papszToken) > 1)
1840 : {
1841 0 : if (EQUALN(papszToken[0],"FONT",4))
1842 : {
1843 0 : if (CSLCount(papszToken) >= 5)
1844 : {
1845 0 : SetFontName(papszToken[1]);
1846 0 : SetFontFGColor(atoi(papszToken[4]));
1847 0 : if (CSLCount(papszToken) ==6)
1848 : {
1849 0 : SetFontBGColor(atoi(papszToken[5]));
1850 0 : SetFontStyleMIFValue(atoi(papszToken[2]),TRUE);
1851 : }
1852 : else
1853 0 : SetFontStyleMIFValue(atoi(papszToken[2]));
1854 :
1855 : // papsztoken[3] = Size ???
1856 : }
1857 :
1858 : }
1859 0 : else if (EQUALN(papszToken[0],"SPACING",7))
1860 : {
1861 0 : if (CSLCount(papszToken) >= 2)
1862 : {
1863 0 : if (EQUALN(papszToken[1],"2",1))
1864 : {
1865 0 : SetTextSpacing(TABTSDouble);
1866 : }
1867 0 : else if (EQUALN(papszToken[1],"1.5",3))
1868 : {
1869 0 : SetTextSpacing(TABTS1_5);
1870 : }
1871 : }
1872 :
1873 0 : if (CSLCount(papszToken) == 7)
1874 : {
1875 0 : if (EQUALN(papszToken[2],"LAbel",5))
1876 : {
1877 0 : if (EQUALN(papszToken[4],"simple",6))
1878 : {
1879 0 : SetTextLineType(TABTLSimple);
1880 0 : SetTextLineEndPoint(fp->GetXTrans(atof(papszToken[5])),
1881 0 : fp->GetYTrans(atof(papszToken[6])));
1882 : }
1883 0 : else if (EQUALN(papszToken[4],"arrow", 5))
1884 : {
1885 0 : SetTextLineType(TABTLArrow);
1886 0 : SetTextLineEndPoint(fp->GetXTrans(atof(papszToken[5])),
1887 0 : fp->GetYTrans(atof(papszToken[6])));
1888 : }
1889 : }
1890 : }
1891 : }
1892 0 : else if (EQUALN(papszToken[0],"Justify",7))
1893 : {
1894 0 : if (CSLCount(papszToken) == 2)
1895 : {
1896 0 : if (EQUALN( papszToken[1],"Center",6))
1897 : {
1898 0 : SetTextJustification(TABTJCenter);
1899 : }
1900 0 : else if (EQUALN( papszToken[1],"Right",5))
1901 : {
1902 0 : SetTextJustification(TABTJRight);
1903 : }
1904 :
1905 : }
1906 :
1907 : }
1908 0 : else if (EQUALN(papszToken[0],"Angle",5))
1909 : {
1910 0 : if (CSLCount(papszToken) == 2)
1911 : {
1912 0 : SetTextAngle(atof(papszToken[1]));
1913 : }
1914 :
1915 : }
1916 0 : else if (EQUALN(papszToken[0],"LAbel",5))
1917 : {
1918 0 : if (CSLCount(papszToken) == 5)
1919 : {
1920 0 : if (EQUALN(papszToken[2],"simple",6))
1921 : {
1922 0 : SetTextLineType(TABTLSimple);
1923 0 : SetTextLineEndPoint(fp->GetXTrans(atof(papszToken[3])),
1924 0 : fp->GetYTrans(atof(papszToken[4])));
1925 : }
1926 0 : else if (EQUALN(papszToken[2],"arrow", 5))
1927 : {
1928 0 : SetTextLineType(TABTLArrow);
1929 0 : SetTextLineEndPoint(fp->GetXTrans(atof(papszToken[3])),
1930 0 : fp->GetYTrans(atof(papszToken[4])));
1931 : }
1932 : }
1933 :
1934 :
1935 : // What I do with the XY coordonate
1936 : }
1937 : }
1938 0 : CSLDestroy(papszToken);
1939 0 : papszToken = NULL;
1940 : }
1941 : /*-----------------------------------------------------------------
1942 : * Create an OGRPoint Geometry...
1943 : * The point X,Y values will be the coords of the lower-left corner before
1944 : * rotation is applied. (Note that the rotation in MapInfo is done around
1945 : * the upper-left corner)
1946 : * We need to calculate the true lower left corner of the text based
1947 : * on the MBR after rotation, the text height and the rotation angle.
1948 : *---------------------------------------------------------------- */
1949 : double dCos, dSin, dX, dY;
1950 0 : dSin = sin(m_dAngle*PI/180.0);
1951 0 : dCos = cos(m_dAngle*PI/180.0);
1952 0 : if (dSin > 0.0 && dCos > 0.0)
1953 : {
1954 0 : dX = dXMin + m_dHeight * dSin;
1955 0 : dY = dYMin;
1956 : }
1957 0 : else if (dSin > 0.0 && dCos < 0.0)
1958 : {
1959 0 : dX = dXMax;
1960 0 : dY = dYMin - m_dHeight * dCos;
1961 : }
1962 0 : else if (dSin < 0.0 && dCos < 0.0)
1963 : {
1964 0 : dX = dXMax + m_dHeight * dSin;
1965 0 : dY = dYMax;
1966 : }
1967 : else // dSin < 0 && dCos > 0
1968 : {
1969 0 : dX = dXMin;
1970 0 : dY = dYMax - m_dHeight * dCos;
1971 : }
1972 :
1973 :
1974 0 : poGeometry = new OGRPoint(dX, dY);
1975 :
1976 0 : SetGeometryDirectly(poGeometry);
1977 :
1978 : /*-----------------------------------------------------------------
1979 : * Compute Text Width: the width of the Text MBR before rotation
1980 : * in ground units... unfortunately this value is not stored in the
1981 : * file, so we have to compute it with the MBR after rotation and
1982 : * the height of the MBR before rotation:
1983 : * With W = Width of MBR before rotation
1984 : * H = Height of MBR before rotation
1985 : * dX = Width of MBR after rotation
1986 : * dY = Height of MBR after rotation
1987 : * teta = rotation angle
1988 : *
1989 : * For [-PI/4..teta..+PI/4] or [3*PI/4..teta..5*PI/4], we'll use:
1990 : * W = H * (dX - H * sin(teta)) / (H * cos(teta))
1991 : *
1992 : * and for other teta values, use:
1993 : * W = H * (dY - H * cos(teta)) / (H * sin(teta))
1994 : *---------------------------------------------------------------- */
1995 0 : dSin = ABS(dSin);
1996 0 : dCos = ABS(dCos);
1997 0 : if (m_dHeight == 0.0)
1998 0 : m_dWidth = 0.0;
1999 0 : else if ( dCos > dSin )
2000 : m_dWidth = m_dHeight * ((dXMax-dXMin) - m_dHeight*dSin) /
2001 0 : (m_dHeight*dCos);
2002 : else
2003 : m_dWidth = m_dHeight * ((dYMax-dYMin) - m_dHeight*dCos) /
2004 0 : (m_dHeight*dSin);
2005 0 : m_dWidth = ABS(m_dWidth);
2006 :
2007 0 : return 0;
2008 : }
2009 :
2010 : /**********************************************************************
2011 : *
2012 : **********************************************************************/
2013 0 : int TABText::WriteGeometryToMIFFile(MIDDATAFile *fp)
2014 : {
2015 : double dXMin,dYMin,dXMax,dYMax;
2016 : char *pszTmpString;
2017 :
2018 : /*-------------------------------------------------------------
2019 : * Note: The text string may contain unescaped "\n" chars or
2020 : * "\\" chars and we expect to receive them in an unescaped
2021 : * form. Those characters are unescaped in memory to be like
2022 : * other OGR drivers. See MapTools bug 1107 for more details.
2023 : *------------------------------------------------------------*/
2024 0 : pszTmpString = TABEscapeString(m_pszString);
2025 0 : if(pszTmpString == NULL)
2026 0 : fp->WriteLine("Text \"\"\n" );
2027 : else
2028 0 : fp->WriteLine("Text \"%s\"\n", pszTmpString );
2029 0 : if (pszTmpString != m_pszString)
2030 0 : CPLFree(pszTmpString);
2031 :
2032 : // UpdateTextMBR();
2033 0 : GetMBR(dXMin, dYMin, dXMax, dYMax);
2034 0 : fp->WriteLine(" %.15g %.15g %.15g %.15g\n",dXMin, dYMin,dXMax, dYMax);
2035 :
2036 0 : if (IsFontBGColorUsed())
2037 : fp->WriteLine(" Font (\"%s\",%d,%d,%d,%d)\n", GetFontNameRef(),
2038 : GetFontStyleMIFValue(),0,GetFontFGColor(),
2039 0 : GetFontBGColor());
2040 : else
2041 : fp->WriteLine(" Font (\"%s\",%d,%d,%d)\n", GetFontNameRef(),
2042 0 : GetFontStyleMIFValue(),0,GetFontFGColor());
2043 :
2044 0 : switch (GetTextSpacing())
2045 : {
2046 : case TABTS1_5:
2047 0 : fp->WriteLine(" Spacing 1.5\n");
2048 0 : break;
2049 : case TABTSDouble:
2050 0 : fp->WriteLine(" Spacing 2.0\n");
2051 : break;
2052 : case TABTSSingle:
2053 : default:
2054 : break;
2055 : }
2056 :
2057 0 : switch (GetTextJustification())
2058 : {
2059 : case TABTJCenter:
2060 0 : fp->WriteLine(" Justify Center\n");
2061 0 : break;
2062 : case TABTJRight:
2063 0 : fp->WriteLine(" Justify Right\n");
2064 : break;
2065 : case TABTJLeft:
2066 : default:
2067 : break;
2068 : }
2069 :
2070 0 : if (ABS(GetTextAngle()) > 0.000001)
2071 0 : fp->WriteLine(" Angle %.15g\n",GetTextAngle());
2072 :
2073 0 : switch (GetTextLineType())
2074 : {
2075 : case TABTLSimple:
2076 0 : if (m_bLineEndSet)
2077 : fp->WriteLine(" Label Line Simple %.15g %.15g \n",
2078 0 : m_dfLineEndX, m_dfLineEndY );
2079 0 : break;
2080 : case TABTLArrow:
2081 0 : if (m_bLineEndSet)
2082 : fp->WriteLine(" Label Line Arrow %.15g %.15g \n",
2083 0 : m_dfLineEndX, m_dfLineEndY );
2084 : break;
2085 : case TABTLNoLine:
2086 : default:
2087 : break;
2088 : }
2089 0 : return 0;
2090 :
2091 : }
2092 :
2093 : /**********************************************************************
2094 : *
2095 : **********************************************************************/
2096 0 : int TABMultiPoint::ReadGeometryFromMIFFile(MIDDATAFile *fp)
2097 : {
2098 : OGRPoint *poPoint;
2099 : OGRMultiPoint *poMultiPoint;
2100 : char **papszToken;
2101 : const char *pszLine;
2102 : int nNumPoint, i;
2103 : double dfX,dfY;
2104 0 : OGREnvelope sEnvelope;
2105 :
2106 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
2107 0 : " \t", CSLT_HONOURSTRINGS);
2108 :
2109 0 : if (CSLCount(papszToken) !=2)
2110 : {
2111 0 : CSLDestroy(papszToken);
2112 0 : return -1;
2113 : }
2114 :
2115 0 : nNumPoint = atoi(papszToken[1]);
2116 0 : poMultiPoint = new OGRMultiPoint;
2117 :
2118 0 : CSLDestroy(papszToken);
2119 0 : papszToken = NULL;
2120 :
2121 : // Get each point and add them to the multipoint feature
2122 0 : for(i=0; i<nNumPoint; i++)
2123 : {
2124 0 : pszLine = fp->GetLine();
2125 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
2126 0 : " \t", CSLT_HONOURSTRINGS);
2127 0 : if (CSLCount(papszToken) !=2)
2128 : {
2129 0 : CSLDestroy(papszToken);
2130 0 : return -1;
2131 : }
2132 :
2133 0 : dfX = fp->GetXTrans(atof(papszToken[0]));
2134 0 : dfY = fp->GetXTrans(atof(papszToken[1]));
2135 0 : poPoint = new OGRPoint(dfX, dfY);
2136 0 : if ( poMultiPoint->addGeometryDirectly( poPoint ) != OGRERR_NONE)
2137 : {
2138 0 : CPLAssert(FALSE); // Just in case OGR is modified
2139 : }
2140 :
2141 : // Set center
2142 0 : if(i == 0)
2143 : {
2144 0 : SetCenter( dfX, dfY );
2145 : }
2146 0 : CSLDestroy(papszToken);
2147 : }
2148 :
2149 0 : if( SetGeometryDirectly( poMultiPoint ) != OGRERR_NONE)
2150 : {
2151 0 : CPLAssert(FALSE); // Just in case OGR is modified
2152 : }
2153 :
2154 0 : poMultiPoint->getEnvelope(&sEnvelope);
2155 : SetMBR(sEnvelope.MinX, sEnvelope.MinY,
2156 0 : sEnvelope.MaxX,sEnvelope.MaxY);
2157 :
2158 : // Read optional SYMBOL line...
2159 :
2160 0 : while (((pszLine = fp->GetLine()) != NULL) &&
2161 : fp->IsValidFeature(pszLine) == FALSE)
2162 : {
2163 : papszToken = CSLTokenizeStringComplex(pszLine," ,()\t",
2164 0 : TRUE,FALSE);
2165 0 : if (CSLCount(papszToken) == 4 && EQUAL(papszToken[0], "SYMBOL") )
2166 : {
2167 0 : SetSymbolNo((GInt16)atoi(papszToken[1]));
2168 0 : SetSymbolColor((GInt32)atoi(papszToken[2]));
2169 0 : SetSymbolSize((GInt16)atoi(papszToken[3]));
2170 : }
2171 0 : CSLDestroy(papszToken);
2172 : }
2173 :
2174 0 : return 0;
2175 : }
2176 :
2177 : /**********************************************************************
2178 : *
2179 : **********************************************************************/
2180 0 : int TABMultiPoint::WriteGeometryToMIFFile(MIDDATAFile *fp)
2181 : {
2182 : OGRGeometry *poGeom;
2183 : OGRPoint *poPoint;
2184 : OGRMultiPoint *poMultiPoint;
2185 : int nNumPoints, iPoint;
2186 :
2187 : /*-----------------------------------------------------------------
2188 : * Fetch and validate geometry
2189 : *----------------------------------------------------------------*/
2190 0 : poGeom = GetGeometryRef();
2191 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPoint)
2192 : {
2193 0 : poMultiPoint = (OGRMultiPoint*)poGeom;
2194 0 : nNumPoints = poMultiPoint->getNumGeometries();
2195 :
2196 0 : fp->WriteLine("MultiPoint %d\n", nNumPoints);
2197 :
2198 0 : for(iPoint=0; iPoint < nNumPoints; iPoint++)
2199 : {
2200 : /*------------------------------------------------------------
2201 : * Validate each point
2202 : *-----------------------------------------------------------*/
2203 0 : poGeom = poMultiPoint->getGeometryRef(iPoint);
2204 0 : if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
2205 : {
2206 0 : poPoint = (OGRPoint*)poGeom;
2207 0 : fp->WriteLine("%.15g %.15g\n",poPoint->getX(),poPoint->getY());
2208 : }
2209 : else
2210 : {
2211 : CPLError(CE_Failure, CPLE_AssertionFailed,
2212 0 : "TABMultiPoint: Missing or Invalid Geometry!");
2213 0 : return -1;
2214 : }
2215 : }
2216 : // Write symbol
2217 : fp->WriteLine(" Symbol (%d,%d,%d)\n",GetSymbolNo(),GetSymbolColor(),
2218 0 : GetSymbolSize());
2219 : }
2220 :
2221 0 : return 0;
2222 : }
2223 :
2224 :
2225 : /**********************************************************************
2226 : *
2227 : **********************************************************************/
2228 0 : int TABCollection::ReadGeometryFromMIFFile(MIDDATAFile *fp)
2229 : {
2230 : char **papszToken;
2231 : const char *pszLine;
2232 : int numParts, i;
2233 0 : OGREnvelope sEnvelope;
2234 :
2235 : /*-----------------------------------------------------------------
2236 : * Fetch number of parts in "COLLECTION %d" line
2237 : *----------------------------------------------------------------*/
2238 : papszToken = CSLTokenizeString2(fp->GetLastLine(),
2239 0 : " \t", CSLT_HONOURSTRINGS);
2240 :
2241 0 : if (CSLCount(papszToken) !=2)
2242 : {
2243 0 : CSLDestroy(papszToken);
2244 0 : return -1;
2245 : }
2246 :
2247 0 : numParts = atoi(papszToken[1]);
2248 0 : CSLDestroy(papszToken);
2249 0 : papszToken = NULL;
2250 :
2251 : // Make sure collection is empty
2252 0 : EmptyCollection();
2253 :
2254 0 : pszLine = fp->GetLine();
2255 :
2256 : /*-----------------------------------------------------------------
2257 : * Read each part and add them to the feature
2258 : *----------------------------------------------------------------*/
2259 0 : for (i=0; i < numParts; i++)
2260 : {
2261 0 : if (pszLine == NULL)
2262 : {
2263 : CPLError(CE_Failure, CPLE_FileIO,
2264 0 : "Unexpected EOF while reading TABCollection from MIF file.");
2265 0 : return -1;
2266 : }
2267 :
2268 0 : while(*pszLine == ' ' || *pszLine == '\t')
2269 0 : pszLine++; // skip leading spaces
2270 :
2271 0 : if (*pszLine == '\0')
2272 0 : continue; // Skip blank lines
2273 :
2274 0 : if (EQUALN(pszLine,"REGION",6))
2275 : {
2276 0 : m_poRegion = new TABRegion(GetDefnRef());
2277 0 : if (m_poRegion->ReadGeometryFromMIFFile(fp) != 0)
2278 : {
2279 : CPLError(CE_Failure, CPLE_NotSupported,
2280 0 : "TABCollection: Error reading REGION part.");
2281 0 : delete m_poRegion;
2282 0 : m_poRegion = NULL;
2283 0 : return -1;
2284 : }
2285 : }
2286 0 : else if (EQUALN(pszLine,"LINE",4) ||
2287 : EQUALN(pszLine,"PLINE",5))
2288 : {
2289 0 : m_poPline = new TABPolyline(GetDefnRef());
2290 0 : if (m_poPline->ReadGeometryFromMIFFile(fp) != 0)
2291 : {
2292 : CPLError(CE_Failure, CPLE_NotSupported,
2293 0 : "TABCollection: Error reading PLINE part.");
2294 0 : delete m_poPline;
2295 0 : m_poPline = NULL;
2296 0 : return -1;
2297 : }
2298 : }
2299 0 : else if (EQUALN(pszLine,"MULTIPOINT",10))
2300 : {
2301 0 : m_poMpoint = new TABMultiPoint(GetDefnRef());
2302 0 : if (m_poMpoint->ReadGeometryFromMIFFile(fp) != 0)
2303 : {
2304 : CPLError(CE_Failure, CPLE_NotSupported,
2305 0 : "TABCollection: Error reading MULTIPOINT part.");
2306 0 : delete m_poMpoint;
2307 0 : m_poMpoint = NULL;
2308 0 : return -1;
2309 : }
2310 : }
2311 : else
2312 : {
2313 : CPLError(CE_Failure, CPLE_FileIO,
2314 : "Reading TABCollection from MIF failed, expecting one "
2315 : "of REGION, PLINE or MULTIPOINT, got: '%s'",
2316 0 : pszLine);
2317 0 : return -1;
2318 : }
2319 :
2320 0 : pszLine = fp->GetLastLine();
2321 : }
2322 :
2323 : /*-----------------------------------------------------------------
2324 : * Set the main OGRFeature Geometry
2325 : * (this is actually duplicating geometries from each member)
2326 : *----------------------------------------------------------------*/
2327 : // use addGeometry() rather than addGeometryDirectly() as this clones
2328 : // the added geometry so won't leave dangling ptrs when the above features
2329 : // are deleted
2330 :
2331 0 : OGRGeometryCollection *poGeomColl = new OGRGeometryCollection();
2332 0 : if(m_poRegion && m_poRegion->GetGeometryRef() != NULL)
2333 0 : poGeomColl->addGeometry(m_poRegion->GetGeometryRef());
2334 :
2335 0 : if(m_poPline && m_poPline->GetGeometryRef() != NULL)
2336 0 : poGeomColl->addGeometry(m_poPline->GetGeometryRef());
2337 :
2338 0 : if(m_poMpoint && m_poMpoint->GetGeometryRef() != NULL)
2339 0 : poGeomColl->addGeometry(m_poMpoint->GetGeometryRef());
2340 :
2341 0 : this->SetGeometryDirectly(poGeomColl);
2342 :
2343 0 : poGeomColl->getEnvelope(&sEnvelope);
2344 : SetMBR(sEnvelope.MinX, sEnvelope.MinY,
2345 0 : sEnvelope.MaxX, sEnvelope.MaxY);
2346 :
2347 0 : return 0;
2348 : }
2349 :
2350 : /**********************************************************************
2351 : *
2352 : **********************************************************************/
2353 0 : int TABCollection::WriteGeometryToMIFFile(MIDDATAFile *fp)
2354 : {
2355 0 : int numParts = 0;
2356 0 : if (m_poRegion) numParts++;
2357 0 : if (m_poPline) numParts++;
2358 0 : if (m_poMpoint) numParts++;
2359 :
2360 0 : fp->WriteLine("COLLECTION %d\n", numParts);
2361 :
2362 0 : if (m_poRegion)
2363 : {
2364 0 : if (m_poRegion->WriteGeometryToMIFFile(fp) != 0)
2365 0 : return -1;
2366 : }
2367 :
2368 0 : if (m_poPline)
2369 : {
2370 0 : if (m_poPline->WriteGeometryToMIFFile(fp) != 0)
2371 0 : return -1;
2372 : }
2373 :
2374 0 : if (m_poMpoint)
2375 : {
2376 0 : if (m_poMpoint->WriteGeometryToMIFFile(fp) != 0)
2377 0 : return -1;
2378 : }
2379 :
2380 0 : return 0;
2381 : }
2382 :
2383 : /**********************************************************************
2384 : *
2385 : **********************************************************************/
2386 0 : int TABDebugFeature::ReadGeometryFromMIFFile(MIDDATAFile *fp)
2387 : {
2388 : const char *pszLine;
2389 :
2390 :
2391 : /* Go to the first line of the next feature */
2392 0 : printf("%s\n", fp->GetLastLine());
2393 :
2394 0 : while (((pszLine = fp->GetLine()) != NULL) &&
2395 : fp->IsValidFeature(pszLine) == FALSE)
2396 : ;
2397 :
2398 0 : return 0;
2399 : }
2400 :
2401 :
2402 : /**********************************************************************
2403 : *
2404 : **********************************************************************/
2405 0 : int TABDebugFeature::WriteGeometryToMIFFile(MIDDATAFile *fp){ return -1; }
2406 :
2407 :
2408 :
2409 :
|