@@ -184,7 +184,7 @@ class LatLonEllipsoidal_Datum extends LatLonEllipsoidal {
184
184
* @param {number|string|Object } lat|latlon - Geodetic Latitude (in degrees) or comma-separated lat/lon or lat/lon object.
185
185
* @param {number } [lon] - Longitude in degrees.
186
186
* @param {number } [height=0] - Height above ellipsoid in metres.
187
- * @param {LatLon.datums } [datum=LatLon.datums. WGS84] - Datum this point is defined within.
187
+ * @param {LatLon.datums } [datum=WGS84] - Datum this point is defined within.
188
188
* @returns {LatLon } Latitude/longitude point on ellipsoidal model earth using given datum.
189
189
* @throws {TypeError } Unrecognised datum.
190
190
*
@@ -221,26 +221,9 @@ class LatLonEllipsoidal_Datum extends LatLonEllipsoidal {
221
221
convertDatum ( toDatum ) {
222
222
if ( ! toDatum || toDatum . ellipsoid == undefined ) throw new TypeError ( `unrecognised datum ‘${ toDatum } ’` ) ;
223
223
224
- let oldLatLon = this ;
225
- let transform = null ;
226
-
227
- if ( oldLatLon . datum == datums . WGS84 ) {
228
- // converting from WGS 84
229
- transform = toDatum . transform ;
230
- }
231
- if ( toDatum == datums . WGS84 ) {
232
- // converting to WGS 84; use inverse transform
233
- transform = oldLatLon . datum . transform . map ( p => - p ) ;
234
- }
235
- if ( transform == null ) {
236
- // neither this.datum nor toDatum are WGS84: convert this to WGS84 first
237
- oldLatLon = this . convertDatum ( datums . WGS84 ) ;
238
- transform = toDatum . transform ;
239
- }
240
-
241
- const oldCartesian = oldLatLon . toCartesian ( ) ; // convert geodetic to cartesian...
242
- const newCartesian = oldCartesian . applyTransform ( transform ) ; // ...apply transform...
243
- const newLatLon = newCartesian . toLatLon ( toDatum ) ; // ...and convert cartesian to geodetic
224
+ const oldCartesian = this . toCartesian ( ) ; // convert geodetic to cartesian
225
+ const newCartesian = oldCartesian . convertDatum ( toDatum ) ; // convert datum
226
+ const newLatLon = newCartesian . toLatLon ( ) ; // convert cartesian back to geodetic
244
227
245
228
return newLatLon ;
246
229
}
@@ -255,7 +238,7 @@ class LatLonEllipsoidal_Datum extends LatLonEllipsoidal {
255
238
*/
256
239
toCartesian ( ) {
257
240
const cartesian = super . toCartesian ( ) ;
258
- const cartesianDatum = new Cartesian_Datum ( cartesian . x , cartesian . y , cartesian . z ) ;
241
+ const cartesianDatum = new Cartesian_Datum ( cartesian . x , cartesian . y , cartesian . z , this . datum ) ;
259
242
return cartesianDatum ;
260
243
}
261
244
@@ -266,31 +249,117 @@ class LatLonEllipsoidal_Datum extends LatLonEllipsoidal {
266
249
267
250
268
251
/**
269
- * Converts geocentric ECEF (earth-centered earth-fixed) cartesian coordinates to latitude/longitude points,
270
- * applies Helmert transformations.
252
+ * Augments Cartesian with datum the cooordinate is based on, and methods to convert between datums
253
+ * (using Helmert 7-parameter transforms) and to convert cartesian to geodetic latitude/longitude
254
+ * point.
271
255
*
272
256
* @extends Cartesian
273
257
*/
274
258
class Cartesian_Datum extends Cartesian {
275
259
260
+ /**
261
+ * Creates cartesian coordinate representing ECEF (earth-centric earth-fixed) point, on a given
262
+ * datum. The datum will identify the primary meridian (for the x-coordinate), and is also
263
+ * useful in transforming to/from geodetic (lat/lon) coordinates.
264
+ *
265
+ * @param {number } x - X coordinate in metres (=> 0°N,0°E).
266
+ * @param {number } y - Y coordinate in metres (=> 0°N,90°E).
267
+ * @param {number } z - Z coordinate in metres (=> 90°N).
268
+ * @param {LatLon.datums } [datum] - Datum this coordinate is defined within.
269
+ * @throws {TypeError } Unrecognised datum.
270
+ *
271
+ * @example
272
+ * import { Cartesian } from '/js/geodesy/latlon-ellipsoidal-datum.js';
273
+ * const coord = new Cartesian(3980581.210, -111.159, 4966824.522);
274
+ */
275
+ constructor ( x , y , z , datum = undefined ) {
276
+ if ( datum && datum . ellipsoid == undefined ) throw new TypeError ( `unrecognised datum ‘${ datum } ’` ) ;
277
+
278
+ super ( x , y , z ) ;
279
+
280
+ if ( datum ) this . _datum = datum ;
281
+ }
282
+
283
+
284
+ /**
285
+ * Datum this point is defined within.
286
+ */
287
+ get datum ( ) {
288
+ return this . _datum ;
289
+ }
290
+ set datum ( datum ) {
291
+ if ( ! datum || datum . ellipsoid == undefined ) throw new TypeError ( `unrecognised datum ‘${ datum } ’` ) ;
292
+ this . _datum = datum ;
293
+ }
294
+
295
+
276
296
/**
277
297
* Converts ‘this’ (geocentric) cartesian (x/y/z) coordinate to (geodetic) latitude/longitude
278
- * point on specified datum.
298
+ * point (based on the same datum, or WGS84 if unset) .
279
299
*
280
- * Shadow of Cartesian.toLatLon(), returning LatLon augmented with LatLonEllipsoidal_Datum methods
281
- * convertDatum, toCartesian, etc.
300
+ * Shadow of Cartesian.toLatLon(), returning LatLon augmented with LatLonEllipsoidal_Datum
301
+ * methods convertDatum, toCartesian, etc.
282
302
*
283
- * @param {LatLon.datums } [datum=LatLon.datums.WGS84] - Datum to use when converting point .
284
- * @returns { LatLon } Latitude/longitude point defined by cartesian coordinates, in given datum.
303
+ * @returns {LatLon } Latitude/longitude point defined by cartesian coordinates .
304
+ * @throws { TypeError } Unrecognised datum
285
305
*
286
306
* @example
287
- * const c = new Cartesian(4027893.924, 307041.993, 4919474.294)
288
- * const p = c.toLatLon().convertDatum(LatLon.datums.OSGB36) ; // 50.7971 °N, 004.3612 °E
307
+ * const c = new Cartesian(4027893.924, 307041.993, 4919474.294);
308
+ * const p = c.toLatLon(); // 50.7978 °N, 004.3592 °E
289
309
*/
290
- toLatLon ( datum = datums . WGS84 ) {
310
+ toLatLon ( deprecatedDatum = undefined ) {
311
+ if ( deprecatedDatum ) {
312
+ console . info ( 'datum parameter to Cartesian_Datum.toLatLon is deprecated: set datum before calling toLatLon()' ) ;
313
+ this . datum = deprecatedDatum ;
314
+ }
315
+ const datum = this . datum || datums . WGS84 ;
291
316
if ( ! datum || datum . ellipsoid == undefined ) throw new TypeError ( `unrecognised datum ‘${ datum } ’` ) ;
292
- const latLon = super . toLatLon ( datum . ellipsoid ) ;
293
- return new LatLonEllipsoidal_Datum ( latLon . lat , latLon . lon , latLon . height , datum ) ;
317
+
318
+ const latLon = super . toLatLon ( datum . ellipsoid ) ; // TODO: what if datum is not geocentric?
319
+ const point = new LatLonEllipsoidal_Datum ( latLon . lat , latLon . lon , latLon . height , this . datum ) ;
320
+ return point ;
321
+ }
322
+
323
+
324
+ /**
325
+ * Converts ‘this’ cartesian coordinate to new datum using Helmert 7-parameter transformation.
326
+ *
327
+ * @param {LatLon.datums } toDatum - Datum this coordinate is to be converted to.
328
+ * @returns {Cartesian } This point converted to new datum.
329
+ * @throws {Error } Undefined datum.
330
+ *
331
+ * @example
332
+ * const c = new Cartesian(3980574.247, -102.127, 4966830.065, LatLon.datums.OSGB36);
333
+ * c.convertDatum(LatLon.datums.Irl1975); // [??,??,??]
334
+ */
335
+ convertDatum ( toDatum ) {
336
+ // TODO: what if datum is not geocentric?
337
+ if ( ! toDatum || toDatum . ellipsoid == undefined ) throw new TypeError ( `unrecognised datum ‘${ toDatum } ’` ) ;
338
+ if ( ! this . datum ) throw new TypeError ( 'cartesian coordinate has no datum' ) ;
339
+
340
+ let oldCartesian = null ;
341
+ let transform = null ;
342
+
343
+ if ( this . datum == undefined || this . datum == datums . WGS84 ) {
344
+ // converting from WGS 84
345
+ oldCartesian = this ;
346
+ transform = toDatum . transform ;
347
+ }
348
+ if ( toDatum == datums . WGS84 ) {
349
+ // converting to WGS 84; use inverse transform
350
+ oldCartesian = this ;
351
+ transform = this . datum . transform . map ( p => - p ) ;
352
+ }
353
+ if ( transform == null ) {
354
+ // neither this.datum nor toDatum are WGS84: convert this to WGS84 first
355
+ oldCartesian = this . convertDatum ( datums . WGS84 ) ;
356
+ transform = toDatum . transform ;
357
+ }
358
+
359
+ const newCartesian = oldCartesian . applyTransform ( transform ) ;
360
+ newCartesian . datum = toDatum ;
361
+
362
+ return newCartesian ;
294
363
}
295
364
296
365
0 commit comments