Бинарное древо (отрисовка), объекты
Всем здравствуйте.
Есть некоторый код: <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. Извините за большую пасту, спойлеров не нашел. |
Цитата:
[HTML hide run][/HTML] О том, как вставить в сообщение исполняемый javascript и html-код, а также о дополнительных возможностях форматирования - читайте http://javascript.ru/formatting. |
Спасибо. Отредактировал.
|
Цитата:
|
d1ver,
формировать общий массив точек для каждого уровня и его выводить в одну строку с равными отступами слева и справа. на счёт не пересечения линий в целом, задача слишком огромная, нужны специальные библиотеки. |
d1ver,
у тебя метод checkDrawPoint возвращает объект, а не массив. объект с индексами, которые node.index. И полем length - количеством пунктов. Соответственно, если в перечне индексов будет "дырка", например, индексы (0, 1, 2, 4, ...), то превед undefined. Либо возвращай нормальный массив (с добавлением туда пунктов с помощью drawPoint.push), либо перебирай его как объект. Имхо, лучше первое. |
Я понимаю, что у меня бывает долго формируется объект, и к пока отсутствующим элементам уже обратиться хотят. Но как это исправить, еще не придумал.
Если подскажете, как, не поймав ту же ошибку, переместить этот объект в массив - скажу большое спасибо, пробовал сразу вносить в массив - и получал эту ошибку. |
Цитата:
объект формируется синхронно, т.е. пока это происходит, никакой другой код выполняться не будет. В 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; }; |
Не пойму, почему, но сработало.
Спасибо, 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> |
Часовой пояс GMT +3, время: 04:49. |