Extended geometry lib.

This commit is contained in:
Stephan Barth 2023-12-30 13:38:26 +01:00
parent 7049ec6a11
commit 3a10b36ab0
4 changed files with 101 additions and 10 deletions

View File

@ -0,0 +1,13 @@
package Manticore::Geometry::LineSegment;
use strict;
use warnings;
use Manticore::Geometry::Point;
sub new {
my ($pkg, $from, $to) = @_;
return bless {from => $from, to => $to}
}
1;

View File

@ -3,16 +3,37 @@ package Manticore::Geometry::Point;
use strict;
use warnings;
use Math::BigRat lib => 'GMP';
sub new {
my (undef, $x, $y) = @_;
return bless [$x,$y]
my ($pkg, $x, $y) = @_;
return bless {
orig=>[$x,$y],
x=>Math::BigRat->new($x),
y=>Math::BigRat->new($y),
}
}
sub x {
my $self = shift;
return $self->{x}
}
sub y {
my $self = shift;
return $self->{y}
}
# parse a string and return as vector
sub fromText {
my (undef,$text)=@_;
my ($pkg,$text)=@_;
if($text=~m#^([0-9\.]+),([0-9\.]+)$#) {
return bless [$1,$2]
my ($x, $y) = ($1, $2);
return bless {
orig=>$text,
x=>Math::BigRat->new($x),
y=>Math::BigRat->new($y),
}
} else {
return { error=> "Parse error: Not a vector" }
}
@ -21,7 +42,7 @@ sub fromText {
# difference between two points; returns a vector
sub diff {
my ($self, $other) = @_;
return Manticore::Geometry::Vector->new($other->[0]-$self->[0], $other->[1]-$self->[1]);
return Manticore::Geometry::Vector->new($other->{x}-$self->{x}, $other->{y}-$self->{y});
}
1;

View File

@ -3,6 +3,11 @@ package Manticore::Geometry::Polygon;
use strict;
use warnings;
use POSIX;
use Math::Trig;
use Manticore::Geometry::Vector;
# Data representation:
# List of {p=>polygon, v=>value}
# Each of these polygons shall be normalized, hence intersection free with itself
@ -13,5 +18,37 @@ sub new {
return bless $pts;
}
# Angle between 3 points A B C, that is between the line segments AB and BC
sub _threePointAngular {
my ($A, $B, $C) = @_;
my $AB = $B->diff($A);
my $BC = $C->diff($B);
#$_ = $_->asFloatVector($_) for $AB, $BC;
#my $cos = $AB->scalar($BC)/$AB->size()/$BC->size();
#my $phi = acos($cos);
#$phi -= 2*pi if $phi>pi;
#return $phi;
my $phi = $BC->angle() - $AB->angle();
$phi -= 2*pi if $phi>pi;
$phi += 2*pi if $phi<-pi;
return $phi
}
# Count of full circles done by the polygon, that is the
# Angular sum over all corners divided by 2pi;
# shall be 1 for normalized polygons
# computed as floats as we only need the precision of what multiple
# of 2pi it is
# the result is then rounded to the next integer number
sub fullCircles {
my $self = shift;
my $sum = 0;
for(0..$#$self) {
$sum += _threePointAngular(@{$self}[$_-2,$_-1,$_]);
}
my $ret = $sum/(2*pi);
floor($ret+0.5)
}
1;

View File

@ -4,26 +4,46 @@ use strict;
use warnings;
sub new {
my (undef, $x, $y) = @_;
return bless [$x,$y]
my ($pkg, $x, $y) = @_;
return bless {
x=>Math::BigRat->new($x),
y=>Math::BigRat->new($y),
orig => [$x, $y],
}
}
sub asFloatVector {
my $self = shift;
return $self unless ref $self->{x};
return bless {
x=>$self->{x}->numify(),
y=>$self->{y}->numify(),
orig=>$self->{orig},
}
}
sub angle {
my $self = shift;
$self = $self->asFloatVector();
return atan2($self->{y}, $self->{x})
}
# add point to a vector
sub add {
my ($self, $other) = @_;
return Manticore::Geometry::Point->new($other->[0]+$self->[0], $other->[1]+$self->[1]);
return Manticore::Geometry::Point->new($other->{x}+$self->{x}, $other->{y}+$self->{y});
}
# returns the size of a vector
sub size {
my $self = shift;
return sqrt($self->[0]*$self->[0]+$self->[1]*$self->[1])
return sqrt($self->{x}*$self->{x}+$self->{y}*$self->{y})
}
# scalarproduct with another vector
sub scalar {
my ($self, $other) = @_;
return $self->[0]*$other->[0] + $self->[1]*$other->[1];
return $self->{x}*$other->{x} + $self->{y}*$other->{y};
}
1;