Path: sranha!katsu From: katsu@sra.co.jp (WATANABE Katsuhiro) Message-ID: Date: 16 Nov 90 09:17:43 Organization: Software Research Associates, Inc.,Japan In-reply-to: iwai@srava.sra.co.jp's message of 15 Nov 90 02:26:37 GMT Newsgroups: sra.wanted Subject: Re: draw lines Distribution: sra References: <4762@srava.sra.co.jp> 記事 <4762@srava.sra.co.jp> で iwai@srava.sra.co.jp (Takehito Iwai) さんいはく > 「ある座標系を持ったイメージデータの任意の二点間に線を引く」 > (Pixmap に XDrawLines() を使って線を引くようなかんじ) 2点間を、連続した点列で結ぼうという比較的単純な話でしょうか? (座標系が直交していないとか、線形でないとか、2次元でないとか、 点の位置が格子点でないとか、XDrawLines() みたいにGC でいろんなことが 指定できなければならないとかでないと楽なのですが......) つまり、 ■■ ■■■■ ←こんな ■■■■ 階段状の ■■■■ ■■ 線を引くのだったら(XDrawPoint() のような点を打つ処理を受け持って くれるものの存在を仮定して)下のような考え方はどうでしょうか? /* なだらかな斜線を引く: X方向にいくつか進むたびにY方向に1段上がる戦略(これによって 連続性が保証される)のため、X方向に1つ進む間にY方向に 2段登らなきゃならないような、急な斜線はひけない。*/ line(x1, y1, x2, y2) int x1, y1, x2, y2; { int x, y, dx, dy; int 1段上がる時機?; /* X方向に1つ進むたびにY方向に dy/dx 段登ろうとする。 1つ進むごとにこの変数に dy/dx を加算していって整数部が 増えるたび1段上がるという戦略。ただし、すべてを 整数演算でやるために、常に dx 倍して考える。 */ dx = x2 - x1; dy = y2 - y1; 1段あがる時機? = dy / 2; /* < dx であれば初期値はいくらでもいいのだが、両端の 美しさを考えて dy / 2 にする。*/ y = y1; for (x = x1; x <= x2; x++) { /* 1段上がる時機? の初期値が < dx である限り、 x == x2 の時には正しく y == y2 になる(端点保証)*/ 点を打つ(x, y); 1段上がる時機? += dy; if (1段上がる時機? >= dx) { 1段上がる時機? -= dx; y++; } } } 急(縦方向に長い、すなわち dy > dx)な斜線を引くときには、 場合分けしてX軸とY軸を入れ換えて処理すればよいはずです。 あと、dx と dy が負になる場合のことは全く考えてませんが、 やはり場合分けでどうにかなる(?)と思います。 > ということをやりたいのですが、良い方法があれば教えてください。 上の方法が「良い」方法と主張する根拠(chmod +まゆつば): 1.両端が(x1, y1), (x2, y2)となることが保証されている 2.点が連続することが保証されている 3.整数演算しかつかわないので丸め誤差の問題を避けられ、一様な線である ことが保証されている 4.整数の演算、それも加減算しか使わないので速い(はず) #全然テストしてないので、間違っていたら笑って下さい。 -- ----____----____ 渡邊克宏@ソフトウェア工学研旧所