当前位置: 首页 > news >正文

基于C#窗体+GDI+绘图实现分形树

实验:分形树

一.  引言

实验目的:继续学习C#窗体应用程序的图形化界面设计以及GDI+绘图的一些基本指示,通过制作各种类型的分形树增强对于递归的理解,在创造分形图形的过程中感受编程的快乐

Tutorial任务

1.制作不同类型的分形图形(本次演示的是两种不同类型的分形树)

2.设计一个美观合理的UI界面

3.巩固关于打开文件和保存文件的操作

二.实验环境

Windows系统下的visual studio 2017

C#窗体应用程序

三.实验流程

1.实验原理介绍

首先,我们先介绍一下分形图形的绘制过程(由于分形图形的种类有很多种,但大多数是采用了递归的思想进行绘制,所以本文以较为常见和相对来讲难度不那么大的分形树进行讲解,感兴趣的读者可以尝试去制作更为复杂的分形图形)

首先,我们先来看一段分形树绘制的核心代码

private void paintFractalTree(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line)
{float yf = yo - (sin(Converttohudu(dangle)) * length);//sin函数将角度转换成弧度float xf = xo - (cos(Converttohudu(dangle)) * length);line.DrawLine(pen, xo, yo, xf, yf);paintFractalTree(pen2, xf, yf, depth - 1, dangle + angle, length, angle, line);paintFractalTree(pen3, xf, yf, depth - 1, dangle - angle, length, angle, line);//画左分支
}
在上述的代码中我们已经看到了递归的影子,接下来会对递归流程进行详细介绍:

百度百科当中关于分形这个几何学术语的解释如下:

分形,具有以非整数维形式充填空间的形态特征。通常被定义为“一个粗糙或零碎的几何形状,可以分成数个部分,且每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。
分形使人们觉悟到科学与艺术的融合,数学与艺术审美上的统一,使从前枯燥的数学不再仅仅是抽象的哲理,而是具体的感受;不再仅仅是揭示一类存在,而是一种艺术创作,分形搭起了科学与艺术的桥梁。

通过"每一部分都(至少近似地)是整体缩小后的形状”,即具有自相似的性质。这一点也能够看出做出分形图案的主要思想就是递归.

我们先考虑当分形树的分形元是下述图案的情况:

这个分形元在C#中是怎么绘制出来的呢?

1.首先,我们设A点坐标为(x,y),B点坐标为(x0,y0)

2.接下来绘制AB这条直线,也就是树的主干部分,即(x,y)--(x0,y0)直线,同时注意到,AB这条线段与横轴的夹角为90度,那么我们就以这个90度作为基础,结合用户输入的angle角度的可调整值,来绘制接下来的分形树分支

3.假设C点坐标为(x1,y1),则由三角函数的性质,结合上图中的α角我们可以看出C点的横坐标为x0-L'×cos(90°-α)(注意,这里面的L'指的是枝干的长度,为了让我们的分形树绘制的更加美观,这里面取枝干长度L'=2L/3,α就是用户输入的角度值)

4.类比3的思路,C点的y坐标y1为y0-L'×sin(90°-α)(值得注意的是,绘图板的左上角为(0,0),所以在向上绘制的时候相应的y坐标就会减少)

5.结合刚才的思想,我们很容易根据图中的提示绘制出右侧的分支,D点的横坐标为x0-L'×cos(90°+α),D点的纵坐标为y0-L'×sin(90°+α),如上图所示

6.连接BC,BD,分形元绘制完成

2.实验过程

这个时候我们回过头来看刚才的那段代码,就显得清楚多了

private void paintFractalTree(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line)//dangle是目前的角度,也就是刚才说的(90+angle)或者(90-angle)传入作为dangle(其实就是需要计算正余弦的角度)
{float yf = yo - (sin(Converttohudu(dangle)) * length);//sin函数将角度转换成弧度,算出新的点所应该在的位置的纵坐标float xf = xo - (cos(Converttohudu(dangle)) * length);//算出新的点所应该在的位置的横坐标line.DrawLine(pen, xo, yo, xf, yf);//将原来点和新的点之间连一条线paintFractalTree(pen2, xf, yf, depth - 1, dangle + angle, length, angle, line);//递归画右分支paintFractalTree(pen3, xf, yf, depth - 1, dangle - angle, length, angle, line);//画左分支
}
//对于递归部分而言,需要注意再下一次递归的时候初始角度相当于不再是90度了,而是90-a(如果是左分支的话),或者是(90+a)(如果是右分支的话),以后每次递归都需要更新前面的角度值(也就是每次传入参数的dangle),通过设置递归深度可以绘制出如下的美丽图形:

注:读者可以在上述基础上做出创新,比如给这颗分形树绘制不同的颜色,让不同的分支长度不同等等,在这里我绘制了一种随机颜色的分形树,效果和代码部分如下:

private void paintFractalTree(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line){if (depth > -1){length = length * 2 / 3;float yf = yo - (sin(Converttohudu(dangle)) * length);//转换成弧度float xf = xo - (cos(Converttohudu(dangle)) * length);line.DrawLine(pen, xo, yo, xf, yf);Random rnd = new Random();// 随机色生成,可以画出彩色的树Color myColor1 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen2 = new Pen(myColor1);paintFractalTree(pen2, xf, yf, depth - 1, dangle + angle, length, angle, line);//画右分支Color myColor2 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen3 = new Pen(myColor2);paintFractalTree(pen3, xf, yf, depth - 1, dangle - angle, length, angle, line);//画左分支}}

几个较为美观的色彩图如下图所示:

通过不同的angle角度的设置,可以产生许多好看的图形,以上为30度和60度以及90度设置下的图形,读者可以自行尝试其他方案,绘制更好看的分形树

3.实验创新

绘制出了上述的最简单的分形树之后,我们也许会思考其他分形元是不是会画出其他神奇的分形图案?答案是肯定的,接下来我会以我绘制的第二种分形树为例,向读者展示绘制不同种分形树的一般方法:

首先来看第二种分形树的效果图:

细心的读者可能已经发现了,实际上绘制一颗分形树的要点就在于一定要掌握好递归的思想,我们简单看一下上图就不难分析出分形元是如下这种图形了:

再分解一下其实就是图中的黑色部分了,也就是我们首先要绘制出黑色的部分,具体的原理读者可以自行尝试一下,在这里直接给出核心代码:

private void paintFractalTree2(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line){double attach = 50;if (depth > -1){float changelength = length * 2 / 3;float x1 = xo - (cos(Converttohudu(dangle))) * length;float y1 = yo- (sin(Converttohudu(dangle)))*length;float x2 = x1 - (cos(Converttohudu(dangle))) * changelength;float y2 = y1 - (sin(Converttohudu(dangle))) * changelength;float x2r = x1 - (cos(Converttohudu(dangle+angle))) * changelength;float y2r = y1 - (sin(Converttohudu(dangle+angle))) * changelength;float x2l = x1 - (cos(Converttohudu(dangle -angle))) * changelength;float y2l = y1 - (sin(Converttohudu(dangle - angle))) * changelength;line.DrawLine(pen, xo, yo, x1, y1);//line.DrawLine(pen, x1, y1, x2, y2);line.DrawLine(pen, x1, y1, x2r, y2r);//line.DrawLine(pen, x1, y1, x2l, y2l);Random rnd = new Random();// 随机色生成Color myColor1 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen2 = new Pen(myColor1);paintFractalTree2(pen2, x2r, y2r, depth - 1, dangle + angle*3/2 + angle, length*2/3, angle, line);//画右分支,这里让角度发生了变化,起到一个图形"折起来"的效果paintFractalTree2(pen2, x2r, y2r, depth - 1, dangle + angle * 3 / 2 - angle, length*2/3, angle, line);//画左分支//paintFractalTree2(pen2, x2l, y2l, depth - 1, dangle - angle * 3 / 2 - angle, length*2/3, 
//这句话加上去又是一种新的图案了,可以试试?Color myColor2 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen3 = new Pen(myColor2);}}

到这里,我们的两种分形树就绘制完成了,可以结合之前的画图软件的操作将我们喜欢的分形树图案保存起来,也可以打开之前绘制好的分形树图案,绘制的窗体界面如下:

总的代码如下图所示(窗体设计部分已省去)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
using System.IO;namespace FractalTree
{public partial class Form1 : Form{bool click1 = false;bool click2 = false;//文件名public string curFileName= @"E:\期末考试复习\C#\分形树v3.0\FractalTree\FractalTree\bin\Debug\picture.jpg";//图像对象private System.Drawing.Bitmap curBitmap;//public Bitmap bmp = new Bitmap(769, 650);public Form1(){InitializeComponent();this.MaximizeBox = false;this.Size = new Size(769, 650);this.CenterToScreen();this.FormBorderStyle = FormBorderStyle.FixedSingle;picturebox.BorderStyle = BorderStyle.Fixed3D;this.Text = "分形树";curBitmap = (Bitmap)Image.FromFile(curFileName);//Graphics g = Graphics.FromImage(bmp);//picturebox.Image = ;//curBitmap = (Bitmap)bmp;}public void pictureBox_Paint(object sender, PaintEventArgs e){//Graphics g = this.CreateGraphics();//picturebox.Refresh();if (curBitmap != null){//使用DrawImage的方法绘制图像Graphics g = e.Graphics;//curBitmap.Width, curBitmap.Height图像的宽度和高度g.DrawImage(curBitmap, 0, 0, curBitmap.Width, curBitmap.Height);}if (click1){//picturebox.Refresh();//Graphics g = e.Graphics;//if(curFileName!=null)curBitmap = (Bitmap)Image.FromFile(curFileName);//else//  curBitmap = bmp;this.picturebox.Image = curBitmap;Graphics g = Graphics.FromImage(this.picturebox.Image);Pen pen = new Pen(Color.Black);float length = Convert.ToSingle(tb1.Text) * 10;double angle = Convert.ToDouble(nud3.Value);int depth = Convert.ToInt32(nud1.Value);float xo = (picturebox.Width / 2) - 2;float yo = picturebox.Height - Convert.ToSingle(5.4);  paintFractalTree(pen, xo, yo, depth, 90, length, angle, g);//那个90是确定这颗树往哪个方向开始长的pen.Dispose();click1 = false;}else if(click2){//picturebox.Refresh();if (curFileName != null)curBitmap = (Bitmap)Image.FromFile(curFileName);//else//  curBitmap = bmp;this.picturebox.Image = curBitmap;Graphics g = Graphics.FromImage(this.picturebox.Image);//Graphics g = e.Graphics;Pen pen = new Pen(Color.Black);float length = Convert.ToSingle(tb1.Text) * 10;double angle = Convert.ToDouble(nud3.Value);int depth = Convert.ToInt32(nud1.Value);float xo = (picturebox.Width / 2) - 2;float yo = picturebox.Height - Convert.ToSingle(5.4);paintFractalTree2(pen, xo, yo, depth, 90, length*1/2, angle, g);//那个90是确定这颗树往哪个方向开始长的pen.Dispose();click2 = false;}}private void paintFractalTree(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line){if (depth > -1){length = length * 2 / 3;float yf = yo - (sin(Converttohudu(dangle)) * length);//转换成弧度float xf = xo - (cos(Converttohudu(dangle)) * length);line.DrawLine(pen, xo, yo, xf, yf);Random rnd = new Random();// 随机色生成Color myColor1 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen2 = new Pen(myColor1);paintFractalTree(pen2, xf, yf, depth - 1, dangle + angle, length, angle, line);//画右分支Color myColor2 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen3 = new Pen(myColor2);paintFractalTree(pen3, xf, yf, depth - 1, dangle - angle, length, angle, line);//画左分支}}private void paintFractalTree2(Pen pen, float xo, float yo, int depth, double dangle, float length, double angle, Graphics line){double attach = 50;if (depth > -1){float changelength = length * 2 / 3;float x1 = xo - (cos(Converttohudu(dangle))) * length;float y1 = yo- (sin(Converttohudu(dangle)))*length;float x2 = x1 - (cos(Converttohudu(dangle))) * changelength;float y2 = y1 - (sin(Converttohudu(dangle))) * changelength;float x2r = x1 - (cos(Converttohudu(dangle+angle))) * changelength;float y2r = y1 - (sin(Converttohudu(dangle+angle))) * changelength;float x2l = x1 - (cos(Converttohudu(dangle -angle))) * changelength;float y2l = y1 - (sin(Converttohudu(dangle - angle))) * changelength;line.DrawLine(pen, xo, yo, x1, y1);//line.DrawLine(pen, x1, y1, x2, y2);line.DrawLine(pen, x1, y1, x2r, y2r);//line.DrawLine(pen, x1, y1, x2l, y2l);Random rnd = new Random();// 随机色生成Color myColor1 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen2 = new Pen(myColor1);paintFractalTree2(pen2, x2r, y2r, depth - 1, dangle + angle*3/2 + angle, length*2/3, angle, line);//画右分支paintFractalTree2(pen2, x2r, y2r, depth - 1, dangle + angle * 3 / 2 - angle, length*2/3, angle, line);//画右分支//paintFractalTree2(pen2, x2l, y2l, depth - 1, dangle - angle * 3 / 2 - angle, length*2/3, angle, line);//画右分支//paintFractalTree2(pen2, x2l, y2l, depth - 1, dangle - angle * 3 / 2 + angle, length * 2 / 3, angle, line);//画右分支Color myColor2 = Color.FromArgb(rnd.Next(0, 255), /*红色*/rnd.Next(0, 255), /*绿色*/rnd.Next(0, 255)  /*蓝色*/);Pen pen3 = new Pen(myColor2);}}private float cos(double angle){return (float)Math.Cos(angle);}//求cos的值private float sin(double angle){return (float)Math.Sin(angle);}//求sin的值private double Converttohudu(double angle){return (Math.PI * angle) / 180;}//将角度转换成弧度private void textBox1_KeyPress(object sender, KeyPressEventArgs e){if (!Char.IsDigit(e.KeyChar) && !Char.IsControl(e.KeyChar) && !e.KeyChar.Equals(',')){e.Handled = true;//可以从文本框中获取键盘读入的数据}}private void drawbt_Click(object sender, EventArgs e){click1 = true;picturebox.Refresh();}private void nud3_ValueChanged(object sender, EventArgs e){}private void nud1_ValueChanged(object sender, EventArgs e){}private void Form1_Load(object sender, EventArgs e){}private void 打开ToolStripMenuItem_Click(object sender, EventArgs e){OpenFileDialog opnDlg = new OpenFileDialog();opnDlg.Filter = "所有图像文件 | *.bmp; *.pcx; *.png; *.jpg; *.gif;" +"*.tif; *.ico; *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf|" +"位图( *.bmp; *.jpg; *.png;...) | *.bmp; *.pcx; *.png; *.jpg; *.gif; *.tif; *.ico|" +"矢量图( *.wmf; *.eps; *.emf;...) | *.dxf; *.cgm; *.cdr; *.wmf; *.eps; *.emf";opnDlg.Title = "打开图像文件";opnDlg.ShowHelp = true;if (opnDlg.ShowDialog() == DialogResult.OK){curFileName = opnDlg.FileName;try{curBitmap = (Bitmap)Image.FromFile(curFileName);}catch (Exception exp){MessageBox.Show(exp.Message);}}//对窗体进行重新绘制,这将强制执行paint事件处理程序Invalidate();picturebox.Refresh();}//private void Form1_Paint(object sender, PaintEventArgs e)//{//    //使用窗体的Paint事件的PaintEventArgs属性来获取一个与窗体相关联的Graphic对象。//    Graphics g = e.Graphics;//    if (curBitmap != null)//    {//        //使用DrawImage的方法绘制图像//        //160,20 :显示在主窗体内,图像左上角的坐标//        //curBitmap.Width, curBitmap.Height图像的宽度和高度//        g.DrawImage(curBitmap, 160, 20, curBitmap.Width, curBitmap.Height);//    }//}public void 保存ToolStripMenuItem_Click(object sender, EventArgs e ){ }private void button1_Click(object sender, EventArgs e){click2 = true;picturebox.Refresh();}private void 保存ToolStripMenuItem_Click_1(object sender, EventArgs e){if (curBitmap == null){return;}Graphics g = Graphics.FromImage(curBitmap);SaveFileDialog saveDlg = new SaveFileDialog();saveDlg.Title = "保存为";saveDlg.OverwritePrompt = true;saveDlg.Filter ="BMP文件 (*.bmp) | *.bmp|" +"Gif文件 (*.gif) | *.gif|" +"JPEG文件 (*.jpg) | *.jpg|" +"PNG文件 (*.png) | *.png";saveDlg.ShowHelp = true;if (saveDlg.ShowDialog() == DialogResult.OK){string fileName = saveDlg.FileName;string strFilExtn = fileName.Remove(0, fileName.Length - 3);switch (strFilExtn){case "bmp":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Bmp);break;case "jpg":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);break;case "gif":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Gif);break;case "tif":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Tiff);break;case "png":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);break;default:break;}}}private void 另存为ToolStripMenuItem_Click(object sender, EventArgs e){if (curBitmap == null){return;}Graphics g = Graphics.FromImage(curBitmap);SaveFileDialog saveDlg = new SaveFileDialog();saveDlg.Title = "保存为";saveDlg.OverwritePrompt = true;saveDlg.Filter ="BMP文件 (*.bmp) | *.bmp|" +"Gif文件 (*.gif) | *.gif|" +"JPEG文件 (*.jpg) | *.jpg|" +"PNG文件 (*.png) | *.png";saveDlg.ShowHelp = true;if (saveDlg.ShowDialog() == DialogResult.OK){string fileName = saveDlg.FileName;string strFilExtn = fileName.Remove(0, fileName.Length - 3);switch (strFilExtn){case "bmp":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Bmp);break;case "jpg":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Jpeg);break;case "gif":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Gif);break;case "tif":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Tiff);break;case "png":curBitmap.Save(fileName, System.Drawing.Imaging.ImageFormat.Png);break;default:break;}}}}}

至此,我们的分形树以及相关代码实现就完成了。

相关文章:

基于C#窗体+GDI+绘图实现分形树

实验:分形树 一. 引言 实验目的:继续学习C#窗体应用程序的图形化界面设计以及GDI绘图的一些基本指示,通过制作各种类型的分形树增强对于递归的理解,在创造分形图形的过程中感受编程的快乐 Tutorial任务 1.制作不同类型的分形图形(本次演示的是两种不同类型的分…...

使用Langchain+DeepSeep进行测试相关工作

1.使用BaseChatModel实现自定义DeepSeekLLM import json import typing from typing import Optional, Any, List, Dict, Union, Sequence, Callable, Literalimport requests from langchain_core.callbacks import CallbackManagerForLLMRun from langchain_core.language_m…...

Java练习6

一.题目 数字加密与解密 需求: 某系统的数字密码(大于 0),比如 1983,采用加密方式进行传输。 规则如下: 先得到每位数,然后每位数都加上 5,再对 10 求余,最后将所有数字反转,得到一…...

二叉树知识点

1、树形结构 1.1概念 二叉树属于树形结构,所以先了解树形结构之后,再学习二叉树。 树形结构是一种非线性的数据结,是由n个有限节点组成的一个具有层次关系的集合,其形状就像一棵到这的树,跟朝上,叶子朝下…...

neo4j暴露公网ip接口——给大模型联通知识图谱

特别鸣谢 我的领导,我的脑子,我的学习能力,感动了 1. 搭建知识图谱数据库(见上一章博客) 这里不加赘述了,请参考上一篇博客搭建 2. FastApi包装接口 这里注意:NEO4J_URI不得写http:,只能写…...

在阿里云实例上部署通义千问QwQ-32B推理模型

通义千问QwQ-32B是阿里云开源的320亿参数推理模型,通过大规模强化学习在数学推理、编程及通用任务中实现性能突破,支持消费级显卡本地部署,兼顾高效推理与低资源消耗。 本文将介绍如何利用vLLM作为通义千问QwQ-32B模型的推理框架,在一台阿里云GPU实例上构建通义千问QwQ-32…...

GEE进行Theil-Sen Median斜率估计和Mann-Kendall检验

介绍一下Theil-Sen Median斜率估计和Mann-Kendall趋势分析,这两种方法经常结合使用,前者用于估计趋势的斜率,后者用于检验趋势的显著性。如多年NPP或者NDVI的趋势分析。 主要介绍使用GEE实现这一内容的代码方法,若使用python&…...

WSL2下Docker desktop的Cadvisor容器监控

由于WSL2的Docker存放是在Linux的docker-desktop目录下,需要从这里面挂载到WSL2里的/var/lib/docker,并且正确挂载启动,才能使 Cadvisor 识别到docker容器并且监控资源。 首先需要在WSL2终端进行挂载操作: sudo mount -t drvfs \…...

深度学习---pytorch搭建深度学习模型(附带图片五分类实例)

一、PyTorch搭建深度学习模型流程 1. 环境准备 安装PyTorch及相关库: pip install torch torchvision numpy matplotlib2. 数据准备 数据集加载:使用内置数据集(如CIFAR-10)或自定义数据集。数据预处理:包括归一化…...

基于 STM32 的智慧图书馆智能控制系统设计与实现

一、系统架构概述 智慧图书馆智能控制系统集成环境调控、安全监控、借阅管理与信息推送功能,通过 STM32 主控芯片联动传感器、执行器及云平台,实现图书馆智能化管理。系统架构分为感知层(传感器)、控制层(STM32 主控)、执行层(继电器 / 显示屏)及云端层(数据交互),…...

4. python3基本数据类型

Python3 中有六个标准的数据类型: Number(数字) String(字符串) List(列表) Tuple(元组) Set(集合) Dictionary(字典) Pyt…...

什么是缓冲区溢出?NGINX是如何防止缓冲区溢出攻击的?

大家好,我是锋哥。今天分享关于【什么是缓冲区溢出?NGINX是如何防止缓冲区溢出攻击的?】面试题。希望对大家有帮助; 什么是缓冲区溢出?NGINX是如何防止缓冲区溢出攻击的? 缓冲区溢出是指程序试图向一个固定…...

4.27搭建用户界面

更新 router下面的index.js添加新的children 先区分一下views文件夹下的不同vue文件: Home.vue是绘制home页面的所有的表格。 Main.vue是架构头部和左侧目录的框架的。 研究一下这个routes对象,就可以发现重定向redirect的奥妙所在,我们先把…...

常用回环检测算法对比(SLAM)

回环检测本质上是一种数据相似性检测算法,原理是通过识别机器人是否回到历史位置,建立位姿约束以优化全局地图,纠正长期的里程计漂移实现全局地图的一致性,简单讲就是识别场景中的重复特征以修正累积误差。 1. 概述 算法类别原理特点优势劣势词袋模型特征聚类为单词,TF-I…...

《从线性到二维:CSS Grid与Flex的布局范式革命与差异解析》

在前端开发的广袤宇宙中,CSS布局技术宛如闪耀的星辰,不断革新与演进,为构建绚丽多彩的网页世界提供了坚实的支撑。其中,CSS Grid布局与Flex布局作为两颗璀璨的明星,以其独特的魅力和强大的功能,深受开发者们…...

理解 EKS CloudWatch Pod CPU Utilization 指标:与 `kubectl top` 及节点 CPU 的关系

在使用 AWS EKS 时,CloudWatch Container Insights 提供了丰富的容器级别监控指标,帮助我们深入了解应用的运行状态。如下截图中的 ContainerInsights pod_cpu_utilization 指标就是一个非常重要的维度。本文将详细解释这个指标的含义,并将其…...

解读JetBrains ToolBox以及Windows环境AppData的那点事

AppData 顾名思义应用程序数据,指的就是程序运行实例数据。用于存储应用程序的自定义设置和缓存数据。这些数据不仅包括程序个性化的配置,还涵盖了在应用程序运行过程中产生的临时文件和日志信息。 本身它是一个隐藏文件夹,位于每个用户的个人…...

Elasticsearch:ES|QL lookup JOIN 介绍 - 8.18/9.0

警告:此功能在 8.18/9.0 中刚推出。此功能处于技术预览阶段,未来版本可能会更改或删除。Elastic 会努力修复任何问题,但技术预览中的功能不受正式 正式发布功能支持 SLA 的约束。 ES|QL LOOKUP JOIN 处理命令将你的 ES|QL 查询结果表中的数据…...

基于开闭原则优化数据库查询语句拼接方法

背景 在开发实践中,曾有同事在实现新功能时,因直接修改一段数据库查询条件拼接方法的代码逻辑,导致生产环境出现故障。 具体来看,该方法通过在函数内部直接编写条件判断语句实现查询拼接,尽管从面向对象设计的开闭原…...

无人机航拍牛只检测数据集VOC+YOLO格式906张1类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):906 标注数量(xml文件个数):906 标注数量(txt文件个数):906 标注…...

【LeetCode 560】和为K的子数组(前缀和+哈希)

题面: 思路: 看到连续非空序列之和,容易想到前缀和计算差分, n u m s nums nums 区间 [ j , i ] [j,i] [j,i] 的和即为: s u m ( i , j ) p r e [ i ] − p r e [ j − 1 ] sum(i, j) pre[i] - pre[j-1] sum(i,j)…...

手术中评估帕金森患者手部运动的无接触式系统

南开大学韩建达教授研究团队提出一种针对帕金森病手术治疗的评估系统,可在手术中对患者手部运动进行实时监测,实现无接触式运动特征提取,并结合可视化数据分析辅助临床决策。相关研究论文“A non-contact system for intraoperative quantita…...

服务器主动发送响应?聊天模块如何实现?

一、背景知识 当我们在某聊天界面中发送一个消息时,如A给B发送了一个消息,而B马上就收到,仔细思考会发现以下问题 : 1. A给服务器发送请求,但服务器却给B发送了响应 2.B没有向服务器发送请求,却收到了…...

服务器远程超出最大连接数的解决方案是什么?

以下是为您撰写的关于服务器远程连接超限问题的解决方案论文,包含技术原理分析、解决策略和实际应用案例: 服务器远程连接超限问题分析与多维解决方案研究 摘要 随着数字化转型进程加速,服务器远程连接过载问题已成为企业IT运维领域的重大挑…...

【资料分享】全志T536(异构多核ARMCortex-A55+玄铁E907 RISC-V)工业核心板硬件说明书

前 言 本文为创龙科技SOM-TLT536工业核心板硬件说明书,主要提供SOM-TLT536工业核心板的产品功能特点、技术参数、引脚定义等内容,以及为用户提供相关电路设计指导。 为便于阅读,下表对文档出现的部分术语进行解释;对于广泛认同释义的术语,在此不做注释。...

Missashe考研日记-day30

Missashe考研日记-day30 0 写在前面 日记也是写到第30篇了哈哈,满月了,虽然过了不止30天中间有断更,但还是表扬一下自己坚持下来了。:) 1 专业课408 学习时间:2h30min学习内容: 今天有其他事…...

工程管理部绩效考核关键指标与项目评估

工程管理部的关键绩效考核指标(KPI)设计旨在全面评估部门在设施设备管理、特种设备保养、维修质量以及业主满意度等方面的工作表现。每个指标都与部门的日常运营紧密相关,直接影响到设施的维护质量和业主的满意度。 本文将深入探讨工程管理部的主要绩效考核指标&am…...

【沉浸式求职学习day29】【信科知识面试题第一部分】【新的模块,值得收藏】

快五一辣,大家什么安排呀哈哈哈~可能五一期间我就不更新啦,时间比较碎片化,要陪重要的人 沉浸式求职学习 理论攻坚-计算机基础知识1.诞生2.发展3.特点4.分类巨型 5.应用计算机辅助: 6.计算机的性能指标7.信息的存储单位 理论攻坚…...

Cliosoft安装

创建安装目录、解压 [rootedatest opt]# mkdir Cliosoft [rootedatest opt]# mv sos_7.05.p9/ Cliosoft/ [rootedatest opt]# cd Cliosoft/ [rootedatest Cliosoft]# cd sos_7.05.p9/ [rootedatest sos_7.05.p9]# tar -xf sos_7.05.p9_linux64.tar 用普通用户eda安装 [rooteda…...

MES管理系统:重构生产任务管理的数智化引擎

在制造业的数字化浪潮中,生产任务管理正从传统的经验驱动转向数据驱动的精细化模式。作为连接计划层与执行层的核心枢纽,MES管理系统通过智能化、动态化的管理手段,将生产任务的接收、分配、执行与优化融入全流程闭环,为企业打造透…...

推荐系统在线离线打分不一致:核心原因与全链路解决方案

目录 一、特征维度:数据处理的「隐形杀手」1.1 特征穿越:训练数据的「上帝视角」1.2 线上线下特征不一致的四大陷阱(1)上线前一致性校验缺失(2)线上特征监控体系缺位(3)特征更新延迟…...

Markdown转WPS office工具pandoc实践笔记

随着DeepSeek、文心一言、讯飞星火等AI工具快速发展,其输出网页内容拷贝到WPS Office过程中,文档编排规整的格式很难快速复制。 注:WPS Office不支持Markdown格式,无法识别式样。 在这里推荐个免费开源工具Pandoc,实现…...

记录java线程中断理解,Thread.currentThread().interrupt();

记录java线程中断理解,Thread.currentThread().interrupt(); 一、概述 中断的理解: 1、Java 线程中断,协作式(通过 Thread.interrupt() 触发,需代码显式检查中断状态或调用可中断方法)。 2、操作系统中断…...

[零基础]内网ubuntu映射到云服务器上,http访问(frp内网穿透)

阿里云服务器,高校教师可以半价, frp下载地址:https://github.com/fatedier/frp/releases,选amd64, 云服务器开放端口 选择网络与安全–>安全组->管理规则 配置开放端口,7000为支持frp开放的端口&…...

Nginx 核心功能笔记

目录 一、Nginx 简介 二、核心功能详解 三、关键指令解析 四、性能优化要点 五、常见应用场景 一、Nginx 简介 定位 高性能的 HTTP/反向代理服务器,同时支持邮件协议代理(IMAP/POP3/SMTP)。采用 事件驱动、异步非阻塞 架构,…...

多地部署Gerrit Replication插件同步异常解决思路及方案(附脚本与CronJob部署)

背景 为了支持多地开发,我司在代码服务器(Gerrit)上使用了Replication插件,进行多地部署同步。 整体结构如下: A地区:主Gerrit服务器B地区:从Gerrit服务器正常的工作流程是: B地区开发者从从服务器拉取代码。B地区开发者向主服务器推送代码。Replication插件保证主从数…...

JAVA--- 关键字static

之前我们学习了JAVA 面向对象的一些基本知识,今天来进阶一下!!! static关键字 static表示静态,是JAVA中的一个修饰符,可以修饰成员方法,成员变量,可用于修饰类的成员(变…...

清华与智谱联合发布TTS模型GLM-4-Voice,支持情绪、语气控制,多语言,实时效果很不错~

项目背景 GLM-4-Voice是由清华大学知识工程组(Tsinghua KEG)和智谱AI(Zhipu AI)联合开发的一个开源端到端语音对话模型,旨在推动语音交互技术的进步,弥合机器与人类自然对话之间的差距。 语音交互的挑战与…...

华为云Astro大屏从iotda影子设备抽取数据做设备运行状态的大屏实施步骤

目录 背景与意义 1. 准备阶段 2. IoTDA 开放影子查询API 3. Astro轻应用创建连接器 4. Astro大屏设计界面 5. 数据绑定与交互逻辑 6. 发布与测试 小结(流程复盘) 背景与意义 随着物联网技术的快速发展,越来越多的设备接入云端&#x…...

Microsoft .NET Framework 3.5 离线安装包 下载

Microsoft. NET Framework 3.5 是支持生成和运行下一代应用程序和XML Web Services 的内部Windows 组件, 对 .NET Framework 2.0 和 3.0 中的许多新功能进行了更新和增补, 且附带了 .NET Framework 2.0 Service Pack 1 和 .NET Framework 3.0 Service…...

通用人工智能(AGI)的技术演进

通用人工智能(AGI)的技术演进是一个漫长而充满探索的过程,涉及多个领域的技术突破和理念转变。以下是对其演进历程的详细介绍: 早期人工智能探索(20世纪50年代 - 80年代) 符号主义兴起:1950年…...

mac word接入deepseek

网上大多使用Windows版word来接入deepseek,vba文件引入mac后,因底层工具不同,难以直接运行,例如CreateObject("MSXML2.XMLHTTP")无法创建,为此写了一版新的vba,基于mac底层工具来实现。 vba文件点…...

基于大模型的大肠息肉全程管理研究报告

目录 一、引言 1.1 研究背景与意义 1.2 研究目的 二、大模型预测大肠息肉的原理与数据基础 2.1 大模型的技术原理简介 2.2 数据收集与处理 三、术前预测与准备方案 3.1 息肉特征及风险预测 3.2 患者身体状况评估 3.3 术前准备措施 四、术中方案制定与监控 4.1 手术…...

Liunx安装Apache Tomcat

目录 一、了解tomcat 二、下载 三、启动tomcat 四、网页访问tomcat 五、Tomcat修改默认8080端口 六、Tomcat创建项目步骤-实现项目对外访问 一、了解tomcat Apache Tomcat 是一个开源的 Java Servlet 容器 和 Web 服务器,主要用于运行基于 Java 的 Web 应用…...

Java基于MyBatis 实现前端组装查询语句、后端动态执行查询的功能

1. 前端设计 前端逻辑与之前的设计保持一致,依然是将用户输入的查询条件组装成 JSON 格式,并通过 HTTP 请求发送到后端。 示例请求体: {"filters": [{"field": "name","operator": "LIKE",...

RabbitMQ Linux 安装教程详解

RabbitMQ Linux 安装教程详解 在 Linux 系统上安装 RabbitMQ 并确保其稳定运行,对于构建可靠的分布式消息系统至关重要。本文将详细介绍如何在 Linux 系统上安装 RabbitMQ,并提供关键的注意事项,帮助您避免常见的坑点,确保安装过…...

健康养生:拥抱活力生活

在生活节奏日益加快的当下,人们对健康养生的重视程度与日俱增。健康养生并非是一时的跟风之举,而是一种关乎生活品质与生命长度的科学理念和生活方式,其核心在于通过合理的饮食、适度的运动、充足的睡眠以及良好的心态调节,达成身…...

京东商品数据实时采集指南:API 接口调用与数据解析实战

在当今数字化时代,数据已经成为企业决策和市场分析的重要依据。对于电商领域的从业者来说,实时采集京东等平台的商品数据,能够帮助他们了解市场动态、分析竞争对手以及优化自身的产品策略。本文将详细介绍如何通过 API 接口调用实现京东商品数…...

最新字节跳动运维云原生面经分享

继续分享最新的go面经。 今天分享的是组织内部的朋友在字节的go运维工程师岗位的云原生方向的面经,涉及Prometheus、Kubernetes、CI/CD、网络代理、MySQL主从、Redis哨兵、系统调优及基础命令行工具等知识点,问题我都整理在下面了 面经详解 Prometheus …...

AimRT 从零到一:官方示例精讲 —— 六、pb_chn示例.md

pb_chn示例 官方仓库:pb_chn 这个官方示例展示了如何基于 protobuf 协议和 local 后端实现 channel 通信。主要包括四种场景: 基础示例:分别用两个模块(Publisher 和 Subscriber)发布和订阅 protobuf 消息&#xff…...