jw_cad 外部変形 - (1222) perlで楕円弧の長さ(表示画面のスケール)を計測表示する -

外部変形は データのやり取りをテキストファイルで行うので プログラム言語は 自由に選ぶことができます。図形は機能的かつシンプルなため、数多くのユーザーに受け入れられています。

 

perlで楕円弧の長さ(表示画面のスケール)を計測表示する

:perlで楕円弧の長さ(表示画面のスケール)を計測表示する
@echo off
perl -x %~f0 jwc_temp.txt
goto:eof

REM #jww
REM #1ci 長さを計測する円・円弧を指示してください
REM #bz
REM #e

#!perl -i.bak
## a2p.exe 024arc_l-2.awk で 変換後に修正した。
BEGIN {
    $PI = atan2(1, 1) * 4;
}
while (<>) {
    chomp;      # strip record separator
    @Fld = split(' ', $_, -1);
    if (/^hs/) {
        for ($i = 0; $i <= 15; $i++) {
            $hs{sprintf('%x', $i)} = $Fld[$i + 1];
        }
    }
    if (/^lg[0-9a-f]/) {
        $plg = substr($_, 2, 1);
        if ($lg eq '') { $lg = $plg; }
    }
    if (/^ci/) {
        $lr = cilength(@Fld) * $hs{$lg}; # / $hs{$plg};
        printf "h#円弧長 L = %.03f\n", $lr;
    }
}

sub cilength {
    my ($r, $p1, $p2, $w, $l);
    $r = $_[3];
    if (@_ == 4) {
        ($p1, $p2, $w) = (0, 0, 1);
    } elsif (@_ == 8) {
        ($p1, $p2, $w) = @_[4..6];
        if ($w > 1) {
            $w = 1 / $w;
            $r /= $w;
            $p1 -= 90;
            $p2 -= 90;
        }
    }
    if ($w == 1) {
        $l = ($p1 == $p2 ? 360 : $p2 - $p1) * $PI / 180;
    } else {
        &eh($N = int(12 * (1.5 / $w))); #Gauss-Legendre
        $l = &arc_l(sqrt(1 - $w ** 2), $p1, $p2);
    }
    return $l * $r;
}

sub arc_l {
    local($k, $p1, $p2, $lp, $n1, $n2, $n3) = @_;
    $Ek = &E($k, $PI / 2);
    if ($p1 == $p2) { return 4 * $Ek; }
    $n1 = int($p1 / 90) + 1;
    if ($n1 > 4) { $n1 = 4; }
    $lp = $Ek * ( ($n1 + 1) % 2) + &E($k, &apa($n1,$p1) * $PI / 180) * (-1) ** ($n1 - 1);
    $n2 = int($p2 / 90) + 1;
    if ($n2 > 4) { $n2 = 4; }
    if ($n1 == $n2) { $n1 += 4; }
    $n3 = 2 * int( ($n2 - 1) / 2) + 5;
    $lp += $Ek * ( ($n3 - $n1) % 4) + &E($k, &apa($n2,$p2) * $PI / 180) * (-1) ** $n2;
    if ($lp < 0) { $lp += 4 * $Ek; }
    $lp;
}

sub apa {
    local($o, $p) = @_;
    (90 * (int( ($o + 1) / 2) * 2 - 1) - $p) * (-1) ** ($o - 1);
}

sub f {
    local($X, $k) = @_;
    sqrt(1 - ($k * sin($X)) ** 2);
}

sub E { #Gauss-Legendre
    local($k, $p, $i, $l) = @_;
    $l = 0;
    if ($N > 1) {
        for ($i = 1; $i <= int($N / 2); $i++) {
            $l += $h{$i} * &f($e{$i} * $p, $k);
        }
    }
    if ($N % 2 == 1) {
        my $M = int($N / 2) + 1;
        $l += $h{$M} * &f($e{$M} * $p, $k) / 2;
    }
    $l * $p;
}

sub eh { #Gauss-Legendre 積分点の係数
    my ($N) = @_;
    my ($M, $E1, $PAI);
    my ($I, $T, $X0, $PKM1, $PK, $K, $T1, $PKP1);
    my ($DEN, $D1, $DPN, $D2PN, $D3PN, $D4PN, $U, $V, $H, $P, $DP, $XI, $FX, $WI);
    $M = int($N / 2) + $N % 2;
    $E1 = $N * ($N + 1);
    $PAI = atan2(1, 1) * 4;
    for ($I = 1; $I <= $M; $I++) {
        #DO 1
        $T = (4 * $I - 1) * $PAI / (4 * $N + 2);
        $X0 = (1 - (1 - 1 / $N) / (8 * $N * $N)) * cos($T);
        $PKM1 = 1;
        $PK = $X0;
        for ($K = 2; $K <= $N; $K++) {
            #DO 3
            $T1 = $X0 * $PK;
            $PKP1 = $T1 - $PKM1 - ($T1 - $PKM1) / $K + $T1;
            $PKM1 = $PK;
            $PK = $PKP1;
        } # 3
        $DEN = 1 - $X0 * $X0;
        $D1 = $N * ($PKM1 - $X0 * $PK);
        $DPN = $D1 / $DEN;
        $D2PN = (2 * $X0 * $DPN - $E1 * $PK) / $DEN;
        $D3PN = (4 * $X0 * $D2PN + (2 - $E1) * $DPN) / $DEN;
        $D4PN = (6 * $X0 * $D3PN + (6 - $E1) * $D2PN) / $DEN;
        $U = $PK / $DPN;
        $V = $D2PN / $DPN;
        $H = -$U * (1 + .5 * $U * ($V + $U * ($V * $V - $D3PN / (3 * $DPN))));
        $P = $PK + $H * ($DPN + .5 * $H * ($D2PN + $H / 3 * ($D3PN + .25 * $H * $D4PN)));
        $DP = $DPN + $H * ($D2PN + .5 * $H * ($D3PN + $H * $D4PN / 3));
        $H = $H - $P / $DP;
        $XI = -($X0 + $H);
        $FX = $D1 - $H * $E1 * ($PK + .5 * $H * ($DPN + $H / 3 * ($D2PN + .25 * $H * ($D3PN + .2 * $H * $D4PN))));
        $WI = 2 * (1 - $XI * $XI) / ($FX * $FX);
        $e{$I} = $XI;
        $h{$I} = $WI;
    } # 1
}
__END__