Я потыркался, вроде и получается, но есть исключения и мне их уже лень думать сегодня. Если хоть как-то
приблизит вас к решению, буду рад. Справа кнопка рефреша. Комменты напишу и баги поправлю потом, если будет нужда. Общая идея - уходим до листиков, рисуем их, потом по усредненному Y рисуем их веточку, веточки дают среднюю Y для ветки их и так далее. Но гд-то явно прогибы есть, голова уже не варит, но задача прикольная.
Код AS3:
package
{
import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* @author gbee
*/
public class TreeTest extends Sprite
{
private static const VGAP:int = 15;
private static const HGAP:int = 50;
private var _levelsOffset:Array;
private var _g:Graphics;
public function TreeTest()
{
super();
var spr:Sprite = new Sprite();
spr.graphics.beginFill(0, 0.4);
spr.graphics.drawRect(800, 0, 100, 40);
spr.addEventListener(MouseEvent.CLICK, refresh);
addChild(spr);
refresh();
}
private function refresh(event:MouseEvent = null):void
{
_g = graphics;
_g.clear();
_g.beginFill(0x008800);
_g.lineStyle(1, 0x004400);
_levelsOffset = [0, 0, 0, 0, 0, 0, 0, 0, 0];
drawTree(generateTree(5, 3), 0);
}
private function generateTree(maxChilds:int, level:int):TreeNode
{
var childsCount:int = int(Math.random() * maxChilds);
var node:TreeNode = new TreeNode();
if (level == 0)
return node;
for (var i:int = 0; i < childsCount; i++)
node.children.push(generateTree(maxChilds, level - 1));
node.count = childsCount;
return node;
}
private function drawTree(node:TreeNode, level:int):Number
{
var levelY:Number = 0;
if (node.count)
{
var linesY:Array = []; //массив Y для рисования связей.
for each(var child:TreeNode in node.children)
{
var cY:Number = drawTree(child, level + 1);
levelY += cY;
linesY.push(cY);
}
_levelsOffset[level + 1] += VGAP;
levelY = levelY / node.count;
if(levelY - _levelsOffset[level] >= VGAP)
_levelsOffset[level] = levelY;
else
{
_levelsOffset[level] += VGAP;
levelY = _levelsOffset[level];
}
//Рисуем связи
for each(cY in linesY)
{
_g.moveTo(HGAP * level, levelY);
_g.lineTo(HGAP * (level + 1), cY);
}
}
else
{
levelY = _levelsOffset[level];
_levelsOffset[level] += VGAP;
//Запрещаем рисовать ноды чужих детей выше себя. Но тут надо подумать в примере не запрещено.
if(_levelsOffset[level + 1] < _levelsOffset[level])
_levelsOffset[level + 1] = _levelsOffset[level];
}
//Рисуем ноду
_g.drawCircle(HGAP * level, levelY, 5);
return levelY;
}
}
}
Код AS3:
package
{
/**
* ...
* @author gbee
*/
public class TreeNode
{
public var children:Array = [];
public var count:int = 0;
public function TreeNode()
{
}
}
}