OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
{
    VSILFILE* fp = poDS_->GetOutputFile();

    if( NULL == poFeature )
    {
        CPLDebug( "GeoJSON", "Feature is null" );
        return OGRERR_INVALID_HANDLE;
    }

    json_object* poObj = OGRGeoJSONWriteFeature( poFeature, bWriteBBOX, nCoordPrecision );
    CPLAssert( NULL != poObj );

    if( nOutCounter_ > 0 )
    {
        /* Separate "Feature" entries in "FeatureCollection" object. */
        VSIFPrintfL( fp, ",\n" );
    }
    VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) );

    json_object_put( poObj );

    ++nOutCounter_;

    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
    if ( bWriteBBOX && !poGeometry->IsEmpty() )
    {
        OGREnvelope3D sEnvelope;
        poGeometry->getEnvelope(&sEnvelope);

        if( poGeometry->getCoordinateDimension() == 3 )
            bBBOX3D = TRUE;

        sEnvelopeLayer.Merge(sEnvelope);
    }

    return OGRERR_NONE;
}
Example #2
0
json_object* OGRGeoJSONWriteFeature( OGRFeature* poFeature, int bWriteBBOX, int nCoordPrecision )
{
    CPLAssert( NULL != poFeature );

    json_object* poObj = json_object_new_object();
    CPLAssert( NULL != poObj );

    json_object_object_add( poObj, "type",
                            json_object_new_string("Feature") );

/* -------------------------------------------------------------------- */
/*      Write FID if available                                          */
/* -------------------------------------------------------------------- */
    if ( poFeature->GetFID() != OGRNullFID )
    {
        json_object_object_add( poObj, "id",
                                json_object_new_int64(poFeature->GetFID()) );
    }

/* -------------------------------------------------------------------- */
/*      Write feature attributes to GeoJSON "properties" object.        */
/* -------------------------------------------------------------------- */
    json_object* poObjProps = NULL;

    poObjProps = OGRGeoJSONWriteAttributes( poFeature );
    json_object_object_add( poObj, "properties", poObjProps );

/* -------------------------------------------------------------------- */
/*      Write feature geometry to GeoJSON "geometry" object.            */
/*      Null geometries are allowed, according to the GeoJSON Spec.     */
/* -------------------------------------------------------------------- */
    json_object* poObjGeom = NULL;

    OGRGeometry* poGeometry = poFeature->GetGeometryRef();
    if ( NULL != poGeometry )
    {
        poObjGeom = OGRGeoJSONWriteGeometry( poGeometry, nCoordPrecision );

        if ( bWriteBBOX && !poGeometry->IsEmpty() )
        {
            OGREnvelope3D sEnvelope;
            poGeometry->getEnvelope(&sEnvelope);

            json_object* poObjBBOX = json_object_new_array();
            json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MinX, nCoordPrecision));
            json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MinY, nCoordPrecision));
            if (poGeometry->getCoordinateDimension() == 3)
                json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MinZ, nCoordPrecision));
            json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MaxX, nCoordPrecision));
            json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MaxY, nCoordPrecision));
            if (poGeometry->getCoordinateDimension() == 3)
                json_object_array_add(poObjBBOX,
                            json_object_new_double_with_precision(sEnvelope.MaxZ, nCoordPrecision));

            json_object_object_add( poObj, "bbox", poObjBBOX );
        }
    }
    
    json_object_object_add( poObj, "geometry", poObjGeom );

    return poObj;
}
Example #3
0
feature_ptr ogr_featureset::next()
{
    if (count_ == 0)
    {
        // Reset the layer reading on the first feature read
        // this is a hack, but needed due to https://github.com/mapnik/mapnik/issues/2048
        // Proper solution is to avoid storing layer state in featureset
        layer_.ResetReading();
    }
    OGRFeature *poFeature;
    while ((poFeature = layer_.GetNextFeature()) != nullptr)
    {
        // ogr feature ids start at 0, so add one to stay
        // consistent with other mapnik datasources that start at 1
        mapnik::value_integer feature_id = (poFeature->GetFID() + 1);
        feature_ptr feature(feature_factory::create(ctx_,feature_id));

        OGRGeometry* geom = poFeature->GetGeometryRef();
        if (geom && ! geom->IsEmpty())
        {
            auto geom_corrected = ogr_converter::convert_geometry(geom);
            mapnik::geometry::correct(geom_corrected);
            feature->set_geometry(std::move(geom_corrected));
        }
        else
        {
            MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry="
                << poFeature->GetFID();
            OGRFeature::DestroyFeature( poFeature );
            continue;
        }

        ++count_;

        int fld_count = layerdef_->GetFieldCount();
        for (int i = 0; i < fld_count; i++)
        {
            OGRFieldDefn* fld = layerdef_->GetFieldDefn(i);
            const OGRFieldType type_oid = fld->GetType();
            const std::string fld_name = fld->GetNameRef();

            switch (type_oid)
            {
            case OFTInteger:
            {
                feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger(i));
                break;
            }
#if GDAL_VERSION_MAJOR >= 2
            case OFTInteger64:
            {
                feature->put<mapnik::value_integer>( fld_name, poFeature->GetFieldAsInteger64(i));
                break;
            }
#endif

            case OFTReal:
            {
                feature->put( fld_name, poFeature->GetFieldAsDouble(i));
                break;
            }

            case OFTString:
            case OFTWideString:     // deprecated !
            {
                feature->put( fld_name, tr_->transcode(poFeature->GetFieldAsString(i)));
                break;
            }

            case OFTIntegerList:
#if GDAL_VERSION_MAJOR >= 2
            case OFTInteger64List:
#endif
            case OFTRealList:
            case OFTStringList:
            case OFTWideStringList: // deprecated !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            case OFTBinary:
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                //feature->put(name,feat->GetFieldAsBinary (i, size));
                break;
            }

            case OFTDate:
            case OFTTime:
            case OFTDateTime:       // unhandled !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            default: // unknown
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid;
                break;
            }
            }
        }
        OGRFeature::DestroyFeature( poFeature );
        return feature;
    }

    MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features";

    return feature_ptr();
}
Example #4
0
feature_ptr ogr_featureset::next()
{
    OGRFeature *poFeature;
    while ((poFeature = layer_.GetNextFeature()) != NULL)
    {
        // ogr feature ids start at 0, so add one to stay
        // consistent with other mapnik datasources that start at 1
        const int feature_id = (poFeature->GetFID() + 1);
        feature_ptr feature(feature_factory::create(ctx_,feature_id));

        OGRGeometry* geom = poFeature->GetGeometryRef();
        if (geom && ! geom->IsEmpty())
        {
            ogr_converter::convert_geometry(geom, feature);
        }
        else
        {
            MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: Feature with null geometry="
                << poFeature->GetFID();
            OGRFeature::DestroyFeature( poFeature );
            continue;
        }

        ++count_;

        int fld_count = layerdef_->GetFieldCount();
        for (int i = 0; i < fld_count; i++)
        {
            OGRFieldDefn* fld = layerdef_->GetFieldDefn(i);
            const OGRFieldType type_oid = fld->GetType();
            const std::string fld_name = fld->GetNameRef();

            switch (type_oid)
            {
            case OFTInteger:
            {
                feature->put( fld_name, poFeature->GetFieldAsInteger(i));
                break;
            }

            case OFTReal:
            {
                feature->put( fld_name, poFeature->GetFieldAsDouble(i));
                break;
            }

            case OFTString:
            case OFTWideString:     // deprecated !
            {
                UnicodeString ustr = tr_->transcode(poFeature->GetFieldAsString(i));
                feature->put( fld_name, ustr);
                break;
            }

            case OFTIntegerList:
            case OFTRealList:
            case OFTStringList:
            case OFTWideStringList: // deprecated !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            case OFTBinary:
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                //feature->put(name,feat->GetFieldAsBinary (i, size));
                break;
            }

            case OFTDate:
            case OFTTime:
            case OFTDateTime:       // unhandled !
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unhandled type_oid=" << type_oid;
                break;
            }

            default: // unknown
            {
                MAPNIK_LOG_WARN(ogr) << "ogr_featureset: Unknown type_oid=" << type_oid;
                break;
            }
            }
        }
        OGRFeature::DestroyFeature( poFeature );
        return feature;
    }

    MAPNIK_LOG_DEBUG(ogr) << "ogr_featureset: " << count_ << " features";

    return feature_ptr();
}
Example #5
0
OGRErr OGRBNALayer::CreateFeature( OGRFeature *poFeature )

{
    int i,j,k,n;
    OGRGeometry     *poGeom = poFeature->GetGeometryRef();
    char eol[3];
    const char* partialEol = (poDS->GetMultiLine()) ? eol : poDS->GetCoordinateSeparator();

    if (poGeom == NULL || poGeom->IsEmpty() )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "OGR BNA driver cannot write features with empty geometries.");
        return OGRERR_FAILURE;
    }

    if (poDS->GetUseCRLF())
    {
        eol[0] = 13;
        eol[1] = 10;
        eol[2] = 0;
    }
    else
    {
        eol[0] = 10;
        eol[1] = 0;
    }
    
    if ( ! bWriter )
    {
        return OGRERR_FAILURE;
    }
    
    if( poFeature->GetFID() == OGRNullFID )
        poFeature->SetFID( nFeatures++ );
    
    VSILFILE* fp = poDS->GetOutputFP();
    int nbPairPerLine = poDS->GetNbPairPerLine();

    switch( poGeom->getGeometryType() )
    {
        case wkbPoint:
        case wkbPoint25D:
        {
            OGRPoint* point = (OGRPoint*)poGeom;
            WriteFeatureAttributes(fp, poFeature);
            VSIFPrintfL( fp, "1");
            VSIFPrintfL( fp, "%s", partialEol);
            WriteCoord(fp, point->getX(), point->getY());
            VSIFPrintfL( fp, "%s", eol);
            break;
        }
            
        case wkbPolygon:
        case wkbPolygon25D:
        {
            OGRPolygon* polygon = (OGRPolygon*)poGeom;
            OGRLinearRing* ring = polygon->getExteriorRing();
            if (ring == NULL)
            {
                return OGRERR_FAILURE;
            }
            
            double firstX = ring->getX(0);
            double firstY = ring->getY(0);
            int nBNAPoints = ring->getNumPoints();
            int is_ellipse = FALSE;
            
            /* This code tries to detect an ellipse in a polygon geometry */
            /* This will only work presumably on ellipses already read from a BNA file */
            /* Mostly a BNA to BNA feature... */
            if (poDS->GetEllipsesAsEllipses() &&
                polygon->getNumInteriorRings() == 0 &&
                nBNAPoints == 361)
            {
                double oppositeX = ring->getX(180);
                double oppositeY = ring->getY(180);
                double quarterX = ring->getX(90);
                double quarterY = ring->getY(90);
                double antiquarterX = ring->getX(270);
                double antiquarterY = ring->getY(270);
                double center1X = 0.5*(firstX + oppositeX);
                double center1Y = 0.5*(firstY + oppositeY);
                double center2X = 0.5*(quarterX + antiquarterX);
                double center2Y = 0.5*(quarterY + antiquarterY);
                if (fabs(center1X - center2X) < 1e-5 && fabs(center1Y - center2Y) < 1e-5 &&
                    fabs(oppositeY - firstY) < 1e-5 &&
                    fabs(quarterX - antiquarterX) < 1e-5)
                {
                    double major_radius = fabs(firstX - center1X);
                    double minor_radius = fabs(quarterY - center1Y);
                    is_ellipse = TRUE;
                    for(i=0;i<360;i++)
                    {
                        if (!(fabs(center1X + major_radius * cos(i * (M_PI / 180)) - ring->getX(i)) < 1e-5 &&
                              fabs(center1Y + minor_radius * sin(i * (M_PI / 180)) - ring->getY(i)) < 1e-5))
                        {
                            is_ellipse = FALSE;
                            break;
                        }
                    }
                    if ( is_ellipse == TRUE )
                    {
                        WriteFeatureAttributes(fp, poFeature);
                        VSIFPrintfL( fp, "2");
                        VSIFPrintfL( fp, "%s", partialEol);
                        WriteCoord(fp, center1X, center1Y);
                        VSIFPrintfL( fp, "%s", partialEol);
                        WriteCoord(fp, major_radius, minor_radius);
                        VSIFPrintfL( fp, "%s", eol);
                    }
                }
            }

            if ( is_ellipse == FALSE)
            {
                int nInteriorRings = polygon->getNumInteriorRings();
                for(i=0;i<nInteriorRings;i++)
                {
                    nBNAPoints += polygon->getInteriorRing(i)->getNumPoints() + 1;
                }
                if (nBNAPoints <= 3)
                {
                    CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
                    return OGRERR_FAILURE;
                }
                WriteFeatureAttributes(fp, poFeature);
                VSIFPrintfL( fp, "%d", nBNAPoints);
                n = ring->getNumPoints();
                int nbPair = 0;
                for(i=0;i<n;i++)
                {
                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                    WriteCoord(fp, ring->getX(i), ring->getY(i));
                    nbPair++;
                }
                for(i=0;i<nInteriorRings;i++)
                {
                    ring = polygon->getInteriorRing(i);
                    n = ring->getNumPoints();
                    for(j=0;j<n;j++)
                    {
                        VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                        WriteCoord(fp, ring->getX(j), ring->getY(j));
                        nbPair++;
                    }
                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                    WriteCoord(fp, firstX, firstY);
                    nbPair++;
                }
                VSIFPrintfL( fp, "%s", eol);
            }
            break;
        }

        case wkbMultiPolygon:
        case wkbMultiPolygon25D:
        {
            OGRMultiPolygon* multipolygon = (OGRMultiPolygon*)poGeom;
            int N = multipolygon->getNumGeometries();
            int nBNAPoints = 0;
            double firstX = 0, firstY = 0; 
            for(i=0;i<N;i++)
            {
                OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
                OGRLinearRing* ring = polygon->getExteriorRing();
                if (ring == NULL)
                    continue;

                if (nBNAPoints)
                    nBNAPoints ++;
                else
                {
                    firstX = ring->getX(0);
                    firstY = ring->getY(0);
                }
                nBNAPoints += ring->getNumPoints();
                int nInteriorRings = polygon->getNumInteriorRings();
                for(j=0;j<nInteriorRings;j++)
                {
                    nBNAPoints += polygon->getInteriorRing(j)->getNumPoints() + 1;
                }
            }
            if (nBNAPoints <= 3)
            {
                CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
                return OGRERR_FAILURE;
            }
            WriteFeatureAttributes(fp, poFeature);
            VSIFPrintfL( fp, "%d", nBNAPoints);
            int nbPair = 0;
            for(i=0;i<N;i++)
            {
                OGRPolygon* polygon = (OGRPolygon*)multipolygon->getGeometryRef(i);
                OGRLinearRing* ring = polygon->getExteriorRing();
                if (ring == NULL)
                    continue;

                n = ring->getNumPoints();
                int nInteriorRings = polygon->getNumInteriorRings();
                for(j=0;j<n;j++)
                {
                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                    WriteCoord(fp, ring->getX(j), ring->getY(j));
                    nbPair++;
                }
                if (i != 0)
                {
                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                    WriteCoord(fp, firstX, firstY);
                    nbPair++;
                }
                for(j=0;j<nInteriorRings;j++)
                {
                    ring = polygon->getInteriorRing(j);
                    n = ring->getNumPoints();
                    for(k=0;k<n;k++)
                    {
                        VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                        WriteCoord(fp, ring->getX(k), ring->getY(k));
                        nbPair++;
                    }
                    VSIFPrintfL( fp, "%s", ((nbPair % nbPairPerLine) == 0) ? partialEol : " ");
                    WriteCoord(fp, firstX, firstY);
                    nbPair++;
                }
            }
            VSIFPrintfL( fp, "%s", eol);
            break;
        }

        case wkbLineString:
        case wkbLineString25D:
        {
            OGRLineString* line = (OGRLineString*)poGeom;
            int n = line->getNumPoints();
            int i;
            if (n < 2)
            {
                CPLError( CE_Failure, CPLE_AppDefined, "Invalid geometry" );
                return OGRERR_FAILURE;
            }
            WriteFeatureAttributes(fp, poFeature);
            VSIFPrintfL( fp, "-%d", n);
            int nbPair = 0;
            for(i=0;i<n;i++)
            {
                VSIFPrintfL( fp, "%s", partialEol);
                WriteCoord(fp, line->getX(i), line->getY(i));
                nbPair++;
            }
            VSIFPrintfL( fp, "%s", eol);
            break;
        }
            
        default:
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                      "Unsupported geometry type : %s.",
                      poGeom->getGeometryName() );

            return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
        }
    }
    
    return OGRERR_NONE;
}
Example #6
0
OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )

{
    OGRFeature  *poFeature;
    OGREnvelope oEnv;
    GBool       bExtentSet = FALSE;

    psExtent->MinX = 0.0;
    psExtent->MaxX = 0.0;
    psExtent->MinY = 0.0;
    psExtent->MaxY = 0.0;

/* -------------------------------------------------------------------- */
/*      If this layer has a none geometry type, then we can             */
/*      reasonably assume there are not extents available.              */
/* -------------------------------------------------------------------- */
    if( GetLayerDefn()->GetGeomType() == wkbNone )
        return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/*      If not forced, we should avoid having to scan all the           */
/*      features and just return a failure.                             */
/* -------------------------------------------------------------------- */
    if( !bForce )
        return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/*      OK, we hate to do this, but go ahead and read through all       */
/*      the features to collect geometries and build extents.           */
/* -------------------------------------------------------------------- */
    ResetReading();
    while( (poFeature = GetNextFeature()) != NULL )
    {
        OGRGeometry *poGeom = poFeature->GetGeometryRef();
        if (poGeom == NULL || poGeom->IsEmpty())
        {
            /* Do nothing */
        }
        else if (!bExtentSet)
        {
            poGeom->getEnvelope(psExtent);
            bExtentSet = TRUE;
        }
        else
        {
            poGeom->getEnvelope(&oEnv);
            if (oEnv.MinX < psExtent->MinX) 
                psExtent->MinX = oEnv.MinX;
            if (oEnv.MinY < psExtent->MinY) 
                psExtent->MinY = oEnv.MinY;
            if (oEnv.MaxX > psExtent->MaxX) 
                psExtent->MaxX = oEnv.MaxX;
            if (oEnv.MaxY > psExtent->MaxY) 
                psExtent->MaxY = oEnv.MaxY;
        }
        delete poFeature;
    }
    ResetReading();

    return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
}
Example #7
0
boost::optional<mapnik::datasource_geometry_t> ogr_datasource::get_geometry_type() const
{
    boost::optional<mapnik::datasource_geometry_t> result;
    if (dataset_ && layer_.is_valid())
    {
        OGRLayer* layer = layer_.layer();
        // NOTE: wkbFlatten macro in ogr flattens 2.5d types into base 2d type
#if GDAL_VERSION_NUM < 1800
        switch (wkbFlatten(layer->GetLayerDefn()->GetGeomType()))
#else
        switch (wkbFlatten(layer->GetGeomType()))
#endif
            {
            case wkbPoint:
            case wkbMultiPoint:
                result.reset(mapnik::datasource_geometry_t::Point);
                break;
            case wkbLinearRing:
            case wkbLineString:
            case wkbMultiLineString:
                result.reset(mapnik::datasource_geometry_t::LineString);
                break;
            case wkbPolygon:
            case wkbMultiPolygon:
                result.reset(mapnik::datasource_geometry_t::Polygon);
                break;
            case wkbGeometryCollection:
                result.reset(mapnik::datasource_geometry_t::Collection);
                break;
            case wkbNone:
            case wkbUnknown:
            {
                // fallback to inspecting first actual geometry
                // TODO - csv and shapefile inspect first 4 features
                if (dataset_ && layer_.is_valid())
                {
                    layer = layer_.layer();
                    // only new either reset of setNext
                    //layer->ResetReading();
                    layer->SetNextByIndex(0);
                    OGRFeature *poFeature;
                    while ((poFeature = layer->GetNextFeature()) != nullptr)
                    {
                        OGRGeometry* geom = poFeature->GetGeometryRef();
                        if (geom && ! geom->IsEmpty())
                        {
                            switch (wkbFlatten(geom->getGeometryType()))
                            {
                            case wkbPoint:
                            case wkbMultiPoint:
                                result.reset(mapnik::datasource_geometry_t::Point);
                                break;
                            case wkbLinearRing:
                            case wkbLineString:
                            case wkbMultiLineString:
                                result.reset(mapnik::datasource_geometry_t::LineString);
                                break;
                            case wkbPolygon:
                            case wkbMultiPolygon:
                                result.reset(mapnik::datasource_geometry_t::Polygon);
                                break;
                            case wkbGeometryCollection:
                                result.reset(mapnik::datasource_geometry_t::Collection);
                                break;
                            default:
                                break;
                            }
                        }
                        OGRFeature::DestroyFeature( poFeature );
                        break;
                    }
                }
                break;
            }
            default:
                break;
            }
    }

    return result;
}
Example #8
0
OGRErr OGRGeoJSONWriteLayer::ICreateFeature( OGRFeature* poFeature )
{
    VSILFILE* fp = poDS_->GetOutputFile();

    OGRFeature* poFeatureToWrite;
    if( poCT_ != nullptr || bRFC7946_ )
    {
        poFeatureToWrite = new OGRFeature(poFeatureDefn_);
        poFeatureToWrite->SetFrom( poFeature );
        poFeatureToWrite->SetFID( poFeature->GetFID() );
        OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef();
        if( poGeometry )
        {
            const char* const apszOptions[] = { "WRAPDATELINE=YES", nullptr };
            OGRGeometry* poNewGeom =
                OGRGeometryFactory::transformWithOptions(
                    poGeometry, poCT_, const_cast<char**>(apszOptions),
                    oTransformCache_);
            if( poNewGeom == nullptr )
            {
                delete poFeatureToWrite;
                return OGRERR_FAILURE;
            }

            OGREnvelope sEnvelope;
            poNewGeom->getEnvelope(&sEnvelope);
            if( sEnvelope.MinX < -180.0 || sEnvelope.MaxX > 180.0 ||
                sEnvelope.MinY < -90.0 || sEnvelope.MaxY > 90.0 )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Geometry extent outside of [-180.0,180.0]x[-90.0,90.0] bounds");
                delete poFeatureToWrite;
                return OGRERR_FAILURE;
            }

            poFeatureToWrite->SetGeometryDirectly( poNewGeom );
        }
    }
    else
    {
        poFeatureToWrite = poFeature;
    }

    json_object* poObj =
        OGRGeoJSONWriteFeature( poFeatureToWrite, oWriteOptions_ );
    CPLAssert( nullptr != poObj );

    if( nOutCounter_ > 0 )
    {
        /* Separate "Feature" entries in "FeatureCollection" object. */
        VSIFPrintfL( fp, ",\n" );
    }
    VSIFPrintfL( fp, "%s", json_object_to_json_string( poObj ) );

    json_object_put( poObj );

    ++nOutCounter_;

    OGRGeometry* poGeometry = poFeatureToWrite->GetGeometryRef();
    if( bWriteFC_BBOX && poGeometry != nullptr && !poGeometry->IsEmpty() )
    {
        OGREnvelope3D sEnvelope = OGRGeoJSONGetBBox( poGeometry,
                                                     oWriteOptions_ );
        if( poGeometry->getCoordinateDimension() == 3 )
            bBBOX3D = true;

        if( !sEnvelopeLayer.IsInit() )
        {
            sEnvelopeLayer = sEnvelope;
        }
        else if( oWriteOptions_.bBBOXRFC7946 )
        {
            const bool bEnvelopeCrossAM = ( sEnvelope.MinX > sEnvelope.MaxX );
            const bool bEnvelopeLayerCrossAM =
                                ( sEnvelopeLayer.MinX > sEnvelopeLayer.MaxX );
            if( bEnvelopeCrossAM )
            {
                if( bEnvelopeLayerCrossAM )
                {
                    sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
                                                   sEnvelope.MinX);
                    sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
                                                   sEnvelope.MaxX);
                }
                else
                {
                    if( sEnvelopeLayer.MinX > 0 )
                    {
                        sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
                                                       sEnvelope.MinX);
                        sEnvelopeLayer.MaxX = sEnvelope.MaxX;
                    }
                    else if( sEnvelopeLayer.MaxX < 0 )
                    {
                        sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
                                                       sEnvelope.MaxX);
                        sEnvelopeLayer.MinX = sEnvelope.MinX;
                    }
                    else
                    {
                        sEnvelopeLayer.MinX = -180.0;
                        sEnvelopeLayer.MaxX = 180.0;
                    }
                }
            }
            else if( bEnvelopeLayerCrossAM )
            {
                if( sEnvelope.MinX > 0 )
                {
                    sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
                                                   sEnvelope.MinX);
                }
                else if( sEnvelope.MaxX < 0 )
                {
                    sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
                                                   sEnvelope.MaxX);
                }
                else
                {
                    sEnvelopeLayer.MinX = -180.0;
                    sEnvelopeLayer.MaxX = 180.0;
                }
            }
            else
            {
                sEnvelopeLayer.MinX = std::min(sEnvelopeLayer.MinX,
                                               sEnvelope.MinX);
                sEnvelopeLayer.MaxX = std::max(sEnvelopeLayer.MaxX,
                                               sEnvelope.MaxX);
            }

            sEnvelopeLayer.MinY = std::min(sEnvelopeLayer.MinY, sEnvelope.MinY);
            sEnvelopeLayer.MaxY = std::max(sEnvelopeLayer.MaxY, sEnvelope.MaxY);
        }
        else
        {
            sEnvelopeLayer.Merge(sEnvelope);
        }
    }

    if( poFeatureToWrite != poFeature )
        delete poFeatureToWrite;

    return OGRERR_NONE;
}
Example #9
0
int main (int argc, const char * argv[]) {
  
  time_t startTime = time(NULL);
  
  if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) {
    usage();
    return(0);
  }
  
  OGRGeometry *geometry;
  
  for (int argNum = 1; argNum < argc; ++argNum) {
    //-- whether to compute the robustness or not
    if (strcmp(argv[argNum], "--robustness") == 0) {
      computeRobustness = true;
    }
    
    //-- whether to use the point set topology paradigm or not
    //-- if not, odd-even paradigm is used by default
    else if (strcmp(argv[argNum], "--setdiff") == 0) {
      pointSet = true;
    }
    
    //-- mininum area to keep in output
    else if (strcmp(argv[argNum], "--minarea") == 0) {
      minArea = atof(argv[argNum+1]);
      ++argNum;
    }
    
    //-- ISR snapping tolerance
    else if (strcmp(argv[argNum], "--isr") == 0) {
      isrTolerance = atof(argv[argNum+1]);
      ++argNum;
      // TODO : scale dataset if tolerance < 1.0 because of CGAL bug
    }
    
    //-- output a shapefile (out.shp) instead of a WKT
    else if (strcmp(argv[argNum], "--shpOut") == 0) {
      shpOut = true;
    }
    
    //-- time the results
    else if (strcmp(argv[argNum], "--time") == 0) {
      timeResults = true;
    }
    
    //-- reading from WKT passed directly
    else if (strcmp(argv[argNum], "--wkt") == 0) {
      unsigned int bufferSize = 100000000;
      char *inputWKT = (char *)malloc(bufferSize*sizeof(char));
      strcpy(inputWKT, argv[argNum+1]);
      ++argNum;
      OGRErr err = OGRGeometryFactory::createFromWkt(&inputWKT, NULL, &geometry);
      if (err != OGRERR_NONE) {
        switch (err) {
          case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
            std::cerr << "Error: geometry must be Polygon or MultiPolygon" << std::endl;
            break;
          case OGRERR_NOT_ENOUGH_DATA:
          case OGRERR_CORRUPT_DATA:
            std::cerr << "Error: corrupted input" << std::endl;
            break;
          default:
            std::cerr << "Error: corrupted input" << std::endl;
            break;
        }
        return 1;
      }
      if (geometry->IsEmpty() == 1) {
        std::cerr << "Error: empty geometry" << std::endl;
        return 1;
      }
      if ( (geometry->getGeometryType() != wkbPolygon) && 
           (geometry->getGeometryType() != wkbMultiPolygon) ) {
        std::cerr << "Error: geometry must be Polygon or MultiPolygon" << std::endl;
        return 1;
      }
    }
    
    //-- reading from WKT stored in first line of a text file
    else if (strcmp(argv[argNum], "-f") == 0) {
      unsigned int bufferSize = 100000000;
      char *inputWKT = (char *)malloc(bufferSize*sizeof(char));
      if (argNum + 1 <= argc - 1 && argv[argNum+1][0] != '-') {
        std::ifstream infile(argv[argNum+1], std::ifstream::in);
        infile.getline(inputWKT, bufferSize);
        ++argNum;
      } else {
        std::cerr << "Error: Missing input file name." << std::endl;
        return 1;
      }
      OGRGeometryFactory::createFromWkt(&inputWKT, NULL, &geometry);
      if (geometry == NULL) {
        std::cout << "Error: WKT is not valid" << std::endl;
        return 1;
      }
    }
    
    //-- reading from a ogr dataset (most supported: shp, geojson, gml, etc)
    else if (strcmp(argv[argNum], "--ogr") == 0) {
      OGRRegisterAll();
      OGRDataSource *dataSource = OGRSFDriverRegistrar::Open(argv[argNum+1], false);
      ++argNum;
      if (dataSource == NULL) {
        std::cerr << "Error: Could not open file." << std::endl;
        return false;
      }
      OGRLayer *dataLayer = dataSource->GetLayer(0); //-- get first layer
      dataLayer->ResetReading();
      //-- Reads all features in this layer
      OGRFeature *feature;
      //-- get first feature
      if (dataLayer->GetFeatureCount(true) > 1)
        std::cout << "Reading only the first feature in the shapefile." << std::endl;
      feature = dataLayer->GetNextFeature();
      if (feature->GetGeometryRef()->getGeometryType() == wkbPolygon) {
        geometry = static_cast<OGRPolygon *>(feature->GetGeometryRef());feature->GetGeometryRef();
      }
      else {
        std::cout << "First feature ain't a POLYGON." << std::endl;
        return(0);
      }
      
    }
    
    else {
      usage();
      return(0);
    }
  }
  
  if (!timeResults) startTime = 0;
  
  PolygonRepair prepair;
  
  //-- compute robustness
  if (computeRobustness == true)
    std::cout << "Robustness of input polygon: " << sqrt(prepair.computeRobustness(geometry)) <<std::endl;
  
  
  OGRMultiPolygon *outPolygons;
  if (pointSet) {
    outPolygons = prepair.repairPointSet(geometry, startTime);
  } else {
    outPolygons = prepair.repairOddEven(geometry, startTime);
  }
  
  if (minArea > 0) {
    prepair.removeSmallPolygons(outPolygons, minArea);
  }
  
  //-- output well known text
  if (shpOut) {
    prepair.saveToShp(outPolygons, "out.shp");
  }
  else {
    char *outputWKT;
    outPolygons->exportToWkt(&outputWKT);
    std::cout << outputWKT << std::endl;
  }
  
  
  //-- compute robustness
  if (computeRobustness == true)
    std::cout << "Robustness of output polygon: " << sqrt(prepair.computeRobustness()) <<std::endl;
  
  //-- time results
  if (timeResults) {
    time_t totalTime = time(NULL)-startTime;
    std::cout << "Done! Process finished in " << totalTime/60 << " minutes " << totalTime%60 << " seconds." << std::endl;
  }
  
  return 0;
}
static
int OGR2SQLITEDealWithSpatialColumn(OGRLayer* poLayer,
                                    int iGeomCol,
                                    const LayerDesc& oLayerDesc,
                                    const CPLString& osTableName,
                                    OGRSQLiteDataSource* poSQLiteDS,
                                    sqlite3* hDB,
                                    int bSpatialiteDB,
                                    const std::set<LayerDesc>&
                                        WHEN_SPATIALITE(oSetLayers),
                                    const std::set<CPLString>&
                                        WHEN_SPATIALITE(oSetSpatialIndex)
                                   )
{
    OGRGeomFieldDefn* poGeomField =
        poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeomCol);
    CPLString osGeomColRaw;
    if( iGeomCol == 0 )
        osGeomColRaw = OGR2SQLITE_GetNameForGeometryColumn(poLayer);
    else
        osGeomColRaw = poGeomField->GetNameRef();
    const char* pszGeomColRaw = osGeomColRaw.c_str();

    CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
    const char* pszGeomColEscaped = osGeomColEscaped.c_str();

    CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
    const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();

    CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
                    oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
    CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));

    /* Make sure that the SRS is injected in spatial_ref_sys */
    OGRSpatialReference* poSRS = poGeomField->GetSpatialRef();
    if( iGeomCol == 0 && poSRS == NULL )
        poSRS = poLayer->GetSpatialRef();
    int nSRSId = poSQLiteDS->GetUndefinedSRID();
    if( poSRS != NULL )
        nSRSId = poSQLiteDS->FetchSRSId(poSRS);

    CPLString osSQL;
#ifdef HAVE_SPATIALITE
    bool bCreateSpatialIndex = false;
#endif
    if( !bSpatialiteDB )
    {
        osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                    "f_geometry_column, geometry_format, geometry_type, "
                    "coord_dimension, srid) "
                    "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
                    pszLayerNameEscaped,
                    pszGeomColEscaped,
                        (int) wkbFlatten(poLayer->GetGeomType()),
                    wkbHasZ( poLayer->GetGeomType() ) ? 3 : 2,
                    nSRSId);
    }
#ifdef HAVE_SPATIALITE
    else
    {
        /* We detect the need for creating a spatial index by 2 means : */

        /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
        /*   table in the SQL --> old/traditional way of requesting spatial indices */
        /*   with spatialite. */

        std::set<LayerDesc>::const_iterator oIter2 = oSetLayers.begin();
        for(; oIter2 != oSetLayers.end(); ++oIter2)
        {
            const LayerDesc& oLayerDescIter = *oIter2;
            if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
            {
                    bCreateSpatialIndex = true;
                    break;
            }
        }

        /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */
        if( !bCreateSpatialIndex )
        {
            std::set<CPLString>::const_iterator oIter3 = oSetSpatialIndex.begin();
            for(; oIter3 != oSetSpatialIndex.end(); ++oIter3)
            {
                const CPLString& osNameIter = *oIter3;
                if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
                {
                    bCreateSpatialIndex = true;
                    break;
                }
            }
        }

        if( poSQLiteDS->HasSpatialite4Layout() )
        {
            int nGeomType = poLayer->GetGeomType();
            int nCoordDimension = 2;
            if( wkbHasZ((OGRwkbGeometryType)nGeomType) )
            {
                nGeomType += 1000;
                nCoordDimension = 3;
            }

            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                        "f_geometry_column, geometry_type, coord_dimension, "
                        "srid, spatial_index_enabled) "
                        "VALUES (Lower('%s'),Lower('%s'),%d ,%d ,%d, %d)",
                        pszLayerNameEscaped,
                        pszGeomColEscaped, nGeomType,
                        nCoordDimension,
                        nSRSId, static_cast<int>(bCreateSpatialIndex) );
        }
        else
        {
            const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType());
            if (pszGeometryType[0] == '\0')
                pszGeometryType = "GEOMETRY";

            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                        "f_geometry_column, type, coord_dimension, "
                        "srid, spatial_index_enabled) "
                        "VALUES ('%s','%s','%s','%s',%d, %d)",
                        pszLayerNameEscaped,
                        pszGeomColEscaped, pszGeometryType,
                        wkbHasZ( poLayer->GetGeomType() ) ? "XYZ" : "XY",
                        nSRSId, static_cast<int>(bCreateSpatialIndex) );
        }
    }
#endif // HAVE_SPATIALITE
    char* pszErrMsg = NULL;
    int rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, &pszErrMsg );
    if( pszErrMsg != NULL )
    {
        CPLDebug("SQLITE", "%s -> %s", osSQL.c_str(), pszErrMsg);
        sqlite3_free(pszErrMsg);
    }

#ifdef HAVE_SPATIALITE
/* -------------------------------------------------------------------- */
/*      Should we create a spatial index ?.                             */
/* -------------------------------------------------------------------- */
    if( !bSpatialiteDB || !bCreateSpatialIndex )
        return rc == SQLITE_OK;

    CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());

    /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
    osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING "
                    "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
                    osIdxNameEscaped.c_str(),
                    nExtraDS,
                    OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());

    rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
    if( rc != SQLITE_OK )
    {
        CPLDebug( "SQLITE",
                  "Error occurred during spatial index creation : %s",
                  sqlite3_errmsg(hDB));
    }
#else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
    rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );

    osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
                    "USING rtree(pkid, xmin, xmax, ymin, ymax)",
                    osIdxNameEscaped.c_str());

    if( rc == SQLITE_OK )
        rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );

    sqlite3_stmt *hStmt = NULL;
    if( rc == SQLITE_OK )
    {
        const char* pszInsertInto = CPLSPrintf(
            "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
            "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
        rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
    }

    OGRFeature* poFeature;
    OGREnvelope sEnvelope;
    OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
    poLayer->ResetReading();

    while( rc == SQLITE_OK &&
            (poFeature = poLayer->GetNextFeature()) != NULL )
    {
        OGRGeometry* poGeom = poFeature->GetGeometryRef();
        if( poGeom != NULL && !poGeom->IsEmpty() )
        {
            poGeom->getEnvelope(&sEnvelope);
            sqlite3_bind_int64(hStmt, 1,
                                (sqlite3_int64) poFeature->GetFID() );
            sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
            sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
            sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
            sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
            rc = sqlite3_step(hStmt);
            if( rc == SQLITE_OK || rc == SQLITE_DONE )
                rc = sqlite3_reset(hStmt);
        }
        delete poFeature;
    }

    poLayer->SetIgnoredFields(NULL);

    sqlite3_finalize(hStmt);

    if( rc == SQLITE_OK )
        rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
    else
    {
        CPLDebug( "SQLITE",
                  "Error occurred during spatial index creation : %s",
                  sqlite3_errmsg(hDB));
        rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
    }
#endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX

#endif // HAVE_SPATIALITE

    return rc == SQLITE_OK;
}
Example #11
0
OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )

{
    OGRGeometry *poGeom = poFeature->GetGeometryRef();
    OGRwkbGeometryType eGType = wkbNone;

    if( poGeom != nullptr )
    {
        if( !poGeom->IsEmpty() )
        {
            OGREnvelope sEnvelope;
            poGeom->getEnvelope(&sEnvelope);
            poDS->UpdateExtent(&sEnvelope);
        }
        eGType = wkbFlatten(poGeom->getGeometryType());
    }

    if( eGType == wkbPoint )
    {
        const char *pszBlockName = poFeature->GetFieldAsString("BlockName");

        // We don't want to treat as a blocks ref if the block is not defined
        if( pszBlockName
            && poDS->oHeaderDS.LookupBlock(pszBlockName) == nullptr )
        {
            if( poDS->poBlocksLayer == nullptr
                || poDS->poBlocksLayer->FindBlock(pszBlockName) == nullptr )
                pszBlockName = nullptr;
        }

        if( pszBlockName != nullptr )
            return WriteINSERT( poFeature );

        else if( poFeature->GetStyleString() != nullptr
            && STARTS_WITH_CI(poFeature->GetStyleString(), "LABEL") )
            return WriteTEXT( poFeature );
        else
            return WritePOINT( poFeature );
    }
    else if( eGType == wkbLineString
             || eGType == wkbMultiLineString )
        return WritePOLYLINE( poFeature );

    else if( eGType == wkbPolygon
             || eGType == wkbTriangle
             || eGType == wkbMultiPolygon)
    {
        if( bWriteHatch )
            return WriteHATCH( poFeature );
        else
            return WritePOLYLINE( poFeature );
    }

    // Explode geometry collections into multiple entities.
    else if( eGType == wkbGeometryCollection )
    {
        OGRGeometryCollection *poGC =
            poFeature->StealGeometry()->toGeometryCollection();
        for( auto&& poMember: poGC )
        {
            poFeature->SetGeometry( poMember );

            OGRErr eErr = CreateFeature( poFeature );

            if( eErr != OGRERR_NONE )
            {
                delete poGC;
                return eErr;
            }
        }

        poFeature->SetGeometryDirectly( poGC );
        return OGRERR_NONE;
    }
    else
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "No known way to write feature with geometry '%s'.",
                  OGRGeometryTypeToName(eGType) );
        return OGRERR_FAILURE;
    }
}
OGRErr OGRGMLLayer::CreateFeature( OGRFeature *poFeature )

{
    int bIsGML3Output = poDS->IsGML3Output();
    VSILFILE *fp = poDS->GetOutputFP();
    int bWriteSpaceIndentation = poDS->WriteSpaceIndentation();

    if( !bWriter )
        return OGRERR_FAILURE;

    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "  ");
    if (bIsGML3Output)
        poDS->PrintLine( fp, "<ogr:featureMember>" );
    else
        poDS->PrintLine( fp, "<gml:featureMember>" );

    if( poFeature->GetFID() == OGRNullFID )
        poFeature->SetFID( iNextGMLId++ );

    int nGMLIdIndex = -1;
    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "    ");
    if (bIsGML3Output)
    {
        nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id");
        if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
            poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s\">",
                poFeatureDefn->GetName(),
                poFeature->GetFieldAsString(nGMLIdIndex) );
        else
            poDS->PrintLine( fp, "<ogr:%s gml:id=\"%s.%ld\">",
                    poFeatureDefn->GetName(),
                    poFeatureDefn->GetName(),
                    poFeature->GetFID() );
    }
    else
        poDS->PrintLine( fp, "<ogr:%s fid=\"F%ld\">",
                poFeatureDefn->GetName(),
                poFeature->GetFID() );

    // Write out Geometry - for now it isn't indented properly.
    /* GML geometries don't like very much the concept of empty geometry */
    OGRGeometry* poGeom = poFeature->GetGeometryRef();
    if( poGeom != NULL && !poGeom->IsEmpty())
    {
        char    *pszGeometry;
        OGREnvelope sGeomBounds;

        poGeom->getEnvelope( &sGeomBounds );
        poDS->GrowExtents( &sGeomBounds );

        if (bIsGML3Output)
        {
            int bCoordSwap;

            if (poGeom->getSpatialReference() == NULL && poSRS != NULL)
                poGeom->assignSpatialReference(poSRS);

            char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
            char szLowerCorner[75], szUpperCorner[75];
            if (bCoordSwap)
            {
                OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, 0, 2);
                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, 0, 2);
            }
            else
            {
                OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, 0, 2);
                OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, 0, 2);
            }
            if (bWriteSpaceIndentation)
                VSIFPrintfL(fp, "      ");
            poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
                             pszSRSName, szLowerCorner, szUpperCorner);
            CPLFree(pszSRSName);
        }

        char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
        if (bIsGML3Output && !poDS->IsLongSRSRequired())
            papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
        pszGeometry = poGeom->exportToGML(papszOptions);
        CSLDestroy(papszOptions);
        if (bWriteSpaceIndentation)
            VSIFPrintfL(fp, "      ");
        poDS->PrintLine( fp, "<ogr:geometryProperty>%s</ogr:geometryProperty>",
                    pszGeometry );
        CPLFree( pszGeometry );
    }

    // Write all "set" fields. 
    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    {
        
        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );

        if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
        {
            const char *pszRaw = poFeature->GetFieldAsString( iField );

            while( *pszRaw == ' ' )
                pszRaw++;

            char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );

            if (poFieldDefn->GetType() == OFTReal)
            {
                /* Use point as decimal separator */
                char* pszComma = strchr(pszEscaped, ',');
                if (pszComma)
                    *pszComma = '.';
            }

            if (bWriteSpaceIndentation)
                VSIFPrintfL(fp, "      ");
            poDS->PrintLine( fp, "<ogr:%s>%s</ogr:%s>",
                        poFieldDefn->GetNameRef(), pszEscaped, 
                        poFieldDefn->GetNameRef() );
            CPLFree( pszEscaped );
        }
    }

    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "    ");
    poDS->PrintLine( fp, "</ogr:%s>", poFeatureDefn->GetName() );
    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "  ");
    if (bIsGML3Output)
        poDS->PrintLine( fp, "</ogr:featureMember>" );
    else
        poDS->PrintLine( fp, "</gml:featureMember>" );

    return OGRERR_NONE;
}
Example #13
0
OGRErr OGRGMLLayer::ICreateFeature( OGRFeature *poFeature )

{
    int bIsGML3Output = poDS->IsGML3Output();
    VSILFILE *fp = poDS->GetOutputFP();
    int bWriteSpaceIndentation = poDS->WriteSpaceIndentation();
    const char* pszPrefix = poDS->GetAppPrefix();
    int bRemoveAppPrefix = poDS->RemoveAppPrefix();

    if( !bWriter )
        return OGRERR_FAILURE;

    poFeature->FillUnsetWithDefault(TRUE, NULL);
    if( !poFeature->Validate( OGR_F_VAL_ALL & ~OGR_F_VAL_GEOM_TYPE & ~OGR_F_VAL_ALLOW_NULL_WHEN_DEFAULT, TRUE ) )
        return OGRERR_FAILURE;

    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "  ");
    if (bIsGML3Output)
    {
        if( bRemoveAppPrefix )
            poDS->PrintLine( fp, "<featureMember>" );
        else
            poDS->PrintLine( fp, "<%s:featureMember>", pszPrefix );
    }
    else
        poDS->PrintLine( fp, "<gml:featureMember>" );

    if( iNextGMLId == 0 )
    {
        bSameSRS = true;
        for( int iGeomField = 1; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
        {
            OGRGeomFieldDefn *poFieldDefn0 = poFeatureDefn->GetGeomFieldDefn(0);
            OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);
            OGRSpatialReference* poSRS0 = poFieldDefn0->GetSpatialRef();
            OGRSpatialReference* poSRS = poFieldDefn->GetSpatialRef();
            if( poSRS0 != NULL && poSRS == NULL )
                bSameSRS = false;
            else if( poSRS0 == NULL && poSRS != NULL )
                bSameSRS = false;
            else if( poSRS0 != NULL && poSRS != NULL &&
                     poSRS0 != poSRS && !poSRS0->IsSame(poSRS) )
            {
                bSameSRS = false;
            }
        }
    }

    if( poFeature->GetFID() == OGRNullFID )
        poFeature->SetFID( iNextGMLId++ );

    int nGMLIdIndex = -1;
    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "    ");
    VSIFPrintfL(fp, "<");
    if( !bRemoveAppPrefix )
        VSIFPrintfL(fp, "%s:", pszPrefix);
    if (bIsGML3Output)
    {
        nGMLIdIndex = poFeatureDefn->GetFieldIndex("gml_id");
        if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
            poDS->PrintLine( fp, "%s gml:id=\"%s\">",
                             poFeatureDefn->GetName(),
                             poFeature->GetFieldAsString(nGMLIdIndex) );
        else
            poDS->PrintLine( fp, "%s gml:id=\"%s." CPL_FRMT_GIB "\">",
                             poFeatureDefn->GetName(),
                             poFeatureDefn->GetName(),
                             poFeature->GetFID() );
    }
    else
    {
        nGMLIdIndex = poFeatureDefn->GetFieldIndex("fid");
        if (bUseOldFIDFormat)
        {
            poDS->PrintLine( fp, "%s fid=\"F" CPL_FRMT_GIB "\">",
                             poFeatureDefn->GetName(),
                             poFeature->GetFID() );
        }
        else if (nGMLIdIndex >= 0 && poFeature->IsFieldSet( nGMLIdIndex ) )
        {
            poDS->PrintLine( fp, "%s fid=\"%s\">",
                             poFeatureDefn->GetName(),
                             poFeature->GetFieldAsString(nGMLIdIndex) );
        }
        else
        {
            poDS->PrintLine( fp, "%s fid=\"%s." CPL_FRMT_GIB "\">",
                             poFeatureDefn->GetName(),
                             poFeatureDefn->GetName(),
                             poFeature->GetFID() );
        }
    }


    for( int iGeomField = 0; iGeomField < poFeatureDefn->GetGeomFieldCount(); iGeomField++ )
    {
        OGRGeomFieldDefn *poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iGeomField);

        // Write out Geometry - for now it isn't indented properly.
        /* GML geometries don't like very much the concept of empty geometry */
        OGRGeometry* poGeom = poFeature->GetGeomFieldRef(iGeomField);
        if( poGeom != NULL && !poGeom->IsEmpty())
        {
            char    *pszGeometry;
            OGREnvelope3D sGeomBounds;

            int nCoordDimension = poGeom->getCoordinateDimension();

            poGeom->getEnvelope( &sGeomBounds );
            if( bSameSRS )
                poDS->GrowExtents( &sGeomBounds, nCoordDimension );

            if (poGeom->getSpatialReference() == NULL && poFieldDefn->GetSpatialRef() != NULL)
                poGeom->assignSpatialReference(poFieldDefn->GetSpatialRef());

            if (bIsGML3Output && poDS->WriteFeatureBoundedBy())
            {
                bool bCoordSwap;

                char* pszSRSName = GML_GetSRSName(poGeom->getSpatialReference(), poDS->IsLongSRSRequired(), &bCoordSwap);
                char szLowerCorner[75], szUpperCorner[75];
                if (bCoordSwap)
                {
                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinY, sGeomBounds.MinX, sGeomBounds.MinZ, nCoordDimension);
                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxY, sGeomBounds.MaxX, sGeomBounds.MaxZ, nCoordDimension);
                }
                else
                {
                    OGRMakeWktCoordinate(szLowerCorner, sGeomBounds.MinX, sGeomBounds.MinY, sGeomBounds.MinZ, nCoordDimension);
                    OGRMakeWktCoordinate(szUpperCorner, sGeomBounds.MaxX, sGeomBounds.MaxY, sGeomBounds.MaxZ, nCoordDimension);
                }
                if (bWriteSpaceIndentation)
                    VSIFPrintfL(fp, "      ");
                poDS->PrintLine( fp, "<gml:boundedBy><gml:Envelope%s%s><gml:lowerCorner>%s</gml:lowerCorner><gml:upperCorner>%s</gml:upperCorner></gml:Envelope></gml:boundedBy>",
                                (nCoordDimension == 3) ? " srsDimension=\"3\"" : "",pszSRSName, szLowerCorner, szUpperCorner);
                CPLFree(pszSRSName);
            }

            char** papszOptions = (bIsGML3Output) ? CSLAddString(NULL, "FORMAT=GML3") : NULL;
            if (bIsGML3Output && !poDS->IsLongSRSRequired())
                papszOptions = CSLAddString(papszOptions, "GML3_LONGSRS=NO");
            const char* pszSRSDimensionLoc = poDS->GetSRSDimensionLoc();
            if( pszSRSDimensionLoc != NULL )
                papszOptions = CSLSetNameValue(papszOptions, "SRSDIMENSION_LOC", pszSRSDimensionLoc);
            if (poDS->IsGML32Output())
            {
                if( poFeatureDefn->GetGeomFieldCount() > 1 )
                    papszOptions = CSLAddString(papszOptions,
                        CPLSPrintf("GMLID=%s.%s." CPL_FRMT_GIB,
                                   poFeatureDefn->GetName(),
                                   poFieldDefn->GetNameRef(),
                                   poFeature->GetFID()));
                else
                    papszOptions = CSLAddString(papszOptions,
                        CPLSPrintf("GMLID=%s.geom." CPL_FRMT_GIB,
                                   poFeatureDefn->GetName(), poFeature->GetFID()));
            }
            if( !bIsGML3Output && OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
            {
                OGRGeometry* poGeomTmp = OGRGeometryFactory::forceTo(
                    poGeom->clone(),OGR_GT_GetLinear(poGeom->getGeometryType()));
                pszGeometry = poGeomTmp->exportToGML(papszOptions);
                delete poGeomTmp;
            }
            else
                pszGeometry = poGeom->exportToGML(papszOptions);
            CSLDestroy(papszOptions);
            if (bWriteSpaceIndentation)
                VSIFPrintfL(fp, "      ");
            if( bRemoveAppPrefix )
                poDS->PrintLine( fp, "<%s>%s</%s>",
                                 poFieldDefn->GetNameRef(),
                                 pszGeometry,
                                 poFieldDefn->GetNameRef() );
            else
                poDS->PrintLine( fp, "<%s:%s>%s</%s:%s>",
                                 pszPrefix, poFieldDefn->GetNameRef(),
                                 pszGeometry,
                                 pszPrefix, poFieldDefn->GetNameRef() );
            CPLFree( pszGeometry );
        }
    }

    // Write all "set" fields.
    for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    {

        OGRFieldDefn *poFieldDefn = poFeatureDefn->GetFieldDefn( iField );

        if( poFeature->IsFieldSet( iField ) && iField != nGMLIdIndex )
        {
            OGRFieldType eType = poFieldDefn->GetType();
            if (eType == OFTStringList )
            {
                char ** papszIter =  poFeature->GetFieldAsStringList( iField );
                while( papszIter != NULL && *papszIter != NULL )
                {
                    char *pszEscaped = OGRGetXML_UTF8_EscapedString( *papszIter );
                    GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                  bRemoveAppPrefix, poFieldDefn, pszEscaped);
                    CPLFree( pszEscaped );

                    papszIter ++;
                }
            }
            else if (eType == OFTIntegerList )
            {
                int nCount = 0;
                const int* panVals = poFeature->GetFieldAsIntegerList( iField, &nCount );
                if(  poFieldDefn->GetSubType() == OFSTBoolean )
                {
                    for(int i = 0; i < nCount; i++)
                    {
                        /* 0 and 1 are OK, but the canonical representation is false and true */
                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                      bRemoveAppPrefix, poFieldDefn,
                                      panVals[i] ? "true" : "false");
                    }
                }
                else
                {
                    for(int i = 0; i < nCount; i++)
                    {
                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                      bRemoveAppPrefix, poFieldDefn,
                                      CPLSPrintf("%d", panVals[i]));
                    }
                }
            }
            else if (eType == OFTInteger64List )
            {
                int nCount = 0;
                const GIntBig* panVals = poFeature->GetFieldAsInteger64List( iField, &nCount );
                if(  poFieldDefn->GetSubType() == OFSTBoolean )
                {
                    for(int i = 0; i < nCount; i++)
                    {
                        /* 0 and 1 are OK, but the canonical representation is false and true */
                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                      bRemoveAppPrefix, poFieldDefn,
                                      panVals[i] ? "true" : "false");
                    }
                }
                else
                {
                    for(int i = 0; i < nCount; i++)
                    {
                        GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                      bRemoveAppPrefix, poFieldDefn,
                                      CPLSPrintf(CPL_FRMT_GIB, panVals[i]));
                    }
                }
            }
            else if (eType == OFTRealList )
            {
                int nCount = 0;
                const double* padfVals = poFeature->GetFieldAsDoubleList( iField, &nCount );
                for(int i = 0; i < nCount; i++)
                {
                    char szBuffer[80];
                    CPLsnprintf( szBuffer, sizeof(szBuffer), "%.15g", padfVals[i]);
                    GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                                  bRemoveAppPrefix, poFieldDefn, szBuffer);
                }
            }
            else if ((eType == OFTInteger || eType == OFTInteger64) &&
                     poFieldDefn->GetSubType() == OFSTBoolean )
            {
                /* 0 and 1 are OK, but the canonical representation is false and true */
                GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                              bRemoveAppPrefix, poFieldDefn,
                              (poFeature->GetFieldAsInteger(iField)) ? "true" : "false");
            }
            else
            {
                const char *pszRaw = poFeature->GetFieldAsString( iField );

                char *pszEscaped = OGRGetXML_UTF8_EscapedString( pszRaw );

                GMLWriteField(poDS, fp, bWriteSpaceIndentation, pszPrefix,
                              bRemoveAppPrefix, poFieldDefn, pszEscaped);
                CPLFree( pszEscaped );
            }
        }
    }

    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "    ");
    if( bRemoveAppPrefix )
        poDS->PrintLine( fp, "</%s>", poFeatureDefn->GetName() );
    else
        poDS->PrintLine( fp, "</%s:%s>", pszPrefix, poFeatureDefn->GetName() );
    if (bWriteSpaceIndentation)
        VSIFPrintfL(fp, "  ");
    if (bIsGML3Output)
    {
        if( bRemoveAppPrefix )
            poDS->PrintLine( fp, "</featureMember>" );
        else
            poDS->PrintLine( fp, "</%s:featureMember>", pszPrefix );
    }
    else
        poDS->PrintLine( fp, "</gml:featureMember>" );

    return OGRERR_NONE;
}
Example #14
0
OGRErr OGRDXFWriterLayer::ICreateFeature( OGRFeature *poFeature )

{
    OGRGeometry *poGeom = poFeature->GetGeometryRef();
    OGRwkbGeometryType eGType = wkbNone;
    
    if( poGeom != NULL )
    {
        if( !poGeom->IsEmpty() )
        {
            OGREnvelope sEnvelope;
            poGeom->getEnvelope(&sEnvelope);
            poDS->UpdateExtent(&sEnvelope);
        }
        eGType = wkbFlatten(poGeom->getGeometryType());
    }

    if( eGType == wkbPoint )
    {
        const char *pszBlockName = poFeature->GetFieldAsString("BlockName");

        // we don't want to treat as a block ref if we are writing blocks layer
        if( pszBlockName != NULL
            && poDS->poBlocksLayer != NULL 
            && poFeature->GetDefnRef() == poDS->poBlocksLayer->GetLayerDefn())
            pszBlockName = NULL;

        // We don't want to treat as a blocks ref if the block is not defined
        if( pszBlockName 
            && poDS->oHeaderDS.LookupBlock(pszBlockName) == NULL )
        {
            if( poDS->poBlocksLayer == NULL
                || poDS->poBlocksLayer->FindBlock(pszBlockName) == NULL )
                pszBlockName = NULL;
        }
                                  
        if( pszBlockName != NULL )
            return WriteINSERT( poFeature );
            
        else if( poFeature->GetStyleString() != NULL
            && EQUALN(poFeature->GetStyleString(),"LABEL",5) )
            return WriteTEXT( poFeature );
        else
            return WritePOINT( poFeature );
    }
    else if( eGType == wkbLineString 
             || eGType == wkbMultiLineString )
        return WritePOLYLINE( poFeature );

    else if( eGType == wkbPolygon 
             || eGType == wkbMultiPolygon )
    {
        if( bWriteHatch )
            return WriteHATCH( poFeature );
        else
            return WritePOLYLINE( poFeature );
    }

    // Explode geometry collections into multiple entities.
    else if( eGType == wkbGeometryCollection )
    {
        OGRGeometryCollection *poGC = (OGRGeometryCollection *)
            poFeature->StealGeometry();
        int iGeom;

        for( iGeom = 0; iGeom < poGC->getNumGeometries(); iGeom++ )
        {
            poFeature->SetGeometry( poGC->getGeometryRef(iGeom) );
                                    
            OGRErr eErr = CreateFeature( poFeature );
            
            if( eErr != OGRERR_NONE )
                return eErr;

        }
        
        poFeature->SetGeometryDirectly( poGC );
        return OGRERR_NONE;
    }
    else 
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "No known way to write feature with geometry '%s'.",
                  OGRGeometryTypeToName(eGType) );
        return OGRERR_FAILURE;
    }
}
Example #15
0
OGRLayer * OGRSQLiteExecuteSQL( OGRDataSource* poDS,
                                const char *pszStatement,
                                OGRGeometry *poSpatialFilter,
                                const char *pszDialect )
{
    char* pszTmpDBName = (char*) CPLMalloc(256);
    sprintf(pszTmpDBName, "/vsimem/ogr2sqlite/temp_%p.db", pszTmpDBName);

    OGRSQLiteDataSource* poSQLiteDS = NULL;
    int nRet;
    int bSpatialiteDB = FALSE;

    CPLString osOldVal;
    const char* pszOldVal = CPLGetConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", NULL);
    if( pszOldVal != NULL )
    {
        osOldVal = pszOldVal;
        pszOldVal = osOldVal.c_str();
    }

/* -------------------------------------------------------------------- */
/*      Create in-memory sqlite/spatialite DB                           */
/* -------------------------------------------------------------------- */

#ifdef HAVE_SPATIALITE

/* -------------------------------------------------------------------- */
/*      Creating an empty spatialite DB (with spatial_ref_sys populated */
/*      has a non-neglectable cost. So at the first attempt, let's make */
/*      one and cache it for later use.                                 */
/* -------------------------------------------------------------------- */
#if 1
    static vsi_l_offset nEmptyDBSize = 0;
    static GByte* pabyEmptyDB = NULL;
    {
        static void* hMutex = NULL;
        CPLMutexHolder oMutexHolder(&hMutex);
        static int bTried = FALSE;
        if( !bTried &&
            CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
        {
            bTried = TRUE;
            char* pszCachedFilename = (char*) CPLMalloc(256);
            sprintf(pszCachedFilename, "/vsimem/ogr2sqlite/reference_%p.db",pszCachedFilename);
            char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
            OGRSQLiteDataSource* poCachedDS = new OGRSQLiteDataSource();
            nRet = poCachedDS->Create( pszCachedFilename, papszOptions );
            CSLDestroy(papszOptions);
            papszOptions = NULL;
            delete poCachedDS;
            if( nRet )
                /* Note: the reference file keeps the ownership of the data, so that */
                /* it gets released with VSICleanupFileManager() */
                pabyEmptyDB = VSIGetMemFileBuffer( pszCachedFilename, &nEmptyDBSize, FALSE );
            CPLFree( pszCachedFilename );
        }
    }

    /* The following configuration option is usefull mostly for debugging/testing */
    if( pabyEmptyDB != NULL && CSLTestBoolean(CPLGetConfigOption("OGR_SQLITE_DIALECT_USE_SPATIALITE", "YES")) )
    {
        GByte* pabyEmptyDBClone = (GByte*)VSIMalloc(nEmptyDBSize);
        if( pabyEmptyDBClone == NULL )
        {
            CPLFree(pszTmpDBName);
            return NULL;
        }
        memcpy(pabyEmptyDBClone, pabyEmptyDB, nEmptyDBSize);
        VSIFCloseL(VSIFileFromMemBuffer( pszTmpDBName, pabyEmptyDBClone, nEmptyDBSize, TRUE ));

        poSQLiteDS = new OGRSQLiteDataSource();
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
        nRet = poSQLiteDS->Open( pszTmpDBName, TRUE );
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
        if( !nRet )
        {
            /* should not happen really ! */
            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);
            return NULL;
        }
        bSpatialiteDB = TRUE;
    }
#else
    /* No caching version */
    poSQLiteDS = new OGRSQLiteDataSource();
    char** papszOptions = CSLAddString(NULL, "SPATIALITE=YES");
    CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
    nRet = poSQLiteDS->Create( pszTmpDBName, papszOptions );
    CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
    CSLDestroy(papszOptions);
    papszOptions = NULL;
    if( nRet )
    {
        bSpatialiteDB = TRUE;
    }
#endif

    else
    {
        delete poSQLiteDS;
        poSQLiteDS = NULL;
#else // HAVE_SPATIALITE
    if( TRUE )
    {
#endif // HAVE_SPATIALITE
        poSQLiteDS = new OGRSQLiteDataSource();
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", "NO");
        nRet = poSQLiteDS->Create( pszTmpDBName, NULL );
        CPLSetThreadLocalConfigOption("OGR_SQLITE_STATIC_VIRTUAL_OGR", pszOldVal);
        if( !nRet )
        {
            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);
            return NULL;
        }
    }

/* -------------------------------------------------------------------- */
/*      Attach the Virtual Table OGR2SQLITE module to it.               */
/* -------------------------------------------------------------------- */
    OGR2SQLITEModule* poModule = OGR2SQLITE_Setup(poDS, poSQLiteDS);
    sqlite3* hDB = poSQLiteDS->GetDB();

/* -------------------------------------------------------------------- */
/*      Analysze the statement to determine which tables will be used.  */
/* -------------------------------------------------------------------- */
    std::set<LayerDesc> oSetLayers;
    std::set<CPLString> oSetSpatialIndex;
    CPLString osModifiedSQL;
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers,
                                     oSetSpatialIndex, osModifiedSQL);
    std::set<LayerDesc>::iterator oIter = oSetLayers.begin();

    if( strcmp(pszStatement, osModifiedSQL.c_str()) != 0 )
        CPLDebug("OGR", "Modified SQL: %s", osModifiedSQL.c_str());
    pszStatement = osModifiedSQL.c_str(); /* do not use it anymore */

    int bFoundOGRStyle = ( osModifiedSQL.ifind("OGR_STYLE") != std::string::npos );

/* -------------------------------------------------------------------- */
/*      For each of those tables, create a Virtual Table.               */
/* -------------------------------------------------------------------- */
    for(; oIter != oSetLayers.end(); ++oIter)
    {
        const LayerDesc& oLayerDesc = *oIter;
        /*CPLDebug("OGR", "Layer desc : %s, %s, %s, %s",
                 oLayerDesc.osOriginalStr.c_str(),
                 oLayerDesc.osSubstitutedName.c_str(),
                 oLayerDesc.osDSName.c_str(),
                 oLayerDesc.osLayerName.c_str());*/

        CPLString osSQL;
        OGRLayer* poLayer = NULL;
        CPLString osTableName;
        int nExtraDS;
        if( oLayerDesc.osDSName.size() == 0 )
        {
            poLayer = poDS->GetLayerByName(oLayerDesc.osLayerName);
            /* Might be a false positive (unlikely) */
            if( poLayer == NULL )
                continue;

            osTableName = oLayerDesc.osLayerName;

            nExtraDS = -1;

            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
                         OGRSQLiteEscapeName(osTableName).c_str(),
                         nExtraDS,
                         OGRSQLiteEscape(osTableName).c_str(),
                         bFoundOGRStyle);
        }
        else
        {
            OGRDataSource* poOtherDS = (OGRDataSource* )
                OGROpen(oLayerDesc.osDSName, FALSE, NULL);
            if( poOtherDS == NULL )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Cannot open datasource '%s'",
                         oLayerDesc.osDSName.c_str() );
                delete poSQLiteDS;
                VSIUnlink(pszTmpDBName);
                CPLFree(pszTmpDBName);
                return NULL;
            }
            
            poLayer = poOtherDS->GetLayerByName(oLayerDesc.osLayerName);
            if( poLayer == NULL )
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Cannot find layer '%s' in '%s'",
                         oLayerDesc.osLayerName.c_str(),
                         oLayerDesc.osDSName.c_str() );
                delete poOtherDS;
                delete poSQLiteDS;
                VSIUnlink(pszTmpDBName);
                CPLFree(pszTmpDBName);
                return NULL;
            }

            osTableName = oLayerDesc.osSubstitutedName;

            nExtraDS = OGR2SQLITE_AddExtraDS(poModule, poOtherDS);

            osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING VirtualOGR(%d,'%s',%d)",
                         OGRSQLiteEscapeName(osTableName).c_str(),
                         nExtraDS,
                         OGRSQLiteEscape(oLayerDesc.osLayerName).c_str(),
                         bFoundOGRStyle);
        }

        char* pszErrMsg = NULL;
        int rc = sqlite3_exec( hDB, osSQL.c_str(),
                               NULL, NULL, &pszErrMsg );
        if( rc != SQLITE_OK )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Cannot create virtual table for layer '%s' : %s",
                     osTableName.c_str(), pszErrMsg);
            sqlite3_free(pszErrMsg);
            continue;
        }

        if( poLayer->GetGeomType() == wkbNone )
            continue;

        CPLString osGeomColRaw(OGR2SQLITE_GetNameForGeometryColumn(poLayer));
        const char* pszGeomColRaw = osGeomColRaw.c_str();

        CPLString osGeomColEscaped(OGRSQLiteEscape(pszGeomColRaw));
        const char* pszGeomColEscaped = osGeomColEscaped.c_str();

        CPLString osLayerNameEscaped(OGRSQLiteEscape(osTableName));
        const char* pszLayerNameEscaped = osLayerNameEscaped.c_str();

        CPLString osIdxNameRaw(CPLSPrintf("idx_%s_%s",
                        oLayerDesc.osLayerName.c_str(), pszGeomColRaw));
        CPLString osIdxNameEscaped(OGRSQLiteEscapeName(osIdxNameRaw));

        /* Make sure that the SRS is injected in spatial_ref_sys */
        OGRSpatialReference* poSRS = poLayer->GetSpatialRef();
        int nSRSId = poSQLiteDS->GetUndefinedSRID();
        if( poSRS != NULL )
            nSRSId = poSQLiteDS->FetchSRSId(poSRS);

        int bCreateSpatialIndex = FALSE;
        if( !bSpatialiteDB )
        {
            osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                        "f_geometry_column, geometry_format, geometry_type, "
                        "coord_dimension, srid) "
                        "VALUES ('%s','%s','SpatiaLite',%d,%d,%d)",
                        pszLayerNameEscaped,
                        pszGeomColEscaped,
                         (int) wkbFlatten(poLayer->GetGeomType()),
                        ( poLayer->GetGeomType() & wkb25DBit ) ? 3 : 2,
                        nSRSId);
        }
#ifdef HAVE_SPATIALITE
        else
        {
            /* We detect the need for creating a spatial index by 2 means : */

            /* 1) if there's an explicit reference to a 'idx_layername_geometrycolumn' */
            /*   table in the SQL --> old/traditionnal way of requesting spatial indices */
            /*   with spatialite. */

            std::set<LayerDesc>::iterator oIter2 = oSetLayers.begin();
            for(; oIter2 != oSetLayers.end(); ++oIter2)
            {
                const LayerDesc& oLayerDescIter = *oIter2;
                if( EQUAL(oLayerDescIter.osLayerName, osIdxNameRaw) )
                {
                     bCreateSpatialIndex = TRUE;
                     break;
                }
            }

            /* 2) or if there's a SELECT FROM SpatialIndex WHERE f_table_name = 'layername' */
            if( !bCreateSpatialIndex )
            {
                std::set<CPLString>::iterator oIter3 = oSetSpatialIndex.begin();
                for(; oIter3 != oSetSpatialIndex.end(); ++oIter3)
                {
                    const CPLString& osNameIter = *oIter3;
                    if( EQUAL(osNameIter, oLayerDesc.osLayerName) )
                    {
                        bCreateSpatialIndex = TRUE;
                        break;
                    }
                }
            }

            if( poSQLiteDS->HasSpatialite4Layout() )
            {
                int nGeomType = poLayer->GetGeomType();
                int nCoordDimension = 2;
                if( nGeomType & wkb25DBit )
                {
                    nGeomType += 1000;
                    nCoordDimension = 3;
                }

                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                            "f_geometry_column, geometry_type, coord_dimension, "
                            "srid, spatial_index_enabled) "
                            "VALUES ('%s',Lower('%s'),%d ,%d ,%d, %d)",
                            pszLayerNameEscaped,
                            pszGeomColEscaped, nGeomType,
                            nCoordDimension,
                            nSRSId, bCreateSpatialIndex );
            }
            else
            {
                const char *pszGeometryType = OGRToOGCGeomType(poLayer->GetGeomType());
                if (pszGeometryType[0] == '\0')
                    pszGeometryType = "GEOMETRY";

                osSQL.Printf("INSERT INTO geometry_columns (f_table_name, "
                            "f_geometry_column, type, coord_dimension, "
                            "srid, spatial_index_enabled) "
                            "VALUES ('%s','%s','%s','%s',%d, %d)",
                            pszLayerNameEscaped,
                            pszGeomColEscaped, pszGeometryType,
                            ( poLayer->GetGeomType() & wkb25DBit ) ? "XYZ" : "XY",
                            nSRSId, bCreateSpatialIndex );
            }
        }
#endif // HAVE_SPATIALITE
        sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );

#ifdef HAVE_SPATIALITE
/* -------------------------------------------------------------------- */
/*      Should we create a spatial index ?.                             */
/* -------------------------------------------------------------------- */
        if( !bSpatialiteDB || !bCreateSpatialIndex )
            continue;

        CPLDebug("SQLITE", "Create spatial index %s", osIdxNameRaw.c_str());

        /* ENABLE_VIRTUAL_OGR_SPATIAL_INDEX is not defined */
#ifdef ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" USING "
                     "VirtualOGRSpatialIndex(%d, '%s', pkid, xmin, xmax, ymin, ymax)",
                     osIdxNameEscaped.c_str(),
                     nExtraDS,
                     OGRSQLiteEscape(oLayerDesc.osLayerName).c_str());

        rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );
        if( rc != SQLITE_OK )
        {
            CPLDebug("SQLITE",
                     "Error occured during spatial index creation : %s",
                     sqlite3_errmsg(hDB));
        }
#else //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX
        rc = sqlite3_exec( hDB, "BEGIN", NULL, NULL, NULL );

        osSQL.Printf("CREATE VIRTUAL TABLE \"%s\" "
                     "USING rtree(pkid, xmin, xmax, ymin, ymax)",
                      osIdxNameEscaped.c_str());

        if( rc == SQLITE_OK )
            rc = sqlite3_exec( hDB, osSQL.c_str(), NULL, NULL, NULL );

        sqlite3_stmt *hStmt = NULL;
        if( rc == SQLITE_OK )
        {
            const char* pszInsertInto = CPLSPrintf(
                "INSERT INTO \"%s\" (pkid, xmin, xmax, ymin, ymax) "
                "VALUES (?,?,?,?,?)", osIdxNameEscaped.c_str());
            rc = sqlite3_prepare(hDB, pszInsertInto, -1, &hStmt, NULL);
        }

        OGRFeature* poFeature;
        OGREnvelope sEnvelope;
        OGR2SQLITE_IgnoreAllFieldsExceptGeometry(poLayer);
        poLayer->ResetReading();

        while( rc == SQLITE_OK &&
               (poFeature = poLayer->GetNextFeature()) != NULL )
        {
            OGRGeometry* poGeom = poFeature->GetGeometryRef();
            if( poGeom != NULL && !poGeom->IsEmpty() )
            {
                poGeom->getEnvelope(&sEnvelope);
                sqlite3_bind_int64(hStmt, 1,
                                   (sqlite3_int64) poFeature->GetFID() );
                sqlite3_bind_double(hStmt, 2, sEnvelope.MinX);
                sqlite3_bind_double(hStmt, 3, sEnvelope.MaxX);
                sqlite3_bind_double(hStmt, 4, sEnvelope.MinY);
                sqlite3_bind_double(hStmt, 5, sEnvelope.MaxY);
                rc = sqlite3_step(hStmt);
                if( rc == SQLITE_OK || rc == SQLITE_DONE )
                    rc = sqlite3_reset(hStmt);
            }
            delete poFeature;
        }

        poLayer->SetIgnoredFields(NULL);

        sqlite3_finalize(hStmt);

        if( rc == SQLITE_OK )
            rc = sqlite3_exec( hDB, "COMMIT", NULL, NULL, NULL );
        else
        {
            CPLDebug("SQLITE",
                     "Error occured during spatial index creation : %s",
                     sqlite3_errmsg(hDB));
            rc = sqlite3_exec( hDB, "ROLLBACK", NULL, NULL, NULL );
        }
#endif //  ENABLE_VIRTUAL_OGR_SPATIAL_INDEX

#endif // HAVE_SPATIALITE

    }

/* -------------------------------------------------------------------- */
/*      Reload, so that virtual tables are recognized                   */
/* -------------------------------------------------------------------- */
    poSQLiteDS->ReloadLayers();

/* -------------------------------------------------------------------- */
/*      Prepare the statement.                                          */
/* -------------------------------------------------------------------- */
    /* This will speed-up layer creation */
    /* ORDER BY are costly to evaluate and are not necessary to establish */
    /* the layer definition. */
    int bUseStatementForGetNextFeature = TRUE;
    int bEmptyLayer = FALSE;

    sqlite3_stmt *hSQLStmt = NULL;
    int rc = sqlite3_prepare( hDB,
                              pszStatement, strlen(pszStatement),
                              &hSQLStmt, NULL );

    if( rc != SQLITE_OK )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                "In ExecuteSQL(): sqlite3_prepare(%s):\n  %s",
                pszStatement, sqlite3_errmsg(hDB) );

        if( hSQLStmt != NULL )
        {
            sqlite3_finalize( hSQLStmt );
        }

        delete poSQLiteDS;
        VSIUnlink(pszTmpDBName);
        CPLFree(pszTmpDBName);

        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Do we get a resultset?                                          */
/* -------------------------------------------------------------------- */
    rc = sqlite3_step( hSQLStmt );
    if( rc != SQLITE_ROW )
    {
        if ( rc != SQLITE_DONE )
        {
            CPLError( CE_Failure, CPLE_AppDefined,
                  "In ExecuteSQL(): sqlite3_step(%s):\n  %s",
                  pszStatement, sqlite3_errmsg(hDB) );

            sqlite3_finalize( hSQLStmt );

            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);

            return NULL;
        }

        if( !EQUALN(pszStatement, "SELECT ", 7) )
        {

            sqlite3_finalize( hSQLStmt );

            delete poSQLiteDS;
            VSIUnlink(pszTmpDBName);
            CPLFree(pszTmpDBName);

            return NULL;
        }

        bUseStatementForGetNextFeature = FALSE;
        bEmptyLayer = TRUE;
    }

/* -------------------------------------------------------------------- */
/*      Create layer.                                                   */
/* -------------------------------------------------------------------- */
    OGRSQLiteSelectLayer *poLayer = NULL;

    poLayer = new OGRSQLiteExecuteSQLLayer( pszTmpDBName,
                                            poSQLiteDS, pszStatement, hSQLStmt,
                                            bUseStatementForGetNextFeature, bEmptyLayer );

    if( poSpatialFilter != NULL )
        poLayer->SetSpatialFilter( poSpatialFilter );

    return poLayer;
}

/************************************************************************/
/*                   OGRSQLiteGetReferencedLayers()                     */
/************************************************************************/

std::set<LayerDesc> OGRSQLiteGetReferencedLayers(const char* pszStatement)
{
/* -------------------------------------------------------------------- */
/*      Analysze the statement to determine which tables will be used.  */
/* -------------------------------------------------------------------- */
    std::set<LayerDesc> oSetLayers;
    std::set<CPLString> oSetSpatialIndex;
    CPLString osModifiedSQL;
    OGR2SQLITEGetPotentialLayerNames(pszStatement, oSetLayers,
                                     oSetSpatialIndex, osModifiedSQL);

    return oSetLayers;
}
Example #16
0
void OGRJMLLayer::endElementCbk(const char *pszName)
{
    if (bStopParsing) return;

    nWithoutEventCounter = 0;

    currentDepth--;

    if( nAttributeElementDepth == currentDepth )
    {
        if( nElementValueLen )
            poFeature->SetField(iAttr, pszElementValue);
        else if( iAttr >= 0 )
            poFeature->SetFieldNull(iAttr);
        nAttributeElementDepth = 0;
        StopAccumulate();
    }
    else if( nGeometryElementDepth > 0 && currentDepth > nGeometryElementDepth )
    {
        AddStringToElementValue("</", 2);
        AddStringToElementValue(pszName, static_cast<int>(strlen(pszName)));
        AddStringToElementValue(">", 1);
    }
    else if( nGeometryElementDepth == currentDepth )
    {
        if( nElementValueLen )
        {
            OGRGeometry* poGeom = reinterpret_cast<OGRGeometry *>(
                OGR_G_CreateFromGML(pszElementValue) );
            if( poGeom != nullptr &&
                poGeom->getGeometryType() == wkbGeometryCollection &&
                poGeom->IsEmpty() )
            {
                delete poGeom;
            }
            else
                poFeature->SetGeometryDirectly(poGeom);
        }

        nGeometryElementDepth = 0;
        StopAccumulate();
    }
    else if( nFeatureElementDepth == currentDepth )
    {
        /* Builds a style string from R_G_B if we don't already have a */
        /* style string */
        OGRGeometry* poGeom = poFeature->GetGeometryRef();
        unsigned int R = 0;
        unsigned int G = 0;
        unsigned int B = 0;
        if( iRGBField >= 0 && poFeature->IsFieldSetAndNotNull(iRGBField) &&
            poFeature->GetStyleString() == nullptr && poGeom != nullptr &&
            sscanf(poFeature->GetFieldAsString(iRGBField),
                       "%02X%02X%02X", &R, &G, &B) == 3 )
        {
            const OGRwkbGeometryType eGeomType
                = wkbFlatten(poGeom->getGeometryType());
            if( eGeomType == wkbPoint || eGeomType == wkbMultiPoint ||
                eGeomType == wkbLineString || eGeomType == wkbMultiLineString )
            {
                poFeature->SetStyleString(
                    CPLSPrintf("PEN(c:#%02X%02X%02X)", R, G, B));
            }
            else if( eGeomType == wkbPolygon || eGeomType == wkbMultiPolygon )
            {
                poFeature->SetStyleString(
                    CPLSPrintf("BRUSH(fc:#%02X%02X%02X)", R, G, B));
            }
        }

        poFeature->SetFID(nNextFID++);

        if( (m_poFilterGeom == nullptr
                || FilterGeometry( poGeom ) )
            && (m_poAttrQuery == nullptr
                || m_poAttrQuery->Evaluate( poFeature )) )
        {
            ppoFeatureTab = static_cast<OGRFeature**>(
                CPLRealloc(ppoFeatureTab,
                           sizeof(OGRFeature*) * (nFeatureTabLength + 1)) );
            ppoFeatureTab[nFeatureTabLength] = poFeature;
            nFeatureTabLength++;
        }
        else
        {
            delete poFeature;
        }
        poFeature = nullptr;
        iAttr = -1;

        nFeatureElementDepth = 0;
    }
    else if( nFeatureCollectionDepth == currentDepth )
    {
        nFeatureCollectionDepth = 0;
    }
}