心动(GDI+)

文章目录

  • 前言
  • 实现步骤
  • 源代码
    • 心形坐标类
    • 心形函数
    • 定时器方法
    • 绘制函数
    • 完整源码
  • 结束语

前言

近期学习了一段时间的GDI+,突然想着用GDI+绘制点啥,用来验证下类与方法。有兴趣的,可以查阅Windows GDI+学习笔记相关文章。
效果展示
心动GDI+

实现步骤

  1. 定义心形函数 。
    这里实现两种心形函数
    函数一:
    心形函数一
    函数二:
    心形函数二
  2. 生成指定宽度、高度的心形坐标集 。
  3. 在定时器中控制,定时刷新绘制区域,控制当前绘制的心形点集,轮廓的点序号、心跳状态。
  4. 根据当前心形点集绘制一个心形用于绕着另一个心形边缘点旋转并逐渐绘制出另一个完整心形。
  5. 用渐变色填充最内层心形。
  6. 增加心形宽、高,生成另一个心形。
  7. 用大的心形围绕待绘制的心形边缘旋转逐渐绘制出另一个完整心形。
  8. 当有两层心形时,交替填充显示最内一层或二层的心形,使其有跳动的效果。
  9. 继续加大心形的宽、高,并在外面绘制更多层的心形。
  10. 当达到一定层数后,用另一个心形函数再次重复上次的绘制过程。

源代码

使用VS创建一个C# WinForm解决方案,将窗体重命名为FrmHeartbeat的,替换窗体中的代码,可直接运行。或在文章后下载解决方案。

心形坐标类

用于记录心形轮廓上每个点的坐标,以及该点相对中心的角度(用于绘制旋转心形)

    /// <summary>
    /// 心形坐标
    /// </summary>
    public class HeartPt
    {
        /// <summary>
        /// 点的角度(用于旋转)
        /// </summary>
        public float Angle { get; set; }
        /// <summary>
        /// 点的坐标
        /// </summary>
        public PointF Pt { get; set; }
    }

心形函数

使用了两种心形函数,生成心形坐标点集

        /// <summary>
        /// 生成心形1
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private List<HeartPt> GetHeartPts(float width, float height)
        {
            var result = new List<HeartPt>();

            // 生成心形坐标
            for (float angle = 0; angle < 360; angle += angleStep)
            {
                var radian = Math.PI * angle / 180;
                var sinT = Math.Sin(radian);
                double x = 16 * Math.Pow(sinT, 3);
                double y = 13 * Math.Cos(radian) - 5 * Math.Cos(2 * radian) - 2 * Math.Cos(3 * radian) - Math.Cos(4 * radian);

                // 转换坐标到画布上
                var xCoord = (float)(x * (width / 2));
                var yCoord = (float)(-y * (height / 2));

                result.Add(new HeartPt()
                {
                    Angle = angle,
                    Pt = new PointF(xCoord, yCoord),
                });
            }
            return result;
        }

        /// <summary>
        /// 生成心形2
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private List<HeartPt> GetHeartPts2(float width,float height)
        {
            width = width * 10;
            height = height * 10;
            var result = new List<HeartPt>();

            var sqrt2 = Math.Sqrt(2);
            // 生成心形坐标
            for (float angle = 0; angle < 360; angle+= angleStep)
            {
                var radian = Math.PI * angle / 180;
                var sinT = Math.Sin(radian);
                double x = -sqrt2 * Math.Pow(sinT, 3);
                var cosT = Math.Cos(radian);
                double y = 2 * cosT - Math.Pow(cosT, 2) - Math.Pow(cosT, 3);

                // 转换坐标到画布上
                var xCoord = (float)(x * (width / 2));
                var yCoord = (float)(-y * (height / 2));

                result.Add(new HeartPt()
                {
                    Angle = angle,
                    Pt = new PointF(xCoord, yCoord),
                });
            }
            return result;
        }

定时器方法

1、定时刷新绘制区域
2、控制当前心形轮廓点的序号
3、当绘制完一个心形后,记录并生成另一个扩大的心形
4、控制心跳频率

        private void Timer_Tick(object sender, EventArgs e)
        {
            this.Invalidate();
            CurrDrawPtIndex++;
            CurrDrawPtIndex = HeartPtList.Count == 0 ? 0 : CurrDrawPtIndex % HeartPtList.Count;
            if (CurrDrawPtIndex == 0)
            {
                if (heartWidth > MaxHeartWidth)
                {//换样式,重绘
                    heartWidth = MinHeartWidth;
                    beatCount = 0;
                    beat = false;
                    FinishedHeartList.Clear();
                    heartType++;
                    heartType = heartType % 2;
                }
                else if (CurrHeartPts.Count > 0)
                {
                    FinishedHeartList.Add(CurrHeartPts.Select(z => new PointF(z.X, z.Y)).ToArray());
                }
                heartWidth++;
                if (heartType == 0)
                {
                    HeartPtList = GetHeartPts(heartWidth, heartWidth);
                }
                else
                {
                    HeartPtList = GetHeartPts2(heartWidth, heartWidth);
                }
                CurrHeartPts = new List<PointF>();
            }
            CurrHeartPts.Add(HeartPtList[CurrDrawPtIndex].Pt);
            beatCount++;
            if (beatCount >= 600 / timer.Interval)
            {//多久跳动一次
                beatCount = 0;
                if (FinishedHeartList.Count > 1)
                {
                    beat = !beat;
                }
            }
        }

绘制函数

1、设计绘制参数、清空背景
2、控制心形中心点坐标
3、绘制已记录的心形,控制最内两层心形的填充和其它层心形的颜色
4、通过待绘制心形点集的序号控制心形绘制位置与旋转角度
5、注意矩阵的变化,使旋转心形的控制点与待绘制轮廓点一致。

        private void FrmHeart_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.Clear(Color.White);
            if (HeartPtList.Count == 0) return;
            //心形中心点
            e.Graphics.TranslateTransform(this.Width / 2, this.Height / 2.2f);

            var pen = FinishedHeartList.Count % 2 == 0 ? Pens.Red : Pens.Pink;

            Color color = Color.Red;

            for (int i = FinishedHeartList.Count - 1; i >= 0; i--)
            {
                var heart = FinishedHeartList[i];
                if (i <= 1)
                {//渐变色填充                    
                    PathGradientBrush pathGBrush = new PathGradientBrush(heart);
                    {
                        if (beat)
                        {//跳动时,最里面不绘制
                            if (i == 0) break;
                            color = Color.Red;
                        }
                        else
                        {
                            color = Colors[i];
                        }
                        pathGBrush.SurroundColors = new Color[] { color };
                        pathGBrush.CenterPoint = new PointF(0, heart.Max(z=>z.Y)/10f);
                        pathGBrush.CenterColor = Color.White;
                        var gPath = new GraphicsPath();
                        gPath.AddClosedCurve(heart);
                        e.Graphics.FillPath(pathGBrush, gPath);
                    }
                }
                else
                {
                    color = GetColor(i);
                    using (var penC = new Pen(color,2))
                    {//心形轮廓
                        e.Graphics.DrawClosedCurve(penC, heart);
                    }
                }
            }
            color = GetColor(FinishedHeartList.Count);
            using (var penC = new Pen(color,2))
            {
                if (CurrHeartPts.Count > 2)
                {//绘制当前心形                   
                    e.Graphics.DrawCurve(penC, CurrHeartPts.ToArray());
                }
                var currHeartPt = HeartPtList[CurrDrawPtIndex].Pt;
                var firstHeartPt = HeartPtList[0].Pt;

                //绘制旋转的心形
                using (var gPath = new GraphicsPath())
                {
                    gPath.AddClosedCurve(HeartPtList.Select(z => z.Pt).ToArray());

                    using (var matrix = new Matrix())
                    {
                        matrix.Translate(currHeartPt.X, currHeartPt.Y, MatrixOrder.Append);

                        matrix.Translate(-firstHeartPt.X, -firstHeartPt.Y, MatrixOrder.Append);

                        matrix.RotateAt(HeartPtList[CurrDrawPtIndex].Angle, currHeartPt, MatrixOrder.Append);

                        gPath.Transform(matrix);
                        e.Graphics.DrawPath(penC, gPath);
                    }
                }
            }
        }

完整源码

    public partial class FrmHeartbeat : Form
    {
        public FrmHeartbeat()
        {
            InitializeComponent();
            this.FormBorderStyle = FormBorderStyle.FixedToolWindow;
            this.Width = 960;
            this.Height = 800;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.DoubleBuffered = true;
            this.Load += new System.EventHandler(this.FrmHeart_Load);
            this.Paint += new System.Windows.Forms.PaintEventHandler(this.FrmHeart_Paint);
        }

        private void FrmHeart_Load(object sender, EventArgs e)
        {
            this.Text = "心动";
            timer = new Timer();
            timer.Interval = 20;//控制绘制速度
            timer.Tick += Timer_Tick;
            timer.Start();
        }
        const int MinHeartWidth = 15;
        const int MaxHeartWidth = 25;

        private int heartWidth = MinHeartWidth;
        private bool beat = false;
        private int beatCount = 0;

        private int heartType = 0;
        private void Timer_Tick(object sender, EventArgs e)
        {
            this.Invalidate();
            CurrDrawPtIndex++;
            CurrDrawPtIndex = HeartPtList.Count == 0 ? 0 : CurrDrawPtIndex % HeartPtList.Count;
            if (CurrDrawPtIndex == 0)
            {
                if (heartWidth > MaxHeartWidth)
                {//换样式,重绘
                    heartWidth = MinHeartWidth;
                    beatCount = 0;
                    beat = false;
                    FinishedHeartList.Clear();
                    heartType++;
                    heartType = heartType % 2;
                }
                else if (CurrHeartPts.Count > 0)
                {
                    FinishedHeartList.Add(CurrHeartPts.Select(z => new PointF(z.X, z.Y)).ToArray());
                }
                heartWidth++;
                if (heartType == 0)
                {
                    HeartPtList = GetHeartPts(heartWidth, heartWidth);
                }
                else
                {
                    HeartPtList = GetHeartPts2(heartWidth, heartWidth);
                }
                CurrHeartPts = new List<PointF>();
            }
            CurrHeartPts.Add(HeartPtList[CurrDrawPtIndex].Pt);
            beatCount++;
            if (beatCount >= 600 / timer.Interval)
            {//多久跳动一次
                beatCount = 0;
                if (FinishedHeartList.Count > 1)
                {
                    beat = !beat;
                }
            }
        }

        /// <summary>
        /// 中间已绘制的心形
        /// </summary>
        List<PointF[]> FinishedHeartList = new List<PointF[]>();
        /// <summary>
        /// 当前心形轮廓
        /// </summary>
        List<HeartPt> HeartPtList = new List<HeartPt>();

        /// <summary>
        /// 当前心形轮廓
        /// </summary>
        List<PointF> CurrHeartPts = new List<PointF>();
        Timer timer;
        /// <summary>
        /// 当前心形坐标集序号
        /// </summary>
        int CurrDrawPtIndex = 0;
        /// <summary>
        /// 角度边长(越大越快)
        /// </summary>
        float angleStep = 2f;

        /// <summary>
        /// 生成心形1
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private List<HeartPt> GetHeartPts(float width, float height)
        {
            var result = new List<HeartPt>();

            // 生成心形坐标
            for (float angle = 0; angle < 360; angle += angleStep)
            {
                var radian = Math.PI * angle / 180;
                var sinT = Math.Sin(radian);
                double x = 16 * Math.Pow(sinT, 3);
                double y = 13 * Math.Cos(radian) - 5 * Math.Cos(2 * radian) - 2 * Math.Cos(3 * radian) - Math.Cos(4 * radian);

                // 转换坐标到画布上
                var xCoord = (float)(x * (width / 2));
                var yCoord = (float)(-y * (height / 2));

                result.Add(new HeartPt()
                {
                    Angle = angle,
                    Pt = new PointF(xCoord, yCoord),
                });
            }
            return result;
        }

        /// <summary>
        /// 生成心形2
        /// </summary>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        private List<HeartPt> GetHeartPts2(float width,float height)
        {
            width = width * 10;
            height = height * 10;
            var result = new List<HeartPt>();

            var sqrt2 = Math.Sqrt(2);
            // 生成心形坐标
            for (float angle = 0; angle < 360; angle+= angleStep)
            {
                var radian = Math.PI * angle / 180;
                var sinT = Math.Sin(radian);
                double x = -sqrt2 * Math.Pow(sinT, 3);
                var cosT = Math.Cos(radian);
                double y = 2 * cosT - Math.Pow(cosT, 2) - Math.Pow(cosT, 3);

                // 转换坐标到画布上
                var xCoord = (float)(x * (width / 2));
                var yCoord = (float)(-y * (height / 2));

                result.Add(new HeartPt()
                {
                    Angle = angle,
                    Pt = new PointF(xCoord, yCoord),
                });
            }
            return result;
        }

        Color[] Colors = new Color[] { Color.Red, Color.Pink };
        /// <summary>
        /// 根据轮廓层次获取其对应颜色
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        private Color GetColor(int index)
        {
            Color color;
            if (beat)
            {
                color = Colors[(index + 1) % 2];
            }
            else
            {
                color = Colors[index % 2];
            }
            return color;
        }

        private void FrmHeart_Paint(object sender, PaintEventArgs e)
        {
            e.Graphics.CompositingQuality = CompositingQuality.HighQuality;
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            e.Graphics.Clear(Color.White);
            if (HeartPtList.Count == 0) return;
            //心形中心点
            e.Graphics.TranslateTransform(this.Width / 2, this.Height / 2.2f);

            var pen = FinishedHeartList.Count % 2 == 0 ? Pens.Red : Pens.Pink;

            Color color = Color.Red;

            for (int i = FinishedHeartList.Count - 1; i >= 0; i--)
            {
                var heart = FinishedHeartList[i];
                if (i <= 1)
                {//渐变色填充                    
                    PathGradientBrush pathGBrush = new PathGradientBrush(heart);
                    {
                        if (beat)
                        {//跳动时,最里面不绘制
                            if (i == 0) break;
                            color = Color.Red;
                        }
                        else
                        {
                            color = Colors[i];
                        }
                        pathGBrush.SurroundColors = new Color[] { color };
                        pathGBrush.CenterPoint = new PointF(0, heart.Max(z=>z.Y)/10f);
                        pathGBrush.CenterColor = Color.White;
                        var gPath = new GraphicsPath();
                        gPath.AddClosedCurve(heart);
                        e.Graphics.FillPath(pathGBrush, gPath);
                    }
                }
                else
                {
                    color = GetColor(i);
                    using (var penC = new Pen(color,2))
                    {//心形轮廓
                        e.Graphics.DrawClosedCurve(penC, heart);
                    }
                }
            }
            color = GetColor(FinishedHeartList.Count);
            using (var penC = new Pen(color,2))
            {
                if (CurrHeartPts.Count > 2)
                {//绘制当前心形                   
                    e.Graphics.DrawCurve(penC, CurrHeartPts.ToArray());
                }
                var currHeartPt = HeartPtList[CurrDrawPtIndex].Pt;
                var firstHeartPt = HeartPtList[0].Pt;

                //绘制旋转的心形
                using (var gPath = new GraphicsPath())
                {
                    gPath.AddClosedCurve(HeartPtList.Select(z => z.Pt).ToArray());

                    using (var matrix = new Matrix())
                    {
                        matrix.Translate(currHeartPt.X, currHeartPt.Y, MatrixOrder.Append);

                        matrix.Translate(-firstHeartPt.X, -firstHeartPt.Y, MatrixOrder.Append);

                        matrix.RotateAt(HeartPtList[CurrDrawPtIndex].Angle, currHeartPt, MatrixOrder.Append);

                        gPath.Transform(matrix);
                        e.Graphics.DrawPath(penC, gPath);
                    }
                }
            }
        }

        private void FrmHeartbeat_Click(object sender, EventArgs e)
        {
            if(timer.Enabled)
            {
                timer.Stop();
            }
            else
            {
                timer.Start();
            }
        }
    }

    /// <summary>
    /// 心形坐标
    /// </summary>
    public class HeartPt
    {
        /// <summary>
        /// 点的角度(用于旋转)
        /// </summary>
        public float Angle { get; set; }
        /// <summary>
        /// 点的坐标
        /// </summary>
        public PointF Pt { get; set; }
    }

结束语

个人认为,要实现本文的绘制有两点需要注意:

  1. 心形函数
    使用一个函数来实现一个完美的心形绘制,这决对不是一件简单的事,本文中的两个函数可能是数学家的呕心沥血之作,向前辈致敬!但对于我们使用它,可能就是一件相对简单的事了。
  2. 控制旋转心形点与待绘制心形轮廓点一致
    在图形的绘制过程中,矩阵的应用一直是个难点(至少对于本人来说),本文中要控制旋转心形与待绘制心形的点一致,使其感觉是用一个心形来绘制另一个心形,其中的矩阵变换,从结果回看,感觉很简单,但在实际应用过程,往往需要重复多次去尝试(肯定是数学理论没过关),有时仅仅因为顺序的不同,导致结果天差地别。在了解了GDI+大部分函数与功能后,对于矩阵变换还是需要花更多时间去研究。
    完整源码下载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/676330.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MobaXterm 连接时间太短,会自动断开

问题现象 MobaXterm成功连接到开发环境后&#xff0c;过一段时间会自动断开。 原因 配置MobaXterm工具时&#xff0c;没有勾选“SSH keepalive”或专业版MobaXterm工具的“Stop server after”时间设置太短。

C++ stack类与queue类

目录 0.前言 1.容器适配器 1.1容器适配器的特点 1.2容器适配器的实现 1.3使用容器适配器的场景 2.stack的介绍与使用 2.1介绍 2.2使用 3.queue的介绍与使用 3.1介绍 3.2使用 4.stack和queue的模拟实现 4.1 stack的模拟实现 4.2 queue的模拟实现 5.结语 &#xf…

探秘IPv6协议在车载网络的应用:打造智能出行新体验

绪论 1969年&#xff0c;互联网的前身——ARPANET成功地连接了四个关键节点&#xff1a;①加州大学洛杉矶分校、②斯坦福研究所、③加州大学圣巴巴拉分校、④犹他州大学。这四个节点的成功连接标志着分组交换&#xff08;Packet Switching&#xff09;网络的正式运行&#xff…

SpringBoot登录认证--衔接SpringBoot案例通关版

文章目录 登录认证登录校验-概述登录校验 会话技术什么是会话呢?cookie Session令牌技术登录认证-登录校验-JWT令牌-介绍JWT SpringBoot案例通关版,上接这篇 登录认证 先讲解基本的登录功能 登录功能本质就是查询操作 那么查询完毕后返回一个Emp对象 如果Emp对象不为空,那…

Android期末大作业:使用AndroidStudio开发图书管理系统APP(使用sqlite数据库)

Android Studio开发项目图书管理系统项目视频展示&#xff1a; 点击进入图书管理系统项目视频 引 言 现在是一个信息高度发达的时代&#xff0c;伴随着科技的进步&#xff0c;文化的汲取&#xff0c;人们对于图书信息的了解与掌握也达到了一定的高度。尤其是学生对于知识的渴…

wvp-gb28181-pro搭建流媒体服务器,内存占用过高问题

直接给出解决办法,端口暴露的太多了,暴露了500个端口导致从3g---->11g 遇到的问题,直接使用镜像《648540858/wvp_pro:latest》在宿主机上运行,如我下面的博客 https://blog.csdn.net/weixin_41012767/article/details/137112338?spm=1001.2014.3001.5502 docker run …

ChineseChess.2024.06.03

ChineseChess.2024.06.03 中国象棋&#xff0c;我下得不是象棋&#xff0c;是娱乐&#xff0c;是想看看自己的程序。哈哈 看很多主播挂棋局&#xff0c;吹牛批&#xff0c;为了涨粉&#xff0c;挂着&#xff0c;蛮摆个残局 中国象棋残局模拟器ChineseChess.2024.06.03

HTML:认识HTML与基本语法的学习

前言 HTML&#xff08;超文本标记语言&#xff09;是用于创建网页的标记语言&#xff0c;由一系列标签组成&#xff0c;定义网页中的元素。由蒂姆伯纳斯 - 李于1990年代初发明&#xff0c;最初用于科研机构间共享文档&#xff0c;迅速演变为Web开发基础。无论是电商、博客、新…

攻防世界---misc---reverseMe

1、这道题是做过最简单的misc题&#xff0c;下载附件是一个图片 2、flag是反的&#xff0c;但是可以自己倒着推也能写出 3、这里推荐使用工具&#xff0c;双击图片&#xff0c;它打开是用的系统自带的软件打开 点击这里最图片编辑 4、接着点击矫正 5、点击这个左右翻转 6、得…

64位Office API声明语句第119讲

跟我学VBA&#xff0c;我这里专注VBA, 授人以渔。我98年开始&#xff0c;从源码接触VBA已经20余年了&#xff0c;随着年龄的增长&#xff0c;越来越觉得有必要把这项技能传递给需要这项技术的职场人员。希望职场和数据打交道的朋友&#xff0c;都来学习VBA,利用VBA,起码可以提高…

我们如何管理网站权限?这么操作最简单

网站权限有哪些 在知道如何管理网站权限之前我们先来了解一下网站权限都有哪些。在日常我们使用浏览器的时候网站都会使用你同意的某些权限进行一些操作&#xff0c;下面是总结的一些网站权限&#xff1a; 位置访问权限&#xff1a;控制网站是否可以访问你的地理位置数据。 …

【MATLAB源码-第220期】基于matlab的Massive-MIMO误码率随着接收天线变化仿真采用ZF均衡和QPSK调制。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 系统背景与目标 无线通信系统的发展极大地推动了现代通信技术的进步&#xff0c;从移动通信到无线局域网&#xff0c;甚至是物联网&#xff0c;均依赖于无线通信系统的高效和可靠性。在无线通信系统中&#xff0c;核心目…

详解和实现数据表格中的行数据合并功能

theme: smartblue 前言 需求场景&#xff1a; 在提供了数据查看和修改的表格视图中(如table、a-table等…)&#xff0c;允许用户自行选择多行数据&#xff0c;依据当前状态进行特定列数据的合并操作。选中的数据将统一显示为选中组的首条数据值。同时&#xff0c;页面会即时反…

k8s怎么监听资源的变更

监听k8s所有的 Deployment 资源 package mainimport ("context""fmt"v1 "k8s.io/api/apps/v1""k8s.io/apimachinery/pkg/util/json""k8s.io/client-go/informers""k8s.io/client-go/kubernetes""k8s.io/cli…

linux,lseek,append用法

打开写的.c文件 内容为 代码 <sys/stat.h> #include <fcntl.h> #include<stdio.h> #include<unistd.h> #include<string.h>//off_t lseek(int fd, off_t offset, int whence); //int open(const char *pathname, int flags); //int open(const …

一个AI板卡电脑--香橙派 AIpro

本文算是一个开箱测评&#xff0c;主要评估它和一个电脑的距离。 香橙派官网&#xff1a;香橙派(Orange Pi)-Orange Pi官网-香橙派开发板,开源硬件,开源软件,开源芯片,电脑键盘香橙派&#xff08;Orange Pi&#xff09;是深圳市迅龙软件有限公司旗下开源产品品牌;香橙派&#x…

【触想智能】工业平板电脑在高铁上的应用分析

随着科技的快速发展&#xff0c;平板电脑作为一种新型的电子设备&#xff0c;已经逐渐成为人们日常生活中的必需品。而工业平板电脑则是一种更为专业的平板电脑&#xff0c;可以应用于各种工业领域&#xff0c;如交通、制造业、医疗、金融、人工智能等。 今天&#xff0c;小编为…

Oracle Hint /*+APPEND*/插入性能总结

oracle append用法 Oracle中的APPEND用法主要用于提高数据插入的效率。 基本用法&#xff1a;在使用了APPEND选项后&#xff0c;插入数据会直接加到表的最后面&#xff0c;而不会在表的空闲块中插入数据。这种做法不需要寻找freelist中的free block&#xff0c;从而避免了在…

推荐一个图片识别的llama3微调版本 清华面壁项目

水一篇&#xff1a; MiniCPM-V是面向图文理解的端侧多模态大模型系列。该系列模型接受图像和文本输入&#xff0c;并提供高质量的文本输出。自2024年2月以来&#xff0c;我们共发布了4个版本模型&#xff0c;旨在实现领先的性能和高效的部署&#xff0c;目前该系列最值得关注的…

36【Aseprite 作图】蒸笼盖——拆解

1 蒸笼盖框架 里圈和外圈的形状都是一样的 扶手处&#xff0c;2 1 2 2 2&#xff08;最好都是2&#xff0c;拐角处用1&#xff09; 2 上色 中间的波浪&#xff0c;是2 2 2 上&#xff08;再 2 2 2 下&#xff09; 下方阴影&#xff0c;左边的阴影&#xff0c;右边的阴影颜色…