void
PCLoaderArcView::load(const std::string& file, OptionsCont& oc, PCPolyContainer& toFill,
                      PCTypeMap&) {
#ifdef HAVE_GDAL
    GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing();
    // get defaults
    std::string prefix = oc.getString("prefix");
    std::string type = oc.getString("type");
    RGBColor color = RGBColor::parseColor(oc.getString("color"));
    int layer = oc.getInt("layer");
    std::string idField = oc.getString("shapefile.id-column");
    bool useRunningID = oc.getBool("shapefile.use-running-id");
    // start parsing
    std::string shpName = file + ".shp";
    OGRRegisterAll();
    OGRDataSource* poDS = OGRSFDriverRegistrar::Open(shpName.c_str(), FALSE);
    if (poDS == NULL) {
        throw ProcessError("Could not open shape description '" + shpName + "'.");
    }

    // begin file parsing
    OGRLayer*  poLayer = poDS->GetLayer(0);
    poLayer->ResetReading();

    // build coordinate transformation
    OGRSpatialReference* origTransf = poLayer->GetSpatialRef();
    OGRSpatialReference destTransf;
    // use wgs84 as destination
    destTransf.SetWellKnownGeogCS("WGS84");
    OGRCoordinateTransformation* poCT = OGRCreateCoordinateTransformation(origTransf, &destTransf);
    if (poCT == NULL) {
        if (oc.isSet("shapefile.guess-projection")) {
            OGRSpatialReference origTransf2;
            origTransf2.SetWellKnownGeogCS("WGS84");
            poCT = OGRCreateCoordinateTransformation(&origTransf2, &destTransf);
        }
        if (poCT == 0) {
            WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed.");
        }
    }

    OGRFeature* poFeature;
    poLayer->ResetReading();
    unsigned int runningID = 0;
    while ((poFeature = poLayer->GetNextFeature()) != NULL) {
        // read in edge attributes
        std::string id = useRunningID ? toString(runningID) : poFeature->GetFieldAsString(idField.c_str());
        ++runningID;
        id = StringUtils::prune(id);
        if (id == "") {
            throw ProcessError("Missing id under '" + idField + "'");
        }
        id = prefix + id;
        // read in the geometry
        OGRGeometry* poGeometry = poFeature->GetGeometryRef();
        if (poGeometry == 0) {
            OGRFeature::DestroyFeature(poFeature);
            continue;
        }
        // try transform to wgs84
        poGeometry->transform(poCT);
        OGRwkbGeometryType gtype = poGeometry->getGeometryType();
        switch (gtype) {
            case wkbPoint: {
                OGRPoint* cgeom = (OGRPoint*) poGeometry;
                Position pos((SUMOReal) cgeom->getX(), (SUMOReal) cgeom->getY());
                if (!geoConvHelper.x2cartesian(pos)) {
                    WRITE_ERROR("Unable to project coordinates for POI '" + id + "'.");
                }
                PointOfInterest* poi = new PointOfInterest(id, type, color, pos, (SUMOReal)layer);
                if (!toFill.insert(id, poi, layer)) {
                    WRITE_ERROR("POI '" + id + "' could not be added.");
                    delete poi;
                }
            }
            break;
            case wkbLineString: {
                OGRLineString* cgeom = (OGRLineString*) poGeometry;
                PositionVector shape;
                for (int j = 0; j < cgeom->getNumPoints(); j++) {
                    Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j));
                    if (!geoConvHelper.x2cartesian(pos)) {
                        WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'.");
                    }
                    shape.push_back_noDoublePos(pos);
                }
                Polygon* poly = new Polygon(id, type, color, shape, false, (SUMOReal)layer);
                if (!toFill.insert(id, poly, layer)) {
                    WRITE_ERROR("Polygon '" + id + "' could not be added.");
                    delete poly;
                }
            }
            break;
            case wkbPolygon: {
                OGRLinearRing* cgeom = ((OGRPolygon*) poGeometry)->getExteriorRing();
                PositionVector shape;
                for (int j = 0; j < cgeom->getNumPoints(); j++) {
                    Position pos((SUMOReal) cgeom->getX(j), (SUMOReal) cgeom->getY(j));
                    if (!geoConvHelper.x2cartesian(pos)) {
                        WRITE_ERROR("Unable to project coordinates for polygon '" + id + "'.");
                    }
                    shape.push_back_noDoublePos(pos);
                }
                Polygon* poly = new Polygon(id, type, color, shape, true, (SUMOReal)layer);
                if (!toFill.insert(id, poly, layer)) {
                    WRITE_ERROR("Polygon '" + id + "' could not be added.");
                    delete poly;
                }
            }
            break;
            case wkbMultiPoint: {
                OGRMultiPoint* cgeom = (OGRMultiPoint*) poGeometry;
                for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
                    OGRPoint* cgeom2 = (OGRPoint*) cgeom->getGeometryRef(i);
                    Position pos((SUMOReal) cgeom2->getX(), (SUMOReal) cgeom2->getY());
                    std::string tid = id + "#" + toString(i);
                    if (!geoConvHelper.x2cartesian(pos)) {
                        WRITE_ERROR("Unable to project coordinates for POI '" + tid + "'.");
                    }
                    PointOfInterest* poi = new PointOfInterest(tid, type, color, pos, (SUMOReal)layer);
                    if (!toFill.insert(tid, poi, layer)) {
                        WRITE_ERROR("POI '" + tid + "' could not be added.");
                        delete poi;
                    }
                }
            }
            break;
            case wkbMultiLineString: {
                OGRMultiLineString* cgeom = (OGRMultiLineString*) poGeometry;
                for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
                    OGRLineString* cgeom2 = (OGRLineString*) cgeom->getGeometryRef(i);
                    PositionVector shape;
                    std::string tid = id + "#" + toString(i);
                    for (int j = 0; j < cgeom2->getNumPoints(); j++) {
                        Position pos((SUMOReal) cgeom2->getX(j), (SUMOReal) cgeom2->getY(j));
                        if (!geoConvHelper.x2cartesian(pos)) {
                            WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'.");
                        }
                        shape.push_back_noDoublePos(pos);
                    }
                    Polygon* poly = new Polygon(tid, type, color, shape, false, (SUMOReal)layer);
                    if (!toFill.insert(tid, poly, layer)) {
                        WRITE_ERROR("Polygon '" + tid + "' could not be added.");
                        delete poly;
                    }
                }
            }
            break;
            case wkbMultiPolygon: {
                OGRMultiPolygon* cgeom = (OGRMultiPolygon*) poGeometry;
                for (int i = 0; i < cgeom->getNumGeometries(); ++i) {
                    OGRLinearRing* cgeom2 = ((OGRPolygon*) cgeom->getGeometryRef(i))->getExteriorRing();
                    PositionVector shape;
                    std::string tid = id + "#" + toString(i);
                    for (int j = 0; j < cgeom2->getNumPoints(); j++) {
                        Position pos((SUMOReal) cgeom2->getX(j), (SUMOReal) cgeom2->getY(j));
                        if (!geoConvHelper.x2cartesian(pos)) {
                            WRITE_ERROR("Unable to project coordinates for polygon '" + tid + "'.");
                        }
                        shape.push_back_noDoublePos(pos);
                    }
                    Polygon* poly = new Polygon(tid, type, color, shape, true, (SUMOReal)layer);
                    if (!toFill.insert(tid, poly, layer)) {
                        WRITE_ERROR("Polygon '" + tid + "' could not be added.");
                        delete poly;
                    }
                }
            }
            break;
            default:
                WRITE_WARNING("Unsupported shape type occured (id='" + id + "').");
                break;
        }
        OGRFeature::DestroyFeature(poFeature);
    }
    PROGRESS_DONE_MESSAGE();
#else
    WRITE_ERROR("SUMO was compiled without GDAL support.");
#endif
}
bool ShpReader::Open(std::wstring fullPath, StudyControllerPtr studyController,
                     VectorMapControllerPtr vectorMapController, ProgressDlgPtr progressDlg) 
{
	// Registers all format drivers built into GDAL/OGR.
	OGRRegisterAll();

	OGRDataSource *OGRDataset;

	// Open vector file path
	std::string tempStr( fullPath.begin(), fullPath.end() );
	OGRDataset = OGRSFDriverRegistrar::Open( tempStr.c_str(), FALSE );

	// Return if no vector files are found
	if( OGRDataset == NULL )
	{
		Log::Inst().Warning("(Warning) Failed to open file at " + tempStr + ".");
		return false;
	}
	if ( App::Inst().GetLayerTreeController()->GetNumMapLayers() >0 )

		MapControllerPtr mapController= App::Inst().GetLayerTreeController()->GetLayerTreeModel()->GetStudy(0)->GetMapLayer(0)->GetMapController();

	// It appears that shapefiles (*.SHP) only support up to one layer per file
	// This will need to be further investigated for other vector filetypes (e.g., KML)
	// For now just grab layer at position 0
	
	OGRLayer *poLayer = OGRDataset->GetLayer( 0 );
	
	// Determine the XY boundaries for the entire vector dataset
	OGREnvelope psEnvelope;

	VectorMapModelPtr vectorMapModel = vectorMapController->GetVectorMapModel();
	poLayer->GetExtent( &psEnvelope );
	vectorMapModel->SetVectorBoundary(psEnvelope);

	if(!SetupVectorProjection(OGRDataset,studyController,poLayer,vectorMapController ))
	{
		OGRDataset->DestroyDataSource(OGRDataset);
		return false;
	}
	
	if(progressDlg)
	{
			if(!progressDlg->Update(0, _T("Reading Vector Map Information...")))
			{
				OGRDataset->DestroyDataSource(OGRDataset);
				return false;
			}
	}	
	GLdouble minX, minY, maxX, maxY;
	minX = minY = std::numeric_limits<float>::max();
	maxX = maxY = -std::numeric_limits<float>::max();

	// Retrieve features from the dataset
	OGRFeature *poFeature;
	poLayer->ResetReading();
	int numFeatures = poLayer->GetFeatureCount();
	int count=0;
    //Log::Inst().Write("Loading shapefile with the following meta data:");

	while ( ( poFeature = poLayer->GetNextFeature() ) != NULL )
	{
		/////////////////////////////////////////////////
		// PHASE 1: Retrieve METADATA from the dataset //
		/////////////////////////////////////////////////
		OGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();
		int iField;

		for( iField = 0; iField < poFDefn->GetFieldCount(); iField++ )
		{
			OGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField );

			//if( poFieldDefn->GetType() == OFTInteger )
			//    printf( "%d,", poFeature->GetFieldAsInteger( iField ) );
			//else if( poFieldDefn->GetType() == OFTReal )
			//    printf( "%.3f,", poFeature->GetFieldAsDouble(iField) );
			//else if( poFieldDefn->GetType() == OFTString )
			//    printf( "%s,", poFeature->GetFieldAsString(iField) );
			//else
			//    printf( "%s,", poFeature->GetFieldAsString(iField) );

			//ofs << poFeature->GetFieldAsString(iField) << ",";

			std::string metaData = poFeature->GetFieldAsString(iField);
			// do something with the meta data...
			//Log::Inst().Write(metaData);
		}
		count++;
		if(progressDlg)
		{
			if(!progressDlg->Update(int(50 + (float(count)/numFeatures)*50)))
				return false;
		}

		///////////////////////////////////////////////////
		// PHASE 2: Retrieve GEOMETRIES from the dataset //
		///////////////////////////////////////////////////
		OGRGeometry *poGeometry;
		poGeometry = poFeature->GetGeometryRef();

		// Move to the next feature in the set if no geometry present
		if( poGeometry == NULL )
		{
			OGRFeature::DestroyFeature( poFeature );
			continue;
		}

		OGRwkbGeometryType whatisit = poGeometry->getGeometryType();

		// Handle POINTS
		if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbPoint )
		{
			GeoVector* geoVector = new GeoVector();
			OGRPoint *poPoint = (OGRPoint *) poGeometry;

			geoVector->SetGeometryType( wkbPoint );
			geoVector->SetNumberOfPoints( 1 );
			if(needProjection)
			{
				double x,y;
				x= poPoint->getX();
				y= poPoint->getY();
				if(!poTransform->Transform(1, &x, &y))
				{
					Log::Inst().Warning("(Warning) Failed to project vector map.");
					OGRDataset->DestroyDataSource(OGRDataset);
					return false;
				}
				
				// project and store the points
				geoVector->pointX[0] = x;
				geoVector->pointY[0] = y;

				if(x < minX) minX=x;
				if(y < minY) minY=y;
				if(x > maxX) maxX=x;
				if(y > maxY) maxY=y;
			}
			else 			
			{
				geoVector->pointX[0] = poPoint->getX();
				geoVector->pointY[0] = poPoint->getY();

			}
			vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );
			
		}
		//Handle MultiPoint
		else if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbMultiPoint )
		{
			OGRMultiPoint *poMultiPoint = (OGRMultiPoint *) poGeometry;

			for ( int currGeometry = 0; currGeometry < poMultiPoint->getNumGeometries(); currGeometry++ )
			{
				GeoVector* geoVector = new GeoVector();				
				OGRPoint *poPoint = ( OGRPoint* )poMultiPoint->getGeometryRef( currGeometry );			
				geoVector->SetGeometryType( wkbPoint );
				geoVector->SetNumberOfPoints( 1 );
				if(needProjection)
				{
					double x,y;
					x= poPoint->getX();
					y= poPoint->getY();
					if(!poTransform->Transform(1, &x, &y))
					{
						Log::Inst().Warning("(Warning) Failed to project vector map.");
						OGRDataset->DestroyDataSource(OGRDataset);
						return false;
					}
					
					// project and store the points
					geoVector->pointX[0] = x;
					geoVector->pointY[0] = y;

					if(x < minX) minX=x;
					if(y < minY) minY=y;
					if(x > maxX) maxX=x;
					if(y > maxY) maxY=y;
				}
				else 			
				{
					geoVector->pointX[0] = poPoint->getX();
					geoVector->pointY[0] = poPoint->getY();

				}
				vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );
			}
			
		}

		//Handle Polylines
		else if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbLineString )
		{
			GeoVector* geoVector = new GeoVector();
			OGRLineString  *poLine = (OGRLineString  *) poGeometry;

			geoVector->SetGeometryType( wkbLineString );
			geoVector->SetNumberOfPoints( poLine->getNumPoints() );

			// Convert and store the points

			for ( int currentPoint = 0; currentPoint < poLine->getNumPoints(); currentPoint++ )
			{
				// Convert and store the points

				if(needProjection)
				{
					double x,y;
					x= poLine->getX( currentPoint );
					y= poLine->getY( currentPoint );
					if(!poTransform->Transform(1, &x, &y))
					{
						Log::Inst().Warning("(Warning) Failed to project vector map.");
						OGRDataset->DestroyDataSource(OGRDataset);
						return false;
					}
				
					// project and store the points
					geoVector->pointX[currentPoint] = x;
					geoVector->pointY[currentPoint] = y;

					if(x < minX) minX=x;
					if(y < minY) minY=y;
					if(x > maxX) maxX=x;
					if(y > maxY) maxY=y;
				}
				else			
				{
					geoVector->pointX[currentPoint] = poLine->getX( currentPoint );
					geoVector->pointY[currentPoint] = poLine->getY( currentPoint );

				}

			}

			vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );			
		}
		
		// Handle MultiPolyLine
		else if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbMultiLineString )
		{
			OGRMultiLineString *poMultiLine = (OGRMultiLineString *) poGeometry;

			for ( int currGeometry = 0; currGeometry < poMultiLine->getNumGeometries(); currGeometry++ )
			{
				GeoVector* geoVector = new GeoVector();
				
				OGRLineString *poLine = ( OGRLineString* )poMultiLine->getGeometryRef( currGeometry );

				geoVector->SetGeometryType( wkbLineString );
				geoVector->SetNumberOfPoints( poLine->getNumPoints() );				

				for ( int currentPoint = 0; currentPoint < poLine ->getNumPoints(); currentPoint++ )
				{

					 if(needProjection)
					{
						double x,y;
						x= poLine->getX( currentPoint );
						y= poLine->getY( currentPoint );
						if(!poTransform->Transform(1, &x, &y))
						{
							Log::Inst().Warning("(Warning) Failed to project vector map.");
							OGRDataset->DestroyDataSource(OGRDataset);
							return false;
						}
				
					// project and store the points
						geoVector->pointX[currentPoint] = x;
						geoVector->pointY[currentPoint] = y;

						if(x < minX) minX=x;
						if(y < minY) minY=y;
						if(x > maxX) maxX=x;
						if(y > maxY) maxY=y;
					}
					else			
					{
						geoVector->pointX[currentPoint] = poLine->getX( currentPoint );
						geoVector->pointY[currentPoint] = poLine->getY( currentPoint );

					}				
					
				}
				vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );				
				
			}
		}

		// Handle POLYGONS
		else if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbPolygon )
		{
			GeoVector* geoVector = new GeoVector();

			OGRPolygon    *poPolygon    = ( OGRPolygon* )poGeometry;
			OGRLinearRing *poLinearRing = poPolygon->getExteriorRing();

			geoVector->SetGeometryType( wkbLinearRing );
			geoVector->SetNumberOfPoints( poLinearRing->getNumPoints() );

			for ( int currentPoint = 0; currentPoint < poLinearRing->getNumPoints(); currentPoint++ )
			{
				if(needProjection)
				{
					double x,y;
					x= poLinearRing->getX( currentPoint );
					y= poLinearRing->getY( currentPoint );
					if(!poTransform->Transform(1, &x, &y))
					{
						Log::Inst().Warning("(Warning) Failed to project vector map.");
						OGRDataset->DestroyDataSource(OGRDataset);
						return false;
					}
				
					// project and store the points
					geoVector->pointX[currentPoint] = x;
					geoVector->pointY[currentPoint] = y;

					if(x < minX) minX=x;
					if(y < minY) minY=y;
					if(x > maxX) maxX=x;
					if(y > maxY) maxY=y;
				}
				else 			
				{
					geoVector->pointX[currentPoint] = poLinearRing->getX( currentPoint );
					geoVector->pointY[currentPoint] = poLinearRing->getY( currentPoint );

				}
			}

			vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );			
		}

		// Handle MULTIPOLYGONS
		else if ( wkbFlatten( poGeometry->getGeometryType() ) == wkbMultiPolygon )
		{
			OGRMultiPolygon *poMultiPolygon = (OGRMultiPolygon *) poGeometry;

			for ( int currGeometry = 0; currGeometry < poMultiPolygon->getNumGeometries(); currGeometry++ )
			{
				GeoVector* geoVector = new GeoVector();

				// OGRPolygon http://www.gdal.org/ogr/classOGRPolygon.html
				OGRPolygon *poPolygon = ( OGRPolygon* )poMultiPolygon->getGeometryRef( currGeometry );

				// Retrieve the EXTERNAL ring of the multipolygon
				OGRLinearRing *poLinearRing = poPolygon->getExteriorRing();

				geoVector->SetGeometryType( wkbLinearRing );
				geoVector->SetNumberOfPoints( poLinearRing->getNumPoints() );

				for ( int currentPoint = 0; currentPoint < poLinearRing->getNumPoints(); currentPoint++ )
				{

					 if(needProjection)
					{
						double x,y;
						x= poLinearRing->getX( currentPoint );
						y= poLinearRing->getY( currentPoint );
						if(!poTransform->Transform(1, &x, &y))
						{
							Log::Inst().Warning("(Warning) Failed to project vector map.");
							OGRDataset->DestroyDataSource(OGRDataset);
							return false;
						}
				
					// project and store the points
						geoVector->pointX[currentPoint] = x;
						geoVector->pointY[currentPoint] = y;

						if(x < minX) minX=x;
						if(y < minY) minY=y;
						if(x > maxX) maxX=x;
						if(y > maxY) maxY=y;
					}
					else			
					{
						geoVector->pointX[currentPoint] = poLinearRing->getX( currentPoint );
						geoVector->pointY[currentPoint] = poLinearRing->getY( currentPoint );

					}				
					
				}
				vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector );				
				
				// Retrieve all the INTERNAL rings of the multipolygon
				for ( int currentRing = 0; currentRing < poPolygon->getNumInteriorRings(); currentRing++ )
				{
					GeoVector* geoVector2 = new GeoVector();

					poLinearRing = poPolygon->getInteriorRing( currentRing );

					geoVector2->SetGeometryType( wkbLinearRing );
					geoVector2->SetNumberOfPoints( poLinearRing->getNumPoints() );

					for ( int currentPoint = 0; currentPoint < poLinearRing->getNumPoints(); currentPoint++ )
					{
						
						 if(needProjection)
						{
							double x,y;
							x= poLinearRing->getX( currentPoint );
							y= poLinearRing->getY( currentPoint );
							if(!poTransform->Transform(1, &x, &y))
							{
								Log::Inst().Warning("(Warning) Failed to project vector map.");
								OGRDataset->DestroyDataSource(OGRDataset);
								return false;
							}
				
						// project and store the points
							geoVector2->pointX[currentPoint] = x;
							geoVector2->pointY[currentPoint] = y;

							if(x < minX) minX=x;
							if(y < minY) minY=y;
							if(x > maxX) maxX=x;
							if(y > maxY) maxY=y;
						}
						else 		
						{
							geoVector2->pointX[currentPoint] = poLinearRing->getX( currentPoint );
							geoVector2->pointY[currentPoint] = poLinearRing->getY( currentPoint );

						}		
					}

					vectorMapController->GetVectorMapModel()->AddGeoVector( geoVector2 );
				}
			}
		}


		// Report a warning message for unhandled geometries
		else
		{
			Log::Inst().Warning("(Warning) Could not load vector data: unsupported geometry.");
		}
		OGRFeature::DestroyFeature( poFeature );
	}

	if (float(minX) == float(maxX) && float(minY) == float(maxY))
	{
		Log::Inst().Warning("(Warning) Failed to project vector map.");
		OGRDataset->DestroyDataSource(OGRDataset);
		return false;
	}

	if(needProjection)
	{
		vectorMapModel->SetVectorBoundary_MinX(minX);
		vectorMapModel->SetVectorBoundary_MaxX(maxX);
		vectorMapModel->SetVectorBoundary_MinY(minY);
		vectorMapModel->SetVectorBoundary_MaxY(maxY);
	}	
	
	if(!SetupVectorScaling(vectorMapModel,progressDlg))
	{ 
		OGRDataset->DestroyDataSource(OGRDataset);
		return false;
	}

	VectorMetaDataInfo(OGRDataset, studyController, vectorMapController);
	OGRDataSource::DestroyDataSource( OGRDataset );
	return true;
}
Example #3
0
OGRFeature *OGRGmtLayer::GetNextRawFeature()

{
#if 0
    int bMultiVertex =
        poFeatureDefn->GetGeomType() != wkbPoint
        && poFeatureDefn->GetGeomType() != wkbUnknown;
#endif
    CPLString osFieldData;
    OGRGeometry *poGeom = NULL;

/* -------------------------------------------------------------------- */
/*      Read lines associated with this feature.                        */
/* -------------------------------------------------------------------- */
    for( ; true; ReadLine() )
    {
        if( osLine.length() == 0 )
            break;

        if( osLine[0] == '>' )
        {
            if( poGeom != NULL
                && wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon )
            {
                OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom;
                if( ScanAheadForHole() )
                {
                    // Add a hole to the current polygon.
                    ((OGRPolygon *) poMP->getGeometryRef(
                        poMP->getNumGeometries()-1 ))->
                        addRingDirectly( new OGRLinearRing() );
                }
                else if( !NextIsFeature() )
                {
                    OGRPolygon *poPoly = new OGRPolygon();

                    poPoly->addRingDirectly( new OGRLinearRing() );

                    poMP->addGeometryDirectly( poPoly );
                }
                else
                    break; /* done geometry */
            }
            else if( poGeom != NULL
                     && wkbFlatten(poGeom->getGeometryType()) == wkbPolygon)
            {
                if( ScanAheadForHole() )
                    ((OGRPolygon *)poGeom)->
                        addRingDirectly( new OGRLinearRing() );
                else
                    break; /* done geometry */
            }
            else if( poGeom != NULL
                     && (wkbFlatten(poGeom->getGeometryType())
                         == wkbMultiLineString)
                     && !NextIsFeature() )
            {
                ((OGRMultiLineString *) poGeom)->
                    addGeometryDirectly( new OGRLineString() );
            }
            else if( poGeom != NULL )
            {
                break;
            }
            else if( poFeatureDefn->GetGeomType() == wkbUnknown )
            {
                poFeatureDefn->SetGeomType( wkbLineString );
                /* bMultiVertex = TRUE; */
            }
        }
        else if( osLine[0] == '#' )
        {
            for( int i = 0;
                 papszKeyedValues != NULL && papszKeyedValues[i] != NULL;
                 i++ )
            {
                if( papszKeyedValues[i][0] == 'D' )
                    osFieldData = papszKeyedValues[i] + 1;
            }
        }
        else
        {
            // Parse point line.
            double dfX;
            double dfY;
            double dfZ = 0.0;
            const int nDim
                = CPLsscanf( osLine, "%lf %lf %lf", &dfX, &dfY, &dfZ );

            if( nDim >= 2 )
            {
                if( poGeom == NULL )
                {
                    switch( poFeatureDefn->GetGeomType() )
                    {
                      case wkbLineString:
                        poGeom = new OGRLineString();
                        break;

                      case wkbPolygon:
                        poGeom = new OGRPolygon();
                        reinterpret_cast<OGRPolygon *>(poGeom)->addRingDirectly(
                            new OGRLinearRing() );
                        break;

                      case wkbMultiPolygon:
                      {
                          OGRPolygon *poPoly = new OGRPolygon();
                          poPoly->addRingDirectly( new OGRLinearRing() );

                          poGeom = new OGRMultiPolygon();
                          reinterpret_cast<OGRMultiPolygon *>(poGeom)->
                              addGeometryDirectly( poPoly );
                      }
                      break;

                      case wkbMultiPoint:
                        poGeom = new OGRMultiPoint();
                        break;

                      case wkbMultiLineString:
                        poGeom = new OGRMultiLineString();
                        reinterpret_cast<OGRMultiLineString *>(poGeom)->
                            addGeometryDirectly(new OGRLineString() );
                        break;

                      case wkbPoint:
                      case wkbUnknown:
                      default:
                        poGeom = new OGRPoint();
                        break;
                    }

                }

                switch( wkbFlatten(poGeom->getGeometryType()) )
                {
                  case wkbPoint:
                    reinterpret_cast<OGRPoint *>(poGeom)->setX( dfX );
                    reinterpret_cast<OGRPoint *>(poGeom)->setY( dfY );
                    if( nDim == 3 )
                        reinterpret_cast<OGRPoint *>(poGeom)->setZ( dfZ );
                    break;

                  case wkbLineString:
                    if( nDim == 3 )
                        reinterpret_cast<OGRLineString *>(poGeom)->
                            addPoint( dfX, dfY, dfZ);
                    else
                        reinterpret_cast<OGRLineString *>(poGeom)->
                            addPoint( dfX, dfY );
                    break;

                  case wkbPolygon:
                  case wkbMultiPolygon:
                  {
                      OGRPolygon *poPoly = NULL;

                      if( wkbFlatten(poGeom->getGeometryType())
                          == wkbMultiPolygon )
                      {
                          OGRMultiPolygon *poMP = (OGRMultiPolygon *) poGeom;
                          poPoly = (OGRPolygon*) poMP->getGeometryRef(
                              poMP->getNumGeometries() - 1 );
                      }
                      else
                          poPoly = reinterpret_cast<OGRPolygon *>(poGeom);

                      OGRLinearRing *poRing = NULL;
                      if( poPoly->getNumInteriorRings() == 0 )
                          poRing = poPoly->getExteriorRing();
                      else
                          poRing = poPoly->getInteriorRing(
                              poPoly->getNumInteriorRings()-1 );

                      if( nDim == 3 )
                          poRing->addPoint( dfX, dfY, dfZ );
                      else
                          poRing->addPoint( dfX, dfY );
                  }
                  break;

                  case wkbMultiLineString:
                  {
                      OGRMultiLineString *poML = (OGRMultiLineString *) poGeom;
                      OGRLineString *poLine = reinterpret_cast<OGRLineString *>(
                          poML->getGeometryRef( poML->getNumGeometries() -1 ) );

                      if( nDim == 3 )
                          poLine->addPoint( dfX, dfY, dfZ );
                      else
                          poLine->addPoint( dfX, dfY );
                  }
                  break;

                  default:
                    CPLAssert( FALSE );
                }
            }
        }

        if( poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
        {
            ReadLine();
            break;
        }
    }

    if( poGeom == NULL )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Create feature.                                                 */
/* -------------------------------------------------------------------- */
    OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
    poGeom->assignSpatialReference(poSRS);
    poFeature->SetGeometryDirectly( poGeom );
    poFeature->SetFID( iNextFID++ );

/* -------------------------------------------------------------------- */
/*      Process field values.                                           */
/* -------------------------------------------------------------------- */
    char **papszFD = CSLTokenizeStringComplex( osFieldData, "|", TRUE, TRUE );

    for( int iField = 0; papszFD != NULL && papszFD[iField] != NULL; iField++ )
    {
        if( iField >= poFeatureDefn->GetFieldCount() )
            break;

        poFeature->SetField( iField, papszFD[iField] );
    }

    CSLDestroy( papszFD );

    m_nFeaturesRead++;

    return poFeature;
}