On Tue, Apr 29, 2008 at 8:23 AM, Jody Garnett wrote:
>
>  Sweet - can you post some examples to the email list Michael? I will punt
> them onto the user guide for you ...
>  Jody
>

Hi Jody - here's the start of a class for doing neighbourhood operations.

After waxing lyrical about ImageWorker this probably isn't the best
example :-)  but I'll be doing more soon with masking etc.  Feel free
to use and hack this code for whatever.

cheers
Michael
/*
 * CafeAnimal: a program to simulate vertebrate population dynamics in changing 
landscapes
 *
 */
package org.cafeanimal.geo.gridlayer;

import java.awt.RenderingHints;
import java.awt.image.RenderedImage;
import javax.media.jai.BorderExtender;
import javax.media.jai.KernelJAI;
import javax.media.jai.operator.BorderDescriptor;
import javax.media.jai.operator.ConvolveDescriptor;
import javax.media.jai.operator.CropDescriptor;

import org.geotools.coverage.grid.GridCoverage2D;
import org.geotools.coverage.CoverageFactoryFinder;
import org.geotools.coverage.grid.GridCoverageFactory;
import org.geotools.geometry.Envelope2D;
import org.geotools.image.ImageWorker;
import org.geotools.referencing.crs.DefaultGeographicCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;

/**
 * Class for neighbourhood-based operations
 * on grid layers.
 * 
 * @author Michael Bedward <[EMAIL PROTECTED]>
 */
public class CAGridNbrOp {

    private GridCoverage2D grid;
    private ImageWorker iworker;

    public CAGridNbrOp(GridCoverage2D grid) {
        this.grid = grid;
        iworker = new ImageWorker(grid.getData().getRenderedImage());
    }

    /**
     * Search for grid locations with a total neighbourhood value greater than
     * or equal to a specified minimum.  The neighbourhood is a circle.
     *
     * Note: at present this operates in pixel coordinates.
     * 
     * @param minValue the threshold value for neighbourhood total
     * @param searchRadius radius of the circular search neighbourhood (in 
pixels)
     * @return a new binary grid layer
     */
    public GridCoverage2D focalThreshold(float minValue, int searchRadius) {

        convolve( createCircleMask(searchRadius) );
        iworker.binarize(minValue);
        
        CoordinateReferenceSystem crs = DefaultGeographicCRS.WGS84;
        Envelope2D envelope = new Envelope2D(crs, 0, 0, w, h);
        GridCoverageFactory factory = 
CoverageFactoryFinder.getGridCoverageFactory(null);
        return factory.create(name, img, envelope);
    }

    private void convolve(float[] kernelMatrix) {

        int kernelW = (int) (Math.sqrt(kernelMatrix.length)+1.0E-6);
        int borderW = kernelW / 2;
        
        RenderingHints hints = iworker.getRenderingHints();
        RenderedImage img = iworker.getRenderedImage();

        img = BorderDescriptor.create(
                img, borderW, borderW, borderW, borderW,
                BorderExtender.createInstance(BorderExtender.BORDER_ZERO),
                hints);
        
        KernelJAI kernel = new KernelJAI(
                kernelW, kernelW, kernelMatrix);
        img = ConvolveDescriptor.create(
                img, kernel, hints);
        
        img = CropDescriptor.create(
                img, (float)borderW, (float)borderW, 
                (float)grid.getPixelWidth(), (float)grid.getPixelHeight(), 
hints);
        
        iworker.setImage(img);
    }
    
    private float[] createCircleMask(int radius) {

        int width = 2 * radius + 1;
        float[] matrix = new float[width * width];

        int x;
        double r2 = radius * radius;
        double y2;
        for (int row = 0; row < radius; row++) {
            y2 = Math.pow(radius - row, 2);
            x = (int) Math.round(Math.sqrt(r2 - y2));

            int upper0 = row * width + radius - x;
            int lower0 = (width - row - 1) * width + radius - x;
            for (int i = 0; i < 2 * x + 1; i++) {
                matrix[upper0 + i] = 1;
                matrix[lower0 + i] = 1;
            }
        }

        int mid0 = radius * width;
        for (int i = 0; i < width; i++) {
            matrix[mid0 + i] = 1;
        }

        return matrix;        
    }
}
-------------------------------------------------------------------------
This SF.net email is sponsored by the 2008 JavaOne(SM) Conference 
Don't miss this year's exciting event. There's still time to save $100. 
Use priority code J8TL2D2. 
http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone
_______________________________________________
Geotools-gt2-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-gt2-users

Reply via email to