Система координат Android Canvas

Пытаюсь найти информацию о том, как изменить систему координат холста. У меня есть векторные данные, которые я хотел бы нарисовать на холсте, используя такие вещи, как круги и линии, но система координат данных не соответствует системе координат холста.

Есть ли способ сопоставить единицы измерения, которые я использую, с единицами измерения экрана?

Я рисую в ImageView, который не занимает весь экран.

Если перед каждым вызовом рисования мне приходится выполнять свои собственные вычисления, как определить ширину и высоту своего ImageView?

Вызовы getWidth () и getHeight (), которые я пытался, похоже, возвращают весь размер холста, а не размер ImageView, что бесполезно.

Я вижу кое-что из матрицы. Мне это подойдет?

Я попытался использовать «общедоступную шкалу пустот (float sx, float sy)», но она больше похожа на масштабирование на уровне пикселей, чем на функцию векторного масштабирования, увеличивая каждый пиксель. Это означает, что если размеры увеличиваются до размеров экрана, толщина линии также увеличивается.


Обновлять:

После некоторого исследования я начинаю думать, что нет возможности изменить систему координат на что-то другое. Мне нужно сопоставить все мои координаты с координатами пикселей экрана и сделать это, изменив каждый вектор. Мне кажется, что getWidth () и getHeight () теперь лучше работают. Я могу сказать, что было не так, но подозреваю, что не могу использовать эти методы внутри конструктора.


person Mitch    schedule 28.05.2010    source источник
comment
Да, getWidth () и getHeight () точно не работают внутри конструктора.   -  person Mitch    schedule 13.06.2010


Ответы (3)


Спасибо за ответ. Я в значительной степени отказался от того, чтобы заставить это работать так, как я думаю. Конечно, я думаю, что вещи должны происходить не так, как они происходят. :)

Вот в основном то, как это работает, но в некоторых случаях кажется, что это не так, как пиксель, и кажется, что кружки пропускают секции, когда что-то попадает в некоторые граничные условия, которые мне еще предстоит выяснить. Лично я считаю, что недопустимо находиться внутри кода приложения и должно быть в библиотеках 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);
    }
...
}
person Mitch    schedule 13.06.2010
comment
Извините за форматирование кода для моего кода. Код выглядит великолепно до того, как я публикую, но после того, как StackOverflow, похоже, совершает какие-то сумасшедшие вещи. - person Mitch; 13.06.2010

Вы можете масштабировать координаты холста до ваших собственных единиц, используя метод preScale() матрицы холста. Однако имейте в виду, что это также масштабирует ширину обводки Paint, что может быть не тем, что вам нужно.

person Rich    schedule 16.04.2011

Единственный известный мне способ создать пользовательскую векторную графику на лету в Android - это отрисовать все в файл изображения, а затем поместить его в ImageView. Я не уверен, что правильно понимаю, о чем вы спрашиваете, но если единственная проблема - масштабирование, ImageView будет масштабировать любое изображение, которое ему дано, до его собственного размера, используя android:scaleType="center" как свойство ImageView.

Что касается изменения системы координат, я сомневаюсь, что это возможно (хотя я не исследовал это). Однако было бы довольно тривиально написать функцию, которая отображала бы систему ваших данных в стандартную систему координат Android.

person Computerish    schedule 11.06.2010