Ciao Michael,
I have spent some time meesing up the WritableGridCoverage2D class you
have put together, I am attaching a small patch for trunk.

Here is some sparse thoughts on it:

 - Think about how to avoid creation of a large number of {...@link
DirectPosition2D} and {...@link GridCoordinates2D}
 - Merge/Borrow from DeferredPlanarImage
 - Allow for making previous {...@link GridCoverage2D} writable in a more
explicit way
-  Think about closer integration with JAI-Tools DiskMemImage class

I still have problems with JIRA, so I cannot open up a new JIRA ( I
did not find one already created). I would suggest we open a new JIRA
for this enhancement.

Ciao,
Simone.
-------------------------------------------------------
Ing. Simone Giannecchini
GeoSolutions S.A.S.
Founder - Software Engineer
Via Carignoni 5
55041  Camaiore (LU)
Italy

phone: +39 0584983027
fax:      +39 0584983027
mob:    +39 333 8128928


http://www.geo-solutions.it
http://geo-solutions.blogspot.com/
http://www.linkedin.com/in/simonegiannecchini
http://twitter.com/simogeo

-------------------------------------------------------



On Tue, May 4, 2010 at 8:11 AM, Michael Bedward
<michael.bedw...@gmail.com> wrote:
> Hi Jody,
>
> I just committed the class and a little demo on trunk into
> demo/example, in the coverage package.
>
> Michael
>
>
>
> On 4 May 2010 16:09, Jody Garnett wrote:
>> Do you have a link to the class? I am curious ...
>>
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Geotools-devel mailing list
> Geotools-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/geotools-devel
>
>
Index: src/main/java/org/geotools/demo/coverage/WritableGridCoverage2D.java
===================================================================
--- src/main/java/org/geotools/demo/coverage/WritableGridCoverage2D.java        
(revision 35430)
+++ src/main/java/org/geotools/demo/coverage/WritableGridCoverage2D.java        
(working copy)
@@ -1,55 +1,138 @@
+/*
+ *    GeoTools - The Open Source Java GIS Tookit
+ *    http://geotools.org
+ * 
+ *    (C) 2010, Open Source Geospatial Foundation (OSGeo)
+ *
+ *    This file is hereby placed into the Public Domain. This means anyone is
+ *    free to do whatever they wish with this file. Use it well and enjoy!
+ */
 package org.geotools.demo.coverage;
 
 import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
 import java.awt.image.DataBuffer;
 import java.awt.image.RenderedImage;
 import java.awt.image.WritableRenderedImage;
 import java.awt.image.renderable.RenderableImage;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import javax.media.jai.TiledImage;
+import java.util.Set;
+
 import javax.media.jai.iterator.RandomIterFactory;
 import javax.media.jai.iterator.WritableRandomIter;
+
 import org.geotools.coverage.grid.GridCoordinates2D;
 import org.geotools.coverage.grid.GridCoverage2D;
 import org.geotools.coverage.grid.ViewType;
 import org.geotools.geometry.DirectPosition2D;
+import org.geotools.renderer.i18n.Errors;
+import org.geotools.util.Utilities;
 import org.opengis.coverage.CannotEvaluateException;
+import org.opengis.coverage.grid.GridRange;
+import org.opengis.coverage.grid.InvalidRangeException;
 import org.opengis.geometry.DirectPosition;
 import org.opengis.referencing.operation.TransformException;
 
 /**
- *
+ * Draft class for a writable {...@link GridCoverage2D} instance.
+ * 
+ * TODO Think about how to avoid creation of a large number of {...@link 
DirectPosition2D} and {...@link GridCoordinates2D}
+ * TODO Merge/Borrow from DeferredPlanarImage
+ * TODO Allow for making previous {...@link GridCoverage2D} writable in a more 
explicit way
+ * 
  * @author Michael Bedward
+ * @author Simone Giannecchini, GeoSolutions S.A.S.
  */
-/**
- * @author Michael Bedward
- */
+...@suppresswarnings("deprecation")
 public class WritableGridCoverage2D extends GridCoverage2D {
 
-    private GridCoverage2D wrapped;
-    private static final int MAX_PENDING_VALUES = 10000;
+    /**
+        * 
+        */
+       private static final long serialVersionUID = -7894734946444396087L;
+       
+       private GridCoverage2D wrapped;
+       
+       /** Default maximum number of cached values waiting to be written 
down.**/
+    private static final int DEFAULT_MAX_PENDING_VALUES = 10000;
 
-    private static class PendingValue {
-        Object pos;
+    /**
+     * Simple placeholder class for pending values.
+     * @author Michael Bedward
+     * @author Simone Giannecchini, GeoSolutions S.A.S.
+     *
+     * @param <P> positions class
+     * @param <V> value class
+     */
+    private static class PendingValue<P,V> {
+        P pos;
         boolean isGeographic;
-        Object value;
+        V value;
     }
 
-    private List<PendingValue> pendingValues = new ArrayList<PendingValue>();
+    /**
+     * Pending value living in raster space.
+     * 
+     * @author Simone Giannecchini, GeoSolutions S.A.S.
+     *
+     */
+    private static class RasterPosition extends 
PendingValue<GridCoordinates2D,Number> {
+    }
 
     /**
+     * Pending value living in model space.
+     * 
+     * @author Simone Giannecchini, GeoSolutions S.A.S.
+     *
+     */
+    private static class ModelPosition extends 
PendingValue<DirectPosition,Number> {
+    }
+    
+    private final List<PendingValue<?,?>> pendingValues = 
Collections.synchronizedList(new ArrayList<PendingValue<?,?>>());
+       
+       private int dataType;
+
+       private final int maxPendingValues;
+
+    /**
      * Constructor: wraps the given grid
      *
-     * @param grid the original grid
+     * @param grid the original {...@link GridCoverage2D}
      */
-    public WritableGridCoverage2D(GridCoverage2D grid) {
-        super(grid.getName().toString(), grid);
+    public WritableGridCoverage2D(final GridCoverage2D grid) {
+       this(grid,DEFAULT_MAX_PENDING_VALUES);
+    }
+    
+    /**
+     * Constructor
+     * 
+     * @param grid the original {...@link GridCoverage2D}
+     * @param maxPendingValues the maximum number of values to keep cached in 
memory prior to writing down.
+     */
+    public WritableGridCoverage2D(final GridCoverage2D grid, final int 
maxPendingValues){
+       super(checkIsWritable(grid).getName().toString(), grid);
         this.wrapped = grid;
+
+        final WritableRenderedImage writableImage = (WritableRenderedImage) 
image;
+        dataType = writableImage.getSampleModel().getDataType();
+        this.maxPendingValues=maxPendingValues;        
     }
 
-    @Override
+    /**
+     * Check that the input {...@link GridCoverage2D} is back by an underlying 
{...@link WritableRenderedImage}.
+     * 
+     * @param grid the input {...@link GridCoverage2D}.
+     * @return the input {...@link GridCoverage2D}.
+     */
+    private static GridCoverage2D checkIsWritable(final GridCoverage2D grid) {
+       Utilities.ensureNonNull("Grid", grid);          
+       if(!(grid.getRenderedImage() instanceof WritableRenderedImage))
+                       throw new 
IllegalArgumentException(Errors.format(org.geotools.resources.i18n.ErrorKeys.ILLEGAL_ARGUMENT_$2,"GridCoverage2D","Not
 Writable"));
+       return grid;
+       }
+
+       @Override
     public Object evaluate(DirectPosition point) throws 
CannotEvaluateException {
         flushCache(true);
         return super.evaluate(point);
@@ -125,6 +208,12 @@
     }
 
     @Override
+       public synchronized Set<ViewType> getViewTypes() {
+        flushCache(true);
+               return super.getViewTypes();
+       }
+
+       @Override
     public RenderableImage getRenderableImage(int xAxis, int yAxis) {
         flushCache(true);
         return super.getRenderableImage(xAxis, yAxis);
@@ -142,11 +231,6 @@
     }
 
     @Override
-    public void prefetch(Rectangle2D area) {
-        // not implemented
-    }
-
-    @Override
     public void show(String title, int xAxis, int yAxis) {
         flushCache(true);
         super.show(title, xAxis, yAxis);
@@ -163,90 +247,197 @@
         flushCache(true);
         return super.view(type);
     }
-
-    public void setValue(DirectPosition worldPos, int value) {
+    
+    /**
+     * Set a value in model space.
+     * @param <V> the value type
+     * @param worldPos the model space position
+     * @param value the value to set
+     */
+    public<V extends Number> void setValue(DirectPosition worldPos, V value) {
         doSetWorldValue(worldPos, value);
     }
-
-    public void setValue(DirectPosition worldPos, float value) {
-        doSetWorldValue(worldPos, value);
-    }
-
-    public void setValue(DirectPosition worldPos, double value) {
-        doSetWorldValue(worldPos, value);
-    }
-
-    public void setValue(GridCoordinates2D gridPos, int value) {
+    
+    /**
+     * Set a value in raster space.
+     * @param <V> the value type
+     * @param worldPos the raster space position
+     * @param value the value to set
+     */
+    public <V extends Number> void setValue(GridCoordinates2D gridPos, V 
value) {
         doSetGridValue(gridPos, value);
     }
 
-    public void setValue(GridCoordinates2D gridPos, float value) {
-        doSetGridValue(gridPos, value);
-    }
-
-    public void setValue(GridCoordinates2D gridPos, double value) {
-        doSetGridValue(gridPos, value);
-    }
-
     private void doSetWorldValue(DirectPosition pos, Number value) {
-        PendingValue pv = new PendingValue();
+        final ModelPosition pv = new ModelPosition();
         pv.pos = new DirectPosition2D(pos);
         pv.isGeographic = true;
         pv.value = value;
-        pendingValues.add(pv);
-        flushCache(false);
+        synchronized (pendingValues) {
+            pendingValues.add(pv);
+            flushCache(false); 
+               }
     }
 
     private void doSetGridValue(GridCoordinates2D gridPos, Number value) {
-        PendingValue pv = new PendingValue();
-        pv.pos = new GridCoordinates2D(gridPos);
+        final RasterPosition pv = new RasterPosition();
+        pv.pos = gridPos.clone();
         pv.isGeographic = false;
         pv.value = value;
-        pendingValues.add(pv);
-        flushCache(false);
+        synchronized (pendingValues) {
+            pendingValues.add(pv);
+            flushCache(false); 
+               }
     }
 
     private void flushCache(boolean force) {
-        if (pendingValues.size() >= MAX_PENDING_VALUES || (force && 
pendingValues.size() > 0)) {
+       synchronized (pendingValues) {
+            if (pendingValues.size() >= maxPendingValues || (force && 
pendingValues.size() > 0)) {
 
-            WritableRenderedImage writableImage = null;
-            if (super.isDataEditable()) {
-                writableImage = (WritableRenderedImage) image;
-            } else {
-                writableImage = new TiledImage(wrapped.getRenderedImage(), 
true);
-            }
-            WritableRandomIter writeIter = 
RandomIterFactory.createWritable(writableImage, null);
-            int dataType = writableImage.getSampleModel().getDataType();
-
-            GridCoordinates2D gridPos = null;
-            for (PendingValue pv : pendingValues) {
-                if (pv.isGeographic) {
-                    try {
-                        gridPos = 
wrapped.getGridGeometry().worldToGrid((DirectPosition) pv.pos);
-                    } catch (TransformException ex) {
-                        throw new RuntimeException("Could not transform 
location [" +
-                                pv.pos + "] to grid coords");
+                final WritableRenderedImage writableImage = 
(WritableRenderedImage) image;
+                final WritableRandomIter writeIter= 
RandomIterFactory.createWritable(writableImage, null);
+                GridCoordinates2D gridPos = null;
+                for (final PendingValue<?,?> pv : pendingValues) {
+                    if (pv.isGeographic) {
+                        try {
+                            gridPos = 
wrapped.getGridGeometry().worldToGrid((DirectPosition) pv.pos);
+                        } catch (TransformException ex) {
+                            throw new RuntimeException("Could not transform 
location [" +pv.pos + "] to grid coords");
+                        }
+                    } else {
+                        gridPos = (GridCoordinates2D) pv.pos;
                     }
-                } else {
-                    gridPos = (GridCoordinates2D) pv.pos;
-                }
 
-                switch (dataType) {
-                    case DataBuffer.TYPE_INT:
-                        writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Integer)pv.value);
-                        break;
 
-                    case DataBuffer.TYPE_FLOAT:
-                        writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Float)pv.value);
-                        break;
+                    switch (dataType) {
+                           case DataBuffer.TYPE_BYTE:
+                               writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Byte)pv.value);
+                               break;
+       
+                           case DataBuffer.TYPE_SHORT:case 
DataBuffer.TYPE_USHORT:
+                               writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Short)pv.value);
+                               break;                    
+                        case DataBuffer.TYPE_INT:
+                            writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Integer)pv.value);
+                            break;
 
-                    case DataBuffer.TYPE_DOUBLE:
-                        writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Double)pv.value);
-                        break;
+                        case DataBuffer.TYPE_FLOAT:
+                            writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Float)pv.value);
+                            break;
+
+                        case DataBuffer.TYPE_DOUBLE:
+                            writeIter.setSample(gridPos.x, gridPos.y, 0, 
(Double)pv.value);
+                            break;
+                    }
                 }
+
+                pendingValues.clear();
+                writeIter.done();
             }
+                       
+               }
+    }
 
-            pendingValues.clear();
-        }
-    }
+       @Override
+       public synchronized boolean dispose(boolean force) {
+               flushCache(true);
+               pendingValues.clear();
+               return super.dispose(force);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, boolean[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]?1:0);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, byte[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, double[] values)
+                       throws InvalidRangeException,
+                       ArrayIndexOutOfBoundsException {
+
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, float[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, int[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
+
+       @Override
+       public void setDataBlock(GridRange gridRange, short[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
+
+
+       
+       @Override
+       public void setPackedDataBlock(GridRange gridRange, byte[] values)
+                       throws InvalidRangeException, 
+                       ArrayIndexOutOfBoundsException {
+               final int minX =gridRange.getLow(0);
+               final int minY =gridRange.getLow(1);
+               final int maxX =gridRange.getSpan(0)+minX;
+               final int maxY =gridRange.getSpan(1)+minY;
+               for(int x=minX;x<maxX;x++)
+                       for(int y=minY;y<maxY;y++)
+                               setValue(new GridCoordinates2D(x, y), 
values[x+y*gridRange.getSpan(0)]);
+       }
 }
Index: src/main/java/org/geotools/demo/coverage/WritableGridDemo.java
===================================================================
--- src/main/java/org/geotools/demo/coverage/WritableGridDemo.java      
(revision 35430)
+++ src/main/java/org/geotools/demo/coverage/WritableGridDemo.java      
(working copy)
@@ -32,7 +32,7 @@
             for (int x = 0; x < WIDTH; x++) {
                 double dx = (x - centre) / centre;
                 double d = Math.sqrt(dx*dx + dy2);
-                GridCoordinates2D coords = new GridCoordinates2D(x, y);
+                final GridCoordinates2D coords = new GridCoordinates2D(x, y);
                 writableCov.setValue(coords, (float) Math.sin(8 * Math.PI * 
d));
             }
         }
------------------------------------------------------------------------------

_______________________________________________
Geotools-devel mailing list
Geotools-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to