Symfoware

Symfowareについての考察blog

Apache PDFBox 扇型、円、楕円を描画する

Apache PDFBox 2.0系のスナップショットを使って、PDFの出力を試しています。
Apache PDFBoxで日本語の出力とフォントの埋め込み


今回は、扇型や円、楕円の描画方法を調べてみます。


扇型



最初、円を描画するcircleや楕円を描画するellipse、ovalというような
メソッドが用意されていると思っていたのですが、
どうやら使えるのは「curveTo」というメソッドのみの模様。

これは三次元ペジェ曲線の描画ですね。
まず、円の1/4の扇形を描画することを考えてみます。

こちらを参考にさせていただきました。
ベジェ曲線による円の近似

x = 200
y = 400
を原点に半径150の扇形を描画していみます。

プログラム中登場する「0.55228475」は、

639_01.png

この部分を事前に計算した結果です。


  1. import org.apache.pdfbox.pdmodel.PDDocument;
  2. import org.apache.pdfbox.pdmodel.PDPage;
  3. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  4. public class MainProccess {
  5.     
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         PDDocument doc = new PDDocument();
  9.         
  10.         // 新しいページを追加
  11.         PDPage page = new PDPage();
  12.         doc.addPage(page);
  13.                 
  14.         // 出力用のストリームを開く
  15.         PDPageContentStream contents = new PDPageContentStream(doc, page);
  16.         
  17.         float x = 200f;
  18.         float y = 400f;
  19.         float r = 150f;
  20.         
  21.         float p = 0.55228475f * r;
  22.         
  23.         
  24.         contents.moveTo(x + r, y);
  25.         contents.curveTo(x + r, y + p,
  26.                         x + p, y + r,
  27.                         x, y + r);
  28.         contents.stroke();
  29.         
  30.         // ストリームを閉じる
  31.         contents.close();
  32.         // pdfファイルを出力
  33.         doc.save("sample.pdf");
  34.         doc.close();
  35.         
  36.         
  37.     }
  38. }




それっぽい線が描けたのでは。

639_02.png





円の描画



円を描画するには、上記の扇型を4つつなぎ合わせれば良いことになります。
どこでバグったかわからなくなるので、べたに実装してみました。


  1. import org.apache.pdfbox.pdmodel.PDDocument;
  2. import org.apache.pdfbox.pdmodel.PDPage;
  3. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  4. public class MainProccess {
  5.     
  6.     public static void main(String... args) throws Exception {
  7.         
  8.         PDDocument doc = new PDDocument();
  9.         
  10.         // 新しいページを追加
  11.         PDPage page = new PDPage();
  12.         doc.addPage(page);
  13.                 
  14.         // 出力用のストリームを開く
  15.         PDPageContentStream contents = new PDPageContentStream(doc, page);
  16.         
  17.         float x = 200f;
  18.         float y = 400f;
  19.         float r = 150f;
  20.         
  21.         float p = 0.55228475f * r;
  22.         
  23.         
  24.         contents.moveTo(x + r, y);
  25.         
  26.         // 右上
  27.         contents.curveTo(x + r, y + p,
  28.                 x + p, y + r,
  29.                 x, y + r);
  30.         
  31.         // 左上
  32.         contents.curveTo(x - p, y + r,
  33.                 x - r, y + p,
  34.                 x - r, y);
  35.         
  36.         // 左下
  37.         contents.curveTo(x - r, y - p,
  38.                 x - p, y - r,
  39.                 x, y - r);
  40.         
  41.         // 右下
  42.         contents.curveTo(x + p, y - r,
  43.                 x + r, y - p,
  44.                 x + r, y);
  45.         
  46.         contents.stroke();
  47.         
  48.         // ストリームを閉じる
  49.         contents.close();
  50.         // pdfファイルを出力
  51.         doc.save("sample.pdf");
  52.         doc.close();
  53.         
  54.         
  55.     }
  56. }




いい感じです。

639_03.png





円の中を塗りつぶし



contents.stroke()をcontents.fill()に変更すれば円を塗りすぶすことができます。


  1. import java.awt.Color;
  2. import org.apache.pdfbox.pdmodel.PDDocument;
  3. import org.apache.pdfbox.pdmodel.PDPage;
  4. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  5. public class MainProccess {
  6.     
  7.     public static void main(String... args) throws Exception {
  8.         
  9.         PDDocument doc = new PDDocument();
  10.         
  11.         // 新しいページを追加
  12.         PDPage page = new PDPage();
  13.         doc.addPage(page);
  14.                 
  15.         // 出力用のストリームを開く
  16.         PDPageContentStream contents = new PDPageContentStream(doc, page);
  17.         
  18.         float x = 200f;
  19.         float y = 400f;
  20.         float r = 150f;
  21.         
  22.         float p = 0.55228475f * r;
  23.         
  24.         
  25.         contents.moveTo(x + r, y);
  26.         
  27.         // 右上
  28.         contents.curveTo(x + r, y + p,
  29.                 x + p, y + r,
  30.                 x, y + r);
  31.         
  32.         // 左上
  33.         contents.curveTo(x - p, y + r,
  34.                 x - r, y + p,
  35.                 x - r, y);
  36.         
  37.         // 左下
  38.         contents.curveTo(x - r, y - p,
  39.                 x - p, y - r,
  40.                 x, y - r);
  41.         
  42.         // 右下
  43.         contents.curveTo(x + p, y - r,
  44.                 x + r, y - p,
  45.                 x + r, y);
  46.         
  47.         
  48.         //contents.stroke();
  49.         // 円を赤で塗りつぶし
  50.         contents.setNonStrokingColor(Color.red);
  51.         contents.fill();
  52.         
  53.         // ストリームを閉じる
  54.         contents.close();
  55.         // pdfファイルを出力
  56.         doc.save("sample.pdf");
  57.         doc.close();
  58.         
  59.         
  60.     }
  61. }




こんなPDFになりました。

639_04.png




楕円



綺麗な楕円ではないのですが、y軸座標に与える内容を修正することで、
それっぽい図形になってくれます。


  1. import java.awt.Color;
  2. import org.apache.pdfbox.pdmodel.PDDocument;
  3. import org.apache.pdfbox.pdmodel.PDPage;
  4. import org.apache.pdfbox.pdmodel.PDPageContentStream;
  5. public class MainProccess {
  6.     
  7.     public static void main(String... args) throws Exception {
  8.         
  9.         PDDocument doc = new PDDocument();
  10.         
  11.         // 新しいページを追加
  12.         PDPage page = new PDPage();
  13.         doc.addPage(page);
  14.                 
  15.         // 出力用のストリームを開く
  16.         PDPageContentStream contents = new PDPageContentStream(doc, page);
  17.         
  18.         float x = 200f;
  19.         float y = 400f;
  20.         float r = 150f;
  21.         float r2 = 100;
  22.         
  23.         float p = 0.55228475f * r;
  24.         float p2 = 0.55228475f * r2;
  25.         
  26.         contents.moveTo(x + r, y);
  27.         
  28.         // 右上
  29.         contents.curveTo(x + r, y + p2,
  30.                 x + p, y + r2,
  31.                 x, y + r2);
  32.         
  33.         // 左上
  34.         contents.curveTo(x - p, y + r2,
  35.                 x - r, y + p2,
  36.                 x - r, y);
  37.         
  38.         // 左下
  39.         contents.curveTo(x - r, y - p2,
  40.                 x - p, y - r2,
  41.                 x, y - r2);
  42.         
  43.         // 右下
  44.         contents.curveTo(x + p, y - r2,
  45.                 x + r, y - p2,
  46.                 x + r, y);
  47.         
  48.         
  49.         //contents.stroke();
  50.         // 円を赤で塗りつぶし
  51.         contents.setNonStrokingColor(Color.red);
  52.         contents.fill();
  53.         
  54.         // ストリームを閉じる
  55.         contents.close();
  56.         // pdfファイルを出力
  57.         doc.save("sample.pdf");
  58.         doc.close();
  59.         
  60.         
  61.     }
  62. }




639_05.png


やってみてわかったことは
・ペジェ曲線難しい
・高校数学(幾何)を真面目にやっておけばよかった



【参考URL】

ベジェ曲線による円の近似

ベジエ曲線について

二次ベジェ曲線による円の近似



関連記事

テーマ:プログラミング - ジャンル:コンピュータ

  1. 2015/08/22(土) 19:05:27|
  2. Java
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
<<Thinreports + JavaでPDF帳票を出力する | ホーム | Apache PDFBox 用紙サイズの指定と用紙の向き(Landscape,Portrait)>>

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://symfoware.blog68.fc2.com/tb.php/1789-bfbd5a76
この記事にトラックバックする(FC2ブログユーザー)