3

この質問は、私が以前に尋ねた質問のフォローアップです 。Javaで鋭い角を持つ境界のあるパスを描く

実験の結果、意図された、またはバグである可能性のある動作を発見しましたが、どちらの方法も私には望まれていません。SSCCE:

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.GeneralPath;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class CornerTest {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CornerTest window = new CornerTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public CornerTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel() {
            protected void paintComponent(Graphics g) {
                GeneralPath path;
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setStroke(new BasicStroke(15.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.setColor(Color.BLACK);
                path = new GeneralPath();
                path.moveTo(100, 100);
                path.lineTo(200, 100);
                path.lineTo(100, 50);
                g2d.draw(path);
            }
        };
        frame.setBackground(Color.CYAN);
        frame.add(panel);
    }
}

path.lineTo(100, 50);を引き、2番目の引数で遊ぶことにより、描画されるパスの角度を変更できます。さまざまな例については、以下の画像を参照してください。

ここに画像の説明を入力してください

基本的にはGeneralPath、各画像で角度を少し小さくして描いています。最終的に(下の画像で)角度はゼロに達します。この場合、丸みを帯びた「結合」はペイントされなくなります。この種の意味はありますが、そうではありません。それが意図されているかどうかはわかりません。興味深いことに、角度を0より少し大きく変更すると(つまり、上記の線をpath.lineTo(100, 99.999);丸みを帯びた角に変更すると、再び描画されます。

私のアプリケーションでは、パスが二重に戻る(つまり、0度の角度を作成する)ことが可能です。この場合、このような場合に結合ラウンドを描画する方が、美的にはるかに魅力的です。これを機能させるためにJavaソースをハックする方法はありますか?

4

2 に答える 2

3

500以上のポイントを含む非常に長いパスを描画しています。これにより、各「サブパス」をチェックするためのペイントメソッドに多くのオーバーヘッドが追加されます。

paintメソッドでGeneralPathを作成しないでください。追加された各ポイントをフィルタリングするラッパークラスを使用できます。ここのコードは、ポイントが追加されるたびに線の傾きを比較します。勾配が同じである場合、が追加さmoveToれる前の最後のポイントに対してaが生成されます。lineToこれにより、ラウンドストロークが生成されます。

import java.awt.*;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.*;
import java.util.List;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class CornerTest {
    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    CornerTest window = new CornerTest();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public CornerTest() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setBounds(100, 100, 450, 450);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final GeneralPath gp = new GeneralPath();
        MyGeneralPath path = new MyGeneralPath(gp);
        path.moveTo(100, 100);
        path.lineTo(200, 100);
        path.lineTo(100, 50);
//        path.lineTo(50, 100);
        path.flush();


        JPanel panel = new JPanel() {
            protected void paintComponent(Graphics g) {
                Graphics2D g2d = (Graphics2D) g;
                g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                        RenderingHints.VALUE_ANTIALIAS_ON);
                g2d.setStroke(new BasicStroke(15.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND));
                g2d.setColor(Color.BLACK);
                g2d.draw(gp);
            }
        };
        frame.setBackground(Color.CYAN);
        frame.add(panel);
    }

    static class MyGeneralPath
    {
        private GeneralPath path;
        private List<Point2D.Double> points = new ArrayList<Point2D.Double>();

        public MyGeneralPath(GeneralPath path)
        {
            this.path = path;
        }

        public void moveTo(double x, double y)
        {
            flush();
            points.add( new Point2D.Double(x, y) );
        }

        public void lineTo(double x, double y)
        {
            Point2D.Double point = new Point2D.Double(x, y);

            checkSlope(point);

            points.add( point );
        }

        private void checkSlope(Point2D.Double p3)
        {
            int size = points.size();

            if (size < 2 )
                return;

            Point2D.Double p2 = points.get(size - 1);
            Point2D.Double p1 = points.get(size - 2);

            double slope1 = (p2.getY() - p1.getY()) / (p2.getX() - p1.getX());
            double slope2 = (p3.getY() - p2.getY()) / (p3.getX() - p2.getX());

            if (slope1 == slope2)
                moveTo(p2.getX(), p2.getY());
        }

        public void flush()
        {
            int size = points.size();

            if (size == 0)
                return;

            Point2D.Double point = points.get(0);
            path.moveTo(point.getX(), point.getY());

            for (int i = 1; i < size; i++)
            {
                point = points.get(i);
                path.lineTo(point.getX(), point.getY());
            }

            points.clear();
        }
    }
}
于 2013-03-23T04:47:17.750 に答える
2

ソースのハッキングについてはわかりませんが、1本の線を引くだけで、この動作を考慮してコードをカスタマイズできる可能性があります。

path = new GeneralPath();
path.moveTo(100, 100);
path.lineTo(200, 100);
path.lineTo(50, 100);

Rectangle bounds = path.getBounds();

if (bounds.height == 0)
{
    path = new GeneralPath();
    path.moveTo(bounds.x, bounds.y);
    path.lineTo(bounds.x + bounds.width, bounds.y);
}

if (bounds.width == 0)
{
    path = new GeneralPath();
    path.moveTo(bounds.x, bounds.y);
    path.lineTo(bounds.x, bounds.y + bounds.height);
}

g2d.draw(path);
于 2013-03-23T01:29:44.250 に答える