这是之前那篇关于C++实现决策树的子问题。用不了Python的Matplotlib,只能用OpenCV手撕。
假定我们要实现这样一个三层四叉树的结构。(画图软件太费时间了直接纸上画了)需要的是画圆,直线和中间标的index写字。最主要的是求圆心坐标。

背景图片我是拿windows自带的画图弄了个20000*20000的全空白jpg。
一、建立树结构

遍历了一下,结果是这样没错。
二、计算坐标
然后拿CV画图比较麻烦的一点就是坐标的计算。
假定:最底层的是所有4的i次方个叶子节点的圆相切。每4个叶子节点圆上一层的根节点圆横坐标在第2、3个叶子节点的正中间位置。
如图,这是一个三层的满四叉树,以此为例。层数i取值为0-2。求出最大层数为max(此处为2)。设d为每个小圆的直径,r为半径,△H为每一层的高度。(d=2r)
1.每层开始A->G->……->T->C坐标总长度Li的计算
可以看出,除了第0层是单个根节点,最底层是所有4max 个圆相切,这两层是特殊的,要单独讨论。其他中间层都是遵循规律的。
最底层长度L2=16 d=42 d。
第二层,所有圆的长度要减去最左和最右两个圆的直径,即L1=4maxd-4d。
该规律可通过四层满四叉树来泛化:
L1=4max d-16d
L2=4maxd-4d
L3=4max d

最后得到:
所以除了第一层和最底层,中间层的长度Li=4max-4max-id。
最底层长度L底=4max d。
2.每层的各个A->G->T->C坐标单长度L0的计算
1,第0层和最底层是特殊的,单独讨论。
将Li的长度细分为若干等长L0,一个根节点对应一个L0。
第1层总长度为L1,则L0=L1。
第2层总长度为L2,则L0=L2/4-d。因为要求的是A->G->T->C的长度,最底层一开始是统一计算一堆圆的直径,所以多了最左和最右2个半径。
为了泛化中间层规律,再次采用四层满四叉树:
L01=L1
L02=3L2/15
L03=L3/16-d
五层满四叉树:
L03=3L3/63
L04=L4/64-d

最后得到:
所以除了第一层和最底层,中间层的长度L0i=3Li/(4i -1)。
最底层长度L0底=L底/(4max-1)-d。
3.得到A,G,T,C的坐标
假设某个根节点的坐标为(x0,y0)。那么:
A(x0-L0/2,y0+△H)
G(x0-L0/6,y0+△H)
T(x0+L0/6,y0+△H)
C(x0+L0/2,y0+△H)
4.算法实现
此处树的结构体里我加了个tag,来区分节点的类型。以A点为例:

if (t->tag == 'a'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 2;pointY += 1000;}

三、做出图形
1.三层满四叉树

2.四层满四叉树

3.实现目标树结构
字体和圆形大小比1、2中有放大。

结论:我在反思是不是应该好好学一下Python,总这么手撕感觉不是个好办法。
Over.
代码

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc.hpp>
using namespace std;
using namespace cv;
struct treeNode
{int layer;int index;char tag;treeNode* aleaf;treeNode* gleaf;treeNode* tleaf;treeNode* cleaf;treeNode() :index(0), layer(0), tag(' '), aleaf(NULL), gleaf(NULL), tleaf(NULL), cleaf(NULL) {}
};
treeNode* createtreeNode()
{treeNode* t = new treeNode();t->aleaf = new treeNode();t->gleaf = new treeNode();t->tleaf = new treeNode();t->cleaf = new treeNode();t->aleaf->layer = 1;t->gleaf->layer = 1;t->tleaf->layer = 1;t->cleaf->layer = 1;t->aleaf->index = 1;t->gleaf->index = 2;t->tleaf->index = 3;t->cleaf->index = 4;t->aleaf->tag = 'a';t->gleaf->tag = 'g';t->tleaf->tag = 't';t->cleaf->tag = 'c';t->aleaf->aleaf = new treeNode();t->aleaf->tleaf = new treeNode();t->cleaf->aleaf = new treeNode();t->cleaf->gleaf = new treeNode();t->cleaf->cleaf = new treeNode();t->aleaf->aleaf->layer = 2;t->aleaf->tleaf->layer = 2;t->cleaf->aleaf->layer = 2;t->cleaf->gleaf->layer = 2;t->cleaf->cleaf->layer = 2;t->aleaf->aleaf->index = 5;t->aleaf->tleaf->index = 6;t->cleaf->aleaf->index = 7;t->cleaf->gleaf->index = 8;t->cleaf->cleaf->index = 9;t->aleaf->aleaf->tag = 'a';t->aleaf->tleaf->tag = 't';t->cleaf->aleaf->tag = 'a';t->cleaf->gleaf->tag = 'g';t->cleaf->cleaf->tag = 'c';return t;
}
vector<int> countLayer;
void traverseTree(treeNode* t)
{if (t == NULL) return;else{countLayer.push_back(t->layer);cout << "index:" << t->index << endl;traverseTree(t->aleaf);traverseTree(t->gleaf);traverseTree(t->tleaf);traverseTree(t->cleaf);}
}
int findMaxLayer(vector<int> c)
{int size = c.size();int max = 0;for (int i = 0; i < size; i++){if (c[i] > max)max = c[i];}return max;
}
Mat image = imread("untitled.jpg");
string intToChar(int n)
{char* num = new char[10];_itoa_s(n, num, sizeof(num), 10);string s = num;delete[] num;return s;
}
void drawTree(treeNode* t, double pointX, double pointY, string output)
{int radius = 200;//r;int maxLayer = findMaxLayer(countLayer);double previousX = pointX;double previousY = pointY;if (t == NULL) return;else{if (t->tag == 'a'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 2;pointY += 1000;}else if (t->tag == 'g'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += -L0 / 6;pointY += 1000;}else if (t->tag == 't'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += L0 / 6;pointY += 1000;}else if (t->tag == 'c'){double L = pow(4, maxLayer) * 2 * radius - pow(4, maxLayer - t->layer) * 2 * radius;double L0 = L * 3 / (pow(4, t->layer) - 1);if (t->aleaf == NULL && t->gleaf == NULL && t->tleaf == NULL && t->cleaf == NULL){L = pow(4, maxLayer) * 2 * radius;L0 = L / pow(4, t->layer - 1) - 2 * radius;}pointX += L0 / 2;pointY += 1000;}else if (t->tag == ' '){pointX = 10000;pointY = 1000;}output = intToChar(t->index);line(image, Point(previousX, previousY), Point(pointX, pointY), Scalar(0, 0, 0), 20);circle(image, Point(previousX, previousY), radius, Scalar(0, 0, 0), 20);circle(image, Point(previousX, previousY), radius - 10, Scalar(255, 255, 255), -1);circle(image, Point(pointX, pointY), radius, Scalar(0, 0, 0), 20);circle(image, Point(pointX, pointY), radius - 10, Scalar(255, 255, 255), -1);drawTree(t->aleaf, pointX, pointY, output);drawTree(t->gleaf, pointX, pointY, output);drawTree(t->tleaf, pointX, pointY, output);drawTree(t->cleaf, pointX, pointY, output);putText(image, &output[0], Point(pointX - 100, pointY + 100), 0, 10, Scalar(0, 0, 0), 20);}
}
void drawTreeTotal(treeNode* t)
{double xCircle = 10000;//x0;double yCircle = 1000;//y0;namedWindow("tree", CV_WINDOW_NORMAL);imshow("tree", image);drawTree(t, xCircle, yCircle,"");
}
int main()
{treeNode* t = createtreeNode();traverseTree(t);drawTree(t, 10000, 1000, "");drawTreeTotal(t);waitKey(0);system("pause");return 0;
}

OpenCV C++实现树结构可视化(画出一棵四叉树)相关推荐

  1. 【圣诞快乐】用 C 语言画出一棵带有装饰的简易圣诞树

    一.前言 2022年圣诞节到来了,给大家画一棵圣诞树,希望大家都能安全地度过这个困难的时刻,希望所有糟糕的都是经历,所有的美好都会在之后到来,希望明年的还能画下新的一棵圣诞树. 总所周知,圣诞树(Ch ...

  2. 用python的opencv库在图片上画出蓝底黑字的文本框

    以下是使用Python的OpenCV库实现在图片上绘制的示例代码: import cv2# 读入图片 img = cv2.imread('example.jpg')# 在图片上绘制红色矩形框 cv2. ...

  3. 用python的opencv画出一棵树的骨架

    如果你也想赚钱,实现财务自由,但接触不到优质的人脉和资源,可以到公June浩:成长home,发"资源" ,就会看到我吐血整理的168条保姆级零基础吸金秘籍,跟着我一起亲历毕业5年. ...

  4. 人体姿态估计中的可视化---画出预测关节位置3D图和地面真实图

    根据模型预测关节位置和真实关节位置画3维图 import pickle import tensorflow as tfimport matplotlib matplotlib.use('TkAgg') ...

  5. 用python画出圣诞树_【闲趣】如何用python画出一棵圣诞树

    C语言你会了,python你会不会? import turtle screen = turtle.Screen() screen.setup(800,600) circle = turtle.Turt ...

  6. 汇编:动态画出一棵七彩圣诞树

    好久没有写文章了,其实想写的有很多,光是汇编代码就有很多知识点值得记下来,但是蓝癌症犯了,总是拖着,今天先写一点,以后慢慢把东西都写到这来吧. 这是 在寒假写的一个汇编程序代码如下: assume c ...

  7. 樱花的季节,教大家用canvas画出飞舞的樱花树

    又到了樱花的季节,教大家使用canvas画出飞舞的樱花树效果. 废话少说,先看效果. 演示效果地址:http://suohb.com/work/tree4.htm 查看演示效果 第一步,我们先画出一棵 ...

  8. java代码画樱花_樱花的季节,教大家用CANVAS画出飞舞的樱花树

    又到了樱花的季节,教大家使用canvas画出飞舞的樱花树效果. 废话少说,先看效果. 演示效果地址:http://suohb.com/work/tree4.htm 第一步,我们先画出一棵树的主体. 我 ...

  9. java代码画樱花飘落_樱花的季节,教大家用canvas画出飞舞的樱花树

    又到了樱花的季节,教大家使用canvas画出飞舞的樱花树效果. 废话少说,先看效果. 演示效果地址:http://suohb.com/work/tree4.htm 第一步,我们先画出一棵树的主体. 我 ...

最新文章

  1. 芯片初创公司一亿融资可以烧多久
  2. 【深度学习】锐化滤波器核 与 边缘检测核
  3. BSEG和BSIS、BSAS、BSID、BSAD、BSIK、BSAK六个表的关系
  4. delphi 调 web api_小程序web同构Kbone
  5. linux服务器安装zookeeper本地项目远程连接
  6. java获取单击内容,java – 单击菜单链接时,获取元素不是可点击的异常
  7. Python风格总结:循环语句
  8. 制作日历组件,点击出来一个弹窗
  9. android(八)、触摸事件分发
  10. python全局变量被覆盖的问题
  11. CSDN发布:AI技术人才成长路线图
  12. python爬取微博用户信息_Python爬取新浪微博用户信息及内容
  13. java的泛型方法_Java中的泛型方法
  14. RTKLIB源码调试.trace文件解析.stat文件解析
  15. 有关“十二生肖”的成语
  16. 全国大江大河实时水情数据下载
  17. 一线城市上海的户口有多好?
  18. CF 1324-F Maximum White Subtree //树形换根dp
  19. UnityShader入门精要-屏幕后处理效果 亮度饱和度对比度、边缘检测、高斯模糊、bloom效果、运动模糊
  20. MySQL中where 1=1真的会影响性能么?

热门文章

  1. day29 | 黑马程序员Java全程笔记 | 第二阶段MySQL高级事务-索引-视图-触发器-存储过程
  2. 数理统计与数据分析第三版习题 第3章 第5题
  3. 04oracle单表查询、连接查询、子查询
  4. ERROR 1366 (HY000): Incorrect string value: '\xE8\xB5\xB5\xE9\x9B\xB7' for column 'Sname' at row 1
  5. 02. Yii 2.0 框架的目录结构
  6. 大数据开发 电脑内存大小
  7. 【C++】-- C++11基础常用知识点(下)
  8. MFC获取菜单、修改菜单文字
  9. 超美二次元响应式引导页源码
  10. Elasticsearch 实现类似SQL语句中like %关键字% 的单纯模糊查询(不进行分词)