PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ SHPWriteObject()

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

Definition at line 1170 of file shpopen.c.

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 str(s)
void * malloc(YYSIZE_T)
void free(void *)
#define SHPT_ARCZ
Definition shapefil.h:312
#define SHPT_MULTIPATCH
Definition shapefil.h:319
#define SHPT_NULL
Definition shapefil.h:306
#define SHPT_ARCM
Definition shapefil.h:316
#define SHPT_POLYGONM
Definition shapefil.h:317
#define SHPT_ARC
Definition shapefil.h:308
#define SHPT_POLYGON
Definition shapefil.h:309
#define DISABLE_MULTIPATCH_MEASURE
Definition shapefil.h:166
#define SHPT_MULTIPOINT
Definition shapefil.h:310
#define SHPT_POINTZ
Definition shapefil.h:311
#define SHPT_MULTIPOINTZ
Definition shapefil.h:314
#define SHPT_MULTIPOINTM
Definition shapefil.h:318
#define SHPT_POINTM
Definition shapefil.h:315
#define SHPT_POINT
Definition shapefil.h:307
#define SHPT_POLYGONZ
Definition shapefil.h:313
static void * SfRealloc(void *pMem, int nNewSize)
Definition shpopen.c:323
static int bBigEndian
Definition shpopen.c:293
psObject nShapeId
Definition shpopen.c:1048
unsigned int int32
Definition shpopen.c:273
#define MIN(a, b)
Definition shpopen.c:283
unsigned char uchar
Definition shpopen.c:268
static void SwapWord(int length, void *wordP)
Definition shpopen.c:302
#define TRUE
Definition shpopen.c:278
#define FALSE
Definition shpopen.c:277
static void _SHPSetBounds(uchar *pabyRec, SHPObject *psShape)
Definition shpopen.c:974
#define ByteCopy(a, b, c)
Definition shpopen.c:281
#define MAX(a, b)
Definition shpopen.c:284
void(* Error)(const char *message)
Definition shapefil.h:264
SAOffset(* FWrite)(void *p, SAOffset size, SAOffset nmemb, SAFile file)
Definition shapefil.h:257
SAOffset(* FSeek)(SAFile file, SAOffset offset, int whence)
Definition shapefil.h:258
int nShapeType
Definition shapefil.h:283
SAFile fpSHP
Definition shapefil.h:280
int nMaxRecords
Definition shapefil.h:288
unsigned int * panRecSize
Definition shapefil.h:290
SAHooks sHooks
Definition shapefil.h:278
double adBoundsMin[4]
Definition shapefil.h:292
int nRecords
Definition shapefil.h:287
int bUpdated
Definition shapefil.h:295
unsigned int nFileSize
Definition shapefil.h:285
unsigned int * panRecOffset
Definition shapefil.h:289
double adBoundsMax[4]
Definition shapefil.h:293
int * panPartType
Definition shapefil.h:346
double dfZMin
Definition shapefil.h:356
double dfZMax
Definition shapefil.h:361
int bMeasureIsUsed
Definition shapefil.h:364
int * panPartStart
Definition shapefil.h:345
double dfMMin
Definition shapefil.h:357
int nSHPType
Definition shapefil.h:340
int nVertices
Definition shapefil.h:348
double dfMMax
Definition shapefil.h:362
double * padfZ
Definition shapefil.h:351
double * padfX
Definition shapefil.h:349
int nParts
Definition shapefil.h:344
double * padfM
Definition shapefil.h:352
double * padfY
Definition shapefil.h:350

References _SHPSetBounds(), SHPInfo::adBoundsMax, SHPInfo::adBoundsMin, bBigEndian, 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, 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, str, SwapWord(), and TRUE.

Referenced by ShpLoaderGenerateShapeRow().

Here is the call graph for this function:
Here is the caller graph for this function: