没有的AffineTransform转化中风? [英] AffineTransform without transforming Stroke?

查看:334
本文介绍了没有的AffineTransform转化中风?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当使用具有两个不同的参数时,Graphics2D 尺度()功能(通过在x方向和y方向上不同的比例缩放),一切以后绘制此Graphics2D对象上规模太大。这具有这样的奇效,在一个方向上绘制的线条比在另一个方向更厚。下面的程序产生该效果,显示了这个窗口:

When using the Graphics2D scale() function with two different parameters (scaling by different ratios in x- and y-direction), everything drawn later on this Graphics2D object is scaled too. This has the strange effect that lines drawn in one direction are thicker than those in another direction. The following program produces this effect, it shows this window:

public class StrokeExample extends JPanel {


    public void paintComponent(Graphics context) {
        super.paintComponent(context);
        Graphics2D g = (Graphics2D)context.create();
        g.setStroke(new BasicStroke(0.2f));

        int height = getHeight();
        int width = getWidth();

        g.scale(width/7.0, height/4.0);

        g.setColor(Color.BLACK);
        g.draw(new Rectangle( 2, 1, 4, 2));
    }

    public static void main(String[] params) {
        EventQueue.invokeLater(new Runnable(){public void run() {

            StrokeExample example = new StrokeExample();

            JFrame f = new JFrame("StrokeExample");
            f.setSize(100, 300);
            f.getContentPane().setLayout(new BorderLayout());
            f.getContentPane().add(example);
            f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
            f.setVisible(true);
        }});

    }

}

我使用这个坐标变换,以避免手动变换(在这个例子中(2,1,2,4))我的应用程序模型坐标屏幕(或组件)像素坐标,但是我不希望这个行程失真。换句话说,我想都行相同的宽度,独立的电流x轴和y规模的因素。

I'm using this coordinate transform to avoid having to manually transform my application model coordinates (the (2,1, 2,4) in this example) to screen (or component) pixel coordinates, but I don't want this stroke distortion. In other words, I want to have all lines the same width, independent of current x- and y-scale-factors.

我知道这会产生的影响(Stroke对象创建矩形的抚摸外形在用户坐标,然后被转换为屏幕坐标画),但我不知道如何解决这个问题。

I know what produces this effect (the Stroke object creates a stroked shape of the rectangle to be painted in user coordinates, which then are translated to screen coordinates), but I'm not sure on how to solve this.


  • 我应该创建一个新的Stroke实现这招不同的形状,X和Y方向(从而撤消失真这里)? (或有没有人已经知道这样的实现?)

  • 我应该改变我的形状,屏幕坐标和中风呢?

  • 任何其他(更好)的想法吗?

推荐答案

原来我的问题不是那么可怕的困难,我在这个问题给出了两个观点其实是同样的想法。下面是它实现了一个 TransformedStroke 类扭曲行程通过变换图形

Turns out my question was not so horrible difficult, and that my two ideas given in the question are actually the same idea. Here is a TransformedStroke class which implements a distorted Stroke by transforming the Shape.

import java.awt.*;
import java.awt.geom.*;


/**
 * A implementation of {@link Stroke} which transforms another Stroke
 * with an {@link AffineTransform} before stroking with it.
 *
 * This class is immutable as long as the underlying stroke is
 * immutable.
 */
public class TransformedStroke
    implements Stroke
{
    /**
     * To make this serializable without problems.
     */
    private static final long serialVersionUID = 1;

    /**
     * the AffineTransform used to transform the shape before stroking.
     */
    private AffineTransform transform;
    /**
     * The inverse of {@link #transform}, used to transform
     * back after stroking.
     */
    private AffineTransform inverse;

    /**
     * Our base stroke.
     */
    private Stroke stroke;


    /**
     * Creates a TransformedStroke based on another Stroke
     * and an AffineTransform.
     */
    public TransformedStroke(Stroke base, AffineTransform at)
        throws NoninvertibleTransformException
    {
        this.transform = new AffineTransform(at);
        this.inverse = transform.createInverse();
        this.stroke = base;
    }


    /**
     * Strokes the given Shape with this stroke, creating an outline.
     *
     * This outline is distorted by our AffineTransform relative to the
     * outline which would be given by the base stroke, but only in terms
     * of scaling (i.e. thickness of the lines), as translation and rotation
     * are undone after the stroking.
     */
    public Shape createStrokedShape(Shape s) {
        Shape sTrans = transform.createTransformedShape(s);
        Shape sTransStroked = stroke.createStrokedShape(sTrans);
        Shape sStroked = inverse.createTransformedShape(sTransStroked);
        return sStroked;
    }

}

使用它,然后我的油漆的方法是这样的:

My paint-method using it then looks like this:

public void paintComponent(Graphics context) {
    super.paintComponent(context);
    Graphics2D g = (Graphics2D)context.create();

    int height = getHeight();
    int width = getWidth();

    g.scale(width/4.0, height/7.0);

    try {
        g.setStroke(new TransformedStroke(new BasicStroke(2f),
                                          g.getTransform()));
    }
    catch(NoninvertibleTransformException ex) {
        // should not occur if width and height > 0
        ex.printStackTrace();
    }

    g.setColor(Color.BLACK);
    g.draw(new Rectangle( 1, 2, 2, 4));
}

然后我的窗口如下所示:

Then my window looks like this:

我与此相当的内容,但如果有人有更多的想法,随时不过来回答。

I'm quite content with this, but if someone has more ideas, feel free to answer nevertheless.

注意: g.getTransform()将退回的完整的转型的先按g 相对于设备空间,不仅改造后的 .create()应用。因此,如果有人给图形到我的组件之前做了一些扩展,这将仍然以2设备像素宽度的行程画,而不是2个像素给我的方法grapics的。如果这将是一个问题,使用这样的:

Attention: This g.getTransform() is returning the complete transformation of g relative to the device space, not only the transformation applied after the .create(). So, if someone did some scaling before giving the Graphics to my component, this would still draw with a 2-device-pixel width stroke, not 2 pixels of the grapics given to my method. If this would be a problem, use it like this:

public void paintComponent(Graphics context) {
    super.paintComponent(context);
    Graphics2D g = (Graphics2D)context.create();

    AffineTransform trans = new AffineTransform();

    int height = getHeight();
    int width = getWidth();

    trans.scale(width/4.0, height/7.0);
    g.transform(trans);

    try {
        g.setStroke(new TransformedStroke(new BasicStroke(2f),
                                          trans));
    }
    catch(NoninvertibleTransformException ex) {
        // should not occur if width and height > 0
        ex.printStackTrace();
    }

    g.setColor(Color.BLACK);
    g.draw(new Rectangle( 1, 2, 2, 4));
}

在摇摆通常是您给图形的的paintComponent 只翻译(​​所以(0,0)是组件的左上角),不进行缩放,所以有是没有区别的。

In Swing normally your Graphics given to the paintComponent is only translated (so (0,0) is the upper left corner of your component), not scaled, so there is no difference.

这篇关于没有的AffineTransform转化中风?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆