Проблема с Android с поворотом изображения и матрицей - PullRequest
1 голос
/ 16 ноября 2010

Надеюсь, это легко, потому что я пытался разными способами избавиться от этого.

Я делаю приложение для Android, которое включает в себя анимацию часов. У меня все работает очень хорошо, кроме одной очень раздражающей вещи.

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

        public float secdegrees, secondwidth, secondheight;

        secondMatrix = new Matrix();
        secondwidth = secondHand.getWidth();
        secondheight = secondHand.getHeight();
        secdegrees = anglepersec * secnow;
        secdegrees += anglepluspermilli * millis;
        secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
        newSecond = Bitmap.createBitmap(secondHand, 0, 0,
               (int) secondwidth, (int) secondheight, secondMatrix, true);
        c.drawBitmap(newSecond, (centrex - newSecond.getWidth()/2),
               ((face.getHeight()/2) - newSecond.getHeight()/2), null);

Это на самом деле делает ту работу, которую я хочу ... почти.

Проблема в том, что руки слегка дрожат / покачиваются вокруг центральной точки, но это действительно заметно и действительно портит эстетику.

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

Для справки: изображение секундной стрелки изначально имело размеры 74 пикселя x 28 пикселей и (в настоящее время) составляет 74 x 74 пикселя .png, при этом середина секундной стрелки точно пересекает точку пересечения. Я также попытался сделать его 75 х 75, чтобы на самом деле был центральный пиксель, но не повезло.

Буду признателен за любую помощь.

** ОБНОВЛЕНИЕ

Я пытался изменить код в случае, если десятичные дроби сбрасывались, но я все еще не повезло, я боюсь. Вот вариант 2, который я пробовал и потерпел неудачу;

        secondMatrix = new Matrix();
        secondwidth = secondHand.getWidth();
        secondheight = secondHand.getHeight();
        secdegrees = anglepersec * secnow;
        secdegrees += anglepluspermilli * millis;
        secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
        newSecond = Bitmap.createBitmap(secondHand, 0, 0, (int) secondwidth,
              (int) secondheight, secondMatrix, true);
        float secW = newSecond.getWidth()/2;
        float secH = newSecond.getHeight()/2;

        // NEW CODE HERE
        float calcdeg = secdegrees % 90;
        calcdeg = (float) Math.toRadians(calcdeg);
        float NegY = (float) ((secondwidth*Math.cos(calcdeg)) +
             (secondwidth * Math.sin(calcdeg)));
        c.drawBitmap(newSecond, centrex - NegY/2,
              ((face.getHeight()/2) - NegY/2), null);

1 Ответ

0 голосов
/ 06 декабря 2010

Я понимаю вашу проблему, я никогда не сталкивался с ней, но это звучит довольно очевидно для меня. Поскольку при поворотах изменяется ширина и высота изображения, ваша неточность исходит из centrex - NegX/2

Я не проверял, но я предлагаю вам попробовать:

Matrix matrix=new Matrix()
//first translate to place the center of the hand at Point(0,0)
matrix.setTranslate(-secondWidth/2,-secondHeight/2);
matrix.setRotate(secdegrees);
//now place the pivot Point(0,0) at its expected location
matrix.setTranslate(centreX,centreY);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,0,0,null);

Конечно, это неоптимально, поскольку битовая карта newSecond намного больше, чем должна быть на самом деле. Поэтому, если ваш centrex и centrey большие, вы можете перевести меньше, а затем нарисовать с переводом разницы.

//now place the pivot to a position where the hand can be fully drawn without imprecion on the future location of Point(0,0)
matrix.setTranslate(secondWith,secondHeight);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,centrex-secondWidth,centrey-secondHeight,null);

Надеюсь, это поможет.

...