-
Notifications
You must be signed in to change notification settings - Fork 31
/
helpers.dart
182 lines (161 loc) · 5.02 KB
/
helpers.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
import 'dart:math';
enum Unit {
meters,
millimeters,
centimeters,
kilometers,
acres,
miles,
nauticalmiles,
inches,
yards,
feet,
radians,
degrees,
}
enum Grid {
point,
square,
hex,
triangle,
}
enum Corner {
nw,
ne,
se,
sw,
center,
centroid,
}
/// Whether to calculate the distance based on geodesic (spheroid) or
/// planar (flat) method.
enum DistanceGeometry {
/// Calculations will be made on a 2D plane, NOT taking into account the
/// earth curvature.
planar,
/// Calculate the distance with geodesic (spheroid) equations. It will take
/// into account the earth as a sphere.
geodesic,
}
/// Earth Radius used with the Harvesine formula and approximates using a spherical (non-ellipsoid) Earth.
const earthRadius = 6371008.8;
/// Unit of measurement factors using a spherical (non-ellipsoid) earth radius.
/// Keys are the name of the unit, values are the number of that unit in a single radian
const factors = <Unit, num>{
Unit.centimeters: earthRadius * 100,
Unit.degrees: earthRadius / 111325,
Unit.feet: earthRadius * 3.28084,
Unit.inches: earthRadius * 39.3701,
Unit.kilometers: earthRadius / 1000,
Unit.meters: earthRadius,
Unit.miles: earthRadius / 1609.344,
Unit.millimeters: earthRadius * 1000,
Unit.nauticalmiles: earthRadius / 1852,
Unit.radians: 1,
Unit.yards: earthRadius * 1.0936,
};
const unitsFactors = <Unit, num>{
Unit.centimeters: 100,
Unit.degrees: 1 / 111325,
Unit.feet: 3.28084,
Unit.inches: 39.370,
Unit.kilometers: 1 / 1000,
Unit.meters: 1,
Unit.miles: 1 / 1609.344,
Unit.millimeters: 1000,
Unit.nauticalmiles: 1 / 1852,
Unit.radians: 1 / earthRadius,
Unit.yards: 1 / 1.0936,
};
/// Area of measurement factors based on 1 square meter.
const areaFactors = <Unit, num>{
Unit.acres: 0.000247105,
Unit.centimeters: 10000,
Unit.feet: 10.763910417,
Unit.inches: 1550.003100006,
Unit.kilometers: 0.000001,
Unit.meters: 1,
Unit.miles: 3.86e-7,
Unit.millimeters: 1000000,
Unit.yards: 1.195990046,
};
/// Round number to precision
num round(num value, [num precision = 0]) {
if (!(precision >= 0)) {
throw Exception("precision must be a positive number");
}
num multiplier = pow(10, precision);
num result = (value * multiplier);
return result.round() / multiplier;
}
/// Convert a distance measurement (assuming a spherical Earth) from radians to a more friendly unit.
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num radiansToLength(num radians, [Unit unit = Unit.kilometers]) {
var factor = factors[unit];
if (factor == null) {
throw Exception("$unit units is invalid");
}
return radians * factor;
}
/// Convert a distance measurement (assuming a spherical Earth) from a real-world unit into radians
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num lengthToRadians(num distance, [Unit unit = Unit.kilometers]) {
num? factor = factors[unit];
if (factor == null) {
throw Exception("$unit units is invalid");
}
return distance / factor;
}
/// Convert a distance measurement (assuming a spherical Earth) from a real-world unit into degrees
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, centimeters, kilometres, feet
num lengthToDegrees(num distance, [Unit unit = Unit.kilometers]) {
return radiansToDegrees(lengthToRadians(distance, unit));
}
/// Converts any bearing angle from the north line direction (positive clockwise)
/// and returns an angle between 0-360 degrees (positive clockwise), 0 being the north line
num bearingToAzimuth(num bearing) {
num angle = bearing.remainder(360);
if (angle < 0) {
angle += 360;
}
return angle;
}
/// Converts an angle in radians to degrees
num radiansToDegrees(num radians) {
num degrees = radians.remainder(2 * pi);
return degrees * 180 / pi;
}
/// Converts an angle in degrees to radians
num degreesToRadians(num degrees) {
num radians = degrees.remainder(360);
return radians * pi / 180;
}
/// Converts a length to the requested unit.
/// Valid units: miles, nauticalmiles, inches, yards, meters, metres, kilometers, centimeters, feet
num convertLength(
num length, [
Unit originalUnit = Unit.kilometers,
Unit finalUnit = Unit.kilometers,
]) {
if (length < 0) {
throw Exception("length must be a positive number");
}
return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);
}
/// Converts a area to the requested unit.
/// Valid units: kilometers, kilometres, meters, metres, centimetres, millimeters, acres, miles, yards, feet, inches, hectares
num convertArea(num area,
[originalUnit = Unit.meters, finalUnit = Unit.kilometers]) {
if (area < 0) {
throw Exception("area must be a positive number");
}
num? startFactor = areaFactors[originalUnit];
if (startFactor == null) {
throw Exception("invalid original units");
}
num? finalFactor = areaFactors[finalUnit];
if (finalFactor == null) {
throw Exception("invalid final units");
}
return (area / startFactor) * finalFactor;
}