【计算机图形学】裁剪算法(逐边裁剪法 Weiler-Atherton裁剪法)

news2025/3/9 10:47:55

一 实验目的

  1. 编写直线段、多边形裁剪算法
  2. 熟悉逐边裁剪法、Weiler-Atherton裁剪法的使用

4:用逐边裁剪法实现多边形裁剪(代码最上方功能区注明是否处理退化边)

无退化实验结果如下图所示:
图形初始化:(红色部分为裁剪框,白色部分为待裁剪多边形)


点击左键进行裁剪:(黄色部分为裁剪后剩余多边形)

 

 


点击右键将裁剪图案右移:(黄色部分为裁剪后剩余多边形)

 

 

有退化实验结果如下图所示:
图形初始化:(红色部分为裁剪框,白色部分为待裁剪多边形)

 点击左键将裁剪图案右移:(黄色部分为裁剪后剩余多边形)

 

5:用Weiler-Atherton裁剪法实现多边形裁剪
实验结果如下图所示:

 说明:白色部分为原始多边形,红色部分为裁剪框,黄色部分为通过Weiler-Atherton裁剪法实现的裁剪多边形。

 

总结:

  1. 上述两种裁剪法的代码实现方法,大致是按照PPT上的算法思路构建的。原始多边形是在全局里面预设的,由于时间紧张没有测试过其他多边形(以及水平很菜),可能存在bug没有找到并维护。望谅解。
  2. 在实现本实验的过程中,调用了之前实验的函数(CSLineClip等),算是一种学以致用吧。

 

 

三 程序说明

Project中程序的调用:

将当前cpp文件的属性——常规——从生成中排除中选择否,其他文件选择是,即可运行当前的cpp文件

 

4题:无退化

//

// 程序名称:多边形裁剪1-1

// 功    能:用逐边裁剪法实现多边形裁剪(无退化)

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-31

#include <graphics.h>

#include <conio.h>

#include <iostream>

using namespace std;

//框的边界

float XL = 5, XR = 140, YB = 74, YT = 149;

POINT Edge[] = { {XR,YB},{XR,YT},{XL,YT},{XL,YB} };

//自定义多边形

POINT Vertex[] = { {110,84},{160,94},{90,169},{90,94},{70,90},{50,230}, {165,230},{175,89},{163,54} };

int inlen = 9;

#define max 100

//判断顶点和裁剪边的内外关系

bool Inside(POINT test, POINT p0, POINT p1) {

    if (p1.x > p0.x) {

         //裁剪边是窗口的下边

         if (test.y >= p0.y) {

             return 1;

         }

    }

    else if (p1.x < p0.x) {

         //裁剪边是窗口的上边

         if (test.y <= p0.y) {

             return 1;

         }

    }

    else if (p1.y > p0.y) {

         //裁剪边是窗口的右边

         if (test.x <= p0.x) {

             return 1;

         }

    }

    else if (p1.y < p0.y) {

         //裁剪边是窗口的左边

         if (test.x >= p0.x) {

             return 1;

         }

    }

    return 0;

}

//求多边形的一条边和裁剪边的交点

void Cross(POINT s, POINT p, POINT p0, POINT p1, POINT &i) {

    if (p0.y == p1.y) {

         //水平裁剪边

         i.y = p0.y;

         i.x = s.x + (p0.y - s.y) * (p.x - s.x) / (p.y - s.y);

    }

    else {

         //竖直裁剪边

         i.x = p0.x;

         i.y = s.y + (p0.x - s.x) * (p.y - s.y) / (p.x - s.x);

    }

}

//将新的多边形顶点加入原有顶点组

void Insert(POINT newpoint, int &mylen, POINT p[]) {

    p[mylen].x = newpoint.x;

    p[mylen].y = newpoint.y;

    mylen++;

    //顶点数+=1

}

//裁剪算法

void SHClip(int mylen, POINT in[], int& outlen, POINT out[], POINT p0, POINT p1) {

    POINT s, p, i;

    outlen = 0;

    s = in[mylen - 1];

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

         p = in[j];

         if (Inside(p, p0, p1)) {

             if (Inside(s, p0, p1)) {

                  Insert(p, outlen, out);

             }

             else {

                  Cross(s, p, p0, p1, i);

                  Insert(i, outlen, out);

                  Insert(p, outlen, out);

             }

         }

         else if (Inside(s, p0, p1)) {

             Cross(s, p, p0, p1, i);

             Insert(i, outlen, out);

         }

         s = p;

    }

}

int main() {

    //接收框的信息

    float x0, y0, x1, y1;

    initgraph(640, 480);

    //绘制自定的point多边形

    setcolor(WHITE);

    polygon(Vertex, 9);

    //绘制框

    setlinecolor(RED);

    line(XL, YT, XR, YT);

    line(XL, YB, XR, YB);

    line(XL, YT, XL, YB);

    line(XR, YT, XR, YB);

    ExMessage m;

    POINT outp1[max], outp2[max], outp3[max], outp4[max];

    int len1, len2, len3, len4;

    int times = 0;

    while (1) {

         m = getmessage(EX_MOUSE | EX_KEY);

         //用户点击左键后生成裁剪图形

         if (m.message == WM_LBUTTONDOWN) {

            

             //裁剪过程

             //POINT Edge[] = { {XR,YB},{XR,YT},{XL,YT},{XL,YB} };

             //右边窗口裁剪边

             SHClip(inlen, Vertex, len1, outp1, Edge[0], Edge[1]);

             //上边窗口裁剪边

             SHClip(len1, outp1, len2, outp2, Edge[1], Edge[2]);

             //左边窗口裁剪边

             SHClip(len2, outp2, len3, outp3, Edge[2], Edge[3]);

             //下边窗口裁剪边

             SHClip(len3, outp3, len4, outp4, Edge[3], Edge[0]);

             //连线过程

             setcolor(YELLOW);

             polygon(outp4, len4);

             //原来的位置进行黄色标注裁剪

            

             times++;

         }

         //用户点击右键后在旁边空白处生成裁剪图形

         else if (m.message == WM_RBUTTONDOWN) {

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

                  outp4[i].x += 200;

             }

             setcolor(YELLOW);

             polygon(outp4, len4);

             times++;

         }

         if (times == 2) {

             break;

         }

    }

    _getch();                 // 按任意键继续

    closegraph();         // 关闭绘图窗口

    return 0;

}

4题:有退化

//

// 程序名称:多边形裁剪1-2

// 功    能:用逐边裁剪法实现多边形裁剪(有退化)

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-31

#include <graphics.h>

#include <conio.h>

#include <iostream>

#include <stdlib.h>

#include <stdio.h>

using namespace std;

//框的边界

float XL = 5, XR = 140, YB = 74, YT = 149;

POINT Edge[] = { {XR,YB},{XR,YT},{XL,YT},{XL,YB} };

//自定义多边形

POINT Vertex[] = { {110,84},{160,94},{90,169},{90,94},{70,90},{50,230}, {165,230},{175,89},{163,54} };

int inlen = 9;

#define max 100

//判断顶点和裁剪边的内外关系

bool Inside(POINT test, POINT p0, POINT p1) {

    if (p1.x > p0.x) {

         //裁剪边是窗口的下边

         if (test.y >= p0.y) {

             return 1;

         }

    }

    else if (p1.x < p0.x) {

         //裁剪边是窗口的上边

         if (test.y <= p0.y) {

             return 1;

         }

    }

    else if (p1.y > p0.y) {

         //裁剪边是窗口的右边

         if (test.x <= p0.x) {

             return 1;

         }

    }

    else if (p1.y < p0.y) {

         //裁剪边是窗口的左边

         if (test.x >= p0.x) {

             return 1;

         }

    }

    return 0;

}

//求多边形的一条边和裁剪边的交点

void Cross(POINT s, POINT p, POINT p0, POINT p1, POINT& i) {

    if (p0.y == p1.y) {

         //水平裁剪边

         i.y = p0.y;

         i.x = s.x + (p0.y - s.y) * (p.x - s.x) / (p.y - s.y);

    }

    else {

         //竖直裁剪边

         i.x = p0.x;

         i.y = s.y + (p0.x - s.x) * (p.y - s.y) / (p.x - s.x);

    }

}

//将新的多边形顶点加入原有顶点组

void Insert(POINT newpoint, int& mylen, POINT p[]) {

    p[mylen].x = newpoint.x;

    p[mylen].y = newpoint.y;

    mylen++;

    //顶点数+=1

}

//裁剪算法

void SHClip(int mylen, POINT in[], int& outlen, POINT out[], POINT p0, POINT p1) {

    POINT s, p, i;

    outlen = 0;

    s = in[mylen - 1];

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

         p = in[j];

         if (Inside(p, p0, p1)) {

             if (Inside(s, p0, p1)) {

                  Insert(p, outlen, out);

             }

             else {

                  Cross(s, p, p0, p1, i);

                  Insert(i, outlen, out);

                  Insert(p, outlen, out);

             }

         }

         else if (Inside(s, p0, p1)) {

             Cross(s, p, p0, p1, i);

             Insert(i, outlen, out);

         }

         s = p;

    }

}

//VS不让用快排啊=。=

int cmp(void* a, void* b) {

    return *(int*)a - *(int*)b;

}

int main() {

    //接收框的信息

    initgraph(640, 480);

    //绘制自定的point多边形

    setcolor(WHITE);

    polygon(Vertex, 9);

    //绘制框

    setlinecolor(RED);

    line(XL, YT, XR, YT);

    line(XL, YB, XR, YB);

    line(XL, YT, XL, YB);

    line(XR, YT, XR, YB);

    ExMessage m;

    POINT outp1[max], outp2[max], outp3[max], outp4[max];

    int len1, len2, len3, len4;

    int times = 0;

    while (1) {

         m = getmessage(EX_MOUSE | EX_KEY);

         //用户点击左键后生成裁剪图形

         if (m.message == WM_LBUTTONDOWN) {

             //裁剪过程

             //POINT Edge[] = { {XR,YB},{XR,YT},{XL,YT},{XL,YB} };

             //右边窗口裁剪边

             SHClip(inlen, Vertex, len1, outp1, Edge[0], Edge[1]);

             //上边窗口裁剪边

             SHClip(len1, outp1, len2, outp2, Edge[1], Edge[2]);

             //左边窗口裁剪边

             SHClip(len2, outp2, len3, outp3, Edge[2], Edge[3]);

             //下边窗口裁剪边

             SHClip(len3, outp3, len4, outp4, Edge[3], Edge[0]);

             //连线过程

             //setcolor(YELLOW);

             //polygon(outp4, len4);

             //原来的位置进行黄色标注裁剪

             /*closegraph();           // 关闭绘图窗口

             for (int t = 0; t < len4; t++) {

                  cout << outp4[t].x <<" " << outp4[t].y << endl;

             }*/

             //退化边,根据outp4修改吧

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

                  int flag = 1;

                  if (outp4[i].x == outp4[i + 1].x) {

                      if (outp4[i].x == int(XL) || outp4[i].x == int(XR)) {

                          flag = 0;

                      }

                 }

                  if (outp4[i].y == outp4[i + 1].y) {

                      if (outp4[i].y == int(YB) || outp4[i].y == int(YT)) {

                          flag = 0;

                      }

                  }

                  if (flag == 1) {

                      setcolor(YELLOW);

                      //+200像素,可能是为了,方便展示orz

                      line(outp4[i].x + 200, outp4[i].y, outp4[i + 1].x + 200, outp4[i + 1].y);

                  }

             }

            

             //float XL = 5, XR = 140, YB = 74, YT = 149;

             //{XR,YB},{XR,YT},{XL,YT},{XL,YB}

             //{ {110,84},{160,94},{90,169},{90,94},{70,90},{50,230}, {165,230},{175,89},{163,54} };

            

             //将坐标值按从小到大排序,奇数线段依次连接。

             int xl[10], xr[10], yb[10], yt[10];//记录和框重合的点

             int cntl = 0, cntr = 0, cntb = 0, cntt = 0;

             for (int t = 0; t < len4; t++) {

                  if (outp4[t].x == int(XL)) {

                      //有了一个x坐标了我还用啥二维数组存坐标啊,笑

                      //[XL,y]

                      xl[cntl++] = outp4[t].y;

                  }

                  if (outp4[t].x == int(XR)) {

                      //[XR,y]

                      xr[cntr++] = outp4[t].y;

                  }

                  if (outp4[t].y == int(YB)) {

                      //[x,YB]

                      yb[cntb++] = outp4[t].x;

                  }

                  if (outp4[t].y == int(YT)) {

                      //[x,YB]

                      yt[cntt++] = outp4[t].x;

                  }

             }

             /*void selectSort(int& a, int alen) {

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

                      int min = i;

                      for (int j = i + 1; j < alen; j++) {

                          if (a[j] < a[min]) {

                               min = j;

                          }

                      }

                      //swap elements

                      int temp = a[min];

                      a[min] = a[i];

                      a[i] = temp;

                  }

             }*/

             //为什么调用sort函数呢,突然的bug猝不及防。还是传统方法改好了。

             //排序x,y坐标

             //画left边

             if (cntl != 0) {

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

                      int min = i;

                      for (int j = i + 1; j < cntl; j++) {

                          if (xl[j] < xl[min]) {

                               min = j;

                          }

                      }

                      int t = xl[min];

                      xl[min] = xl[i];

                      xl[i] = t;

                  }

                  for (int i = 0; i < cntl; i += 2) {

                      setcolor(YELLOW);

                      line(int(XL) + 200, xr[i], int(XL) + 200, xr[i + 1]);

                  }

             }

             //画right边

             if (cntr != 0) {

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

                      int min = i;

                      for (int j = i + 1; j < cntr; j++) {

                          if (xr[j] < xr[min]) {

                               min = j;

                          }

                      }

                      int t = xr[min];

                      xr[min] = xr[i];

                      xr[i] = t;

                 }

                  for (int i = 0; i < cntr; i += 2) {

                      setcolor(YELLOW);

                      line(int(XR) + 200, xr[i], int(XR) + 200, xr[i + 1]);

                  }

             }

             //画bottom边

             if (cntb != 0) {

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

                      int min = i;

                      for (int j = i + 1; j < cntb; j++) {

                          if (yb[j] < yb[min]) {

                               min = j;

                          }

                      }

                      int t = yb[min];

                      yb[min] = yb[i];

                      yb[i] = t;

                  }

                  for (int i = 0; i < cntb; i += 2) {

                      setcolor(YELLOW);

                      line(yb[i] + 200, int(YB), yb[i + 1] + 200, int(YB));

                  }

             }

             //画top边

             if (cntt != 0) {

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

                      int min = i;

                      for (int j = i + 1; j < cntt; j++) {

                          if (yt[j] < yt[min]) {

                               min = j;

                          }

                      }

                      int t = yt[min];

                      yt[min] = yt[i];

                      yt[i] = t;

                  }

                  for (int i = 0; i < cntt; i += 2) {

                      setcolor(YELLOW);

                      line(yt[i] + 200, int(YT), yt[i + 1] + 200, int(YT));

                  }

             }

         }

    }

    _getch();                 // 按任意键继续

    closegraph();         // 关闭绘图窗口

    return 0;

}

5

//

// 程序名称:多边形裁剪2

// 功    能:用Weiler-Atherton裁剪法实现多边形裁剪

// 编译环境:VS2019,EasyX_20220116

// 最后修改:2022-3-31

#include <graphics.h>

#include <conio.h>

#include <iostream>

using namespace std;

//框的边界

float XL = 20, XR = 150, YB = 200, YT = 450;

POINT Edge[] = { {XR,YB},{XR,YT},{XL,YT},{XL,YB} };

//自定义多边形,顺时针排序点坐标

POINT Vertex[] = { {300,100},{100,400},{200,120},{50,300},{100,100} };

int inlen = 5, outlen = 0;

int keepx[100], keepy[100];

//编码数值

#define LEFT 1

#define RIGHT 2

#define BOTTOM 4

#define TOP 8

//编码函数

int encode(float x, float y, int* code) {

    int c = 0;

    if (x < XL) {

         c = c | LEFT;

    }

    else if (x > XR) {

         c = c | RIGHT;

    }

    if (y < YB) {

         c = c | BOTTOM;;

    }

    else if (y > YT) {

         c = c | TOP;

    }

    *code = c;

    return 0;

}

//CS裁剪

int CSLineClip(float x1, float y1, float x2, float y2) {

    //记录原始点

    float x10 = x1, y10 = y1, x20 = x2, y20 = y2;

    int code1, code2, code;

    float x, y;

    encode(x1, y1, &code1);

    encode(x2, y2, &code2);

    while (code1 != 0 || code2 != 0) {

         if ((code1 & code2) != 0) {

             return 0;

         }

         code = code1;

         if (code1 == 0) {

             code = code2;

         }

         //找交点,通过边界找坐标值

         if ((LEFT & code) != 0) {

             x = XL;

             y = y1 + (y2 - y1) * (XL - x1) / (x2 - x1);

         }

         else if ((RIGHT & code) != 0) {

             x = XR;

             y = y1 + (y2 - y1) * (XR - x1) / (x2 - x1);

         }

         else if ((BOTTOM & code) != 0) {

             y = YB;

             x = x1 + (x2 - x1) * (YB - y1) / (y2 - y1);

         }

         else if ((TOP & code) != 0) {

             y = YT;

             x = x1 + (x2 - x1) * (YT - y1) / (y2 - y1);

         }

         //更新范围内的交点

         if (code == code1) {

             x1 = x;

             y1 = y;

             encode(x, y, &code1);

         }

         else {

             x2 = x;

             y2 = y;

             encode(x, y, &code2);

         }

    }

    //最终端点是x1 y1, x2 y2

    //由于本题的特殊性,一定有一个是原始点,那先在一开始记录下

    //把求得的交点push到keep数组中

    //记录原始点 float x10 = x1, y10 = y1, x20 = x2, y20 = y2;

    if (x10 == x1 && y10 == y1) {

         //1点和原始点一样,那2点是交点,存入2点

         keepx[outlen] = x2;

         keepy[outlen] = y2;

         outlen++;//???换个名字就可以全局了

    }

    else if (x20 == x2 && y20 == y2) {

         //2点和原始点一样,那1点是交点,存入1点

         keepx[outlen] = x1;

         keepy[outlen] = y1;

         outlen++;

    }

    //画线

    setlinecolor(YELLOW);

    line(x1, y1, x2, y2);

    return 0;

}

int main() {

    initgraph(640, 480);

    //绘制自定的point多边形

    setcolor(WHITE);

    polygon(Vertex, inlen);

    setcolor(RED);

    polygon(Edge, 4);

    //寻找第一个从外部->内部的边,求交点

    int startnum = -1, endnum = -1;

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

         int code1 = -1, code2 = -1;

         //非末尾点判断

         if (i < inlen - 1) {

             encode(Vertex[i].x, Vertex[i].y, &code1);

             encode(Vertex[i + 1].x, Vertex[i + 1].y, &code2);

             if (code1 != 0 && code2 == 0) {

                  //external to internal

                  startnum = i;

                  endnum = i + 1;

                  break;

             }

         }

         //末尾点判断

         else {

             encode(Vertex[inlen - 1].x, Vertex[inlen - 1].y, &code1);

             encode(Vertex[0].x, Vertex[0].y, &code2);

             if (code1 != 0 && code2 == 0) {

                  //external to internal

                  startnum = i;

                  endnum = i + 1;

                  break;

             }

         }

    }

    //看看框和多边形是否有交集

    if (startnum == -1) {

         //没找到交点

         return 0;

    }

    /*else {

         cout << startnum << " " << endnum; //输出判断

    }*/

    //设置全局count不行,给到主函数然后传参进去吧

    //int count = 0;

    //CSCLIP救我老命啊,直接求内外交点然后clip掉

    CSLineClip(Vertex[startnum].x, Vertex[startnum].y, Vertex[endnum].x, Vertex[endnum].y);

    int curnum = endnum;

    int times = 1;//判断是否循环结束

    while (1) {

         int code1 = -1, code2 = -1;

         int flag = -1;

         //给起始点编码,看看是否在框内

         if (curnum < inlen - 1) {

             encode(Vertex[curnum].x, Vertex[curnum].y, &code1);

             encode(Vertex[curnum + 1].x, Vertex[curnum + 1].y, &code2);

             flag = 1;

         }

         else {

             encode(Vertex[inlen - 1].x, Vertex[inlen - 1].y, &code1);

             encode(Vertex[0].x, Vertex[0].y, &code2);

             flag = 0;

         }

         //两个点都在框内

         if (code1 == 0 && code2 == 0) {

             setlinecolor(YELLOW);

             if (flag == 1) {

                  line(Vertex[curnum].x, Vertex[curnum].y, Vertex[curnum + 1].x, Vertex[curnum + 1].y);

             }

             else if (flag == 0) {

                  line(Vertex[inlen - 1].x, Vertex[inlen - 1].y, Vertex[0].x, Vertex[0].y);

             }

         }

         //起点内,终点外

         else if (code1 == 0 && code2 != 0) {

             if (flag == 1) {

                  CSLineClip(Vertex[curnum].x, Vertex[curnum].y, Vertex[curnum + 1].x, Vertex[curnum + 1].y);

             }

             else if (flag == 0) {

                  CSLineClip(Vertex[inlen - 1].x, Vertex[inlen - 1].y, Vertex[0].x, Vertex[0].y);

             }

         }

         //起点外,终点内

         else if (code1 != 0 && code2 == 0) {

             if (flag == 1) {

                  CSLineClip(Vertex[curnum].x, Vertex[curnum].y, Vertex[curnum + 1].x, Vertex[curnum + 1].y);

             }

             else if (flag == 0) {

                  CSLineClip(Vertex[inlen - 1].x, Vertex[inlen - 1].y, Vertex[0].x, Vertex[0].y);

             }

         }

         //起点外,终点外

         else {

             //不画线

         }

         //记录入框交点和出框交点,并连结

         //当前线段判断完并连线完,给下一轮循环更新curnum

         if (curnum == inlen - 1) {

             curnum = 0;

             times++;

         }

         else {

             curnum++;

             times++;

         }

         //判断循环退出

         if (times == inlen) {

             break;

         }

    }

    for (int i = 0; i < outlen; i += 2) {

         line(keepx[i], keepy[i], keepx[i + 1], keepy[i + 1]);

    }

    _getch();                 // 按任意键继续

    closegraph();         // 关闭绘图窗口

    //cout << outlen;

    /*

    //交点判断

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

         cout << keepx[i] << " " << keepy[i] << endl;

    }

    */

    return 0;

}

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

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

相关文章

GaussDB工作级开发者认证—第五章GaussDB数据库操作与管理

一、数据库对象基本操作 查询数据库&#xff1a; postgres# \l --使用元命令查看数据库 postgres# select * from pg_database; --通过系统表查看数据库 表注意事项: 只有表的所有者有权限执行ALTER TABLE命令&#xff0c;系统管理员默认拥有此权限 不能修改分区表的tables…

creator-assetbundle分包

title: creator-assetbundle分包 categories: Cocos2dx tags: [creator, 分包, assetbundle] date: 2023-04-10 15:55:22 comments: false mathjax: true toc: true creator-assetbundle分包 前篇 Asset Bundle 介绍 - https://docs.cocos.com/creator/manual/zh/asset/bundle…

国家出手管人工智能AI了

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 全球都在封杀AI&#xff0c;国家也出手了&#xff0c;人工智能AI的强监管来了!这次反应速度算是很快了。国家出手&#xff0c;AI必须管。 国家网信办拟针对生成式人工智能服务出台管理办法&#…

【万象奥科】RZ/G2UL网关内存压力测试

测试目的 内存压力测试的目的是测试系统内存的稳定性和可靠性&#xff0c;以便确定系统是否能够在各种负载情况下正常运行。其主要目的有&#xff1a; 测试内存的正确性&#xff1a;通过模拟各种内存负载情况&#xff0c;例如写入随机数据、重复写入相同数据、使用指定的模式…

原型模式解读

目录 模式引进问题 原型模式 原型模式原理结构图-uml 类图 原型模式解决克隆羊问题的应用实例 深拷贝和浅拷贝 浅拷贝的介绍 深拷贝基本介绍 重写 clone 方法来实现深拷贝 通过对象的序列化实现实现深拷贝&#xff08;推荐&#xff09; 原型模式的注意事项和细节 模式…

阿里云linux云服务器 安装指定版本node.js

我们在实例管理中找到自己的服务器 然后点击右侧的 远程连接 接着点击理解登录 进入命令窗口 我们在这上面输入 curl -h阿里云的服务器都还是最好会有 curl的 然后 我们输入 sudo curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | bash下把nv…

带头部表头和侧边表头样式的布局

原型设计的页面中的表格除了头部还有左侧侧边是表头的一个表格&#xff0c;查阅组件文档&#xff0c;发现表格table没有两个表头的布局。 思路&#xff1a; 1、使用div自己布局 2、使用表格table&#xff0c;修改其第一列样式背景&#xff0c;展示除了的样子看着像是有多个表头…

突发!ChatGPT疯了!

‍数据智能产业创新服务媒体——聚焦数智 改变商业今天&#xff0c;笔者正常登录ChatGPT&#xff0c;试图调戏一下他。但是&#xff0c;突然震惊的发现&#xff0c;ChatGPT居然疯了。之所以说他是疯了&#xff0c;而不是崩溃了&#xff0c;是因为他还能回复我&#xff0c;但回…

【计算机网络】1、概念、TCP | UDP | 本地 socket 编程

文章目录一、网络基本概念1.1 端口&#xff08;port&#xff09;1.2 IP 地址 网络地址&#xff08;network&#xff09;和 主机&#xff08;host&#xff09;1.3 子网&#xff08;subnet&#xff09;1.4 子网掩码&#xff08;netmask&#xff09;1.5 保留网段1.6 CIDR 表述形式…

【计算机网络复习】第三章 传输层 3

拥塞 网络边缘主机发送到网络中的负载超出了网络的承载能力&#xff0c;即导致拥塞 u 网络拥塞的特征 时延增大 — 由于在路由器缓存中排队而导致 数据包丢失 — 由于路由器的缓存溢出而导致 u 随着网络负载的增加 传输时延增大 吞吐量下降 拥塞控制&#…

ptuning v2 的 chatglm垂直领域训练记录

thunlp chatglm 6B是一款基于海量高质量中英文语料训练的面向文本对话场景的语言模型。 THUDM/ChatGLM-6B: ChatGLM-6B&#xff1a;开源双语对话语言模型 | An Open Bilingual Dialogue Language Model (github.com) 国内的一位大佬把chatglm ptuning 的训练改成了多层多卡并…

Spring 事务

目录 一、事务简介 二、在Spring中实现事务 编程式事务 声明式事务 三、事务的传播机制 一、事务简介 事务&#xff1a;就是将一组操作封装成为一个整体执行单元&#xff0c;要么全部执行&#xff0c;要么都不执行。 假如事务执行了一半发生了错误就会对已经执行的部分进…

Linux嵌入式学习之Ubuntu入门(三)用户、用户组及文件权限

系列文章目录 一、Linux嵌入式学习之Ubuntu入门&#xff08;一&#xff09;基本命令、软件安装及文件结构 二、Linux嵌入式学习之Ubuntu入门&#xff08;二&#xff09;磁盘文件介绍及分区、格式化等 文章目录系列文章目录用户与用户组创建用户和用户组图形化创建命令创建文件…

【人工智能】— 逻辑Agent、一般逻辑、Entailment 蕴涵、命题逻辑、前向链接、反向链接、Resolution归结

【人工智能】— 逻辑Agent、逻辑智能体Knowledge bases一个简单的基于知识的智能体一般逻辑Entailment 蕴涵Models模型蕴涵与推理命题逻辑逻辑连接词枚举推理有效性可满足性推导和证明霍恩子句Forward chaining 前向链接Proof of completeness&#xff08;完备性&#xff09;Ba…

QT学习开发笔记(项目实战之智能家居物联网项目1 )

智能家居物联网项目 本章介绍使用 Qt 开发智能家居中的一个物联应用。简单直白的说就是通过云服务器远程控 制设备&#xff08;与设备通信等&#xff09;。本章可以直接做毕设&#xff0c;是毕设物联网项目的一大福音&#xff01;本章将实现远 程点亮开发板 LED 作为一个项目实…

springboot从2.1.3升级到2.3.5后控制台自动输出http请求日志RequestResponseBodyMethodProcessor

springboot从2.1.3升级到2.3.5后控制台自动输出http请求日志RequestResponseBodyMethodProcessor和RequestMappingHandlerMapping推荐使用第二个方案简单 明了 方便 快捷方案一第一步定义TurboFilter第二步配置logback方案二 直接配置logback的配置XML推荐使用第二个方案简单 明…

Insomnia 简单使用方法

文章目录1. 新建工程2. 新建若干文件夹3. 设置环境变量4. 授权以及进行请求的链式调用 (chaining requests)4. 1 解决办法 14. 2 解决办法 2Insomnia 同 Postman&#xff0c; 用于测试后端 endpoint&#xff0c;很容易使用。使用步骤如下&#xff1a;1. 新建工程 2. 新建若干文…

字节跳动软件测试面试过了,起薪20k

普通二本计算机专业毕业&#xff0c;从毕业后&#xff0c;第一份接触测试的工作是在一家通讯小公司&#xff0c;大部分接触的工作是以功能测试为主&#xff0c;一直都是几千块钱工资&#xff0c;还一度被派出差&#xff0c;以及兼职各种产品、运维、运营的活&#xff0c;感觉自…

四十五、docker之nginx手动部署前端项目

nginx的作用&#xff1a; 一、静态文件服务器和反向代理django服务 django框架中的静态文件服务只在开发调试时提供服务&#xff0c;当以生产模式运行时需要将静态文件部署到静态文件服务器上。 1. 收集django项目中的静态文件 在配置文件中配置STATIC_ROOT 我们在我的项目…

如何在低代码平台上构建ERP软件?

ERP软件是企业管理日常运营需求的关键组件。然而&#xff0c;对于许多企业&#xff0c;尤其是资源有限的企业来说&#xff0c;尝试构建和管理ERP平台可能要担负较高的成本的。幸运的是&#xff0c;低代码平台可以使这个过程变得容易得多。今天我们来解释如何在低代码平台上构建…