This is an automated email from the ASF dual-hosted git repository.

jsorel pushed a commit to branch feat/exportableTransform
in repository https://gitbox.apache.org/repos/asf/sis.git

commit 9386f8fe782404391b2b3bec0f95abde818b9211
Author: jsorel <[email protected]>
AuthorDate: Thu Jun 12 12:07:20 2025 +0200

    Implement ExportableTransform for EllipsoidToRadiusTransform
---
 .../sis/referencing/ExportableTransform.java       |   2 +-
 .../transform/EllipsoidToCentricTransform.java     | 103 ++++++++++++---------
 .../transform/EllipsoidToRadiusTransform.java      |  63 +++++++++----
 3 files changed, 105 insertions(+), 63 deletions(-)

diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/ExportableTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/ExportableTransform.java
index 52f9238575..ad0250efc0 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/ExportableTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/ExportableTransform.java
@@ -26,7 +26,7 @@ public interface ExportableTransform {
     /**
      * The produced code should transform one value only.
      * Input array is expected to be named src.
-     * Ouput array is expected to be named dat.
+     * Ouput array is expected to be named dst.
      *
      * Example of expected produced code :
      * <pre>
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
index 46ef6c71e6..cf7824023b 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToCentricTransform.java
@@ -966,12 +966,19 @@ public class EllipsoidToCentricTransform extends 
AbstractMathTransform implement
                 "\t\tconst sinφ  = Math.sin(φ);\n" +
                 "\t\tconst ν     = 1.0/Math.sqrt(1 - eccentricitySquared * 
(sinφ*sinφ)); // Prime vertical radius of curvature at latitude φ\n" +
                 "\t\tconst rcosφ = (ν + h) * Math.cos(φ);\n" +
-                "\t\tconst d0 = rcosφ * Math.cos(λ); // X: Toward prime 
meridian\n" +
-                "\t\tconst d1 = rcosφ * Math.sin(λ); // Y: Toward 90° east\n" +
-                "\t\tconst d2 = (ν * (1 - eccentricitySquared) + h) * sinφ; // 
Z: Toward north pole\n" +
-                "\t\treturn [d0,d1,d2];\n" +
-                "\t}\n"
+                "\t\tconst Z     = (h + ν * (1.0 - eccentricitySquared)) * 
sinφ;\n");
+
+            if (toSphericalCS) {
+                sb.append(
+                  "\t\treturn [λ, Math.atan(Z / rcosφ), Math.hypot(Z, 
rcosφ)];" +
+                  "\t}\n"
+                );
+            } else {
+                sb.append(
+                  "\t\treturn [rcosφ * Math.cos(λ), rcosφ * Math.sin(λ), Z];" +
+                  "\t}\n"
                 );
+            }
         } else {
             //constants
             sb.append("\t_ANGULAR_TOLERANCE : 
").append(Double.toString(Formulas.ANGULAR_TOLERANCE)).append(",\n");
@@ -986,54 +993,62 @@ public class EllipsoidToCentricTransform extends 
AbstractMathTransform implement
 
             sb.append(
                 "\ttransform : function(src){\n" +
-                "\t\tlet dst = new Array("+getTargetDimensions()+");\n" +
-                "\t\tconst X = src[0];\n" +
-                "\t\tconst Y = src[1];\n" +
-                "\t\tconst Z = src[2];\n" +
-                "\t\tconst p = Math.hypot(X, Y);\n" +
-                "\t\tconst tanq  = Z / (p*this._axisRatio);\n" +
-                "\t\tconst cos2q = 1.0/(1.0 + tanq*tanq);\n" +
-                "\t\tconst sin2q = 1.0 - cos2q;\n" +
-                "\t\tlet φ = Math.atan((Z + 
this._copySign(this._eccentricitySquared * sin2q*Math.sqrt(sin2q), tanq) / 
this._axisRatio) /\n" +
-                "                (p -          this._eccentricitySquared * 
cos2q*Math.sqrt(cos2q)));\n" +
-                "\t\t\n");
-            if (!useIterations) {
+                "\t\tlet dst = new Array("+getTargetDimensions()+");\n"
+            );
+
+            if (toSphericalCS) {
                 sb.append(
-                    "\t\tdst[0] = Math.atan2(Y, X);\n" +
-                    "\t\tdst[1] = φ;\n");
-                if (withHeight) {
-                    sb.append(
-                        "\t\tconst sinφ = Math.sin(φ);\n" +
-                        "\t\tconst ν = 1.0/Math.sqrt(1 - 
this._eccentricitySquared * (sinφ*sinφ));\n" +
-                        "\t\tdst[2] = p/Math.cos(φ) - ν;\n");
-                }
+                    "\t\tconst λ = src[0]; // Spherical longitude\n" +
+                    "\t\tconst Ω = src[1]; // Spherical latitude\n" +
+                    "\t\tconst R = src[2]; // Spherical radius\n" +
+                    "\t\tconst p = R * Math.cos(Ω); // Projection of radius in 
equatorial plane\n" +
+                    "\t\tconst Z = R * Math.sin(Ω); // Toward north pole\n"
+                );
             } else {
                 sb.append(
-                    "\t\tlet found = false;\n" +
-                    "\t\tfor (let it = this._MAXIMUM_ITERATIONS; !found && it 
>= 0; it--) {\n" +
-                    "\t\t\tconst sinφ = Math.sin(φ);\n" +
-                    "\t\t\tconst ν = 1/sqrt(1 - this._eccentricitySquared * 
(sinφ*sinφ));\n" +
-                    "\t\t\tconst Δφ = φ - (φ = atan((Z + 
this._eccentricitySquared * ν * sinφ) / p));\n" +
-                    "\t\t\tif (!(abs(Δφ) >= this._ANGULAR_TOLERANCE * 
(Math.PI/180) * 0.25)) { // Use ! for accepting NaN.\n" +
-                    "\t\t\t\tdst[0] = Math.atan2(Y, X);\n" +
-                    "\t\t\t\tdst[1] = φ;\n");
+                    "\t\tconst X = src[0]; // Toward prime meridian\n" +
+                    "\t\tconst Y = src[1]; // Toward 90° east\n" +
+                    "\t\tconst Z = src[2]; // Toward north pole\n" +
+                    "\t\tconst p = Math.hypot(X, Y); // Projection of radius 
in equatorial plane\n" +
+                    "\t\tconst λ = Math.atan2(Y, X); // Spherical and geodetic 
longitude\n"
+                );
+            }
+
+            sb.append(
+                "\t\tconst tanq  = Z / (p*this._axisRatio);\n" +
+                "\t\tconst cos2q = 1/(1 + tanq*tanq);\n" +
+                "\t\tconst sin2q = 1 - cos2q;\n" +
+                "\t\tlet φ = Math.atan((Z + 
this._copySign(this._eccentricitySquared * (Math.sqrt(sin2q) * sin2q), tanq) / 
this._axisRatio) / (p - this._eccentricitySquared * (Math.sqrt(cos2q) * 
cos2q)));\n"
+              );
+
+            if (useIterations) {
+                sb.append(
+                    "\t\tlet it = this._MAXIMUM_ITERATIONS;\n" +
+                    "\t\tlet sinφ = 0.0;\n" +
+                    "\t\tlet iν = 0.0;\n" +
+                    "\t\tlet Δφ = 0.0;\n" +
+                    "\t\tdo {\n" +
+                    "\t\t\tif (--it <0) {\n" +
+                    "\t\t\t\tthrow new Error(\"No convergence.\");\n" +
+                    "\t\t\t}\n" +
+                    "\t\t\tsinφ = Math.sin(φ);\n" +
+                    "\t\t\tiν = Math.sqrt(1 - this._eccentricitySquared * 
(sinφ*sinφ));\n" +
+                    "\t\t\tΔφ = φ - (φ = Math.atan((Z + 
this._eccentricitySquared * sinφ / iν) / p));\n" +
+                    "\t\twhile (Math.abs(Δφ) >= this._ANGULAR_TOLERANCE * 
(Math.PI/180) * 0.25);\n"
+                  );
                 if (withHeight) {
                     sb.append(
-                        "\t\t\t\tdst[2] = p/Math.cos(φ) - ν;\n");
+                        "\t\tdst[2] = (Math.abs(sinφ) == 1.0) ? (Math.abs(Z) - 
this._axisRatio) : (p/Math.cos(φ) - 1.0/iν);\n"
+                      );
                 }
-                sb.append(
-                    "\t\t\t\tfound = true;\n" +
-                    "\t\t\t}\n" +
-                    "\t\t}\n" +
-                    "\t\tif (!found) {\n" +
-                    "\t\t\tdst[0] = Number.NaN;\n" +
-                    "\t\t\tdst[1] = Number.NaN;\n" +
-                    "\t\t}\n"
-                    );
             }
+
             sb.append(
+                "\t\tdst[0] = λ;\n" +
+                "\t\tdst[1] = φ;\n" +
                 "\t\treturn dst;\n" +
-                "\t}\n");
+                "\t}\n"
+            );
         }
 
         sb.append("}");
diff --git 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransform.java
 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransform.java
index 94e625e118..14dd9cc8b6 100644
--- 
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransform.java
+++ 
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/transform/EllipsoidToRadiusTransform.java
@@ -16,38 +16,39 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
-import java.util.Arrays;
 import java.io.Serializable;
 import static java.lang.Math.*;
+import java.util.Arrays;
 import javax.measure.Unit;
 import javax.measure.quantity.Length;
-import org.opengis.util.FactoryException;
-import org.opengis.parameter.ParameterValueGroup;
-import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.referencing.datum.Ellipsoid;
-import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.MathTransform;
-import org.opengis.referencing.operation.MathTransformFactory;
-import org.opengis.referencing.operation.TransformException;
-import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.apache.sis.metadata.iso.citation.Citations;
+import org.apache.sis.parameter.ParameterBuilder;
+import org.apache.sis.parameter.Parameterized;
+import org.apache.sis.parameter.Parameters;
+import org.apache.sis.referencing.ExportableTransform;
 import org.apache.sis.referencing.datum.DefaultEllipsoid;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.referencing.operation.matrix.MatrixSIS;
 import org.apache.sis.referencing.operation.provider.MapProjection;
 import org.apache.sis.referencing.operation.provider.Spherical2Dto3D;
 import org.apache.sis.referencing.operation.provider.Spherical3Dto2D;
-import org.apache.sis.referencing.privy.ReferencingUtilities;
 import org.apache.sis.referencing.privy.Formulas;
-import org.apache.sis.parameter.Parameters;
-import org.apache.sis.parameter.Parameterized;
-import org.apache.sis.parameter.ParameterBuilder;
-import org.apache.sis.metadata.iso.citation.Citations;
-import org.apache.sis.util.Debug;
+import org.apache.sis.referencing.privy.ReferencingUtilities;
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.Debug;
 import org.apache.sis.util.privy.Constants;
 import org.apache.sis.util.privy.DoubleDouble;
 import org.apache.sis.util.privy.Numerics;
+import org.opengis.parameter.ParameterDescriptorGroup;
+import org.opengis.parameter.ParameterValueGroup;
+import org.opengis.referencing.datum.Ellipsoid;
+import org.opengis.referencing.operation.MathTransform;
+import org.opengis.referencing.operation.MathTransformFactory;
+import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.NoninvertibleTransformException;
+import org.opengis.referencing.operation.TransformException;
+import org.opengis.util.FactoryException;
 
 
 /**
@@ -86,7 +87,7 @@ import org.apache.sis.util.privy.Numerics;
  *
  * @since 1.5
  */
-public class EllipsoidToRadiusTransform extends AbstractMathTransform 
implements Serializable {
+public class EllipsoidToRadiusTransform extends AbstractMathTransform 
implements Serializable, ExportableTransform {
     /**
      * Serial number for inter-operability with different versions.
      */
@@ -405,7 +406,7 @@ public class EllipsoidToRadiusTransform extends 
AbstractMathTransform implements
      * The "almost" is because {@link #inverse()} returns a non-linear 
transform.
      * For that reason, this class cannot implement {@link LinearTransform}.
      */
-    private final class Inverse extends OnewayLinearTransform implements 
Parameterized {
+    private final class Inverse extends OnewayLinearTransform implements 
Parameterized, ExportableTransform {
         /**
          * Serial number for inter-operability with different versions.
          */
@@ -463,6 +464,11 @@ public class EllipsoidToRadiusTransform extends 
AbstractMathTransform implements
             
pg.values().addAll(EllipsoidToRadiusTransform.this.getParameterValues().values());
             return pg;
         }
+
+        @Override
+        public String toECMAScript() throws UnsupportedOperationException {
+            return DELEGATE.toECMAScript();
+        }
     }
 
     /**
@@ -502,4 +508,25 @@ public class EllipsoidToRadiusTransform extends 
AbstractMathTransform implements
         }
         return false;
     }
+
+    @Override
+    public String toECMAScript() throws UnsupportedOperationException {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("{\n");
+
+        sb.append(
+            "\ttransform : function(src){\n" +
+            "\t\tconst eccentricitySquared = " + 
Double.toString(eccentricitySquared) + ";\n" +
+            "\t\tconst Ω     = src[1];\n" +
+            "\t\tconst cosΩ  = Math.cos(Ω);\n" +
+            "\t\tconst r2    = 1 - eccentricitySquared*(cosΩ*cosΩ);\n" +
+            "\t\tconst r     = Math.sqrt(r2); // Inverse of radius.\n" +
+            "\t\treturn [src[0], Ω, 1.0/r];\n" +
+            "\t}\n"
+            );
+
+        sb.append("}");
+        return sb.toString();
+    }
+
 }

Reply via email to