our
$VERSION
=
'v1.0.3'
;
my
$RE_INT
=
'(?:(?:[-+]?)(?:[0123456789]+))'
;
sub
convertSubtype {
my
$fig
=
shift
;
my
$prefix
=
shift
;
my
$value
=
shift
;
my
$context
=
shift
;
my
$result
;
my
$temp
;
$value
=~ y/[A-Z]/[a-z]/;
if
(
$value
eq
"open"
) {
return
1;
}
if
(
$value
eq
"pie"
||
$value
eq
"pie-wedge"
||
$value
eq
"closed"
) {
return
2;
}
if
(!(
$value
=~ s/^\s*(
$RE_INT
)//)) {
croak(
"${prefix}: ${value}: error: expected open or pie"
);
}
if
(
$value
!= 1 &&
$value
!= 2) {
croak(
"${prefix}: ${value}: error: expected 1 or 2"
);
}
return
$value
;
}
sub
convertDirection {
my
$fig
=
shift
;
my
$prefix
=
shift
;
my
$value
=
shift
;
my
$context
=
shift
;
my
$result
;
my
$temp
;
$value
=~ y/[A-Z]/[a-z]/;
if
(
$value
eq
"clockwise"
||
$value
eq
"cw"
) {
return
0;
}
if
(
$value
eq
"counterclockwise"
||
$value
eq
"ccw"
) {
return
1;
}
if
(!(
$value
=~ s/^\s*(
$RE_INT
)//)) {
croak(
"${prefix}: ${value}: error: expected clockwise or "
.
"counterclockwise"
);
}
if
(
$value
!= 0 &&
$value
!= 1) {
croak(
"${prefix}: ${value}: error: expected 0 or 1"
);
}
return
$value
;
}
my
%ArcParameterTemplate
= (
positional
=> {
"."
=> [
"r"
],
".."
=> [
"r"
,
"angle"
],
"@"
=> [
"points"
],
},
named
=> [
\
%Graphics::Fig::Parameters::UnitsParameter
,
\
%Graphics::Fig::Parameters::PositionParameter
,
@Graphics::Fig::Parameters::ArrowParameters
,
\
%Graphics::Fig::Parameters::CapStyleParameter
,
\
%Graphics::Fig::Parameters::CenterParameter
,
\
%Graphics::Fig::Parameters::ColorParameter
,
\
%Graphics::Fig::Parameters::DepthParameter
,
@Graphics::Fig::Parameters::FillParameters
,
@Graphics::Fig::Parameters::LineParameters
,
\
%Graphics::Fig::Parameters::PointsParameter
,
\
%Graphics::Fig::Parameters::RotationParameter
,
{
name
=>
"subtype"
,
convert
=> \
&convertSubtype
,
default
=> 1
},
{
name
=>
"d"
,
aliases
=> [
"diameter"
],
convert
=> \
&Graphics::Fig::Parameters::convertLength
,
},
{
name
=>
"r"
,
aliases
=> [
"radius"
],
convert
=> \
&Graphics::Fig::Parameters::convertLength
,
},
{
name
=>
"direction"
,
convert
=> \
&convertDirection
,
},
{
name
=>
"controlAngle"
,
convert
=> \
&Graphics::Fig::Parameters::convertAngle
,
},
{
name
=>
"angle"
,
aliases
=> [
"Θ"
],
convert
=> \
&Graphics::Fig::Parameters::convertAngle
,
},
],
);
my
%ArctoParameterTemplate
= (
positional
=> {
".."
=> [
"distance"
,
"heading"
],
"..."
=> [
"distance"
,
"heading"
,
"angle"
],
"@"
=> [
"points"
],
},
named
=> [
\
%Graphics::Fig::Parameters::UnitsParameter
,
\
%Graphics::Fig::Parameters::PositionParameter
,
@Graphics::Fig::Parameters::ArrowParameters
,
\
%Graphics::Fig::Parameters::CapStyleParameter
,
\
%Graphics::Fig::Parameters::CenterParameter
,
\
%Graphics::Fig::Parameters::ColorParameter
,
\
%Graphics::Fig::Parameters::DepthParameter
,
@Graphics::Fig::Parameters::FillParameters
,
@Graphics::Fig::Parameters::LineParameters
,
\
%Graphics::Fig::Parameters::PointsParameter
,
{
name
=>
"distance"
,
convert
=> \
&Graphics::Fig::Parameters::convertLength
,
},
{
name
=>
"heading"
,
convert
=> \
&Graphics::Fig::Parameters::convertAngle
,
},
{
name
=>
"subtype"
,
convert
=> \
&convertSubtype
,
default
=> 1
},
{
name
=>
"direction"
,
convert
=> \
&convertDirection
,
},
{
name
=>
"controlAngle"
,
convert
=> \
&Graphics::Fig::Parameters::convertAngle
,
},
{
name
=>
"angle"
,
aliases
=> [
"Θ"
, ],
convert
=> \
&Graphics::Fig::Parameters::convertAngle
,
},
],
);
sub
normalizeAngle {
my
$angle
=
shift
;
my
$direction
=
shift
;
if
(
abs
(
$angle
) > pi) {
$angle
=
atan2
(
sin
(
$angle
),
cos
(
$angle
));
}
die
"arc: internal error 1"
unless
(
$angle
>= - pi &&
$angle
<= pi);
if
(
$direction
&&
$angle
< 0) {
$angle
+= 2 * pi;
}
elsif
(!
$direction
&&
$angle
> 0) {
$angle
-= 2 * pi;
}
return
$angle
;
}
sub
calcAngleParameters {
my
$parameters
=
shift
;
my
$angle
= ${
$parameters
}{
"angle"
};
my
$controlAngle
= ${
$parameters
}{
"controlAngle"
};
my
$direction
= ${
$parameters
}{
"direction"
};
if
(!
defined
(
$direction
)) {
if
(
defined
(
$angle
)) {
$direction
=
$angle
>= 0;
}
elsif
(
defined
(
$controlAngle
)) {
$direction
=
$controlAngle
>= 0;
}
else
{
$direction
= 1;
}
}
if
(
defined
(
$angle
)) {
$angle
=
&normalizeAngle
(
$angle
,
$direction
);
}
else
{
if
(
$direction
) {
$angle
= pi / 2;
}
else
{
$angle
= - pi / 2;
}
}
if
(
defined
(
$controlAngle
)) {
$controlAngle
=
&normalizeAngle
(
$controlAngle
,
$direction
);
if
(
abs
(
$controlAngle
) >=
abs
(
$angle
)) {
croak(
"arc: error: controlAngle is outside of arc"
);
}
}
else
{
$controlAngle
=
$angle
/ 2;
}
die
"arc: internal error 2"
if
$angle
*
$controlAngle
< 0;
die
"arc: internal error 3"
if
abs
(
$controlAngle
) >
abs
(
$angle
);
die
"arc: internal error 4"
if
$controlAngle
*
$angle
< 0;
return
(
$angle
,
$controlAngle
);
}
sub
calcAnglesFromPoints {
my
$points
=
shift
;
my
$x1
= ${
$points
}[0][0];
my
$y1
= ${
$points
}[0][1];
my
$x2
= ${
$points
}[1][0];
my
$y2
= ${
$points
}[1][1];
my
$x3
= ${
$points
}[2][0];
my
$y3
= ${
$points
}[2][1];
my
@M
= (
[
$x1
,
$y1
, 1, -(
$x1
*$x1
+
$y1
*$y1
) ],
[
$x2
,
$y2
, 1, -(
$x2
*$x2
+
$y2
*$y2
) ],
[
$x3
,
$y3
, 1, -(
$x3
*$x3
+
$y3
*$y3
) ],
);
my
$d
= Graphics::Fig::Matrix::reduce(\
@M
);
if
(
abs
(
$d
) < Graphics::Fig::Matrix::EPS) {
croak(
"arc: error: singular matrix"
);
}
my
$D
=
$M
[0][3];
my
$E
=
$M
[1][3];
my
$F
=
$M
[2][3];
my
$z
=
$x1
* (
$y2
-
$y3
) +
$x2
* (
$y3
-
$y1
) +
$x3
* (
$y1
-
$y2
);
my
$direction
= (
$z
< 0);
my
(
$x
,
$y
);
my
(
$r
,
$b
,
$xc
,
$yc
,
$dummy_rotation
) =
Graphics::Fig::Ellipse::generalToCanonical(1, 0, 1,
$D
,
$E
,
$F
);
die
"arc: internal error 6: $r != $b"
unless
$r
==
$b
;
my
$c
= (
$x1
-
$xc
) /
$r
;
my
$s
= -(
$y1
-
$yc
) /
$r
;
$x
=
$c
* (
$x2
-
$xc
) -
$s
* (
$y2
-
$yc
);
$y
=
$s
* (
$x2
-
$xc
) +
$c
* (
$y2
-
$yc
);
my
$controlAngle
=
&normalizeAngle
(
atan2
(-
$y
,
$x
),
$direction
);
$x
=
$c
* (
$x3
-
$xc
) -
$s
* (
$y3
-
$yc
);
$y
=
$s
* (
$x3
-
$xc
) +
$c
* (
$y3
-
$yc
);
my
$angle
=
&normalizeAngle
(
atan2
(-
$y
,
$x
),
$direction
);;
die
"arc: internal error 7"
if
abs
(
$controlAngle
) >
abs
(
$angle
);
die
"arc: internal error 8"
if
$controlAngle
*
$angle
< 0;
return
(
$angle
,
$controlAngle
);
}
sub
findPoint2 {
my
$self
=
shift
;
my
$point1
= ${
$self
}{
"point1"
};
my
$point3
= ${
$self
}{
"point3"
};
my
$angle
= ${
$self
}{
"angle"
};
my
$controlAngle
= ${
$self
}{
"controlAngle"
};
my
$x1
= ${
$point1
}[0];
my
$y1
= ${
$point1
}[1];
my
$x3
= ${
$point3
}[0];
my
$y3
= ${
$point3
}[1];
my
$half_cot
= cot(
$angle
/ 2) / 2;
my
$xc
=
$x1
+ (
$x3
-
$x1
) / 2 + (
$y3
-
$y1
) *
$half_cot
;
my
$yc
=
$y1
+ (
$y3
-
$y1
) / 2 - (
$x3
-
$x1
) *
$half_cot
;
my
$c
=
cos
(
$controlAngle
);
my
$s
=
sin
(
$controlAngle
);
my
$x
=
$x1
-
$xc
;
my
$y
=
$y1
-
$yc
;
my
$x2
=
$xc
+
$c
*
$x
+
$s
*
$y
;
my
$y2
=
$yc
+ -
$s
*
$x
+
$c
*
$y
;
return
([
$xc
,
$yc
], [
$x2
,
$y2
]);
}
sub
arc {
my
$proto
=
shift
;
my
$fig
=
shift
;
my
%parameters
;
my
$stack
= ${
$fig
}{
"stack"
};
my
$tos
= ${
$stack
}[$
eval
{
Graphics::Fig::Parameters::parse(
$fig
,
"arc"
,
\
%ArcParameterTemplate
,
${
$tos
}{
"options"
}, \
%parameters
,
@_
);
};
if
($@) {
$@ =~ s/ at [^\s]* line \d+\.\n//;
croak(
"$@"
);
}
my
$self
= {
subtype
=>
$parameters
{
"subtype"
},
lineStyle
=>
$parameters
{
"lineStyle"
},
lineThickness
=>
$parameters
{
"lineThickness"
},
penColor
=>
$parameters
{
"penColor"
},
fillColor
=>
$parameters
{
"fillColor"
},
depth
=>
$parameters
{
"depth"
},
areaFill
=>
$parameters
{
"areaFill"
},
styleVal
=>
$parameters
{
"styleVal"
},
capStyle
=>
$parameters
{
"capStyle"
},
point1
=>
undef
,
point3
=>
undef
,
angle
=>
undef
,
controlAngle
=>
undef
,
};
Graphics::Fig::Parameters::copyArrowParameters(
$self
, \
%parameters
);
my
$r
;
if
(
defined
(
$parameters
{
"r"
})) {
if
(
defined
(
$parameters
{
"d"
})) {
croak(
"arc: error: r and d cannot be given together"
);
}
$r
=
$parameters
{
"r"
};
}
elsif
(
defined
(
$parameters
{
"d"
})) {
$r
=
$parameters
{
"d"
} / 2.0;
}
my
$points
=
$parameters
{
"points"
};
if
(!
defined
(
$points
)) {
if
(!
defined
(
$r
)) {
croak(
"arc: error: r, d or points parameter required"
);
}
my
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
my
(
$xc
,
$yc
);
if
(
defined
(
$parameters
{
"center"
})) {
(
$xc
,
$yc
) = @{
$parameters
{
"center"
}};
}
else
{
(
$xc
,
$yc
) = @{
$parameters
{
"position"
}};
}
my
$rotation
;
if
(!
defined
(
$rotation
=
$parameters
{
"rotation"
})) {
$rotation
= 0;
}
${
$self
}{
"point1"
} = [
$xc
+
$r
*
cos
(
$rotation
),
$yc
+
$r
* -
sin
(
$rotation
) ];
${
$self
}{
"point3"
} = [
$xc
+
$r
*
cos
(
$rotation
+
$angle
),
$yc
+
$r
* -
sin
(
$rotation
+
$angle
) ];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
elsif
(
scalar
(@{
$points
}) == 1) {
my
(
$xc
,
$yc
,
$x3
,
$y3
);
if
(
defined
(
$parameters
{
"d"
})) {
croak(
"arc: error: d cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"r"
})) {
croak(
"arc: error: r cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"rotation"
})) {
croak(
"arc: error: radius required with point and rotation"
);
}
if
(
defined
(
$parameters
{
"center"
})) {
(
$xc
,
$yc
) = @{
$parameters
{
"center"
}};
}
else
{
(
$xc
,
$yc
) = @{
$parameters
{
"position"
}};
}
my
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
my
$x
= ${
$points
}[0][0] -
$xc
;
my
$y
= ${
$points
}[0][1] -
$yc
;
my
$c
=
cos
(
$angle
);
my
$s
=
sin
(
$angle
);
$x3
=
$xc
+
$c
*
$x
+
$s
*
$y
;
$y3
=
$yc
-
$s
*
$x
+
$c
*
$y
;
${
$self
}{
"point1"
} = ${
$points
}[0];
${
$self
}{
"point3"
} = [
$x3
,
$y3
];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
elsif
(
scalar
(@{
$points
}) == 2) {
if
(
defined
(
$parameters
{
"d"
})) {
croak(
"arc: error: d cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"r"
})) {
croak(
"arc: error: r cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"center"
})) {
croak(
"arc: error: center cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"rotation"
})) {
croak(
"arc: error: rotation cannot be given with two points"
);
}
my
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
${
$self
}{
"point1"
} = ${
$points
}[0];
${
$self
}{
"point3"
} = ${
$points
}[1];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
elsif
(
scalar
(@{
$points
}) == 3) {
if
(
defined
(
$parameters
{
"d"
})) {
croak(
"arc: error: d cannot be given with three points"
);
}
if
(
defined
(
$parameters
{
"r"
})) {
croak(
"arc: error: r cannot be given with three points"
);
}
if
(
defined
(
$parameters
{
"direction"
})) {
croak(
"arc: error: direction cannot be given with three points"
);
}
if
(
defined
(
$parameters
{
"controlAngle"
})) {
croak(
"arc: error: controlAngle cannot be given with three points"
);
}
if
(
defined
(
$parameters
{
"angle"
})) {
croak(
"arc: error: angle cannot be given with three points"
);
}
my
(
$angle
,
$controlAngle
) =
&calcAnglesFromPoints
(
$points
);
${
$self
}{
"point1"
} = ${
$points
}[0];
${
$self
}{
"point3"
} = ${
$points
}[2];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
else
{
croak(
"arc: error: expected between zero and three points"
);
}
my
$class
=
ref
(
$proto
) ||
$proto
;
bless
(
$self
,
$class
);
push
(@{${
$tos
}{
"objects"
}},
$self
);
return
$self
;
}
sub
arcto {
my
$proto
=
shift
;
my
$fig
=
shift
;
my
%parameters
;
my
$stack
= ${
$fig
}{
"stack"
};
my
$tos
= ${
$stack
}[$
eval
{
Graphics::Fig::Parameters::parse(
$fig
,
"arcto"
,
\
%ArctoParameterTemplate
,
${
$tos
}{
"options"
}, \
%parameters
,
@_
);
};
if
($@) {
$@ =~ s/ at [^\s]* line \d+\.\n//;
croak(
"$@"
);
}
my
$self
= {
subtype
=>
$parameters
{
"subtype"
},
lineStyle
=>
$parameters
{
"lineStyle"
},
lineThickness
=>
$parameters
{
"lineThickness"
},
penColor
=>
$parameters
{
"penColor"
},
fillColor
=>
$parameters
{
"fillColor"
},
depth
=>
$parameters
{
"depth"
},
areaFill
=>
$parameters
{
"areaFill"
},
styleVal
=>
$parameters
{
"styleVal"
},
capStyle
=>
$parameters
{
"capStyle"
},
point1
=>
undef
,
point3
=>
undef
,
angle
=>
undef
,
controlAngle
=>
undef
,
};
Graphics::Fig::Parameters::copyArrowParameters(
$self
, \
%parameters
);
my
$points
=
$parameters
{
"points"
};
if
(!
defined
(
$points
)) {
my
(
$x3
,
$y3
,
$angle
,
$controlAngle
);
if
(
defined
(
$parameters
{
"distance"
}) ||
defined
(
$parameters
{
"heading"
})) {
if
(
defined
(
$parameters
{
"center"
})) {
croak(
"arcto: error: center cannot be given with distance "
.
"and heading"
);
}
if
(!
defined
(
$parameters
{
"distance"
})) {
croak(
"arcto: error: distance must be given with heading"
);
}
if
(!
defined
(
$parameters
{
"heading"
})) {
croak(
"arcto: error: heading must be given with distance"
);
}
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
$x3
=
$parameters
{
"position"
}[0]
+
$parameters
{
"distance"
} *
cos
(
$parameters
{
"heading"
});
$y3
=
$parameters
{
"position"
}[1]
-
$parameters
{
"distance"
} *
sin
(
$parameters
{
"heading"
});
}
else
{
if
(!
defined
(
$parameters
{
"center"
})) {
croak(
"arcto: error: expected distance and heading, center "
.
"or points"
);
}
if
(
defined
(
$parameters
{
"distance"
})) {
croak(
"arcto: error: distance cannot be given with center"
);
}
if
(
defined
(
$parameters
{
"heading"
})) {
croak(
"arcto: error: heading cannot be given with center"
);
}
my
(
$xc
,
$yc
) = @{
$parameters
{
"center"
}};
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
my
$x
=
$parameters
{
"position"
}[0] -
$xc
;
my
$y
=
$parameters
{
"position"
}[1] -
$yc
;
my
$c
=
cos
(
$angle
);
my
$s
=
sin
(
$angle
);
$x3
=
$xc
+
$c
*
$x
+
$s
*
$y
;
$y3
=
$yc
-
$s
*
$x
+
$c
*
$y
;
}
${
$self
}{
"point1"
} =
$parameters
{
"position"
};
${
$self
}{
"point3"
} = [
$x3
,
$y3
];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
elsif
(
scalar
(@{
$points
} == 1)) {
if
(
defined
(
$parameters
{
"center"
})) {
croak(
"arcto: error: center cannot be given with points"
);
}
if
(
defined
(
$parameters
{
"distance"
})) {
croak(
"arcto: error: distance cannot be given with points"
);
}
if
(
defined
(
$parameters
{
"heading"
})) {
croak(
"arcto: error: heading cannot be given with points"
);
}
my
(
$angle
,
$controlAngle
) =
&calcAngleParameters
(\
%parameters
);
${
$self
}{
"point1"
} =
$parameters
{
"position"
};
${
$self
}{
"point3"
} =
$parameters
{
"points"
}[0];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
elsif
(
scalar
(@{
$points
} == 2)) {
if
(
defined
(
$parameters
{
"angle"
})) {
croak(
"arcto: error: angle cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"center"
})) {
croak(
"arcto: error: center cannot be given with points"
);
}
if
(
defined
(
$parameters
{
"controlAngle"
})) {
croak(
"arcto: error: controlAngle cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"direction"
})) {
croak(
"arcto: error: direction cannot be given with two points"
);
}
if
(
defined
(
$parameters
{
"distance"
})) {
croak(
"arcto: error: distance cannot be given with points"
);
}
if
(
defined
(
$parameters
{
"heading"
})) {
croak(
"arcto: error: heading cannot be given with points"
);
}
my
(
$angle
,
$controlAngle
) =
&calcAnglesFromPoints
([
$parameters
{
"position"
}, ${
$points
}[0], ${
$points
}[1] ]);
${
$self
}{
"point1"
} =
$parameters
{
"position"
};
${
$self
}{
"point3"
} = ${
$points
}[1];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
else
{
croak(
"arcto: error: expected point"
);
}
${
$tos
}{
"options"
}{
"position"
} = ${
$self
}{
"point3"
};
my
$class
=
ref
(
$proto
) ||
$proto
;
bless
(
$self
,
$class
);
push
(@{${
$tos
}{
"objects"
}},
$self
);
return
$self
;
}
sub
translate {
my
$self
=
shift
;
my
$parameters
=
shift
;
( ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} ) =
Graphics::Fig::Parameters::translatePoints(
$parameters
, ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} );
return
1;
}
sub
rotate {
my
$self
=
shift
;
my
$parameters
=
shift
;
my
$rotation
= ${
$parameters
}{
"rotation"
};
( ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} ) =
Graphics::Fig::Parameters::rotatePoints(
$parameters
, ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} );
return
1;
}
sub
scale {
my
$self
=
shift
;
my
$parameters
=
shift
;
my
$scale
= ${
$parameters
}{
"scale"
};
die
unless
defined
(
$scale
);
my
$u
= ${
$scale
}[0];
my
$v
= ${
$scale
}[1];
if
(
abs
(
$u
) ==
abs
(
$v
)) {
( ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} ) =
Graphics::Fig::Parameters::scalePoints(
$parameters
, ${
$self
}{
"point1"
}, ${
$self
}{
"point3"
} );
if
(
$u
*
$v
< 0) {
${
$self
}{
"angle"
} *= -1;
${
$self
}{
"controlAngle"
} *= -1;
}
}
else
{
my
$point1
= ${
$self
}{
"point1"
};
my
$point3
= ${
$self
}{
"point3"
};
my
(
$old_center
,
$point2
) =
&findPoint2
(
$self
);
my
@newPoints
= Graphics::Fig::Parameters::scalePoints(
$parameters
,
$point1
,
$point2
,
$point3
);
my
(
$angle
,
$controlAngle
) =
&calcAnglesFromPoints
(\
@newPoints
);
${
$self
}{
"point1"
} =
$newPoints
[0];
${
$self
}{
"point3"
} =
$newPoints
[2];
${
$self
}{
"angle"
} =
$angle
;
${
$self
}{
"controlAngle"
} =
$controlAngle
;
}
}
sub
crosses_axis {
my
$point1
=
shift
;
my
$point3
=
shift
;
my
$axis
=
shift
;
my
$x1
= ${
$point1
}[0];
my
$y1
= ${
$point1
}[1];
my
$x3
= ${
$point3
}[0];
my
$y3
= ${
$point3
}[1];
my
$x
= ${
$axis
}[0];
my
$y
= ${
$axis
}[1];
return
$x1
*
$y3
-
$x3
*
$y1
+ (
$y1
-
$y3
) *
$x
+ (
$x3
-
$x1
) *
$y
;
}
sub
getbbox {
my
$self
=
shift
;
my
$parameters
=
shift
;
my
$point1
= ${
$self
}{
"point1"
};
my
$point3
= ${
$self
}{
"point3"
};
my
$angle
= ${
$self
}{
"angle"
};
my
$x1
= ${
$point1
}[0];
my
$y1
= ${
$point1
}[1];
my
$x3
= ${
$point3
}[0];
my
$y3
= ${
$point3
}[1];
my
$half_cot
= cot(
$angle
/ 2) / 2;
my
$xc
=
$x1
+ (
$x3
-
$x1
) / 2 + (
$y3
-
$y1
) *
$half_cot
;
my
$yc
=
$y1
+ (
$y3
-
$y1
) / 2 - (
$x3
-
$x1
) *
$half_cot
;
my
$dx
=
$x1
-
$xc
;
my
$dy
=
$y1
-
$yc
;
my
$r
=
sqrt
(
$dx
*
$dx
+
$dy
*
$dy
);
my
$bbox
= Graphics::Fig::Parameters::getbboxFromPoints(
$point1
,
$point3
);
if
(
&crosses_axis
(
$point1
,
$point3
, [
$xc
-
$r
,
$yc
]) *
$angle
> 0) {
if
(
$xc
-
$r
< ${
$bbox
}[0][0]) {
${
$bbox
}[0][0] =
$xc
-
$r
;
}
}
if
(
&crosses_axis
(
$point1
,
$point3
, [
$xc
,
$yc
-
$r
]) *
$angle
> 0) {
if
(
$yc
-
$r
< ${
$bbox
}[0][1]) {
${
$bbox
}[0][1] =
$yc
-
$r
;
}
}
if
(
&crosses_axis
(
$point1
,
$point3
, [
$xc
+
$r
,
$yc
]) *
$angle
> 0) {
if
(
$xc
+
$r
> ${
$bbox
}[1][0]) {
${
$bbox
}[1][0] =
$xc
+
$r
;
}
}
if
(
&crosses_axis
(
$point1
,
$point3
, [
$xc
,
$yc
+
$r
]) *
$angle
> 0) {
if
(
$yc
+
$r
> ${
$bbox
}[1][1]) {
${
$bbox
}[1][1] =
$yc
+
$r
;
}
}
return
$bbox
;
}
sub
print
{
my
$self
=
shift
;
my
$fh
=
shift
;
my
$parameters
=
shift
;
my
$figPerInch
= Graphics::Fig::_figPerInch(
$parameters
);
my
$subtype
= ${
$self
}{
"subtype"
};
my
$direction
= ${
$self
}{
"angle"
} >= 0;
my
$point1
= ${
$self
}{
"point1"
};
my
(
$center
,
$point2
) =
&findPoint2
(
$self
);
my
$point3
= ${
$self
}{
"point3"
};
printf
$fh
(
"5 %d %d %.0f %d %d %d -1 %d %.3f %d %d %d %d "
.
"%.0f %.0f %.0f %.0f %.0f %.0f %.0f %.0f\n"
,
$subtype
,
${
$self
}{
"lineStyle"
},
${
$self
}{
"lineThickness"
} * 80.0,
${
$self
}{
"penColor"
},
${
$self
}{
"fillColor"
},
${
$self
}{
"depth"
},
${
$self
}{
"areaFill"
},
${
$self
}{
"styleVal"
} * 80.0,
${
$self
}{
"capStyle"
},
$direction
,
defined
(${
$self
}{
"fArrow"
}) ? 1 : 0,
defined
(${
$self
}{
"bArrow"
}) ? 1 : 0,
${
$center
}[0] *
$figPerInch
, ${
$center
}[1] *
$figPerInch
,
${
$point1
}[0] *
$figPerInch
, ${
$point1
}[1] *
$figPerInch
,
${
$point2
}[0] *
$figPerInch
, ${
$point2
}[1] *
$figPerInch
,
${
$point3
}[0] *
$figPerInch
, ${
$point3
}[1] *
$figPerInch
);
Graphics::Fig::Parameters::printArrowParameters(
$self
,
$fh
,
$parameters
);
}
1;