Rand Stats

Point

zef:elcaro

NAME

Point - Point class

SYNOPSIS

This is a simple immutable Point class for Raku. It's implementation is loosely based on Tuple but is restricted to only accepting 2 Real numbers: an x and a y.

Internally, the values are stored as native num's for speed, as well as allowing for decimal values, also useful when calculating the Euclidean distance (with the usual floating-point precision caveats).

Like Tuple, the Point is a value type, so Point objects will behave inside data structures such as Set.

use Point; # exports a 'point' sub

my $p = point(1,  1);
my $q = point(2, -3);

# addition between points returns a new point
say $p + $q;  # (3, -2)

# point values will behave inside a Set
say set($p, $p, $q);  # set((1, 1) (2, -3))

# maybe these subs will be included with the module in future?

sub cityblock-distance($p, $q = point(0, 0)) {
    abs($p.x + $q.x) + abs($p.y + $q.y)
}

sub euclidean-distance($p, $q = point(0, 0)) {
    (($p.x - $q.x)² + ($p.y - $q.y)²) ** 0.5
}

say cityblock-distance($p, $q);  # 5 
say euclidean-distance($p, $q);  # 4.123105625617661 

An addition (+) infix op is exported to support addition of points.

From Version 1.2.0, infix ops are also exported for

... as well as unary prefix negation.

Here's a simple Eclidean vector implementation using some of those features

use Point;

class Vec {
    has $.pos = point(0, 0);  # position
    has $.vel = point(0, 0);  # velocity
    has $.acc = point(0, 0);  # acceleration
    has $.mas = 1;            # mass

    # magnitude of velocity
    method speed() {
        (.x² + .y²).sqrt given $!vel;
    }

    method apply-force(Point $f) {
        $!acc += $f ÷ $!mas;
    }

    method update() {
        $!vel += $!acc;
        $!pos += $!vel;
        $!acc ×= 0;
    }
}

I stopped short of export multi's for other math functions (abs, floor, etc) but if there is a great crying out of need for these, I would consider it. In the meantime, implementing these multi's in your own code is easy enough.

CAVEATS

A Point object is not a List. It cannot be directly indexed into; just use the .x and .y methods. It will try to stay in item context most of the time. However if you want to (eg. to slip x and y to some external function) you can call .list (or any other method that indirectly calls .list) to get the Num values as a list, eg.

my @p = |$p;
say @p.raku;  # [1e0, 1e0]

LICENCE

The Artistic License 2.0

See LICENSE file in the repository for the full license text.