my ($r);
$r= atan2($b->{Y} - $a->{Y},
$b->{X} - $a->{X});
- $r -= 2 * $pi;
- while ($r < $a->{A}) { $r += 2 * $pi; }
+ $r -= 4.0 * $pi;
+ while ($r < $a->{A}) { $r += 2.0 * $pi; }
+ $r;
}
sub v_dist ($$) {
# v_dist(A,B)
}
}
-sub arc ($$$$$$) {
- my ($to, $ctr,$from,$fromsense, $radius,$delta) = @_;
+sub arc ($$$$$) {
+ my ($to, $ctr,$from, $radius,$delta) = @_;
# does parametric_segment to draw an arc centred on $ctr
+ # ($ctr->{A} ignored)
# from $from with radius $radius (this must be consistent!)
# and directionally-subtending an angle $delta.
# sets $to->... to be the other end, and returns $to
- # $fromsense is 1 or -1, and affects only the interpretation
- # of $from->{A} (not the result).
- my ($beta, $fromadj);
- $fromadj= (1.0 - $fromsense) * $pi;
- $to->{A}= $beta= $from->{A} + $fromadj + $delta;
+ my ($beta);
+ $to->{A}= $beta= $from->{A} + $delta;
$to->{X}= $ctr->{X} - $radius * sin($beta);
$to->{Y}= $ctr->{Y} + $radius * cos($beta);
+ return if abs($delta*$radius) < 1E-9;
parametric_segment(0.0,1.0, abs($radius*$delta), sub {
my ($beta) = $from->{A} + $delta * $param;
return { X => $ctr->{X} - $radius * sin($beta),
my (@paths);
if ($how eq 'arcs') {
my ($sigma,$distfact, $theta,$phi, $a,$b,$c,$d, $m,$r);
- my ($cvec,$cfrom,$cto,$midpt, $delta1,$delta2, $path);
+ my ($cvec,$cfrom,$cto,$midpt, $delta1,$delta2, $path,$reverse);
$sigma= ev_bearing($from,$to);
$distfact= v_dist($from,$to);
$theta= 0.5 * $pi - ($from->{A} - $sigma);
foreach $m (qw(-1 1)) {
$r= -0.5 * (-$b + $m*$d) / $a;
$radius= -$r * $distfact;
- $cvec= { X => 0, Y => -$radius, A => 0.5*$pi };
- $cfrom= ev_compose({}, $from, $cvec);
- $cto= ev_compose({}, $to, $cvec);
+ $cfrom= ev_compose({}, $from, { X=>0, Y=>-$radius, A=>-0.5*$pi });
+ $cto= ev_compose({}, $to, { X=>0, Y=> $radius, A=> 0.5*$pi });
$midpt= ev_lincomb({}, $cfrom, $cto, 0.5);
- $delta1= ev_bearing($cfrom, $midpt);
- $delta2= ev_bearing($cto, $midpt);
- $delta2 -= 2*$pi;
- $path= [{ T=>Arc, F=>$from, C=>$cfrom, R=>$radius, D=>$delta1 },
- { T=>Arc, F=>$to, C=>$cto, R=>$radius, D=>$delta2 }];
+ $reverse= signum($r);
+ if ($reverse<0) {
+ $cfrom->{A} += $pi;
+ $cto->{A} += $pi;
+ }
+ $delta1= ev_bearing($cfrom, $midpt) - $cfrom->{A};
+ $delta2= ev_bearing($cto, $midpt) - $cto->{A};
+ if ($reverse<0) {
+ $delta1 -= 2*$pi;
+ $delta2 -= 2*$pi;
+ }
+ my ($fs);
+ $path= [{ T=>Arc, F=>$from, C=>$cfrom, R=> $radius, D=>$delta1 },
+ { T=>Arc, F=>$to, C=>$cto, R=>-$radius, D=>$delta2 }];
push @paths, $path;
}
}
o("% chose path $bestpath\n");
foreach $segment (@$bestpath) {
if ($segment->{T} eq 'Arc') {
- arc({}, $segment->{C}, $segment->{F}, 1.0,
- $segment->{R}, $segment->{D});
+ arc({}, $segment->{C},$segment->{F},$segment->{R},$segment->{D});
} else {
die "unknown segment";
}
$beta -= $sign_ang * $sign_r * $beta_interval * $pi;
}
printf DEBUG "ctr->{Y}=$ctr->{Y} radius=$radius beta=$beta\n";
- arc($to, ,$ctr,$from,1.0, $radius,$delta);
+ arc($to, ,$ctr,$from, $radius,$delta);
}
printf DEBUG "to $to->{X} $to->{Y} $to->{A}\n";
}