1/* 2 * dms - calculate in degrees, minutes, and seconds (based on deg) 3 * 4 * Copyright (C) 1999,2010,2021 David I. Bell and Landon Curt Noll 5 * 6 * Calc is open software; you can redistribute it and/or modify it under 7 * the terms of the version 2.1 of the GNU Lesser General Public License 8 * as published by the Free Software Foundation. 9 * 10 * Calc is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General 13 * Public License for more details. 14 * 15 * A copy of version 2.1 of the GNU Lesser General Public License is 16 * distributed with calc under the filename COPYING-LGPL. You should have 17 * received a copy with calc; if not, write to Free Software Foundation, Inc. 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 19 * 20 * Under source code control: 1990/02/15 01:50:33 21 * File existed as early as: before 1990 22 * 23 * Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/ 24 */ 25 26 27obj dms {deg, min, sec}; 28 29define dms(deg, min, sec) 30{ 31 local obj dms ans; /* return value */ 32 33 /* default missing args to 0 */ 34 if (isnull(sec)) { 35 sec = 0; 36 } 37 if (isnull(min)) { 38 min = 0; 39 } 40 41 /* load object */ 42 ans.deg = deg; 43 ans.min = min; 44 ans.sec = sec; 45 46 /* return properly formed object */ 47 ans = fixdms(ans); 48 return ans; 49} 50 51 52define dms_add(a, b) 53{ 54 local obj dms ans; /* return value */ 55 56 /* initialize value to 1st arg */ 57 if (istype(a, ans)) { 58 /* 1st arg is dms object, load it */ 59 ans.deg = a.deg; 60 ans.min = a.min; 61 ans.sec = a.sec; 62 } else { 63 /* 1st arg is not dms, assume scalar degrees */ 64 ans.deg = a; 65 ans.min = 0; 66 ans.sec = 0; 67 } 68 69 /* add value of 2nd arg */ 70 if (istype(b, ans)) { 71 /* 2nd arg is dms object, add it */ 72 ans.deg += b.deg; 73 ans.min += b.min; 74 ans.sec += b.sec; 75 } else { 76 /* 2nd arg is not dms, add scalar degrees */ 77 ans.deg += b; 78 } 79 80 /* return normalized result */ 81 ans = fixdms(ans); 82 return ans; 83} 84 85 86define dms_neg(a) 87{ 88 local obj dms ans; /* return value */ 89 90 /* negate argument */ 91 if (istype(a, ans)) { 92 /* 1st arg is dms object, load it */ 93 ans.deg = -a.deg; 94 ans.min = -a.min; 95 ans.sec = -a.sec; 96 } else { 97 /* 2nd arg is not dms, negate scalar degrees */ 98 ans.deg = -a; 99 ans.min = 0; 100 ans.sec = 0; 101 } 102 103 /* return normalized result */ 104 ans = fixdms(ans); 105 return ans; 106} 107 108 109define dms_sub(a, b) 110{ 111 local obj dms ans; /* return value */ 112 113 /* initialize value to 1st arg */ 114 if (istype(a, ans)) { 115 /* 1st arg is dms object, load it */ 116 ans.deg = a.deg; 117 ans.min = a.min; 118 ans.sec = a.sec; 119 } else { 120 /* 1st arg is not dms, assume scalar degrees */ 121 ans.deg = a; 122 ans.min = 0; 123 ans.sec = 0; 124 } 125 126 /* subtract value of 2nd arg */ 127 if (istype(b, ans)) { 128 /* 2nd arg is dms object, subtract it */ 129 ans.deg -= b.deg; 130 ans.min -= b.min; 131 ans.sec -= b.sec; 132 } else { 133 /* 2nd arg is not dms, subtract scalar degrees */ 134 ans.deg -= b; 135 } 136 137 /* return normalized result */ 138 ans = fixdms(ans); 139 return ans; 140} 141 142 143define dms_mul(a, b) 144{ 145 local obj dms ans; /* return value */ 146 147 /* dms object multiplication */ 148 if (istype(a, ans) && istype(b, ans)) { 149 ans.deg = dms_abs(a) * dms_abs(b); 150 ans.min = 0; 151 ans.sec = 0; 152 153 /* scalar multiplication */ 154 } else if (istype(a, ans)) { 155 ans.deg = a.deg * b; 156 ans.min = a.min * b; 157 ans.sec = a.sec * b; 158 } else { 159 ans.deg = b.deg * a; 160 ans.min = b.min * a; 161 ans.sec = b.sec * a; 162 } 163 164 /* return normalized result */ 165 ans = fixdms(ans); 166 return ans; 167} 168 169 170define dms_print(a) 171{ 172 local obj dms ans; /* temp object for dms type testing */ 173 174 /* firewall - arg must be a dms object */ 175 if (! istype(a, ans)) { 176 quit "dms_print called with non dms object"; 177 } 178 179 /* print in dms form */ 180 print a.deg : 'd' : a.min : 'm' : a.sec : 's' :; 181} 182 183 184define dms_abs(a) 185{ 186 local obj dms ans; /* temp object for dms type testing */ 187 local deg; /* return scalar value */ 188 189 /* firewall - just absolute value non dms objects */ 190 if (! istype(a, ans)) { 191 return abs(a); 192 } 193 194 /* compute degrees */ 195 deg = a.deg + a.min / 60 + a.sec / 3600; 196 197 /* return degrees */ 198 return deg; 199} 200 201 202define dms_norm(a) 203{ 204 local obj dms ans; /* temp object for dms type testing */ 205 local deg; /* degrees */ 206 207 /* firewall - arg must be a dms object */ 208 if (! istype(a, ans)) { 209 quit "dms_norm called with non dms object"; 210 } 211 212 /* square degrees (norm is the square of absolute value */ 213 deg = dms_abs(a); 214 215 /* return degrees */ 216 return deg*deg; 217} 218 219 220define dms_test(a) 221{ 222 local obj dms ans; /* temp value */ 223 224 /* firewall - arg must be a dms object */ 225 if (! istype(a, ans)) { 226 quit "dms_test called with non dms object"; 227 } 228 229 /* return false of non-zero */ 230 ans = fixdms(a); 231 if (ans.deg == 0 && ans.min == 0 && ans.sec == 0) { 232 /* false */ 233 return 0; 234 } 235 /* true */ 236 return 1; 237} 238 239 240define dms_int(a) 241{ 242 local obj dms ans; /* return value */ 243 244 /* firewall - arg must be a dms object */ 245 if (! istype(a, ans)) { 246 quit "dms_int called with non dms object"; 247 } 248 249 /* normalize the argument */ 250 ans = fixdms(a); 251 252 /* truncate to the nearest second */ 253 ans.sec = int(ans.sec); 254 255 /* return value to the nearest second */ 256 return ans; 257} 258 259 260define dms_frac(a) 261{ 262 local obj dms ans; /* return value */ 263 264 /* firewall - arg must be a dms object */ 265 if (! istype(a, ans)) { 266 quit "dms_frac called with non dms object"; 267 } 268 269 /* normalize the argument */ 270 ans = fixdms(a); 271 272 /* remove all but fractional seconds */ 273 ans.deg = 0; 274 ans.min = 0; 275 ans.sec = frac(ans.sec); 276 277 /* return value to the second fraction */ 278 return ans; 279} 280 281 282define dms_rel(a,b) 283{ 284 local abs_a, abs_b; /* scalars of the arguments */ 285 286 /* compute scalars of the arguments */ 287 abs_a = dms_abs(a); 288 abs_b = dms_abs(b); 289 290 /* return the comparison */ 291 return cmp(abs_a, abs_b); 292} 293 294 295define dms_cmp(a,b) 296{ 297 local abs_a, abs_b; /* scalars of the arguments */ 298 299 /* compute scalars of the arguments */ 300 abs_a = dms_abs(a); 301 abs_b = dms_abs(b); 302 303 /* return the equality comparison */ 304 return (abs_a == abs_b); 305} 306 307 308define dms_inc(a) 309{ 310 local obj dms ans; /* return value */ 311 312 /* increment a dms object */ 313 if (istype(a, ans)) { 314 ans = a; 315 ++ans.sec; 316 317 /* return normalized result */ 318 ans = fixdms(ans); 319 return ans; 320 } 321 322 /* increment a scalar */ 323 return a+1; 324} 325 326 327define dms_dec(a) 328{ 329 local obj dms ans; /* return value */ 330 331 /* decrement a dms object */ 332 if (istype(a, ans)) { 333 ans = a; 334 --ans.sec; 335 336 /* return normalized result */ 337 ans = fixdms(ans); 338 return ans; 339 } 340 341 /* decrement a scalar */ 342 return a-1; 343} 344 345 346define fixdms(a) 347{ 348 local obj dms ans; /* temp value */ 349 350 /* firewall */ 351 if (! istype(a, ans)) { 352 quit "attempt to fix a non dms object"; 353 } 354 355 /* use builtin d2dms function */ 356 d2dms(a.deg + a.min/60 + a.sec/3600, a.deg, a.min, a.sec),; 357 358 /* return normalized result */ 359 return a; 360} 361 362if (config("resource_debug") & 3) { 363 print "obj dms {deg, min, sec} defined"; 364} 365