1 : /******************************************************************************
2 : * $Id: ogrtindex.cpp 17890 2009-10-24 15:51:01Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Program to generate a UMN MapServer compatible tile index for a
6 : * set of OGR data sources.
7 : * Author: Frank Warmerdam, warmerdam@pobox.com
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2002, Frank Warmerdam
11 : *
12 : * Permission is hereby granted, free of charge, to any person obtaining a
13 : * copy of this software and associated documentation files (the "Software"),
14 : * to deal in the Software without restriction, including without limitation
15 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16 : * and/or sell copies of the Software, and to permit persons to whom the
17 : * Software is furnished to do so, subject to the following conditions:
18 : *
19 : * The above copyright notice and this permission notice shall be included
20 : * in all copies or substantial portions of the Software.
21 : *
22 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 : * DEALINGS IN THE SOFTWARE.
29 : ****************************************************************************/
30 :
31 : #include "ogrsf_frmts.h"
32 : #include "cpl_conv.h"
33 : #include "cpl_string.h"
34 :
35 : #include <cassert>
36 :
37 : CPL_CVSID("$Id: ogrtindex.cpp 17890 2009-10-24 15:51:01Z rouault $");
38 :
39 : static void Usage();
40 :
41 : /************************************************************************/
42 : /* main() */
43 : /************************************************************************/
44 :
45 3 : int main( int nArgc, char ** papszArgv )
46 :
47 : {
48 3 : int nFirstSourceDataset = -1, bLayersWildcarded = TRUE, iArg;
49 3 : const char *pszFormat = "ESRI Shapefile";
50 3 : const char *pszTileIndexField = "LOCATION";
51 3 : const char *pszOutputName = NULL;
52 3 : int write_absolute_path = FALSE;
53 3 : int skip_different_projection = FALSE;
54 3 : char* current_path = NULL;
55 3 : int accept_different_schemas = FALSE;
56 3 : int bFirstWarningForNonMatchingAttributes = TRUE;
57 :
58 : /* Check strict compilation and runtime library version as we use C++ API */
59 3 : if (! GDAL_CHECK_VERSION(papszArgv[0]))
60 0 : exit(1);
61 : /* -------------------------------------------------------------------- */
62 : /* Register format(s). */
63 : /* -------------------------------------------------------------------- */
64 3 : OGRRegisterAll();
65 :
66 : /* -------------------------------------------------------------------- */
67 : /* Processing command line arguments. */
68 : /* -------------------------------------------------------------------- */
69 15 : for( iArg = 1; iArg < nArgc; iArg++ )
70 : {
71 13 : if( EQUAL(papszArgv[iArg], "--utility_version") )
72 : {
73 : printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
74 1 : papszArgv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
75 1 : return 0;
76 : }
77 12 : else if( EQUAL(papszArgv[iArg],"-f") && iArg < nArgc-1 )
78 : {
79 0 : pszFormat = papszArgv[++iArg];
80 : }
81 12 : else if( EQUAL(papszArgv[iArg],"-write_absolute_path"))
82 : {
83 0 : write_absolute_path = TRUE;
84 : }
85 12 : else if( EQUAL(papszArgv[iArg],"-skip_different_projection"))
86 : {
87 2 : skip_different_projection = TRUE;
88 : }
89 10 : else if( EQUAL(papszArgv[iArg],"-accept_different_schemas"))
90 : {
91 0 : accept_different_schemas = TRUE;
92 : }
93 10 : else if( EQUAL(papszArgv[iArg],"-tileindex") && iArg < nArgc-1 )
94 : {
95 0 : pszTileIndexField = papszArgv[++iArg];
96 : }
97 20 : else if( EQUAL(papszArgv[iArg],"-lnum")
98 10 : || EQUAL(papszArgv[iArg],"-lname") )
99 : {
100 0 : iArg++;
101 0 : bLayersWildcarded = FALSE;
102 : }
103 10 : else if( papszArgv[iArg][0] == '-' )
104 0 : Usage();
105 10 : else if( pszOutputName == NULL )
106 2 : pszOutputName = papszArgv[iArg];
107 8 : else if( nFirstSourceDataset == -1 )
108 2 : nFirstSourceDataset = iArg;
109 : }
110 :
111 2 : if( pszOutputName == NULL || nFirstSourceDataset == -1 )
112 0 : Usage();
113 :
114 : /* -------------------------------------------------------------------- */
115 : /* Try to open as an existing dataset for update access. */
116 : /* -------------------------------------------------------------------- */
117 : OGRDataSource *poDstDS;
118 2 : OGRLayer *poDstLayer = NULL;
119 :
120 2 : poDstDS = OGRSFDriverRegistrar::Open( pszOutputName, TRUE );
121 :
122 : /* -------------------------------------------------------------------- */
123 : /* If that failed, find the driver so we can create the tile index.*/
124 : /* -------------------------------------------------------------------- */
125 2 : if( poDstDS == NULL )
126 : {
127 2 : OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
128 2 : OGRSFDriver *poDriver = NULL;
129 : int iDriver;
130 :
131 4 : for( iDriver = 0;
132 : iDriver < poR->GetDriverCount() && poDriver == NULL;
133 : iDriver++ )
134 : {
135 2 : if( EQUAL(poR->GetDriver(iDriver)->GetName(),pszFormat) )
136 : {
137 2 : poDriver = poR->GetDriver(iDriver);
138 : }
139 : }
140 :
141 2 : if( poDriver == NULL )
142 : {
143 0 : fprintf( stderr, "Unable to find driver `%s'.\n", pszFormat );
144 0 : fprintf( stderr, "The following drivers are available:\n" );
145 :
146 0 : for( iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++ )
147 : {
148 0 : fprintf( stderr, " -> `%s'\n", poR->GetDriver(iDriver)->GetName() );
149 : }
150 0 : exit( 1 );
151 : }
152 :
153 2 : if( !poDriver->TestCapability( ODrCCreateDataSource ) )
154 : {
155 : fprintf( stderr, "%s driver does not support data source creation.\n",
156 0 : pszFormat );
157 0 : exit( 1 );
158 : }
159 :
160 : /* -------------------------------------------------------------------- */
161 : /* Now create it. */
162 : /* -------------------------------------------------------------------- */
163 :
164 2 : poDstDS = poDriver->CreateDataSource( pszOutputName, NULL );
165 2 : if( poDstDS == NULL )
166 : {
167 : fprintf( stderr, "%s driver failed to create %s\n",
168 0 : pszFormat, pszOutputName );
169 0 : exit( 1 );
170 : }
171 :
172 2 : if( poDstDS->GetLayerCount() == 0 )
173 : {
174 2 : OGRFieldDefn oLocation( pszTileIndexField, OFTString );
175 :
176 2 : oLocation.SetWidth( 200 );
177 :
178 2 : if( nFirstSourceDataset < nArgc && papszArgv[nFirstSourceDataset][0] == '-' )
179 : {
180 0 : nFirstSourceDataset++;
181 : }
182 :
183 2 : OGRSpatialReference* poSrcSpatialRef = NULL;
184 :
185 : /* Fetches the SRS of the first layer and use it when creating the tileindex layer */
186 2 : if (nFirstSourceDataset < nArgc)
187 : {
188 2 : OGRDataSource* poDS = OGRSFDriverRegistrar::Open( papszArgv[nFirstSourceDataset],
189 4 : FALSE );
190 :
191 2 : if (poDS)
192 : {
193 : int iLayer;
194 :
195 4 : for( iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
196 : {
197 2 : int bRequested = bLayersWildcarded;
198 2 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
199 :
200 2 : for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
201 : {
202 0 : if( EQUAL(papszArgv[iArg],"-lnum")
203 0 : && atoi(papszArgv[iArg+1]) == iLayer )
204 0 : bRequested = TRUE;
205 0 : else if( EQUAL(papszArgv[iArg],"-lname")
206 0 : && EQUAL(papszArgv[iArg+1],
207 : poLayer->GetLayerDefn()->GetName()) )
208 0 : bRequested = TRUE;
209 : }
210 :
211 2 : if( !bRequested )
212 0 : continue;
213 :
214 2 : if ( poLayer->GetSpatialRef() )
215 1 : poSrcSpatialRef = poLayer->GetSpatialRef()->Clone();
216 2 : break;
217 : }
218 : }
219 :
220 2 : OGRDataSource::DestroyDataSource( poDS );
221 : }
222 :
223 2 : poDstLayer = poDstDS->CreateLayer( "tileindex", poSrcSpatialRef );
224 2 : poDstLayer->CreateField( &oLocation, OFTString );
225 :
226 2 : OGRSpatialReference::DestroySpatialReference( poSrcSpatialRef );
227 : }
228 : }
229 :
230 : /* -------------------------------------------------------------------- */
231 : /* Identify target layer and field. */
232 : /* -------------------------------------------------------------------- */
233 : int iTileIndexField;
234 :
235 2 : poDstLayer = poDstDS->GetLayer(0);
236 2 : if( poDstLayer == NULL )
237 : {
238 0 : fprintf( stderr, "Can't find any layer in output tileindex!\n" );
239 0 : exit( 1 );
240 : }
241 :
242 : iTileIndexField =
243 2 : poDstLayer->GetLayerDefn()->GetFieldIndex( pszTileIndexField );
244 2 : if( iTileIndexField == -1 )
245 : {
246 : fprintf( stderr, "Can't find %s field in tile index dataset.\n",
247 0 : pszTileIndexField );
248 0 : exit( 1 );
249 : }
250 :
251 2 : OGRFeatureDefn* poFeatureDefn = NULL;
252 :
253 : /* Load in memory existing file names in SHP */
254 2 : int nExistingLayers = 0;
255 2 : char** existingLayersTab = NULL;
256 2 : OGRSpatialReference* alreadyExistingSpatialRef = NULL;
257 2 : int alreadyExistingSpatialRefValid = FALSE;
258 2 : nExistingLayers = poDstLayer->GetFeatureCount();
259 2 : if (nExistingLayers)
260 : {
261 : int i;
262 0 : existingLayersTab = (char**)CPLMalloc(nExistingLayers * sizeof(char*));
263 0 : for(i=0;i<nExistingLayers;i++)
264 : {
265 0 : OGRFeature* feature = poDstLayer->GetNextFeature();
266 0 : existingLayersTab[i] = CPLStrdup(feature->GetFieldAsString( iTileIndexField));
267 0 : if (i == 0)
268 : {
269 : OGRDataSource *poDS;
270 0 : char* filename = CPLStrdup(existingLayersTab[i]);
271 : int j;
272 0 : for(j=strlen(filename)-1;j>=0;j--)
273 : {
274 0 : if (filename[j] == ',')
275 0 : break;
276 : }
277 0 : if (j >= 0)
278 : {
279 0 : int iLayer = atoi(filename + j + 1);
280 0 : filename[j] = 0;
281 : poDS = OGRSFDriverRegistrar::Open(filename,
282 0 : FALSE );
283 0 : if (poDS)
284 : {
285 0 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
286 0 : if (poLayer)
287 : {
288 0 : alreadyExistingSpatialRefValid = TRUE;
289 : alreadyExistingSpatialRef =
290 0 : (poLayer->GetSpatialRef()) ? poLayer->GetSpatialRef()->Clone() : NULL;
291 :
292 0 : if (poFeatureDefn == NULL)
293 0 : poFeatureDefn = poLayer->GetLayerDefn()->Clone();
294 : }
295 0 : OGRDataSource::DestroyDataSource( poDS );
296 : }
297 : }
298 : }
299 : }
300 : }
301 :
302 :
303 2 : if (write_absolute_path)
304 : {
305 0 : current_path = CPLGetCurrentDir();
306 0 : if (current_path == NULL)
307 : {
308 : fprintf( stderr, "This system does not support the CPLGetCurrentDir call. "
309 0 : "The option -write_absolute_path will have no effect\n");
310 0 : write_absolute_path = FALSE;
311 : }
312 : }
313 : /* ==================================================================== */
314 : /* Process each input datasource in turn. */
315 : /* ==================================================================== */
316 :
317 10 : for(; nFirstSourceDataset < nArgc; nFirstSourceDataset++ )
318 : {
319 : int i;
320 : OGRDataSource *poDS;
321 :
322 8 : if( papszArgv[nFirstSourceDataset][0] == '-' )
323 : {
324 0 : nFirstSourceDataset++;
325 0 : continue;
326 : }
327 :
328 : char* fileNameToWrite;
329 : VSIStatBuf sStatBuf;
330 :
331 8 : if (write_absolute_path && CPLIsFilenameRelative( papszArgv[nFirstSourceDataset] ) &&
332 0 : VSIStat( papszArgv[nFirstSourceDataset], &sStatBuf ) == 0)
333 : {
334 0 : fileNameToWrite = CPLStrdup(CPLProjectRelativeFilename(current_path,papszArgv[nFirstSourceDataset]));
335 : }
336 : else
337 : {
338 8 : fileNameToWrite = CPLStrdup(papszArgv[nFirstSourceDataset]);
339 : }
340 :
341 8 : poDS = OGRSFDriverRegistrar::Open( papszArgv[nFirstSourceDataset],
342 16 : FALSE );
343 :
344 8 : if( poDS == NULL )
345 : {
346 : fprintf( stderr, "Failed to open dataset %s, skipping.\n",
347 0 : papszArgv[nFirstSourceDataset] );
348 0 : CPLFree(fileNameToWrite);
349 0 : continue;
350 : }
351 :
352 : /* -------------------------------------------------------------------- */
353 : /* Check all layers, and see if they match requests. */
354 : /* -------------------------------------------------------------------- */
355 : int iLayer;
356 :
357 16 : for( iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++ )
358 : {
359 8 : int bRequested = bLayersWildcarded;
360 8 : OGRLayer *poLayer = poDS->GetLayer(iLayer);
361 :
362 8 : for( iArg = 1; iArg < nArgc && !bRequested; iArg++ )
363 : {
364 0 : if( EQUAL(papszArgv[iArg],"-lnum")
365 0 : && atoi(papszArgv[iArg+1]) == iLayer )
366 0 : bRequested = TRUE;
367 0 : else if( EQUAL(papszArgv[iArg],"-lname")
368 0 : && EQUAL(papszArgv[iArg+1],
369 : poLayer->GetLayerDefn()->GetName()) )
370 0 : bRequested = TRUE;
371 : }
372 :
373 8 : if( !bRequested )
374 0 : continue;
375 :
376 : /* Checks that the layer is not already in tileindex */
377 8 : for(i=0;i<nExistingLayers;i++)
378 : {
379 : char szLocation[5000];
380 : sprintf( szLocation, "%s,%d",
381 0 : fileNameToWrite, iLayer );
382 0 : if (EQUAL(szLocation, existingLayersTab[i]))
383 : {
384 : fprintf(stderr, "Layer %d of %s is already in tileindex. Skipping it.\n",
385 0 : iLayer, papszArgv[nFirstSourceDataset]);
386 0 : break;
387 : }
388 : }
389 8 : if (i != nExistingLayers)
390 : {
391 0 : continue;
392 : }
393 :
394 8 : OGRSpatialReference* spatialRef = poLayer->GetSpatialRef();
395 8 : if (alreadyExistingSpatialRefValid)
396 : {
397 6 : if ((spatialRef != NULL && alreadyExistingSpatialRef != NULL &&
398 : spatialRef->IsSame(alreadyExistingSpatialRef) == FALSE) ||
399 : ((spatialRef != NULL) != (alreadyExistingSpatialRef != NULL)))
400 : {
401 : fprintf(stderr, "Warning : layer %d of %s is not using the same projection system as "
402 : "other files in the tileindex. This may cause problems when "
403 : "using it in MapServer for example.%s\n", iLayer, papszArgv[nFirstSourceDataset],
404 0 : (skip_different_projection) ? " Skipping it" : "");
405 0 : if (skip_different_projection)
406 : {
407 0 : continue;
408 : }
409 : }
410 : }
411 : else
412 : {
413 2 : alreadyExistingSpatialRefValid = TRUE;
414 2 : alreadyExistingSpatialRef = (spatialRef) ? spatialRef->Clone() : NULL;
415 : }
416 :
417 : /* -------------------------------------------------------------------- */
418 : /* Check if all layers in dataset have the same attributes schema. */
419 : /* -------------------------------------------------------------------- */
420 8 : if( poFeatureDefn == NULL )
421 : {
422 2 : poFeatureDefn = poLayer->GetLayerDefn()->Clone();
423 : }
424 6 : else if ( !accept_different_schemas )
425 : {
426 6 : OGRFeatureDefn* poFeatureDefnCur = poLayer->GetLayerDefn();
427 6 : assert(NULL != poFeatureDefnCur);
428 :
429 6 : int fieldCount = poFeatureDefnCur->GetFieldCount();
430 :
431 6 : if( fieldCount != poFeatureDefn->GetFieldCount())
432 : {
433 : fprintf( stderr, "Number of attributes of layer %s of %s does not match ... skipping it.\n",
434 0 : poLayer->GetLayerDefn()->GetName(), papszArgv[nFirstSourceDataset]);
435 0 : if (bFirstWarningForNonMatchingAttributes)
436 : {
437 : fprintf( stderr, "Note : you can override this behaviour with -accept_different_schemas option\n"
438 0 : "but this may result in a tileindex incompatible with MapServer\n");
439 0 : bFirstWarningForNonMatchingAttributes = FALSE;
440 : }
441 0 : continue;
442 : }
443 :
444 6 : int bSkip = FALSE;
445 12 : for( int fn = 0; fn < poFeatureDefnCur->GetFieldCount(); fn++ )
446 : {
447 6 : OGRFieldDefn* poField = poFeatureDefn->GetFieldDefn(fn);
448 6 : OGRFieldDefn* poFieldCur = poFeatureDefnCur->GetFieldDefn(fn);
449 :
450 : /* XXX - Should those pointers be checked against NULL? */
451 6 : assert(NULL != poField);
452 6 : assert(NULL != poFieldCur);
453 :
454 6 : if( poField->GetType() != poFieldCur->GetType()
455 : || poField->GetWidth() != poFieldCur->GetWidth()
456 : || poField->GetPrecision() != poFieldCur->GetPrecision()
457 : || !EQUAL( poField->GetNameRef(), poFieldCur->GetNameRef() ) )
458 : {
459 : fprintf( stderr, "Schema of attributes of layer %s of %s does not match ... skipping it.\n",
460 0 : poLayer->GetLayerDefn()->GetName(), papszArgv[nFirstSourceDataset]);
461 0 : if (bFirstWarningForNonMatchingAttributes)
462 : {
463 : fprintf( stderr, "Note : you can override this behaviour with -accept_different_schemas option\n"
464 0 : "but this may result in a tileindex incompatible with MapServer\n");
465 0 : bFirstWarningForNonMatchingAttributes = FALSE;
466 : }
467 0 : bSkip = TRUE;
468 0 : break;
469 : }
470 : }
471 :
472 6 : if (bSkip)
473 0 : continue;
474 : }
475 :
476 :
477 : /* -------------------------------------------------------------------- */
478 : /* Get layer extents, and create a corresponding polygon */
479 : /* geometry. */
480 : /* -------------------------------------------------------------------- */
481 8 : OGREnvelope sExtents;
482 8 : OGRPolygon oRegion;
483 8 : OGRLinearRing oRing;
484 :
485 8 : if( poLayer->GetExtent( &sExtents, TRUE ) != OGRERR_NONE )
486 : {
487 : fprintf( stderr, "GetExtent() failed on layer %s of %s, skipping.\n",
488 0 : poLayer->GetLayerDefn()->GetName(),
489 0 : papszArgv[nFirstSourceDataset] );
490 0 : continue;
491 : }
492 :
493 8 : oRing.addPoint( sExtents.MinX, sExtents.MinY );
494 8 : oRing.addPoint( sExtents.MinX, sExtents.MaxY );
495 8 : oRing.addPoint( sExtents.MaxX, sExtents.MaxY );
496 8 : oRing.addPoint( sExtents.MaxX, sExtents.MinY );
497 8 : oRing.addPoint( sExtents.MinX, sExtents.MinY );
498 :
499 8 : oRegion.addRing( &oRing );
500 :
501 : /* -------------------------------------------------------------------- */
502 : /* Add layer to tileindex. */
503 : /* -------------------------------------------------------------------- */
504 : char szLocation[5000];
505 8 : OGRFeature oTileFeat( poDstLayer->GetLayerDefn() );
506 :
507 : sprintf( szLocation, "%s,%d",
508 8 : fileNameToWrite, iLayer );
509 8 : oTileFeat.SetGeometry( &oRegion );
510 8 : oTileFeat.SetField( iTileIndexField, szLocation );
511 :
512 8 : if( poDstLayer->CreateFeature( &oTileFeat ) != OGRERR_NONE )
513 : {
514 0 : fprintf( stderr, "Failed to create feature on tile index ... terminating." );
515 0 : OGRDataSource::DestroyDataSource( poDstDS );
516 0 : exit( 1 );
517 : }
518 : }
519 :
520 : /* -------------------------------------------------------------------- */
521 : /* Cleanup this data source. */
522 : /* -------------------------------------------------------------------- */
523 8 : CPLFree(fileNameToWrite);
524 8 : OGRDataSource::DestroyDataSource( poDS );
525 : }
526 :
527 : /* -------------------------------------------------------------------- */
528 : /* Close tile index and clear buffers. */
529 : /* -------------------------------------------------------------------- */
530 2 : OGRDataSource::DestroyDataSource( poDstDS );
531 2 : OGRFeatureDefn::DestroyFeatureDefn( poFeatureDefn );
532 :
533 2 : if (alreadyExistingSpatialRef != NULL)
534 1 : OGRSpatialReference::DestroySpatialReference( alreadyExistingSpatialRef );
535 :
536 2 : CPLFree(current_path);
537 :
538 2 : if (nExistingLayers)
539 : {
540 : int i;
541 0 : for(i=0;i<nExistingLayers;i++)
542 : {
543 0 : CPLFree(existingLayersTab[i]);
544 : }
545 0 : CPLFree(existingLayersTab);
546 : }
547 :
548 2 : return 0;
549 : }
550 :
551 : /************************************************************************/
552 : /* Usage() */
553 : /************************************************************************/
554 :
555 0 : static void Usage()
556 :
557 : {
558 : printf( "Usage: ogrtindex [-lnum n]... [-lname name]... [-f output_format]\n"
559 : " [-write_absolute_path] [-skip_different_projection]\n"
560 : " [-accept_different_schemas]\n"
561 0 : " output_dataset src_dataset...\n" );
562 0 : printf( "\n" );
563 : printf( " -lnum n: Add layer number 'n' from each source file\n"
564 0 : " in the tile index.\n" );
565 : printf( " -lname name: Add the layer named 'name' from each source file\n"
566 0 : " in the tile index.\n" );
567 : printf( " -f output_format: Select an output format name. The default\n"
568 0 : " is to create a shapefile.\n" );
569 : printf( " -tileindex field_name: The name to use for the dataset name.\n"
570 0 : " Defaults to LOCATION.\n" );
571 0 : printf( " -write_absolute_path: Filenames are written with absolute paths.\n" );
572 : printf( " -skip_different_projection: Only layers with same projection ref \n"
573 0 : " as layers already inserted in the tileindex will be inserted.\n" );
574 : printf( " -accept_different_schemas: by default ogrtindex checks that all layers inserted\n"
575 : " into the index have the same attribute schemas. If you\n"
576 : " specify this option, this test will be disabled. Be aware that\n"
577 0 : " resulting index may be incompatible with MapServer!\n" );
578 0 : printf( "\n" );
579 : printf( "If no -lnum or -lname arguments are given it is assumed that\n"
580 : "all layers in source datasets should be added to the tile index\n"
581 0 : "as independent records.\n" );
582 0 : exit( 1 );
583 : }
|