Skip to content

Commit f7aba22

Browse files
authored
Merge pull request #327 from lcalisto/master
Added geocentric projections
2 parents 6b33614 + ca99734 commit f7aba22

File tree

9 files changed

+157
-58
lines changed

9 files changed

+157
-58
lines changed

Gruntfile.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ var projs = [
2727
'aeqd',
2828
'ortho',
2929
'qsc',
30-
'robin'
30+
'robin',
31+
'geocent'
3132
];
32-
module.exports = function(grunt) {
33+
module.exports = function (grunt) {
3334
grunt.initConfig({
3435
pkg: grunt.file.readJSON('package.json'),
3536
connect: {

lib/core.js

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,33 @@ function transformer(from, to, coords) {
77
if (Array.isArray(coords)) {
88
transformedArray = transform(from, to, coords);
99
if (coords.length > 2) {
10-
return [transformedArray.x, transformedArray.y].concat(coords.splice(2));
11-
}
12-
else {
10+
if ((typeof from.name !== 'undefined' && from.name === 'geocent') || (typeof to.name !== 'undefined' && to.name === 'geocent')) {
11+
if (typeof transformedArray.z === 'number') {
12+
return [transformedArray.x, transformedArray.y, transformedArray.z].concat(coords.splice(3));
13+
} else {
14+
return [transformedArray.x, transformedArray.y, coords[2]].concat(coords.splice(3));
15+
}
16+
} else {
17+
return [transformedArray.x, transformedArray.y].concat(coords.splice(2));
18+
}
19+
} else {
1320
return [transformedArray.x, transformedArray.y];
1421
}
15-
}
16-
else {
22+
} else {
1723
out = transform(from, to, coords);
1824
keys = Object.keys(coords);
1925
if (keys.length === 2) {
2026
return out;
2127
}
2228
keys.forEach(function (key) {
23-
if (key === 'x' || key === 'y') {
24-
return;
29+
if ((typeof from.name !== 'undefined' && from.name === 'geocent') || (typeof to.name !== 'undefined' && to.name === 'geocent')) {
30+
if (key === 'x' || key === 'y' || key === 'z') {
31+
return;
32+
}
33+
} else {
34+
if (key === 'x' || key === 'y') {
35+
return;
36+
}
2537
}
2638
out[key] = coords[key];
2739
});
@@ -38,6 +50,7 @@ function checkProj(item) {
3850
}
3951
return proj(item);
4052
}
53+
4154
function proj4(fromProj, toProj, coord) {
4255
fromProj = checkProj(fromProj);
4356
var single = false;
@@ -46,8 +59,7 @@ function proj4(fromProj, toProj, coord) {
4659
toProj = fromProj;
4760
fromProj = wgs84;
4861
single = true;
49-
}
50-
else if (typeof toProj.x !== 'undefined' || Array.isArray(toProj)) {
62+
} else if (typeof toProj.x !== 'undefined' || Array.isArray(toProj)) {
5163
coord = toProj;
5264
toProj = fromProj;
5365
fromProj = wgs84;
@@ -56,13 +68,12 @@ function proj4(fromProj, toProj, coord) {
5668
toProj = checkProj(toProj);
5769
if (coord) {
5870
return transformer(fromProj, toProj, coord);
59-
}
60-
else {
71+
} else {
6172
obj = {
62-
forward: function(coords) {
73+
forward: function (coords) {
6374
return transformer(fromProj, toProj, coords);
6475
},
65-
inverse: function(coords) {
76+
inverse: function (coords) {
6677
return transformer(toProj, fromProj, coords);
6778
}
6879
};
@@ -72,4 +83,4 @@ function proj4(fromProj, toProj, coord) {
7283
return obj;
7384
}
7485
}
75-
export default proj4;
86+
export default proj4;

lib/includedProjections.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import aegd from "./projections/aeqd";
2323
import etmerc from './projections/etmerc';
2424
import qsc from './projections/qsc';
2525
import robin from './projections/robin';
26+
import geocent from './projections/geocent';
2627

2728
var projs = [
2829
tmerc,
@@ -49,11 +50,12 @@ var projs = [
4950
aegd,
5051
etmerc,
5152
qsc,
52-
robin
53+
robin,
54+
geocent
5355
];
5456

55-
export default function(proj4){
56-
projs.forEach(function(proj){
57+
export default function (proj4) {
58+
projs.forEach(function (proj) {
5759
proj4.Proj.projections.add(proj);
5860
});
59-
}
61+
}

lib/projections/geocent.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import {
2+
geodeticToGeocentric,
3+
geocentricToGeodetic
4+
} from '../datumUtils';
5+
6+
export function init() {
7+
this.name = 'geocent';
8+
9+
}
10+
11+
export function forward(p) {
12+
var point = geodeticToGeocentric(p, this.es, this.a);
13+
return point;
14+
}
15+
16+
export function inverse(p) {
17+
var point = geocentricToGeodetic(p, this.es, this.a, this.b);
18+
return point;
19+
}
20+
21+
export var names = ["Geocentric", 'geocentric', "geocent", "Geocent"];
22+
export default {
23+
init: init,
24+
forward: forward,
25+
inverse: inverse,
26+
names: names
27+
};

lib/transform.js

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,15 @@ export default function transform(source, dest, point) {
2929
if (source.projName === 'longlat') {
3030
point = {
3131
x: point.x * D2R,
32-
y: point.y * D2R
32+
y: point.y * D2R,
33+
z: point.z || 0
3334
};
34-
}
35-
else {
35+
} else {
3636
if (source.to_meter) {
3737
point = {
3838
x: point.x * source.to_meter,
39-
y: point.y * source.to_meter
39+
y: point.y * source.to_meter,
40+
z: point.z || 0
4041
};
4142
}
4243
point = source.inverse(point); // Convert Cartesian to longlat
@@ -53,22 +54,25 @@ export default function transform(source, dest, point) {
5354
if (dest.from_greenwich) {
5455
point = {
5556
x: point.x - dest.from_greenwich,
56-
y: point.y
57+
y: point.y,
58+
z: point.z || 0
5759
};
5860
}
5961

6062
if (dest.projName === 'longlat') {
6163
// convert radians to decimal degrees
6264
point = {
6365
x: point.x * R2D,
64-
y: point.y * R2D
66+
y: point.y * R2D,
67+
z: point.z || 0
6568
};
6669
} else { // else project
6770
point = dest.forward(point);
6871
if (dest.to_meter) {
6972
point = {
7073
x: point.x / dest.to_meter,
71-
y: point.y / dest.to_meter
74+
y: point.y / dest.to_meter,
75+
z: point.z || 0
7276
};
7377
}
7478
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"doc": "docs"
1010
},
1111
"scripts": {
12+
"prepare": "grunt",
1213
"build": "grunt",
1314
"build:tmerc": "grunt build:tmerc",
1415
"test": "npm run build && istanbul test _mocha test/test.js"

projs.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import aeqd from './lib/projections/aeqd';
2424
import ortho from './lib/projections/ortho';
2525
import qsc from './lib/projections/qsc';
2626
import robin from './lib/projections/robin';
27+
import geocent from './lib/projections/geocent';
2728
export default function(proj4){
2829
proj4.Proj.projections.add(tmerc);
2930
proj4.Proj.projections.add(etmerc);
@@ -51,4 +52,5 @@ export default function(proj4){
5152
proj4.Proj.projections.add(ortho);
5253
proj4.Proj.projections.add(qsc);
5354
proj4.Proj.projections.add(robin);
55+
proj4.Proj.projections.add(geocent);
5456
}

test/test.js

Lines changed: 58 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ function startTests(chai, proj4, testPoints) {
122122
x: testPoint.xy[0],
123123
y: testPoint.xy[1]
124124
};
125+
// in case of geocentric proj we need Z value.
126+
if (typeof testPoint.xy[2] === 'number') {
127+
pt.z = testPoint.xy[2]
128+
}
125129
var ll = proj4(testPoint.code, proj4.WGS84, pt);
126130
assert.closeTo(ll.x, testPoint.ll[0], llEPSLN, 'x is close');
127131
assert.closeTo(ll.y, testPoint.ll[1], llEPSLN, 'y is close');
@@ -167,28 +171,44 @@ function startTests(chai, proj4, testPoints) {
167171
});
168172
});
169173
describe('points', function () {
170-
it('should ignore stuff it does not know', function (){
171-
172-
var sweref99tm = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs';
173-
var rt90 = '+lon_0=15.808277777799999 +lat_0=0.0 +k=1.0 +x_0=1500000.0 +y_0=0.0 +proj=tmerc +ellps=bessel +units=m +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0 +no_defs';
174-
var rslt = proj4(sweref99tm, rt90).forward({
175-
x: 319180,
176-
y: 6399862,
177-
z: 0,
178-
m: 1000,
179-
method: function () {
180-
return 'correct answer';
181-
}
182-
});
183-
assert.closeTo(rslt.x, 1271137.9275601401, 0.000001);
184-
assert.closeTo(rslt.y, 6404230.291459564, 0.000001);
185-
assert.equal(rslt.z, 0);
186-
assert.equal(rslt.m, 1000);
187-
assert.equal(rslt.method(), 'correct answer');
174+
it('should ignore stuff it does not know', function () {
175+
var sweref99tm = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs';
176+
var rt90 = '+lon_0=15.808277777799999 +lat_0=0.0 +k=1.0 +x_0=1500000.0 +y_0=0.0 +proj=tmerc +ellps=bessel +units=m +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0 +no_defs';
177+
var rslt = proj4(sweref99tm, rt90).forward({
178+
x: 319180,
179+
y: 6399862,
180+
z: 0,
181+
m: 1000,
182+
method: function () {
183+
return 'correct answer';
184+
}
185+
});
186+
assert.closeTo(rslt.x, 1271137.9275601401, 0.000001);
187+
assert.closeTo(rslt.y, 6404230.291459564, 0.000001);
188+
assert.equal(rslt.z, 0);
189+
assert.equal(rslt.m, 1000);
190+
assert.equal(rslt.method(), 'correct answer');
191+
});
192+
it('should be able to compute X Y Z M in geocenteric coordinates', function () {
193+
var epsg4978 = '+proj=geocent +datum=WGS84 +units=m +no_defs';
194+
var rslt = proj4(epsg4978).forward({
195+
x: -7.76166,
196+
y: 39.19685,
197+
z: 0,
198+
m: 1000,
199+
method: function () {
200+
return 'correct answer';
201+
}
202+
});
203+
assert.closeTo(rslt.x, 4904199.584207411, 0.000001);
204+
assert.closeTo(rslt.y, -668448.8153664203, 0.000001);
205+
assert.closeTo(rslt.z, 4009276.930771821, 0.000001);
206+
assert.equal(rslt.m, 1000);
207+
assert.equal(rslt.method(), 'correct answer');
188208
});
189209
});
190210
describe('points array', function () {
191-
it('should ignore stuff it does not know', function (){
211+
it('should ignore stuff it does not know', function () {
192212
var sweref99tm = '+proj=utm +zone=33 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs';
193213
var rt90 = '+lon_0=15.808277777799999 +lat_0=0.0 +k=1.0 +x_0=1500000.0 +y_0=0.0 +proj=tmerc +ellps=bessel +units=m +towgs84=414.1,41.3,603.1,-0.855,2.141,-7.023,0 +no_defs';
194214
var rslt = proj4(sweref99tm, rt90).forward([
@@ -202,23 +222,36 @@ function startTests(chai, proj4, testPoints) {
202222
assert.equal(rslt[2], 0);
203223
assert.equal(rslt[3], 1000);
204224
});
225+
it('should be able to compute X Y Z M in geocenteric coordinates', function () {
226+
var epsg4978 = '+proj=geocent +datum=WGS84 +units=m +no_defs';
227+
var rslt = proj4(epsg4978).forward([
228+
-7.76166,
229+
39.19685,
230+
0,
231+
1000
232+
]);
233+
assert.closeTo(rslt[0], 4904199.584207411, 0.000001);
234+
assert.closeTo(rslt[1], -668448.8153664203, 0.000001);
235+
assert.closeTo(rslt[2], 4009276.930771821, 0.000001);
236+
assert.equal(rslt[3], 1000);
237+
});
205238
});
206-
describe('defs', function() {
239+
describe('defs', function () {
207240
assert.equal(proj4.defs('testmerc'), proj4.defs['testmerc']);
208241
proj4.defs('foo', '+proj=merc +lon_0=5.937 +lat_ts=45.027 +ellps=sphere');
209242
assert.typeOf(proj4.defs['foo'], 'object');
210243
proj4.defs('urn:x-ogc:def:crs:EPSG:4326', proj4.defs('EPSG:4326'));
211244
assert.strictEqual(proj4.defs['urn:x-ogc:def:crs:EPSG:4326'], proj4.defs['EPSG:4326']);
212245

213-
describe('wkt', function() {
214-
it('should provide the correct conversion factor for WKT GEOGCS projections', function() {
246+
describe('wkt', function () {
247+
it('should provide the correct conversion factor for WKT GEOGCS projections', function () {
215248
proj4.defs('EPSG:4269', 'GEOGCS["NAD83",DATUM["North_American_Datum_1983",SPHEROID["GRS 1980",6378137,298.257222101,AUTHORITY["EPSG","7019"]],AUTHORITY["EPSG","6269"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4269"]]');
216-
assert.equal(proj4.defs['EPSG:4269'].to_meter, 6378137*0.01745329251994328);
249+
assert.equal(proj4.defs['EPSG:4269'].to_meter, 6378137 * 0.01745329251994328);
217250

218251
proj4.defs('EPSG:4279', 'GEOGCS["OS(SN)80",DATUM["OS_SN_1980",SPHEROID["Airy 1830",6377563.396,299.3249646,AUTHORITY["EPSG","7001"]],AUTHORITY["EPSG","6279"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.01745329251994328,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4279"]]');
219-
assert.equal(proj4.defs['EPSG:4279'].to_meter, 6377563.396*0.01745329251994328);
252+
assert.equal(proj4.defs['EPSG:4279'].to_meter, 6377563.396 * 0.01745329251994328);
220253
});
221-
it('should parse wkt and proj4 of the same crs and result in the same params', function() {
254+
it('should parse wkt and proj4 of the same crs and result in the same params', function () {
222255
var s1 = 'GEOGCS["PSD93",DATUM["PDO_Survey_Datum_1993",SPHEROID["Clarke 1880 (RGS)",6378249.145,293.465,AUTHORITY["EPSG","7012"]],TOWGS84[-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.7101],AUTHORITY["EPSG","6134"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4134"]]';
223256
var s2 = '+proj=longlat +ellps=clrk80 +towgs84=-180.624,-225.516,173.919,-0.81,-1.898,8.336,16.7101 +no_defs';
224257
var crs1 = proj4(s1);

test/testData.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -556,18 +556,36 @@ var testPoints = [
556556
{
557557
code: 'PROJCS["WGS 84 / Pseudo-Mercator", GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 0, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic latitude", NORTH], AXIS["Geodetic longitude", EAST], AUTHORITY["EPSG","4326"]], PROJECTION["Popular Visualisation Pseudo Mercator", AUTHORITY["EPSG","1024"]], PARAMETER["semi_minor", 6378137.0], PARAMETER["latitude_of_origin", 0.0], PARAMETER["central_meridian", 0.0], PARAMETER["scale_factor", 1.0], PARAMETER["false_easting", 0.0], PARAMETER["false_northing", 0.0], UNIT["m", 1.0], AXIS["Easting", EAST], AXIS["Northing", NORTH], AUTHORITY["EPSG","3857"]]',
558558
xy: [-12523490.49256873, 5166512.50707369],
559-
ll: [-112.50042920000004,42.036926809999976]
559+
ll: [-112.50042920000004, 42.036926809999976]
560560
},
561561
{
562562
code: 'PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","9999"]]',
563563
xy: [-12523490.49256873, 5166512.50707369],
564-
ll: [-112.50042920000004,42.036926809999976]
564+
ll: [-112.50042920000004, 42.036926809999976]
565+
},
566+
{
567+
code: '+proj=geocent +datum=WGS84 +units=m +no_defs',
568+
ll: [-7.56234, 38.96618, 0],
569+
xy: [4922499, -653508, 3989398],
570+
acc: {
571+
ll: 0,
572+
xy: 0
573+
}
574+
},
575+
{
576+
code: '+proj=geocent +ellps=GRS80 +units=m +no_defs',
577+
ll: [-7.56234, 38.96618, 1],
578+
xy: [4922499, -653508, 3989399],
579+
acc: {
580+
ll: 0,
581+
xy: 0
582+
}
565583
}
566584
];
567-
if(typeof module !== 'undefined'){
585+
if (typeof module !== 'undefined') {
568586
module.exports = testPoints;
569-
}else if(typeof define === 'function'){
570-
define(function(){
587+
} else if (typeof define === 'function') {
588+
define(function () {
571589
return testPoints;
572590
});
573-
}
591+
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy