Rational geometry lib extended.
This commit is contained in:
parent
3a10b36ab0
commit
3f28e8738a
@ -10,4 +10,19 @@ sub new {
|
|||||||
return bless {from => $from, to => $to}
|
return bless {from => $from, to => $to}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# relative position of a point to a line segment AB
|
||||||
|
# that is two values, pd, such that
|
||||||
|
# p is 0 at A, p is 1 at B, p<0 pre A, p>1 post B
|
||||||
|
# d is distance to the line
|
||||||
|
sub relative {
|
||||||
|
my ($self, $pt) = @_;
|
||||||
|
my $ab = $self->{to}->diff($self->{from});
|
||||||
|
my $abr = $ab->rightRotate();
|
||||||
|
my $ap = $pt->diff($self->{from});
|
||||||
|
return [
|
||||||
|
$ab->scalar($ap)/$ab->sizeSq(),
|
||||||
|
$abr->scalar($ap),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@ -50,5 +50,8 @@ sub fullCircles {
|
|||||||
floor($ret+0.5)
|
floor($ret+0.5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# 2: inside, 1: on border, 0: outside
|
||||||
|
sub pointInside {
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
@ -34,6 +34,11 @@ sub add {
|
|||||||
return Manticore::Geometry::Point->new($other->{x}+$self->{x}, $other->{y}+$self->{y});
|
return Manticore::Geometry::Point->new($other->{x}+$self->{x}, $other->{y}+$self->{y});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# returns the square of the size of a vector
|
||||||
|
sub sizeSq {
|
||||||
|
my $self = shift;
|
||||||
|
return ($self->{x}*$self->{x}+$self->{y}*$self->{y})
|
||||||
|
}
|
||||||
# returns the size of a vector
|
# returns the size of a vector
|
||||||
sub size {
|
sub size {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
@ -46,4 +51,13 @@ sub scalar {
|
|||||||
return $self->{x}*$other->{x} + $self->{y}*$other->{y};
|
return $self->{x}*$other->{x} + $self->{y}*$other->{y};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# new vector, rotated by 90°
|
||||||
|
sub rightRotate {
|
||||||
|
my $self = shift;
|
||||||
|
return bless {
|
||||||
|
x => -$self->{y},
|
||||||
|
y => $self->{x},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|||||||
40
Manticore/Num.pm
Normal file
40
Manticore/Num.pm
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
package Manticore::Num;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
# otherwise conversion between strings and numbers is incompatible between scalar and BigFloat values
|
||||||
|
use POSIX;
|
||||||
|
setlocale(LC_NUMERIC, "C");
|
||||||
|
|
||||||
|
use Math::BigFloat;
|
||||||
|
use Math::BigRat;
|
||||||
|
|
||||||
|
my %_numify = (
|
||||||
|
'Math::BigRat' => sub {
|
||||||
|
# split apart for debugging of the LC_NUMERIC problem...
|
||||||
|
my $x = shift;
|
||||||
|
my $f = $x->as_float();
|
||||||
|
my $s = $f->bstr();
|
||||||
|
my $ret = 0 + $s;
|
||||||
|
#print "{{ $x -- $f -- $s -- $ret }}\n";
|
||||||
|
$ret },
|
||||||
|
'Math::BigFloat' => sub { my $x = shift; 0 + $x->bstr() },
|
||||||
|
);
|
||||||
|
|
||||||
|
sub numify {
|
||||||
|
my $x = shift;
|
||||||
|
my $refx = ref $x;
|
||||||
|
if($refx) {
|
||||||
|
if($_numify{$refx}) {
|
||||||
|
return $_numify{$refx}->($x)
|
||||||
|
} else {
|
||||||
|
die "Manticore::Num::numify: no handler for $refx found"
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1;
|
||||||
66
tests/lineRelative.pl
Executable file
66
tests/lineRelative.pl
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env perl
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Math::BigRat;
|
||||||
|
|
||||||
|
use Tk;
|
||||||
|
|
||||||
|
BEGIN { push @INC, '..' }
|
||||||
|
|
||||||
|
use Manticore::Geometry::LineSegment;
|
||||||
|
use Manticore::Geometry::Point;
|
||||||
|
use Manticore::Geometry::Vector;
|
||||||
|
use Manticore::Num;
|
||||||
|
|
||||||
|
my $main = MainWindow->new();
|
||||||
|
|
||||||
|
my $can = $main->Canvas(-width=>400, -height=>400, -background=>'#000000')->pack;
|
||||||
|
|
||||||
|
my $p = '';
|
||||||
|
my $q = '';
|
||||||
|
|
||||||
|
my $u = Manticore::Geometry::Point->new(10,10);
|
||||||
|
my $v = Manticore::Geometry::Point->new(20,20);
|
||||||
|
|
||||||
|
my $pt = Manticore::Geometry::Point->new(30,30);
|
||||||
|
|
||||||
|
$main->Label(-textvariable=>\$p)->pack;
|
||||||
|
$main->Label(-textvariable=>\$q)->pack;
|
||||||
|
|
||||||
|
$can->Tk::bind('<1>'=>[sub {
|
||||||
|
my (undef, $x, $y) = @_;
|
||||||
|
$u = Manticore::Geometry::Point->new($x, $y);
|
||||||
|
draw();
|
||||||
|
}, Ev('x'), Ev('y')]);
|
||||||
|
|
||||||
|
$can->Tk::bind('<3>'=>[sub {
|
||||||
|
my (undef, $x, $y) = @_;
|
||||||
|
$v = Manticore::Geometry::Point->new($x, $y);
|
||||||
|
draw();
|
||||||
|
}, Ev('x'), Ev('y')]);
|
||||||
|
|
||||||
|
|
||||||
|
$can->Tk::bind('<Motion>'=>[sub {
|
||||||
|
my (undef, $x, $y) = @_;
|
||||||
|
$pt = Manticore::Geometry::Point->new($x, $y);
|
||||||
|
draw();
|
||||||
|
}, Ev('x'), Ev('y')]);
|
||||||
|
|
||||||
|
sub draw {
|
||||||
|
$can->delete('all');
|
||||||
|
$can->createOval($v->x()-7, $v->y()-7, $v->x()+7, $v->y()+7, -width=>5, -fill=>'#00ffff');
|
||||||
|
$can->createLine($u->x(), $u->y(), $v->x(), $v->y(), -width=>5, -fill=>'#0000ff');
|
||||||
|
my $line = Manticore::Geometry::LineSegment->new($u, $v);
|
||||||
|
my $ret = $line->relative($pt);
|
||||||
|
my $pn = Manticore::Num::numify($ret->[0]);
|
||||||
|
my $qn = Manticore::Num::numify($ret->[1]);
|
||||||
|
#print "<< $pn $qn >>\n";
|
||||||
|
$p = "[[ ".($pn)." ]]";
|
||||||
|
$q = "[[ ".($qn)." ]]";
|
||||||
|
}
|
||||||
|
|
||||||
|
MainLoop;
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user