13.10.2017, 10:19
|
Новичок на форуме
|
|
Регистрация: 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.
Причина: Исправление ошибок...
|
|
13.10.2017, 10:28
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,109
|
|
Сообщение от d1ver
|
спойлеров не нашел.
|
[HTML hide run][/HTML]
О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting.
|
|
13.10.2017, 11:05
|
Новичок на форуме
|
|
Регистрация: 25.09.2017
Сообщений: 9
|
|
Спасибо. Отредактировал.
|
|
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 будет ошибка
|
|
13.10.2017, 12:11
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,109
|
|
d1ver,
формировать общий массив точек для каждого уровня и его выводить в одну строку с равными отступами слева и справа.
на счёт не пересечения линий в целом, задача слишком огромная, нужны специальные библиотеки.
|
|
13.10.2017, 12:25
|
|
Профессор
|
|
Регистрация: 25.10.2016
Сообщений: 1,012
|
|
d1ver,
у тебя метод checkDrawPoint возвращает объект, а не массив.
объект с индексами, которые node.index. И полем length - количеством пунктов. Соответственно, если в перечне индексов будет "дырка", например, индексы (0, 1, 2, 4, ...), то превед undefined.
Либо возвращай нормальный массив (с добавлением туда пунктов с помощью drawPoint.push), либо перебирай его как объект. Имхо, лучше первое.
|
|
13.10.2017, 13:04
|
Новичок на форуме
|
|
Регистрация: 25.09.2017
Сообщений: 9
|
|
Я понимаю, что у меня бывает долго формируется объект, и к пока отсутствующим элементам уже обратиться хотят. Но как это исправить, еще не придумал.
Если подскажете, как, не поймав ту же ошибку, переместить этот объект в массив - скажу большое спасибо, пробовал сразу вносить в массив - и получал эту ошибку.
|
|
13.10.2017, 16:13
|
|
Профессор
|
|
Регистрация: 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;
};
|
|
14.10.2017, 02:07
|
Новичок на форуме
|
|
Регистрация: 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.
Причина: Добавил демо готового кода.
|
|
|
|