[GIS] Openlayers/Proj4js not transforming coordinates the first time

javascriptopenlayers-2proj

Something seems to be going wrong with my transformations. Before I added proj4js, transforming a coordinate went fine:

new OpenLayers.LonLat(-1.0, 52.0).transform(new OpenLayers.Projection('EPSG:4326'), new OpenLayers.Projection('EPSG:900913'))

results in proper google-coordinates:

lon: -111319.49077778
lat: 6800125.4534507

This properly set the center of my map somewhere in Europe.

After adding proj4js to my project, suddenly the center of the map shifted to Africa (close to 0,0). After setting a breakpoint, I could see what happened. The resulting coordinates of the statement at the start of this question yieled this result:

lon: -1
lat: 52

So no transformation whatsoever has taken place! However, if I would execute the same statement again, still at the same breakpoint, it would start giving the right result again:

lon: -111319.49079327356
lat: 6800125.454397307

What is going on here? Do I need to initialise something before I can use proj4js properly?

These are my script includes:

<script type="text/javascript" src="/OpenLayers-2.10/OpenLayers.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/proj4js.js"></script>

Best Answer

After further investigation, I've managed to solve the problem. What is causing the problem is that Proj4js will dynamically load any parts it needs rather than immediately loading all of it's scripts.

Internet Explorer has most trouble with this, but also Firefox and Chrome show the symptom. IE managed to not be able to use any transformations, even after a subsequent ajax call to get data had already finished. Both Firefox and Chrome did not have the transformations available on time for the center of the map being set correctly, but did have them very shortly after, resulting in my ajax-loaded data to be transformed correctly for displaying on the map.

From Visual Studio I could see that after each call to create a new projection, scripts would be dynamically loaded. Firstly, it would load the projection definition:

/Scripts/proj4js/defs/EPSG27700.js

From the definition it would then load the projection type being used (in this case transverse mercator):

/Scripts/proj4js/projCode/tmerc.js

The only problem was that apparantly, the browser was not able to process these files in time before needing to use them, resulting in no transformation actually taking place. The solution to this was to add any needed definitions to my script-includes manually:

<script type="text/javascript" src="/OpenLayers-2.10/OpenLayers.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/proj4js.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/projCode/merc.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/projCode/tmerc.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/defs/EPSG27700.js"></script>
<script type="text/javascript" src="/Scripts/proj4js/defs/EPSG900913.js"></script>

And now all the transformations I needed were avaiable as soon as the page had loaded, so it would perform all transformations correctly.

In order to know what extra files to include, see which (EPSG) definitions you need. Inlcude those definitions. Look inside those files and see which projections they use For example, EPSG 27700 is defined as follows:

Proj4js.defs["EPSG:27700"] = "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs";

So we can see that it uses tmerc (transverse mercator), so we include that projection. Do this for any definition you need.

Note that WGS84 (EPSG:4326) is included by default. It doesn't even have a separate defining javascript file.