1+ import type { Faker } from '../..' ;
12import { FakerError } from '../../errors/faker-error' ;
2- import { ModuleBase } from '../../internal/module-base' ;
3+ import { SimpleModuleBase } from '../../internal/module-base' ;
34
45/**
56 * Represents a language with its full name, 2 character ISO 639-1 code, and 3 character ISO 639-2 code.
@@ -21,6 +22,178 @@ export interface Language {
2122 alpha3 : string ;
2223}
2324
25+ /**
26+ * Module with location functions that don't require localized data
27+ */
28+ export class SimpleLocationModule extends SimpleModuleBase {
29+ /**
30+ * Generates a random latitude.
31+ *
32+ * @param options An options object.
33+ * @param options.max The upper bound for the latitude to generate. Defaults to `90`.
34+ * @param options.min The lower bound for the latitude to generate. Defaults to `-90`.
35+ * @param options.precision The number of decimal points of precision for the latitude. Defaults to `4`.
36+ *
37+ * @example
38+ * faker.location.latitude() // -30.9501
39+ * faker.location.latitude({ max: 10 }) // 5.7225
40+ * faker.location.latitude({ max: 10, min: -10 }) // -9.6273
41+ * faker.location.latitude({ max: 10, min: -10, precision: 5 }) // 2.68452
42+ *
43+ * @since 8.0.0
44+ */
45+ latitude (
46+ options : {
47+ /**
48+ * The upper bound for the latitude to generate.
49+ *
50+ * @default 90
51+ */
52+ max ?: number ;
53+ /**
54+ * The lower bound for the latitude to generate.
55+ *
56+ * @default -90
57+ */
58+ min ?: number ;
59+ /**
60+ * The number of decimal points of precision for the latitude.
61+ *
62+ * @default 4
63+ */
64+ precision ?: number ;
65+ } = { }
66+ ) : number {
67+ const { max = 90 , min = - 90 , precision = 4 } = options ;
68+
69+ return this . faker . number . float ( { min, max, fractionDigits : precision } ) ;
70+ }
71+
72+ /**
73+ * Generates a random longitude.
74+ *
75+ * @param options An options object.
76+ * @param options.max The upper bound for the longitude to generate. Defaults to `180`.
77+ * @param options.min The lower bound for the longitude to generate. Defaults to `-180`.
78+ * @param options.precision The number of decimal points of precision for the longitude. Defaults to `4`.
79+ *
80+ * @example
81+ * faker.location.longitude() // -30.9501
82+ * faker.location.longitude({ max: 10 }) // 5.7225
83+ * faker.location.longitude({ max: 10, min: -10 }) // -9.6273
84+ * faker.location.longitude({ max: 10, min: -10, precision: 5 }) // 2.68452
85+ *
86+ * @since 8.0.0
87+ */
88+ longitude (
89+ options : {
90+ /**
91+ * The upper bound for the longitude to generate.
92+ *
93+ * @default 180
94+ */
95+ max ?: number ;
96+ /**
97+ * The lower bound for the longitude to generate.
98+ *
99+ * @default -180
100+ */
101+ min ?: number ;
102+ /**
103+ * The number of decimal points of precision for the longitude.
104+ *
105+ * @default 4
106+ */
107+ precision ?: number ;
108+ } = { }
109+ ) : number {
110+ const { max = 180 , min = - 180 , precision = 4 } = options ;
111+
112+ return this . faker . number . float ( { max, min, fractionDigits : precision } ) ;
113+ }
114+
115+ /**
116+ * Generates a random GPS coordinate within the specified radius from the given coordinate.
117+ *
118+ * @param options The options for generating a GPS coordinate.
119+ * @param options.origin The original coordinate to get a new coordinate close to.
120+ * If no coordinate is given, a random one will be chosen.
121+ * @param options.radius The maximum distance from the given coordinate to the new coordinate. Defaults to `10`.
122+ * @param options.isMetric If `true` assume the radius to be in kilometers. If `false` for miles. Defaults to `false`.
123+ *
124+ * @example
125+ * faker.location.nearbyGPSCoordinate() // [ 33.8475, -170.5953 ]
126+ * faker.location.nearbyGPSCoordinate({ origin: [33, -170] }) // [ 33.0165, -170.0636 ]
127+ * faker.location.nearbyGPSCoordinate({ origin: [33, -170], radius: 1000, isMetric: true }) // [ 37.9163, -179.2408 ]
128+ *
129+ * @since 8.0.0
130+ */
131+ nearbyGPSCoordinate (
132+ options : {
133+ /**
134+ * The original coordinate to get a new coordinate close to.
135+ */
136+ origin ?: [ latitude : number , longitude : number ] ;
137+ /**
138+ * The maximum distance from the given coordinate to the new coordinate.
139+ *
140+ * @default 10
141+ */
142+ radius ?: number ;
143+ /**
144+ * If `true` assume the radius to be in kilometers. If `false` for miles.
145+ *
146+ * @default false
147+ */
148+ isMetric ?: boolean ;
149+ } = { }
150+ ) : [ latitude : number , longitude : number ] {
151+ const { origin, radius = 10 , isMetric = false } = options ;
152+
153+ // If there is no origin, the best we can do is return a random GPS coordinate.
154+ if ( origin == null ) {
155+ return [ this . latitude ( ) , this . longitude ( ) ] ;
156+ }
157+
158+ const angleRadians = this . faker . number . float ( {
159+ max : 2 * Math . PI ,
160+ fractionDigits : 5 ,
161+ } ) ; // in ° radians
162+
163+ const radiusMetric = isMetric ? radius : radius * 1.60934 ; // in km
164+ const errorCorrection = 0.995 ; // avoid float issues
165+ const distanceInKm =
166+ this . faker . number . float ( {
167+ max : radiusMetric ,
168+ fractionDigits : 3 ,
169+ } ) * errorCorrection ; // in km
170+
171+ /**
172+ * The distance in km per degree for earth.
173+ */
174+ const kmPerDegree = 40_000 / 360 ; // in km/°
175+
176+ const distanceInDegree = distanceInKm / kmPerDegree ; // in °
177+
178+ const coordinate : [ latitude : number , longitude : number ] = [
179+ origin [ 0 ] + Math . sin ( angleRadians ) * distanceInDegree ,
180+ origin [ 1 ] + Math . cos ( angleRadians ) * distanceInDegree ,
181+ ] ;
182+
183+ // Box latitude [-90°, 90°]
184+ coordinate [ 0 ] = coordinate [ 0 ] % 180 ;
185+ if ( coordinate [ 0 ] < - 90 || coordinate [ 0 ] > 90 ) {
186+ coordinate [ 0 ] = Math . sign ( coordinate [ 0 ] ) * 180 - coordinate [ 0 ] ;
187+ coordinate [ 1 ] += 180 ;
188+ }
189+
190+ // Box longitude [-180°, 180°]
191+ coordinate [ 1 ] = ( ( ( coordinate [ 1 ] % 360 ) + 540 ) % 360 ) - 180 ;
192+
193+ return [ coordinate [ 0 ] , coordinate [ 1 ] ] ;
194+ }
195+ }
196+
24197/**
25198 * Module to generate addresses and locations. Prior to Faker 8.0.0, this module was known as `faker.address`.
26199 *
@@ -32,7 +205,11 @@ export interface Language {
32205 *
33206 * For a random country, you can use [`country()`](https://fakerjs.dev/api/location.html#country) or [`countryCode()`](https://fakerjs.dev/api/location.html#countrycode).
34207 */
35- export class LocationModule extends ModuleBase {
208+ export class LocationModule extends SimpleLocationModule {
209+ constructor ( protected readonly faker : Faker ) {
210+ super ( faker ) ;
211+ }
212+
36213 /**
37214 * Generates random zip code from specified format. If format is not specified,
38215 * the locale's zip format is used.
@@ -350,92 +527,6 @@ export class LocationModule extends ModuleBase {
350527 return this . faker . helpers . arrayElement ( stateDataSet ) ;
351528 }
352529
353- /**
354- * Generates a random latitude.
355- *
356- * @param options An options object.
357- * @param options.max The upper bound for the latitude to generate. Defaults to `90`.
358- * @param options.min The lower bound for the latitude to generate. Defaults to `-90`.
359- * @param options.precision The number of decimal points of precision for the latitude. Defaults to `4`.
360- *
361- * @example
362- * faker.location.latitude() // -30.9501
363- * faker.location.latitude({ max: 10 }) // 5.7225
364- * faker.location.latitude({ max: 10, min: -10 }) // -9.6273
365- * faker.location.latitude({ max: 10, min: -10, precision: 5 }) // 2.68452
366- *
367- * @since 8.0.0
368- */
369- latitude (
370- options : {
371- /**
372- * The upper bound for the latitude to generate.
373- *
374- * @default 90
375- */
376- max ?: number ;
377- /**
378- * The lower bound for the latitude to generate.
379- *
380- * @default -90
381- */
382- min ?: number ;
383- /**
384- * The number of decimal points of precision for the latitude.
385- *
386- * @default 4
387- */
388- precision ?: number ;
389- } = { }
390- ) : number {
391- const { max = 90 , min = - 90 , precision = 4 } = options ;
392-
393- return this . faker . number . float ( { min, max, fractionDigits : precision } ) ;
394- }
395-
396- /**
397- * Generates a random longitude.
398- *
399- * @param options An options object.
400- * @param options.max The upper bound for the longitude to generate. Defaults to `180`.
401- * @param options.min The lower bound for the longitude to generate. Defaults to `-180`.
402- * @param options.precision The number of decimal points of precision for the longitude. Defaults to `4`.
403- *
404- * @example
405- * faker.location.longitude() // -30.9501
406- * faker.location.longitude({ max: 10 }) // 5.7225
407- * faker.location.longitude({ max: 10, min: -10 }) // -9.6273
408- * faker.location.longitude({ max: 10, min: -10, precision: 5 }) // 2.68452
409- *
410- * @since 8.0.0
411- */
412- longitude (
413- options : {
414- /**
415- * The upper bound for the longitude to generate.
416- *
417- * @default 180
418- */
419- max ?: number ;
420- /**
421- * The lower bound for the longitude to generate.
422- *
423- * @default -180
424- */
425- min ?: number ;
426- /**
427- * The number of decimal points of precision for the longitude.
428- *
429- * @default 4
430- */
431- precision ?: number ;
432- } = { }
433- ) : number {
434- const { max = 180 , min = - 180 , precision = 4 } = options ;
435-
436- return this . faker . number . float ( { max, min, fractionDigits : precision } ) ;
437- }
438-
439530 /**
440531 * Returns a random direction (cardinal and ordinal; northwest, east, etc).
441532 *
@@ -549,87 +640,6 @@ export class LocationModule extends ModuleBase {
549640 ) ;
550641 }
551642
552- /**
553- * Generates a random GPS coordinate within the specified radius from the given coordinate.
554- *
555- * @param options The options for generating a GPS coordinate.
556- * @param options.origin The original coordinate to get a new coordinate close to.
557- * If no coordinate is given, a random one will be chosen.
558- * @param options.radius The maximum distance from the given coordinate to the new coordinate. Defaults to `10`.
559- * @param options.isMetric If `true` assume the radius to be in kilometers. If `false` for miles. Defaults to `false`.
560- *
561- * @example
562- * faker.location.nearbyGPSCoordinate() // [ 33.8475, -170.5953 ]
563- * faker.location.nearbyGPSCoordinate({ origin: [33, -170] }) // [ 33.0165, -170.0636 ]
564- * faker.location.nearbyGPSCoordinate({ origin: [33, -170], radius: 1000, isMetric: true }) // [ 37.9163, -179.2408 ]
565- *
566- * @since 8.0.0
567- */
568- nearbyGPSCoordinate (
569- options : {
570- /**
571- * The original coordinate to get a new coordinate close to.
572- */
573- origin ?: [ latitude : number , longitude : number ] ;
574- /**
575- * The maximum distance from the given coordinate to the new coordinate.
576- *
577- * @default 10
578- */
579- radius ?: number ;
580- /**
581- * If `true` assume the radius to be in kilometers. If `false` for miles.
582- *
583- * @default false
584- */
585- isMetric ?: boolean ;
586- } = { }
587- ) : [ latitude : number , longitude : number ] {
588- const { origin, radius = 10 , isMetric = false } = options ;
589-
590- // If there is no origin, the best we can do is return a random GPS coordinate.
591- if ( origin == null ) {
592- return [ this . latitude ( ) , this . longitude ( ) ] ;
593- }
594-
595- const angleRadians = this . faker . number . float ( {
596- max : 2 * Math . PI ,
597- fractionDigits : 5 ,
598- } ) ; // in ° radians
599-
600- const radiusMetric = isMetric ? radius : radius * 1.60934 ; // in km
601- const errorCorrection = 0.995 ; // avoid float issues
602- const distanceInKm =
603- this . faker . number . float ( {
604- max : radiusMetric ,
605- fractionDigits : 3 ,
606- } ) * errorCorrection ; // in km
607-
608- /**
609- * The distance in km per degree for earth.
610- */
611- const kmPerDegree = 40_000 / 360 ; // in km/°
612-
613- const distanceInDegree = distanceInKm / kmPerDegree ; // in °
614-
615- const coordinate : [ latitude : number , longitude : number ] = [
616- origin [ 0 ] + Math . sin ( angleRadians ) * distanceInDegree ,
617- origin [ 1 ] + Math . cos ( angleRadians ) * distanceInDegree ,
618- ] ;
619-
620- // Box latitude [-90°, 90°]
621- coordinate [ 0 ] = coordinate [ 0 ] % 180 ;
622- if ( coordinate [ 0 ] < - 90 || coordinate [ 0 ] > 90 ) {
623- coordinate [ 0 ] = Math . sign ( coordinate [ 0 ] ) * 180 - coordinate [ 0 ] ;
624- coordinate [ 1 ] += 180 ;
625- }
626-
627- // Box longitude [-180°, 180°]
628- coordinate [ 1 ] = ( ( ( coordinate [ 1 ] % 360 ) + 540 ) % 360 ) - 180 ;
629-
630- return [ coordinate [ 0 ] , coordinate [ 1 ] ] ;
631- }
632-
633643 /**
634644 * Returns a random IANA time zone relevant to this locale.
635645 *
0 commit comments