line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Math::JSpline; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
28708
|
use 5.010001; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
29
|
|
4
|
1
|
|
|
1
|
|
6
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
34
|
|
5
|
1
|
|
|
1
|
|
4
|
use warnings; |
|
1
|
|
|
|
|
6
|
|
|
1
|
|
|
|
|
731
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require Exporter; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
# Items to export into callers namespace by default. Note: do not export |
12
|
|
|
|
|
|
|
# names by default without a very good reason. Use EXPORT_OK instead. |
13
|
|
|
|
|
|
|
# Do not simply export all your public functions/methods/constants. |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# This allows declaration use Math::JSpline ':all'; |
16
|
|
|
|
|
|
|
# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK |
17
|
|
|
|
|
|
|
# will save memory. |
18
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw( |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
) ] ); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our @EXPORT = qw( |
25
|
|
|
|
|
|
|
JSpline |
26
|
|
|
|
|
|
|
); |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# Do a J-Spline, with facility to handle ending points properly as well (or do loops too) |
33
|
|
|
|
|
|
|
sub JSpline { # link=0 (join), 1 (simple clamp), 2 (tangent clamp), or 3 (loop) |
34
|
0
|
|
|
0
|
0
|
|
my ($sl,$a,$b,$link,@pts)=@_; # sl usually ~ 5. a=b=1 for b-spline, a=b=0 for 4-point subdiv, etc |
35
|
0
|
|
|
|
|
|
my @ret; |
36
|
|
|
|
|
|
|
|
37
|
0
|
|
|
|
|
|
foreach my $px(@pts) { |
38
|
|
|
|
|
|
|
|
39
|
0
|
|
|
|
|
|
my(@x)=@{$px}; # Where the spline gets built |
|
0
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
|
41
|
0
|
|
|
|
|
|
my $k = 0; |
42
|
0
|
|
|
|
|
|
while ( $k++ < $sl ) { |
43
|
|
|
|
|
|
|
|
44
|
0
|
0
|
|
|
|
|
if($link==1) { # simple clamping 0Pn = 20Pn–1 – 0Pn–2 and 0Pn+1 = 20Pn–1 – 0Pn–3. |
|
|
0
|
|
|
|
|
|
45
|
0
|
|
|
|
|
|
push(@x,$x[$#x]*2-$x[$#x-1]); # 0P–1 = 20P0 – 0P1 and 0P–2 = 20P0 – 0P2. |
46
|
0
|
|
|
|
|
|
push(@x,$x[$#x-1]*2-$x[$#x-3]); |
47
|
0
|
|
|
|
|
|
my $px1=$x[0]*2-$x[1]; # 0Pn = 20Pn–1 – 0Pn–2 and 0Pn+1 = 20Pn–1 – 0Pn–3. |
48
|
0
|
|
|
|
|
|
my $px2=$x[0]*2-$x[2]; |
49
|
0
|
|
|
|
|
|
@x=($px2,$px1,@x); |
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
} elsif($link==2) { # tangent preservation 0P–1 = (9–s)/4 0P0 + (s–3)/2 0P1 + (1–s)/4 0P2 and 0P–2 = (12–s)/2 0P0 + (s–8) 0P1 + (6–s)/2 0P2 |
53
|
0
|
|
|
|
|
|
my $px1=(9-$a)/4 * $x[0] + ($a-3)/2 * $x[1] + (1-$a)/4 * $x[2]; |
54
|
0
|
|
|
|
|
|
my $px2=(12-$a)/2 * $x[0] + ($a-8) * $x[1] + (6-$a)/2 * $x[2]; |
55
|
0
|
|
|
|
|
|
@x=($px2,$px1,@x); |
56
|
0
|
|
|
|
|
|
$px1=(9-$a)/4 * $x[$#x] + ($a-3)/2 * $x[$#x-1] + (1-$a)/4 * $x[$#x-2]; |
57
|
0
|
|
|
|
|
|
$px2=(12-$a)/2 * $x[$#x] + ($a-8) * $x[$#x-1] + (6-$a)/2 * $x[$#x-2]; |
58
|
0
|
|
|
|
|
|
push @x,$px1; push @x,$px2; |
|
0
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
0
|
|
|
|
|
|
my $j = 0; my (@tx,$ptx); |
|
0
|
|
|
|
|
|
|
62
|
0
|
|
|
|
|
|
while ( $j <= $#x ) { |
63
|
0
|
0
|
0
|
|
|
|
last if(($j==$#x)&&($link!=3)); |
64
|
0
|
0
|
0
|
|
|
|
if (( $j == 0 ) && ($link!=3)){ # Anchor start of output line to the start point |
|
|
0
|
0
|
|
|
|
|
65
|
0
|
|
|
|
|
|
push( @tx, $x[$j] ); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
elsif(( $j + 1 <= $#x )||($link==3)) { # |
69
|
0
|
0
|
|
|
|
|
if($link==3) { |
70
|
0
|
|
|
|
|
|
$ptx = ( $a * $x[( $j - 1 )%($#x+1)] + ( 8 - 2 * $a ) * $x[$j] + $a * $x[( $j + 1 )%($#x+1)] ) / 8; |
71
|
|
|
|
|
|
|
} else { |
72
|
0
|
|
|
|
|
|
$ptx = ( $a * $x[ $j - 1 ] + ( 8 - 2 * $a ) * $x[$j] + $a * $x[ $j + 1 ] ) / 8; |
73
|
|
|
|
|
|
|
} |
74
|
0
|
|
|
|
|
|
push( @tx, $ptx ); |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
0
|
0
|
0
|
|
|
|
if (($link==3)||( $j + 2 <= $#x && $j > 0)) { |
|
|
|
0
|
|
|
|
|
78
|
0
|
|
|
|
|
|
my ( $ptx ); |
79
|
0
|
0
|
|
|
|
|
if($link==3) { |
80
|
0
|
|
|
|
|
|
$ptx = ( ( $b - 1 ) * $x[($j -1)%($#x+1)] + ( 9 - $b ) * $x[ $j ] + ( 9 - $b ) * $x[( $j + 1 )%($#x+1)] + ( $b - 1 ) * $x[( $j + 2 )%($#x+1)] ) / 16; |
81
|
|
|
|
|
|
|
} else { |
82
|
0
|
|
|
|
|
|
$ptx = ( ( $b - 1 ) * $x[$j -1] + ( 9 - $b ) * $x[ $j ] + ( 9 - $b ) * $x[ $j + 1 ] + ( $b - 1 ) * $x[ $j + 2 ] ) / 16; |
83
|
|
|
|
|
|
|
} |
84
|
0
|
|
|
|
|
|
push( @tx, $ptx ); |
85
|
|
|
|
|
|
|
} |
86
|
0
|
|
|
|
|
|
$j++; |
87
|
|
|
|
|
|
|
} |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
|
90
|
0
|
0
|
|
|
|
|
if($link==3) { |
|
|
0
|
|
|
|
|
|
91
|
|
|
|
|
|
|
# skip push |
92
|
|
|
|
|
|
|
} elsif($link>0) { |
93
|
0
|
|
|
|
|
|
@tx=@tx[3..$#tx-2]; |
94
|
|
|
|
|
|
|
} else { |
95
|
0
|
|
|
|
|
|
push( @tx, $x[$#x] ); |
96
|
|
|
|
|
|
|
} |
97
|
|
|
|
|
|
|
|
98
|
0
|
|
|
|
|
|
@x=@tx; |
99
|
|
|
|
|
|
|
} |
100
|
0
|
0
|
|
|
|
|
if($link==3) { |
101
|
0
|
|
|
|
|
|
push @x,$x[0]; #join end to start for drawing |
102
|
|
|
|
|
|
|
} |
103
|
0
|
|
|
|
|
|
push @ret,\@x; |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
|
return @ret; |
106
|
|
|
|
|
|
|
} # jsplinexyl |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# Preloaded methods go here. |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
1; |
112
|
|
|
|
|
|
|
__END__ |