【计算机图形学】曲线和曲面

news2024/11/25 6:33:44

模块5 曲线和曲面

一 实验目的

  1. 编写曲线和曲面的算法

二 实验内容

1:绘制Bezier曲线,并采用自行设计输入和交互修改数据点的方式。

实验结果如下图所示:

第一步:输入特征多边形的顶点个数,并按照顺序输入顶点的坐标。


第二步:点击左键生成bezier曲线(白色部分)和多边形顶点(绿色部分)。

 

 


第三步:点击右键修改顶点,首先输入需要修改的顶点在数组中的坐标(即顺序个数-1),此处以(100,100)为例,将其修改为(100,300)。


第四步:通过敲击回车键,可观察修改后的bezier曲线和顶点。

 

 

第五步:如果需要继续修改顶点坐标,用户可以继续点击右键,重复上述操作。此处不再赘述。如果需要退出图像绘制界面,用户可以通过敲击esc键,即可退出本实验界面。

2:绘制Bezier曲面,双三次类型。


实验结果如下图所示:

 

2.1:绘制Bezier曲面,并采用自行设计输入和交互修改数据点的方式,改进。


实验结果如下图所示:


修改数据点:

 

 

新贝塞尔曲面:

 

三 程序说明

最终的实验代码如下表所示:

1

//

// 程序名称:Bezier曲线

// 功    能:绘制Bezier曲线,并采用自行设计输入和交互修改数据点的方式。

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-4-28

#include <graphics.h>

#include <conio.h>

#include <iostream>

#include <math.h>

using namespace std;

//特征多边形的特征

int n;

int px[100], py[100];

//初始化特征多边形

void initialize() {

    cout << "please input the number of your points (no more than 100)" << endl;

    cin >> n;

    cout << "please input each coordinate of your points in order" << endl;

    for (int i = 0; i < n; i++) {

         cin >> px[i] >> py[i];

    }

    cout << "successfully set" << endl;

}

//递归

int Factorial(int nn) {

    if (nn == 0 || nn == 1) return 1;

    else return nn * Factorial(nn - 1);

}

//绘制bezier曲线

void Bezier() {

    int nn = n - 1;

    //line(px[0], py[0], px[1], py[1]);

    double i = 0, n1, n2;

    n1 = Factorial(nn);

    moveto(px[0], py[0]);

    POINT point;

    //在[0,1]内循环

    for (; i <= 1; i += 0.01) {

         point.x = 0;

         point.y = 0;

         for (int j = 0; j <= nn; j++) {

             n2 = (n1 / (Factorial(j) * Factorial(nn - j))) * pow(i, j) * pow(1 - i, nn - j);

             point.x += n2 * px[j];

             point.y += n2 * py[j];

         }

         lineto(point.x, point.y);

    }

    lineto(px[n - 1], py[n - 1]);

    //描绘用户定义的点

    for (int ii = 0; ii < n; ii++) {

         setfillcolor(GREEN);

         fillcircle(px[ii], py[ii], 3);

    }

}

//主函数

int main() {

    //初始化

    initialize();

    initgraph(640, 480);

    ExMessage m;

    //绘制图像

    while (1) {

         m = getmessage(EX_MOUSE | EX_KEY);

         switch (m.message) {

             //右键修改坐标信息

             case WM_RBUTTONDOWN:

                  closegraph();

                  int arr, newx, newy;

                  //输入数组中的坐标,进行修改

                  cout << "which point do you want to change? please input its array number" << endl;

                  while (1) {

                      cin >> arr;

                      if (arr >= n) {

                          cout << "input error, try again" << endl;

                      }

                      else {

                          break;

                      }

                  }

                  cout << "please input the reset coordinate" << endl;

                  cin >> newx >> newy;

                  px[arr] = newx;

                  py[arr] = newy;

                  cout << "successfully reset, please wait a second to see a new graph" << endl;

                  initgraph(640, 480);

             //左键绘制

             case WM_LBUTTONDOWN:

                  Bezier();

             //退出图形化界面

             case WM_KEYDOWN:

                  if (m.vkcode == VK_ESCAPE) {

                      return 0;

                  }

         }

    }

    _getch();

    closegraph();

    return 0;

}

2

//

// 程序名称:Bezier曲面

// 功    能:绘制Bezier曲面,双三次类型。

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-5-9

#include <graphics.h>

#include <conio.h>

#include <iostream>

#include <cmath>

using namespace std;

#define pi 3.1415926

#define MAX 20

//三维点类

class Point3D {

public:

    double x, y, z;

    Point3D(int x = 0, int y = 0, int z = 0) {

         this->x = x;

         this->y = y;

         this->z = z;

    };

    void operator=(Point3D& a) {

         x = a.x;

         y = a.y;

         z = a.z;

    };

    Point3D operator*(double a) {

         return Point3D(a * x, a * y, a * z);

    };

    Point3D operator+(Point3D a) {

         return Point3D(x + a.x, y + a.y, z + a.z);

    };

    void operator+=(Point3D a) {

         x += a.x;

         y += a.y;

         z += a.z;

    };

};

//求阶乘

long int Factorial(int n) {

    int i, sum = 1;

    if (n == 0) {

         return 1;

    }

    for (i = 2; i <= n; i++) {

         sum *= i;

    }

    return sum;

}

//Bernstein函数

double Bernstein(int i, int n, double t) {

    return (double)Factorial(n) / Factorial(i) / Factorial(n - i) * pow(t, i) * pow(1 - t, n - i);

}

//Bezier曲面求解

void BezierCurve(Point3D p[][MAX], int n, int m, int nd, int md, double sita, double fai) {

    double hu = 1.0 / nd;

    double hv = 1.0 / md;

    double u = 0, v = 0;

    int i, j, k, l;

    sita = sita * pi / 180;

    fai = fai * pi / 180;

    int** pB = new int* [nd + 1];

    for (i = 0; i <= nd; i++) {

         pB[i] = new int[2 * md + 2];

    }

    Point3D ptemp(0, 0, 0);

    for (i = 0; i <= nd; i++, u += hu) {

         v = 0;

         for (j = 0; j <= 2 * md + 1; j += 2, v += hv) {

             ptemp.x = 0;

             ptemp.y = 0;

             ptemp.z = 0;

             for (k = 0; k <= n; k++) {

                  for (l = 0; l <= m; l++) {

                      ptemp += p[k][l] * Bernstein(k, n, u) * Bernstein(l, m, v);

                  }

             }

             pB[i][j] = ptemp.x * cos(sita) - ptemp.y * sin(sita) + 500;

             pB[i][j + 1] = -ptemp.x * sin(sita) * sin(fai) - ptemp.y * cos(sita) * sin(fai) + ptemp.z * cos(fai) + 400;

         }

         drawpoly(md + 1, pB[i]);

    }

    for (i = 0; i < nd + 1; i++) {

         delete[]pB[i];

    }

    delete[]pB;

}

//画控制多边形

void drawControlPoly_3D(Point3D p[][MAX], int n, int m, double sita, double fai, int color) {

    int** p2d = new int* [n + 1];

    int i, j;

    setcolor(color);

    sita = sita * pi / 180;

    fai = fai * pi / 180;

    for (i = 0; i < n + 1; i++) {

         p2d[i] = new int[2 * m + 4];

    }

    char str[80];

    //3D->2D

    for (i = 0; i <= n; i++) {

         for (j = 0; j <= m; j++) {

             p2d[i][2 * j] = p[i][j].x * cos(sita) - p[i][j].y * sin(sita) + 500;

             p2d[i][2 * j + 1] = -p[i][j].x * sin(sita) * sin(fai) - p[i][j].y * cos(sita) * sin(fai) + p[i][j].z * cos(fai) + 400;

         }

         p2d[i][2 * j] = p2d[i][0];

         p2d[i][2 * j + 1] = p2d[i][1];

         drawpoly(m + 2, p2d[i]);

    }

    for (j = 0; j <= 2 * m + 1; j += 2) {

         moveto(p2d[0][j], p2d[0][j + 1]);

         for (i = 1; i <= n; i++) {

             lineto(p2d[i][j], p2d[i][j + 1]);

         }

    }

    for (i = 0; i < n + 1; i++) {

         delete[]p2d[i];

    }

    delete[]p2d;

}

//双几次曲面

void BezierCurve_Shuang(Point3D p[][MAX], int pn, int pm, int nd, int md, double sita, double fai, int shuangjici) {

    int i, j, k, l;

    Point3D point[MAX][MAX];

    for (i = 0; i < pn - shuangjici; i += shuangjici) {

         for (j = 0; j < pm - shuangjici; j += shuangjici) {

             for (k = 0; k <= shuangjici; k++) {

                  for (l = 0; l <= shuangjici; l++) {

                      point[k][l] = p[i + k][j + l];

                  }

             }

             BezierCurve(point, shuangjici, shuangjici, nd, md, sita, fai);

         }

    }

}

//主函数

int main() {

    int n;

    double fai, sita;

    //固定角度了。

    sita = 20;

    fai = 160;

    n = 3;

    //顶点集合

    Point3D p[][MAX] = {

         {Point3D(0,0,0),Point3D(150,150,150),Point3D(250,150,150),Point3D(400,0,0)},

        {Point3D(50,200,0),Point3D(150,250,150),Point3D(250,250,150),Point3D(450,200,0)},

        {Point3D(20,400,0),Point3D(150,350,150),Point3D(250,350,150),Point3D(420,400,0)},

        {Point3D(0,600,0),Point3D(150,550,150),Point3D(250,550,150),Point3D(400,600,0)}

    };

    /*

    cout << "please input sita and fai" << endl;

    cin >> sita >> fai;

    cout << "please input your n" << endl;

    cin >> n;

    */

    //初始化界面

    initgraph(1000, 700);

    setcolor(RED);

    //Bezier曲面

    BezierCurve_Shuang(p, 4, 4, 100, 100, sita, fai, n);

    //画控制多边形

    drawControlPoly_3D(p, 3, 3, sita, fai, GREEN);

    _getch();

    closegraph();

    return 0;

}

2题改进版本

//

// 程序名称:Bezier曲面

// 功    能:绘制Bezier曲面,并采用自行设计输入和交互修改数据点的方式。

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-5-13

#include <iostream>

#include <graphics.h>

#include <conio.h>

#include <math.h>

using namespace std;

#define PI 3.1415926

//定义 N * N 的控制点数组

const int N = 8;

float controlPoints[N][N][3] ={

    { {-150, -150, 100}, {-100, -150, 0}, {-50, -150, 0}, {0, -150, 50}, {50, -150, 0}, {100, -150, 0}, {150, -150, -100}, {200, -150, 0} },

    { {-150, -100, 0}, {-100, -100, 50}, {-50, -100, -100}, {0, -100, 0}, {50, -100, 0}, {100, -100, 100}, {150, -100, 0}, {200, -100, -50} },

    { {-150, -50, 0}, {-100, -50, 0}, {-50, -50, 50}, {0, -50, 0}, {50, -50, 0}, {100, -50, 0}, {150, -50, -50}, {200, -50, 0} },

    { {-150, 0, -50}, {-100, 0, -100}, {-50, 0, 0}, {0, 0, 150}, {50, 0, 0}, {100, 0, -100}, {150, 0, -50}, {200, 0, -50} },

    { {-150, 50, 0}, {-100, 50, 0}, {-50, 50, -100}, {0, 50, 0}, {50, 50, 50}, {100, 50, 0}, {150, 50, 0}, {200, 50, 50} },

    { {-150, 100, 50}, {-100, 100, 0}, {-50, 100, 0}, {0, 100, -50}, {50, 100, -50}, {100, 100, 50}, {150, 100, 0}, {200, 100, 0} },

    { {-150, 150, 0}, {-100, 150, 100}, {-50, 150, -100}, {0, 150, 0}, {50, 150, 0}, {100, 150, 0}, {150, 150, -150}, {200, 150, 50} },

    { {-150, 200, 0}, {-100, 200, 0}, {-50, 200, 50}, {0, 200, -50}, {50, 200, 0}, {100, 200, -100}, {150, 200, 0}, {200, 200, 50} }

};

//计算贝塞尔基函数的C值

int C(int n, int k) {

    if (k > n) {

        return 0;

    }

    int c = 1;

    for (int i = 0; i < k; i++) {

        c *= (n - i);

        c /= (i + 1);

    }

    return c;

}

//勾勒函数

void display(float x, float y, float z) {

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300), RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400), int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) + 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) + 1, RED);

    putpixel(int(0.7071 * x - 0.7071 * y + 0.5f + 400) - 1, int(-0.4082 * x - 0.4082 * y + 0.8165 * z + 0.5f + 300) - 1, RED);

}

//Bezier曲面绘制

void Bezier() {

    //绘制控制点

    for (int i = 0; i < N - 1; i++) {

        for (int j = 0; j < N - 1; j++) {

            fillcircle(int(0.7071 * controlPoints[i][j][0] - 0.7071 * controlPoints[i][j][1] + 0.5f + 400), int(-0.4082 * controlPoints[i][j][0] - 0.4082 * controlPoints[i][j][1] + 0.8165 * controlPoints[i][j][2] + 0.5f + 300), 3);

        }

    }

    // 绘制贝塞尔曲面

    const int nPoints = 50;  // 每行/列计算的点数

    float uStep = 1.0f / nPoints;

    float vStep = 1.0f / nPoints;

    for (float u = 0; u < 1; u += uStep) {

        for (float v = 0; v < 1; v += vStep) {

            float x = 0, y = 0, z = 0;

            for (int i = 0; i < N; i++) {

                for (int j = 0; j < N; j++) {

                    // 计算贝塞尔基函数的值

                    float basisU = powf(1 - u, N - 1 - i) * powf(u, i) * float(C(N - 1, i));

                    float basisV = powf(1 - v, N - 1 - j) * powf(v, j) * float(C(N - 1, j));

                    float basis = basisU * basisV;

                    // 使用贝塞尔基函数的值和控制点计算曲面上的点

                    x += basis * controlPoints[i][j][0];

                    y += basis * controlPoints[i][j][1];

                    z += basis * controlPoints[i][j][2];

                }

            }

            // 将曲面上的点连接起来

            display(x, y, z);

        }

    }

}

//主函数

int main(){

    initgraph(800, 600);

    Bezier();

    ExMessage m;

    while (1) {

        m = getmessage(EX_MOUSE | EX_KEY);

        switch (m.message) {

        case WM_RBUTTONDOWN:

            //右键修改坐标信息

            closegraph();

            int row, column, newx, newy, newz;

            //输入数组中的坐标,进行修改

            cout << "which point do you want to change? please input its row & column array number" << endl;

            while (1) {

                cin >> row;

                cin >> column;

                if (row >= N) {

                    cout << "row number input error, try again" << endl;

                }

                else if (column >= N) {

                    cout << "column number input error, try again" << endl;

                }

                else {

                    break;

                }

            }

            cout << "please input the reset coordinate" << endl;

            cin >> newx >> newy >> newz;

            controlPoints[row][column][0] = newx;

            controlPoints[row][column][1] = newy;

            controlPoints[row][column][2] = newz;

            cout << "successfully reset, please wait a second to see a new graph" << endl;

            initgraph(800, 600);

        case WM_LBUTTONDOWN:

            //左键绘制

            Bezier();

        case WM_KEYDOWN:

            //退出图形化界面

            if (m.vkcode == VK_ESCAPE) {

                return 0;

            }

        }

    }

   

    _getch();

    closegraph();

    return 0;

}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《心静的力量》读书笔记

让心静下来&#xff0c;战胜一切忧虑 于我们每个人而言&#xff0c;最重要的就是不要去看远方模糊不清的事&#xff0c;而要做手边真实清楚的事。 明天的重担&#xff0c;加上昨天的重担&#xff0c;会成为今天的最大障碍&#xff0c;要把未来同过去一样紧紧地关在门外……未…

将MetaHuman的身体替换为虚幻商城模型的身体

一、准备好MetaHuman模型和虚幻商城模型 1.准备好MetaHuman模型,参考这篇文章 虚幻商城模型转MetaHuman制作MetaHuman并导入UE,同时复制一个MetaHuman模型 2.下载虚幻商城的原始模型,并导入UE 二、将虚幻商城模型的头去掉 1.打开虚幻商城的模型,找到分段 2.在右边点击…

chatgpt赋能Python-pythonapp开发

PythonApp开发&#xff1a;为什么选择Python实现&#xff1f; Python是当今最流行的编程语言之一&#xff0c;尤其在Web应用开发和数据分析领域更是大有作为。本文将探讨Python在App开发领域中的表现&#xff0c;为什么Python可以成为您理想的选择&#xff1f; 1. 简单易学 …

深度学习基础入门篇[8]::计算机视觉与卷积神经网络、卷积模型CNN综述、池化讲解、CNN参数计算

【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化算法、卷积模型、序列模型、预训练模型、对抗神经网络等 专栏详细介绍&#xff1a;【深度学习入门到进阶】必看系列&#xff0c;含激活函数、优化策略、损失函数、模型调优、归一化…

leetcode--优先队列

2163,删除元素后的最小差值 给你一个下标从 0 开始的整数数组 nums &#xff0c;它包含 3 * n 个元素。 你可以从 nums 中删除 恰好 n 个元素&#xff0c;剩下的 2 * n 个元素将会被分成两个 相同大小 的部分。 前面 n 个元素属于第一部分&#xff0c;它们的和记为 sumfirst …

RabbitMQ如何保证顺序性

1. RabbitMQ消息顺序性说明 顺序性&#xff1a; 消息的顺序性是指消费者消费到消息和发送者发布的消息的顺序是一致的 举个例子&#xff0c;不考虑消息重复的情况下&#xff0c;如果生产者发布的消息分别为msg1、msg2、msg3 那么消费者必然也是按照 msg1、msg2、msg3 的顺序来…

【数据结构】--- 博主拍了拍你并向你扔了一“堆”二叉树(堆的概念+结构+代码实现)

文章目录 前言&#x1f31f;一、二叉树的顺序结构及实现&#xff1a;&#x1f31f;二、堆的概念及结构&#xff1a;&#x1f31f;三、堆的代码实现&#xff1a;&#x1f30f;3.1 堆的创建&#xff1a;&#x1f30f;3.2 堆的结构&#xff1a;&#x1f30f;3.3 初始化&#xff1a…

Spring Security 如何实现身份认证和授权?

Spring Security 是一个开源的安全框架&#xff0c;提供了基于权限的访问控制、身份认证、安全性事件发布等功能。在 Spring Boot 应用中使用 Spring Security 可以非常方便地实现用户身份认证和授权。 Spring Security 实现身份认证的主要方式是使用认证过滤器链&#xff0c;…

C语言入门级小游戏——扫雷

文章目录 游戏思路游戏文件的创建游戏菜单棋盘的创建初始化棋盘打印棋盘 布置雷排查雷game.h —— 游戏函数的声明game.c —— 游戏函数的实现test.c —— 游戏的测试 今天我们写一个小游戏——扫雷来增加我们对编程的兴趣 希望这篇文章对友友们有帮助! 游戏思路 游戏文件的创…

Linux:iptables防火墙(SNAT和DNAT)

Linux&#xff1a;iptables防火墙 一、SNAT策略及应用1.1 SNAT原理1.2 SNAT应用 二、DNAT策略及应用2.1 DNAT原理2.2 DNAT应用 一、SNAT策略及应用 1.1 SNAT原理 SNAT 应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xff08;私有不能在Internet中正常路由…

MySQL数据库笔记——进阶篇

文章目录 存储引擎MySQL体系结构存储引擎简介InnoDB介绍MyISAMMemory 存储引擎的选择小结 索引概述索引结构概述BtreeBTreeHash 存储引擎 MySQL体系结构 连接层&#xff1a; 最上层是一些客户端和链接服务&#xff0c;主要完成一些类似于连接处理、授权认证、及相关的安全方案…

《计算机网络—自顶向下方法》 Wireshark实验(十):NAT 协议分析

NAT&#xff08;Network Address Translation&#xff09;网络地址转换&#xff0c;即在私有地址和全局地址之间转换的协议。私有地址是不能用在 Internet 上(路由器将丢弃寻址这种地址的包)的内部地址。这些地址是不能够在公网上面用的&#xff0c;只能用在局域网的内部。私有…

win安装Nodejs

文章目录 1、安装环境2、安装步骤3、更换npm源为淘宝镜像4、更多node版本下载 1、安装环境 node.js下载官网: nodejs官网 点击选中图标下载即可&#xff1a; 2、安装步骤 1、双击安装包&#xff0c;一直点击next 2、点击change按钮&#xff0c;更换到自己的指定安装位置&…

基于fpga的图像处理之3x3_5x5算子模板中值排序

本文的思路框架&#xff1a; ①本文介绍3x3算子模块和5x5算子模块中&#xff0c;矩阵转化成串行数据后&#xff0c;对其排序&#xff0c;并获取矩阵中值数据&#xff1b; ②本例程中采用的FPGA设计技巧&#xff0c;可用于借鉴&#xff0c;一是采用for循环实现串行数据转化并行数…

vite创建vue2项目

使用vite首先需要注意官方给出的兼容性注意 Vite 需要 Node.js 版本 14.18&#xff0c;16。然而&#xff0c;有些模板需要依赖更高的 Node 版本才能正常运行&#xff0c;当你的包管理器发出警告时&#xff0c;请注意升级你的 Node 版本。 1.初始化vite项目 输入以下命令&#…

Spring MVC 是什么?与 Struts 的区别是什么?

Spring MVC是Spring框架中的一个模块&#xff0c;它提供了一种基于MVC&#xff08;Model-View-Controller&#xff09;架构的Web开发方式。与传统的JSP/Servlet开发方式相比&#xff0c;Spring MVC更加灵活、高效&#xff0c;可以帮助开发人员快速构建高质量的Web应用程序。本文…

vue diff算法与虚拟dom知识整理(10) 梳理patch处理相同节点比较的基本逻辑

这次 我们来讲 diff算法处理到 当新旧节点 是同一个节点时的处理 我们之前也说过 如果不是同一个节点 他就会暴力拆旧 把新的插上去 但当他们是同一个节点 需要精细化比较 最做小化更新 这块我们还没有处理 打开我们的案例 打开 patch.js 对应其实就还是这一块还没有写 我们…

PostgreSQL查询引擎——transform expressions之AEXPR_OP

static Node *transformAExprOp(ParseState *pstate, A_Expr *a){Node *lexpr a->lexpr; Node *rexpr a->rexpr; // 操作符左右表达式Node *result;/* Special-case "foo NULL" and "NULL foo" for compatibility with standards-broke…

Bug——后端返回LocalDateTime类型数据中间出现一个T

错误如下图所示: 返回的JSON格式数据里面会有一个多出来的T. 解决方案&#xff1a; 在后端的POJO层的实体类的LocalDateTime属性上面加上一个注解 JsonFormat(pattern"yyyy-MM-dd HH:mm:ss") 如下所示&#xff0c;然后在返回JSON格式数据时就不会出现那个多余的T了…

C++之模板初阶

目录 前言 1.泛型编程 2.模板 2.1 函数模板 2.1.1 函数模板概念 2.1.2 函数模板格式 2.1.3 函数模板的原理 2.1.4 函数模板的实例化 2.1.5 模板参数的匹配原则 2.2 类模板 2.2.1 类模板定义模式 2.2.2 类模板的实例化 前言 我们会不会有疑惑为什么C语言中&#xf…