Monthly Archives: Грудень 2015

Встановлення Python 3.5 з джерельного коду, встановлення Django

Ок, продовжу спроби підготуватись до DjangoGirls так, щоб там ми вчили найпередовіші технології. :)

Такі експерименти краще робити у захищеному середовищі, тому бажано щоб у вас були VirtualBox та Vagrant:

sudo apt-get install virtualbox vagrant

Поки вони ставляться, раджу коротко ознайомитись як користуватись тим Vagrant-ом.

В директорії з кодом створюємо такий файл:

# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "forwarded_port", guest: 8000, host: 8000
end

Це поки що він такий. Пізніше поміняю, і вся інсталяція має більш автоматизуватись. Тепер команда vagrant up дозволяє підняти чисте середовище. vagrant ssh – зайти в його термінал.

Ми хочемо Python 3.5, а його інакше як з сорсів не отримаєш, тому качаємо з сайту: https://www.python.org/downloads/

sudo apt-get update
sudo apt-get install build-essential libsqlite3-dev sqlite3 bzip2 libbz2-dev
sudo apt-get install libreadline-dev libncurses5-dev tk-dev libssl-dev
wget -c https://www.python.org/ftp/python/3.5.0/Python-3.5.0.tar.xz
tar xJf Python-3.5.0.tar.xz
cd Python-3.5.0
./configure
make
sudo make install

Тепер нарешті можна створювати віртуальне середовище (всередині віртуальної машини, ага), і ставити Django:

mkdir djangogirls
cd djangogirls
python3.5 -m venv myenv
source myenv/bin/activate
pip install django

Та-дааммм!!!

Successfully installed django-1.9

Не знав що вже є Django 1.9. Хоча, звісно що не знав, його вчора випустили. Кажуть там змінили дизайн адмінки. Давайте швиденько подивимось:

django-admin startproject mysite .
python manage.py migrate
python manage.py createsuperuser
python manage.py runserver
Адмінка як адмінка.

Адмінка як адмінка.


Filed under: Інструменти, Кодерство Tagged: linux, Python

Як намалювати стрілочку в SVG

Креслення стрілочки, з позначенням деяких змінних

Креслення стрілочки, з позначенням деяких змінних

Поточна ситуація така, що на запит “як намалювати стрілочку”, Google видає купу порад дівчатам про те як зашпаклювати лице. Але проблема трапляється часто, і не тільки в SVG, ось наприклад старий пост про те як малювати вектори в OpenGL, для програмки що проводить структурний аналіз кінематики машин і механізмів. Тому треба виправити цю ситуацію, і написати ще пару публікацій про малювання стрілочок. :)

Тут буде код який було весело писати, і яким варто поділитись. Присутній також JsFiddle. Код дозволяє малювати стрілочки наступного вигляду:

arrows


Написано з використанням D3.js, але код можна причепити де завгодно, так як головне тут – функція arrow_path, яка генерує значення атрибуту d для тега path. Приймає вона координати початку і кінця стрілки, ширину лінії стрілки, радіус (задає розмір трикутника на кінці стрілки, і радіус gizmo (пімпочки на середині)). directed – булевий аргумент, що вказує чи малювати стрілочку на кінці лінії взагалі. gizmo – якщо false – пімпочки не буде, 'circle' – буде коло, 'diamond' – буде ромбик.

Думаю тут можна було б ще зекономити на ручному перетворенні систем координат, бо виходить забагато арифметики. Натомість використати translate, але щось зразу не додумався. Правда воно і так не тормозить, навіть коли малює отаке чудо:

large_map

Сучасні браузери – потужні машини!

var panel = d3.select('body');

svg = panel.append('svg')
    .attr('width', 500)
    .attr('height', 500);


var arrow_path = function(x1, y1, x2, y2, width, r, directed, gizmo) {
    var dx = x2 - x1; // direction of arrow
    var dy = y2 - y1;
    var l = Math.sqrt(dx * dx + dy * dy); // length of arrow
    var fx = dx / l; // forward vector
    var fy = dy / l;
    
    var lx = -fy; // side vector
    var ly = fx;
    
    var line_rectangle = [
        (x1 + lx*width) + ',' + (y1 + ly*width),
        (x2 + lx*width) + ',' + (y2 + ly*width),
        (x2 - lx*width) + ',' + (y2 - ly*width),
        (x1 - lx*width) + ',' + (y1 - ly*width)
    ];
    
    var alx, aly, arx, ary;
    if (directed) {
        alx = x2 - fx*r*2 + lx*r;
        aly = y2 - fy*r*2 + ly*r;
        arx = x2 - fx*r*2 - lx*r;
        ary = y2 - fy*r*2 - ly*r;
    };
    
    var get_end_points = function () {
        // return list of end vertexes that for an arrow or just side of rectangle.
        if(directed) {            
            return [
                'L' + (x2 - fx*r*2 + lx * width) + ',' + (y2 - fy*r*2 + ly * width),
                'L' + (x2 - fx*r*2 + lx * r) + ',' + (y2 - fy*r*2 + ly * r),
                'L' + x2 + ',' + y2,
                'L' + (x2 - fx*r*2 - lx * r) + ',' + (y2 - fy*r*2 - ly * r),
				'L' + (x2 - fx*r*2 - lx * width) + ',' + (y2 - fy*r*2 - ly * width),
            ];      
        } else {
            return [
                'L' + line_rectangle[1],
                'L' + line_rectangle[2],
            ];

        };
    };
    
    if (!gizmo) {
        return [
            'M' + x1 + ',' + y1,
            'L' + line_rectangle[0]
        ].concat(
            get_end_points(),
            [
                'L' + line_rectangle[3],
                'L' + x1 + ',' + y1,
            ]
        ).join(' ');
    };
    
    var cx = (x1 + x2) / 2;
    var cy = (y1 + y2) / 2;
    var h = Math.sqrt(r*r - width*width);
    
    var arc_rectangle = [
        (cx - fx*h + lx*width) + ',' + (cy - fy*h + ly*width),
        (cx + fx*h + lx*width) + ',' + (cy + fy*h + ly*width),
        (cx + fx*h - lx*width) + ',' + (cy + fy*h - ly*width),
        (cx - fx*h - lx*width) + ',' + (cy - fy*h - ly*width),
    ];
    
    if (gizmo === 'circle') {
        return [
            'M' + x1 + ',' + y1,
            'L' + line_rectangle[0],
            'L' + arc_rectangle[0],
            'A' + r + ',' + r + ' 0 0,0 ' + arc_rectangle[1],
        ].concat(
            get_end_points(),
            [
                'L' + arc_rectangle[2],
                'A' + r + ',' + r + ' 0 0,0 ' + arc_rectangle[3],
                'L' + line_rectangle[3],
                'L' + x1 + ',' + y1,
            ]
        ).join(' ');
    };
    
    if (gizmo === 'diamond') {
        return [
            'M' + x1 + ',' + y1,
            'L' + line_rectangle[0],
            'L' + arc_rectangle[0],
            'L' + (cx + lx * r) + ',' + (cy + ly*r),
            'L' + arc_rectangle[1],
        ].concat(
            get_end_points(),
            [
                'L' + arc_rectangle[2],
                'L' + (cx - lx * r) + ',' + (cy - ly*r),
                'L' + arc_rectangle[3],
                'L' + line_rectangle[3],
                'L' + x1 + ',' + y1,
            ]
        ).join(' ');
    };
    
    throw 'Unknown gizmo value'
};

svg.append('path')
    .attr("d", arrow_path(0, 100, 200, 300, 2, 10, false, 'circle'));

svg.append('path')
    .attr("d", arrow_path(50, 100, 250, 300, 2, 10, false, false));

svg.append('path')
    .attr("d", arrow_path(100, 100, 300, 300, 2, 10, true, false));

svg.append('path')
    .attr("d", arrow_path(150, 100, 350, 300, 2, 10, true, 'circle'));

svg.append('path')
    .attr("d", arrow_path(200, 100, 400, 300, 2, 10, true, 'diamond'));

В кінцевому результаті виходить подібний SVG:

<path d="M150,100 L148.5857864376269,101.41421356237309 L241.6575832073514,194.4860103320976 A10,10 0 0,0 255.51398966790242,208.3424167926486 L334.44365081389594,287.27207793864216 L328.7867965644036,292.9289321881345 L350,300 L342.9289321881345,278.7867965644036 L337.27207793864216,284.44365081389594 L258.34241679264863,205.5139896679024 A10,10 0 0,0 244.4860103320976,191.6575832073514 L151.4142135623731,98.58578643762691 L150,100">

<path d="M200,100 L199.29289321881345,100.70710678118655 L292.2572695790783,193.6714831414514 L292.9289321881345,207.07106781186548 L306.3285168585486,207.7427304209217 L385.1507575950825,286.5649711574556 L378.7867965644036,292.9289321881345 L400,300 L392.9289321881345,278.7867965644036 L386.5649711574556,285.1507575950825 L307.7427304209217,206.3285168585486 L307.0710678118655,192.92893218813452 L293.6714831414514,192.2572695790783 L200.70710678118655,99.29289321881345 L200,100">

Страшненько, в порівнянні з line тому добре що його можна не руками писати.

P.S. Є ще простіший спосіб – називається SVG marker. Правда з ним біда – маркер має окремі обробники для всіх подій миші, тому якщо вішати функції на ці події – якщо миша буде над маркером а не над лінією – не спрацює. Інша проблема – маркер не змінює колір коли змінювати колір лінії. Цей код уникає цих двох проблем. Але якщо вас події і кольори не цікавлять – користуйтесь маркерами.


Filed under: Графіка, Кодерство Tagged: графіка, JavaScript, linux