PostGIS  2.1.10dev-r@@SVN_REVISION@@
int SHPAPI_CALL SHPWriteObject ( SHPHandle  psSHP,
int  nShapeId,
SHPObject psObject 
)

Definition at line 1171 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, SAHooks::FSeek, SAHooks::FWrite, MAX, MIN, 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, SfRealloc(), SHPInfo::sHooks, 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().

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

Here is the call graph for this function:

Here is the caller graph for this function: