Книга: Написание скриптов для Blender 2.49

Скрипт построения гистограммы

Скрипт построения гистограммы

Здесь мы покажем важные части кода кусками (полный файл доступен как barchart.blend, который включает barchart.py как вложенный текст). Мы начинаем с создания нового объекта Мира и установки цветов его зенита и горизонта целиком в нейтральный белый (выделенная часть следующего кода):

if __name__ == '__main__':
    w=World.New('BarWorld')
    w.setHor([1,1,1])
    w.setZen([1,1,1])

Затем, мы извлекаем последний аргумент, переданный в Блендер и проверяем является ли расширение файла тем же самым .csv. Реальный промышленный код должен, конечно, иметь более серьёзную проверку на ошибки:

csv = sys.argv[-1]
if csv.endswith('.csv'):

Если у него правильное расширение, мы создаём новую Сцену с именем BarScene и присваиваем её атрибут world к нашему вновь созданному миру (Это было вдохновлено более сложным сценарием jessethemid на   Blender   Artists http://blenderartists.org/forum/showthread.php?t=79285).   Фоновый режим не загружает никакого .blend файла по-умолчанию, так что сцена по-умолчанию не будет содержать никаких объектов. Тем не менее, просто, чтобы убедиться, мы создаем новую пустую сцену со значимым именем, которое будет содержать наши объекты:

sc=Scene.New('BarScene')
sc.world=w
sc.makeCurrent()

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

center = barchart(sys.argv[-1])
addcamera(center)
addlamp()

Рендеринг самый простой (мы столкнемся с более сложными примерами в Главе 8, Рендеринг и Обработка Изображения). Мы извлекаем контекст рендеринга, который хранит всю информацию о рендеринге, например, номер кадра, какой выходной формат, размер изображения, и так далее. И, поскольку большинство атрибутов по умолчанию разумны, мы установим только выходной формат на PNG и запустим рендер.

context=sc.getRenderingContext()
context.setImageType(Scene.Render.PNG)
context.render()

Наконец, мы устанавливаем выходной каталог в пустую строку, чтобы сделать наш вывод в текущий каталог (каталог, в котором мы были, когда вызывали Блендер) и сохраняем наше визуализированное изображение. Изображение будет иметь то же базовое имя, как у .csv-файла, который мы приняли как первый аргумент, но будет иметь расширение .png. Мы проверили, что имя файла заканчивается на .csv, так что вполне безопасно тупо удалить последние четыре символа из имени файла и добавить .png

context.setRenderPath('')
context.saveRenderedImage(csv[:-4]+'.png')

Добавление лампы не значительно отличается от добавления любого другого объекта и очень подобно примеру "hello world". Мы создаём новый объект Lamp, добавляем его к текущей сцене и устанавливаем его позицию. Объект Lamp имеет, конечно, много настраиваемых параметров, но мы в этом примере довольствуемся не-направленной лампой по-умолчанию. Выделенный код показывает типичную идиому Питона: loc - кортеж из трех величин, но setLocation() принимает три отдельных аргумента, так что мы указываем, что хотим распаковать кортеж на отдельные значения с помощью * нотации:

def addlamp(loc=(0.0,0.0,10.0)):
    sc = Scene.GetCurrent()
    la = Lamp.New('Lamp')
    ob = sc.objects.new(la)
    ob.setLocation(*loc)

Добавление камеры будет чуть-чуть сложнее, так как мы должны направить её на нашу гистограмму и убедиться, что угол обзора достаточно широкий, чтобы все видеть. Мы определяем здесь перспективную камеру и устанавливаем довольно широкий угол. Поскольку камера по-умолчанию уже сориентирована вдоль оси z, мы не должны задавать никакого вращения, только установим позицию в 12 единиц от центра вдоль оси z, как выделено на второй снизу строке следующего кода:

def addcamera(center):
    sc = Scene.GetCurrent()
    ca = Camera.New('persp','Camera')
    ca.angle=75.0
    ob = sc.objects.new(ca)
    ob.setLocation(center[0],center[1],center[2]+12.0)
    sc.objects.camera=ob

Сама функция barchart не такая уж большая неожиданность. Мы открываем файл с полученным именем и используем стандартный модуль csv из Питона, чтобы читать данные из файла. Мы загружаем все заголовки столбцов в xlabel, а остальные данные в rows (строки).

from csv import DictReader
def barchart(filename):
    csv = open(filename)
    data = DictReader(csv)
    xlabel = data.fieldnames[0]
    rows = [d for d in data]

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

maximum = max([float(r[n]) for n in data.fieldnames[1:] 
               for r in rows])
minimum = min([float(r[n]) for n in data.fieldnames[1:] 
               for r in rows])

Чтобы фактически создать столбики, мы проходим по всем строкам. Поскольку значение по x может быть текстовой меткой (как название месяца, например), мы сохраняем отдельно цифровое значение x для того, чтобы позиционировать столбики. Само значение x добавляется к сцене в виде объекта Text3d функцией label(), поскольку значения y визуализируются соответственно масштабированными объектами  Cube (Куб), добавляемыми функцией bar(). Функции label() и bar() не показаны здесь.

for x,row in enumerate(rows):
    lastx=x
    label(row[xlabel],(x,10,0))
    for y,ylabel in enumerate(data.fieldnames[1:]):
        bar(10.0*(float(row[ylabel])-minimum)/maximum,
(x,0,y+1))
x = lastx+1

Наконец, мы подписываем каждый столбец (то есть, каждый набор данных) своим собственным заголовком столбца как label. Мы сохранили число значений по x, так что мы можем вернуть центр нашей гистограммы деля его на два (y-компонент установлен на 5.0, так как мы масштабировали все значения по y, чтобы они лежали в пределах диапазона от 0 до 10).

for y,ylabel in enumerate(data.fieldnames[1:]):
    label(ylabel,(x,0,y+0.5),'x')
return (lastx/2.0,5.0,0.0)


Хитрость в Windows: SendTo (Отправить)

Как только у вас будет ваш .blend файл, содержащий корректный скрипт Питона и вы поймёте, как правильно вызвать его из командной строки, Вы можете интегрировать его более тесно с Windows XP, создав программу SendTo. Программа SendTo (в нашем случае .BAT-файл) - любая программа, которая принимает единственное имя файла как аргумент и что-либо делает с этим файлом. Он должен находиться в каталоге SendTo, который может быть расположен на разных местах в зависимости от вашей конфигурации системы. Его просто найти, щелкнув по кнопке Пуск, выбрав Выполнить..., и набрав sendto вместо команды. Откроется искомый каталог. В этот каталог Вы можете поместить .BAT-файл, в нашем случае он называется BarChart.BAT, и он будет содержать единственную команду:

/полный/путь/к/blender.exe /путь/к/barchart.blend -P barchart.py -- %1

(заметьте знак процента). Теперь мы можем просто щелкать правой кнопкой мыши по любому .csv-файлу, с которым мы сталкиваемся, и затем выбирать BarChart.BAT в меню Отправить, и вуаля, .png файл появится рядом с нашим .csv.

Оглавление книги

Оглавление статьи/книги

Генерация: 0.030. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз