00001 #include "bgeo_lvcs.h"
00002
00003
00004 #include <vcl_string.h>
00005 #include <vcl_cstring.h>
00006 #include <vsl/vsl_basic_xml_element.h>
00007 #include <vpgl/bgeo/bgeo_datum_conversion.h>
00008 #include <vpgl/bgeo/bgeo_earth_constants.h>
00009
00010 #define SMALL_STEP 1.0e-6 // assumed to be in radians
00011
00012 const char* bgeo_lvcs::cs_name_strings[] = { "wgs84", "nad27n", "wgs72"};
00013
00014 bgeo_lvcs::cs_names bgeo_lvcs::str_to_enum(const char* s)
00015 {
00016 for (int i=0; i < bgeo_lvcs::NumNames; i++)
00017 if (vcl_strcmp(s, bgeo_lvcs::cs_name_strings[i]) == 0)
00018 return (bgeo_lvcs::cs_names) i;
00019 return bgeo_lvcs::NumNames;
00020 }
00021
00022 void bgeo_lvcs::set_angle_conversions(AngUnits ang_unit, double& to_radians,
00023 double& to_degrees)
00024 {
00025 to_radians=1.0;
00026 to_degrees=1.0;
00027 if (ang_unit == DEG)
00028 to_radians = DEGREES_TO_RADIANS;
00029 else
00030 to_degrees = RADIANS_TO_DEGREES;
00031 }
00032
00033 void bgeo_lvcs::set_length_conversions(LenUnits len_unit, double& to_meters,
00034 double& to_feet)
00035 {
00036 to_meters = 1.0;
00037 to_feet = 1.0;
00038 if (len_unit == FEET)
00039 to_meters = FEET_TO_METERS;
00040 else
00041 to_feet = METERS_TO_FEET;
00042 }
00043
00044 bgeo_lvcs::bgeo_lvcs(const bgeo_lvcs& lvcs)
00045 : vbl_ref_count(),
00046 local_cs_name_(lvcs.local_cs_name_),
00047 localCSOriginLat_(lvcs.localCSOriginLat_),
00048 localCSOriginLon_(lvcs.localCSOriginLon_),
00049 localCSOriginElev_(lvcs.localCSOriginElev_),
00050 lat_scale_(lvcs.lat_scale_),
00051 lon_scale_(lvcs.lon_scale_),
00052 geo_angle_unit_(lvcs.geo_angle_unit_),
00053 localXYZUnit_(lvcs.localXYZUnit_),
00054 lox_(lvcs.lox_),
00055 loy_(lvcs.loy_),
00056 theta_(lvcs.theta_)
00057 {
00058 if (lat_scale_ == 0.0 || lon_scale_ == 0.0)
00059 this->compute_scale();
00060 }
00061
00062
00063 bgeo_lvcs& bgeo_lvcs::operator=(const bgeo_lvcs& lvcs)
00064 {
00065 local_cs_name_ = lvcs.local_cs_name_;
00066 localCSOriginLat_ = lvcs.localCSOriginLat_;
00067 localCSOriginLon_ = lvcs.localCSOriginLon_;
00068 localCSOriginElev_ = lvcs.localCSOriginElev_;
00069 lat_scale_ = lvcs.lat_scale_;
00070 lon_scale_ = lvcs.lon_scale_;
00071 geo_angle_unit_ = lvcs.geo_angle_unit_,
00072 localXYZUnit_ = lvcs.localXYZUnit_;
00073 lox_ = lvcs.lox_;
00074 loy_ = lvcs.loy_;
00075 theta_ = lvcs.theta_;
00076 if (lat_scale_ == 0.0 || lon_scale_ == 0.0)
00077 this->compute_scale();
00078 return *this;
00079 }
00080
00081 bgeo_lvcs::bgeo_lvcs(double orig_lat, double orig_lon, double orig_elev,
00082 cs_names cs_name,
00083 double lat_scale, double lon_scale,
00084 AngUnits ang_unit,
00085 LenUnits len_unit ,
00086 double lox,
00087 double loy,
00088 double theta)
00089 :local_cs_name_(cs_name),
00090 localCSOriginLat_(orig_lat),
00091 localCSOriginLon_(orig_lon),
00092 localCSOriginElev_(orig_elev),
00093 lat_scale_(lat_scale),
00094 lon_scale_(lon_scale),
00095 geo_angle_unit_(ang_unit),
00096 localXYZUnit_(len_unit),
00097 lox_(lox),
00098 loy_(loy),
00099 theta_(theta)
00100 {
00101 if (lat_scale_ == 0.0 || lon_scale_ == 0.0)
00102 this->compute_scale();
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112 bgeo_lvcs::bgeo_lvcs(double orig_lat, double orig_lon, double orig_elev,
00113 cs_names cs_name,
00114 AngUnits ang_unit,
00115 LenUnits len_unit)
00116 : local_cs_name_(cs_name),
00117 localCSOriginLat_(orig_lat), localCSOriginLon_(orig_lon),
00118 localCSOriginElev_(orig_elev),
00119 geo_angle_unit_(ang_unit), localXYZUnit_(len_unit), lox_(0), loy_(0), theta_(0)
00120 {
00121 lat_scale_ = 0;
00122 lon_scale_ = 0;
00123 this->compute_scale();
00124 }
00125
00126
00127
00128
00129
00130
00131
00132
00133 bgeo_lvcs::bgeo_lvcs(double lat_low, double lon_low,
00134 double lat_high, double lon_high,
00135 double elev,
00136 cs_names cs_name, AngUnits ang_unit, LenUnits elev_unit)
00137 : local_cs_name_(cs_name), localCSOriginElev_(elev),
00138 geo_angle_unit_(ang_unit), localXYZUnit_(elev_unit)
00139 {
00140 double average_lat = (lat_low + lat_high)/2.0;
00141 double average_lon = (lon_low + lon_high)/2.0;
00142 localCSOriginLat_ = average_lat;
00143 localCSOriginLon_ = average_lon;
00144 lat_scale_ = 0;
00145 lon_scale_ = 0;
00146 this->compute_scale();
00147 }
00148
00149 double bgeo_lvcs::radians_to_degrees(const double val)
00150 {
00151 return val*RADIANS_TO_DEGREES;
00152 }
00153
00154 void bgeo_lvcs::radians_to_degrees(double& x, double& y, double& z)
00155 {
00156 x = x * RADIANS_TO_DEGREES;
00157 y = y * RADIANS_TO_DEGREES;
00158 z = z * RADIANS_TO_DEGREES;
00159 }
00160
00161 void bgeo_lvcs::degrees_to_dms(double geoval, int& degrees, int& minutes, double& seconds)
00162 {
00163 double fmin = vcl_fabs(geoval - (int)geoval)*60.0;
00164 int isec = (int) ((fmin - (int)fmin)*60.0 + .5);
00165 int imin = (int) ((isec == 60) ? fmin+1 : fmin) ;
00166 int extra = (geoval>0) ? 1 : -1;
00167 degrees = (int) ( (imin == 60) ? geoval+extra : geoval);
00168 minutes = ( imin== 60 ? 0 : imin);
00169 seconds = (fmin - (int)fmin)*60.0;
00170 }
00171
00172
00173 void bgeo_lvcs::compute_scale()
00174 {
00175 double wgs84_phi, wgs84_lamda, wgs84_hgt;
00176 double grs80_x, grs80_y, grs80_z;
00177 double grs80_x1, grs80_y1, grs80_z1;
00178 double to_meters, to_feet, to_radians, to_degrees;
00179 this->set_angle_conversions(geo_angle_unit_, to_radians, to_degrees);
00180 this->set_length_conversions(localXYZUnit_, to_meters, to_feet);
00181
00182 switch (local_cs_name_)
00183 {
00184 case bgeo_lvcs::wgs84:
00185 wgs84_phi = localCSOriginLat_*to_radians;
00186 wgs84_lamda = localCSOriginLon_*to_radians;
00187 wgs84_hgt = localCSOriginElev_*to_meters;
00188 break;
00189
00190 case bgeo_lvcs::nad27n:
00191
00192 nad27n_to_wgs84(localCSOriginLat_*to_degrees,
00193 localCSOriginLon_*to_degrees,
00194 localCSOriginElev_*to_meters,
00195 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
00196 wgs84_phi *= to_radians;
00197 wgs84_lamda *= to_radians;
00198 break;
00199 case bgeo_lvcs::wgs72:
00200
00201 wgs72_to_wgs84(localCSOriginLat_*to_degrees,
00202 localCSOriginLon_*to_degrees,
00203 localCSOriginElev_*to_meters,
00204 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
00205 wgs84_phi *= to_radians;
00206 wgs84_lamda *= to_radians;
00207 break;
00208 case bgeo_lvcs::NumNames:
00209 break;
00210 default:
00211 break;
00212 }
00213
00214
00215
00216
00217 latlong_to_GRS(wgs84_phi, wgs84_lamda, wgs84_hgt,
00218 &grs80_x, &grs80_y, &grs80_z, GRS80_a, GRS80_b);
00219
00220 if (lat_scale_ == 0.0)
00221 {
00222 switch (local_cs_name_)
00223 {
00224 case bgeo_lvcs::nad27n:
00225
00226
00227 nad27n_to_wgs84(
00228 (localCSOriginLat_*to_radians+SMALL_STEP)*to_degrees,
00229 localCSOriginLon_*to_degrees,
00230 localCSOriginElev_*to_meters,
00231 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
00232 wgs84_phi *= to_radians;
00233 wgs84_lamda *= to_radians;
00234 break;
00235 case bgeo_lvcs::wgs84:
00236 wgs84_phi = localCSOriginLat_*to_radians + SMALL_STEP;
00237 wgs84_lamda = localCSOriginLon_*to_radians;
00238 wgs84_hgt = localCSOriginElev_*to_meters;
00239 break;
00240 case bgeo_lvcs::wgs72:
00241 break;
00242 case bgeo_lvcs::NumNames:
00243 break;
00244 default:
00245 break;
00246 }
00247
00248 latlong_to_GRS(wgs84_phi, wgs84_lamda, wgs84_hgt,
00249 &grs80_x1, &grs80_y1, &grs80_z1, GRS80_a, GRS80_b);
00250
00251 lat_scale_ = SMALL_STEP/vcl_sqrt((grs80_x - grs80_x1)*(grs80_x - grs80_x1) +
00252 (grs80_y - grs80_y1)*(grs80_y - grs80_y1) +
00253 (grs80_z - grs80_z1)*(grs80_z - grs80_z1));
00254
00255 }
00256
00257 if (lon_scale_ == 0.0)
00258 {
00259 switch (local_cs_name_)
00260 {
00261 case bgeo_lvcs::nad27n:
00262 nad27n_to_wgs84(localCSOriginLat_*to_degrees,
00263 (localCSOriginLon_*to_radians+SMALL_STEP)*to_degrees,
00264 localCSOriginElev_*to_meters,
00265 &wgs84_phi, &wgs84_lamda, &wgs84_hgt);
00266 wgs84_phi *= to_radians;
00267 wgs84_lamda *= to_radians;
00268 break;
00269 case bgeo_lvcs::wgs84:
00270 wgs84_phi = localCSOriginLat_*to_radians;
00271 wgs84_lamda = localCSOriginLon_*to_radians + SMALL_STEP;
00272 wgs84_hgt = localCSOriginElev_*to_meters;
00273 break;
00274 case bgeo_lvcs::wgs72:
00275 break;
00276 case bgeo_lvcs::NumNames:
00277 break;
00278 default:
00279 break;
00280 }
00281
00282 latlong_to_GRS(wgs84_phi, wgs84_lamda, wgs84_hgt,
00283 &grs80_x1, &grs80_y1, &grs80_z1, GRS80_a, GRS80_b);
00284
00285 lon_scale_ = SMALL_STEP/vcl_sqrt((grs80_x - grs80_x1)*(grs80_x - grs80_x1) +
00286 (grs80_y - grs80_y1)*(grs80_y - grs80_y1) +
00287 (grs80_z - grs80_z1)*(grs80_z - grs80_z1));
00288
00289 }
00290 }
00291
00292
00293
00294
00295
00296
00297
00298
00299 void bgeo_lvcs::local_to_global(const double pointin_x,
00300 const double pointin_y,
00301 const double pointin_z,
00302 cs_names global_cs_name,
00303 double& pointout_lon,
00304 double& pointout_lat,
00305 double& pointout_z,
00306 AngUnits output_ang_unit,
00307 LenUnits output_len_unit
00308 )
00309 {
00310 double local_to_meters, local_to_feet, local_to_radians, local_to_degrees;
00311 this->set_angle_conversions(geo_angle_unit_, local_to_radians,
00312 local_to_degrees);
00313 this->set_length_conversions(localXYZUnit_, local_to_meters, local_to_feet);
00314
00315 double local_lat, local_lon, local_elev;
00316 double global_lat, global_lon, global_elev;
00317
00318
00319 double aligned_x = pointin_x;
00320 double aligned_y = pointin_y;
00321 local_transform(aligned_x, aligned_y);
00322
00323
00324 local_lat =
00325 aligned_y*local_to_meters*lat_scale_ + localCSOriginLat_*local_to_radians;
00326
00327 local_lon =
00328 aligned_x*local_to_meters*lon_scale_ + localCSOriginLon_*local_to_radians;
00329
00330 local_elev = pointin_z*local_to_meters + localCSOriginElev_*local_to_meters;
00331
00332 local_lat *= RADIANS_TO_DEGREES;
00333 local_lon *= RADIANS_TO_DEGREES;
00334
00335
00336
00337 if (local_cs_name_ == global_cs_name)
00338 {
00339
00340 global_lat = local_lat;
00341 global_lon = local_lon;
00342 global_elev = local_elev;
00343 }
00344 else
00345 if (local_cs_name_ == bgeo_lvcs::nad27n)
00346 {
00347
00348 if (global_cs_name == bgeo_lvcs::wgs84)
00349 {
00350 nad27n_to_wgs84(local_lat,
00351 local_lon,
00352 local_elev,
00353 &global_lat, &global_lon, &global_elev);
00354 }
00355 else if (global_cs_name == bgeo_lvcs::wgs72)
00356 {
00357 nad27n_to_wgs72(local_lat, local_lon,
00358 local_elev,
00359 &global_lat, &global_lon, &global_elev);
00360 }
00361 else
00362 vcl_cout << "Error: Global CS " << bgeo_lvcs::cs_name_strings[global_cs_name]
00363 << " unrecognized." << '\n';
00364 }
00365 else if (local_cs_name_ == bgeo_lvcs::wgs72)
00366 {
00367
00368 if (global_cs_name == bgeo_lvcs::nad27n)
00369 {
00370 wgs72_to_nad27n(local_lat,
00371 local_lon,
00372 local_elev,
00373 &global_lat, &global_lon, &global_elev);
00374 }
00375 else if (global_cs_name == bgeo_lvcs::wgs84)
00376 {
00377 wgs72_to_wgs84(local_lat,
00378 local_lon,
00379 local_elev,
00380 &global_lat, &global_lon, &global_elev);
00381 }
00382 else
00383 vcl_cout << "Error: Global CS " << bgeo_lvcs::cs_name_strings[global_cs_name]
00384 << " unrecognized." << '\n';
00385 }
00386 else if (local_cs_name_ == bgeo_lvcs::wgs84)
00387 {
00388
00389 if (global_cs_name == bgeo_lvcs::nad27n)
00390 {
00391 wgs84_to_nad27n(local_lat,
00392 local_lon,
00393 local_elev,
00394 &global_lat, &global_lon, &global_elev);
00395 }
00396 else if (global_cs_name == bgeo_lvcs::wgs72)
00397 {
00398 wgs84_to_wgs72(local_lat,
00399 local_lon,
00400 local_elev,
00401 &global_lat, &global_lon, &global_elev);
00402 }
00403 else
00404 vcl_cout << "Error: Global CS " << bgeo_lvcs::cs_name_strings[global_cs_name]
00405 << " unrecognized." << '\n';
00406 }
00407 else
00408 vcl_cout << "Error: Local CS " << bgeo_lvcs::cs_name_strings[local_cs_name_]
00409 << " unrecognized." << '\n';
00410
00411
00412
00413 if (output_ang_unit==DEG)
00414 {
00415 pointout_lon = global_lon;
00416 pointout_lat = global_lat;
00417 }
00418 else
00419 {
00420 pointout_lon = global_lon*DEGREES_TO_RADIANS;
00421 pointout_lat = global_lat*DEGREES_TO_RADIANS;
00422 }
00423
00424 if (output_len_unit == METERS)
00425 pointout_z = global_elev;
00426 else
00427 pointout_z = global_elev*METERS_TO_FEET;
00428
00429 #ifdef LVCS_DEBUG
00430 vcl_cout << "Local " << bgeo_lvcs::cs_name_strings[local_cs_name_]
00431 << " [" << pointin_y << ", " << pointin_x << ", " << pointin_z
00432 << "] MAPS TO Global "
00433 << bgeo_lvcs::cs_name_strings[global_cs_name]
00434 << " [" << pointout_lat << ", " << pointout_lon << ", " << pointout_z << "]\n";
00435 #endif
00436 }
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446 void bgeo_lvcs::global_to_local(const double pointin_lon,
00447 const double pointin_lat,
00448 const double pointin_z,
00449 cs_names global_cs_name,
00450 double& pointout_x,
00451 double& pointout_lat,
00452 double& pointout_z,
00453 AngUnits input_ang_unit,
00454 LenUnits input_len_unit)
00455 {
00456 double local_to_meters, local_to_feet, local_to_radians, local_to_degrees;
00457 this->set_angle_conversions(geo_angle_unit_, local_to_radians,
00458 local_to_degrees);
00459 this->set_length_conversions(localXYZUnit_, local_to_meters, local_to_feet);
00460 double global_lat, global_lon, global_elev;
00461 double local_lat, local_lon, local_elev;
00462
00463 global_lat = pointin_lat;
00464 global_lon = pointin_lon;
00465 global_elev = pointin_z;
00466
00467
00468
00469 if (input_ang_unit==RADIANS)
00470 {
00471 global_lat *= RADIANS_TO_DEGREES;
00472 global_lon *= RADIANS_TO_DEGREES;
00473 }
00474
00475 if (input_len_unit==FEET)
00476 global_elev *= FEET_TO_METERS;
00477
00478
00479 if (global_cs_name == local_cs_name_)
00480 {
00481
00482 local_lat = global_lat;
00483 local_lon = global_lon;
00484 local_elev = global_elev;
00485 }
00486 else if (global_cs_name == bgeo_lvcs::nad27n)
00487 {
00488
00489 if (local_cs_name_ == bgeo_lvcs::wgs84)
00490 {
00491 nad27n_to_wgs84(global_lat, global_lon, global_elev,
00492 &local_lat, &local_lon, &local_elev);
00493 }
00494 else if (local_cs_name_ == bgeo_lvcs::wgs72)
00495 {
00496 nad27n_to_wgs72(global_lat, global_lon, global_elev,
00497 &local_lat, &local_lon, &local_elev);
00498 }
00499 else
00500 vcl_cout << "Error: Local CS " << bgeo_lvcs::cs_name_strings[local_cs_name_]
00501 << " unrecognized." << '\n';
00502 }
00503 else if (global_cs_name == bgeo_lvcs::wgs72)
00504 {
00505
00506 if (local_cs_name_ == bgeo_lvcs::nad27n)
00507 {
00508 wgs72_to_nad27n(global_lat, global_lon, global_elev,
00509 &local_lat, &local_lon, &local_elev);
00510 }
00511 else if (local_cs_name_ == bgeo_lvcs::wgs84)
00512 {
00513 wgs72_to_wgs84(global_lat, global_lon, global_elev,
00514 &local_lat, &local_lon, &local_elev);
00515 }
00516 else
00517 vcl_cout << "Error: Local CS " << bgeo_lvcs::cs_name_strings[local_cs_name_]
00518 << " unrecognized." << '\n';
00519 }
00520 else if (global_cs_name == bgeo_lvcs::wgs84)
00521 {
00522
00523 if (local_cs_name_ == bgeo_lvcs::nad27n)
00524 {
00525 wgs84_to_nad27n(global_lat, global_lon, global_elev,
00526 &local_lat, &local_lon, &local_elev);
00527 }
00528 else if (local_cs_name_ == bgeo_lvcs::wgs72)
00529 {
00530 wgs84_to_wgs72(global_lat, global_lon, global_elev,
00531 &local_lat, &local_lon, &local_elev);
00532 }
00533 else
00534 vcl_cout << "Error: Local CS " << bgeo_lvcs::cs_name_strings[local_cs_name_]
00535 << " unrecognized." << '\n';
00536 }
00537 else
00538 vcl_cout << "Error: Global CS " << bgeo_lvcs::cs_name_strings[global_cs_name]
00539 << " unrecognized." << '\n';
00540
00541
00542
00543
00544 pointout_lat =
00545 (local_lat*DEGREES_TO_RADIANS -
00546 localCSOriginLat_*local_to_radians)/lat_scale_;
00547 pointout_x =
00548 (local_lon*DEGREES_TO_RADIANS -
00549 localCSOriginLon_*local_to_radians)/lon_scale_;
00550
00551 pointout_z = local_elev - localCSOriginElev_*local_to_meters;
00552
00553 if (localXYZUnit_==FEET)
00554 {
00555 pointout_x *= METERS_TO_FEET;
00556 pointout_lat *= METERS_TO_FEET;
00557 pointout_z *= METERS_TO_FEET;
00558 }
00559
00560 inverse_local_transform(pointout_x,pointout_lat);
00561
00562 #ifdef LVCS_DEBUG
00563 vcl_cout << "Global " << bgeo_lvcs::cs_name_strings[global_cs_name]
00564 << " [" << pointin_lon << ", " << pointin_lat << ", " << pointin_z
00565 << "] MAPS TO Local "
00566 << bgeo_lvcs::cs_name_strings[local_cs_name_]
00567 << " [" << pointout_x << ", " << pointout_lat << ", " << pointout_z << "]\n";
00568 #endif
00569 }
00570
00571
00572
00573 void bgeo_lvcs::print(vcl_ostream& strm) const
00574 {
00575 vcl_string len_u = "meters", ang_u="degrees";
00576 if (localXYZUnit_ == FEET)
00577 len_u = "feet";
00578 if (geo_angle_unit_ == RADIANS)
00579 ang_u= "radians";
00580 strm << "lvcs [\n"
00581 << "coordinate system name : " << cs_name_strings[local_cs_name_] << '\n'
00582 << "angle unit " << ang_u << '\n'
00583 << "length unit " << len_u << '\n'
00584 << "local origin(lat, lon, elev) : (" << localCSOriginLat_ << ' '
00585 << localCSOriginLon_ << ' ' << localCSOriginElev_ << ")\n"
00586 << "scales(lat lon) : (" << lat_scale_ << ' ' << lon_scale_ << ")\n"
00587 << "local transform(lox loy theta) : (" << lox_ << ' ' << loy_
00588 << ' ' << theta_ << ")\n]\n";
00589 }
00590
00591
00592 void bgeo_lvcs::read(vcl_istream& strm)
00593 {
00594 vcl_string len_u = "meters", ang_u="degrees";
00595
00596 vcl_string local_cs_name_str;
00597 strm >> local_cs_name_str;
00598 if (local_cs_name_str.compare("wgs84") == 0)
00599 local_cs_name_ = wgs84;
00600 else if (local_cs_name_str.compare("nad27n") == 0)
00601 local_cs_name_ = nad27n;
00602 else if (local_cs_name_str.compare("wgs72") == 0)
00603 local_cs_name_ = wgs72;
00604 else
00605 vcl_cerr << "undefined local_cs_name\n";
00606
00607 strm >> ang_u >> len_u;
00608 if (ang_u.compare("feet") == 0)
00609 localXYZUnit_ = FEET;
00610 else if (ang_u.compare("meters") == 0)
00611 localXYZUnit_ = METERS;
00612 else
00613 vcl_cerr << "undefined localXYZUnit_\n";
00614
00615 if (len_u.compare("degrees") == 0)
00616 geo_angle_unit_ = DEG;
00617 else if (len_u.compare("radians") == 0)
00618 geo_angle_unit_ = RADIANS;
00619 else
00620 vcl_cerr << "undefined geo_angle_unit_\n";
00621
00622 strm >> localCSOriginLat_ >> localCSOriginLon_ >> localCSOriginElev_;
00623 strm >> lat_scale_ >> lon_scale_;
00624 strm >> lox_ >> loy_ >> theta_;
00625
00626 if (lat_scale_==0.0 && lon_scale_==0.0)
00627 this->compute_scale();
00628 }
00629
00630
00631
00632 void bgeo_lvcs::local_transform(double& x, double& y)
00633 {
00634 double theta=theta_;
00635 if (geo_angle_unit_ == DEG)
00636 theta=theta_*DEGREES_TO_RADIANS;
00637
00638
00639 double xo = x - lox_;
00640 double yo = y - loy_;
00641
00642
00643 double ct,st;
00644 if (vcl_fabs(theta) < 1e-5)
00645 {
00646 ct = 1.0;
00647 st = theta;
00648 }
00649 else
00650 {
00651 ct = vcl_cos(-theta);
00652 st = vcl_sin(-theta);
00653 }
00654 x = ct*xo + st*yo;
00655 y = -st*xo + ct*yo;
00656 }
00657
00658
00659
00660 void bgeo_lvcs::inverse_local_transform(double& x, double& y)
00661 {
00662 double theta=theta_;
00663 if (geo_angle_unit_ == DEG)
00664 theta=theta_*DEGREES_TO_RADIANS;
00665
00666
00667 double ct,st;
00668 if (vcl_fabs(theta) < 1e-5)
00669 {
00670 ct = 1.0;
00671 st = theta;
00672 }
00673 else
00674 {
00675 ct = vcl_cos(-theta);
00676 st = vcl_sin(-theta);
00677 }
00678 double xo = ct*x + st*y;
00679 double yo = -st*x + ct*y;
00680
00681
00682 x = xo + lox_;
00683 y = yo + loy_;
00684 }
00685
00686 vcl_ostream& operator << (vcl_ostream& os, const bgeo_lvcs& local_coord_sys)
00687 {
00688 local_coord_sys.print(os);
00689 return os;
00690 }
00691
00692 vcl_istream& operator >> (vcl_istream& is, bgeo_lvcs& local_coord_sys)
00693 {
00694 local_coord_sys.read(is);
00695 return is;
00696 }
00697
00698 bool bgeo_lvcs::operator==(bgeo_lvcs const& r) const
00699 {
00700 bool eq = true;
00701 eq = eq && (this->local_cs_name_ == r.local_cs_name_);
00702 eq = eq && (this->localCSOriginLat_ == r.localCSOriginLat_);
00703 eq = eq && (this->localCSOriginLon_ == r.localCSOriginLon_);
00704 eq = eq && (this->localCSOriginElev_ == r.localCSOriginElev_);
00705 eq = eq && (this->lat_scale_ == r.lat_scale_);
00706 eq = eq && (this->lon_scale_ == r.lon_scale_);
00707 eq = eq && (this->geo_angle_unit_ == r.geo_angle_unit_);
00708 eq = eq && (this->localXYZUnit_ == r.localXYZUnit_);
00709 eq = eq && (this->lox_ == r.lox_);
00710 eq = eq && (this->loy_ == r.loy_);
00711 eq = eq && (this->theta_ == r.theta_);
00712 return eq;
00713 }
00714
00715
00716
00717 void bgeo_lvcs::b_write(vsl_b_ostream &os) const
00718 {
00719 unsigned csn = static_cast<unsigned>(local_cs_name_);
00720 vsl_b_write(os, csn);
00721 vsl_b_write(os, localCSOriginLat_);
00722 vsl_b_write(os, localCSOriginLon_);
00723 vsl_b_write(os, localCSOriginElev_);
00724 vsl_b_write(os, lat_scale_);
00725 vsl_b_write(os, lon_scale_);
00726 unsigned gaunit = static_cast<unsigned>(geo_angle_unit_);
00727 vsl_b_write(os, gaunit);
00728 unsigned xyzunit = static_cast<unsigned>(localXYZUnit_);
00729 vsl_b_write(os, xyzunit);
00730 vsl_b_write(os, lox_);
00731 vsl_b_write(os, loy_);
00732 vsl_b_write(os, theta_);
00733 }
00734
00735
00736 void bgeo_lvcs::b_read(vsl_b_istream &is)
00737 {
00738 unsigned cs_name;
00739 vsl_b_read(is, cs_name);
00740 local_cs_name_ = static_cast<cs_names>(cs_name);
00741 vsl_b_read(is, localCSOriginLat_);
00742 vsl_b_read(is, localCSOriginLon_);
00743 vsl_b_read(is, localCSOriginElev_);
00744 vsl_b_read(is, lat_scale_);
00745 vsl_b_read(is, lon_scale_);
00746 unsigned gaunit;
00747 vsl_b_read(is, gaunit);
00748 geo_angle_unit_ = static_cast<AngUnits>(gaunit);
00749 unsigned lunit;
00750 vsl_b_read(is, lunit);
00751 localXYZUnit_ = static_cast<LenUnits>(lunit);
00752 vsl_b_read(is, lox_);
00753 vsl_b_read(is, loy_);
00754 vsl_b_read(is, theta_);
00755 }
00756
00757 void bgeo_lvcs::x_write(vcl_ostream &os, vcl_string element_name) const
00758 {
00759 vcl_string len_u = "meters", ang_u="degrees";
00760 if (localXYZUnit_ == FEET)
00761 len_u = "feet";
00762 if (geo_angle_unit_ == RADIANS)
00763 ang_u= "radians";
00764
00765 vsl_basic_xml_element xml_element(element_name);
00766 xml_element.add_attribute("cs_name", cs_name_strings[local_cs_name_]);
00767 xml_element.add_attribute("origin_lon", localCSOriginLon_);
00768 xml_element.add_attribute("origin_lat", localCSOriginLat_);
00769 xml_element.add_attribute("origin_elev", localCSOriginElev_);
00770 xml_element.add_attribute("lon_scale", lon_scale_);
00771 xml_element.add_attribute("lat_scale", lat_scale_);
00772 xml_element.add_attribute("local_XYZ_unit", len_u);
00773 xml_element.add_attribute("geo_angle_unit", ang_u);
00774 xml_element.add_attribute("local_origin_x", lox_);
00775 xml_element.add_attribute("local_origin_y", loy_);
00776 xml_element.add_attribute("theta", theta_);
00777 xml_element.x_write(os);
00778 }