Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 13.10.2017, 10:19
Новичок на форуме
Отправить личное сообщение для d1ver Посмотреть профиль Найти все сообщения от d1ver
 
Регистрация: 25.09.2017
Сообщений: 9

Бинарное древо (отрисовка), объекты
Всем здравствуйте.
Есть некоторый код:

<script type="text/javascript">
function drawPoly (id, arr) { //id тега <canvas> и массив координат
	var canvas = document.getElementById(id).getContext('2d');
	// Отрисовка
	canvas.clearRect(0,0,500,400);
	canvas.beginPath();
	clear_all();

	for (var i = 0; i < arr.length; i++) {
*!*
		canvas.strokeRect(arr[`${i}`].x + 250, arr[`${i}`].y * 10, 5, 5);

		console.log("x: " + arr[`${i}`].x + " y: " + arr[`${i}`].y);
*/!*
	}
}

function clear_all (){
	console.clear();
}

function BinarySearchTree() {
    this.root = null;
    this.index = 0;
}

BinarySearchTree.prototype.add = function(value) {
    var currentNode = this.makeNode(value);
    if (!this.root) {
        this.root = currentNode;
    } else {
        this.insert(currentNode);
    }
    return this;
};

BinarySearchTree.prototype.makeNode = function(value) {
    var node = {};
    node.value = value;
    node.info = {};
    node.left = null;
    node.right = null;
	node.parent = null;
	node.depth = 0;
	node.drawPoint = {
		x: 0,
		y: 0
	}
	node.index = this.index;
	this.index += 1;
    return node;
};

BinarySearchTree.prototype.insert = function(currentNode) {
    var value = currentNode.value;

    var traverse = function(node) {
        //if value is equal to the value of the node, ignore
        //and exit function since we don't want duplicates
        if (value === node.value) {
            return;
        } else if (value > node.value) {
            if (!node.right) {
                node.right = currentNode;
				node.depth++;
                return;
            } else
                traverse(node.right);
        } else if (value < node.value) {
            if (!node.left) {
                node.left = currentNode;
				node.depth++;
                return;
            } else
                traverse(node.left);
        }
    };
    traverse(this.root);
};


BinarySearchTree.prototype.setDepth = function() {
    var node = this.root;
    var maxDepth = 0;
    var traverse = function(node, depth) {
        if (!node) return null;
        if (node) {
            maxDepth = depth > maxDepth ? depth : maxDepth;
			node.depth = depth;
			//set parent too
			if (node.right){
				(node.right).parent = node;
			}
			if (node.left){
        		(node.left).parent = node;
        	}
            traverse(node.left, depth + 1);
            traverse(node.right, depth + 1);
        }
    };
    traverse(node, 1);
};

BinarySearchTree.prototype.maxDepth = function() {
    var node = this.root;
    var maxDepth = 0;
    var traverse = function(node) {
        if (!node) return null;
        if (node) {
            maxDepth = node.depth > maxDepth ? node.depth : maxDepth;
            traverse(node.left);
            traverse(node.right);
        }
    };
    traverse(node, 0);
    return maxDepth;
};

BinarySearchTree.prototype.setDrawPoint = function(maxDepth, resizer) {
    var node = this.root;
    var parentX, coef;
    var traverse = function(node, left) {
        if (!node) return null;
        if (node) {
*!*
        	parentX = node.parent ? (node.parent).drawPoint.x : 0;
        	parentX = left ? - parentX : parentX;
        	coef = left ? -coef : coef;
			node.drawPoint.x = parentX + Math.pow(2, maxDepth - node.depth);
			node.drawPoint.y = node.depth + resizer;
*/!*
            traverse(node.left, true);
            traverse(node.right);
        }
    };
    traverse(node);
};

BinarySearchTree.prototype.checkDrawPoint = function() {
    var node = this.root;
    var drawPoint = {};
    var counter = 0;
    var traverse = function(node) {
        if (!node) return null;
        if (node) {
        	*!*drawPoint[`${node.index}`] = node.drawPoint;*/!*
        	counter++;
            traverse(node.left);
            traverse(node.right);
        }
    };
    traverse(node, 0);
    drawPoint.length = counter;
    return drawPoint;
};


BinarySearchTree.prototype.setInfo = function() {
    var node = this.root;
    var traverse = function(node) {
        if (!node) return null;
        if (node) {
		    node.info = {};
			node.info.depth = node.depth;
			node.info.index = node.index;
			node.info.parent = node.parent;
			delete node.parent;
			delete node.depth;
			delete node.index;
            traverse(node.left);
            traverse(node.right);
        }
    };
    traverse(node, 0);
};

function BinaryTreeConstructor (num) {
	var tree = new BinarySearchTree();
	for (let i = 0; i < num; i++) {
		tree.add(parseInt((Math.random()*1000).toFixed(1)));
	}
	tree.setDepth();
	*!*tree.setDrawPoint(tree.maxDepth(), 0);*/!*
        delete(tree.index);
	return tree;
}

function createCoordArray(num) {
	var tree = new BinaryTreeConstructor(num);
	*!*var coordArray = tree.checkDrawPoint();*/!*
	return coordArray;
}





</script>
 
<form>
<canvas style='border:1px dashed #888;' id='canvasId' width='500' height='400'>
Извините, тег Canvas недоступен!
</canvas>
<br>
<input style="width:auto;" type="button" value="Draw" onclick="drawPoly('canvasId', createCoordArray(document.getElementById('count').value))">
<input style="width:auto;" type="text" value="10" id="count">
</form>



Суть проблемы: при работе функции отрисовки на большом кол-ве элементов вылезает ошибка

Uncaught TypeError: Cannot read property 'x' of undefined
    at drawPoly (Отрисовка.html:16)// в текущем документе - 10
    at HTMLInputElement.onclick (Отрисовка.html:207)

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

Суть второй проблемы: как правильно менять координаты ветки дерева, чтобы точки друг-друга не перекрывали и линии (которые я добавлю позже) не пересекались?
Мое решение, реализованное в коде, пока не проходит (по логике вещей, второй этаж сверху должен рисоваться симметрично, ну и т.д.).
Спасибо.

P.S. Извините за большую пасту, спойлеров не нашел.

Последний раз редактировалось d1ver, 13.10.2017 в 11:10. Причина: Исправление ошибок...
Ответить с цитированием
  #2 (permalink)  
Старый 13.10.2017, 10:28
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

Сообщение от d1ver
спойлеров не нашел.
[HTML hide run][/HTML]



О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.
Ответить с цитированием
  #3 (permalink)  
Старый 13.10.2017, 11:05
Новичок на форуме
Отправить личное сообщение для d1ver Посмотреть профиль Найти все сообщения от d1ver
 
Регистрация: 25.09.2017
Сообщений: 9

Спасибо. Отредактировал.
Ответить с цитированием
  #4 (permalink)  
Старый 13.10.2017, 11:35
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

Сообщение от d1ver
Cannot read property 'x' of undefined
смотрите как формируются у вас ключи обьекта arr, их просто нет иногда для примера 0, 1, 3,...,9 ключа 2 нет - значит и arr[2].x будет ошибка
Ответить с цитированием
  #5 (permalink)  
Старый 13.10.2017, 12:11
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,109

d1ver,
формировать общий массив точек для каждого уровня и его выводить в одну строку с равными отступами слева и справа.

на счёт не пересечения линий в целом, задача слишком огромная, нужны специальные библиотеки.
Ответить с цитированием
  #6 (permalink)  
Старый 13.10.2017, 12:25
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

d1ver,

у тебя метод checkDrawPoint возвращает объект, а не массив.

объект с индексами, которые node.index. И полем length - количеством пунктов. Соответственно, если в перечне индексов будет "дырка", например, индексы (0, 1, 2, 4, ...), то превед undefined.

Либо возвращай нормальный массив (с добавлением туда пунктов с помощью drawPoint.push), либо перебирай его как объект. Имхо, лучше первое.
Ответить с цитированием
  #7 (permalink)  
Старый 13.10.2017, 13:04
Новичок на форуме
Отправить личное сообщение для d1ver Посмотреть профиль Найти все сообщения от d1ver
 
Регистрация: 25.09.2017
Сообщений: 9

Я понимаю, что у меня бывает долго формируется объект, и к пока отсутствующим элементам уже обратиться хотят. Но как это исправить, еще не придумал.
Если подскажете, как, не поймав ту же ошибку, переместить этот объект в массив - скажу большое спасибо, пробовал сразу вносить в массив - и получал эту ошибку.
Ответить с цитированием
  #8 (permalink)  
Старый 13.10.2017, 16:13
Аватар для Alexandroppolus
Профессор
Отправить личное сообщение для Alexandroppolus Посмотреть профиль Найти все сообщения от Alexandroppolus
 
Регистрация: 25.10.2016
Сообщений: 1,012

Сообщение от d1ver
Я понимаю, что у меня бывает долго формируется объект, и к пока отсутствующим элементам уже обратиться хотят. Но как это исправить, еще не придумал.
это здесь ни при чем.

объект формируется синхронно, т.е. пока это происходит, никакой другой код выполняться не будет. В onclick все действия синхронные, нет запросов, таймеров и т.д.

поправить надо вот что:
BinarySearchTree.prototype.checkDrawPoint = function() {
    var node = this.root;
    *!*var drawPoint = [];*/!*
    var counter = 0;
    var traverse = function(node) {
        if (!node) return null;
        if (node) {
        	*!*drawPoint.push(node.drawPoint);*/!*
        	counter++;
            traverse(node.left);
            traverse(node.right);
        }
    };
    traverse(node, 0);
    drawPoint.length = counter;
    return drawPoint;
};
Ответить с цитированием
  #9 (permalink)  
Старый 14.10.2017, 02:07
Новичок на форуме
Отправить личное сообщение для d1ver Посмотреть профиль Найти все сообщения от d1ver
 
Регистрация: 25.09.2017
Сообщений: 9

Не пойму, почему, но сработало.
Спасибо, Alexandroppolus.
Объект вмещал в себе все индексы от 0 до конца дерева последовательно, но формировал их не по порядку. Это было критично?

Вот код, все проблемы решил, кому интересно - заглядывайте:

<p data-height="520" data-theme-id="light" data-slug-hash="aLaKWB" data-default-tab="js,result" data-user="IntroD1ver" data-embed-version="2" data-pen-title="aLaKWB" class="codepen">See the Pen <a href="https://codepen.io/IntroD1ver/pen/aLaKWB/">aLaKWB</a> by D1ver (<a href="https://codepen.io/IntroD1ver">@IntroD1ver</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

Последний раз редактировалось d1ver, 14.10.2017 в 02:17. Причина: Добавил демо готового кода.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как удалить объекты select D_Sergeevich Элементы интерфейса 2 16.09.2014 21:13
clone() клонирует копируемые объекты stella1982 jQuery 1 18.08.2014 08:28
Объекты в массиве. delias Общие вопросы Javascript 2 21.04.2010 22:28