Metrika

27 августа 2013 г.

JavaScript: Построение выпуклого многоугольника по конечному однородному множеству точек

Построение многоугольника будет производиться алгоритмом QuickHull. Код можно брать и использовать. Я его проверял на массивах до 30000 точек, не лагало. Если найдете баги, пишите в коменты.

// Построение выпуклого многоугольника по массиву однородных точек
function Point() {
    this.x = 0;
    this.y = 0;
}

Point.prototype.init_by_building = function (building) {
    this.x = building.lng;
    this.y = building.lat;

    return this;
}

Point.prototype.init = function (x, y) {
    this.x = x;
    this.y = y;

    return this;
}

// Отрезок
function Line(x1, y1, x2, y2) {
    this.start = new Point().init(x1, y1);
    this.end = new Point().init(x2, y2);

    // Расчет дистанции до точки
    this.distanceToPoint = function (point) {
        var Vy = this.end.x - this.start.x;
        var Vx = this.start.y - this.end.y;

        return Vx * (point.x - this.start.x) + Vy * (point.y - this.start.y);
    };

    this.findMostDistantPoint = function (points) {
        var max_dist = 0;
        var max_point = null;
        var new_points = [];

        for (var idx in points) {
            var pt = points[idx];
            var d = this.distanceToPoint(pt);

            if (d > 0) new_points.push(pt);
            else continue;

            if (d > max_dist) {
                max_dist = d;
                max_point = pt;
            }
        }

        return {'maxPoint':max_point, 'newPoints':new_points}
    };
}

function QuickHull(points) {
    this.points = points;

    this.all_lines = [];

    this._getBaseLine = function () {
        var max_x = -10000;
        var min_x = 10000;
        var max_point, min_point;

        for (var idx in points) {
            var pt = points[idx];
            if (pt.x > max_x) {
                max_point = pt;
                max_x = pt.x;
            }

            if (pt.x < min_x) {
                min_point = pt;
                min_x = pt.x;
            }
        }

        return new Line(min_point.x, min_point.y, max_point.x, max_point.y);
    };

    this._buildConvexHull = function(line, points) {
        this.all_lines.push(line);

        var convex_hull_base_lines = [];

        var t = line.findMostDistantPoint(points);

        // Если есть точка за пределами линии
        if (t.maxPoint != null) {
            var pt = t.maxPoint;
            convex_hull_base_lines = convex_hull_base_lines.concat(this._buildConvexHull(new Line(line.start.x, line.start.y, pt.x, pt.y), t.newPoints));
            convex_hull_base_lines = convex_hull_base_lines.concat(this._buildConvexHull(new Line(pt.x, pt.y, line.end.x, line.end.y), t.newPoints));

            return convex_hull_base_lines;
        }
        else { return [line]; }// Нет точки за пределами линии
    };


    this.Start = function () {
        var base_line = this._getBaseLine();

        return [].concat(this._buildConvexHull(base_line, this.points), this._buildConvexHull(new Line(base_line.end.x, base_line.end.y, base_line.start.x, base_line.start.y), this.points));
    };
}

Как использовать:
var qh = new QuickHull(points);
var cvx_lines = qh.Start();

Необходимо передать массив точек в конструктор QuickHull. Я использовал алгоритм для построения полигона на карте, поэтому у меня в объекте Point два конструктора: init_by_building, куда передается объект здания, который в свою очередь имеет свойства lat (широта) и lng (долгота); и init, куда передются координаты x и y точки.
После выполнения в массиве cvx_lines будут содержаться объекты типа Line, которые формируют многоугольник.

18 июля 2013 г.

Аналог ROW_NUMBER в MySQL

В статье T-SQL: Функция ROW_NUMBER я рассказывал, как выводить номер строки в запросе в Microsoft SQL Server. Тут я расскажу, как выводить номер строки в запросе в MySQL.

Для того, что бы это работало, в строке соединения с базой должно быть прописано: allow user variables=true;

Запрос, выводящий номера строк выглядит вот так:
SELECT @row:=@row+1 row_number, t.* 
FROM tbl t
INNER JOIN (SELECT @row := 0) c

26 июня 2013 г.

Base64 кодирование в JavaScript

Если нужно кодировать и декодировать строки в/из Base64 в браузере,  подойдет вот эта библиотека: http://jsbase64.codeplex.com/

Только она, из найденных мной, работает с русским языком в UTF-8.


11 марта 2013 г.

JMeter: Нагрузочное тестирование MySQL

Речь пойдет об использовании инструмента Apache JMeter™ для нагрузочного тестирования сервера MySQL.

JMeter - это опенсорсный продукт на Java. Его можно использовать для нагрузочного тестирования Web-сервера, FTP-сервера, сервера БД и пр. Обладает хорошим пользовательским интерфейсом и гибкими настройками.

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

Мне было необходимо погонять различные SELECT-запросы к MySQL для определения наиболее проблемных и для их оптимизации. Для этого, сначала,надо было подключить JMeter к серверу MySQL, а затем выполнять SQL-запросы с различными параметрами в условиях.

Как подключать JMeter к MySQL и создавать запросы к базе описано здесь: http://jmeter.apache.org/usermanual/build-db-test-plan.html.  Проблема, которая обычно возникает во время подключения к базе, - это установка драйвера MySQL для Java. Его нужно скачать здесь: http://dev.mysql.com/downloads/connector/j/, распаковать архив и положить файл mysql-connector-java-5.1.23-bin.jar в папку lib в папке установки JMeter.

Мне было интересно делать запросы с реальными условиями, т.е. для каждого нового запроса к базе ставить свои параметры. Для этого я сохранил необходимые значения в CSV файл. Для того, что бы сгенерить выражение для получения данных для запроса из CSV файла, воспользовался Function Helper Dialog (в главном меню: Options->Function Helper Dialog):


Далее добавил полученное выражение как параметр в SQL-запрос:








7 февраля 2013 г.

IIS: проблемы с генерацией статического контента в ASP.NET

Если мне нужно сгенерировать на сайте ASP.NET статический контент (например JavaScript-файл), то я делаю это через Global.asax в обработчике события Application_BeginRequest:


    void Application_BeginRequest(object sender, EventArgs e)
    {
        string req = HttpContext.Current.Request.AppRelativeCurrentExecutionFilePath.ToLower();
     
        // Перенаправление обращений к JavaScript файлам на их динамическое формирование      
        if (req.CompareTo("~/scripts/item_types.js")==0)
        {
            Context.RewritePath("~/js_item_types.aspx");
            return;
        }
    }
Файл  js_item_types.aspx в ответ выдает необходимый контент, например после обращения к БД.

Все отлично работает, когда я запускаю проект на локальной машине под управлением встроенного в VS Web-сервера, но перестает работать, когда я развертываю проект на IIS сервере. При обращении к файлу /scripts/item_types.js возникает ошибка 404.

Проблема в том, что для IIS файлы *.js это статический контент и он проверяет их наличие или отсутствие еще до того, как передаст управление в ASP.NET

Что бы так не происходило, надо указать IIS, что этот файл обрабатывается в ASP.NET. Для этого в панели управления IIS выбираем сайт, далее тыкаем в иконку Handler Mappings, откроется список и в него надо добавить новый хендлер. Справа нажимаем Add Managed Handler в появившемся окне заполняем поля: Request path -> *item_types.js, Type -> ASP.global_asax, Name -> JS_item_types и давим OK.