Revision: 6624
          http://sourceforge.net/p/jump-pilot/code/6624
Author:   michaudm
Date:     2020-11-15 17:54:16 +0000 (Sun, 15 Nov 2020)
Log Message:
-----------
Fix more deeply and document the half pixel shift problem

Modified Paths:
--------------
    core/trunk/ChangeLog
    
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
    
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoReferencedRaster.java

Modified: core/trunk/ChangeLog
===================================================================
--- core/trunk/ChangeLog        2020-11-15 09:42:42 UTC (rev 6623)
+++ core/trunk/ChangeLog        2020-11-15 17:54:16 UTC (rev 6624)
@@ -6,6 +6,7 @@
 
 2020-11-15 mmichaud
   * fix #512 about georeferencing (introduced by r6523)
+  * fix #503 again (half-pixel shift)
 
 2020-10-25 Giuseppe Aruta
   * Updated CadTool plugin to ver. 1.0: activated Add and remove area plugin

Modified: 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java
===================================================================
--- 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java   
    2020-11-15 09:42:42 UTC (rev 6623)
+++ 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoImage.java   
    2020-11-15 17:54:16 UTC (rev 6624)
@@ -148,7 +148,7 @@
 
           // First, scale the original image
           double scaleX = scale * gtr.getDblModelUnitsPerRasterUnit_X();
-          double scaleY = scale * gtr.getDblModelUnitsPerRasterUnit_Y();
+          double scaleY = scale * 
Math.abs(gtr.getDblModelUnitsPerRasterUnit_Y());
 
           // calculate predicted dimensions
           double scaledW = scaleX * src_img.getWidth();

Modified: 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoReferencedRaster.java
===================================================================
--- 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoReferencedRaster.java
    2020-11-15 09:42:42 UTC (rev 6623)
+++ 
core/trunk/src/com/vividsolutions/jump/workbench/imagery/geoimg/GeoReferencedRaster.java
    2020-11-15 17:54:16 UTC (rev 6624)
@@ -71,9 +71,25 @@
   Envelope envModel_image;
   Envelope envModel_image_backup;
 
+  // To be removed in 2.0
+  @Deprecated
   Coordinate coorRasterTiff_tiepointLT;
+  @Deprecated
   Coordinate coorModel_tiepointLT;
 
+  public enum AreaOrPoint {AREA,POINT}
+  AreaOrPoint areaOrPoint = AreaOrPoint.AREA;
+
+  //https://trac.osgeo.org/gdal/ticket/4977
+  boolean honourNegativeScaleY = false;
+
+  // Rename upper left image coordinate with more expressive names
+  // Remarks in GeoTIFF, rasterULPixelCenter is
+  // 0.5, 0.5 in  AREA_OR_POINT=Area (default)
+  // 0,   0   in  AREA_OR_POINT=Point
+  private Coordinate rasterULPixelCenter;
+  private Coordinate modelULPixelCenter;
+
   private double dblModelUnitsPerRasterUnit_X;
   private double dblModelUnitsPerRasterUnit_Y;
 
@@ -127,23 +143,18 @@
                 + MSG_GENERAL);
       }
       double[] tags = new double[6];
-      tags[0] = fieldModelGeoTransform.getAsDouble(0); // pixel size in x
-                                                       // direction
-      tags[1] = fieldModelGeoTransform.getAsDouble(1); // rotation about y-axis
-      tags[2] = fieldModelGeoTransform.getAsDouble(4); // rotation about x-axis
-      tags[3] = fieldModelGeoTransform.getAsDouble(5); // pixel size in the
-                                                       // y-direction
-      tags[4] = fieldModelGeoTransform.getAsDouble(3); // x-coordinate of the
-                                                       // center of the upper
-                                                       // left pixel
-      tags[5] = fieldModelGeoTransform.getAsDouble(7); // y-coordinate of the
-                                                       // center of the upper
-                                                       // left pixel
-                                                       // 
setCoorRasterTiff_tiepointLT(new
-                                                       // Coordinate(-0.5,
-                                                       // -0,5));
-      // setCoorModel_tiepointLT(new Coordinate(0, 0));
-      // setAffineTransformation(new AffineTransform(tags));
+      // pixel size in x direction (x-scale)
+      tags[0] = fieldModelGeoTransform.getAsDouble(0);
+      // rotation about y-axis
+      tags[1] = fieldModelGeoTransform.getAsDouble(1);
+      // rotation about x-axis
+      tags[2] = fieldModelGeoTransform.getAsDouble(4);
+      // pixel size in the y-direction (y-scale)
+      tags[3] = fieldModelGeoTransform.getAsDouble(5);
+      // x-ordinate of the center of the upper left pixel
+      tags[4] = fieldModelGeoTransform.getAsDouble(3);
+      // y-ordinate of the center of the upper left pixel
+      tags[5] = fieldModelGeoTransform.getAsDouble(7);
       Logger.debug("gtiff trans: " + Arrays.toString(tags));
       setEnvelope(tags);
     }
@@ -155,13 +166,25 @@
       // Map the modeltiepoints from raster to model space
 
       // Read the tiepoints
-      setCoorRasterTiff_tiepointLT(new Coordinate(
-          fieldModelTiePoints.getAsDouble(0),
-          fieldModelTiePoints.getAsDouble(1), 0));
-      setCoorModel_tiepointLT(new Coordinate(
-          fieldModelTiePoints.getAsDouble(3),
-          fieldModelTiePoints.getAsDouble(4), 0));
-      setEnvelope();
+      double offset = (areaOrPoint == AreaOrPoint.AREA) ? 0.5 : 0.0;
+      // in areaOrPoint=AREA model, reference for the TiePoint is the UL
+      // corner of the pixel
+      // To set the transformation parameters we use the center of the
+      // UL coordinate
+      Coordinate imageCoord = new Coordinate(
+              fieldModelTiePoints.getAsDouble(0)-offset,
+              fieldModelTiePoints.getAsDouble(1)-offset);
+      Coordinate modelCoord = new Coordinate(
+              fieldModelTiePoints.getAsDouble(3),
+              fieldModelTiePoints.getAsDouble(4));
+
+      //setCoorRasterTiff_tiepointLT(new Coordinate(
+      //    fieldModelTiePoints.getAsDouble(0),
+      //    fieldModelTiePoints.getAsDouble(1), 0));
+      //setCoorModel_tiepointLT(new Coordinate(
+      //    fieldModelTiePoints.getAsDouble(3),
+      //    fieldModelTiePoints.getAsDouble(4), 0));
+      //setEnvelope();
       // Find the ModelPixelScale field
       XTIFFField fieldModelPixelScale = dir
           .getField(XTIFF.TIFFTAG_GEO_PIXEL_SCALE);
@@ -172,11 +195,23 @@
             + "\n" + MSG_GENERAL);
       }
 
-      Logger.debug("gtiff tiepoints found.");
+      Logger.debug("gtiff tiepoints found : " + 
Arrays.toString(fieldModelTiePoints.getAsDoubles()));
 
-      setDblModelUnitsPerRasterUnit_X(fieldModelPixelScale.getAsDouble(0));
-      setDblModelUnitsPerRasterUnit_Y(fieldModelPixelScale.getAsDouble(1));
+      dblModelUnitsPerRasterUnit_X = fieldModelPixelScale.getAsDouble(0);
+      dblModelUnitsPerRasterUnit_Y = fieldModelPixelScale.getAsDouble(1);
+      //https://trac.osgeo.org/gdal/ticket/4977
+      if (!honourNegativeScaleY) dblModelUnitsPerRasterUnit_Y = - 
Math.abs(dblModelUnitsPerRasterUnit_Y);
+      Logger.debug("gtiff scale : scalex=" + dblModelUnitsPerRasterUnit_X + ", 
scaley=" + dblModelUnitsPerRasterUnit_Y);
 
+      double tx = 
modelCoord.x-getDblModelUnitsPerRasterUnit_X()*(imageCoord.x);
+      double ty = 
modelCoord.y-getDblModelUnitsPerRasterUnit_Y()*(imageCoord.y);
+
+      // Compute the model coordinate for the center of UL and LR pixels
+      rasterULPixelCenter = new Coordinate(0.0,0.0);
+      modelULPixelCenter = new Coordinate(
+              getDblModelUnitsPerRasterUnit_X()*rasterULPixelCenter.x + tx,
+              getDblModelUnitsPerRasterUnit_Y()*rasterULPixelCenter.y + ty);
+
       setEnvelope();
 
     }
@@ -231,10 +266,8 @@
         tags[1] = geoTransform[4]; // rotation about y-axis
         tags[2] = geoTransform[2]; // rotation about x-axis
         tags[3] = geoTransform[5]; // pixel size in the y-direction
-        tags[4] = geoTransform[0]; // x-coordinate of the center of the upper
-                                   // left pixel
-        tags[5] = geoTransform[3]; // y-coordinate of the center of the upper
-                                   // left pixel
+        tags[4] = geoTransform[0]; // x-coordinate of the center of the upper 
left pixel
+        tags[5] = geoTransform[3]; // y-coordinate of the center of the upper 
left pixel
         setEnvelope(tags);
 
         // still with us? must have succeeded
@@ -342,34 +375,37 @@
     //setCoorModel_tiepointLT(new Coordinate(0, 0));
     AffineTransform transform = new AffineTransform(tags);
 
-    double scaleX = Math.abs(transform.getScaleX());
-    double scaleY = Math.abs(transform.getScaleY());
+    //We should honour negative scale y, but gdal created plenty of
+    //files where sign is not correct.
+    //We now have to consider that the scale y sign is not significative
+    //and offer an option to honour negative scales
+    //https://trac.osgeo.org/gdal/ticket/4977
+    //double scaleX = Math.abs(transform.getScaleX());
+    //double scaleY = Math.abs(transform.getScaleY());
 
-    setDblModelUnitsPerRasterUnit_X(scaleX);
-    setDblModelUnitsPerRasterUnit_Y(scaleY);
+    dblModelUnitsPerRasterUnit_X = transform.getScaleX();
+    dblModelUnitsPerRasterUnit_Y = transform.getScaleY();
 
     Point2D rasterLT = new Point2D.Double(src.getMinX(), src.getMinY());
     Point2D modelLT = new Point2D.Double();
     transform.transform(rasterLT, modelLT);
 
-    setCoorRasterTiff_tiepointLT(new Coordinate(rasterLT.getX(),
-        rasterLT.getY()));
-    setCoorModel_tiepointLT(new Coordinate(modelLT.getX(), modelLT.getY()));
+    rasterULPixelCenter = new Coordinate(src.getMinX(), src.getMinY());
+    modelULPixelCenter = new Coordinate(modelLT.getX(), modelLT.getY());
 
     setEnvelope();
   }
 
   void setEnvelope() {
+    double offset = (areaOrPoint == AreaOrPoint.AREA) ? 0.5 : 0.0;
     // Get the image coordinate of the bottom left corner of the bottom left 
pixel
     // from the image coordinate of the center of the bottom left pixel
     Coordinate coorRaster_imageLB = new Coordinate(
-            coorRasterTiff_tiepointLT.x-0.5,
-            src.getHeight()-0.5);
+            rasterULPixelCenter.x-offset,src.getHeight()-offset);
     // Get the image coordinate of the top right corner of the top right pixel
     // from the image coordinate of the center of the top right pixel
     Coordinate coorRaster_imageRT = new Coordinate(
-            src.getWidth()-0.5,
-            -0.5);
+            src.getWidth()-offset, -offset);
     // Transform the bottom left and the top right corner to model coordinate
     // to get the envelope of the image
     Coordinate coorModel_imageLB = rasterToModelSpace(coorRaster_imageLB);
@@ -391,11 +427,11 @@
   private Coordinate rasterToModelSpace(Coordinate coorRaster) {
     Coordinate coorModel = new Coordinate();
 
-    coorModel.x = coorModel_tiepointLT.x
-        + (coorRaster.x - coorRasterTiff_tiepointLT.x)
+    coorModel.x = modelULPixelCenter.x
+        + (coorRaster.x - rasterULPixelCenter.x)
         * dblModelUnitsPerRasterUnit_X;
-    coorModel.y = coorModel_tiepointLT.y
-        - (coorRaster.y + coorRasterTiff_tiepointLT.y)
+    coorModel.y = modelULPixelCenter.y
+        + (coorRaster.y - rasterULPixelCenter.y)
         * dblModelUnitsPerRasterUnit_Y;
     coorModel.z = 0;
 
@@ -410,50 +446,54 @@
     return envModel_image_backup;
   }
 
-  /**
-   * @param coordinate
-   */
-  private void setCoorModel_tiepointLT(Coordinate coordinate) {
-    coorModel_tiepointLT = coordinate;
-    // setEnvelope();
-  }
+  ///**
+  // * @param coordinate
+  // */
+  //@Deprecated
+  //private void setCoorModel_tiepointLT(Coordinate coordinate) {
+  //  coorModel_tiepointLT = coordinate;
+  //  // setEnvelope();
+  //}
 
-  /**
-   * @param coordinate
-   */
-  private void setCoorRasterTiff_tiepointLT(Coordinate coordinate) {
-    coorRasterTiff_tiepointLT = coordinate;
-    // setEnvelope();
-  }
+  ///**
+  // * @param coordinate
+  // */
+  //private void setCoorRasterTiff_tiepointLT(Coordinate coordinate) {
+  //  coorRasterTiff_tiepointLT = coordinate;
+  //  // setEnvelope();
+  //}
 
-  /**
-   * @param d
-   */
-  private void setDblModelUnitsPerRasterUnit_X(double d) {
-    dblModelUnitsPerRasterUnit_X = d;
-    // setEnvelope();
-  }
+  ///**
+  // * @param d
+  // */
+  //private void setDblModelUnitsPerRasterUnit_X(double d) {
+  //  dblModelUnitsPerRasterUnit_X = d;
+  //  // setEnvelope();
+  //}
 
-  /**
-   * @param d
-   */
-  private void setDblModelUnitsPerRasterUnit_Y(double d) {
-    dblModelUnitsPerRasterUnit_Y = d;
-    // setEnvelope();
-  }
+  ///**
+  // * @param d
+  // */
+  //private void setDblModelUnitsPerRasterUnit_Y(double d) {
+  //  dblModelUnitsPerRasterUnit_Y = d;
+  //  // setEnvelope();
+  //}
 
   /**
    * @return coordinate of left-top corner in the model coordinate system
    */
   public Coordinate getCoorModel_tiepointLT() {
-    return coorModel_tiepointLT;
+    //return coorModel_tiepointLT;
+    return modelULPixelCenter;
   }
 
   /**
    * @return coordinate of left-top corner in the raster coordinate system
    */
+  @Deprecated
   public Coordinate getCoorRasterTiff_tiepointLT() {
-    return coorRasterTiff_tiepointLT;
+    //return coorRasterTiff_tiepointLT;
+    return rasterULPixelCenter;
   }
 
   /**
@@ -481,9 +521,10 @@
         // set new scale values
         RenderedOp img = super.getImage();
         double xUnit = Math.abs(envGeom.getWidth() / img.getWidth());
-        setDblModelUnitsPerRasterUnit_X(xUnit);
+        dblModelUnitsPerRasterUnit_X = xUnit;
         double yUnit = Math.abs(envGeom.getHeight() / img.getHeight());
-        setDblModelUnitsPerRasterUnit_Y(yUnit);
+        // y-scale is generally negative (won't work if model y axis is 
top-down)
+        dblModelUnitsPerRasterUnit_Y = -yUnit;
         // assign&return new envelope
         return envModel_image = new Envelope(envGeom);
       }



_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to