2009-07-07 37 views
22

Tôi đã thử sử dụng phương thức drawOval với chiều cao và chiều rộng bằng nhau nhưng khi đường kính tăng vòng tròn trở nên tệ hơn. Những gì tôi có thể làm để có một vòng tròn tìm kiếm phong nha không có vấn đề kích thước. Làm thế nào tôi sẽ thực hiện chống răng cưa trong java hoặc một số phương pháp khác.Làm thế nào để vẽ một vòng tròn tìm kiếm phong nha trong Java

Trả lời

37

Khi nó quay ra, Java2D (mà tôi giả sử là những gì bạn đang sử dụng) đã khá tốt ở đây! Có một hướng dẫn đàng hoàng ở đây: http://www.javaworld.com/javaworld/jw-08-1998/jw-08-media.html

Điểm mấu quan trọng là:

graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
          RenderingHints.VALUE_ANTIALIAS_ON); 
+4

Bạn phải yêu các liên kết 11 tuổi, hy vọng chúng sẽ không bao giờ chết. –

+16

Dường như các hằng số đã được chuyển từ Graphics2D sang RenderingHints. Xem [ví dụ này] (http://www.java2s.com/Code/JavaAPI/java.awt/Graphics2DsetRenderingHintKeyhintKeyObjecthintValue.htm). –

+1

Đã 17 tuổi rồi ... vẫn còn sống xD lol – maganap

27

bạn có thể đặt gợi ý render:

Graphics2D g2 = (Graphics2D) g; 
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 
    RenderingHints.VALUE_ANTIALIAS_ON); 
12

Hai điều đó có thể giúp:

  1. Sử dụng Graphics2D.draw(Shape) với một thể hiện của java.awt.geom.Ellipse2D thay vì Graphics.drawOval
  2. Nếu kết quả vẫn chưa đạt yêu cầu, hãy thử sử dụng Graphics2D.setRenderingHint để bật tính năng chống răng cưa

Ví dụ

public void paint(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 
    Shape theCircle = new Ellipse2D.Double(centerX - radius, centerY - radius, 2.0 * radius, 2.0 * radius); 
    g2d.draw(theCircle); 
} 
câu trả lời

Xem Josef cho một ví dụ về setRenderingHint

6

Tất nhiên bạn thiết lập bán kính của bạn với những gì mà bạn cần:

@Override 
public void paint(Graphics g) { 
    Graphics2D g2d = (Graphics2D) g; 
    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); 
    g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); 
    Ellipse2D.Double hole = new Ellipse2D.Double(); 
    hole.width = 28; 
    hole.height = 28; 
    hole.x = 14; 
    hole.y = 14; 
    g2d.draw(hole); 
} 
+0

Bạn cũng cần phải đặt vị trí của hình elip, và tôi nghĩ bạn muốn g2d.draw không g2d.stroke – finnw

3

Không có khả năng để vẽ một "vòng tròn trai đàng hoàng" có liên quan đến lỗi rất cũ 6431487.

Biến tính khử răng cưa không giúp ích nhiều - chỉ cần kiểm tra loại "vòng tròn" được tạo bởi drawOval() hoặc drawShape (Eclipse) khi kích thước vòng tròn yêu cầu là 16 pixel (vẫn khá phổ biến đối với kích thước biểu tượng) và chống răng cưa đang bật. Các vòng tròn chống răng cưa lớn hơn sẽ trông đẹp hơn nhưng chúng vẫn không đối xứng, nếu ai đó sẽ quan tâm đến chúng một cách chặt chẽ.

Dường như để vẽ "vòng tròn tìm kiếm phong nha", người ta phải vẽ một cách thủ công. Nếu không có antialiasing nó sẽ là trung điểm vòng tròn thuật toán (điều này question có một câu trả lời với một mã java khá cho nó).

-1

CHỈNH SỬA: 06 tháng 9 năm 2017

Đó là thuật toán do tôi tạo ra để vẽ vòng tròn trên ma trận số nguyên. Ý tưởng tương tự có thể được sử dụng để viết một vòng tròn bên trong BufferedImage. Nếu bạn đang cố gắng vẽ vòng tròn đó bằng cách sử dụng lớp Đồ họa, đây không phải là phần mềm answare bạn đang tìm kiếm (trừ khi bạn muốn sửa đổi từng màu gán với g.drawLine (x, y, x + 1, y), nhưng nó có thể rất chậm).

protected boolean runOnCircumference(int[][] matrix, int x, int y, int ray, int color) { 
    boolean ret; 
    int[] rowUpper = null, rowInferior = null, rowCenterUpper = null, rowCenterInferior = null; 

    if (ret = ray > 0) { 
     if (ray == 1) { 
      matrix[y][x + 1] = color; 
      rowUpper = matrix[++y]; 
      rowUpper[x] = color; 
      rowUpper[x + 2] = color; 
      matrix[y][x] = color; 
     } else { 
      double rRay = ray + 0.5; 
      int r = 0, c = 0, ray2 = ray << 1, ray_1 = ray - 1, halfRay = (ray >> 1) + ray % 2, rInf, 
        ray1 = ray + 1, horizontalSymmetricOldC; 
      // draw cardinal points 

      rowUpper = matrix[ray + y]; 
      rowUpper[x] = color; 
      rowUpper[x + ray2] = color; 
      matrix[y][x + ray] = color; 
      matrix[ray2 + y][x + ray] = color; 

      horizontalSymmetricOldC = ray1; 
      rInf = ray2; 
      c = ray_1; 
      for (r = 0; r < halfRay; r++, rInf--) { 

       rowUpper = matrix[r + y]; 
       rowInferior = matrix[rInf + y]; 

       while (c > 0 && (Math.hypot(ray - c, (ray - r)) < rRay)) { 

        rowUpper[x + c] = color; 
        rowUpper[x + horizontalSymmetricOldC] = color; 
        rowInferior[x + c] = color; 
        rowInferior[x + horizontalSymmetricOldC] = color; 

        // get the row pointer to optimize 
        rowCenterUpper = matrix[c + y]; 
        rowCenterInferior = matrix[horizontalSymmetricOldC + y]; 
        // draw 
        rowCenterUpper[x + r] = color; 
        rowCenterUpper[x + rInf] = color; 
        rowCenterInferior[x + r] = color; 
        rowCenterInferior[x + rInf] = color; 
        horizontalSymmetricOldC++; 
        c--; 
       } 
      } // end r circle 
     } 
    } 
    return ret; 
} 

Tôi đã thử rất nhiều lần, xác minh thủ công chính xác, vì vậy tôi nghĩ nó sẽ hoạt động. Tôi đã không thực hiện bất kỳ kiểm tra phạm vi chỉ để đơn giản hóa mã. Tôi hy vọng nó sẽ giúp bạn và mọi người muốn vẽ một vòng tròn trên một ma trận (ví dụ, những lập trình viên cố gắng tạo ra trò chơi điện tử của riêng mình trên mã thuần túy và cần quản lý bản đồ trò chơi theo ma trận để lưu trữ các đối tượng nằm trên bản đồ trò chơi [nếu bạn cần trợ giúp về điều này, hãy gửi email cho tôi]).

3

Nhờ Oleg Estekhin đã chỉ ra báo cáo lỗi, vì nó giải thích cách thực hiện.

Dưới đây là một số vòng kết nối nhỏ trước và sau. Đã phóng to một vài lần để xem lưới pixel.

Circles before and after

Giảm xuống một hàng, chúng di chuyển nhẹ bằng số lượng subpixel.

Cột đầu tiên không có gợi ý hiển thị. Thứ hai là chỉ với antialias. Thứ ba là với antialias và chế độ thuần túy.

Lưu ý cách đề xuất chống răng cưa chỉ, ba vòng kết nối đầu tiên giống nhau và hai vòng kết nối đầu tiên cũng giống nhau. Dường như có một số chuyển đổi rời rạc xảy ra. Có lẽ làm tròn tại một số điểm.

Đây là mã. Đó là trong Jython cho dễ đọc, nhưng nó ổ đĩa thư viện thời gian chạy Java bên dưới và có thể được losslessly chuyển đến nguồn Java tương đương, với chính xác cùng một hiệu ứng.

from java.lang import * 
from java.io import * 
from java.awt import * 
from java.awt.geom import * 
from java.awt.image import * 
from javax.imageio import * 

bim = BufferedImage(30, 42, BufferedImage.TYPE_INT_ARGB) 
g = bim.createGraphics() 
g.fillRect(0, 0, 100, 100) 
g.setColor(Color.BLACK) 
for i in range(5): 
    g.draw(Ellipse2D.Double(2+0.2*i, 2+8.2*i, 5, 5)) 

g.setRenderingHint(RenderingHints. KEY_ANTIALIASING, 
        RenderingHints.VALUE_ANTIALIAS_ON) 

for i in range(5): 
    g.draw(Ellipse2D.Double(12+0.2*i, 2+8.2*i, 5, 5)) 

g.setRenderingHint(RenderingHints. KEY_STROKE_CONTROL, 
        RenderingHints.VALUE_STROKE_PURE) 

for i in range(5): 
    g.draw(Ellipse2D.Double(22+0.2*i, 2+8.2*i, 5, 5)) 

#You'll probably want this too later on: 
#g.setRenderingHint(RenderingHints. KEY_INTERPOLATION, 
#     RenderingHints.VALUE_INTERPOLATION_BICUBIC) 
#g.setRenderingHint(RenderingHints. KEY_RENDERING, 
#     RenderingHints.VALUE_RENDER_QUALITY) 

ImageIO.write(bim, "PNG", File("test.png")) 

Tóm tắt: bạn cần cả hai VALUE_ANTIALIAS_ONVALUE_STROKE_PURE để có được hợp tìm kiếm vòng tròn được vẽ với độ chính xác subpixel.

Các vấn đề liên quan