Вопрос

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

Вот такая ситуация

У меня есть абстрактная концепция сетки с Y шагами на расстоянии ровно Y_STEP друг от друга (x шагов работают нормально, поэтому игнорируйте их пока).

Сетка находится в абстрактном координатном пространстве, и чтобы все выровнять, у меня там есть волшебное смещение, давайте назовем его Y_OFFSET

чтобы привязаться к сетке, у меня есть следующий код (python)

def snapToGrid(originalPos, offset, step):
    index = int((originalPos - offset) / step) #truncates the remainder away
    return index * gap + offset

итак, я передаю позицию курсора, Y_OFFSET и Y_STEP в эту функцию, и она возвращает мне ближайшую к полу позицию y в сетке

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

Прокрутка сделана настолько простой, насколько я могу это понять, у меня есть окно просмотра, которое ведет подсчет расстояния, пройденного по оси Y, и просто компенсирует все, что проходит через него.

Вот фрагмент кода перемещения курсора mouseMotion:

def mouseMotion(self, event):
    pixelPos = event.pos[Y]
    odePos = Scroll.pixelPosToOdePos(pixelPos)
    self.tool.positionChanged(odePos)

Итак, есть две вещи, на которые стоит обратить внимание: сначала перевод модуля прокрутки из положения пикселя в абстрактное координатное пространство, затем функция positionChanged инструмента, которая принимает значение абстрактного координатного пространства и привязывается к ближайшему Y-шагу.

Вот соответствующий код прокрутки

def pixelPosToOdePos(pixelPos):
    offsetPixelPos = pixelPos - self.viewPortOffset
    return pixelsToOde(offsetPixelPos)

def pixelsToOde(pixels):
    return float(pixels) / float(pixels_in_an_ode_unit)

И инструменты обновляют код

def positionChanged(self, newPos):
    self.snappedPos = snapToGrid(originalPos, Y_OFFSET, Y_STEP)

Последний релевантный фрагмент - это когда инструмент переходит к рендерингу самого себя.Он проходит через объект прокрутки, который преобразует положение инструмента в пространстве с привязанными координатами в положение пикселя на экране, вот код:

#in Tool
def render(self, screen):
    Scroll.render(screen, self.image, self.snappedPos)

#in Scroll
def render(self, screen, image, odePos):
    pixelPos = self.odePosToPixelPos(odePos)
    screen.blit(image, pixelPos) # screen is a surface from pygame for the curious

def odePosToPixelPos(self.odePos):
    offsetPos = odePos + self.viewPortOffset
    return odeToPixels(offsetPos)

def odeToPixels(odeUnits):
    return int(odeUnits * pixels_in_an_ode_unit)

Фух, это было длинное объяснение.Надеюсь, ты все еще со мной...

Проблема, с которой я сейчас сталкиваюсь, заключается в том, что при прокрутке вверх нарисованное изображение теряет выравнивание по курсору.
Он начинает привязываться к шагу Y ровно на 1 шаг ниже курсора.Кроме того, похоже, что он входит в выравнивание по фазе и выходит из него.
На некоторых свитках он превышен на 1, а на других - на месте.
Он никогда не выходит больше чем на 1 и всегда привязывается к допустимому местоположению сетки.

Лучшее предположение, которое я могу придумать, это то, что где-то я усекаю какие-то данные не в том месте, но понятия не имею, где и как это приводит к такому поведению.

Кто-нибудь знаком с координатными пространствами, прокруткой и привязкой?

Это было полезно?

Решение

Хорошо, я отвечаю здесь на свой собственный вопрос, как упоминал alexk, использование int для усечения было моей ошибкой.

Поведение, к которому я стремлюсь, лучше всего моделируется math.floor().

Прошу прощения, первоначальный вопрос не содержит достаточной информации, чтобы действительно разобраться, в чем проблема.На тот момент у меня не было дополнительной информации.

Что касается примечания об опечатке, я думаю, что, возможно, я неправильно использую контекст...С точки зрения функции positionChanged(), параметр представляет собой ввод новой позиции.
С точки зрения функции snapToGrid() параметр представляет собой исходную позицию, которая изменяется на привязанную позицию.Язык такой, потому что часть его находится в моем коде обработки событий, а другая часть - в моем коде общих служб.Я должен был изменить это для примера

Другие советы

У вас есть опечатка в positionChanged()?

def positionChanged(self, newPos):
    self.snappedPos = snapToGrid(newPos, Y_OFFSET, Y_STEP)

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

def snapToGrid(originalPos, offset, step):
    EPS = 1e-6
    index = int((originalPos - offset) / step  + EPS) #truncates the remainder away
    return index * gap + offset

Спасибо за ответ, возможно, здесь опечатка, но я ее не вижу...

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top