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