Математика, чтобы получить относительный масштаб из уровня стека - PullRequest
0 голосов
/ 12 февраля 2012

Извинения за ужасное название. Я потратил 10 минут, пытаясь объяснить это в одном предложении, и потерпел неудачу.

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

Мое фактическое требование структурировано немного проще, чем некоторые из следующих примеров, но я постараюсь изложить идею просто и ясно.

Скажем, у меня есть 5 "уровней изображения", каждый уровень в два раза больше предыдущего уровня:

  • уровень 1 = квадрат 100px
  • уровень 2 = 200px квадрат
  • уровень 3 = 400px квадрат
  • уровень 4 = 800px квадрат
  • уровень 5 = ​​1600px квадратный

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

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

Допустим, пользователь находится на уровне 3 (400 пикселей) и выполняет операцию масштабирования до 1,8. Новый размер будет (1,8 * 400 = 720), что означает, что я должен показать уровень 4 (800px), масштабированный до 0,9 (800 * 0,9 = 720).

Другой пример - пользователь находится на уровне 2 и масштабируется до 5,2. Размер будет (5,2 * 200 = 1040). Поэтому покажите уровень 5, масштабированный до 0,65 (1600 * 0,65 = 1040).

Зная размеры уровней, логика довольно проста.

  1. Возьмите размер текущего уровня, умножьте его на пользовательский масштаб. Назовите это newSize
  2. Найдите самый низкий уровень, размер которого больше этого числа. Назовите это targetLevel
  3. Разделите newSize на размер targetLevel. Это относительная шкала.

Теперь, допустим, я на самом деле не знаю фактических размеров изображений, и нет никакого способа получить к ним доступ, и, возможно, они не совсем соответствуют размеру, который они должны быть (хотя они всегда будут вдвое больше, чем предыдущие уровень), и может быть любое количество уровней.

Используя только текущий уровень и определенное пользователем значение шкалы, какая математика или логика используется для получения соответствующего целевого уровня и его относительной (новой) шкалы?

Больше примеров ...

  • Пользователь на уровне 5 масштабируется до 0,2. Новый уровень должен быть 3, новая шкала должна быть 0,8
  • Пользователь на уровне 1 масштабируется до 3,6. Новый уровень должен быть 3, новая шкала должна быть 0,9
  • Пользователь на уровне 1 масштабируется до 5,0. Новый уровень должен быть 4, новый масштаб должен быть 0,625
  • Пользователь на уровне 2 масштабируется до 5,0. Новый уровень должен быть 5, новый масштаб должен быть 0,625
  • Пользователь на уровне 3 масштабируется до 3,0. Новый уровень должен быть 5, новая шкала должна быть 0,75
  • Пользователь на уровне 4 масштабируется до 0,3. Новый уровень должен быть 3, новый масштаб должен быть 0,6
  • Пользователь на уровне 4 масштабируется до 1,6. Новый уровень должен быть 5, новая шкала должна быть 0,8
  • Пользователь на уровне 4 масштабируется до 0,6. Новый уровень должен быть 4, новый масштаб должен быть 0,6 [1]

[1], вероятно, очевидно, но все, что меньше 1, но больше 0,5, останется прежним

TYIA

Ответы [ 3 ]

3 голосов
/ 12 февраля 2012

Ваши «уровни» могут быть определены следующей экспоненциальной функцией (с вашими уровнями, начинающимися с 1):
imagex-1">

Для простоты предположим, что у вас есть imagex"> (масштаб) и level(x), и вы пытаетесь найти level(y).

Видя, как определяется level(x), вы можете видеть, что

imagea * level(x) = level(x+a)">

Тем не менее, ваша шкала не дана в чистых степенях 2, как это, поэтому вы можете найти со следующим (округление в соответствии с вашим сценарием):

image2(sx)⌉ = a">

Что означает, что image2(sx)⌉"> и image⌈log2(sx)⌉ * level(x)">

Теперь, когда у нас есть новый уровень, у нас есть следующее уравнение:
imagex * level(x) = sy * level(y)
">
imagex * baseSize * 2x-1 = sy * baseSize * 2y-1">
imagex * 2x-1 / 2y-1 = sy">
imagex * 2x-y = sy">

/ редактировать
Да, вот что означает 2 x-1 .

  • s x - это просто некоторая константа, которая идет с x (в данном случае это ваш масштаб), аналогично, s y - это некоторая константа, которая идет с y.

  • Странные квадратные скобки с верхним битом (⌈ ⌉) - это просто функция потолка (Math.ceil).

  • Логарифмы обратны возведению в степень. Логарифмы определяются следующим образом: если a c = b, то log a (b) = c. Например, log 2 (8) = 3, потому что 2 3 = 8. Что-то еще сбивает с толку?

/ образец Java

int newLevel = oldLevel + (int) Math.ceil(Math.log(oldScale) / Math.log(2));
double newScale = oldScale * Math.pow(2, oldLevel - newLevel);

Мы должны использовать формула изменения базы для логарифмов, потому что Math только обеспечивает log e и журнал 10 . Возможно, стоит создать константу для Math.log(2), поэтому вы не будете постоянно ее пересчитывать.

1 голос
/ 12 февраля 2012

Эта простая игра на совпадение использует enum Game, чтобы указать константы, необходимые для четырех уровней игры. Переопределив toString() (и слегка нарушив соглашение о регистре для констант), Game.values() можно использовать для непосредственного заполнения выбора уровня gameCombo. Изменение уровней требует чуть больше, чем замена компонентов и вызов validate() на включающем Container.

0 голосов
/ 12 февраля 2012

пока ...

public static void getZoom(int currentLevel, double userScale){
        double ns = (1 << (currentLevel - 1)) * userScale;
        int newLevel = 1;
        int ts = 1;
        while(ts < ns){
            ts <<= 1;
            newLevel++;
        }
        double newScale = ns / ts;
        System.out.println(newLevel + ", " + newScale);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...