- PR -

Strokeで2重線を描画する方法について

1
投稿者投稿内容
Guri
会議室デビュー日: 2007/01/16
投稿数: 12
投稿日時: 2007-01-16 14:21
Graphics2DでsetStroke(Stroke)を使用した後、Shapeを2重線で描画したいのですが、
2重線を描画するStrokeをどう実装すべきか分かりません。

前提として、Strokeを使用するShapeは描画時点まで不定です。

これまで、やったこととしては、java.awt.BasicStrokeの実装では、2重線を描画できないため、BasicStrokeをメンバーに持つ、Strokeインタフェイスを実装したクラスAを作成しました。

次に、クラスAのStrokeインタフェイスメソッドのcreateStrokedShape(Shape)で,
メンバーのBasicStroke.createStrokedShape(Shape)の戻り値を、Affine変換して、java.awt.geom.GeneralPathで結合しようとしました。

ただ、描画時点まで描画するShapeは不定であるため、適用するAffine変換も
不定になり、実装できないことに気づきました。

Shapeが固定であれば、つまりハードコーディングすれば、実装できますが、
ハードコードせずに、2重線を描画するStroke実装のアイディア、方法を教えて下さい。

よろしく御願いします。

環境:
java version "1.5.0_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_01-b08)
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-01-16 16:48
私も自前で実装したことはないのですが…

java.awt.Strokeの実装を作るという話でよいのでしょうか。
さらに言えばShape.getPathIterator()で取得したPathIteratorの
currentSegment()で得た値を元にShapeを実装しろってことになるのでしょうか。

さて、渡されたShapeを元にどうやって二重線を表すShapeを作るかということですよね。
まじめに線分の方向を見ながら等距離に2本線を引くShapeを作ると確かに大変そうです。

不真面目に実装するのだとしたら、やや縮小したShapeと
やや拡大したShapeをAffineTransformで作ってやって、
それらをまとめてひとつのShapeとして扱うようなShapeを実装すれば
それっぽくはできるのかもしれませんね。
nekoyama
ベテラン
会議室デビュー日: 2005/03/12
投稿数: 71
投稿日時: 2007-01-16 21:33
要件に合うか分かりませんが、こんな感じでどうでしょうか。

コード:
import java.awt.Stroke;
import java.awt.BasicStroke;
import java.awt.Shape;
public class WStroke implements Stroke{
	
	private float width1;
	private float width2;
	
	private static Stroke createStroke(float width){
		return new BasicStroke(width);
	}
	public DoubleStroke(float width1, float width2){
		this.width1 = width1;
		this.width2 = width2;
	}
	public Shape createStrokedShape(Shape s){
         Shape out = createStroke(width1).createStrokedShape(s);
		return createStroke(width2).createStrokedShape(out);
	}



これで、2重線は表現できます。
Graphics2D.setStroke(new WStroke(8.0f, 0.5f));のように使用します。

ただし、難点としては、Strokeを適用する形状によっては
BasicStrokeが作成するパスに、不要なパスが含まれることです。

不要なパスは、例えばRectangle2Dに適用した場合、4隅に現れます。

処理の概要としては、外部のパスを一時取得して、その結果に対してStroke2を
適用することで、本来の形状をくりぬいたような形状を表現します。
Guri
会議室デビュー日: 2007/01/16
投稿数: 12
投稿日時: 2007-01-16 23:07
nagiseさん、未記入さん
回答ありがとうございます。

未記入さんの方法で実装します。
不要なパスは、BasicStrokeのPathIteratorを操作してみます。

ありがとうございました。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-01-17 10:15
引用:

未記入さんの書き込み (2007-01-16 21:33) より:
処理の概要としては、外部のパスを一時取得して、その結果に対してStroke2を
適用することで、本来の形状をくりぬいたような形状を表現します。



そういう方法論もあるのですね。
ところで、これって背景がすでにある場合、透明にくり抜いてくれるのですか?
nekoyama
ベテラン
会議室デビュー日: 2005/03/12
投稿数: 71
投稿日時: 2007-01-18 00:57
引用:

そういう方法論もあるのですね。
ところで、これって背景がすでにある場合、透明にくり抜いてくれるのですか?


nagiseさんの意図と異なるかもしれませんが。
一応、ええ、まぁ。。
(下記のように、nagiseさんの言っていることを、私の想像に置き換えた限りでは。)

public void paint(Graphics g){
Graphics2D g2d = (Graphics2D)g;
g2d.drawImage(Instance of BufferedImage, null, 0, 0);
g2d.setPaint(Color.RED);
g2d.setStroke(二重線Stroke);
g2d.draw(Instance of Shape);
}
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-01-18 10:12
うーむ。
どういう仕組みになってるんだろ…。
個人的に研究してみます。

どうも自分の中でのShapeの概念の理解が間違えているっぽい。
1

スキルアップ/キャリアアップ(JOB@IT)