proj4js v2.6.1 not working?
hoogw opened this issue · comments
I use browserify to get a reproject.js file, include in html script tag. I get proj4 , I get proj4 not define error.
Does it means, reproject.js does not have 'proj4' object? read the previous issue, it should already include proj4 object, it is 6k line of code, have 204KB size.
How I fix?
I manually include script tag for proj4 v2.6.1
proj4 undefine error is gone, but reproject is not working.
proj4.defs('EPSG:2229','+proj=lcc +lat_1=35.46666666666667 +lat_2=34.03333333333333 +lat_0=33.5 +lon_0=-118 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs');
var from_projection = "+proj=lcc +lat_1=35.46666666666667 +lat_2=34.03333333333333 +lat_0=33.5 +lon_0=-118 +x_0=2000000.0001016 +y_0=500000.0001016001 +ellps=GRS80 +datum=NAD83 +to_meter=0.3048006096012192 +no_defs"
// for reproject.js only
var crss = {
// 'EPSG:2229': proj4.defs('EPSG:2229'),
// "EPSG:4326": proj4.defs('EPSG:4326')
};
var ___reprojected_geojson = reproject.reproject(_geometry_, from_projection, proj4.WGS84, ___crss)
Do I need extra include proj4 v2.6.1?
without this extra script tag, I always get proj4 is undefine error.
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.6.1/proj4.js"></script>
After include this script tag, reproject.reproject(.....) failed working.
Is it because proj4.js v2.6.1 not compatibile? I use browserify.js
Hi!
You can provide proj4
object directly, but usually you don't need to, it's simpler to just provide the proj definition, since reproject
already includes proj4.
Here is a small sample similar to yours:
const fromProj = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs '
const geojson = {
type: 'Point',
coordinates: [319180, 6399862]
}
const reprojected = reproject.toWgs84(geojson, fromProj)
document.getElementById("app").innerHTML = JSON.stringify(reprojected, null, 2);
As you can see, you don't need to bother with crss
or Proj4's defs
, it is usually simpler to just pass in the proj4 definitions as strings directly.
You can see the sampe above in action here: https://codesandbox.io/s/busy-morse-igpjb?fontsize=14&hidenavigation=1&theme=dark
test your sample on browserified reproject.js file, it works !!!!
For those beginner like me, run into several trouble before it works,
read the steps below will help you avoid the trouble I had.
1) must use sudo install globally
sudo npm install -g brwoserify
https://github.com/perliedman/reproject
sudo npm install reproject // install locally is fine
must manually create 'dist' folder for later output file use
2) must use --s expose global variable function 'reproject' and or 'toWgs84' you will use later in browser js.
without --s , will get 'reproject' undefined error . https://makerlog.org/posts/creating-js-library-builds-with-browserify-and-other-npm-modules
browserify --help will list all options. -o means output file directory
browserify node_modules/reproject/index.js --s reproject -o node_modules/reproject/dist/reproject.js
3) in browser js, NOTE: reproject is a global object, represent the whole module, all sub function must start from it
reproject.reproject(....)
reproject.toWgs84(...)
Once you had browserify file at :
dist/reproject.js
Run this test code, it works
function test_reproject(){
// works
const test_fromProj = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs '
const test_geojson = {
type: 'Point',
coordinates: [319180, 6399862]
}
const reprojected = reproject.toWgs84(test_geojson, test_fromProj)
console.log(' test reprojected ' , reprojected)
}
However, I get error:
uncaught exception: Terraformer: invalid input for Terraformer.Point
because I use terraformer.js
I guess reproject.js and terraformer.js shared some same variable, cause variable polluted
I am not sure why,
I found the reason, test code working is because test_geometry object prototype is kind of empty.
however, geometry ( this is my real data, get from WKT -> terraformor.WKT.parser -> geometry)
geometry object's prototype constructor is not empty, it has some stuff inheritage from terraformer.point. when I run reproject.reproject(geometry) will get above error.
I guess reproject.js use trigger 'point' constructor, which trigger terraformer.js to work
This is first time I see this kind of error.
the solution is before feed into reproject.js, you must clean the terraformer.js polluted geometry object,
I recommend if you can provide a browserified reproject.js in source code foder dist/reproject.js
and also we can use:
wget https://raw.github.com/perliedman/reproject/master/dist/reproject.js
directly download, and directly use script tag include in html and directly use it as:
reproject.toWgs84()
and
reproject.reproject()
This will save 4 hours frustration that other beginner could had.
specially when use browserify, you must use --s reproject
browserify node_modules/reproject/index.js --s reproject -o node_modules/reproject/dist/reproject.js
without --s reproject, you will get reproject undefine error
I already have one, but can't upload here, best if you provide one here
wellknown.js will not pollute geometry, use reproject.js will not cause error.
So wellknownText string -> wellknown.js -> geometry object -> reproject.js works fine
// use terraformer wkt parser(both works 1)
//var ___geometry = Terraformer.WKT.parse(___wkt_string);
// use wellknown.js (both works 2)
var ___geometry = wellknown.parse(___wkt_string);
However,
wellknownText string -> terraformer.WKT.parser.js -> geometry object(polluted, must clean) -> reproject.js
// terraformer.js polluted geometry object, its prototype have constructor as terraformer.Point when feed into reproject.js, will trigger constructor call, then invalide point error.
var _cleaned_geometry = {}
_cleaned_geometry.type = _geometry_.type
_cleaned_geometry.coordinates = _geometry_.coordinates
var ___reprojected_geometry = reproject.toWgs84(_cleaned_geometry , from_projection)
*/
// wellknown.js not need to clean (only terraformer.js WKT parser need to)
var ___reprojected_geometry = reproject.toWgs84(_geometry_ , from_projection)
other wise, if you want you can write your own re-project funtion
when I can't get reproject to work, I wrote my own, now, I just use reproject.js,
unless if you want to speed up the performance, remove the overhead, wrote your own function.
function reproject_coordinate(_geometry_){
// not finish yet, only support point so far.
// alternative to reproject.js
// manually re-project each long-lat pair by proj4js based on type(point, line, polygon etc.)
/*
EPSG: 4326 uses a coordinate system on the surface of a sphere or ellipsoid of reference.
EPSG: 3857 uses a coordinate system PROJECTED from the surface of the sphere or ellipsoid to a flat surface.
Think of it as this way:
EPSG 4326 uses a coordinate system the same as a GLOBE (curved surface). EPSG 3857 uses a coordinate system the same as a MAP (flat surface).
Google Earth is in a Geographic coordinate system with the wgs84 datum. (EPSG: 4326)
Google Maps is in a projected coordinate system that is based on the wgs84 datum. (EPSG 3857)
The data in Open Street Map database is stored in a gcs with units decimal degrees & datum of wgs84. (EPSG: 4326)
The Open Street Map tiles and the WMS webservice, are in the projected coordinate system that is based on the wgs84 datum. (EPSG 3857)
So if you are making a web map, which uses the tiles from Google Maps or tiles from the Open Street Map webservice, they will be in Sperical Mercator (EPSG 3857 or srid: 900913) and hence your map has to have the same projection.
All of this further confused by that fact that often even though the map is in Web Mercator(EPSG: 3857), the actual coordinates used are in lat-long (EPSG: 4326). This convention is used in many places, such as:
In Most Mapping API,s You can give the coordinates in Lat-long, and the API automatically transforms it to the appropriate Web Mercator coordinates.
While Making a KML, you will always give the coordinates in geographic Lat-long, even though it might be showed on top of a web Mercator map.
Most mobile mapping Libraries use lat-long for position, while the map is in web Mercator.
EPSG:3857 calls its units metres, but they are not real metres. The more to the north you come, the more squeezed they are
Google uses Google Mercator (EPSG:3857 or EPSG:900913) for displaying, but I think you/the Javascript API want lat/lon coordinates for input. see here https://spatialreference.org/ref/sr-org/google-projection/
OpenLayers is capable of dealing with most projections. If you do not explicitly set one, your map is going to use our default which is the Web Mercator projection (EPSG:3857).
The same projection is used e.g. for the maps of the OpenStreetMap-project and commercial products such as Bing Maps or Google Maps.
*/
var ___unproj_coordinate = _geometry_.coordinates
var _geometry_type_ = _geometry_.type
var ___reproj_coordinate;
switch(_geometry_type_.toLowerCase()){
case 'point':
// code block
___reproj_coordinate = proj4(from_projection_EPSG, to_projection_EPSG, ___unproj_coordinate);
break;
case 'polygon':
// code block
break;
case 'line':
// code block
break;
case 'multipolygon':
// code block
break;
default:
// code block
} // case
_geometry_.coordinates = ___reproj_coordinate
return _geometry_
}
It looks like your main issue here is your build setup and various tools you are integrating with. Not sure there is really an issue related to reproject itself?