Exemplo n.º 1
0
static CPLErr
BlendMaskGenerator(
#ifndef HAVE_GEOS
                    CPL_UNUSED int nXOff, CPL_UNUSED int nYOff,
                    CPL_UNUSED int nXSize, CPL_UNUSED int nYSize,
                    CPL_UNUSED GByte *pabyPolyMask,
                    CPL_UNUSED float *pafValidityMask,
                    CPL_UNUSED OGRGeometryH hPolygon,
                    CPL_UNUSED double dfBlendDist
#else
                    int nXOff, int nYOff, int nXSize, int nYSize,
                    GByte *pabyPolyMask, float *pafValidityMask,
                    OGRGeometryH hPolygon, double dfBlendDist
#endif
)
{
#ifndef HAVE_GEOS
    CPLError( CE_Failure, CPLE_AppDefined,
              "Blend distance support not available without the GEOS library.");
    return CE_Failure;

#else /* HAVE_GEOS */

/* -------------------------------------------------------------------- */
/*      Convert the polygon into a collection of lines so that we       */
/*      measure distance from the edge even on the inside.              */
/* -------------------------------------------------------------------- */
    OGRGeometry *poLines
        = OGRGeometryFactory::forceToMultiLineString(
            ((OGRGeometry *) hPolygon)->clone() );

/* -------------------------------------------------------------------- */
/*      Prepare a clipping polygon a bit bigger than the area of        */
/*      interest in the hopes of simplifying the cutline down to        */
/*      stuff that will be relavent for this area of interest.          */
/* -------------------------------------------------------------------- */
    CPLString osClipRectWKT;

    osClipRectWKT.Printf( "POLYGON((%g %g,%g %g,%g %g,%g %g,%g %g))", 
                          nXOff - (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1), 
                          nXOff + nXSize + (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1), 
                          nXOff + nXSize + (dfBlendDist+1), 
                          nYOff + nYSize + (dfBlendDist+1), 
                          nXOff - (dfBlendDist+1), 
                          nYOff + nYSize + (dfBlendDist+1), 
                          nXOff - (dfBlendDist+1), 
                          nYOff - (dfBlendDist+1) );
    
    OGRPolygon *poClipRect = NULL;
    char *pszWKT = (char *) osClipRectWKT.c_str();
    
    OGRGeometryFactory::createFromWkt( &pszWKT, NULL, 
                                       (OGRGeometry**) (&poClipRect) );

    if( poClipRect )
    {

        /***** if it doesnt intersect the polym zero the mask and return *****/

        if ( ! ((OGRGeometry *) hPolygon)->Intersects( poClipRect ) )
        {
            
            memset( pafValidityMask, 0, sizeof(float) * nXSize * nYSize );

            delete poLines;
            delete poClipRect;

            return CE_None;
        }

        /***** if it doesnt intersect the line at all just return *****/
         
        else if ( ! ((OGRGeometry *) poLines)->Intersects( poClipRect ) )
        {
            delete poLines;
            delete poClipRect;

            return CE_None;
        }

        OGRGeometry *poClippedLines = 
            poLines->Intersection( poClipRect );
        delete poLines;
        poLines = poClippedLines;
        delete poClipRect;
    }

/* -------------------------------------------------------------------- */
/*      Convert our polygon into GEOS format, and compute an            */
/*      envelope to accelerate later distance operations.               */
/* -------------------------------------------------------------------- */
    OGREnvelope sEnvelope;
    int iXMin, iYMin, iXMax, iYMax;
    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
    GEOSGeom poGEOSPoly;

    poGEOSPoly = poLines->exportToGEOS(hGEOSCtxt);
    OGR_G_GetEnvelope( hPolygon, &sEnvelope );

    delete poLines;

    /***** this check was already done in the calling *****/
    /***** function and should never be true          *****/

    /*if( sEnvelope.MinY - dfBlendDist > nYOff+nYSize 
        || sEnvelope.MaxY + dfBlendDist < nYOff 
        || sEnvelope.MinX - dfBlendDist > nXOff+nXSize
        || sEnvelope.MaxX + dfBlendDist < nXOff )
        return CE_None;
    */


    iXMin = MAX(0,(int) floor(sEnvelope.MinX - dfBlendDist - nXOff));
    iXMax = MIN(nXSize, (int) ceil(sEnvelope.MaxX + dfBlendDist - nXOff));
    iYMin = MAX(0,(int) floor(sEnvelope.MinY - dfBlendDist - nYOff));
    iYMax = MIN(nYSize, (int) ceil(sEnvelope.MaxY + dfBlendDist - nYOff));

/* -------------------------------------------------------------------- */
/*      Loop over potential area within blend line distance,            */
/*      processing each pixel.                                          */
/* -------------------------------------------------------------------- */
    int iY, iX;
    double dfLastDist;
    
    for( iY = 0; iY < nYSize; iY++ )
    {
        dfLastDist = 0.0;

        for( iX = 0; iX < nXSize; iX++ )
        {
            if( iX < iXMin || iX >= iXMax
                || iY < iYMin || iY > iYMax
                || dfLastDist > dfBlendDist + 1.5 )
            {
                if( pabyPolyMask[iX + iY * nXSize] == 0 )
                    pafValidityMask[iX + iY * nXSize] = 0.0;

                dfLastDist -= 1.0;
                continue;
            }
            
            double dfDist, dfRatio;
            CPLString osPointWKT;
            GEOSGeom poGEOSPoint;

            osPointWKT.Printf( "POINT(%d.5 %d.5)", iX + nXOff, iY + nYOff );
            poGEOSPoint = GEOSGeomFromWKT_r( hGEOSCtxt, osPointWKT );

            GEOSDistance_r( hGEOSCtxt, poGEOSPoly, poGEOSPoint, &dfDist );
            GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoint );

            dfLastDist = dfDist;

            if( dfDist > dfBlendDist )
            {
                if( pabyPolyMask[iX + iY * nXSize] == 0 )
                    pafValidityMask[iX + iY * nXSize] = 0.0;

                continue;
            }

            if( pabyPolyMask[iX + iY * nXSize] == 0 )
            {
                /* outside */
                dfRatio = 0.5 - (dfDist / dfBlendDist) * 0.5;
            }
            else 
            {
                /* inside */
                dfRatio = 0.5 + (dfDist / dfBlendDist) * 0.5;
            }                

            pafValidityMask[iX + iY * nXSize] *= (float)dfRatio;
        }
    }

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
    GEOSGeom_destroy_r( hGEOSCtxt, poGEOSPoly );
    OGRGeometry::freeGEOSContext( hGEOSCtxt );

    return CE_None;

#endif /* HAVE_GEOS */
}
Exemplo n.º 2
0
void lasclip(std::string &outfile, std::string &shapefile,
		std::string &layername, std::vector<std::string> &files,
		std::set<int> &classes, bool quiet) {

	if (outfile.empty())
		g_argerr("An output file is required.");
	if (shapefile.empty())
		g_argerr("A shape file is required.");
	if (files.size() == 0)
		g_argerr("At least one input file is required.");
	if (classes.size() == 0)
		g_warn("No classes specified, matching all classes.");

	/* Attempt to open and load geometries from the shape file. */
	OGRRegisterAll();
	OGRLayer *layer;
	OGRFeature *feat;
	OGRGeometry *og;
	OGRwkbGeometryType type;
	gg::GeometryCollection *geomColl;
	gg::Geometry *geom;

	OGRDataSource *ds = OGRSFDriverRegistrar::Open(shapefile.c_str(), FALSE);
	if (ds == nullptr)
		g_runerr("Couldn't open shapefile.");
	if (layername.empty()) {
		layer = ds->GetLayer(0);
	} else {
		layer = ds->GetLayerByName(layername.c_str());
	}
	if (layer == nullptr)
		g_runerr("Couldn't get layer.");

	type = layer->GetGeomType();
	if (type != wkbPolygon && type != wkbMultiPolygon)
		g_runerr("Geometry must be polygon or multipolygon.");

	const GEOSContextHandle_t gctx = OGRGeometry::createGEOSContext();
	const gg::GeometryFactory *gf = gg::GeometryFactory::getDefaultInstance();
	const gg::CoordinateSequenceFactory *cf =
			gf->getCoordinateSequenceFactory();
	std::vector<gg::Geometry *> geoms;

	while ((feat = layer->GetNextFeature()) != NULL) {
		og = feat->GetGeometryRef();
		geom = (gg::Geometry *) og->exportToGEOS(gctx);
		geoms.push_back(geom);
	}

	GDALClose(ds);

	if (geoms.size() == 0)
		g_runerr("No geometries were found.");

	/* The geometry collection is used for checking whether a las file intersects
	 the region of interest. */
	geomColl = gf->createGeometryCollection(geoms);
	const gg::Envelope *env = geomColl->getEnvelopeInternal();
	Bounds cbounds(env->getMinX(), env->getMinY(), env->getMaxX(),
			env->getMaxY());

	/* Loop over files and figure out which ones are relevant. */
	liblas::ReaderFactory rf;
	liblas::Header *dsth = nullptr;
	std::vector<unsigned int> indices;

	for (unsigned int i = 0; i < files.size(); ++i) {

		std::ifstream in(files[i].c_str(), std::ios::in | std::ios::binary);
		liblas::Reader r = rf.CreateWithStream(in);
		liblas::Header h = r.GetHeader();

		if (i == 0)
			dsth = new liblas::Header(h);

		std::vector<gg::Coordinate> coords;
		coords.push_back(gg::Coordinate(h.GetMinX(), h.GetMinY()));
		coords.push_back(gg::Coordinate(h.GetMaxX(), h.GetMinY()));
		coords.push_back(gg::Coordinate(h.GetMaxX(), h.GetMaxY()));
		coords.push_back(gg::Coordinate(h.GetMinX(), h.GetMaxY()));
		coords.push_back(gg::Coordinate(h.GetMinX(), h.GetMinY()));

		gg::CoordinateSequence *cs = cf->create(&coords);
		gg::LinearRing *lr = gf->createLinearRing(cs);
		gg::Polygon *bounds = gf->createPolygon(lr, NULL);

		if (bounds->intersects(geomColl))
			indices.push_back(i);

		in.close();
	}

	if (indices.size() == 0)
		g_runerr("No files matched the given bounds.");

	std::ofstream out(outfile, std::ios::out | std::ios::binary);
	liblas::WriterFactory wf;
	liblas::Writer w(out, *dsth);
	liblas::Header::RecordsByReturnArray recs;
	int count = 0;

	double bounds[] = { G_DBL_MAX_POS, G_DBL_MAX_NEG, G_DBL_MAX_POS,
			G_DBL_MAX_NEG, G_DBL_MAX_POS, G_DBL_MAX_NEG };

	g_trace("Using points from " << indices.size() << " files.");

	for (int i = 0; i < 5; ++i)
		recs.push_back(0);

	for (unsigned int i = 0; i < indices.size(); ++i) {

		std::ifstream in(files[indices[i]].c_str(),
				std::ios::in | std::ios::binary);
		liblas::Reader r = rf.CreateWithStream(in);
		liblas::Header h = r.GetHeader();

		g_trace("Processing file " << files[indices[i]]);

		while (r.ReadNextPoint()) {
			liblas::Point pt = r.GetPoint();

			int cls = pt.GetClassification().GetClass();
			if (classes.size() > 0 && !Util::inList(classes, cls))
				continue;

			double x = pt.GetX();
			double y = pt.GetY();
			const gg::Coordinate c(x, y);
			gg::Point *p = gf->createPoint(c);

			if (cbounds.contains(x, y) && geomColl->contains(p)) {
				++recs[cls];
				++count;
				w.WritePoint(pt);
				if (pt.GetX() < bounds[0])
					bounds[0] = pt.GetX();
				if (pt.GetX() > bounds[1])
					bounds[1] = pt.GetX();
				if (pt.GetY() < bounds[2])
					bounds[2] = pt.GetY();
				if (pt.GetY() > bounds[3])
					bounds[3] = pt.GetY();
				if (pt.GetZ() < bounds[4])
					bounds[4] = pt.GetZ();
				if (pt.GetZ() > bounds[5])
					bounds[5] = pt.GetZ();
			}
		}

		in.close();
	}

	// Set the total count and update the point record counts.
	dsth->SetMin(bounds[0], bounds[2], bounds[4]);
	dsth->SetMax(bounds[1], bounds[3], bounds[5]);
	dsth->SetPointRecordsCount(count);
	for (unsigned int i = 0; i < recs.size(); ++i)
		dsth->SetPointRecordsByReturnCount(i, recs[i]);

	w.WriteHeader();

}
Exemplo n.º 3
0
void OGRILI1Layer::PolygonizeAreaLayer()
{
    if (poAreaLineLayer == 0) return;

    //add all lines from poAreaLineLayer to collection
    OGRGeometryCollection *gc = new OGRGeometryCollection();
    poAreaLineLayer->ResetReading();
    while (OGRFeature *feature = poAreaLineLayer->GetNextFeatureRef())
        gc->addGeometry(feature->GetGeometryRef());

    //polygonize lines
    CPLDebug( "OGR_ILI", "Polygonizing layer %s with %d multilines", poAreaLineLayer->GetLayerDefn()->GetName(), gc->getNumGeometries());
    poAreaLineLayer = 0;
    OGRMultiPolygon* polys = Polygonize( gc , false);
    CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
    if (polys->getNumGeometries() != poAreaReferenceLayer->GetFeatureCount())
    {
        CPLDebug( "OGR_ILI", "Feature count of layer %s: %d", poAreaReferenceLayer->GetLayerDefn()->GetName(), GetFeatureCount());
        CPLDebug( "OGR_ILI", "Polygonizing again with crossing line fix");
        delete polys;
        polys = Polygonize( gc, true ); //try again with crossing line fix
    }
    delete gc;

    //associate polygon feature with data row according to centroid
#if defined(HAVE_GEOS)
    int i;
    OGRPolygon emptyPoly;
    GEOSGeom *ahInGeoms = NULL;

    CPLDebug( "OGR_ILI", "Associating layer %s with area polygons", GetLayerDefn()->GetName());
    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*),polys->getNumGeometries());
    for( i = 0; i < polys->getNumGeometries(); i++ )
    {
        ahInGeoms[i] = polys->getGeometryRef(i)->exportToGEOS();
        if (!GEOSisValid(ahInGeoms[i])) ahInGeoms[i] = NULL;
    }
    poAreaReferenceLayer->ResetReading();
    while (OGRFeature *feature = poAreaReferenceLayer->GetNextFeatureRef())
    {
        OGRGeometry* geomRef = feature->GetGeometryRef();
        if( !geomRef )
        {
            continue;
        }
        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS());
        for (i = 0; i < polys->getNumGeometries(); i++ )
        {
            if (ahInGeoms[i] && GEOSWithin(point, ahInGeoms[i]))
            {
                OGRFeature* areaFeature = new OGRFeature(poFeatureDefn);
                areaFeature->SetFrom(feature);
                areaFeature->SetGeometry( polys->getGeometryRef(i) );
                AddFeature(areaFeature);
                break;
            }
        }
        if (i == polys->getNumGeometries())
        {
            CPLDebug( "OGR_ILI", "Association between area and point failed.");
            feature->SetGeometry( &emptyPoly );
        }
        GEOSGeom_destroy( point );
    }
    for( i = 0; i < polys->getNumGeometries(); i++ )
        GEOSGeom_destroy( ahInGeoms[i] );
    CPLFree( ahInGeoms );
#endif
    poAreaLineLayer = 0;
    delete polys;
}
Exemplo n.º 4
0
void OGRILI1Layer::PolygonizeAreaLayer( OGRILI1Layer* poAreaLineLayer, int nAreaFieldIndex, int nPointFieldIndex )
{
    //add all lines from poAreaLineLayer to collection
    OGRGeometryCollection *gc = new OGRGeometryCollection();
    poAreaLineLayer->ResetReading();
    while (OGRFeature *feature = poAreaLineLayer->GetNextFeatureRef())
        gc->addGeometry(feature->GetGeometryRef());

    //polygonize lines
    CPLDebug( "OGR_ILI", "Polygonizing layer %s with %d multilines", poAreaLineLayer->GetLayerDefn()->GetName(), gc->getNumGeometries());
    poAreaLineLayer = 0;
    OGRMultiPolygon* polys = Polygonize( gc , false);
    CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
    if (polys->getNumGeometries() != GetFeatureCount())
    {
        CPLDebug( "OGR_ILI", "Feature count of layer %s: " CPL_FRMT_GIB, GetLayerDefn()->GetName(), GetFeatureCount());
        CPLDebug( "OGR_ILI", "Polygonizing again with crossing line fix");
        delete polys;
        polys = Polygonize( gc, true ); //try again with crossing line fix
        CPLDebug( "OGR_ILI", "Resulting polygons: %d", polys->getNumGeometries());
    }
    delete gc;

    //associate polygon feature with data row according to centroid
#if defined(HAVE_GEOS)
    int i;
    OGRPolygon emptyPoly;
    GEOSGeom *ahInGeoms = NULL;

    CPLDebug( "OGR_ILI", "Associating layer %s with area polygons", GetLayerDefn()->GetName());
    ahInGeoms = (GEOSGeom *) CPLCalloc(sizeof(void*), polys->getNumGeometries());
    GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
    for( i = 0; i < polys->getNumGeometries(); i++ )
    {
        ahInGeoms[i] = polys->getGeometryRef(i)->exportToGEOS(hGEOSCtxt);
        if (!GEOSisValid_r(hGEOSCtxt, ahInGeoms[i])) ahInGeoms[i] = NULL;
    }
    for ( int nFidx = 0; nFidx < nFeatures; nFidx++)
    {
        OGRFeature *feature = papoFeatures[nFidx];
        OGRGeometry* geomRef = feature->GetGeomFieldRef(nPointFieldIndex);
        if( !geomRef )
        {
            continue;
        }
        GEOSGeom point = (GEOSGeom)(geomRef->exportToGEOS(hGEOSCtxt));
        for (i = 0; i < polys->getNumGeometries(); i++ )
        {
            if (ahInGeoms[i] && GEOSWithin_r(hGEOSCtxt, point, ahInGeoms[i]))
            {
                feature->SetGeomField(nAreaFieldIndex, polys->getGeometryRef(i));
                break;
            }
        }
        if (i == polys->getNumGeometries())
        {
            CPLDebug( "OGR_ILI", "Association between area and point failed.");
            feature->SetGeometry( &emptyPoly );
        }
        GEOSGeom_destroy_r( hGEOSCtxt, point );
    }
    for( i = 0; i < polys->getNumGeometries(); i++ )
        GEOSGeom_destroy_r( hGEOSCtxt, ahInGeoms[i] );
    CPLFree( ahInGeoms );
    OGRGeometry::freeGEOSContext( hGEOSCtxt );
#endif
    poAreaLineLayer = 0;
    delete polys;
}