【SkiaSharp绘图15】SKPath属性详解:边界、填充、凹凸、类型判断、坐标、路径类型

文章目录

  • SKPath 构造函数
  • SKPath 属性
    • Bounds 边界(宽边界)
    • TightBounds紧边界
    • FillType填充方式
    • IsConcave 是否凹/ IsConvex 是否凸
    • IsEmpty是否为空
    • IsLine是否为线段
    • IsRect是否为矩形
    • IsOval是否为椭圆或圆
    • IsRoundRect是否为圆角矩形
    • Item[] 获取路径的坐标
    • LastPoint最后点的坐标
    • PointCount总共坐标点的个数
    • Points获取所有坐标点
    • SegmentMasks 路径包含的类型
    • VerbCount动词个数
    • 示例

SKPath 构造函数

public class SKPath : SkiaSharp.SKObject

复合的几何路径,封装由直线段、二次曲线、三次组成的复合(多轮廓)几何路径

public SKPath ();//构造一个空路径
public SKPath (SkiaSharp.SKPath path);//深拷贝一个已存在的路径。

可构造一个空路径或深拷贝一个已存在的路径。

var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
using (var txtPaint = new SKPaint())
{
    paint.Color = SKColors.Red;
    paint.IsStroke = true;
    paint.IsAntialias = true;
    txtPaint.TextSize = 18;
    txtPaint.IsAntialias = true;
    txtPaint.Typeface = SKTypeface.FromFamilyName("宋体");

    var pathA=new SKPath();
    pathA.AddCircle(100, 100, 50);

    var pathB=new SKPath(pathA);//深拷贝

    pathA.AddRect(new SKRect(50, 200, 150, 300));

    canvas.DrawPath(pathA, paint);
    canvas.DrawText($"测试构造一个已存在路径时,深拷贝,还是浅拷贝。", 50, 400, txtPaint);

    canvas.Translate(300, 0);
    paint.Color = SKColors.Green;

    pathB.AddCircle(100,250,50);
    canvas.DrawPath(pathB, paint);

}
  1. 创建一个空路径pathA,并添加一个圆.
  2. 创建另一个复制路径pathB
  3. 在pathA中再加入一个矩形。
  4. 在pathB中加入另一个圆。
  5. pathA与pathB互不影响。
    SKPath构造函数
    克隆源路径有问题时,会抛出异常。

SKPath 属性

Bounds 边界(宽边界)

public SkiaSharp.SKRect Bounds { get; }

获取路径的边界矩形。如果路径为空,则返回空矩形。
注意些边界不是路径的真实边路,可能比实际边界大,因为其包含的是控制点或独立点(MoveTo)。

var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
using (var paint = new SKPaint())
using (var txtPaint = new SKPaint())
{
    paint.Color = SKColors.Red;
    paint.IsStroke = true;
    paint.IsAntialias = true;
    paint.TextSize = 36;

    var path = new SKPath();
    var pts = new SKPoint[]
    {
        new SKPoint(100,100),
        new SKPoint(200,200),
        new SKPoint(300,50),
        new SKPoint(400,250),
        new SKPoint(500,150)
    };
    //绘制一段贝赛尔曲线
    path.MoveTo(pts[0]);
    path.CubicTo(pts[1], pts[2], pts[3]);
    //构造一个独立点
    path.MoveTo(pts[4]);

    canvas.DrawPath(path, paint);

    var bounds = path.Bounds;
    if (bounds != SKRect.Empty)
    {
        paint.StrokeWidth = 5;
        paint.Color = SKColors.Green;
        canvas.DrawRect(bounds, paint);
        canvas.DrawText($"Bounds",bounds.Right,bounds.Top, paint);
    }

    var tightBounds = path.TightBounds;
    if (tightBounds != SKRect.Empty)
    {
        paint.StrokeWidth = 3;
        paint.Color = SKColors.Purple;
        canvas.DrawRect(tightBounds, paint);
        canvas.DrawText($"TightBounds", tightBounds.Right, tightBounds.Bottom, paint);
    }

    paint.StrokeWidth = 10;
    paint.StrokeCap = SKStrokeCap.Round;
    paint.Color = SKColors.Blue;
    canvas.DrawPoints(SKPointMode.Points, pts, paint);
}
  1. 通过四个点构造一段贝赛尔曲线,并构造一个独立点
  2. 验证Bounds的边界情况。
  3. 验证TightBounds的边界情况
  4. 红色为曲线,绿色为Bounds,紫色为TightBounds,蓝色为控制点。
    在这里插入图片描述

TightBounds紧边界

public SkiaSharp.SKRect TightBounds { get; }

路径的实际边界。

FillType填充方式

public SkiaSharp.SKPathFillType FillType { get; set; }//默认是Winding

获取和设置路径的填充类型。
各枚举值的意义

  1. Winding(默认值)

    • 基于“非零缠绕数”规则来确定填充区域。
    • 当路径穿过点的次数(方向考虑在内)不为零时,点在填充区域内。
  2. EvenOdd

    • 基于“奇偶规则”来确定填充区域。
    • 当路径穿过点的次数为奇数时,点在填充区域内;为偶数时,点在填充区域外。
  3. InverseWinding

    • Winding 类似,但填充区域是 Winding 填充区域的反向。
    • 当路径穿过点的次数(方向考虑在内)不为零时,点在填充区域外。
  4. InverseEvenOdd

    • EvenOdd 类似,但填充区域是 EvenOdd 填充区域的反向。
    • 当路径穿过点的次数为奇数时,点在填充区域外;为偶数时,点在填充区域内。
/// <summary>
/// 获取五星路径
/// </summary>
/// <returns></returns>
private SKPath GetStarPath(SKPoint center,float outerRadius)
{
    // 计算五角星的角度
    float angleStep = (float)(2 * Math.PI / 5);

    // 设置五角星的尺寸和位置
    //float outerRadius = 100;
    //SKPoint center = new SKPoint(150, 150); // 五角星中心点的位置

    // 计算五个顶点的坐标
    SKPoint[] starPoints = new SKPoint[5];
    for (int i = 0; i < 5; i++)
    {
        float angle = angleStep * i;
        // 外部顶点
        float x = center.X + outerRadius * (float)Math.Sin(angle);
        float y = center.Y - outerRadius * (float)Math.Cos(angle); // 减号确保顶点在中心上方
        starPoints[i] = new SKPoint(x, y);
    }
    var starPath=new SKPath();
    // 开始定义路径
    starPath.MoveTo(starPoints[0]); // 从第一个顶点开始

    int index2 = 0;
    // 连接相隔的两个顶点
    for (int i = 2; i <= 5; i ++)
    {
        index2 = (index2 + 2) % 5;
        starPath.LineTo(starPoints[index2]);
    }

    // 关闭路径
    starPath.Close();
    return starPath;
}
var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
var info = e.Info;
using (var paint = new SKPaint())
using (var txtPaint = new SKPaint())
{

    paint.IsAntialias = true;
    paint.TextAlign = SKTextAlign.Center;
    paint.StrokeWidth = 3;
    paint.TextSize = 24;

    var path = GetStarPath(new SKPoint(150, 150),100F);
    var fillTypes = Enum.GetValues(typeof(SKPathFillType)) as SKPathFillType[];

    float dx = info.Width / 2;
    float dy = info.Height / 2; ;
    var index = 0;
    //
    foreach (var fillType in fillTypes)
    {
        path.FillType = fillType;
        canvas.Save();
        canvas.Translate(dx * (index % 2), dy * (index / 2));
        canvas.ClipRect(SKRect.Create(dx, dy));
        paint.Color = SKColors.Red;
        canvas.DrawPath(path, paint);
        paint.Color = SKColors.Green;
        canvas.DrawText($"FillType:{fillType}", 150, 280, paint);               
        canvas.Restore();
        index++;
    }
}
  1. 定义一个生成五角星的函数
  2. 将画布分成四块,在每一块用不同的填充方式绘制五角星。

FillType

IsConcave 是否凹/ IsConvex 是否凸

public bool IsConcave { get; }
public bool IsConvex { get; }

判断一个路径的凹凸性。

  • 凹点(Convex Point):如果轮廓上的每个点都在其相邻两个点所形成的线段的同侧(包括线段上的端点),那么这个点就是凸的。
  • 凹点(Concave Point):如果轮廓上的某个点不满足凸点的定义,则称其为凹点。
var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
var info = e.Info;
using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.StrokeWidth = 3;
    paint.TextSize = 24;
    paint.Color = SKColors.Red;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");

    var pathA = GetStarPath(new SKPoint(150, 150), 100);
    var pathB = new SKPath();
    pathB.AddRect(new SKRect(300, 50, 500, 200));

    canvas.DrawPath(pathA, paint);
    canvas.DrawText($"IsConcave凹:{pathA.IsConcave}", 20, 280, paint);
    canvas.DrawText($"IsConvex 凸:{pathA.IsConvex}", 20, 320, paint);

    canvas.DrawPath(pathB, paint);
    canvas.DrawText($"IsConcave凹:{pathB.IsConcave}", 320, 280, paint);
    canvas.DrawText($"IsConvex 凸:{pathB.IsConvex}", 320, 320, paint);
}

绘制一个五角星和一个矩形,判断其凹凸性。
IsConcave/IsConvex

IsEmpty是否为空

public bool IsEmpty { get; }

判断一个路径是否不包含任何线段或曲线。

IsLine是否为线段

public bool IsLine { get; }

判断一个路径是否为一条线段。

IsRect是否为矩形

public bool IsRect { get; }

判断路径是否为矩形。
注意,不是水平、垂直相交相连的线组成的矩形,这里返回的结果还是false。(是Skia的Bug吗?)

IsOval是否为椭圆或圆

public bool IsOval { get; }

判断路径是否为椭圆或圆。
注意四段贝赛尔曲线构成的圆,这里返回的结果还是false。

IsRoundRect是否为圆角矩形

public bool IsRoundRect { get; }

判断路径是否为圆角矩形。

** 相关示例 **

var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
var info = e.Info;
using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.StrokeWidth = 3;
    paint.TextSize = 24;
    paint.Color = SKColors.Red;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");

    var pathA = new SKPath();
    var offsetY = 30F;
    var offsetX = 150F;
    canvas.DrawText($"1.new SKPath() IsEmpty:{pathA.IsEmpty}", offsetX, offsetY, paint);                
    offsetY += paint.FontSpacing;
    pathA.MoveTo(50, 50);
    canvas.DrawText($"2.1 MoveTo(50, 50) IsEmpty:{pathA.IsEmpty}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;

    canvas.DrawText($"2.1 MoveTo(50, 50) IsLine: {pathA.IsLine}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;

    pathA.LineTo(100, 50);
    canvas.DrawText($"3 LineTo(100, 50 IsLine: {pathA.IsLine}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;

    pathA.LineTo(100, 100);
    pathA.LineTo(50, 100);
    pathA.Close();
    canvas.DrawText($"4 LineTo(100, 100),LineTo(50, 100),Close() IsRect: {pathA.IsRect}", offsetX, offsetY, paint);

    canvas.DrawPath(pathA, paint);

    var pathB=new SKPath();
    pathB.MoveTo(100, 150);
    pathB.LineTo(150, 200);
    pathB.LineTo(100, 250);
    pathB.LineTo(50, 200);
    pathB.Close();
    paint.IsStroke = true;
    canvas.DrawPath(pathB, paint);

    var width = (float)(Math.Sqrt(2) * 50);

    offsetY += 100;
    canvas.DrawText($"pathB IsRect: {pathB.IsRect}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
    var pathC=new SKPath();

    var rect = new SKRect(0, 0, width, width);
    paint.IsStroke = false;
    pathC.AddRect(rect);
    paint.Color = SKColors.LightGreen.WithAlpha(128);
    canvas.DrawText($"与pathB相同大小的pathC IsRect: {pathC.IsRect}", offsetX, offsetY, paint);

    canvas.Save();
    canvas.Translate(100, 150);
    canvas.RotateDegrees(45F);

    canvas.DrawPath(pathC, paint);
    canvas.Restore();

    var pathD=new SKPath();
    pathD.AddCircle(100, 350, 50);
    paint.IsStroke = true;
    canvas.DrawPath(pathD, paint);
    offsetY += 100;
    canvas.DrawText($"pathD IsOval: {pathD.IsOval}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;

    var pathE = CreateCircleWithBeziers(100, 350, 50);
    paint.Color = SKColors.LightBlue.WithAlpha(128);
    paint.IsStroke = false;
    canvas.DrawPath(pathE, paint);
    canvas.DrawText($"贝赛尔曲线构成的圆 pathE IsOval: {pathE.IsOval}", offsetX, offsetY, paint);
    offsetY += 100;

    paint.Color = SKColors.LightBlue;
    canvas.DrawText($"pathC IsRoundRect: {pathE.IsRoundRect}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
    var pathF = new SKPath();
    pathF.AddRoundRect(new SKRect(30, 450, 150, 500), 10, 20);
    canvas.DrawPath(pathF, paint);
    canvas.DrawText($"pathF IsRoundRect: {pathF.IsRoundRect}", offsetX, offsetY, paint);
}

四条贝赛尔构成的圆

/// <summary>
/// 四条贝赛尔曲线构成的圆
/// </summary>
/// <param name="centerX"></param>
/// <param name="centerY"></param>
/// <param name="radius"></param>
/// <returns></returns>
public SKPath CreateCircleWithBeziers(float centerX, float centerY, float radius)
{
    // 定义路径
    var path = new SKPath();

    // 贝塞尔曲线控制点的系数
    float c = (float)(radius * (4.0f / 3.0f) * (Math.Sqrt(2) - 1));

    // 定义起点
    path.MoveTo(centerX + radius, centerY);

    // 第一段贝塞尔曲线
    path.CubicTo(centerX + radius, centerY + c, centerX + c, centerY + radius, centerX, centerY + radius);

    // 第二段贝塞尔曲线
    path.CubicTo(centerX - c, centerY + radius, centerX - radius, centerY + c, centerX - radius, centerY);

    // 第三段贝塞尔曲线
    path.CubicTo(centerX - radius, centerY - c, centerX - c, centerY - radius, centerX, centerY - radius);

    // 第四段贝塞尔曲线
    path.CubicTo(centerX + c, centerY - radius, centerX + radius, centerY - c, centerX + radius, centerY);

    // 闭合路径
    path.Close();

    return path;
}

路径形状判断

Item[] 获取路径的坐标

public SkiaSharp.SKPoint this[int index] { get; }

获取路径上指定序号的点的坐标。如果序号超出小于0或大于等于PointCount,则返回(0,0)。

LastPoint最后点的坐标

public SkiaSharp.SKPoint LastPoint { get; }

获取路径的最后一个点的坐标。如果路径为空,返回(0,0)。

PointCount总共坐标点的个数

public int PointCount { get; }

获取路径所有坐标点的个数。

Points获取所有坐标点

public SkiaSharp.SKPoint[] Points { get; }

获取路径所有坐标点。注意,这些点包含控制点,即不一定在路径轮廓上。

SegmentMasks 路径包含的类型

public SkiaSharp.SKPathSegmentMask SegmentMasks { get; }

获取一组标志,指示路径是否包含该类型的一个或多个段。

说明
Line =1线段(2个点)
Quad=2二次贝赛尔曲线(3个点)
Cubic=8三次贝赛尔曲线(4个点)
Conic=4圆锥曲线(3个点+权重)

VerbCount动词个数

public int VerbCount { get; }

获取路径中动词的数量(即SKPathVerb,有Move、Line、Quad、Conic、Cubic、Close、Done)
用SKPath对象的CreateRawIterator可获取相关SKPathVerb。

示例

  1. 在路径中添加圆、矩形、椭圆、圆角矩形、画线段、二次/三次贝赛尔曲线
  2. 通过路径动词和坐标集来复制一个路径。
var canvas = e.Surface.Canvas;
canvas.Clear(SKColors.White);
var info = e.Info;
using (var paint = new SKPaint())
{
    paint.IsAntialias = true;
    paint.StrokeWidth = 7;
    paint.IsStroke = true;
    paint.TextSize = 24;
    paint.Color = SKColors.Red;
    paint.Typeface = SKTypeface.FromFamilyName("宋体");

    var path=new SKPath();
    path.AddCircle(200, 200, 100);

    path.AddRect(new SKRect(350, 100, 550, 200));

    path.AddOval(new SKRect(100, 350, 300, 450));

    path.AddRoundRect(new SKRoundRect(new SKRect(400,350,700,500),30));

    path.LineTo(300, 600);

    canvas.DrawPath(path, paint);

    var pts = path.Points;

    var verbCount = path.VerbCount;
    paint.Color = SKColors.Blue;
    canvas.DrawPoints(SKPointMode.Points, pts, paint);

    paint.StrokeWidth = 2;
    var drawPtList=new List<SKPoint>();
    for (int i = 0; i < pts.Length; i++)
    {
        var pt = pts[i];
        var count = drawPtList.Count(z => z.Equals(pt));
        if (count > 0)
        {
            var color = paint.Color;
            paint.Color = SKColors.Green;
            canvas.DrawText($"{i}", new SKPoint(pt.X - paint.TextSize * count, pt.Y), paint);
            paint.Color = color;
        }
        else
        {
            canvas.DrawText($"{i}", pts[i], paint);
        }
        drawPtList.Add(pt);
    }

    paint.Color = SKColors.Green;

    var newPath = ClonePathByVerb(path);

    paint.StrokeWidth = 1;
    canvas.DrawPath(newPath, paint);

    var offsetX = 20F;
    var offsetY = 500F;
    canvas.DrawText($"Path.PointCount:{path.PointCount}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
    canvas.DrawText($"Path.SegmentMasks:{path.SegmentMasks}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
    canvas.DrawText($"Path.VerbCount:{path.VerbCount}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
    canvas.DrawText($"Path.LastPoint:{path.LastPoint}", offsetX, offsetY, paint);
    offsetY += paint.FontSpacing;
}

SKPath属性

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

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

相关文章

基于香橙派AIpro搭建的车牌识别系统

引言 本人正有学习嵌入式的想法&#xff0c;正好碰到机会让我搞了块OrangePi AIpro&#xff08;香橙派AIpro&#xff09;开发板&#xff0c;正合我意&#xff0c;直接上手进行体验&#xff0c;顺便给大家分享下我的实践过程。 开发板介绍与初次启动 OrangePiAIPro开发板是香…

WPF UI InkCanvas 导师演示画板 演示 笔记 画笔 识别

<Grid><InkCanvas Name"inkCanvas"/><Button Content"识别" Click"Button_Click" VerticalAlignment"Bottom"/></Grid> 引用内库 Ink ink new Ink(); private void Button_Click(object sender, RoutedEvent…

基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用

基于STM32F103C8T6的同步电机驱动-CubeMX配置与IQmath调用 一、功能描述: 上位机通过CAN总线实现对电机的运动控制,主要包含三种模式:位置模式、速度模式以及力矩模式。驱动器硬件核心为STM32F103C8T6,带相电压采集电路以及母线电压采集电路。其中供电电压12V。 PWM中心对…

Android-卷积神经网络(Convolutional Neural Network, CNN)

一个复杂且在Android开发中常见的算法是图像处理中的卷积神经网络(Convolutional Neural Network, CNN)。CNN被广泛用于图像识别、物体检测和图像分割等任务,其复杂性在于需要处理大量的图像数据、复杂的神经网络结构和高效的计算。 1. 卷积操作(Convolution) 数学原理:…

企业级监控系统Zabbix

文章目录 Zabbix介绍Zabbix架构Zabbix serverZabbix agentZabbix proxy Zabbix Server的安装Zabbix Agent的安装监控主机流程zabbix_get自定义模板和监控项实战用户登录数监控1.指定监控项命令2.重启Agent服务3.在Server上创建监控项4.测试监控项5.查看监控项图形 触发器定义触…

字符设备驱动程序

简单做个模板框架 字符设备开发流程 确定设备号dev_t&#xff0c;动态分配 alloc_chrdev_region() 或静态分配 register_chrdev_region()定义file_opeartion 结构体*fops *&#xff0c;在结构体成员中实现对应的 *open()、read()*等函数。cdev_init() 将 fops 与 cdev 绑定&…

STM32学习历程(day2)

GPIO解释 GPIO(General-purpose input/output) 可以配置为八种输入输出模式 引脚电平 0V-3.3V 部分引脚可容忍5v 输出模式可控制端口输出高低电平 用以驱动LED、控制蜂鸣器、模拟通信协议输出时序 输入模式可读取端口的高低电平或电压&#xff0c;用于读取按键输入、外界…

firefly rk3588 sdk安装问题记录

目录 一、python版本不对 1.1 下载python2.6 1.2 安装python2.6 1.3 安装遇到问题 二、安装hashlib 三、更新3588 SDK代码 一、python版本不对 我的环境的python版本是python3.7。初次安装的时候执行命令报错&#xff0c;说是版本不对导致 fuhdell:rk3588_sdk$ .repo/rep…

centos通过官网下载安装最新版mysql方案

官网下载步骤&#xff1a; 点击DOCUMENTATION mysql的yum仓库Using the MySQL Yum Repository 向下翻&#xff0c;查看安装命令 点击下载mysql安装包 下载对应的版本 不注册&#xff0c;直接下载社区版 下载好的安装包 安装步骤&#xff1a; 把rpm包导入到服务器…

AI 驱动的数据中心变革与前景

文章主要探讨了AI计算时代数据中心的转型&#xff0c;涉及计算技术的多样性、规格尺寸和加速器的发展、大型语言模型&#xff08;LLM&#xff09;的发展、功耗和冷却趋势、基准测试的重要性以及数据中心的发展等方面。为大家提供深入了解AI基础设施发展的视角。 计算技术的多样…

​浅谈 Linux 中的 core dump 分析方法

在 Linux 系统开发领域中&#xff0c;core dump&#xff08;核心转储&#xff09;是一个不可或缺的工具&#xff0c;它为我们提供了在程序崩溃时分析程序状态的重要线索。当程序因为某种原因&#xff08;如段错误、非法指令等&#xff09;异常终止时&#xff0c;Linux 系统会尝…

spring boot + vue3+element plus 项目搭建

一、vue 项目搭建 1、创建 vue 项目 vue create vue-element说明:创建过程中可以选择路由,也可也可以不选择,可以通过 npm install 安装 vue 项目目录结构 说明:api 为自己创建的文件夹,router 选择路由模块会自动创建 router下的index.js文件(配置路由的文件) im…

泰国内部安全行动司令部数据泄露

BreachForums 论坛的一名成员宣布发生一起重大数据泄露事件&#xff0c;涉及泰国内部安全行动司令部 (ISOC)&#xff0c;该机构被称为泰国皇家武装部队的政治部门。 目前&#xff0c;我们无法准确确认此次泄露的真实性&#xff0c;因为该组织尚未在其网站上发布有关该事件的任…

微信开发者工具报错 Error: module ‘xxx.js‘ is not defined, require args is ‘xxx.js‘

背景 报错如下 检查 代码逻辑和写法都是ok的重新打开项目又是可以的 解决方案 先确保微信开发者工具和uniapp的将js编译成es5都开着&#xff08;这个是默认开的&#xff09; 然后把微信开发者工具关了重开 一般做这一步就会好了&#xff0c;但是只是临时解决 &#xff08…

如何使用 3D 建模库在 C# 中将 3DS 转换为 USDZ?

USDZ/USD是一种 3D 文件格式&#xff0c;被广泛用于跨平台共享 3D 资产。另一方面&#xff0c;3DS是另一种以块形式存储数据的 3D 文件格式。在某些情况下&#xff0c;您需要将3DS 文件转换为 USDZ/USD文件格式。因此&#xff0c;本篇博文介绍了一个功能丰富的3D 建模库&#x…

记录一下简单导入导出excel二级表头

数据库导入导出表头 之前的工具类GenerateExcelToFile新增两个导出这种二级表头方法 package com.njry.utils;import cn.hutool.core.util.IdUtil; import com.njry.config.FileProperties; import com.njry.exception.BadRequestException; import org.apache.poi.hssf.user…

《Winodws API每日一练》8.2 static控件

在 Windows 编程中&#xff0c;"Static" 控件是一种常见的用户界面元素&#xff0c;用于显示静态文本或图像&#xff0c;而无法进行用户交互。它通常用于显示标签、标题、说明文本或静态图像等信息。Static 控件是一种静态的、只读的显示元素&#xff0c;不接受用户的…

JAVA 快递100wms工具类

快递wms工具类 import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.gson.Gson; import com.kuaidi100.sdk.api.QueryTrack; import com.kuaidi100.sdk.api.Subscribe; import com.kuaidi100.sdk.contant.ApiInfoConstant; import c…

11.SQL注入-盲注基于(base on boolian)

SQL注入-盲注基于boolian案例利用 首先总结一下sql语句中的函数意思 #查看当前所在的数据库 mysql> select database(); ------------ | database() | ------------ | pikachu | ------------ 1 row in set (0.00 sec)#函数substr里1是从第几位开始取字符&#xff0c;2…

mybatis-使用自动生成(根据数据库反向生成pojo、映射文件,映射接口)

1.在pom.xml中导入依赖和插件 <dependencies> <!-- 导入自动生成依赖--><dependency><groupId>org.mybatis.generator</groupId><artifactId>mybatis-generator-maven-plugin</artifactId><version>1.4.0</version>&…