Perl: 2014年4月アーカイブ

ちょっと思うところあって、Perl で PDF の出力を行う方法について調べてみた。

Perl 用の PDF 生成モジュールは何種類かあるんだけど、一番有名な PDFlib は有料なので、今回は PDF::API2 モジュールで試してみた。

モジュール内の SYNOPSIS に載ってるソース例を元に、「衡山毛筆フォント」というフリーの毛筆フォントで日本語を出力する CGI を作成してみた。

#!/usr/bin/perl

use PDF::API2;

# Create a blank PDF file
my $pdf = PDF::API2->new();

# Add a blank page
my $page = $pdf->page();

# Set the page size
$page->mediabox('A4');

# Add an external TTF font to the PDF
my $font = $pdf->ttfont('/usr/local/share/fonts/kouzanmouhitufont.ttf', -encode, "utf-8");

# Add some text to the page
my $str =<<EOS;
2014/04/25
我が性春に悔いなし!
俺は海賊船になる!!
EOS

my $text = $page->text();
$text->font($font, 30);
$text->translate(100, 700);
# 改行を含む文字列は、1行ずつ改行処理を入れながら出力
foreach my $line(split/\n/, $str){
$text->text($line);
#行の高さ分改行(下に改行するならマイナス値)
$text->cr(-30);
}

# Save the PDF
my $pdf_file = 'temp/test.pdf';
$pdf->saveas($pdf_file);

# ブラウザに出力
my $pdf_size = -s $pdf_file;

open (IN, $pdf_file);
my $pdf_data = join '', (<IN>);
close(IN);

print "Content-type: application/pdf\n";
print "Content-Length: $pdf_size\n\n";
print $pdf_data;

# END

こんな感じ。

一点、文章の途中で改行コードを入れていてもそのまま PDF にセットすると化けるだけなので、改行コードで文章を分割し、1行出力する度に $text->cr で改行してやらないと駄目。
ちょっとハマったのはこれくらいで、あとは何の問題もなくすんなり出力されたので拍子抜けした(笑)

20140425_pdf.jpg

まあ、きれいなレイアウトで文章を配置しようとするとけっこうややこしいコードを書かなくちゃいけないんだろうけど、とりあえず一つの文章を A4 用紙の上から表示していくだけなら簡単やねえ。

ちなみに、こんな簡単な例でも、ちょっと一呼吸おくくらい処理時間がかかる。
複雑な文書だと、数秒はまたないといけないのかもなあ・・・

引き続き、複雑なレイアウトのものを作ってみる。
地点間の距離を求める要件あり。
まあ、よくある「今いる地点の近くの物件を全部表示」的な仕様の対応です。

多分、実際にはここまで厳密な距離を求める必要はないので、実装はしないと思うけど、「緯度経度より距離を求める方法・備忘録 | 地球は丸い!」に PHP で書いた例が乗っていたので、Perl で書きなおしてみた。

Perl には、deg2rad(度からラジアンに変換)といった関数は標準では用意されていないので、自分で書くか、Math::Trig モジュールを組み込む。もちろん俺はモジュール使うよ(笑)

#!/usr/bin/perl

use Math::Trig; # 三角関数計算用モジュール

$ido1 = 34.410280; # 場所1の緯度(10進)
$keido1 = 132.450732; # 場所1の経度(10進)

$ido2 = 34.397349; # 場所2の緯度(10進)
$keido2 = 132.447650; # 場所2の経度(10進)

$earth_r = 6378.137; # 地球の半径(km)

$idoSa = deg2rad(abs($ido2 - $ido1)); # 緯度差をラジアンに
$keidoSa = deg2rad(abs($keido2 - $keido1)); #経度差をラジアンに

$nanbokuKyori =  $earth_r * $idoSa; # 南北の距離

# 東西の距離(赤道から離れると経度間の距離は縮まるので誤差計算)
$start_ido = $ido1; # 緯度の小さい方を開始地点に
if ($ido1 > $ido2) {
$start_ido = $ido2;
}
$touzaiKyori = cos(deg2rad($start_ido)) * $earth_r * $keidoSa;

# 三平方の定理(xの2乗 + yの2乗 = 求める距離の2乗)で直線距離計算
$d = sqrt(($touzaiKyori ** 2) + ($nanbokuKyori ** 2));

print "2点間の距離=" . $d . "km\n";

# END

ちなみに、場所1は横川駅で、場所2は十日市電停(紙屋町方面行き)だ。
直線距離で約1.5kmあるが、計算してみると、「2点間の距離=1.46704568780563km」と出た。
1.46km。うん、良い感じ。

岩国の自宅と十日市電停の距離を計算すると 47.3516365429946km って・・・
正しいかどうかわからん(^^;
しかし、十日市電停と紙屋町西電停の間を計算すると 0.881788682313342kmと出たんで、正しく計算できてそうだな。

このアーカイブについて

このページには、2014年4月以降に書かれたブログ記事のうちPerlカテゴリに属しているものが含まれています。

前のアーカイブはPerl: 2013年6月です。

次のアーカイブはPerl: 2014年5月です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら