Andrea Aime ha scritto:
> Andrea Aime ha scritto:
> 
>> Now, I'm wondering, besides extending point sampling inside
>> the original bbox (instead of using only the perimeter) do
>> we have any smarter method? Even sampling inside the bbox
>> we could loose part of the actual map area in 4326 if sampling
>> did not happen to catch the pole...

Ok, I rolled a solution, which is basically a brute force recursive
sampling, quadtree inspired, that ends its recursion when the area
of the current envelope did not expand more than a certain tolerance.

Seems to be quick enough, and to converge relatively fast to the
ideal envelope even in this pesky stereographic case.

Here is a code sample:

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



import java.util.Iterator;

import org.geotools.geometry.jts.JTS;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.geometry.Envelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;

public class ReprojectEnvelopeTest {
     public static void main(String[] args) throws Exception {
         CoordinateReferenceSystem c3031 = CRS.decode("EPSG:3031", true);
         CoordinateReferenceSystem c4326 = CRS.decode("EPSG:4326", true);
         ReferencedEnvelope envelope = new 
ReferencedEnvelope(-3943612.4042124213,
                 3729092.5890516187, -4078471.954436003, 
4033483.085688618, c3031);
         MathTransform transform = CRS.findMathTransform(c3031, c4326);
         Envelope out = CRS.transform(transform, envelope);
         System.out.println("CRS reproject: " + out);

         envelope = new ReferencedEnvelope(-3943612.4042124213, 
3729092.5890516187,
                 -4078471.954436003, 4033483.085688618, c3031);
         System.out.println("JTS transform: " + JTS.transform(envelope, 
transform));

         System.out.println("Recursive sample");
         envelope = new ReferencedEnvelope(-3943612.4042124213, 
3729092.5890516187,
                 -4078471.954436003, 4033483.085688618, c3031);
         double tolerance = 0.1;
         for (int i = 0; i < 20; i++) {
             transform(envelope, transform, tolerance);
             tolerance /= 10.0;
         }
     }

     public static com.vividsolutions.jts.geom.Envelope transform(final 
ReferencedEnvelope envelope, final MathTransform transform, double 
tolerance) throws TransformException
     {
         System.out.println("Tolerance: " + tolerance);
         long start = System.currentTimeMillis();
         com.vividsolutions.jts.geom.Envelope result = new 
com.vividsolutions.jts.geom.Envelope();

         // initial sampling, 4 corners of the envelope
         final double xmin   = envelope.getMinX();
         final double xmax   = envelope.getMaxX();
         final double ymin   = envelope.getMinY();
         final double ymax   = envelope.getMaxY();
         double[] coords = new double[8];

         coords[0] = xmin;
         coords[1] = ymax;
         coords[2] = xmax;
         coords[3] = ymax;
         coords[4] = xmin;
         coords[5] = ymin;
         coords[6] = xmax;
         coords[7] = ymin;
         transform.transform(coords, 0, coords, 0, 4);
         for (int i = 0, j = 0; i < 4; i++) {
             result.expandToInclude(coords[j++], coords[j++]);
         }

         // recursive quadtree scan, each call samples a cross shaped 
set of 5 point
         int samples = transform(envelope.getCenter(0), 
envelope.getCenter(1), envelope.getWidth() / 2, envelope.getHeight() / 
2, result, transform, new double[10], tolerance);
         System.out.println("Elapsed " + (System.currentTimeMillis() - 
start) + ", " + samples  + " samples " + result );
         return result;
     }

     private static int transform(double cx, double cy, double hw, 
double hh, com.vividsolutions.jts.geom.Envelope result, MathTransform 
transform, double[] coords, double tolerance) throws TransformException {
         double initialArea = result.getWidth() * result.getHeight();

         // build the cross, first center, then 4 satellites
         coords[0] = cx;
         coords[1] = cy;
         coords[2] = cx;
         coords[3] = cy - hh;
         coords[4] = cx;
         coords[5] = cy + hh;
         coords[6] = cx - hw;
         coords[7] = cy;
         coords[8] = cx + hw;
         coords[9] = cy;
         transform.transform(coords, 0, coords, 0, 5);
         for (int i = 0, j = 0; i < 4; i++) {
             result.expandToInclude(coords[j++], coords[j++]);
         }

         // if we did expand the envelope at least one thousands, keep 
on recursinv it
         int samples = 10;
         if(result.getWidth() * result.getHeight() / initialArea > (1 + 
tolerance)) {
             double qw = hw / 2;
             double qh = hh / 2;
             samples += transform(cx - qw, cy - qh, qw, qh, result, 
transform, coords, tolerance);
             samples +=transform(cx + qw, cy - qh, qw, qh, result, 
transform, coords, tolerance);
             samples +=transform(cx - qw, cy + qh, qw, qh, result, 
transform, coords, tolerance);
             samples +=transform(cx + qw, cy + qh, qw, qh, result, 
transform, coords, tolerance);
         }
         return samples;
     }

}

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

If you run it, you'll see that with a tolerance of 0.0001 we're already
pretty much within the ideal envelope, and even asking for a tolerance
of 1e-20 does not loads the processor up enough to make for a measurable
delay (the sysouts printing elapsed time are more or less always
0 on my PC, with some occasional 15 milliseconds, I guess this is the
shortest time my PC tick can measure).

Cheers
Andrea

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Geotools-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/geotools-devel

Reply via email to