2022-05-14 03:28:14 +08:00
|
|
|
/******************************************************************************
|
|
|
|
*
|
|
|
|
* Project: OpenGIS Simple Features Reference Implementation
|
|
|
|
* Purpose: Allow a user to dissolve geometries based on an attribute.
|
|
|
|
* Author: Howard Butler, hobu.inc@gmail.com
|
|
|
|
*
|
|
|
|
******************************************************************************
|
|
|
|
* Copyright (c) 2007, Howard Butler
|
|
|
|
*
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
*
|
|
|
|
* The above copyright notice and this permission notice shall be included
|
|
|
|
* in all copies or substantial portions of the Software.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
|
|
* DEALINGS IN THE SOFTWARE.
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "ogrsf_frmts.h"
|
|
|
|
#include "ogr_p.h"
|
|
|
|
#include "cpl_conv.h"
|
|
|
|
#include "cpl_string.h"
|
|
|
|
#include "ogr_api.h"
|
|
|
|
#include "commonutils.h"
|
|
|
|
#include <map>
|
|
|
|
#include <list>
|
|
|
|
|
|
|
|
static void Usage();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
static int DissolveLayer(OGRDataSource *poSrcDS, OGRLayer *poSrcLayer,
|
|
|
|
OGRDataSource *poDstDS, char **papszLSCO,
|
|
|
|
const char *pszNewLayerName, int bTransform,
|
|
|
|
OGRSpatialReference *poOutputSRS,
|
|
|
|
OGRSpatialReference *poSourceSRS,
|
|
|
|
char **papszSelFields, int bAppend, int eGType,
|
|
|
|
int bOverwrite);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
static int bSkipFailures = FALSE;
|
|
|
|
static int nGroupTransactions = 200;
|
|
|
|
static int bPreserveFID = FALSE;
|
|
|
|
static int nFIDToFetch = OGRNullFID;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
typedef std::multimap<CPLString, OGRGeometry *> StringGeometryMMap;
|
|
|
|
typedef std::map<CPLString, OGRGeometryCollection *> StringGeometryColMap;
|
|
|
|
typedef std::map<CPLString, OGRGeometry *> StringGeometryMap;
|
|
|
|
typedef std::list<OGRGeometry *> GeometriesList;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* main() */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
MAIN_START(nArgc, papszArgv)
|
|
|
|
|
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
const char *pszFormat = "ESRI Shapefile";
|
|
|
|
const char *pszDataSource = NULL;
|
|
|
|
const char *pszDestDataSource = NULL;
|
|
|
|
char **papszLayers = NULL;
|
|
|
|
char **papszDSCO = NULL, **papszLCO = NULL;
|
|
|
|
int bTransform = FALSE;
|
|
|
|
int bAppend = FALSE, bUpdate = FALSE, bOverwrite = FALSE;
|
|
|
|
const char *pszOutputSRSDef = NULL;
|
|
|
|
const char *pszSourceSRSDef = NULL;
|
2022-05-14 03:28:14 +08:00
|
|
|
OGRSpatialReference *poOutputSRS = NULL;
|
|
|
|
OGRSpatialReference *poSourceSRS = NULL;
|
2024-04-24 11:11:49 +08:00
|
|
|
const char *pszNewLayerName = NULL;
|
|
|
|
const char *pszWHERE = NULL;
|
2022-05-14 03:28:14 +08:00
|
|
|
OGRGeometry *poSpatialFilter = NULL;
|
2024-04-24 11:11:49 +08:00
|
|
|
const char *pszSelect;
|
|
|
|
char **papszSelFields = NULL;
|
|
|
|
const char *pszSQLStatement = NULL;
|
|
|
|
int eGType = -2;
|
|
|
|
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Register format(s). */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
OGRRegisterAll();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Processing command line arguments. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
nArgc = OGRGeneralCmdLineProcessor(nArgc, &papszArgv, 0);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (nArgc < 1)
|
|
|
|
exit(-nArgc);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (int iArg = 1; iArg < nArgc; iArg++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (EQUAL(papszArgv[iArg], "--help"))
|
|
|
|
{
|
|
|
|
Usage();
|
|
|
|
}
|
|
|
|
if ((EQUAL(papszArgv[iArg], "-f") || EQUAL(papszArgv[iArg], "-of")) &&
|
|
|
|
iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszFormat = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-dsco") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
papszDSCO = CSLAddString(papszDSCO, papszArgv[++iArg]);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-lco") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
papszLCO = CSLAddString(papszLCO, papszArgv[++iArg]);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-preserve_fid"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bPreserveFID = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (STARTS_WITH_CI(papszArgv[iArg], "-skip"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bSkipFailures = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-append"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bAppend = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-overwrite"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bOverwrite = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-update"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bUpdate = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-fid") && papszArgv[iArg + 1] != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
nFIDToFetch = atoi(papszArgv[++iArg]);
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-sql") && papszArgv[iArg + 1] != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszSQLStatement = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-nln") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszNewLayerName = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-nlt") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
int bIs3D = FALSE;
|
2024-04-24 11:11:49 +08:00
|
|
|
CPLString osGeomName = papszArgv[iArg + 1];
|
|
|
|
if (strlen(papszArgv[iArg + 1]) > 3 &&
|
|
|
|
STARTS_WITH_CI(papszArgv[iArg + 1] +
|
|
|
|
strlen(papszArgv[iArg + 1]) - 3,
|
|
|
|
"25D"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bIs3D = TRUE;
|
|
|
|
osGeomName.resize(osGeomName.size() - 3);
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (strlen(papszArgv[iArg + 1]) > 1 &&
|
|
|
|
STARTS_WITH_CI(papszArgv[iArg + 1] +
|
|
|
|
strlen(papszArgv[iArg + 1]) - 1,
|
|
|
|
"Z"))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
bIs3D = TRUE;
|
|
|
|
osGeomName.resize(osGeomName.size() - 1);
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
if (EQUAL(osGeomName, "NONE"))
|
2022-05-14 03:28:14 +08:00
|
|
|
eGType = wkbNone;
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(osGeomName, "GEOMETRY"))
|
2022-05-14 03:28:14 +08:00
|
|
|
eGType = wkbUnknown;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
eGType = OGRFromOGCGeomType(osGeomName);
|
|
|
|
if (eGType == wkbUnknown)
|
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
fprintf(stderr, "-nlt %s: type not recognised.\n",
|
|
|
|
papszArgv[iArg + 1]);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (eGType != wkbNone && bIs3D)
|
|
|
|
eGType = wkbSetZ((OGRwkbGeometryType)eGType);
|
|
|
|
iArg++;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-tg") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
nGroupTransactions = atoi(papszArgv[++iArg]);
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-s_srs") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszSourceSRSDef = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-a_srs") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszOutputSRSDef = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-t_srs") && iArg < nArgc - 1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszOutputSRSDef = papszArgv[++iArg];
|
|
|
|
bTransform = TRUE;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-spat") &&
|
|
|
|
papszArgv[iArg + 1] != NULL && papszArgv[iArg + 2] != NULL &&
|
|
|
|
papszArgv[iArg + 3] != NULL && papszArgv[iArg + 4] != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRLinearRing oRing;
|
|
|
|
|
|
|
|
oRing.addPoint(CPLAtof(papszArgv[iArg + 1]),
|
|
|
|
CPLAtof(papszArgv[iArg + 2]));
|
|
|
|
oRing.addPoint(CPLAtof(papszArgv[iArg + 1]),
|
|
|
|
CPLAtof(papszArgv[iArg + 4]));
|
|
|
|
oRing.addPoint(CPLAtof(papszArgv[iArg + 3]),
|
|
|
|
CPLAtof(papszArgv[iArg + 4]));
|
|
|
|
oRing.addPoint(CPLAtof(papszArgv[iArg + 3]),
|
|
|
|
CPLAtof(papszArgv[iArg + 2]));
|
|
|
|
oRing.addPoint(CPLAtof(papszArgv[iArg + 1]),
|
|
|
|
CPLAtof(papszArgv[iArg + 2]));
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
poSpatialFilter = new OGRPolygon();
|
2024-04-24 11:11:49 +08:00
|
|
|
poSpatialFilter->toPolygon()->addRing(&oRing);
|
2022-05-14 03:28:14 +08:00
|
|
|
iArg += 4;
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-where") &&
|
|
|
|
papszArgv[iArg + 1] != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszWHERE = papszArgv[++iArg];
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (EQUAL(papszArgv[iArg], "-select") &&
|
|
|
|
papszArgv[iArg + 1] != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
pszSelect = papszArgv[++iArg];
|
2024-04-24 11:11:49 +08:00
|
|
|
papszSelFields =
|
|
|
|
CSLTokenizeStringComplex(pszSelect, " ,", FALSE, FALSE);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (papszArgv[iArg][0] == '-')
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
Usage();
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (pszDestDataSource == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
pszDestDataSource = papszArgv[iArg];
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (pszDataSource == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
pszDataSource = papszArgv[iArg];
|
|
|
|
else
|
2024-04-24 11:11:49 +08:00
|
|
|
papszLayers = CSLAddString(papszLayers, papszArgv[iArg]);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (pszDataSource == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
Usage();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Open data source. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
OGRDataSource *poDS;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poDS = OGRSFDriverRegistrar::Open(pszDataSource, FALSE);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Report failure */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (poDS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("FAILURE:\n"
|
|
|
|
"Unable to open datasource `%s' with the following drivers.\n",
|
|
|
|
pszDataSource);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf(" -> %s\n", poR->GetDriver(iDriver)->GetName());
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Try opening the output datasource as an existing, writable */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
OGRDataSource *poODS;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (bUpdate)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
poODS = OGRSFDriverRegistrar::Open(pszDestDataSource, TRUE);
|
|
|
|
if (poODS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("FAILURE:\n"
|
|
|
|
"Unable to open existing output datasource `%s'.\n",
|
|
|
|
pszDestDataSource);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Find the output driver. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRSFDriver *poDriver = NULL;
|
|
|
|
int iDriver;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iDriver = 0; iDriver < poR->GetDriverCount() && poDriver == NULL;
|
|
|
|
iDriver++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (EQUAL(poR->GetDriver(iDriver)->GetName(), pszFormat))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
poDriver = poR->GetDriver(iDriver);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poDriver == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("Unable to find driver `%s'.\n", pszFormat);
|
|
|
|
printf("The following drivers are available:\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf(" -> `%s'\n", poR->GetDriver(iDriver)->GetName());
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (!poDriver->TestCapability(ODrCCreateDataSource))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("%s driver does not support data source creation.\n",
|
|
|
|
pszFormat);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* --------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
/* Create the output data source. */
|
|
|
|
/* --------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
poODS = poDriver->CreateDataSource(pszDestDataSource, papszDSCO);
|
|
|
|
if (poODS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("%s driver failed to create %s\n", pszFormat,
|
|
|
|
pszDestDataSource);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Parse the output SRS definition if possible. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (pszOutputSRSDef != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
poOutputSRS = new OGRSpatialReference();
|
|
|
|
poOutputSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poOutputSRS->SetFromUserInput(pszOutputSRSDef) != OGRERR_NONE)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("Failed to process SRS definition: %s\n", pszOutputSRSDef);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Parse the source SRS definition if possible. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (pszSourceSRSDef != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
poSourceSRS = new OGRSpatialReference();
|
|
|
|
poSourceSRS->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poSourceSRS->SetFromUserInput(pszSourceSRSDef) != OGRERR_NONE)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("Failed to process SRS definition: %s\n", pszSourceSRSDef);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Special case for -sql clause. No source layers required. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (pszSQLStatement != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
OGRLayer *poResultSet;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (pszWHERE != NULL)
|
|
|
|
printf("-where clause ignored in combination with -sql.\n");
|
|
|
|
if (CSLCount(papszLayers) > 0)
|
|
|
|
printf("layer names ignored in combination with -sql.\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poResultSet = poDS->ExecuteSQL(pszSQLStatement, poSpatialFilter, NULL);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poResultSet != NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (!DissolveLayer(poDS, poResultSet, poODS, papszLCO,
|
|
|
|
pszNewLayerName, bTransform, poOutputSRS,
|
|
|
|
poSourceSRS, papszSelFields, bAppend, eGType,
|
|
|
|
bOverwrite))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
|
|
"Terminating translation prematurely after failed\n"
|
|
|
|
"translation from sql statement.");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
poDS->ReleaseResultSet(poResultSet);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Process each data source layer. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
for (int iLayer = 0;
|
|
|
|
pszSQLStatement == NULL && iLayer < poDS->GetLayerCount(); iLayer++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRLayer *poLayer = poDS->GetLayer(iLayer);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poLayer == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("FAILURE: Couldn't fetch advertised layer %d!\n", iLayer);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (CSLCount(papszLayers) == 0 ||
|
|
|
|
CSLFindString(papszLayers, poLayer->GetLayerDefn()->GetName()) !=
|
|
|
|
-1)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (pszWHERE != NULL)
|
|
|
|
poLayer->SetAttributeFilter(pszWHERE);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poSpatialFilter != NULL)
|
|
|
|
poLayer->SetSpatialFilter(poSpatialFilter);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (!DissolveLayer(poDS, poLayer, poODS, papszLCO, pszNewLayerName,
|
|
|
|
bTransform, poOutputSRS, poSourceSRS,
|
|
|
|
papszSelFields, bAppend, eGType, bOverwrite) &&
|
|
|
|
!bSkipFailures)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
|
|
"Terminating translation prematurely after failed\n"
|
|
|
|
"translation of layer %s\n",
|
|
|
|
poLayer->GetLayerDefn()->GetName());
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Close down. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
OGRSpatialReference::DestroySpatialReference(poOutputSRS);
|
|
|
|
OGRSpatialReference::DestroySpatialReference(poSourceSRS);
|
|
|
|
OGRDataSource::DestroyDataSource(poODS);
|
|
|
|
OGRDataSource::DestroyDataSource(poDS);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
CSLDestroy(papszSelFields);
|
2024-04-24 11:11:49 +08:00
|
|
|
CSLDestroy(papszArgv);
|
|
|
|
CSLDestroy(papszLayers);
|
|
|
|
CSLDestroy(papszDSCO);
|
|
|
|
CSLDestroy(papszLCO);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
OGRCleanupAll();
|
|
|
|
|
|
|
|
#ifdef DBMALLOC
|
|
|
|
malloc_dump(1);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
MAIN_END
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Usage() */
|
|
|
|
/************************************************************************/
|
|
|
|
|
|
|
|
static void Usage()
|
|
|
|
|
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRSFDriverRegistrar *poR = OGRSFDriverRegistrar::GetRegistrar();
|
|
|
|
|
|
|
|
printf("Usage: ogr2ogr [--help] [--help-general]\n"
|
|
|
|
" [-skipfailures] [-append] [-update]\n"
|
|
|
|
" [-select field_list] [-where restricted_where] \n"
|
|
|
|
" [-sql <sql statement>] \n"
|
|
|
|
" [-spat xmin ymin xmax ymax] [-preserve_fid] [-fid "
|
|
|
|
"FID]\n"
|
|
|
|
" [-a_srs srs_def] [-t_srs srs_def] [-s_srs srs_def]\n"
|
|
|
|
" [-f format_name] [-overwrite] [[-dsco NAME=VALUE] "
|
|
|
|
"...]\n"
|
|
|
|
" dst_datasource_name src_datasource_name\n"
|
|
|
|
" [-lco NAME=VALUE] [-nln name] [-nlt type] [layer "
|
|
|
|
"[layer ...]]\n"
|
|
|
|
"\n"
|
|
|
|
" -f format_name: output file format name, possible values are:\n");
|
|
|
|
|
|
|
|
for (int iDriver = 0; iDriver < poR->GetDriverCount(); iDriver++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
OGRSFDriver *poDriver = poR->GetDriver(iDriver);
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poDriver->TestCapability(ODrCCreateDataSource))
|
|
|
|
printf(" -f \"%s\"\n", poDriver->GetName());
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
printf(
|
|
|
|
" -append: Append to existing layer instead of creating new if it "
|
|
|
|
"exists\n"
|
|
|
|
" -overwrite: delete the output layer and recreate it empty\n"
|
|
|
|
" -update: Open existing output datasource in update mode\n"
|
|
|
|
" -select field_list: Comma-delimited list of fields from input layer "
|
|
|
|
"to\n"
|
|
|
|
" copy to the new layer (defaults to all)\n"
|
|
|
|
" -where restricted_where: Attribute query (like SQL WHERE)\n"
|
|
|
|
" -sql statement: Execute given SQL statement and save result.\n"
|
|
|
|
" -skipfailures: skip features or layers that fail to convert\n"
|
|
|
|
" -spat xmin ymin xmax ymax: spatial query extents\n"
|
|
|
|
" -dsco NAME=VALUE: Dataset creation option (format specific)\n"
|
|
|
|
" -lco NAME=VALUE: Layer creation option (format specific)\n"
|
|
|
|
" -nln name: Assign an alternate name to the new layer\n"
|
|
|
|
" -nlt type: Force a geometry type for new layer. One of NONE, "
|
|
|
|
"GEOMETRY,\n"
|
|
|
|
" POINT, LINESTRING, POLYGON, GEOMETRYCOLLECTION, MULTIPOINT, "
|
|
|
|
"MULTILINE,\n"
|
|
|
|
" MULTIPOLYGON, or MULTILINESTRING. Add \"25D\" for 3D layers.\n"
|
|
|
|
" Default is type of source layer.\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
printf(" -a_srs srs_def: Assign an output SRS\n"
|
|
|
|
" -t_srs srs_def: Reproject/transform to this SRS on output\n"
|
|
|
|
" -s_srs srs_def: Override source SRS\n"
|
|
|
|
"\n"
|
|
|
|
" Srs_def can be a full WKT definition (hard to escape properly),\n"
|
|
|
|
" or a well known definition (i.e. EPSG:4326) or a file with a WKT\n"
|
2024-04-24 11:11:49 +08:00
|
|
|
" definition.\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
StringGeometryMap *CollectGeometries(OGRLayer *poSrcLayer,
|
|
|
|
const char **papszFields)
|
|
|
|
{
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* CollectGeometries returns a dictionary where the keys are the */
|
|
|
|
/* values in the fields that the user has selected and the values */
|
|
|
|
/* are a GeometryCollection of all of the geometries for records */
|
|
|
|
/* with that value. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
StringGeometryMMap poGeometriesMap;
|
|
|
|
|
|
|
|
poSrcLayer->ResetReading();
|
|
|
|
|
|
|
|
int iField;
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Get all of the features and put them in a multi map. This may */
|
|
|
|
/* include values for which the selected fields is NULL. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (auto &poFeature : poSrcLayer)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
CPLString poKey("");
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iField = 0; papszFields[iField] != NULL; iField++)
|
|
|
|
{
|
2022-05-14 03:28:14 +08:00
|
|
|
int nField = poFeature->GetFieldIndex(papszFields[iField]);
|
|
|
|
poKey = poKey + poFeature->GetFieldAsString(nField);
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poFeature->GetGeometryRef()->IsValid())
|
|
|
|
{
|
|
|
|
poGeometriesMap.insert(
|
|
|
|
std::make_pair(CPLString(poKey), poFeature->GetGeometryRef()));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
CPLDebug("CollectGeometries",
|
|
|
|
"Geometry was invalid not adding!!!!");
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Loop through our features map and get a unique list of field */
|
|
|
|
/* values. This could be done using something other than a map */
|
|
|
|
/* of course, but it was convenient. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
typedef std::map<CPLString, int> StringIntMap;
|
|
|
|
StringIntMap::const_iterator ipos;
|
|
|
|
StringIntMap poFieldsmap;
|
|
|
|
|
|
|
|
StringGeometryMMap::const_iterator pos;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (pos = poGeometriesMap.begin(); pos != poGeometriesMap.end(); ++pos)
|
|
|
|
{
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* we currently throw out any null field values at this time */
|
|
|
|
// if (!(pos->first.empty())) {
|
|
|
|
poFieldsmap[CPLString(pos->first.c_str())] = 1;
|
|
|
|
// }
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Make a new map of GeometryCollection for each value in the */
|
|
|
|
/* poFieldsmap. This is a 1:1 relationship, and all of the */
|
|
|
|
/* geometries for a given field are all put into the same */
|
|
|
|
/* GeometryCollection. After we build the poCollections, we will */
|
|
|
|
/* use GEOS' buffer(0) trick to have GEOS perform the segmentation */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
StringGeometryColMap poCollections;
|
|
|
|
|
|
|
|
CPLDebug("CollectGeometries", "Field map size: %d", poFieldsmap.size());
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (ipos = poFieldsmap.begin(); ipos != poFieldsmap.end(); ++ipos)
|
|
|
|
{
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
CPLString fid = ipos->first;
|
|
|
|
CPLDebug("CollectGeometries", "First %s Second %d", ipos->first.c_str(),
|
|
|
|
ipos->second);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRGeometryCollection *geom = new OGRGeometryCollection;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (pos = poGeometriesMap.lower_bound(fid);
|
|
|
|
pos != poGeometriesMap.upper_bound(fid); ++pos)
|
|
|
|
{
|
|
|
|
geom->addGeometry(pos->second);
|
|
|
|
}
|
|
|
|
poCollections.insert(std::make_pair(fid, geom));
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
CPLDebug("CollectGeometries", "Geo map size: %d", poCollections.size());
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Loop through our poCollections map and buffer(0) each */
|
|
|
|
/* GeometryCollection. GEOS will collapse the geometries down */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
StringGeometryMap *buffers = new StringGeometryMap;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
StringGeometryColMap::const_iterator collections_i;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (collections_i = poCollections.begin();
|
|
|
|
collections_i != poCollections.end(); ++collections_i)
|
|
|
|
{
|
|
|
|
CPLDebug("CollectGeometries", "poCollections Geometry size %d",
|
|
|
|
collections_i->second->getNumGeometries());
|
|
|
|
OGRGeometry *buffer = collections_i->second->Buffer(0);
|
|
|
|
buffers->insert(std::make_pair(collections_i->first, buffer));
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
for (collections_i = poCollections.begin();
|
2024-04-24 11:11:49 +08:00
|
|
|
collections_i != poCollections.end(); ++collections_i)
|
|
|
|
{
|
|
|
|
delete collections_i->second;
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return buffers;
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
GeometriesList *FlattenGeometries(GeometriesList *input)
|
|
|
|
{
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
GeometriesList::const_iterator geometry_i;
|
2024-04-24 11:11:49 +08:00
|
|
|
GeometriesList *output = new GeometriesList;
|
|
|
|
|
|
|
|
CPLDebug("CollectGeometries",
|
|
|
|
"Input geometries in FlattenGeometries size: %d", input->size());
|
|
|
|
for (geometry_i = input->begin(); geometry_i != input->end(); ++geometry_i)
|
|
|
|
{
|
|
|
|
|
|
|
|
OGRGeometry *buffer = (*geometry_i);
|
|
|
|
// int nGeometries = buffer->getNumGeometries();
|
|
|
|
OGRwkbGeometryType iGType = buffer->getGeometryType();
|
|
|
|
|
|
|
|
if (iGType == wkbPolygon)
|
|
|
|
{
|
|
|
|
output->push_back(buffer);
|
|
|
|
CPLDebug("CollectGeometries",
|
|
|
|
"Collapsing wkbPolygon geometries......");
|
|
|
|
}
|
|
|
|
if (iGType == wkbMultiPolygon)
|
|
|
|
{
|
|
|
|
OGRMultiPolygon *geom = buffer->toMultiPolygon();
|
|
|
|
for (int i = 0; i < geom->getNumGeometries(); i++)
|
|
|
|
{
|
|
|
|
OGRPolygon *g = geom->getGeometryRef(i)->toPolygon();
|
|
|
|
output->push_back((OGRGeometry *)g);
|
|
|
|
}
|
|
|
|
|
|
|
|
CPLDebug("CollectGeometries",
|
|
|
|
"Collapsing wkbMultiPolygon geometries......");
|
|
|
|
}
|
|
|
|
if (iGType == wkbGeometryCollection)
|
|
|
|
{
|
|
|
|
OGRGeometryCollection *geom = buffer->toGeometryCollection();
|
|
|
|
GeometriesList *collection = new GeometriesList;
|
|
|
|
GeometriesList::const_iterator g_i;
|
|
|
|
for (int i = 0; i < geom->getNumGeometries(); i++)
|
|
|
|
{
|
|
|
|
OGRGeometry *g = geom->getGeometryRef(i);
|
|
|
|
collection->push_back(g);
|
|
|
|
}
|
|
|
|
GeometriesList *collapsed = FlattenGeometries(collection);
|
|
|
|
for (g_i = collapsed->begin(); g_i != collapsed->end(); g_i++)
|
|
|
|
{
|
|
|
|
output->push_back((OGRGeometry *)(*g_i));
|
|
|
|
CPLDebug("CollectGeometries",
|
|
|
|
"Collapsing wkbGeometryCollection geometries.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// CPLDebug( "CollectGeometries",
|
|
|
|
// "Buffered Geometry size %d",
|
|
|
|
// nGeometries);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return output;
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
|
|
/* DissolveLayer() */
|
|
|
|
/************************************************************************/
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
static int DissolveLayer(OGRDataSource *poSrcDS, OGRLayer *poSrcLayer,
|
|
|
|
OGRDataSource *poDstDS, char **papszLCO,
|
|
|
|
const char *pszNewLayerName, int bTransform,
|
|
|
|
OGRSpatialReference *poOutputSRS,
|
|
|
|
OGRSpatialReference *poSourceSRS,
|
|
|
|
char **papszSelFields, int bAppend, int eGType,
|
|
|
|
int bOverwrite)
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
{
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRLayer *poDstLayer;
|
2022-05-14 03:28:14 +08:00
|
|
|
OGRFeatureDefn *poFDefn;
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRErr eErr;
|
|
|
|
int bForceToPolygon = FALSE;
|
|
|
|
int bForceToMultiPolygon = FALSE;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (pszNewLayerName == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (wkbFlatten(eGType) == wkbPolygon)
|
2022-05-14 03:28:14 +08:00
|
|
|
bForceToPolygon = TRUE;
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (wkbFlatten(eGType) == wkbMultiPolygon)
|
2022-05-14 03:28:14 +08:00
|
|
|
bForceToMultiPolygon = TRUE;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Setup coordinate transformation if we need it. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
OGRCoordinateTransformation *poCT = NULL;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (bTransform)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poSourceSRS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
poSourceSRS = poSrcLayer->GetSpatialRef();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poSourceSRS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("Can't transform coordinates, source layer has no\n"
|
|
|
|
"coordinate system. Use -s_srs to set one.\n");
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
CPLAssert(NULL != poSourceSRS);
|
|
|
|
CPLAssert(NULL != poOutputSRS);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poCT = OGRCreateCoordinateTransformation(poSourceSRS, poOutputSRS);
|
|
|
|
if (poCT == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
char *pszWKT = NULL;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
printf("Failed to create coordinate transformation between the\n"
|
|
|
|
"following coordinate systems. This may be because they\n"
|
|
|
|
"are not transformable, or because projection services\n"
|
2024-04-24 11:11:49 +08:00
|
|
|
"(PROJ.4 DLL/.so) could not be loaded.\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poSourceSRS->exportToPrettyWkt(&pszWKT, FALSE);
|
|
|
|
printf("Source:\n%s\n", pszWKT);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poOutputSRS->exportToPrettyWkt(&pszWKT, FALSE);
|
|
|
|
printf("Target:\n%s\n", pszWKT);
|
|
|
|
exit(1);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Get other info. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
poFDefn = poSrcLayer->GetLayerDefn();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poOutputSRS == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
poOutputSRS = poSrcLayer->GetSpatialRef();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Find the layer. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
2022-05-14 03:28:14 +08:00
|
|
|
int iLayer = -1;
|
|
|
|
poDstLayer = NULL;
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poLayer != NULL &&
|
|
|
|
EQUAL(poLayer->GetLayerDefn()->GetName(), pszNewLayerName))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
poDstLayer = poLayer;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* If the user requested overwrite, and we have the layer in */
|
|
|
|
/* question we need to delete it now so it will get recreated */
|
|
|
|
/* (overwritten). */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (poDstLayer != NULL && bOverwrite)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poDstDS->DeleteLayer(iLayer) != OGRERR_NONE)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
fprintf(stderr, "DeleteLayer() failed when overwrite requested.\n");
|
2022-05-14 03:28:14 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
poDstLayer = NULL;
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* If the layer does not exist, then create it. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if (poDstLayer == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
if (eGType == -2)
|
2022-05-14 03:28:14 +08:00
|
|
|
eGType = poFDefn->GetGeomType();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (!poDstDS->TestCapability(ODsCCreateLayer))
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
fprintf(
|
|
|
|
stderr,
|
|
|
|
"Layer %s not found, and CreateLayer not supported by driver.",
|
|
|
|
pszNewLayerName);
|
2022-05-14 03:28:14 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
CPLErrorReset();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
poDstLayer = poDstDS->CreateLayer(pszNewLayerName, poOutputSRS,
|
|
|
|
(OGRwkbGeometryType)eGType, papszLCO);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (poDstLayer == NULL)
|
2022-05-14 03:28:14 +08:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
bAppend = FALSE;
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Otherwise we will append to it, if append was requested. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
else if (!bAppend)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("FAILED: Layer %s already exists, and -append not specified.\n"
|
|
|
|
" Consider using -append, or -overwrite.\n",
|
|
|
|
pszNewLayerName);
|
2022-05-14 03:28:14 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Add fields. Default to copy all field. */
|
|
|
|
/* If only a subset of all fields requested, then output only */
|
|
|
|
/* the selected fields, and in the order that they were */
|
|
|
|
/* selected. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
int iField;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (papszSelFields && !bAppend)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iField = 0; papszSelFields[iField] != NULL; iField++)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
|
|
|
int iSrcField = poFDefn->GetFieldIndex(papszSelFields[iField]);
|
|
|
|
if (iSrcField >= 0)
|
2024-04-24 11:11:49 +08:00
|
|
|
poDstLayer->CreateField(poFDefn->GetFieldDefn(iSrcField));
|
2022-05-14 03:28:14 +08:00
|
|
|
else
|
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
printf("Field '%s' not found in source layer.\n",
|
|
|
|
papszSelFields[iField]);
|
|
|
|
if (!bSkipFailures)
|
2022-05-14 03:28:14 +08:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
else if (!bAppend)
|
2022-05-14 03:28:14 +08:00
|
|
|
{
|
2024-04-24 11:11:49 +08:00
|
|
|
for (iField = 0; iField < poFDefn->GetFieldCount(); iField++)
|
|
|
|
poDstLayer->CreateField(poFDefn->GetFieldDefn(iField));
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
/* Transfer features. */
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
OGRFeature *poFeature;
|
|
|
|
int nFeaturesInTransaction = 0;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
poSrcLayer->ResetReading();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (nGroupTransactions)
|
2022-05-14 03:28:14 +08:00
|
|
|
poDstLayer->StartTransaction();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
StringGeometryMap *buffers =
|
|
|
|
CollectGeometries(poSrcLayer, (const char **)papszSelFields);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
StringGeometryMap::const_iterator buffers_i;
|
2024-04-24 11:11:49 +08:00
|
|
|
GeometriesList *input = new GeometriesList;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
CPLDebug("CollectGeometries", "Buffers size: %d", buffers->size());
|
2024-04-24 11:11:49 +08:00
|
|
|
for (buffers_i = buffers->begin(); buffers_i != buffers->end(); ++buffers_i)
|
|
|
|
{
|
|
|
|
input->push_back(buffers_i->second);
|
2022-05-14 03:28:14 +08:00
|
|
|
}
|
2024-04-24 11:11:49 +08:00
|
|
|
GeometriesList *geometries = FlattenGeometries(input);
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
GeometriesList::const_iterator g_i;
|
2024-04-24 11:11:49 +08:00
|
|
|
for (g_i = geometries->begin(); g_i != geometries->end(); g_i++)
|
|
|
|
{
|
|
|
|
OGRFeature *feature = new OGRFeature(poFDefn);
|
2022-05-14 03:28:14 +08:00
|
|
|
feature->SetGeometry((*g_i));
|
2024-04-24 11:11:49 +08:00
|
|
|
feature->SetField("TAXDIST", "fid");
|
2022-05-14 03:28:14 +08:00
|
|
|
poDstLayer->CreateFeature(feature);
|
|
|
|
}
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
if (nGroupTransactions)
|
2022-05-14 03:28:14 +08:00
|
|
|
poDstLayer->CommitTransaction();
|
|
|
|
|
2024-04-24 11:11:49 +08:00
|
|
|
// getGeometryType
|
|
|
|
// if( pszNewLayerName == NULL )
|
|
|
|
// pszNewLayerName = poSrcLayer->GetLayerDefn()->GetName();
|
|
|
|
//
|
|
|
|
// if( wkbFlatten(eGType) == wkbPolygon )
|
|
|
|
// bForceToPolygon = TRUE;
|
|
|
|
// else if( wkbFlatten(eGType) == wkbMultiPolygon )
|
|
|
|
// bForceToMultiPolygon = TRUE;
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Setup coordinate transformation if we need it. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// OGRCoordinateTransformation *poCT = NULL;
|
|
|
|
//
|
|
|
|
// if( bTransform )
|
|
|
|
// {
|
|
|
|
// if( poSourceSRS == NULL )
|
|
|
|
// poSourceSRS = poSrcLayer->GetSpatialRef();
|
|
|
|
//
|
|
|
|
// if( poSourceSRS == NULL )
|
|
|
|
// {
|
|
|
|
// printf( "Can't transform coordinates, source layer has no\n"
|
|
|
|
// "coordinate system. Use -s_srs to set one.\n" );
|
|
|
|
// exit( 1 );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// CPLAssert( NULL != poSourceSRS );
|
|
|
|
// CPLAssert( NULL != poOutputSRS );
|
|
|
|
//
|
|
|
|
// poCT = OGRCreateCoordinateTransformation( poSourceSRS,
|
|
|
|
// poOutputSRS ); if( poCT == NULL )
|
|
|
|
// {
|
|
|
|
// char *pszWKT = NULL;
|
|
|
|
//
|
|
|
|
// printf("Failed to create coordinate transformation between
|
|
|
|
// the\n"
|
|
|
|
// "following coordinate systems. This may be because
|
|
|
|
// they\n" "are not transformable, or because projection
|
|
|
|
// services\n"
|
|
|
|
// "(PROJ.4 DLL/.so) could not be loaded.\n" );
|
|
|
|
//
|
|
|
|
// poSourceSRS->exportToPrettyWkt( &pszWKT, FALSE );
|
|
|
|
// printf( "Source:\n%s\n", pszWKT );
|
|
|
|
//
|
|
|
|
// poOutputSRS->exportToPrettyWkt( &pszWKT, FALSE );
|
|
|
|
// printf( "Target:\n%s\n", pszWKT );
|
|
|
|
// exit( 1 );
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Get other info. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// poFDefn = poSrcLayer->GetLayerDefn();
|
|
|
|
//
|
|
|
|
// if( poOutputSRS == NULL )
|
|
|
|
// poOutputSRS = poSrcLayer->GetSpatialRef();
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Find the layer. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// int iLayer = -1;
|
|
|
|
// poDstLayer = NULL;
|
|
|
|
//
|
|
|
|
// for( iLayer = 0; iLayer < poDstDS->GetLayerCount(); iLayer++ )
|
|
|
|
// {
|
|
|
|
// OGRLayer *poLayer = poDstDS->GetLayer(iLayer);
|
|
|
|
//
|
|
|
|
// if( poLayer != NULL
|
|
|
|
// && EQUAL(poLayer->GetLayerDefn()->GetName(),pszNewLayerName)
|
|
|
|
// )
|
|
|
|
// {
|
|
|
|
// poDstLayer = poLayer;
|
|
|
|
// break;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* If the user requested overwrite, and we have the layer in */
|
|
|
|
// /* question we need to delete it now so it will get recreated */
|
|
|
|
// /* (overwritten). */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// if( poDstLayer != NULL && bOverwrite )
|
|
|
|
// {
|
|
|
|
// if( poDstDS->DeleteLayer( iLayer ) != OGRERR_NONE )
|
|
|
|
// {
|
|
|
|
// fprintf( stderr,
|
|
|
|
// "DeleteLayer() failed when overwrite requested.\n"
|
|
|
|
// );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
// poDstLayer = NULL;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* If the layer does not exist, then create it. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// if( poDstLayer == NULL )
|
|
|
|
// {
|
|
|
|
// if( eGType == -2 )
|
|
|
|
// eGType = poFDefn->GetGeomType();
|
|
|
|
//
|
|
|
|
// if( !poDstDS->TestCapability( ODsCCreateLayer ) )
|
|
|
|
// {
|
|
|
|
// fprintf( stderr,
|
|
|
|
// "Layer %s not found, and CreateLayer not supported by
|
|
|
|
// driver.",
|
|
|
|
// pszNewLayerName );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// CPLErrorReset();
|
|
|
|
//
|
|
|
|
// poDstLayer = poDstDS->CreateLayer( pszNewLayerName, poOutputSRS,
|
|
|
|
// (OGRwkbGeometryType) eGType,
|
|
|
|
// papszLCO );
|
|
|
|
//
|
|
|
|
// if( poDstLayer == NULL )
|
|
|
|
// return FALSE;
|
|
|
|
//
|
|
|
|
// bAppend = FALSE;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Otherwise we will append to it, if append was requested. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// else if( !bAppend )
|
|
|
|
// {
|
|
|
|
// printf( "FAILED: Layer %s already exists, and -append not
|
|
|
|
// specified.\n"
|
|
|
|
// " Consider using -append, or -overwrite.\n",
|
|
|
|
// pszNewLayerName );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Add fields. Default to copy all field. */
|
|
|
|
// /* If only a subset of all fields requested, then output only */
|
|
|
|
// /* the selected fields, and in the order that they were */
|
|
|
|
// /* selected. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// int iField;
|
|
|
|
//
|
|
|
|
// if (papszSelFields && !bAppend )
|
|
|
|
// {
|
|
|
|
// for( iField=0; papszSelFields[iField] != NULL; iField++)
|
|
|
|
// {
|
|
|
|
// int iSrcField =
|
|
|
|
// poFDefn->GetFieldIndex(papszSelFields[iField]); if (iSrcField
|
|
|
|
// >= 0)
|
|
|
|
// poDstLayer->CreateField( poFDefn->GetFieldDefn(iSrcField)
|
|
|
|
// );
|
|
|
|
// else
|
|
|
|
// {
|
|
|
|
// printf( "Field '%s' not found in source layer.\n",
|
|
|
|
// papszSelFields[iField] );
|
|
|
|
// if( !bSkipFailures )
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// else if( !bAppend )
|
|
|
|
// {
|
|
|
|
// for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
|
|
|
|
// poDstLayer->CreateField( poFDefn->GetFieldDefn(iField) );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Transfer features. */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// OGRFeature *poFeature;
|
|
|
|
// int nFeaturesInTransaction = 0;
|
|
|
|
//
|
|
|
|
// poSrcLayer->ResetReading();
|
|
|
|
//
|
|
|
|
// if( nGroupTransactions )
|
|
|
|
// poDstLayer->StartTransaction();
|
|
|
|
//
|
|
|
|
// while( true )
|
|
|
|
// {
|
|
|
|
// OGRFeature *poDstFeature = NULL;
|
|
|
|
//
|
|
|
|
// if( nFIDToFetch != OGRNullFID )
|
|
|
|
// {
|
|
|
|
// // Only fetch feature on first pass.
|
|
|
|
// if( nFeaturesInTransaction == 0 )
|
|
|
|
// poFeature = poSrcLayer->GetFeature(nFIDToFetch);
|
|
|
|
// else
|
|
|
|
// poFeature = NULL;
|
|
|
|
// }
|
|
|
|
// else
|
|
|
|
// poFeature = poSrcLayer->GetNextFeature();
|
|
|
|
//
|
|
|
|
// if( poFeature == NULL )
|
|
|
|
// break;
|
|
|
|
//
|
|
|
|
// if( ++nFeaturesInTransaction == nGroupTransactions )
|
|
|
|
// {
|
|
|
|
// poDstLayer->CommitTransaction();
|
|
|
|
// poDstLayer->StartTransaction();
|
|
|
|
// nFeaturesInTransaction = 0;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// CPLErrorReset();
|
|
|
|
// poFDefn = poSrcLayer->GetLayerDefn();
|
|
|
|
//
|
|
|
|
// if( poDstFeature->SetFrom( poFeature, TRUE ) != OGRERR_NONE )
|
|
|
|
// {
|
|
|
|
// if( nGroupTransactions )
|
|
|
|
// poDstLayer->CommitTransaction();
|
|
|
|
//
|
|
|
|
// CPLError( CE_Failure, CPLE_AppDefined,
|
|
|
|
// "Unable to translate feature %d from layer %s.\n",
|
|
|
|
// poFeature->GetFID(), poFDefn->GetName() );
|
|
|
|
//
|
|
|
|
// OGRFeature::DestroyFeature( poFeature );
|
|
|
|
// OGRFeature::DestroyFeature( poDstFeature );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if( bPreserveFID )
|
|
|
|
// poDstFeature->SetFID( poFeature->GetFID() );
|
|
|
|
//
|
|
|
|
// if( poCT && poDstFeature->GetGeometryRef() != NULL )
|
|
|
|
// {
|
|
|
|
// eErr = poDstFeature->GetGeometryRef()->transform( poCT );
|
|
|
|
// if( eErr != OGRERR_NONE )
|
|
|
|
// {
|
|
|
|
// if( nGroupTransactions )
|
|
|
|
// poDstLayer->CommitTransaction();
|
|
|
|
//
|
|
|
|
// printf( "Failed to transform feature %d.\n",
|
|
|
|
// static_cast<int>(poFeature->GetFID()) );
|
|
|
|
// if( !bSkipFailures )
|
|
|
|
// {
|
|
|
|
// OGRFeature::DestroyFeature( poFeature );
|
|
|
|
// OGRFeature::DestroyFeature( poDstFeature );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if( poDstFeature->GetGeometryRef() != NULL && bForceToPolygon )
|
|
|
|
// {
|
|
|
|
// poDstFeature->SetGeometryDirectly(
|
|
|
|
// OGRGeometryFactory::forceToPolygon(
|
|
|
|
// poDstFeature->StealGeometry() ) );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if( poDstFeature->GetGeometryRef() != NULL &&
|
|
|
|
// bForceToMultiPolygon )
|
|
|
|
// {
|
|
|
|
// poDstFeature->SetGeometryDirectly(
|
|
|
|
// OGRGeometryFactory::forceToMultiPolygon(
|
|
|
|
// poDstFeature->StealGeometry() ) );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// OGRFeature::DestroyFeature( poFeature );
|
|
|
|
//
|
|
|
|
// CPLErrorReset();
|
|
|
|
// if( poDstLayer->CreateFeature( poDstFeature ) != OGRERR_NONE
|
|
|
|
// && !bSkipFailures )
|
|
|
|
// {
|
|
|
|
// if( nGroupTransactions )
|
|
|
|
// poDstLayer->RollbackTransaction();
|
|
|
|
//
|
|
|
|
// OGRFeature::DestroyFeature( poDstFeature );
|
|
|
|
// return FALSE;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// OGRFeature::DestroyFeature( poDstFeature );
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// if( nGroupTransactions )
|
|
|
|
// poDstLayer->CommitTransaction();
|
|
|
|
//
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// /* Cleaning */
|
|
|
|
// /* --------------------------------------------------------------------
|
|
|
|
// */
|
|
|
|
// delete poCT;
|
2022-05-14 03:28:14 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|