安卓画布坐标系统

5
我正在寻找如何更改画布的坐标系的信息。我有一些矢量数据,想要使用圆和线条绘制到画布上,但是数据的坐标系与画布的坐标系不匹配。 是否有一种方法可以将我使用的单位映射到屏幕的单位? 我正在绘制一个未占据整个显示屏的ImageView。 如果我必须在每次绘制调用之前进行自己的计算,如何找到我的ImageView的宽度和高度? 我尝试了getWidth()和getHeight()调用,但似乎返回的是整个画布的大小而不是ImageView的大小,这对我没有帮助。 我看到一些矩阵相关的东西,那是对我有用的吗? 我尝试使用"public void scale(float sx, float sy)",但这更像是像素级缩放而不是向量缩放函数,通过扩展每个像素来实现。这意味着如果将尺寸增加以适应屏幕,则线条粗细也会增加。
更新:
经过一些研究,我开始认为没有办法将坐标系更改为其他内容。我需要将所有坐标映射到屏幕的像素坐标,并通过修改每个矢量来实现。getWidth()和getHeight()现在对我来说效果更好了。我可以说出问题所在,但我怀疑我无法在构造函数中使用这些方法。

是的,getWidth()和getHeight()肯定不能在构造函数中使用。 - Mitch
3个回答

2
感谢回复。我已经放弃了让它按照我想的方式工作的想法。当然,我认为事情应该是怎样发生的并不是它们实际发生的方式。 :)
以下是基本的工作原理,但在某些情况下似乎会有一个像素的偏差,并且当物体着陆在我尚未解决的某些边界条件上时,圆圈似乎会缺少一些部分。 我个人认为这在应用程序代码中是不可接受的,应该放入Android库中...如果你在Google工作的话,请注意了。 :)
private class LinearMapCanvas
{
    private final Canvas canvas_; // hold a wrapper to the actual canvas.

    // scaling and translating values:
    private double scale_;

    private int translateX_;
    private int translateY_;

// linear mapping from my coordinate system to the display's:
    private double mapX(final double x)
    {
    final double result = translateX_ + scale_*x;
    return result;
    }

    private double mapY(final double y)
    {
        final double result = translateY_ - scale_*y;
        return result;
    }

    public LinearMapCanvas(final Canvas canvas)
    {
        canvas_ = canvas;

// Find the extents of your drawing coordinates:
        final double minX = extentArray_[0];
    final double minY = extentArray_[1];
    final double maxX = extentArray_[2];
    final double maxY = extentArray_[3];

// deltas:
    final double dx = maxX - minX;
    final double dy = maxY - minY;

// The display's available pixels, accounting for margins and pen stroke width:
    final int width = width_ - strokeWidth_ - 2*margin_;
    final int height = height_ - strokeWidth_ - 2*margin_;

    final double scaleX = width / dx;
    final double scaleY = height / dy;

    scale_ = Math.min(scaleX , scaleY); // Pick the worst case, so the drawing fits

// Translate so the image is centered:
        translateX_ = (int)((width_ - (int)(scale_*dx))/2.0 - scale_*minX);
        translateY_ = (int)((height_ - (int)(scale_*dy))/2.0 + scale_*maxY);
    }

// wrappers around the canvas functions you use.  These are only two of many that would need to be wrapped.  Annoying and error prone, but beats any alternative I can find.
    public void drawCircle(final float cx, final float cy, final float radius, final Paint paint)
    {
    canvas_.drawCircle((float)mapX(cx), (float)mapY(cy), (float)(scale_*radius), paint);
    }

    public void drawLine(final float startX, final float startY, final float stopX, final float stopY, final Paint paint)
    {
    canvas_.drawLine((float)mapX(startX), (float)mapY(startY), (float)mapX(stopX), (float)mapY(stopY), paint);
    }
...
}

抱歉我的代码格式可能有些混乱。在我发布之前,代码看起来很好,但是在 StackOverflow 上似乎会出现一些奇怪的问题。 - Mitch

1

您可以使用画布矩阵的preScale()方法将画布坐标缩放到自己的单位。但请注意,这也会缩放Paint的描边宽度,这可能不是您想要的。


0
我所知道的在Android上实时绘制自定义矢量图形的唯一方法是将所有内容绘制到图像文件中,然后将其放入ImageView中。我不确定您确切地想要什么,但如果唯一的问题是缩放,ImageView将使用android:scaleType="center"作为ImageView的属性来缩放其所给定的任何图像到其自身大小。
至于更改坐标系,我怀疑这是不可能的(尽管我没有进行过研究)。不过编写一个函数将您的数据系统映射到标准的Android坐标系可能相当简单。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接