$SVG::Estimate::Path::QuadraticBezier::VERSION
=
'1.02'
;
has
point
=> (
is
=>
'ro'
,
required
=> 1,
);
has
control
=> (
is
=>
'ro'
,
required
=> 1,
);
sub
BUILDARGS {
my
(
$class
,
@args
) =
@_
;
my
$args
=
@args
% 2 ?
$args
[0] : {
@args
};
if
(
$args
->{transformer}->has_transforms) {
$args
->{point} =
$args
->{transformer}->transform(
$args
->{point});
$args
->{control} =
$args
->{transformer}->transform(
$args
->{control});
}
$args
->{end_point} = clone
$args
->{point};
my
$start
=
$class
->this_point(
$args
, 0);
my
$end
=
$class
->this_point(
$args
, 1);
$args
->{min_x} = min
$args
->{start_point}->[0],
$args
->{control}->[0],
$args
->{point}->[0];
$args
->{max_x} = max
$args
->{start_point}->[0],
$args
->{control}->[0],
$args
->{point}->[0];
$args
->{min_y} = min
$args
->{start_point}->[1],
$args
->{control}->[1],
$args
->{point}->[1];
$args
->{max_y} = max
$args
->{start_point}->[1],
$args
->{control}->[1],
$args
->{point}->[1];
$args
->{shape_length} =
$class
->segment_length(
$args
, 0, 1,
$start
,
$end
, 1e-4, 7, 0);
$args
->{travel_length} = 0;
return
$args
;
}
sub
_calculate_length {
my
$class
=
shift
;
my
$args
=
shift
;
my
$start
=
$args
->{start_point};
my
$control
=
$args
->{control};
my
$end
=
$args
->{point};
my
$a_x
=
$start
->[0] - 2 *
$control
->[0] +
$end
->[0];
my
$a_y
=
$start
->[1] - 2 *
$control
->[1] +
$end
->[1];
my
$b_x
= 2 * (
$end
->[0] -
$start
->[0]);
my
$b_y
= 2 * (
$end
->[1] -
$start
->[1]);
my
$A
= 4 * (
$a_x
**2 +
$a_y
**2);
my
$B
= 4 * (
$a_x
*$b_x
+
$a_y
*$b_y
);
my
$C
=
$b_x
**2 +
$b_y
**2;
my
$SABC
= 2 *
sqrt
(
$A
+
$B
+
$C
);
my
$SA
=
sqrt
(
$A
);
my
$A32
= 2 *
$A
*
$SA
;
my
$SC
= 2
*sqrt
(
$C
);
my
$BA
=
$B
/
$SA
;
my
$length
= (
$A32
+
$SA
*$B
*(
$SABC
-
$SC
) + (4
*$C
*$A
-
$B
*$B
)
*log
( (2
*$SA
+
$BA
+
$SABC
)/(
$BA
+
$SC
) ) ) / (4*(
$A32
));
return
$length
;
}
sub
this_point {
my
$class
=
shift
;
my
$args
=
shift
;
my
$t
=
shift
;
return
[
$class
->_this_point(
$t
,
$args
->{start_point}->[0],
$args
->{control}->[0],
$args
->{point}->[0]),
$class
->_this_point(
$t
,
$args
->{start_point}->[1],
$args
->{control}->[1],
$args
->{point}->[1])
];
}
sub
_this_point {
shift
;
my
(
$t
,
$s
,
$c
,
$p
) =
@_
;
return
((1 -
$t
)**2 *
$s
)
+ (2*(1 -
$t
)
*$t
*$c
)
+ (
$t
**2 *
$p
)
;
}
1;