| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
|
|
2
|
|
|
|
|
|
|
# geometry of space: value range checks, normalisation and computing distance |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
package Graphics::Toolkit::Color::Space::Shape; |
|
5
|
34
|
|
|
34
|
|
406639
|
use v5.12; |
|
|
34
|
|
|
|
|
163
|
|
|
6
|
34
|
|
|
34
|
|
201
|
use warnings; |
|
|
34
|
|
|
|
|
71
|
|
|
|
34
|
|
|
|
|
2124
|
|
|
7
|
34
|
|
|
34
|
|
885
|
use Graphics::Toolkit::Color::Space::Basis; |
|
|
34
|
|
|
|
|
233
|
|
|
|
34
|
|
|
|
|
1386
|
|
|
8
|
34
|
|
|
34
|
|
180
|
use Graphics::Toolkit::Color::Space::Util qw/round_decimals is_nr/; |
|
|
34
|
|
|
|
|
66
|
|
|
|
34
|
|
|
|
|
126665
|
|
|
9
|
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
#### constructor ####################################################### |
|
11
|
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
sub new { |
|
13
|
316
|
|
|
316
|
0
|
23731
|
my $pkg = shift; |
|
14
|
316
|
|
|
|
|
1072
|
my ($basis, $type, $range, $precision) = @_; |
|
15
|
316
|
100
|
|
|
|
988
|
return unless ref $basis eq 'Graphics::Toolkit::Color::Space::Basis'; |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
# check axis type definition |
|
18
|
315
|
100
|
100
|
|
|
2427
|
if (not defined $type){ $type = [ (1) x $basis->axis_count ] } # set all axis as linear per default |
|
|
185
|
100
|
|
|
|
561
|
|
|
19
|
|
|
|
|
|
|
elsif (ref $type eq 'ARRAY' and @$type == $basis->axis_count ) { |
|
20
|
128
|
|
|
|
|
346
|
for my $i ($basis->axis_iterator) { |
|
21
|
382
|
|
|
|
|
598
|
my $atype = $type->[$i]; # type def of this axis |
|
22
|
382
|
50
|
|
|
|
774
|
return unless defined $atype; |
|
23
|
382
|
100
|
100
|
|
|
3097
|
if ($atype eq 'angular' or $atype eq 'circular' or $atype eq '0') { $type->[$i] = 0 } |
|
|
130
|
100
|
100
|
|
|
350
|
|
|
|
|
100
|
100
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
24
|
246
|
|
|
|
|
575
|
elsif ($atype eq 'linear' or $atype eq '1') { $type->[$i] = 1 } |
|
25
|
4
|
|
|
|
|
12
|
elsif ($atype eq 'no' or $atype eq '2') { $type->[$i] = 2 } |
|
26
|
2
|
|
|
|
|
17
|
else { return 'invalid axis type at element '.$i.'. It has to be "angular", "linear" or "no".' } |
|
27
|
|
|
|
|
|
|
} |
|
28
|
2
|
|
|
|
|
6
|
} else { return 'invalid axis type definition in color space '.$basis->space_name } |
|
29
|
|
|
|
|
|
|
|
|
30
|
311
|
|
|
|
|
3203
|
$range = check_range_definition( $basis, $range ); |
|
31
|
311
|
100
|
|
|
|
1041
|
return $range unless ref $range; |
|
32
|
303
|
|
|
|
|
769
|
$precision = check_precision_definition( $basis, $precision ); |
|
33
|
303
|
100
|
|
|
|
719
|
return $precision unless ref $precision; |
|
34
|
|
|
|
|
|
|
|
|
35
|
301
|
|
|
|
|
3318
|
bless { basis => $basis, type => $type, range => $range, precision => $precision, constraint => {} } |
|
36
|
|
|
|
|
|
|
} |
|
37
|
|
|
|
|
|
|
sub check_range_definition { # check if range def is valid and eval (expand) it |
|
38
|
1490
|
|
|
1490
|
0
|
2771
|
my ($basis, $range) = @_; |
|
39
|
1490
|
50
|
|
|
|
3781
|
$basis = $basis->{'basis'} if ref $basis eq __PACKAGE__; |
|
40
|
1490
|
|
|
|
|
2238
|
my $error_msg = 'Bad value range definition!'; |
|
41
|
1490
|
100
|
100
|
|
|
5829
|
$range = 1 if not defined $range or $range eq 'normal'; |
|
42
|
1490
|
100
|
|
|
|
3665
|
$range = 100 if $range eq 'percent'; |
|
43
|
1490
|
100
|
66
|
|
|
9184
|
return $error_msg." It has to be 'normal', 'percent', a number or ARRAY of numbers or ARRAY of ARRAY's with two number!" |
|
|
|
|
100
|
|
|
|
|
|
44
|
|
|
|
|
|
|
unless (not ref $range and is_nr( $range )) or (ref $range eq 'ARRAY') ; |
|
45
|
1489
|
100
|
|
|
|
4704
|
$range = [$range] unless ref $range; |
|
46
|
1489
|
100
|
|
|
|
4818
|
$range = [(@$range) x $basis->axis_count] if @$range == 1; |
|
47
|
1489
|
100
|
|
|
|
3809
|
return "Range definition needs inside an ARRAY either one definition for all axis or one definition". |
|
48
|
|
|
|
|
|
|
" for each axis!" if @$range != $basis->axis_count; |
|
49
|
1486
|
|
|
|
|
3364
|
for my $axis_index ($basis->axis_iterator) { |
|
50
|
4489
|
|
|
|
|
33797
|
my $axis_range = $range->[$axis_index]; |
|
51
|
4489
|
100
|
|
|
|
7684
|
if (not ref $axis_range){ |
|
|
|
50
|
|
|
|
|
|
|
52
|
4227
|
100
|
|
|
|
11034
|
if ($axis_range eq 'normal') {$range->[$axis_index] = [0, 1]} |
|
|
3
|
50
|
|
|
|
20
|
|
|
53
|
0
|
|
|
|
|
0
|
elsif ($axis_range eq 'percent') {$range->[$axis_index] = [0, 100]} |
|
54
|
4224
|
|
|
|
|
9725
|
else {$range->[$axis_index] = [0, $axis_range+0]} |
|
55
|
|
|
|
|
|
|
} elsif (ref $axis_range eq 'ARRAY') { |
|
56
|
262
|
100
|
|
|
|
587
|
return $error_msg.' Array at axis number '.$axis_index.' has to have two elements' unless @$axis_range == 2; |
|
57
|
260
|
50
|
|
|
|
2925
|
return $error_msg.' None numeric value at lower bound for axis number '.$axis_index unless is_nr( $axis_range->[0] ); |
|
58
|
260
|
100
|
|
|
|
692
|
return $error_msg.' None numeric value at upper bound for axis number '.$axis_index unless is_nr( $axis_range->[1] ); |
|
59
|
259
|
100
|
|
|
|
896
|
return $error_msg.' Lower bound (first value) is >= than upper bound at axis number '.$axis_index if $axis_range->[0] >= $axis_range->[1]; |
|
60
|
0
|
|
|
|
|
0
|
} else { return "Range definitin for axis $axis_index was not an two element ARRAY!" } |
|
61
|
|
|
|
|
|
|
} |
|
62
|
1482
|
|
|
|
|
3675
|
return $range; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
sub check_precision_definition { # check if precision def is valid and eval (exapand) it |
|
65
|
312
|
|
|
312
|
0
|
722
|
my ($basis, $precision) = @_; |
|
66
|
312
|
50
|
|
|
|
927
|
$basis = $basis->{'basis'} if ref $basis eq __PACKAGE__; |
|
67
|
312
|
100
|
|
|
|
753
|
$precision = -1 unless defined $precision; |
|
68
|
312
|
100
|
|
|
|
1023
|
$precision = [($precision) x $basis->axis_count] unless ref $precision; |
|
69
|
312
|
50
|
|
|
|
3144
|
return 'need an ARRAY as definition of axis value precision' unless ref $precision eq 'ARRAY'; |
|
70
|
312
|
100
|
|
|
|
5296
|
return 'definition of axis value precision has to have same lengths as basis' unless @$precision == $basis->axis_count; |
|
71
|
310
|
|
|
|
|
672
|
return $precision; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
sub add_constraint { |
|
74
|
0
|
|
|
0
|
0
|
0
|
my ($self, $name, $error_msg, $checker, $remedy) = @_; |
|
75
|
0
|
0
|
0
|
|
|
0
|
return unless defined $name and not exists $self->{'constraint'}{$name} |
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
76
|
|
|
|
|
|
|
and defined $error_msg and not ref $error_msg and length($error_msg) > 10 |
|
77
|
|
|
|
|
|
|
and ref $checker eq 'CODE' and ref $remedy eq 'CODE'; |
|
78
|
0
|
|
|
|
|
0
|
$self->{'constraint'}{$name} = {checker => $checker, remedy => $remedy, error => $error_msg}; |
|
79
|
|
|
|
|
|
|
} |
|
80
|
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
#### getter ############################################################ |
|
82
|
9917
|
|
|
9917
|
0
|
29419
|
sub basis { $_[0]{'basis'}} |
|
83
|
|
|
|
|
|
|
sub is_linear { # overall linear space ? |
|
84
|
3
|
|
|
3
|
0
|
13456
|
my ($self) = @_; |
|
85
|
3
|
100
|
|
|
|
37
|
map { return 0 if $self->{'type'}[$_] != 1 } $self->basis->axis_iterator; |
|
|
8
|
|
|
|
|
38
|
|
|
86
|
2
|
|
|
|
|
12
|
return 1; |
|
87
|
|
|
|
|
|
|
} |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
sub is_int_valued { # all ranges int valued ? |
|
90
|
3
|
|
|
3
|
0
|
14
|
my ($self) = @_; |
|
91
|
3
|
100
|
|
|
|
10
|
map { return 0 if $self->{'precision'}[$_] != 0 } $self->basis->axis_iterator; |
|
|
4
|
|
|
|
|
31
|
|
|
92
|
0
|
|
|
|
|
0
|
return 1; |
|
93
|
|
|
|
|
|
|
} |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub is_axis_numeric { |
|
96
|
13172
|
|
|
13172
|
0
|
20662
|
my ($self, $axis_nr) = @_; |
|
97
|
13172
|
100
|
66
|
|
|
41656
|
return 0 if not defined $axis_nr or not exists $self->{'type'}[$axis_nr]; |
|
98
|
13168
|
100
|
|
|
|
46810
|
$self->{'type'}[$axis_nr] == 2 ? 0 : 1; |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
} |
|
101
|
|
|
|
|
|
|
sub axis_value_max { # --> +value |
|
102
|
9
|
|
|
9
|
0
|
37
|
my ($self, $axis_nr, $range) = @_; |
|
103
|
9
|
|
|
|
|
37
|
$range = $self->try_check_range_definition( $range ); |
|
104
|
9
|
50
|
|
|
|
57
|
return undef unless ref $range; |
|
105
|
9
|
100
|
|
|
|
40
|
return undef unless $self->is_axis_numeric($axis_nr); |
|
106
|
8
|
|
|
|
|
53
|
return $range->[$axis_nr][1]; |
|
107
|
|
|
|
|
|
|
} |
|
108
|
|
|
|
|
|
|
sub axis_value_min { # --> +value |
|
109
|
4
|
|
|
4
|
0
|
15
|
my ($self, $axis_nr, $range) = @_; |
|
110
|
4
|
|
|
|
|
10
|
$range = $self->try_check_range_definition( $range ); |
|
111
|
4
|
50
|
|
|
|
14
|
return undef unless ref $range; |
|
112
|
4
|
100
|
|
|
|
10
|
return undef unless $self->is_axis_numeric($axis_nr); |
|
113
|
3
|
|
|
|
|
19
|
return $range->[$axis_nr][0]; |
|
114
|
|
|
|
|
|
|
} |
|
115
|
|
|
|
|
|
|
sub axis_value_precision { # --> +precision? |
|
116
|
16
|
|
|
16
|
0
|
9142
|
my ($self, $axis_nr, $precision) = @_; |
|
117
|
16
|
50
|
33
|
|
|
116
|
return undef if not defined $axis_nr or not exists $self->{'type'}[$axis_nr]; |
|
118
|
16
|
100
|
|
|
|
50
|
return undef unless $self->is_axis_numeric($axis_nr); |
|
119
|
15
|
|
33
|
|
|
80
|
$precision //= $self->{'precision'}; |
|
120
|
15
|
50
|
33
|
|
|
71
|
return undef unless ref $precision eq 'ARRAY' and exists $precision->[$axis_nr]; |
|
121
|
15
|
|
|
|
|
113
|
$precision->[$axis_nr]; |
|
122
|
|
|
|
|
|
|
} |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
#### data checker ###################################################### |
|
125
|
|
|
|
|
|
|
sub try_check_range_definition { # check if range def is valid and eval (expand) it |
|
126
|
3578
|
|
|
3578
|
0
|
6407
|
my ($self, $range) = @_; |
|
127
|
3578
|
100
|
|
|
|
9193
|
return $self->{'range'} unless defined $range; |
|
128
|
1179
|
|
|
|
|
2682
|
return check_range_definition( $self->{'basis'}, $range ); |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
sub try_check_precision_definition { # check if range def is valid and eval (expand) it |
|
131
|
992
|
|
|
992
|
0
|
1727
|
my ($self, $precision) = @_; |
|
132
|
992
|
100
|
|
|
|
2552
|
return $self->{'precision'} unless defined $precision; |
|
133
|
9
|
|
|
|
|
42
|
return check_precision_definition( $self->{'basis'}, $precision ); |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
sub check_value_shape { # $vals -- $range, $precision --> $@vals | ~! |
|
137
|
220
|
|
|
220
|
0
|
547
|
my ($self, $values, $range, $precision) = @_; |
|
138
|
220
|
100
|
|
|
|
581
|
return 'color value tuple in '.$self->basis->space_name.' space needs to be ARRAY ref with '.$self->basis->axis_count.' elements' |
|
139
|
|
|
|
|
|
|
unless $self->basis->is_value_tuple( $values ); |
|
140
|
180
|
|
|
|
|
432
|
$range = $self->try_check_range_definition( $range ); |
|
141
|
180
|
50
|
|
|
|
423
|
return $range unless ref $range; |
|
142
|
180
|
|
|
|
|
363
|
$precision = $self->try_check_precision_definition( $precision ); |
|
143
|
180
|
50
|
|
|
|
405
|
return $precision unless ref $precision; |
|
144
|
180
|
|
|
|
|
326
|
my @names = $self->basis->long_axis_names; |
|
145
|
180
|
|
|
|
|
356
|
for my $axis_index ($self->basis->axis_iterator){ |
|
146
|
417
|
50
|
|
|
|
798
|
next unless $self->is_axis_numeric( $axis_index ); |
|
147
|
417
|
100
|
|
|
|
1514
|
return $names[$axis_index]." value is below minimum of ".$range->[$axis_index][0] |
|
148
|
|
|
|
|
|
|
if $values->[$axis_index] < $range->[$axis_index][0]; |
|
149
|
362
|
100
|
|
|
|
1277
|
return $names[$axis_index]." value is above maximum of ".$range->[$axis_index][1] |
|
150
|
|
|
|
|
|
|
if $values->[$axis_index] > $range->[$axis_index][1]; |
|
151
|
303
|
100
|
100
|
|
|
1017
|
return $names[$axis_index]." value is not properly rounded " |
|
152
|
|
|
|
|
|
|
if $precision->[$axis_index] >= 0 |
|
153
|
|
|
|
|
|
|
and round_decimals($values->[$axis_index], $precision->[$axis_index]) != $values->[$axis_index]; |
|
154
|
|
|
|
|
|
|
} |
|
155
|
47
|
|
|
|
|
94
|
for my $constraint (values %{$self->{'constraint'}}){ |
|
|
47
|
|
|
|
|
145
|
|
|
156
|
0
|
0
|
|
|
|
0
|
return $constraint->{'error'} unless $constraint->{'checker'}->( $values ); |
|
157
|
|
|
|
|
|
|
} |
|
158
|
47
|
|
|
|
|
404
|
return $values; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
sub is_in_linear_bounds { # :values --> ? |
|
162
|
349
|
|
|
349
|
0
|
649
|
my ($self, $values) = @_; |
|
163
|
349
|
100
|
|
|
|
678
|
return 0 unless $self->basis->is_number_tuple( $values ); |
|
164
|
346
|
|
|
|
|
727
|
for my $axis_nr ($self->basis->axis_iterator) { |
|
165
|
|
|
|
|
|
|
return 0 if $self->{'type'}[$axis_nr] == 1 |
|
166
|
|
|
|
|
|
|
and ( $values->[$axis_nr] < $self->{'range'}[$axis_nr][0] |
|
167
|
993
|
100
|
100
|
|
|
9076
|
or $values->[$axis_nr] > $self->{'range'}[$axis_nr][1] ); |
|
|
|
|
100
|
|
|
|
|
|
168
|
|
|
|
|
|
|
} |
|
169
|
286
|
|
|
|
|
434
|
for my $constraint (values %{$self->{'constraint'}}){ |
|
|
286
|
|
|
|
|
546
|
|
|
170
|
0
|
0
|
|
|
|
0
|
return 0 unless $constraint->{'checker'}->( $values ); |
|
171
|
|
|
|
|
|
|
} |
|
172
|
286
|
|
|
|
|
759
|
return 1; |
|
173
|
|
|
|
|
|
|
} |
|
174
|
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub is_equal { |
|
176
|
8
|
|
|
8
|
0
|
25
|
my ($self, $values_a, $values_b, $precision) = @_; |
|
177
|
8
|
100
|
100
|
|
|
24
|
return 0 unless $self->basis->is_value_tuple( $values_a ) and $self->basis->is_value_tuple( $values_b ); |
|
178
|
3
|
|
|
|
|
11
|
$precision = $self->try_check_precision_definition( $precision ); |
|
179
|
3
|
|
|
|
|
8
|
for my $axis_nr ($self->basis->axis_iterator) { |
|
180
|
9
|
50
|
|
|
|
26
|
return 0 if round_decimals($values_a->[$axis_nr], $precision->[$axis_nr]) |
|
181
|
|
|
|
|
|
|
!= round_decimals($values_b->[$axis_nr], $precision->[$axis_nr]); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
3
|
|
|
|
|
18
|
return 1; |
|
184
|
|
|
|
|
|
|
} |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
#### value shape ####################################################### |
|
187
|
|
|
|
|
|
|
sub clamp { # change values if outside of range to nearest boundary, angles get rotated into range |
|
188
|
1945
|
|
|
1945
|
0
|
22494
|
my ($self, $values, $range) = @_; |
|
189
|
1945
|
|
|
|
|
4576
|
$range = $self->try_check_range_definition( $range ); |
|
190
|
1945
|
50
|
|
|
|
4072
|
return $range unless ref $range; |
|
191
|
1945
|
50
|
|
|
|
4278
|
$values = [] unless ref $values eq 'ARRAY'; |
|
192
|
1945
|
|
|
|
|
4190
|
pop @$values while @$values > $self->basis->axis_count; |
|
193
|
1945
|
|
|
|
|
12074
|
for my $axis_nr ($self->basis->axis_iterator){ |
|
194
|
5861
|
50
|
|
|
|
11283
|
next unless $self->is_axis_numeric( $axis_nr ); # touch only numeric values |
|
195
|
5861
|
100
|
|
|
|
10985
|
if (not defined $values->[$axis_nr]){ |
|
196
|
29
|
|
|
|
|
47
|
my $default_value = 0; |
|
197
|
29
|
100
|
66
|
|
|
153
|
$default_value = $range->[$axis_nr][0] if $default_value < $range->[$axis_nr][0] |
|
198
|
|
|
|
|
|
|
or $default_value > $range->[$axis_nr][1]; |
|
199
|
29
|
|
|
|
|
57
|
$values->[$axis_nr] = $default_value; |
|
200
|
29
|
|
|
|
|
67
|
next; |
|
201
|
|
|
|
|
|
|
} |
|
202
|
5832
|
100
|
|
|
|
10217
|
if ($self->{'type'}[$axis_nr]){ |
|
203
|
5448
|
100
|
|
|
|
11945
|
$values->[$axis_nr] = $range->[$axis_nr][0] if $values->[$axis_nr] < $range->[$axis_nr][0]; |
|
204
|
5448
|
100
|
|
|
|
12333
|
$values->[$axis_nr] = $range->[$axis_nr][1] if $values->[$axis_nr] > $range->[$axis_nr][1]; |
|
205
|
|
|
|
|
|
|
} else { |
|
206
|
384
|
|
|
|
|
737
|
my $delta = $range->[$axis_nr][1] - $range->[$axis_nr][0]; |
|
207
|
384
|
|
|
|
|
1120
|
$values->[$axis_nr] += $delta while $values->[$axis_nr] < $range->[$axis_nr][0]; |
|
208
|
384
|
|
|
|
|
2096
|
$values->[$axis_nr] -= $delta while $values->[$axis_nr] > $range->[$axis_nr][1]; |
|
209
|
384
|
100
|
|
|
|
1008
|
$values->[$axis_nr] = $range->[$axis_nr][0] if $values->[$axis_nr] == $range->[$axis_nr][1]; |
|
210
|
|
|
|
|
|
|
} |
|
211
|
|
|
|
|
|
|
} |
|
212
|
1945
|
|
|
|
|
3014
|
for my $constraint (values %{$self->{'constraint'}}){ |
|
|
1945
|
|
|
|
|
4478
|
|
|
213
|
0
|
0
|
|
|
|
0
|
$values = $constraint->{'remedy'}->( $values ) unless $constraint->{'checker'}->( $values ); |
|
214
|
|
|
|
|
|
|
} |
|
215
|
1945
|
|
|
|
|
6137
|
return $values; |
|
216
|
|
|
|
|
|
|
} |
|
217
|
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub round { |
|
219
|
809
|
|
|
809
|
0
|
15595
|
my ($self, $values, $precision) = @_; |
|
220
|
809
|
50
|
|
|
|
1500
|
return unless $self->basis->is_value_tuple( $values ); |
|
221
|
809
|
|
|
|
|
2955
|
$precision = $self->try_check_precision_definition( $precision ); |
|
222
|
809
|
50
|
|
|
|
1694
|
return "round got bad precision definition" unless ref $precision; |
|
223
|
809
|
100
|
66
|
|
|
2217
|
[ map { ($self->is_axis_numeric( $_ ) and $precision->[$_] >= 0) ? round_decimals ($values->[$_], $precision->[$_]) : $values->[$_] } $self->basis->axis_iterator ]; |
|
|
2434
|
|
|
|
|
5412
|
|
|
224
|
|
|
|
|
|
|
} |
|
225
|
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
#### normalisation ##################################################### |
|
227
|
|
|
|
|
|
|
sub normalize { |
|
228
|
554
|
|
|
554
|
0
|
9330
|
my ($self, $values, $range) = @_; |
|
229
|
554
|
50
|
|
|
|
1217
|
return unless $self->basis->is_value_tuple( $values ); |
|
230
|
554
|
|
|
|
|
1432
|
$range = $self->try_check_range_definition( $range ); |
|
231
|
554
|
50
|
|
|
|
1393
|
return $range unless ref $range; |
|
232
|
554
|
50
|
|
|
|
1143
|
[ map { ($self->is_axis_numeric( $_ )) ? (($values->[$_] - $range->[$_][0]) / ($range->[$_][1]-$range->[$_][0])) |
|
|
1666
|
|
|
|
|
2966
|
|
|
233
|
|
|
|
|
|
|
: $values->[$_] } $self->basis->axis_iterator ]; |
|
234
|
|
|
|
|
|
|
} |
|
235
|
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
sub denormalize { |
|
237
|
849
|
|
|
849
|
0
|
14851
|
my ($self, $values, $range) = @_; |
|
238
|
849
|
50
|
|
|
|
1903
|
return unless $self->basis->is_value_tuple( $values ); |
|
239
|
849
|
|
|
|
|
2061
|
$range = $self->try_check_range_definition( $range ); |
|
240
|
849
|
50
|
|
|
|
1875
|
return $range unless ref $range; |
|
241
|
849
|
50
|
|
|
|
1669
|
return [ map { ($self->is_axis_numeric( $_ )) ? ($values->[$_] * ($range->[$_][1]-$range->[$_][0]) + $range->[$_][0]) |
|
|
2554
|
|
|
|
|
4693
|
|
|
242
|
|
|
|
|
|
|
: $values->[$_] } $self->basis->axis_iterator ]; |
|
243
|
|
|
|
|
|
|
} |
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
sub denormalize_delta { |
|
246
|
30
|
|
|
30
|
0
|
4261
|
my ($self, $delta_values, $range) = @_; |
|
247
|
30
|
50
|
|
|
|
65
|
return unless $self->basis->is_value_tuple( $delta_values ); |
|
248
|
30
|
|
|
|
|
85
|
$range = $self->try_check_range_definition( $range ); |
|
249
|
30
|
50
|
|
|
|
109
|
return $range unless ref $range; |
|
250
|
30
|
50
|
|
|
|
73
|
[ map { ($self->is_axis_numeric( $_ )) |
|
|
91
|
|
|
|
|
178
|
|
|
251
|
|
|
|
|
|
|
? ($delta_values->[$_] * ($range->[$_][1]-$range->[$_][0])) |
|
252
|
|
|
|
|
|
|
: $delta_values->[$_] } $self->basis->axis_iterator ]; |
|
253
|
|
|
|
|
|
|
} |
|
254
|
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
sub delta { # values have to be normalized |
|
256
|
43
|
|
|
43
|
0
|
10115
|
my ($self, $values1, $values2) = @_; |
|
257
|
43
|
100
|
100
|
|
|
142
|
return unless $self->basis->is_value_tuple( $values1 ) and $self->basis->is_value_tuple( $values2 ); |
|
258
|
|
|
|
|
|
|
# ignore none numeric dimensions |
|
259
|
37
|
50
|
|
|
|
104
|
my @delta = map { $self->is_axis_numeric($_) ? ($values2->[$_] - $values1->[$_]) : 0 } $self->basis->axis_iterator; |
|
|
112
|
|
|
|
|
262
|
|
|
260
|
37
|
100
|
|
|
|
102
|
[ map { $self->{'type'}[$_] ? $delta[$_] : # adapt to circular dimensions |
|
|
112
|
100
|
|
|
|
494
|
|
|
|
|
100
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
$delta[$_] < -0.5 ? ($delta[$_]+1) : |
|
262
|
|
|
|
|
|
|
$delta[$_] > 0.5 ? ($delta[$_]-1) : $delta[$_] } $self->basis->axis_iterator ]; |
|
263
|
|
|
|
|
|
|
} |
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
1; |