doLayout method

  1. @override
void doLayout(
  1. Context context,
  2. Graph graph,
  3. num width,
  4. num height,
)
override

Implementation

@override
void doLayout(Context context, Graph graph, num width, num height) {
  List<GraphNode> nodes = graph.nodes;
  int n = graph.nodes.length;
  if (n == 0) {
    onLayoutEnd();
    return;
  }
  List<num> center = [this.center[0].convert(width), this.center[1].convert(height)];
  if (n == 1) {
    nodes[0].x = center[0].toDouble();
    nodes[0].y = center[1].toDouble();
    onLayoutEnd();
    return;
  }

  List<GraphNode> layoutNodes = graph.nodes;
  Map<GraphNode, num> sortMap = _innerSortNode(graph, layoutNodes);

  ///数据分层
  var maxValueNode = layoutNodes[0];
  var maxValue = sortMap[maxValueNode] ?? 0;
  var maxLevelDiff = this.maxLevelDiff ?? maxValue / 4;
  Map<int, List<GraphNode>> levelMap = {};
  for (var ele in layoutNodes) {
    if (ele == maxValueNode) {
      continue;
    }
    var levelIndex = (maxValue - (sortMap[ele] ?? 0)) ~/ maxLevelDiff;
    levelIndex + 1;
    List<GraphNode> levelList = levelMap[levelIndex] ?? [];
    levelMap[levelIndex] = levelList;
    levelList.add(ele);
  }

  ///没有存储最大点的值
  List<List<GraphNode>> levelList = [];
  List<num> keyList = List.from(levelMap.keys);
  keyList.sort();
  for (var index in keyList) {
    levelList.add(levelMap[index]!);
  }

  ///计算每个分层的半径和大小
  Map<int, _LevelInfo> infoMap = {};
  for (int i = 0; i < levelList.length; i++) {
    var level = levelList[i];
    _LevelInfo info = infoMap[i] ?? _LevelInfo();
    infoMap[i] = info;
    var maxSizeNode = findMaxSizeNode(level);
    if (i == 0) {
      info.r = getNodeSize(maxSizeNode) + getNodeSize(maxValueNode);
      info.angleSpace = computeLevelAngleSpace(level, info.r);
    } else {
      _LevelInfo lastLevel = infoMap[i - 1]!;
      info.r = getNodeSize(maxSizeNode) + lastLevel.r + getNodeSize(findMaxSizeNode(levelList[i - 1]));
      info.angleSpace = computeLevelAngleSpace(level, info.r);
    }
  }

  ///等距
  if (equidistant) {
    _LevelInfo info = infoMap.values.first;
    infoMap.forEach((key, value) {
      if (value.r > info.r) {
        info = value;
      }
    });
    infoMap.forEach((key, value) {
      value.r = info.r;
      value.angleSpace = computeLevelAngleSpace(levelList[key], value.r);
    });
  }

  ///布局
  for (int i = 0; i < levelList.length; i++) {
    var level = levelList[i];
    var levelInfo = infoMap[i]!;
    num rr = levelInfo.r;
    num ap = levelInfo.angleSpace;

    num startAngle = this.startAngle;
    for (int j = 0; j < level.length; j++) {
      var node = level[j];
      node.x = center[0] + rr * cos(startAngle * Constants.angleUnit);
      node.y = center[1] + rr * sin(startAngle * Constants.angleUnit);
      num nodeAngle = computeNodeAngle(node, rr);
      startAngle += (clockwise ? 1 : -1) * (ap + nodeAngle);
    }
  }

  ///最大节点
  maxValueNode.x = center[0].toDouble();
  maxValueNode.y = center[1].toDouble();

  onLayoutEnd();
}