PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ SHPWriteObject()

int SHPAPI_CALL SHPWriteObject ( SHPHandle  psSHP,
int  nShapeId,
SHPObject psObject 
)

Definition at line 1170 of file shpopen.c.

References _SHPSetBounds(), SHPInfo::adBoundsMax, SHPInfo::adBoundsMin, SHPObject::bMeasureIsUsed, SHPInfo::bUpdated, ByteCopy, SHPObject::dfMMax, SHPObject::dfMMin, SHPObject::dfZMax, SHPObject::dfZMin, DISABLE_MULTIPATCH_MEASURE, SAHooks::Error, FALSE, SHPInfo::fpSHP, free(), SAHooks::FSeek, SAHooks::FWrite, malloc(), MAX, MIN, nEntitySize, SHPInfo::nFileSize, SHPInfo::nMaxRecords, SHPObject::nParts, SHPInfo::nRecords, nShapeId, SHPInfo::nShapeType, SHPObject::nSHPType, SHPObject::nVertices, SHPObject::padfM, SHPObject::padfX, SHPObject::padfY, SHPObject::padfZ, SHPObject::panPartStart, SHPObject::panPartType, SHPInfo::panRecOffset, SHPInfo::panRecSize, psShape, SfRealloc(), SHPInfo::sHooks, SHPAPI_CALL1, SHPReadObject(), SHPT_ARC, SHPT_ARCM, SHPT_ARCZ, SHPT_MULTIPATCH, SHPT_MULTIPOINT, SHPT_MULTIPOINTM, SHPT_MULTIPOINTZ, SHPT_NULL, SHPT_POINT, SHPT_POINTM, SHPT_POINTZ, SHPT_POLYGON, SHPT_POLYGONM, SHPT_POLYGONZ, SwapWord(), and TRUE.

Referenced by ShpLoaderGenerateShapeRow().

1172 {
1173  unsigned int nRecordOffset, nRecordSize=0;
1174  int i;
1175  uchar *pabyRec;
1176  int32 i32;
1177 
1178  psSHP->bUpdated = TRUE;
1179 
1180 /* -------------------------------------------------------------------- */
1181 /* Ensure that shape object matches the type of the file it is */
1182 /* being written to. */
1183 /* -------------------------------------------------------------------- */
1184  assert( psObject->nSHPType == psSHP->nShapeType
1185  || psObject->nSHPType == SHPT_NULL );
1186 
1187 /* -------------------------------------------------------------------- */
1188 /* Ensure that -1 is used for appends. Either blow an */
1189 /* assertion, or if they are disabled, set the shapeid to -1 */
1190 /* for appends. */
1191 /* -------------------------------------------------------------------- */
1192  assert( nShapeId == -1
1193  || (nShapeId >= 0 && nShapeId < psSHP->nRecords) );
1194 
1195  if( nShapeId != -1 && nShapeId >= psSHP->nRecords )
1196  nShapeId = -1;
1197 
1198 /* -------------------------------------------------------------------- */
1199 /* Add the new entity to the in memory index. */
1200 /* -------------------------------------------------------------------- */
1201  if( nShapeId == -1 && psSHP->nRecords+1 > psSHP->nMaxRecords )
1202  {
1203  psSHP->nMaxRecords =(int) ( psSHP->nMaxRecords * 1.3 + 100);
1204 
1205  psSHP->panRecOffset = (unsigned int *)
1206  SfRealloc(psSHP->panRecOffset,sizeof(unsigned int) * psSHP->nMaxRecords );
1207  psSHP->panRecSize = (unsigned int *)
1208  SfRealloc(psSHP->panRecSize,sizeof(unsigned int) * psSHP->nMaxRecords );
1209  }
1210 
1211 /* -------------------------------------------------------------------- */
1212 /* Initialize record. */
1213 /* -------------------------------------------------------------------- */
1214  pabyRec = (uchar *) malloc(psObject->nVertices * 4 * sizeof(double)
1215  + psObject->nParts * 8 + 128);
1216 
1217 /* -------------------------------------------------------------------- */
1218 /* Extract vertices for a Polygon or Arc. */
1219 /* -------------------------------------------------------------------- */
1220  if( psObject->nSHPType == SHPT_POLYGON
1221  || psObject->nSHPType == SHPT_POLYGONZ
1222  || psObject->nSHPType == SHPT_POLYGONM
1223  || psObject->nSHPType == SHPT_ARC
1224  || psObject->nSHPType == SHPT_ARCZ
1225  || psObject->nSHPType == SHPT_ARCM
1226  || psObject->nSHPType == SHPT_MULTIPATCH )
1227  {
1228  int32 nPoints, nParts;
1229  int i;
1230 
1231  nPoints = psObject->nVertices;
1232  nParts = psObject->nParts;
1233 
1234  _SHPSetBounds( pabyRec + 12, psObject );
1235 
1236  if( bBigEndian ) SwapWord( 4, &nPoints );
1237  if( bBigEndian ) SwapWord( 4, &nParts );
1238 
1239  ByteCopy( &nPoints, pabyRec + 40 + 8, 4 );
1240  ByteCopy( &nParts, pabyRec + 36 + 8, 4 );
1241 
1242  nRecordSize = 52;
1243 
1244  /*
1245  * Write part start positions.
1246  */
1247  ByteCopy( psObject->panPartStart, pabyRec + 44 + 8,
1248  4 * psObject->nParts );
1249  for( i = 0; i < psObject->nParts; i++ )
1250  {
1251  if( bBigEndian ) SwapWord( 4, pabyRec + 44 + 8 + 4*i );
1252  nRecordSize += 4;
1253  }
1254 
1255  /*
1256  * Write multipatch part types if needed.
1257  */
1258  if( psObject->nSHPType == SHPT_MULTIPATCH )
1259  {
1260  memcpy( pabyRec + nRecordSize, psObject->panPartType,
1261  4*psObject->nParts );
1262  for( i = 0; i < psObject->nParts; i++ )
1263  {
1264  if( bBigEndian ) SwapWord( 4, pabyRec + nRecordSize );
1265  nRecordSize += 4;
1266  }
1267  }
1268 
1269  /*
1270  * Write the (x,y) vertex values.
1271  */
1272  for( i = 0; i < psObject->nVertices; i++ )
1273  {
1274  ByteCopy( psObject->padfX + i, pabyRec + nRecordSize, 8 );
1275  ByteCopy( psObject->padfY + i, pabyRec + nRecordSize + 8, 8 );
1276 
1277  if( bBigEndian )
1278  SwapWord( 8, pabyRec + nRecordSize );
1279 
1280  if( bBigEndian )
1281  SwapWord( 8, pabyRec + nRecordSize + 8 );
1282 
1283  nRecordSize += 2 * 8;
1284  }
1285 
1286  /*
1287  * Write the Z coordinates (if any).
1288  */
1289  if( psObject->nSHPType == SHPT_POLYGONZ
1290  || psObject->nSHPType == SHPT_ARCZ
1291  || psObject->nSHPType == SHPT_MULTIPATCH )
1292  {
1293  ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
1294  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1295  nRecordSize += 8;
1296 
1297  ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
1298  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1299  nRecordSize += 8;
1300 
1301  for( i = 0; i < psObject->nVertices; i++ )
1302  {
1303  ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
1304  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1305  nRecordSize += 8;
1306  }
1307  }
1308 
1309  /*
1310  * Write the M values, if any.
1311  */
1312  if( psObject->bMeasureIsUsed
1313  && (psObject->nSHPType == SHPT_POLYGONM
1314  || psObject->nSHPType == SHPT_ARCM
1316  || psObject->nSHPType == SHPT_MULTIPATCH
1317 #endif
1318  || psObject->nSHPType == SHPT_POLYGONZ
1319  || psObject->nSHPType == SHPT_ARCZ) )
1320  {
1321  ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
1322  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1323  nRecordSize += 8;
1324 
1325  ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
1326  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1327  nRecordSize += 8;
1328 
1329  for( i = 0; i < psObject->nVertices; i++ )
1330  {
1331  ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
1332  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1333  nRecordSize += 8;
1334  }
1335  }
1336  }
1337 
1338 /* -------------------------------------------------------------------- */
1339 /* Extract vertices for a MultiPoint. */
1340 /* -------------------------------------------------------------------- */
1341  else if( psObject->nSHPType == SHPT_MULTIPOINT
1342  || psObject->nSHPType == SHPT_MULTIPOINTZ
1343  || psObject->nSHPType == SHPT_MULTIPOINTM )
1344  {
1345  int32 nPoints;
1346  int i;
1347 
1348  nPoints = psObject->nVertices;
1349 
1350  _SHPSetBounds( pabyRec + 12, psObject );
1351 
1352  if( bBigEndian ) SwapWord( 4, &nPoints );
1353  ByteCopy( &nPoints, pabyRec + 44, 4 );
1354 
1355  for( i = 0; i < psObject->nVertices; i++ )
1356  {
1357  ByteCopy( psObject->padfX + i, pabyRec + 48 + i*16, 8 );
1358  ByteCopy( psObject->padfY + i, pabyRec + 48 + i*16 + 8, 8 );
1359 
1360  if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 );
1361  if( bBigEndian ) SwapWord( 8, pabyRec + 48 + i*16 + 8 );
1362  }
1363 
1364  nRecordSize = 48 + 16 * psObject->nVertices;
1365 
1366  if( psObject->nSHPType == SHPT_MULTIPOINTZ )
1367  {
1368  ByteCopy( &(psObject->dfZMin), pabyRec + nRecordSize, 8 );
1369  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1370  nRecordSize += 8;
1371 
1372  ByteCopy( &(psObject->dfZMax), pabyRec + nRecordSize, 8 );
1373  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1374  nRecordSize += 8;
1375 
1376  for( i = 0; i < psObject->nVertices; i++ )
1377  {
1378  ByteCopy( psObject->padfZ + i, pabyRec + nRecordSize, 8 );
1379  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1380  nRecordSize += 8;
1381  }
1382  }
1383 
1384  if( psObject->bMeasureIsUsed
1385  && (psObject->nSHPType == SHPT_MULTIPOINTZ
1386  || psObject->nSHPType == SHPT_MULTIPOINTM) )
1387  {
1388  ByteCopy( &(psObject->dfMMin), pabyRec + nRecordSize, 8 );
1389  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1390  nRecordSize += 8;
1391 
1392  ByteCopy( &(psObject->dfMMax), pabyRec + nRecordSize, 8 );
1393  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1394  nRecordSize += 8;
1395 
1396  for( i = 0; i < psObject->nVertices; i++ )
1397  {
1398  ByteCopy( psObject->padfM + i, pabyRec + nRecordSize, 8 );
1399  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1400  nRecordSize += 8;
1401  }
1402  }
1403  }
1404 
1405 /* -------------------------------------------------------------------- */
1406 /* Write point. */
1407 /* -------------------------------------------------------------------- */
1408  else if( psObject->nSHPType == SHPT_POINT
1409  || psObject->nSHPType == SHPT_POINTZ
1410  || psObject->nSHPType == SHPT_POINTM )
1411  {
1412  ByteCopy( psObject->padfX, pabyRec + 12, 8 );
1413  ByteCopy( psObject->padfY, pabyRec + 20, 8 );
1414 
1415  if( bBigEndian ) SwapWord( 8, pabyRec + 12 );
1416  if( bBigEndian ) SwapWord( 8, pabyRec + 20 );
1417 
1418  nRecordSize = 28;
1419 
1420  if( psObject->nSHPType == SHPT_POINTZ )
1421  {
1422  ByteCopy( psObject->padfZ, pabyRec + nRecordSize, 8 );
1423  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1424  nRecordSize += 8;
1425  }
1426 
1427  if( psObject->bMeasureIsUsed
1428  && (psObject->nSHPType == SHPT_POINTZ
1429  || psObject->nSHPType == SHPT_POINTM) )
1430  {
1431  ByteCopy( psObject->padfM, pabyRec + nRecordSize, 8 );
1432  if( bBigEndian ) SwapWord( 8, pabyRec + nRecordSize );
1433  nRecordSize += 8;
1434  }
1435  }
1436 
1437 /* -------------------------------------------------------------------- */
1438 /* Not much to do for null geometries. */
1439 /* -------------------------------------------------------------------- */
1440  else if( psObject->nSHPType == SHPT_NULL )
1441  {
1442  nRecordSize = 12;
1443  }
1444 
1445  else
1446  {
1447  /* unknown type */
1448  assert( FALSE );
1449  }
1450 
1451 /* -------------------------------------------------------------------- */
1452 /* Establish where we are going to put this record. If we are */
1453 /* rewriting and existing record, and it will fit, then put it */
1454 /* back where the original came from. Otherwise write at the end. */
1455 /* -------------------------------------------------------------------- */
1456  if( nShapeId == -1 || psSHP->panRecSize[nShapeId] < nRecordSize-8 )
1457  {
1458  unsigned int nExpectedSize = psSHP->nFileSize + nRecordSize;
1459  if( nExpectedSize < psSHP->nFileSize ) /* due to unsigned int overflow */
1460  {
1461  char str[128];
1462  sprintf( str, "Failed to write shape object. "
1463  "File size cannot reach %u + %u.",
1464  psSHP->nFileSize, nRecordSize );
1465  psSHP->sHooks.Error( str );
1466  free( pabyRec );
1467  return -1;
1468  }
1469 
1470  if( nShapeId == -1 )
1471  nShapeId = psSHP->nRecords++;
1472 
1473  psSHP->panRecOffset[nShapeId] = nRecordOffset = psSHP->nFileSize;
1474  psSHP->panRecSize[nShapeId] = nRecordSize-8;
1475  psSHP->nFileSize += nRecordSize;
1476  }
1477  else
1478  {
1479  nRecordOffset = psSHP->panRecOffset[nShapeId];
1480  psSHP->panRecSize[nShapeId] = nRecordSize-8;
1481  }
1482 
1483 /* -------------------------------------------------------------------- */
1484 /* Set the shape type, record number, and record size. */
1485 /* -------------------------------------------------------------------- */
1486  i32 = nShapeId+1; /* record # */
1487  if( !bBigEndian ) SwapWord( 4, &i32 );
1488  ByteCopy( &i32, pabyRec, 4 );
1489 
1490  i32 = (nRecordSize-8)/2; /* record size */
1491  if( !bBigEndian ) SwapWord( 4, &i32 );
1492  ByteCopy( &i32, pabyRec + 4, 4 );
1493 
1494  i32 = psObject->nSHPType; /* shape type */
1495  if( bBigEndian ) SwapWord( 4, &i32 );
1496  ByteCopy( &i32, pabyRec + 8, 4 );
1497 
1498 /* -------------------------------------------------------------------- */
1499 /* Write out record. */
1500 /* -------------------------------------------------------------------- */
1501  if( psSHP->sHooks.FSeek( psSHP->fpSHP, nRecordOffset, 0 ) != 0 )
1502  {
1503  psSHP->sHooks.Error( "Error in psSHP->sHooks.FSeek() while writing object to .shp file." );
1504  free( pabyRec );
1505  return -1;
1506  }
1507  if( psSHP->sHooks.FWrite( pabyRec, nRecordSize, 1, psSHP->fpSHP ) < 1 )
1508  {
1509  psSHP->sHooks.Error( "Error in psSHP->sHooks.Fwrite() while writing object to .shp file." );
1510  free( pabyRec );
1511  return -1;
1512  }
1513 
1514  free( pabyRec );
1515 
1516 /* -------------------------------------------------------------------- */
1517 /* Expand file wide bounds based on this shape. */
1518 /* -------------------------------------------------------------------- */
1519  if( psSHP->adBoundsMin[0] == 0.0
1520  && psSHP->adBoundsMax[0] == 0.0
1521  && psSHP->adBoundsMin[1] == 0.0
1522  && psSHP->adBoundsMax[1] == 0.0 )
1523  {
1524  if( psObject->nSHPType == SHPT_NULL || psObject->nVertices == 0 )
1525  {
1526  psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = 0.0;
1527  psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = 0.0;
1528  psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = 0.0;
1529  psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = 0.0;
1530  }
1531  else
1532  {
1533  psSHP->adBoundsMin[0] = psSHP->adBoundsMax[0] = psObject->padfX[0];
1534  psSHP->adBoundsMin[1] = psSHP->adBoundsMax[1] = psObject->padfY[0];
1535  psSHP->adBoundsMin[2] = psSHP->adBoundsMax[2] = psObject->padfZ[0];
1536  psSHP->adBoundsMin[3] = psSHP->adBoundsMax[3] = psObject->padfM[0];
1537  }
1538  }
1539 
1540  for( i = 0; i < psObject->nVertices; i++ )
1541  {
1542  psSHP->adBoundsMin[0] = MIN(psSHP->adBoundsMin[0],psObject->padfX[i]);
1543  psSHP->adBoundsMin[1] = MIN(psSHP->adBoundsMin[1],psObject->padfY[i]);
1544  psSHP->adBoundsMin[2] = MIN(psSHP->adBoundsMin[2],psObject->padfZ[i]);
1545  psSHP->adBoundsMin[3] = MIN(psSHP->adBoundsMin[3],psObject->padfM[i]);
1546  psSHP->adBoundsMax[0] = MAX(psSHP->adBoundsMax[0],psObject->padfX[i]);
1547  psSHP->adBoundsMax[1] = MAX(psSHP->adBoundsMax[1],psObject->padfY[i]);
1548  psSHP->adBoundsMax[2] = MAX(psSHP->adBoundsMax[2],psObject->padfZ[i]);
1549  psSHP->adBoundsMax[3] = MAX(psSHP->adBoundsMax[3],psObject->padfM[i]);
1550  }
1551 
1552  return( nShapeId );
1553 }
#define SHPT_MULTIPATCH
Definition: shapefil.h:319
#define SHPT_ARCM
Definition: shapefil.h:316
unsigned int int32
Definition: shpopen.c:273
double adBoundsMin[4]
Definition: shapefil.h:292
unsigned int nFileSize
Definition: shapefil.h:285
int * panPartStart
Definition: shapefil.h:345
static void * SfRealloc(void *pMem, int nNewSize)
Definition: shpopen.c:323
#define SHPT_POLYGONM
Definition: shapefil.h:317
int nVertices
Definition: shapefil.h:348
#define ByteCopy(a, b, c)
Definition: shpopen.c:281
double dfZMax
Definition: shapefil.h:361
double dfZMin
Definition: shapefil.h:356
#define DISABLE_MULTIPATCH_MEASURE
Definition: shapefil.h:166
double * padfX
Definition: shapefil.h:349
#define SHPT_MULTIPOINT
Definition: shapefil.h:310
#define SHPT_POLYGON
Definition: shapefil.h:309
#define SHPT_MULTIPOINTZ
Definition: shapefil.h:314
#define MIN(a, b)
Definition: shpopen.c:283
double * padfY
Definition: shapefil.h:350
int nRecords
Definition: shapefil.h:287
#define SHPT_ARCZ
Definition: shapefil.h:312
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition: shapefil.h:257
#define FALSE
Definition: shpopen.c:277
unsigned int * panRecOffset
Definition: shapefil.h:289
static int bBigEndian
Definition: shpopen.c:293
SAHooks sHooks
Definition: shapefil.h:278
#define MAX(a, b)
Definition: shpopen.c:284
int bMeasureIsUsed
Definition: shapefil.h:364
int nParts
Definition: shapefil.h:344
int nMaxRecords
Definition: shapefil.h:288
#define SHPT_MULTIPOINTM
Definition: shapefil.h:318
double adBoundsMax[4]
Definition: shapefil.h:293
#define SHPT_POINTZ
Definition: shapefil.h:311
#define SHPT_POINTM
Definition: shapefil.h:315
#define SHPT_POLYGONZ
Definition: shapefil.h:313
#define SHPT_POINT
Definition: shapefil.h:307
#define SHPT_NULL
Definition: shapefil.h:306
unsigned int * panRecSize
Definition: shapefil.h:290
static void _SHPSetBounds(uchar *pabyRec, SHPObject *psShape)
Definition: shpopen.c:974
psObject nShapeId
Definition: shpopen.c:1048
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
Definition: shapefil.h:258
double * padfZ
Definition: shapefil.h:351
void free(void *)
void * malloc(YYSIZE_T)
double dfMMax
Definition: shapefil.h:362
int nSHPType
Definition: shapefil.h:340
int bUpdated
Definition: shapefil.h:295
double * padfM
Definition: shapefil.h:352
#define SHPT_ARC
Definition: shapefil.h:308
double dfMMin
Definition: shapefil.h:357
#define TRUE
Definition: shpopen.c:278
static void SwapWord(int length, void *wordP)
Definition: shpopen.c:302
unsigned char uchar
Definition: shpopen.c:268
void(* Error)(const char *message)
Definition: shapefil.h:264
int nShapeType
Definition: shapefil.h:283
SAFile fpSHP
Definition: shapefil.h:280
int * panPartType
Definition: shapefil.h:346
Here is the call graph for this function:
Here is the caller graph for this function: