OGRGeometry *OGRLinearRing::clone() const { OGRLinearRing *poNewLinearRing = new OGRLinearRing(); poNewLinearRing->assignSpatialReference( getSpatialReference() ); poNewLinearRing->setPoints( nPointCount, paoPoints, padfZ, padfM ); poNewLinearRing->flags = flags; return poNewLinearRing; }
OGRErr OGRPolygon::importFromWKTListOnly( char ** ppszInput, int bHasZ, int bHasM, OGRRawPoint*& paoPoints, int& nMaxPoints, double*& padfZ ) { char szToken[OGR_WKT_TOKEN_MAX] = {}; const char *pszInput = *ppszInput; // Skip first '('. pszInput = OGRWktReadToken( pszInput, szToken ); if( EQUAL(szToken, "EMPTY") ) { *ppszInput = (char*) pszInput; return OGRERR_NONE; } if( !EQUAL(szToken, "(") ) return OGRERR_CORRUPT_DATA; /* ==================================================================== */ /* Read each ring in turn. Note that we try to reuse the same */ /* point list buffer from ring to ring to cut down on */ /* allocate/deallocate overhead. */ /* ==================================================================== */ int nMaxRings = 0; double *padfM = NULL; do { const char* pszNext = OGRWktReadToken( pszInput, szToken ); if( EQUAL(szToken, "EMPTY") ) { /* -------------------------------------------------------------------- */ /* Do we need to grow the ring array? */ /* -------------------------------------------------------------------- */ if( oCC.nCurveCount == nMaxRings ) { nMaxRings = nMaxRings * 2 + 1; oCC.papoCurves = static_cast<OGRCurve **>( CPLRealloc(oCC.papoCurves, nMaxRings * sizeof(OGRLinearRing*))); } oCC.papoCurves[oCC.nCurveCount] = new OGRLinearRing(); oCC.nCurveCount++; pszInput = OGRWktReadToken( pszNext, szToken ); if( !EQUAL(szToken, ",") ) break; continue; } /* -------------------------------------------------------------------- */ /* Read points for one ring from input. */ /* -------------------------------------------------------------------- */ int nPoints = 0; int flagsFromInput = flags; if( flagsFromInput == 0 ) { // Flags was not set, this is not called by us. if( bHasM ) flagsFromInput |= OGR_G_MEASURED; if( bHasZ ) flagsFromInput |= OGR_G_3D; } pszInput = OGRWktReadPointsM( pszInput, &paoPoints, &padfZ, &padfM, &flagsFromInput, &nMaxPoints, &nPoints ); if( pszInput == NULL || nPoints == 0 ) { CPLFree(padfM); return OGRERR_CORRUPT_DATA; } if( (flagsFromInput & OGR_G_3D) && !(flags & OGR_G_3D) ) { flags |= OGR_G_3D; bHasZ = TRUE; } if( (flagsFromInput & OGR_G_MEASURED) && !(flags & OGR_G_MEASURED) ) { flags |= OGR_G_MEASURED; bHasM = TRUE; } /* -------------------------------------------------------------------- */ /* Do we need to grow the ring array? */ /* -------------------------------------------------------------------- */ if( oCC.nCurveCount == nMaxRings ) { nMaxRings = nMaxRings * 2 + 1; oCC.papoCurves = static_cast<OGRCurve **>( CPLRealloc(oCC.papoCurves, nMaxRings * sizeof(OGRLinearRing*))); } /* -------------------------------------------------------------------- */ /* Create the new ring, and assign to ring list. */ /* -------------------------------------------------------------------- */ OGRLinearRing* poLR = new OGRLinearRing(); oCC.papoCurves[oCC.nCurveCount] = poLR; if( bHasM && bHasZ ) poLR->setPoints(nPoints, paoPoints, padfZ, padfM); else if( bHasM ) poLR->setPointsM(nPoints, paoPoints, padfM); else if( bHasZ ) poLR->setPoints(nPoints, paoPoints, padfZ); else poLR->setPoints(nPoints, paoPoints); oCC.nCurveCount++; /* -------------------------------------------------------------------- */ /* Read the delimiter following the ring. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); } while( szToken[0] == ',' ); CPLFree( padfM ); /* -------------------------------------------------------------------- */ /* freak if we don't get a closing bracket. */ /* -------------------------------------------------------------------- */ if( szToken[0] != ')' ) return OGRERR_CORRUPT_DATA; *ppszInput = const_cast<char *>(pszInput); return OGRERR_NONE; }
OGRFeature *OGRIdrisiLayer::GetNextRawFeature() { while(TRUE) { if (eGeomType == wkbPoint) { double dfId; double dfX, dfY; if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfX, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfY, sizeof(double), 1, fp) != 1) { return NULL; } CPL_LSBPTR64(&dfId); CPL_LSBPTR64(&dfX); CPL_LSBPTR64(&dfY); if (m_poFilterGeom != NULL && (dfX < m_sFilterEnvelope.MinX || dfX > m_sFilterEnvelope.MaxX || dfY < m_sFilterEnvelope.MinY || dfY > m_sFilterEnvelope.MaxY)) { nNextFID ++; continue; } OGRPoint* poGeom = new OGRPoint(dfX, dfY); if (poSRS) poGeom->assignSpatialReference(poSRS); OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetField(0, dfId); poFeature->SetFID(nNextFID ++); poFeature->SetGeometryDirectly(poGeom); ReadAVLLine(poFeature); return poFeature; } else if (eGeomType == wkbLineString) { double dfId; double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape; unsigned int nNodes; if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1) { return NULL; } CPL_LSBPTR64(&dfId); CPL_LSBPTR64(&dfMinXShape); CPL_LSBPTR64(&dfMaxXShape); CPL_LSBPTR64(&dfMinYShape); CPL_LSBPTR64(&dfMaxYShape); if (VSIFReadL(&nNodes, sizeof(unsigned int), 1, fp) != 1) { return NULL; } CPL_LSBPTR32(&nNodes); if (nNodes > 100 * 1000 * 1000) return NULL; if (m_poFilterGeom != NULL && (dfMaxXShape < m_sFilterEnvelope.MinX || dfMinXShape > m_sFilterEnvelope.MaxX || dfMaxYShape < m_sFilterEnvelope.MinY || dfMinYShape > m_sFilterEnvelope.MaxY)) { nNextFID ++; VSIFSeekL(fp, sizeof(OGRRawPoint) * nNodes, SEEK_CUR); continue; } OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nNodes); if (poRawPoints == NULL) { return NULL; } if ((unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes) { VSIFree(poRawPoints); return NULL; } #if defined(CPL_MSB) for(unsigned int iNode=0; iNode<nNodes; iNode++) { CPL_LSBPTR64(&poRawPoints[iNode].x); CPL_LSBPTR64(&poRawPoints[iNode].y); } #endif OGRLineString* poGeom = new OGRLineString(); poGeom->setPoints(nNodes, poRawPoints, NULL); VSIFree(poRawPoints); if (poSRS) poGeom->assignSpatialReference(poSRS); OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetField(0, dfId); poFeature->SetFID(nNextFID ++); poFeature->SetGeometryDirectly(poGeom); ReadAVLLine(poFeature); return poFeature; } else /* if (eGeomType == wkbPolygon) */ { double dfId; double dfMinXShape, dfMaxXShape, dfMinYShape, dfMaxYShape; unsigned int nParts; unsigned int nTotalNodes; if (VSIFReadL(&dfId, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMinXShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMaxXShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMinYShape, sizeof(double), 1, fp) != 1 || VSIFReadL(&dfMaxYShape, sizeof(double), 1, fp) != 1) { return NULL; } CPL_LSBPTR64(&dfId); CPL_LSBPTR64(&dfMinXShape); CPL_LSBPTR64(&dfMaxXShape); CPL_LSBPTR64(&dfMinYShape); CPL_LSBPTR64(&dfMaxYShape); if (VSIFReadL(&nParts, sizeof(unsigned int), 1, fp) != 1 || VSIFReadL(&nTotalNodes, sizeof(unsigned int), 1, fp) != 1) { return NULL; } CPL_LSBPTR32(&nParts); CPL_LSBPTR32(&nTotalNodes); if (nParts > 100000 || nTotalNodes > 100 * 1000 * 1000) return NULL; if (m_poFilterGeom != NULL && (dfMaxXShape < m_sFilterEnvelope.MinX || dfMinXShape > m_sFilterEnvelope.MaxX || dfMaxYShape < m_sFilterEnvelope.MinY || dfMinYShape > m_sFilterEnvelope.MaxY)) { VSIFSeekL(fp, sizeof(unsigned int) * nParts + sizeof(OGRRawPoint) * nTotalNodes, SEEK_CUR); nNextFID ++; continue; } OGRRawPoint* poRawPoints = (OGRRawPoint*)VSIMalloc2(sizeof(OGRRawPoint), nTotalNodes); if (poRawPoints == NULL) { return NULL; } unsigned int* panNodesCount = NULL; if( nParts > 1 ) { panNodesCount = (unsigned int *)CPLMalloc(sizeof(unsigned int) * nParts); if (VSIFReadL(panNodesCount, sizeof(unsigned int) * nParts, 1, fp) != 1) { VSIFree(poRawPoints); VSIFree(panNodesCount); return NULL; } #if defined(CPL_MSB) for(unsigned int iPart=0; iPart < nParts; iPart ++) { CPL_LSBPTR32(&panNodesCount[iPart]); } #endif } else { unsigned int nNodes; if (VSIFReadL(&nNodes, sizeof(unsigned int) * nParts, 1, fp) != 1) { VSIFree(poRawPoints); return NULL; } CPL_LSBPTR32(&nNodes); if( nNodes != nTotalNodes ) { VSIFree(poRawPoints); return NULL; } } unsigned int iPart; OGRPolygon* poGeom = new OGRPolygon(); for(iPart = 0; iPart < nParts; iPart ++) { unsigned int nNodes = (nParts > 1) ? panNodesCount[iPart] : nTotalNodes; if (nNodes > nTotalNodes || (unsigned int)VSIFReadL(poRawPoints, sizeof(OGRRawPoint), nNodes, fp) != nNodes) { VSIFree(poRawPoints); VSIFree(panNodesCount); delete poGeom; return NULL; } #if defined(CPL_MSB) for(unsigned int iNode=0; iNode<nNodes; iNode++) { CPL_LSBPTR64(&poRawPoints[iNode].x); CPL_LSBPTR64(&poRawPoints[iNode].y); } #endif OGRLinearRing* poLR = new OGRLinearRing(); poGeom->addRingDirectly(poLR); poLR->setPoints(nNodes, poRawPoints, NULL); } VSIFree(poRawPoints); VSIFree(panNodesCount); if (poSRS) poGeom->assignSpatialReference(poSRS); OGRFeature* poFeature = new OGRFeature(poFeatureDefn); poFeature->SetField(0, dfId); poFeature->SetFID(nNextFID ++); poFeature->SetGeometryDirectly(poGeom); ReadAVLLine(poFeature); return poFeature; } } }
OGRFeature * OGRSDTSLayer::GetNextUnfilteredFeature() { /* -------------------------------------------------------------------- */ /* If not done before we need to assemble the geometry for a */ /* polygon layer. */ /* -------------------------------------------------------------------- */ if( poTransfer->GetLayerType(iLayer) == SLTPoly ) { ((SDTSPolygonReader *) poReader)->AssembleRings(poTransfer,iLayer); } /* -------------------------------------------------------------------- */ /* Fetch the next sdts style feature object from the reader. */ /* -------------------------------------------------------------------- */ SDTSFeature *poSDTSFeature = poReader->GetNextFeature(); OGRFeature *poFeature; if( poSDTSFeature == NULL ) return NULL; /* -------------------------------------------------------------------- */ /* Create the OGR feature. */ /* -------------------------------------------------------------------- */ poFeature = new OGRFeature( poFeatureDefn ); m_nFeaturesRead++; switch( poTransfer->GetLayerType(iLayer) ) { /* -------------------------------------------------------------------- */ /* Translate point feature specific information and geometry. */ /* -------------------------------------------------------------------- */ case SLTPoint: { SDTSRawPoint *poPoint = (SDTSRawPoint *) poSDTSFeature; poFeature->SetGeometryDirectly( new OGRPoint( poPoint->dfX, poPoint->dfY, poPoint->dfZ ) ); } break; /* -------------------------------------------------------------------- */ /* Translate line feature specific information and geometry. */ /* -------------------------------------------------------------------- */ case SLTLine: { SDTSRawLine *poLine = (SDTSRawLine *) poSDTSFeature; OGRLineString *poOGRLine = new OGRLineString(); poOGRLine->setPoints( poLine->nVertices, poLine->padfX, poLine->padfY, poLine->padfZ ); poFeature->SetGeometryDirectly( poOGRLine ); poFeature->SetField( "SNID", (int) poLine->oStartNode.nRecord ); poFeature->SetField( "ENID", (int) poLine->oEndNode.nRecord ); } break; /* -------------------------------------------------------------------- */ /* Translate polygon feature specific information and geometry. */ /* -------------------------------------------------------------------- */ case SLTPoly: { SDTSRawPolygon *poPoly = (SDTSRawPolygon *) poSDTSFeature; OGRPolygon *poOGRPoly = new OGRPolygon(); for( int iRing = 0; iRing < poPoly->nRings; iRing++ ) { OGRLinearRing *poRing = new OGRLinearRing(); int nVertices; if( iRing == poPoly->nRings - 1 ) nVertices = poPoly->nVertices - poPoly->panRingStart[iRing]; else nVertices = poPoly->panRingStart[iRing+1] - poPoly->panRingStart[iRing]; poRing->setPoints( nVertices, poPoly->padfX + poPoly->panRingStart[iRing], poPoly->padfY + poPoly->panRingStart[iRing], poPoly->padfZ + poPoly->panRingStart[iRing] ); poOGRPoly->addRingDirectly( poRing ); } poFeature->SetGeometryDirectly( poOGRPoly ); } break; default: break; } /* -------------------------------------------------------------------- */ /* Set attributes for any indicated attribute records. */ /* -------------------------------------------------------------------- */ int iAttrRecord; for( iAttrRecord = 0; iAttrRecord < poSDTSFeature->nAttributes; iAttrRecord++) { DDFField *poSR; poSR = poTransfer->GetAttr( poSDTSFeature->paoATID+iAttrRecord ); if( poSR != NULL ) AssignAttrRecordToFeature( poFeature, poTransfer, poSR ); } /* -------------------------------------------------------------------- */ /* If this record is an attribute record, attach the local */ /* attributes. */ /* -------------------------------------------------------------------- */ if( poTransfer->GetLayerType(iLayer) == SLTAttr ) { AssignAttrRecordToFeature( poFeature, poTransfer, ((SDTSAttrRecord *) poSDTSFeature)->poATTR); } /* -------------------------------------------------------------------- */ /* Translate the record id. */ /* -------------------------------------------------------------------- */ poFeature->SetFID( poSDTSFeature->oModId.nRecord ); poFeature->SetField( 0, (int) poSDTSFeature->oModId.nRecord ); if( poFeature->GetGeometryRef() != NULL ) poFeature->GetGeometryRef()->assignSpatialReference( poDS->GetSpatialRef() ); if( !poReader->IsIndexed() ) delete poSDTSFeature; return poFeature; }
OGRErr OGRMultiPolygon::importFromWkt( char ** ppszInput ) { char szToken[OGR_WKT_TOKEN_MAX]; const char *pszInput = *ppszInput; OGRErr eErr = OGRERR_NONE; /* -------------------------------------------------------------------- */ /* Clear existing rings. */ /* -------------------------------------------------------------------- */ empty(); /* -------------------------------------------------------------------- */ /* Read and verify the MULTIPOLYGON keyword token. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); if( !EQUAL(szToken,getGeometryName()) ) return OGRERR_CORRUPT_DATA; /* -------------------------------------------------------------------- */ /* The next character should be a ( indicating the start of the */ /* list of polygons. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); if( EQUAL(szToken,"EMPTY") ) { *ppszInput = (char *) pszInput; return OGRERR_NONE; } if( szToken[0] != '(' ) return OGRERR_CORRUPT_DATA; /* -------------------------------------------------------------------- */ /* If the next token is EMPTY, then verify that we have proper */ /* EMPTY format will a trailing closing bracket. */ /* -------------------------------------------------------------------- */ OGRWktReadToken( pszInput, szToken ); if( EQUAL(szToken,"EMPTY") ) { pszInput = OGRWktReadToken( pszInput, szToken ); pszInput = OGRWktReadToken( pszInput, szToken ); *ppszInput = (char *) pszInput; if( !EQUAL(szToken,")") ) return OGRERR_CORRUPT_DATA; else return OGRERR_NONE; } /* ==================================================================== */ /* Read each polygon in turn. Note that we try to reuse the same */ /* point list buffer from ring to ring to cut down on */ /* allocate/deallocate overhead. */ /* ==================================================================== */ OGRRawPoint *paoPoints = NULL; int nMaxPoints = 0; double *padfZ = NULL; do { OGRPolygon *poPolygon = new OGRPolygon(); /* -------------------------------------------------------------------- */ /* The next character should be a ( indicating the start of the */ /* list of polygons. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); if( szToken[0] != '(' ) { eErr = OGRERR_CORRUPT_DATA; delete poPolygon; break; } /* -------------------------------------------------------------------- */ /* Loop over each ring in this polygon. */ /* -------------------------------------------------------------------- */ do { int nPoints = 0; /* -------------------------------------------------------------------- */ /* Read points for one line from input. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints, &nPoints ); if( pszInput == NULL ) { eErr = OGRERR_CORRUPT_DATA; break; } /* -------------------------------------------------------------------- */ /* Create the new line, and add to collection. */ /* -------------------------------------------------------------------- */ OGRLinearRing *poLine; poLine = new OGRLinearRing(); poLine->setPoints( nPoints, paoPoints, padfZ ); poPolygon->addRingDirectly( poLine ); /* -------------------------------------------------------------------- */ /* Read the delimeter following the ring. */ /* -------------------------------------------------------------------- */ pszInput = OGRWktReadToken( pszInput, szToken ); } while( szToken[0] == ',' && eErr == OGRERR_NONE ); /* -------------------------------------------------------------------- */ /* Verify that we have a closing bracket. */ /* -------------------------------------------------------------------- */ if( eErr == OGRERR_NONE ) { if( szToken[0] != ')' ) eErr = OGRERR_CORRUPT_DATA; else pszInput = OGRWktReadToken( pszInput, szToken ); } /* -------------------------------------------------------------------- */ /* Add the polygon to the MULTIPOLYGON. */ /* -------------------------------------------------------------------- */ if( eErr == OGRERR_NONE ) eErr = addGeometryDirectly( poPolygon ); else delete poPolygon; } while( szToken[0] == ',' && eErr == OGRERR_NONE ); /* -------------------------------------------------------------------- */ /* freak if we don't get a closing bracket. */ /* -------------------------------------------------------------------- */ CPLFree( paoPoints ); CPLFree( padfZ ); if( eErr != OGRERR_NONE ) return eErr; if( szToken[0] != ')' ) return OGRERR_CORRUPT_DATA; *ppszInput = (char *) pszInput; return OGRERR_NONE; }
OGRGeometry *OGRGRASSLayer::GetFeatureGeometry ( long nFeatureId, int *cat ) { CPLDebug ( "GRASS", "OGRGRASSLayer::GetFeatureGeometry nFeatureId = %d", nFeatureId ); int cidx = paFeatureIndex[(int)nFeatureId]; int type, id; Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, cat, &type, &id ); //CPLDebug ( "GRASS", "cat = %d type = %d id = %d", *cat, type, id ); OGRGeometry *poOGR = NULL; int bIs3D = Vect_is_3d(poMap); switch ( type ) { case GV_POINT: { Vect_read_line ( poMap, poPoints, poCats, id); if (bIs3D) poOGR = new OGRPoint( poPoints->x[0], poPoints->y[0], poPoints->z[0] ); else poOGR = new OGRPoint( poPoints->x[0], poPoints->y[0] ); } break; case GV_LINE: case GV_BOUNDARY: { Vect_read_line ( poMap, poPoints, poCats, id); OGRLineString *poOGRLine = new OGRLineString(); if (bIs3D) poOGRLine->setPoints( poPoints->n_points, poPoints->x, poPoints->y, poPoints->z ); else poOGRLine->setPoints( poPoints->n_points, poPoints->x, poPoints->y ); poOGR = poOGRLine; } break; case GV_AREA: { Vect_get_area_points ( poMap, id, poPoints ); OGRPolygon *poOGRPoly; poOGRPoly = new OGRPolygon(); OGRLinearRing *poRing; poRing = new OGRLinearRing(); if (bIs3D) poRing->setPoints( poPoints->n_points, poPoints->x, poPoints->y, poPoints->z ); else poRing->setPoints( poPoints->n_points, poPoints->x, poPoints->y ); poOGRPoly->addRingDirectly( poRing ); // Islands int nisles = Vect_get_area_num_isles ( poMap, id ); for ( int i = 0; i < nisles; i++ ) { int isle = Vect_get_area_isle ( poMap, id, i ); Vect_get_isle_points ( poMap, isle, poPoints ); poRing = new OGRLinearRing(); if (bIs3D) poRing->setPoints( poPoints->n_points, poPoints->x, poPoints->y, poPoints->z ); else poRing->setPoints( poPoints->n_points, poPoints->x, poPoints->y ); poOGRPoly->addRingDirectly( poRing ); } poOGR = poOGRPoly; } break; default: // Should not happen { CPLError( CE_Failure, CPLE_AppDefined, "Unknown GRASS feature type."); return NULL; } } return poOGR; }
OGRErr OGRPGeoLayer::createFromShapeBin( GByte *pabyShape, OGRGeometry **ppoGeom, int nBytes ) { *ppoGeom = NULL; if( nBytes < 1 ) return OGRERR_FAILURE; int nSHPType = pabyShape[0]; // CPLDebug( "PGeo", // "Shape type read from PGeo data is nSHPType = %d", // nSHPType ); /* -------------------------------------------------------------------- */ /* type 50 appears to just be an alias for normal line */ /* strings. (#1484) */ /* Type 51 appears to just be an alias for normal polygon. (#3100) */ /* TODO: These types include additional attributes including */ /* non-linear segments and such. They should be handled. */ /* -------------------------------------------------------------------- */ switch( nSHPType ) { case 50: nSHPType = SHPT_ARC; break; case 51: nSHPType = SHPT_POLYGON; break; case 52: nSHPType = SHPT_POINT; break; case 53: nSHPType = SHPT_MULTIPOINT; break; case 54: nSHPType = SHPT_MULTIPATCH; } /* ==================================================================== */ /* Extract vertices for a Polygon or Arc. */ /* ==================================================================== */ if( nSHPType == SHPT_ARC || nSHPType == SHPT_ARCZ || nSHPType == SHPT_ARCM || nSHPType == SHPT_ARCZM || nSHPType == SHPT_POLYGON || nSHPType == SHPT_POLYGONZ || nSHPType == SHPT_POLYGONM || nSHPType == SHPT_POLYGONZM || nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM) { GInt32 nPoints, nParts; int i, nOffset; GInt32 *panPartStart; if (nBytes < 44) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Extract part/point count, and build vertex and part arrays */ /* to proper size. */ /* -------------------------------------------------------------------- */ memcpy( &nPoints, pabyShape + 40, 4 ); memcpy( &nParts, pabyShape + 36, 4 ); CPL_LSBPTR32( &nPoints ); CPL_LSBPTR32( &nParts ); if (nPoints < 0 || nParts < 0 || nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.", nPoints, nParts); return OGRERR_FAILURE; } int bHasZ = ( nSHPType == SHPT_POLYGONZ || nSHPType == SHPT_POLYGONZM || nSHPType == SHPT_ARCZ || nSHPType == SHPT_ARCZM || nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM ); int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM ); /* With the previous checks on nPoints and nParts, */ /* we should not overflow here and after */ /* since 50 M * (16 + 8 + 8) = 1 600 MB */ int nRequiredSize = 44 + 4 * nParts + 16 * nPoints; if ( bHasZ ) { nRequiredSize += 16 + 8 * nPoints; } if( bIsMultiPatch ) { nRequiredSize += 4 * nParts; } if (nRequiredSize > nBytes) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d", nPoints, nParts, nBytes, nSHPType); return OGRERR_FAILURE; } panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32)); if (panPartStart == NULL) { CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts); return OGRERR_FAILURE; } /* -------------------------------------------------------------------- */ /* Copy out the part array from the record. */ /* -------------------------------------------------------------------- */ memcpy( panPartStart, pabyShape + 44, 4 * nParts ); for( i = 0; i < nParts; i++ ) { CPL_LSBPTR32( panPartStart + i ); /* We check that the offset is inside the vertex array */ if (panPartStart[i] < 0 || panPartStart[i] >= nPoints) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d", i, panPartStart[i], nPoints); CPLFree(panPartStart); return OGRERR_FAILURE; } if (i > 0 && panPartStart[i] <= panPartStart[i-1]) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d", i, panPartStart[i], i - 1, panPartStart[i - 1]); CPLFree(panPartStart); return OGRERR_FAILURE; } } nOffset = 44 + 4*nParts; /* -------------------------------------------------------------------- */ /* If this is a multipatch, we will also have parts types. For */ /* now we ignore and skip past them. */ /* -------------------------------------------------------------------- */ if( bIsMultiPatch ) nOffset += 4*nParts; /* -------------------------------------------------------------------- */ /* Copy out the vertices from the record. */ /* -------------------------------------------------------------------- */ double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints); double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints); double *padfZ = (double *) VSICalloc(sizeof(double),nPoints); if (padfX == NULL || padfY == NULL || padfZ == NULL) { CPLFree( panPartStart ); CPLFree( padfX ); CPLFree( padfY ); CPLFree( padfZ ); CPLError(CE_Failure, CPLE_OutOfMemory, "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts); return OGRERR_FAILURE; } for( i = 0; i < nPoints; i++ ) { memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 ); memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 ); CPL_LSBPTR64( padfX + i ); CPL_LSBPTR64( padfY + i ); } nOffset += 16*nPoints; /* -------------------------------------------------------------------- */ /* If we have a Z coordinate, collect that now. */ /* -------------------------------------------------------------------- */ if( bHasZ ) { for( i = 0; i < nPoints; i++ ) { memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 ); CPL_LSBPTR64( padfZ + i ); } nOffset += 16 + 8*nPoints; } /* -------------------------------------------------------------------- */ /* Build corresponding OGR objects. */ /* -------------------------------------------------------------------- */ if( nSHPType == SHPT_ARC || nSHPType == SHPT_ARCZ || nSHPType == SHPT_ARCM || nSHPType == SHPT_ARCZM ) { /* -------------------------------------------------------------------- */ /* Arc - As LineString */ /* -------------------------------------------------------------------- */ if( nParts == 1 ) { OGRLineString *poLine = new OGRLineString(); *ppoGeom = poLine; poLine->setPoints( nPoints, padfX, padfY, padfZ ); } /* -------------------------------------------------------------------- */ /* Arc - As MultiLineString */ /* -------------------------------------------------------------------- */ else { OGRMultiLineString *poMulti = new OGRMultiLineString; *ppoGeom = poMulti; for( i = 0; i < nParts; i++ ) { OGRLineString *poLine = new OGRLineString; int nVerticesInThisPart; if( i == nParts-1 ) nVerticesInThisPart = nPoints - panPartStart[i]; else nVerticesInThisPart = panPartStart[i+1] - panPartStart[i]; poLine->setPoints( nVerticesInThisPart, padfX + panPartStart[i], padfY + panPartStart[i], padfZ + panPartStart[i] ); poMulti->addGeometryDirectly( poLine ); } } } /* ARC */ /* -------------------------------------------------------------------- */ /* Polygon */ /* -------------------------------------------------------------------- */ else if( nSHPType == SHPT_POLYGON || nSHPType == SHPT_POLYGONZ || nSHPType == SHPT_POLYGONM || nSHPType == SHPT_POLYGONZM ) { OGRPolygon *poMulti = new OGRPolygon; *ppoGeom = poMulti; for( i = 0; i < nParts; i++ ) { OGRLinearRing *poRing = new OGRLinearRing; int nVerticesInThisPart; if( i == nParts-1 ) nVerticesInThisPart = nPoints - panPartStart[i]; else nVerticesInThisPart = panPartStart[i+1] - panPartStart[i]; poRing->setPoints( nVerticesInThisPart, padfX + panPartStart[i], padfY + panPartStart[i], padfZ + panPartStart[i] ); poMulti->addRingDirectly( poRing ); } } /* polygon */ /* -------------------------------------------------------------------- */ /* Multipatch */ /* -------------------------------------------------------------------- */ else if( bIsMultiPatch ) { /* return to this later */ } CPLFree( panPartStart ); CPLFree( padfX ); CPLFree( padfY ); CPLFree( padfZ ); if( !bHasZ ) (*ppoGeom)->setCoordinateDimension( 2 ); return OGRERR_NONE; } /* ==================================================================== */ /* Extract vertices for a MultiPoint. */ /* ==================================================================== */ else if( nSHPType == SHPT_MULTIPOINT || nSHPType == SHPT_MULTIPOINTM || nSHPType == SHPT_MULTIPOINTZ || nSHPType == SHPT_MULTIPOINTZM ) { #ifdef notdef int32 nPoints; int i, nOffset; memcpy( &nPoints, psSHP->pabyRec + 44, 4 ); if( bBigEndian ) SwapWord( 4, &nPoints ); psShape->nVertices = nPoints; psShape->padfX = (double *) calloc(nPoints,sizeof(double)); psShape->padfY = (double *) calloc(nPoints,sizeof(double)); psShape->padfZ = (double *) calloc(nPoints,sizeof(double)); psShape->padfM = (double *) calloc(nPoints,sizeof(double)); for( i = 0; i < nPoints; i++ ) { memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 ); memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 ); if( bBigEndian ) SwapWord( 8, psShape->padfX + i ); if( bBigEndian ) SwapWord( 8, psShape->padfY + i ); } nOffset = 48 + 16*nPoints; /* -------------------------------------------------------------------- */ /* Get the X/Y bounds. */ /* -------------------------------------------------------------------- */ memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 + 4, 8 ); memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 ); memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 ); memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 ); if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) ); if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) ); if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) ); if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) ); /* -------------------------------------------------------------------- */ /* If we have a Z coordinate, collect that now. */ /* -------------------------------------------------------------------- */ if( psShape->nSHPType == SHPT_MULTIPOINTZ || psShape->nSHPType == SHPT_MULTIPOINTZM ) { memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 ); memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 ); if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) ); if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) ); for( i = 0; i < nPoints; i++ ) { memcpy( psShape->padfZ + i, psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, psShape->padfZ + i ); } nOffset += 16 + 8*nPoints; } /* -------------------------------------------------------------------- */ /* If we have a M measure value, then read it now. We assume */ /* that the measure can be present for any shape if the size is */ /* big enough, but really it will only occur for the Z shapes */ /* (options), and the M shapes. */ /* -------------------------------------------------------------------- */ if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints ) { memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 ); memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 ); if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) ); if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) ); for( i = 0; i < nPoints; i++ ) { memcpy( psShape->padfM + i, psSHP->pabyRec + nOffset + 16 + i*8, 8 ); if( bBigEndian ) SwapWord( 8, psShape->padfM + i ); } } #endif } /* ==================================================================== */ /* Extract vertices for a point. */ /* ==================================================================== */ else if( nSHPType == SHPT_POINT || nSHPType == SHPT_POINTM || nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM ) { int nOffset; double dfX, dfY, dfZ = 0; int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM); if (nBytes < 4 + 8 + 8 + ((nSHPType == SHPT_POINTZ) ? 8 : 0)) { CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType); return OGRERR_FAILURE; } memcpy( &dfX, pabyShape + 4, 8 ); memcpy( &dfY, pabyShape + 4 + 8, 8 ); CPL_LSBPTR64( &dfX ); CPL_LSBPTR64( &dfY ); nOffset = 20 + 8; if( bHasZ ) { memcpy( &dfZ, pabyShape + 4 + 16, 8 ); CPL_LSBPTR64( &dfZ ); } *ppoGeom = new OGRPoint( dfX, dfY, dfZ ); if( !bHasZ ) (*ppoGeom)->setCoordinateDimension( 2 ); return OGRERR_NONE; } char* pszHex = CPLBinaryToHex( nBytes, pabyShape ); CPLDebug( "PGEO", "Unsupported geometry type:%d\nnBytes=%d, hex=%s", nSHPType, nBytes, pszHex ); CPLFree(pszHex); return OGRERR_FAILURE; }