txt: ## dist_zef-librasteve-Physics-Navigation.md
  [![](https://img.shields.io/badge/License-Artistic%202.0-0298c3.svg)](https://opensource.org/licenses/Artistic-2.0)
  [![](https://github.com/librasteve/raku-Physics-Navigation/actions/workflows/navigation-weekly.yaml/badge.svg)](https://github.com/librasteve/raku-Physics-Navigation/actions/workflows/navigation-weekly.yaml)
  
  # raku Physics::Navigation
  
  This module is an abstraction on [Physics::Measure](https://github.com/librasteve/raku-Physics-Measure) that provides Latitude, Longitude, Bearing, Position, Course and Buoy classes.
  
  Provides Measure objects that have value, units and error and can be used in many common physics calculations. Uses [Physics::Unit](https://github.com/librasteve/raku-Physics-Unit) and [Physics::Error](https://github.com/librasteve/raku-Physics-Error).
  
  # Instructions
  
  `zef --verbose install Physics::Navigation`
  
  and, conversely, `zef uninstall Physics::Navigation`
  
  **For a gentler introduction to and explanation of these features, please refer to [raku Yacht Navigation](https://github.com/librasteve/raku-Yacht-Navigation) for a descriptive Jupyter notebook**
  
  # Synopsis
  
  ```
  use lib '../lib';
  use Physics::Navigation;
  use Physics::Measure;
  
  # objects can be set up longhand as in Physics::Measure, now joined by Latitude, Longitude, etc.
  $Physics::Measure::round-val = 0.1;
  
  my Distance $d1   .=new( value => 42,  units => 'nmile' );	  say ~$d1;
  my Time     $t1   .=new( value => 1.5, units => 'hr' );		  say ~$t1;
  my Latitude $lat1 .=new( value => 45, compass => <N> );		  say ~$lat1;
  
  # the emoji ♓️ <pisces> operator shorthand does all that the Physics::Measure emoji ♎️ <libra> operator does
  my $d2 = ♓️'42 nmile';						  say ~$d2;
  my $t2 = ♓️'1.5 hr';						  say ~$t2;
  my $s2 = $d2 / $t2;						  say ~$s2.in('knots');
  
  # and then some - parses final NEWS letter to determine lat or long
  my $lat2 = ♓️<43°30′30″S>;				          say ~$lat2;
  my $long1 = ♓️<45°W>;						  say ~$long1;
  my $long2 = ♓️<22°E>;						  say ~$long2;
  
  # the .in conversion method works and the identity 1° lat === 1 nautical mile is preserved
  my $lat3 = in-lat( $d1 );					  say ~$lat3;
  my $d3 = $lat2.in('nmiles');			                  say ~$d3;
  
  # you can do "Measure math" using the standard operators <[+-*/**]>
  my $d4 = $d3 * 2;						  say ~$d4;
  my $lat4 = $lat2 - $lat1;                                         say ~$lat4;
  
  # Bearings can be True(T) or Magnetic(M), with Variation and Deviation [Vw|Ve|Dw|De]
  $Physics::Navigation::variation =  ♓️<7°Vw>;
  
  my $bear1 = ♓️<80°T>;                                             say ~$bear1;
  my $bear2 = ♓️<43°30′30″M>;                                       say ~$bear2;
  my $bear3 = $bear2 + $bear1.M;                                    say ~$bear3;
  
  # here's how to steer your boat to Port (Pt) or Starboard (Sb)
  my $steer = ♓️<50°Pt>;                                            say ~$steer;
  my $bear4 = $bear2 + $steer;                                      say ~$bear4;
  my $bear5 = $bear4.back;                                          say ~$bear5; #and take a back bearing
  
  try {
  	my $bear-nope = $bear2 + $bear1;
  }
  if $! { say "Can't mix True & Magnetic ... $!" }
  
  my Position $start  .=new( $lat1, $long1 );	                  say ~$start;
  my Position $finish .=new( $lat2, $long2 );	                  say ~$finish;
  
  # get great circle distance and initial azimuth bearing
  say ~$start.haversine-dist($finish).in('km');
  say ~$start.forward-azimuth($finish);
  
  # make a Vector (angle + distance) and move by that amount
  my $vector  = $start.diff($finish);			         say ~$vector;
  my $finish2 = $start.move($vector);			         say ~$finish2;
  
  # use Measure math to make Velocity objects
  my $dur     = ♓️'3 weeks';			                 say ~$dur;
  my $vel     = $vector.divide: $dur;			         say ~$vel;
  my $vector2 = $vel.multiply: $dur;		                 say ~$vector2;
  
  my $pos-A = Position.new( ♓️<51.5072°N>, ♓️<0.1276°W> );
  my $pos-B = Position.new( ♓️<51.5072°N>, ♓️<0.1110°W> );
  my $pos-C = Position.new( ♓️<51.5072°N>, ♓️<0.1100°W> );
  
  # there are Fixes, Estimated positions and Transits
  my $fix-A = Fix.new( direction => ♓️<112°T>, location  => $pos-A );
  my $fix-B = Fix.new( direction => ♓️<25°T>,  location  => $pos-B );
  
  my $ep = Estimate.new( :$fix-A, :$fix-B );                      say ~$ep;
  
  my $tr = Transit.new( :$pos-A, :$pos-B );                       say $tr.aligned( $pos-C );
  
  # Course objects handle Course To Steer, Tidal Flow, Course Over Ground (and leeway)
  %course-info<leeway> =  ♓️<112°Pt>;
  my $tidal-flow = Velocity.new( θ => ♓️<112°T>, s => ♓️'2.2 knots' );
  my Course $course .= new( over-ground => ♓️<22°T>, :$tidal-flow );  say ~$course;
  say $course.speed-over-ground.in('knots');
  
  # Buoy objects know their shape, colour, light pattern, etc.
  my $scm = SouthCardinal.new( position => $pos-A );               say ~$scm;
  my $ncm = NorthCardinal.new( position => $pos-A );               say ~$ncm;
  
  # Lateral Buoys know about IALA standards
  $IALA = A;
  my $plm = PortLateral.new( position => $pos-B );                 say ~$plm;
  
  # use .light-defn to get an English description
  say $plm.light-defn;
  
  # .duration and .patterm methods also support SVG animation
  say "SVG-animation: duration is {$plm.light-svg.duration}s, pattern is: [{$plm.light-svg.pattern}];";
  
  ```
  
  # Summary
  
  The family of Physics::Navigation, Physics::Measure, Physics::Unit, Physics::Error and Physics::Constants raku modules is a consistent and extensible toolkit intended for science and education. It provides a comprehensive library of both metric (SI) and non-metric units, it is built on a Type Object foundation, it has a unit expression Grammar and implements math, conversion and comparison methods.
  
  # Contribution
  
  You are welcome to contribute in any way - please open a pull request.
  
  Any feedback is welcome to librasteve / via the github Issues above.
  
  Copyright (c) Henley Cloud Consulting Ltd. 2021-2023
  