Metrika

Показаны сообщения с ярлыком javascript. Показать все сообщения
Показаны сообщения с ярлыком javascript. Показать все сообщения

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, которые формируют многоугольник.

26 июня 2013 г.

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

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

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


6 ноября 2012 г.

JavaScript: Форматирование числа - добавление пробелов

Весьма полезная функция - добавить пробелы, которые разделяют тысячи, миллионы и т.д.:

function addCommas(nStr)
{
  nStr += '';
  x = nStr.split('.');
  x1 = x[0];
  x2 = x.length > 1 ? '.' + x[1] : '';
  var rgx = /(\d+)(\d{3})/;
  while (rgx.test(x1)) {
    x1 = x1.replace(rgx, '$1' + ' ' + '$2');
  }
  return x1 + x2;
}

Взял тут:

1 апреля 2011 г.

Проверка правильности JSON

Вот здесь: http://json.org/ внизу страницы перечислены различные утилиты для работы с JSON. Мне понравилась утилита проверки правильности JSON-кода написанная на C#: JSON_checker.

Кстати, о том, зачем я начал проверять JSON. Сначала я использовал в проекте www.asvix.ru jQuery 1.3.2 и когда я делал вызов метода:
$.getJSON(url, callback);
То callback-функция нормально вызывалась после получения ответа с сервера. У меня с сервера возвращался не очень корректный ответ в виде JSON, примерно такой: {x:"50",y:"100"}.
После перехода на jQuery 1.5 колбэки перестали работать, т.е. сама callback-функция работала, если ее вызвать на прямую, но из getJSON она не вызывалась. Проблема оказалась в том, что JSON был некорректен. Исправил на сервере, что бы возвращало правильно: {"x":"50","y":"100"} и все заработало.

28 января 2011 г.

Определение высоты документа для любого браузера

function getDocHeight() {
    var D = document;
    return Math.max(
        Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
        Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
        Math.max(D.body.clientHeight, D.documentElement.clientHeight)
    );
}

Если высота документа меньше высоты видимой области окна, то будет возвращена высота видимой области окна.

Взято здесь.

27 января 2011 г.

Проблема с событием onload в объекте Image в браузере Opera

Наткнулся на проблему при использовании плагина для jQuery lightbox 0.5. В Opera 11.00 - при нажатии на ссылку, которая должна отобразить фотографию, открывался оверлей, но фотография не отображалась. Если закрыть оверлей и снова нажать на туже ссылку, то фотография отображалась нормально.
Начал копаться в коде lightbox. Выяснил, что проблема в том, что в функции _set_image_to_view() из файла jquery.lightbox-0.5.js устанавливается обработчик события onload на объект Image, внутри обработчика выполняется отображение фотографии:
objImagePreloader.onload = function () {
                $('#lightbox-image').attr('src', settings.imageArray[settings.activeImage][0]);
                // Perfomance an effect in the image container resizing it
                _resize_container_image_box(objImagePreloader.width, objImagePreloader.height);
                //    clear onLoad, IE behaves irratically with animated gifs otherwise
                objImagePreloader.onload = function () { };
            };
Но после загрузки фотографии обработчик onload не запускается.
Поскольку в других браузерах все работало отлично, понял, что проблема в Opera. Погуглив нашел несколько постов в форумах на эту тему:
Решения не нашел, поэтому сделал такую заплатку: в функцию  _set_image_to_view() из файла jquery.lightbox-0.5.js после строк:
            // Image preload process
            var objImagePreloader = new Image();
           
            objImagePreloader.onload = function () {
                $('#lightbox-image').attr('src', settings.imageArray[settings.activeImage][0]);
                // Perfomance an effect in the image container resizing it
                _resize_container_image_box(objImagePreloader.width, objImagePreloader.height);
                //    clear onLoad, IE behaves irratically with animated gifs otherwise
                objImagePreloader.onload = function () { };
            };

            objImagePreloader.src = settings.imageArray[settings.activeImage][0];

добавил:

            if (window.opera) {
                var ver = window.opera.version();
                if (ver == '11.00' || ver == '11.01' || ver == '7.50' || var == '7.54') {
                    ___pause(1000);
                    objImagePreloader.onload();
                }
            }

Функция  ___pause определена в файле jquery.lightbox-0.5.js. Значение задержки надо подобрать в зависимости от скорости загрузки фотографий. В общем 100% результат не гарантирован, т.к. скорость загрузки всегда разная.
Решение не очень красивое, но другого не придумал :)