Skip to content

A Physics::Measure abstraction layer providing Latitude, Longitude, Bearing , Position, Course and Buoy classes.

License

Notifications You must be signed in to change notification settings

librasteve/raku-Physics-Navigation

Repository files navigation

License: Artistic-2.0 raku-physics-navigation -> DH

raku Physics::Navigation

This module is an abstraction on 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 and 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 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

About

A Physics::Measure abstraction layer providing Latitude, Longitude, Bearing , Position, Course and Buoy classes.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published