2

Java2D を使用してマップを描画しようとしています。マップをズームアウトすると、道路が描画アーティファクトでいっぱいになります。これは、完全な米国の州を描画するときの画面の一部です。

図面アーティファクトを示す州縮尺で描かれた道路セクション

これは、ズームインしたときの道路の同様のセクションです。

人工物なしでサブカウンティ スケールで描かれた道路セクション

使用される線のスタイルは、幅が 2 ピクセルに相当するようにスケーリングされた青い実線です。さまざまなレンダリングのヒントと行結合ルールを試しましたが、何も役に立たないようです。

OS/X 10.8 を実行している Mac で Open JDK 1.7 を使用していますが、これは Sun JDK 1.6 を搭載した Linux マシンでも再現可能です。

すべての形状と変換は、Java2D で可能な限り倍精度です。線のジオメトリには、間隔の狭い点が多数あります。描画アーティファクトの原因は、1 ピクセルよりも近い連続した点によってレンダラーが混乱していることだと思います。

ポイントを細くせずにズームアウトした形状の外観を改善する方法はありますか?

編集 描画アーティファクトは、別々の線分が交わる点にあるため、欠落しているピクセルは、終点が同一であっても、ライン キャップ (端) が交わらないことに関係しています。この画像は、2 つの線分が交わる点を示しています。各線分を 7 ピクセルのスケーリングされた線のスタイル (白で XOR 処理) で強調表示しましたが、非常によく見ると、元の青い線の一部がまだ見えます (これは、丸みを帯びたキャップが重なっており、XOR 描画モードによるものです)。 .) 通常の縮尺では両端が重なり合っているように見えますが、通常のペイント モードでズームアウトして元に戻すと、破線の効果があります。

回避策の 1 つは、隣接するすべての線分を結合してから描画することですが、描画アーティファクトの本当の原因を知りたいと思います。

2 つの道路セグメント間の結合

4

2 に答える 2

1

OS X 1.6 JDK を使用した場合の状況を再現することはできませんが、いくつか提案があります。

これを単に状態の概要を示すために使用している場合は、GeneralPathclassの使用を検討してください。メソッドを使用しlineTo(x,y)て、ライン上の各ポイントを確立できます。繰り返しますが、を使用して問題を再現することはできないためLine2D.Double、これが実際に異なるかどうかはわかりません.

2 番目に、おそらくもっと重要なのは、ズームインとズームアウトの方法です。AffineTransformオブジェクトに(with setScaleTo(x,y))を使用していGraphics2Dますが、すべて問題なく動作しています。データ内のポイントをズーム倍率 (またはその他の方法) でスケーリングする代替手段と比較すると、これはかなり簡単です。また、すべてが縮小されるため、線のストロークを係数で調整する必要があります。ご希望があれば、スクリーンショットを投稿できます。

于 2012-08-15T01:53:01.917 に答える
1

Xiaolin Wu のライン アルゴリズムを確認してください。質問に答えてくれるはずです。

基本的な考え方

function plot(x, y, c) is
plot the pixel at (x, y) with brightness c (where 0 ≤ c ≤ 1)

function ipart(x) is
return integer part of x

function round(x) is
return ipart(x + 0.5)

function fpart(x) is
return fractional part of x

function rfpart(x) is
return 1 - fpart(x)

function drawLine(x1,y1,x2,y2) is
dx = x2 - x1
dy = y2 - y1
if abs(dx) < abs(dy) then                 
  swap x1, y1
  swap x2, y2
  swap dx, dy
end if
if x2 < x1
  swap x1, x2
  swap y1, y2
end if
gradient = dy / dx

// handle first endpoint
xend = round(x1)
yend = y1 + gradient * (xend - x1)
xgap = rfpart(x1 + 0.5)
xpxl1 = xend  // this will be used in the main loop
ypxl1 = ipart(yend)
plot(xpxl1, ypxl1, rfpart(yend) * xgap)
plot(xpxl1, ypxl1 + 1, fpart(yend) * xgap)
intery = yend + gradient // first y-intersection for the main loop

// handle second endpoint
xend = round (x2)
yend = y2 + gradient * (xend - x2)
xgap = fpart(x2 + 0.5)
xpxl2 = xend  // this will be used in the main loop
ypxl2 = ipart (yend)
plot (xpxl2, ypxl2, rfpart (yend) * xgap)
plot (xpxl2, ypxl2 + 1, fpart (yend) * xgap)

// main loop
for x from xpxl1 + 1 to xpxl2 - 1 do
    plot (x, ipart (intery), rfpart (intery))
    plot (x, ipart (intery) + 1, fpart (intery))
    intery = intery + gradient
end function
于 2012-08-14T13:23:21.957 に答える