图形系统开发实战课程:进阶篇(上)——6.图形交互操作:拾取


[

图形开发学院|GraphAnyWhere

  • 课程名称:图形系统开发实战课程:进阶篇(上)
  • 课程章节:“图形交互操作:拾取”
  • 原文地址:https://www.graphanywhere.com/graph/advanced/2-6.html

第六章 图形交互操作:拾取

\quad 在图形系统中,拾取是指从屏幕上选择一个图形对象的过程。这个过程通常是通过鼠标或触摸屏等输入设备来实现的。当用户将鼠标移动到图形对象上时,图形系统会检测到鼠标的位置,然后根据鼠标位置计算该位置上的图形对象,从而实现了拾取操作,这个过程也称之为‘碰撞检测’。

\quad 由于 Canvas 不会保存绘制图形的信息,一旦绘制完成用户在浏览器中得到的是一张图片,用户在图片上点击时时不能直接获取到对应的图形对象,所以在绘图时需要缓存已经绘制的图形对象,碰撞检测有以下几种方案:

  • 内置API法:通过Canvas渲染上下文对象内置的 API,实现拾取图形
  • 几何法:通过几何运算,判断鼠标点击位置附近的对象,实现拾取图形
  • 取色法:通过获取点击位置的颜色值,实现图形拾取

1 内置API法

\quad Canvas 渲染上下文对象提供了 isPointInPath() 可以判断一个坐标点是否在路径内, 提供了 isPointInStroke() 判断一个坐标点是否在描边的边上。

\quad 我们在 图形系统开发实战课程-基础篇 中曾经讲述了Canvas路径的用法,路径可完成各种常见基本几何图形,和贝塞尔曲线的绘制,下图是 anyGraph内置的一些点的类型。

在这里插入图片描述

\quad 上面这些点类型均是通过路径绘制出来的,从这张图可以看出通过路径我们不仅仅可以绘制常见的几何图形,如三角形、矩形、圆形、多边形,还可以绘制诸如黑桃、红桃、梅花、花朵等复杂的带有曲线的图形。

\quad 如今 Canvas 渲染上下文对象更是提供了 isPointInPath() 可以判断一个坐标点是否在路径内, 提供了 isPointInStroke() 判断一个坐标点是否在描边的边上。利用这两个API我们可以实现几乎所有类型的图形对象拾取。

\quad 下面这个示例是在上一篇文章 图形交互:图形交互操作:平移和缩放 中的示例基础上做出了一些改变,在 redraw() 方法中增加了 point参数,该参数为鼠标当前的位置。当鼠标移动到某个方块内的时候,即 isPointInPath()返回true,该方块将会显示为红颜色;当鼠标移动到某个方块边缘的时候,即 isPointInStroke()返回true,该方块将会显示为黄颜色。 运行效果如下图所示:

在这里插入图片描述

\quad 这个示例中采用了 Canvas 渲染上下文对象提供的 isPointInPath()isPointInStroke() 方法判断点是否在路径中或边框之上。其源代码如下:

// 绘图
function redraw(point) {
    // 清除已有内容
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    // 绘制七巧板
    tangram.forEach(shape => {
        // 坐标转换
        let pixel = [];
        shape.coords.forEach(coord => {
            pixel.push(convert(coord, graphExtent, canvasExtent));
        })

        // 定义路径
        ctx.beginPath();
        for (let i = 0, ii = pixel.length; i < ii; i += 1) {
            if (i === 0) {
                ctx.moveTo(pixel[i][0], pixel[i][1]);
            } else {
                ctx.lineTo(pixel[i][0], pixel[i][1]);
            }
        }
        ctx.closePath();

        // 定义渲染颜色值
        let fillColor = shape.style.fillColor;
        let strokeColor = shape.style.color; 

        // 如果Point参数为空,则无需进行碰撞检测
        if (point != null && point.length == 2) {
            // 判断点是否在路径内, 如果在路径内,则将颜色改为红色
            if (ctx.isPointInPath(point[0], point[1])) {
                fillColor = "red";
                strokeColor = "red"
            } 
            // 判断点是否在路径的描边线上, 如果在路径内,则将颜色改为金色
            else {
                if (ctx.isPointInStroke(point[0], point[1])) {
                    fillColor = "gold";
                    strokeColor = "gold";
                }
            }
        }

        // 绘制
        ctx.save();
        ctx.strokeStyle = strokeColor;
        ctx.fillStyle = fillColor;
        ctx.fill();
        ctx.stroke();
        ctx.restore();
    })
}

使用该方法需要注意:

  1. 我们在 第四章 图形基本形状 讲述的图形对象类型包括:点、线、多边形、图像、文本、圆等,其中文本类型和图像类型无法通过该方法判断是否与点碰撞。
  2. 如果点存在大小时,该方法仅能判断其中心是否在路径内,而无法判断点的边缘是否在路境内。
  3. 在使用 isPointInPath(x, y)isPointInStroke(x, y) 方法判断点是否在路径中或边框之上的时候,这个点(x,y)坐标是指画布中的像素坐标。如果 画布在绘制路径之前进行了变形操作,参数依旧需传入画布变形前的像素坐标值。

2 几何法

\quad 几何法是指根据点的位置,采用几何算法判断该位置是否存在图形对象。我们在 第四章 图形基本形状 讲述的图形对象类型包括:点、线、矩形、多边形、图像、文本、圆等等。使用几何法进行判断时,需要分别对这些类型进行判断。

2.1 点与点

判断规则:

\quad 判断点与点是否相交,最简单的判断方法是两个点的坐标是否相等,如果相等则判断这两个点相交,而实际绘图的点是有大小的,而且由于浮点误差方面的原因,不能简单判断点与点是否相等,而因改为计算点与点之间的距离,如果这个距离小于容差值,则判断这两个点相交。

实现代码:

/**
 * 判断点与点是否碰撞
 * @param {Point} p1 {x, y}
 * @param {Point} p2 {x, y}
 * @param {float} buffer 
 * @returns boolean
 */
function pointPoint(point1, point2, buffer) {
    if (buffer === undefined) {
        buffer = 0.1;
    }
    if (CoordUtil.dist([point1.x, point1.y], [point2.x, point2.y]) <= buffer) {
        return true;
    }
    return false;
}

运行效果:

在这里插入图片描述

2.2 点与圆

判断规则:

\quad 判断点与圆是否相交的规则和判断点与点是否相交的规则类似,通过计算点与圆心之间的距离,如果距离小于等于圆的半径,则判断点在圆内,否则判断点不在圆内。

实现代码:

/**
 * 判断点与圆是否碰撞
 * @param {Point} p {x, y}
 * @param {Circle} c {cx, cy, radius}
 * @returns boolean
 */
function pointCircle(point, circle) {
    if (CoordUtil.dist([point.x, point.y], [circle.cx, circle.cy]) <= circle.radius) {
        return true;
    }
    return false;
};

运行效果:

在这里插入图片描述

2.3 点与线

判断规则:

\quad 判断点与线是否相交的规则: 分别计算点与线的两个端点之间的距离,如果距离之和等于线的长度,则可判定点与线相交。

实现代码:

/**
 * 判断点与线段是否碰撞
 * @param {*} point {x, y}
 * @param {*} line {x1, y1, x2, y2}
 * @param {*} buffer 容差
 * @returns boolean
 */
function pointLine(point, line, buffer) {
    if (buffer === undefined) {
        buffer = 0.1;
    }

    // 计算点与线段的两个端点之间的距离
    let d1 = Coordinate.dist([point.x, point.y], [line.x1, line.y1]);
    let d2 = Coordinate.dist([point.x, point.y], [line.x2, line.y2]);

    // 计算线段长度
    let lineLen = Coordinate.dist([line.x1, line.y1], [line.x2, line.y2]);

    // 如果点与线段的两个端点之间的距离之和等于线的长度,则可判定点与线相交
    if (d1 + d2 >= lineLen - buffer && d1 + d2 <= lineLen + buffer) {
        return true;
    }
    return false;
}

运行效果:

在这里插入图片描述

折线通常包含了多个线段,点与折线是否相交的判断规则是以 点与线段是否相交为基础,逐一判断点与每段线的关系。点只要与其中任何一段线相交,即可判段点与折线相交。

2.4 点与矩形

判断规则:

\quad 判断点与矩形是否相交的规则:当点的X坐标大于等于矩形的起点X坐标,小于等于矩形的起点X坐标加上矩形宽度,且点的Y坐标大于等于矩形的起点Y坐标,小于等于矩形的起点Y坐标加上矩形高度时,判断点在矩形内,否则判断点不在矩形内。

实现代码:

/**
 * 判断点与矩形是否碰撞
 * @param {*} point {x, y}
 * @param {*} rect {x, y, width, height}
 * @returns boolean
 */
function pointRect(point, rect) {
    if (point.x >= rect.x && point.x <= rect.x + rect.width &&    // X坐标大于等于矩形的起点X坐标,小于等于矩形的起点X坐标加上矩形宽度
        point.y >= rect.y && point.y <= rect.y + rect.height) {   // Y坐标大于等于矩形的起点Y坐标,小于等于矩形的起点Y坐标加上矩形高度
        return true;
    }
    return false;
}

运行效果:

在这里插入图片描述

2.5 点与文本

判断规则:

\quad 文本绘制的结果是一个矩形区域,因此其判断点与文本是否相交的方法与矩形一样。需要注意的是在绘制文本的时候 水平对齐方式垂直对齐方式 对文本的绘制位置有很大影响。下面的代码可计算绘制文本时的矩形位置和大小:

/**
 * 返回对象边界
 * @param {Boolean} useCoord 为true时返回坐标Bound,为false时返回屏幕像素Bound
 * @returns {Extent} extent
 */
getBBox(useCoord = true) {
    let coord = useCoord === false ? this.getPixel() : this.getCoord();

    // 矢量字体才考虑宽度和高度对BBOX的影响
    let width = this._renderWidth;   // 渲染文本时记录的文本宽度,可通过ctx.measureText(this.text).width获取
    let height = this._renderHeight;  // 通常为字体大小

    // 根据字体水平对齐方式确定文本的bbox
    let left, top;
    if (this.style.textAlign == "center" || this.style.textAlign == "middle") {
        left = coord[0][0] - width / 2;
    } else if (this.style.textAlign == "right") {
        left = coord[0][0] - width;
    } else {
        left = coord[0][0]
    }
    // 属性值有 top(文本块的顶部), hanging(悬挂基线), middle(文本块的中间), alphabetic(标准的字母基线), ideographic(表意字基线), bottom(文本块的底部)
    if (this.style.textBaseline == "middle") {
        top = coord[0][1] - height / 2;
    } else if (this.style.textBaseline == "bottom" || this.style.textBaseline == "ideographic") {
        top = coord[0][1] - height;
    } else if (this.style.textBaseline == "alphabetic") {
        top = coord[0][1] - height;;
    } else {    // top,  "hanging"
        top = coord[0][1];
    }
    return [left, top, left + width, top + height];
}

运行效果:

在这里插入图片描述

2.6 点与图像

判断规则:

\quad 图像绘制的结果是也一个矩形区域,因此其判断点与文本是否相交的方法与矩形一样,且其Bounding Box的计算较为简单,这里就不展开叙述了。

2.7 点与多边形

\quad 判断点与多边形是否相交的规则是:判断这个点和多边形每条边的位置关系。在一个多条边围成的区域,点在一条边的右侧,这个点可能在多边形内部,也可能在外部。但是如果判断完点和每一条边的左右关系,如果在右边的边是奇数个,那么点就在内部,如果是偶数,那么点就在外部。通过这个规则,就可以判断点是否包含在多边形内。

来源:https://blog.csdn.net/tom_221x/article/details/51861129

\quad 那么,如何判断一个点和一条边的位置关系? 这里需要用到一个向量叉积公式。比如,点(x, y),与线 (x1, y1) (x2, y2) 的位置关系。我们先求出两个向量 (x - x1, y - y1) 和 (x2 - x1, y2 - y1)。对这两个向量做叉积的结果是 (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1), 如果结果是0,那么点在线上。如果结果大于0,点在线的右边。如果结果小于0,点在线的左边。 利用这个公式,我们就能判断点是否在多边形的内部还是外部。

实现代码:

/**
 * 判断点与多边形是否碰撞
 * @param {*} point {x, y}
 * @param {*} polygon [[x,y],[x,y],[x,y]]
 * @returns 
 */
function pointPoly(point, polygon) {
    let collision = false;

    // 遍历多边形的每一条边
    let next = 0;
    for (let current = 0; current < polygon.length; current++) {

        // 当前顶点
        let vc = polygon[current];
        // 下一个顶点
        next = (current === polygon.length - 1 ? 0 : current + 1);
        let vn = polygon[next]; 

        // 判断一个点和一条边(vc,vn)的位置关系, 如果两个检查都为 true,则切换到其相反的值
        if ((vc[1] >= point.y && vn[1] < point.y) || (vc[1] < point.y && vn[1] >= point.y)) {
            // 求出两个向量(x - x1, y - y1) 和 (x2 - x1, y2 - y1), 
            // 并对两个向量做叉积的 (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1)
            if ((point.x - vc[0]) < (point.y - vc[1]) * (vn[0] - vc[0]) / (vn[1] - vc[1])) {
                // 如果结果为零: 表示点在线上
                // 如果结果为正: 表示点在线的右边
                // 如果结果为负: 表示点在线的左边
                collision = !collision;
            }
        }
    }
    return collision;
}

运行效果:

在这里插入图片描述

点与多边形是否相交的几何判断方法很重要,2.4节中讲述了点与矩形的判断方法,那种方法在矩形旋转后,就无法判断了。而对于旋转的矩形可将计算矩形旋转后各个角的坐标值,然后将其转换为多边形,采用点与多边形是否相交的办法进行判断。

3. 取色法

\quad 取色法的核心思想是在绘制图像的同时,在另一个Canvas中绘制一份与当前图形中各个对象坐标位置和大小均相同,且使用独一无二颜色绘制的图形(缓存图形),同时还需保存一份图形颜色与图形对象的对照表。利用 Canvas 渲染上下文对象提供的像素操作API,在进行拾取操作时,从缓存图形中根据点的位置获取相应的颜色信息,并从颜色对照表中取出对应的图形对象。

\quad 下图展示了取色法的核心思想,图形的左侧是要绘制的图形,图形的右侧是缓存的图形,这份缓存图形中中的对象位置和大小和原图完全一样,而颜色却是随机产生的独一无二的颜色。使用 Canvas 渲染上下文对象的 ctx.getImageData(x, y, 1, 1) 方法,可取的指定位置那个像素的颜色,最后通过颜色与图形对象对照表即可取得拾取的对象。

在这里插入图片描述

\quad ctx.getImageData() 返回的数据中包含了 data 属性,该属性属于Uint8ClampedArray类型,存储了像素数据,每个像素包含了4个byte的值,分别是该像素对应的红,绿,蓝和透明值(r,g,b,a)。下图显示了imageData中data的数组结构,每个像素均占了data数组中的4个元素,第一个像素存储在data数组的0至3个元素,第二个像素存储在data数组的4至7个元素。

在这里插入图片描述

\quad 我们这里仅拾取了1个像素值,因此该数组仅包含4个元素。拾取指定位置颜色的代码如下所示:

/**
 * 获取图形中指定位置的颜色值
 * @param {Array} point 
 * @returns color
 */
function getColor(point) {
    if (this._hitContext) {
        let imageData = this._hitContext.getImageData(point[0], point[1], 1, 1);
        if (imageData.data[0] === 0 && imageData.data[1] === 0 && imageData.data[2] === 0 && imageData.data[3] === 0) {
            return null;
        } else {
            return new Color(imageData.data[0], imageData.data[1], imageData.data[2], imageData.data[3]).toHex();
        }
    } else {
        return null;
    }
}

\quad 对于常见的几何图形,使用这个思路直接在缓存的图形中绘制即可。对于文本和图像,则需要将其转换为矩形,通过矩形的方式绘制在缓存的图形中。下图演示了使用 取色法 从一张包含了各类图形对象的图形中拾取对象的效果。

在这里插入图片描述

4. 方案比较

4.1 内置API法

优点:

  • 开发简单;
  • 识别率高;

缺点:

  • 拾取效率低,拾取的时候定义路径导致拾取效率低;
  • 无法拾取非路径绘制的图形,例如文本和图像;
  • 无法实现根据矩形或多边形进行拾取;

4.2 几何法

优点:

  • 扩展性强;
  • 识别率高;

缺点:

  • 开发复杂,需针对各种类型的图形分别实现其算法;
  • 拾取效率一般;

4.3 取色法

优点:

  • 开发简单;
  • 拾取效率高;

缺点:

  • 渲染开销加倍,每次图形渲染时间为内置API法或几何法的两倍;
  • 当图形重叠时,仅能识别到最上层的图形对象;
  • 无法实现根据矩形或多边形进行拾取;

5. anyGraph 的实现

anyGraph 实现了 几何法 和 取色法 两种图形对象的拾取方案。

5.1 取色法

Graph 对象在初始化时可通过 hitGetColor 选项,指定是否启用‘取色法拾取方案’。 该参数的缺省值为 false

下面这段代码启用了‘取色法拾取方案’。

// graph对象
let graph = new Graph({
    "target": "graphWrapper",
    "hitGetColor": true
});

下面这段代码演示了取色法的碰撞检测:

// 取色法进行碰撞检测
function _collideCheck(coord) {
    // 显示颜色值
    let hitColor = graph.getRenderer().getColor(coord);
    if (hitColor) {
        if (graph.viewGeomList.has(hitColor)) {
            let clone = graph.viewGeomList.get(hitColor).clone();

            // 在浮动层突出显示拾取的对象
            clone.setStyle({ "fillColor": "gold", "color": "gold" });
            overLayer.getSource().add(clone);
            return true;
        }
    }
    return false;
}

5.2 几何法

\quad anyGraph 图形基本形状类 Geometry对象提供了 contain(point)方法,各子类均已实现了该方法,通过该方法可判断图形对象与点的位置关系。

\quad 下面这段代码演示了几何法的碰撞检测:

// 逐一与数据层中的对象进行碰撞检测
function _collideCheck(coord) {
    let datas = layer.getSource().getData();
    for (let i = 0, len = datas.length; i < len; i++) {
        if (datas[i].contain([coord[0], coord[1]])) {
            let clone = datas[i].clone();
            clone.setStyle({ "fillColor": "#FF2020", "color": "#FF2020", "lineWidth":4 });
            overLayer.getSource().add(clone);
            return true;
        }
    }
    return false;
}

\quad “图形系统实战开发-进阶篇 第六章 图形交互操作: 拾取” 的内容讲解到这里就结束了,如果觉得对你有帮助有收获,可以关注我们的官方账号,持续关注更多精彩内容。

相关资料

▶ 系列教程及代码资料:https://GraphAnyWhere.com
▶ 图形系统开发实战课程:进阶篇(上)——前言
▶ 图形系统开发实战课程:进阶篇(上)——1.基础知识
▶ 图形系统开发实战课程:进阶篇(上)——2.图形管理类(Graph)
▶ 图形系统开发实战课程:进阶篇(上)——3.图层类(Layer)
▶ 图形系统开发实战课程:进阶篇(上)——4.图形基本形状
▶ 图形系统开发实战课程:进阶篇(上)——5.图形交互操作:平移和缩放


作者信息

作者 : 图形开发学院
CSDN: https://blog.csdn.net/2301_81340430?type=blog
官网:https://graphanywhere.com

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

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

相关文章

Avalonia 初学笔记(2):简单了解与WPF的区别

文章目录 相关链接前言Avalonia相对于WPF的新特性简单介绍ChatGPT推荐Avalonia Demo案例Avalonia 开始使用Avalonia 文件扩展名Avalonia Toolkit 扩展安装修改.net core版本Avalonia对WPF的修改类CSS选择器Style的定义简单代码 数据绑定直接绑定UserControl.DataContext和Desig…

128.乐理基础-五线谱-纯四度、纯五度

内容参考于&#xff1a;三分钟音乐社 上一个内容&#xff1a;127.乐理基础-五线谱-纯一度、纯八度-CSDN博客 上一个内容里练习的答案&#xff1a; 纯四度、纯五度的结论 纯四度例子&#xff1a; 例子1&#xff1a; 例子2&#xff1a; 纯四度两个条件&#xff0c;音数是2.5&a…

HTML好玩代码合集(2)

这一期HTML好玩代码合集是动态烟花文字&#xff0c;是本期里最好玩的一个HTML代码&#xff08;把文字可以改成表白的&#xff09;&#xff0c;先看效果&#xff1a; 这个效果是动态的&#xff0c;那些数字都是有烟花堆积成的&#xff0c;代码在哪里呢&#xff1f; 在这里&…

SpringBoot---集成MybatisPlus

介绍 使用SpringBoot集成MybatisPlus框架。 第一步&#xff1a;添加MybatisPlus依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version> </dependenc…

第一个Qt程序中的秘密

创建第一个程序 首先我们打开Qt Creator 打开文件->New Projects... 菜单&#xff0c;创建我们的第一个Qt项目 选择 Qt Widgets Application&#xff0c;点击选择...按钮 之后&#xff0c;输入项目名称QtLearning&#xff0c;并选择创建路径&#xff0c; 在build system中选…

Linux:gitlab创建组,创建用户,创建项目

创建组和项目 让后可以在组里创建一个个仓库 创建成员 我创建个成员再把他分配进这个组里 进入管理员 密码等会我们创建完用户再去配置密码 Regular是普通的用户&#xff0c;只可以正常去访问指定规则的项目 而下面的administrator就是管理员&#xff0c;可以随便进项目&…

springcloud:2.OpenFeign 详细讲解

OpenFeign 是一个基于 Netflix 的 Feign 库进行扩展的工具,它简化了开发人员在微服务架构中进行服务间通信的流程,使得编写和维护 RESTful API 客户端变得更加简单和高效。作为一种声明式的 HTTP 客户端,OpenFeign 提供了直观的注解驱动方式,使得开发人员可以轻松定义和调用…

【Pytorch深度学习开发实践学习】B站刘二大人课程笔记整理lecture04反向传播

lecture04反向传播 课程网址 Pytorch深度学习实践 部分课件内容&#xff1a; import torchx_data [1.0,2.0,3.0] y_data [2.0,4.0,6.0] w torch.tensor([1.0]) w.requires_grad Truedef forward(x):return x*wdef loss(x,y):y_pred forward(x)return (y_pred-y)**2…

【TCP/IP】组播

一、组播介绍 组播&#xff08;Multicast&#xff09;是网络技术中数据传输的一种方法&#xff0c;它允许将数据包同时发送给一组指定的目标&#xff0c;而不是单个的目标&#xff08;单播 Unicast&#xff09;或所有可能的目标&#xff08;广播 Broadcast&#xff09;。组播传…

WEB甘特图选型

1.火车侠 GitHub - w1301625107/Vue-Gantt-chart: 使用Vue做数据控制的Gantt图表 优点&#xff1a;有小时选项 缺点&#xff1a;不支持拖拽 2.火车侠二号 GitHub - liyang5945/vue-drag-gantt-chart: Vue拖拽甘特图 a draggable gantt-chart with vue 有点&#xff1a;实现了…

盲盒小程序开发,线上盲盒应该具备哪些功能?

盲盒在我国是一个热门行业&#xff0c;它的种类繁多&#xff0c;玩法新奇有趣&#xff0c;吸引了无数年轻人的眼光&#xff0c;发展更是经久不衰&#xff01; 随着科学技术的不断发展&#xff0c;盲盒行业也在继续保持上升趋势&#xff0c;为我国消费者带来了更多的新体验&…

Python假数据生成库之mimesis使用详解

概要 在软件开发和测试过程中,经常需要使用假数据来模拟真实环境,进行测试、演示或者填充数据库。Python Mimesis 库就是一个强大的工具,可以帮助快速、方便地生成各种类型的假数据。本文将深入探讨 Mimesis 库的功能、用法和示例代码,以帮助大家更好地了解如何利用这个库…

Kubernetes部署CNI网络组件

目录 1.概述 K8S的三种网络 VLAN和VXLAN的区别 K8S中Pod网络通信 flannel的三种模式 flannel的UDP模式工作原理 flannel的VXLAN模式工作原理 2.部署flannel 在node01节点上操作 在master01节点上操作 3.部署Calico Calico主要由三个部分组成 calico的IPIP模式工作…

免费搭建个人网盘

免费搭建一个属于个人的网盘。 服务端 详情请参考原网站的服务端下载和安装虚拟磁盘Fuse4Ui可以支持把网盘内容挂载成系统的分区&#xff1b; 挂载工具效果图&#xff1a;应用端应用端的下载 效果图

2024.2.22

将互斥机制的代码实现 #include<myhead.h> int num7; pthread_mutex_t mutex;//创建互斥锁变量 void *task1(void *arg) {printf("task1:\n");//获取锁资源pthread_mutex_lock(&mutex);num77777;sleep(2); printf("task1:num%d\n",num); //释放…

【Linux】日志命令行练习(持续更新)

文章目录 前言环境情景1. 获取实时日志2. 关键字定位3. 关键字取并集4. 关键字取交集5. 关键字取差集6. 关键字实时日志捕获7. 关键词上下文打印8. 关键词滚动搜索9. 看最早的日志信息 前言 公司生产问题需要登录堡垒机排查。 没有日志平台的情况下&#xff0c;生产问题同样要…

【Three.js】前端从零开始学习 threejs:创建第一个 threejs3D 页面

课程和学习大纲 对应的课程在这里&#xff1a;Threejs教程、2023最新最全最详细Threejs教程、零基础Threejs最详细教程&#xff08;已完结&#xff09; 学习知识要点思维导图&#xff1a; 官网和文档的使用 three.js 官网 如果无法访问&#xff0c;可以下载国内大佬的镜像…

在UE5中制作UI环形进度条

在日常开发中&#xff0c;经常会有环形进度条UI的效果&#xff0c;例如技能CD时间、加载动画等&#xff0c;本文将通过材质球节点实现该效果&#xff0c;相较于准备美术素材&#xff0c;这样的做法更为方便&#xff0c;效果如下&#xff1a; 1.制作环状效果材质函数 在内容面…

使用RingAttention处理百万长度视频和语言的世界模型

摘要 2402.08268v1.pdf (arxiv.org) 当前的语言模型在理解不容易用语言描述的世界方面存在不足&#xff0c;并且在处理复杂、长篇的任务时也存在困难。视频序列提供了语言中不存在的有价值的时间信息&#xff0c;使其与语言联合建模变得具有吸引力。这样的模型可以发展出对人…