2

我正在尝试使用 Java2D 绘制地图。当我的地图被缩小时,我的道路上到处都是绘画文物。这是绘制完整美国州时屏幕的一小部分:

以州级比例绘制的道路部分,展示了绘画文物

放大后,这是一段类似的路段:

以县级尺度绘制的路段,无绘图文物

使用的线条样式是一条蓝色实线,宽度缩放为 2 个像素。我尝试了各种渲染提示和线连接规则,但似乎没有任何帮助。

我在运行 OS/X 10.8 的 Mac 上使用 Open JDK 1.7,这也可以在装有 Sun JDK 1.6 的 Linux 机器上重现。

Java2D 中的所有形状和变换都尽可能是双精度的。线条的几何形状有许多相距很近的点,我怀疑绘图伪影的原因是渲染器被比单个像素更近的连续点弄糊涂了。

有没有办法在不细化点的情况下改善缩小形状的外观?

编辑 绘图伪影位于单独的线段相交的点,因此丢失的像素与线帽(末端)不相交有关,即使端点相同。此图像显示了两条线段之间的交汇点。我已经以 7 像素缩放的线条样式(与白色异或)突出显示了每个线段,但如果您仔细观察,您仍然可以看到原始蓝线的一部分(这是由于圆顶重叠和 XOR 绘制模式.) 在普通比例下,两端似乎重叠,但在普通绘画模式下缩小和返回时,会出现断线效果。

一种解决方法是在绘制之前将所有连续的线段连接在一起,但我仍然想知道绘制伪影的真正原因。

在两个路段之间连接

4

2 回答 2

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 回答
1

我无法重现您使用 OS X 1.6 JDK 的情况,但我仍有一些建议给您。

如果您只是使用它来概述状态,请考虑使用GeneralPathclass。您可以使用该lineTo(x,y)方法在线上建立每个点。同样,因为我无法使用 重新创建您的问题Line2D.Double,所以我不知道这是否真的会有所不同。

其次,可能更重要的是,你是如何放大和缩小的。我在我的对象上使用AffineTransform(with setScaleTo(x,y)) Graphics2D,一切都在顺利进行。与通过缩放因子(或您可以做的任何其他事情)缩放数据中的点的替代方法相比,这相当容易。您还必须按因子调整线条的笔触,因为它会缩小所有内容。如果您愿意,我可以发布屏幕截图。

于 2012-08-15T01:53:01.917 回答