Guest User

Untitled

a guest
Jan 20th, 2019
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.18 KB | None | 0 0
  1. =cut
  2. correct_point_names_in_FBK_data.pl
  3.  
  4. Cleans raw field survey data in fieldbook (FBK) format by renaming all
  5. points according to their position to ease the reporting of deformation
  6. monitoring surveys.
  7.  
  8. This program solves the following problem:
  9. We've done a monitoring survey. We want to make sure that all the points
  10. are named correctly. Sometimes points are named incorrectly by the
  11. surveyor working in the field. This makes it more difficult to process
  12. the data and create the report. This program automatically renames every
  13. point based on its position. And it gives you in the summary a list of
  14. any points it could not match by coordinates, which it’s up to you to
  15. decide what to do with.
  16.  
  17. Data Formats:
  18.  
  19. In the FBK file, angles can be in either decimal degrees (default) or
  20. DMS (DDD.MMSS) format. You have to tell this program which format your
  21. data is in.
  22.  
  23. The coordinate database file must be a comma separated values file with
  24. this format: PointName, Northing, Easting, Height
  25.  
  26. Usage Syntax:
  27. perl correct_point_names_in_FBK_data.pl
  28. angle_format # Specify decimal or dms, (decimal is default)
  29. input_file_name
  30. coordinate_database_file_name # Current coordinates are best
  31. output_path
  32. output_file_name
  33. log_file_name
  34. summary_file_name
  35.  
  36. Usage Notes:
  37. full path must be given for:
  38. input_file_name
  39. coordinate_database_file_name
  40.  
  41. output_path applies to: output_file_name, log_file_name, summary_file_name
  42.  
  43. Usage Example:
  44.  
  45. perl correct_point_names_in_FBK_data.pl decimal "C:\temp\monitor1\1-RawDataConversion\Epoch10\RawDataFromTPSObsReport.txt" "C:\temp\monitor1\AllPointsCurrentCoordinates.csv" "C:\temp\monitor1\1-RawDataConversion\Epoch10" "point_names_corrected.fbk" "point_names_correction_log.txt" "point_names_correction_summary.txt"
  46.  
  47. =cut
  48.  
  49. use strict;
  50. use warnings;
  51.  
  52. my $huge = 9E99;
  53.  
  54. sub Deg2Rad
  55. {
  56. my $angle = shift;
  57. return $angle * 0.01745329251;
  58. }
  59.  
  60. sub sinD
  61. {
  62. my $angle = shift;
  63. return sin(Deg2Rad($angle));
  64. }
  65.  
  66. sub cosD
  67. {
  68. my $angle = shift;
  69. return cos(Deg2Rad($angle));
  70. }
  71.  
  72.  
  73. sub dms2deg
  74. {
  75. my $x = shift;
  76. my $d = int $x;
  77. my $f = $x - $d;
  78. my $m = int(100.0 * $f);
  79. if ($m == 99) {
  80. $m = 59;
  81. }
  82. my $s = 10000.0 * ($f - 0.01 * $m);
  83. if ($s >= 99.9) {
  84. $s = 0.0;
  85. $m++;
  86. }
  87. if ($m == 60) {
  88. $m = 0;
  89. $d++;
  90. }
  91. return $d + ($m + $s / 60.0) / 60.0;
  92. }
  93.  
  94. # settings / configuration
  95.  
  96. my $max_sd = 0.06; # Maximum allowable slope distance for matching points to reference coordinates
  97.  
  98. my $units = "m"; # m = metres
  99.  
  100. my $angle_format = $ARGV[0];
  101. my $input_file = $ARGV[1];
  102. my $coord_db_file = $ARGV[2];
  103. my $output_path = $ARGV[3];
  104. my $output_file = $ARGV[4];
  105. my $log_file = $ARGV[5];
  106. my $summary_file = $ARGV[6];
  107.  
  108. use constant
  109. {
  110. DECIMAL => 0,
  111. DMS => 1
  112. };
  113.  
  114. if (lc($angle_format) eq "dms")
  115. {
  116. $angle_format = DMS;
  117. }
  118. else
  119. {
  120. $angle_format = DECIMAL;
  121. }
  122.  
  123. sub fullpath
  124. {
  125. my $file = shift;
  126. return $output_path . "\\" . $file;
  127. }
  128.  
  129. $output_file = fullpath($output_file);
  130. $log_file = fullpath($log_file);
  131. $summary_file = fullpath($summary_file);
  132.  
  133. open my $handle, '<', $input_file;
  134. chomp(my @lines = <$handle>);
  135. close $handle;
  136.  
  137. open $handle, '<', $coord_db_file;
  138. chomp(my @coord_db_lines = <$handle>);
  139. close $handle;
  140.  
  141. open (LOGFILE, ">$log_file");
  142. open (SUMMARYFILE, ">$summary_file");
  143.  
  144. print SUMMARYFILE "Summary for the process of making sure that all the points are named correctly.\n";
  145.  
  146. print LOGFILE "Loading coordinates of points from database file \"$coord_db_file\"\n";
  147.  
  148. my %coords = (); #HoA
  149. foreach my $line (@coord_db_lines)
  150. {
  151. if (length($line) > 0)
  152. {
  153. if ($line =~ /^([\w\s\.]+),([0-9\.-]+),([0-9\.-]+),([0-9\.-]+)$/)
  154. {
  155. # Pt, N, E, H
  156. my $pt = $1;
  157. my $n = $2;
  158. my $e = $3;
  159. my $h = $4;
  160. if (!exists($coords{$pt}))
  161. {
  162. push @{ $coords{$pt} }, $n;
  163. push @{ $coords{$pt} }, $e;
  164. push @{ $coords{$pt} }, $h;
  165. print LOGFILE "Loaded $pt.\n";
  166. }
  167. else
  168. {
  169. print LOGFILE "Point $pt already seen, so ignoring input line:\n$line\n";
  170. }
  171. }
  172. }
  173. }
  174.  
  175. #system("pause");
  176.  
  177. my $stn_id;
  178. my $stn_n;
  179. my $stn_e;
  180. my $stn_h;
  181. my $stn_hi;
  182. my $ht = 0.0;
  183.  
  184. my $have_put_stn_line_in_summary = 0;
  185. my $stn_line = "";
  186.  
  187. print LOGFILE "Reading FBK input file \"$input_file\"\n";
  188. print LOGFILE "Traversing and checking coordinates relative to points in database.\n";
  189. open (FILEOUT, ">$output_file");
  190.  
  191. my $max_d = 0.0;
  192. my $max_pt;
  193.  
  194. my @summary_lines = ();
  195.  
  196. foreach my $line (@lines)
  197. {
  198. if (length($line) > 0)
  199. {
  200. if ($line eq "!Setup")
  201. {
  202. print FILEOUT "$line\n";
  203. }
  204. elsif ($line =~ /^NEZ "([\w\s\.]+)" ([0-9\.-]+ [0-9\.-]+ [0-9\.-]+)$/)
  205. {
  206. my $coords = $2;
  207. ($stn_n, $stn_e, $stn_h) = split / /, $coords;
  208. print FILEOUT "$line\n";
  209. }
  210. elsif ($line =~ /^STN "([\w\s\.]+)" ([0-9\.-]+)/)
  211. {
  212. $stn_id = $1;
  213. $stn_hi = $2;
  214. $stn_line = "New Station: $stn_id HI = $stn_hi NEH ($stn_n $stn_e $stn_h)";
  215. print LOGFILE "\n$stn_line\n";
  216. print FILEOUT "$line\n";
  217. print LOGFILE "Input Data Line, Given Point Name, Calculated Coordinates Northing, Easting, Height, >>> Closest Point By Coordinates, Slope Distance, Passed / Exceeded Allowable Coordinate Difference, Point Named Correctly, Renaming Point\n";
  218.  
  219. $have_put_stn_line_in_summary = 0;
  220. }
  221. elsif ($line =~ /^F([\w]+) VA "([\w\s\.]+)" ([0-9\.-]+) ([0-9\.-]+) ([0-9\.-]+)$/)
  222. {
  223. my $face = $1;
  224. my $pt_id = $2;
  225. my $hz = $3;
  226. my $sd = $4;
  227. my $za = $5;
  228. my $hz_; #for internal use only
  229. my $za_; #for internal use only
  230.  
  231. if ($angle_format == DECIMAL)
  232. {
  233. #angles are good
  234. $hz_ = $hz;
  235. $za_ = $za;
  236. }
  237. else
  238. {
  239. #convert angles from DMS into decimal
  240. $hz_ = dms2deg($hz);
  241. $za_ = dms2deg($za);
  242. }
  243.  
  244. my $hd = $sd * sinD($za_);
  245. my $dh = $sd * cosD($za_) + $stn_hi - $ht;
  246.  
  247. # traverse
  248. my $pt_n = $stn_n + $hd * cosD($hz_);
  249. my $pt_e = $stn_e + $hd * sinD($hz_);
  250. my $pt_h = $stn_h + $dh;
  251.  
  252.  
  253. my $rounded_coords = sprintf("%.3f, %.3f, %.3f", $pt_n, $pt_e, $pt_h);
  254. #print LOGFILE "Traversed to: $pt_id at NEH ($rounded_coords)\n";
  255. print LOGFILE "$line, $pt_id, $rounded_coords";
  256. =cut
  257. # lookup this point by name
  258. if ($coords{$pt_id})
  259. {
  260. my ($n, $e, $h) = $coords{$pt_id};
  261. my $dn = $pt_n - $n;
  262. my $de = $pt_e - $e;
  263. my $dh = $pt_h - $h;
  264. print "Differences from reference coordinates: NEH ($dn $de $dh)\n";
  265. }
  266. else
  267. {
  268. print "We do not have coordinates for this point number.\n";
  269. }
  270. =cut
  271. # find the closest point by coordinates
  272. my $min_d = $huge;
  273. my $min_hd = $huge;
  274. my $min_vdiff = $huge;
  275. my $min_pt;
  276. for my $pt ( keys %coords )
  277. {
  278. my @dbcoords = @{$coords{$pt}};
  279. my $n = $dbcoords[0];
  280. my $e = $dbcoords[1];
  281. my $h = $dbcoords[2];
  282. my $dn = $pt_n - $n;
  283. my $de = $pt_e - $e;
  284. my $dh = $pt_h - $h;
  285. my $dist_hd = sqrt($dn**2 + $de**2); # horizontal distance
  286. my $dist_3d = sqrt($dn**2 + $de**2 + $dh**2); # 3D slope distance
  287. if ($dist_3d < $min_d)
  288. {
  289. $min_d = $dist_3d;
  290. $min_pt = $pt;
  291.  
  292. $min_hd = $dist_hd;
  293. $min_vdiff = $dh;
  294. }
  295. }
  296. my $rounded = sprintf("%.3f", $min_d);
  297. #print LOGFILE "Closest point by coordinates: $min_pt, slope distance = $rounded\n";
  298. print LOGFILE ", >>> $min_pt, $rounded";
  299. if ($min_d > $max_sd)
  300. {
  301. #print LOGFILE "Distance exceeds maximum allowable slope distance for matching points to reference coordinates.\n";
  302. #print LOGFILE "Input data line:\n$line\n";
  303.  
  304. print LOGFILE ", Exceeded, ,\n";
  305.  
  306. print FILEOUT "$line\n";
  307.  
  308. if (!$have_put_stn_line_in_summary)
  309. {
  310. push @summary_lines, "\n$stn_line\n";
  311.  
  312. $have_put_stn_line_in_summary = 1;
  313. }
  314. push @summary_lines, "\n $line\n";
  315. my $rounded_hd = sprintf("%.3f", $min_hd);
  316. my $rounded_vdiff = sprintf("%.3f", $min_vdiff);
  317. push @summary_lines, " Closest point: $min_pt\n slope distance = $rounded\n horizontal dist = $rounded_hd\n vertical diff = $rounded_vdiff\n";
  318. }
  319. else
  320. {
  321. # track maximum allowed distance and which point was measured
  322. if ($min_d > $max_d)
  323. {
  324. $max_d = $min_d;
  325. $max_pt = $min_pt;
  326. }
  327.  
  328. if ($min_pt eq $pt_id)
  329. {
  330. #print LOGFILE "Point was named correctly.\n";
  331.  
  332. print LOGFILE ", Passed, Named Correctly,\n";
  333.  
  334. print FILEOUT "$line\n";
  335. }
  336. else
  337. {
  338. #print LOGFILE "Renaming point to $min_pt\n";
  339.  
  340. print LOGFILE ", Passed, , Renaming\n";
  341.  
  342. $pt_id = $min_pt;
  343. print FILEOUT "F$face VA \"$pt_id\" $hz $sd $za\n";
  344. }
  345. }
  346. }
  347. elsif ($line =~ /^PRISM ([0-9\.-]+)$/)
  348. {
  349. $ht = $1;
  350. print LOGFILE "New prism height " . $ht . "\n";
  351. print FILEOUT "$line\n";
  352. }
  353. }
  354. }
  355.  
  356. print SUMMARYFILE "\nEvery point that was coordinated within the tolerance of $max_sd $units has been renamed (unless it was already named correctly).\n";
  357.  
  358. my $rounded = sprintf("%.3f", $max_d);
  359. print SUMMARYFILE "\nThe maximum allowed slope distance within the tolerance was $rounded for point $max_pt\n";
  360.  
  361. print SUMMARYFILE "\nFor all measurements listed below, the slope distance from the closest point in the database exceeds the maximum allowable slope distance for matching points to reference coordinates. Therefore these points as measured are not recognized and it's up to you what you want to do with them.\n";
  362.  
  363. foreach my $line (@summary_lines)
  364. {
  365. print SUMMARYFILE $line;
  366. }
  367.  
  368. close (FILEOUT);
  369. close (LOGFILE);
  370. close (SUMMARYFILE);
  371. print "\nGenerated Summary file : \"$summary_file\"\n";
  372. print "\nGenerated Output file (FBK data with point names corrected) : \"$output_file\"\n";
  373. print "\nGenerated Log file : \"$log_file\"\n";
Add Comment
Please, Sign In to add comment