GL绘制自定义线条3_自定义线帽

news2025/1/21 6:23:58

安卓Path搭配Paint可以设置线帽,我想能不能把我自己的线条绘制Demo也加上类似的功能。

线头规则描述:

        1、设一个线宽一半的线段,坐标为(0, 0)到(-lineWidth / 2, 0)。

        2、设步骤1的线段有一垂直于它的向量(0,1),然后传入最近两次触摸坐标,并将第二次触摸坐标减去第一次触摸触摸坐标,得到当前画线的前进方向向量,然后求与(0, 1)向量夹角。

        3、以从步骤2中得到的夹角,到该夹角+180度为止,以一定的角度步进量旋转步骤1的线段,形成一个切合线段的半圆。

        4、最后添加一个(-lineWidth / 2, 0)到(lineWidth / 2, 0)的线段并旋转到步骤3的最终角度,方便和线段本体对接。

线尾规则描述:

        1、只需把线头的规则中的步骤二改为,最后一次的之前一次的触摸坐标 减去 最后一次的触摸坐标作为方向向量即可(和前进方向相反)。

        2、去冗余处理,每前进一次,就把之前添加的线尾半圆顶点删掉。

        关键代码:

        

 /**给线头添加符合线宽的边界,便于和纤体本身链接**/
    private void lineCapAddBorder(double angle, float firstVec[], List<float[]> newVecs) {
        try {
            float rotatedVec0[] = rotate2d(new float[] {-mLineWidth / 2f, 0}, angle + 180);
            float rotatedVec1[] = rotate2d(new float[] {mLineWidth / 2f, 0}, angle + 180);
            float newVec[] = new float[6];
            //偏移到对应位置
            newVec[0] = rotatedVec0[0] + firstVec[0];
            newVec[1] = rotatedVec0[1] + firstVec[1];
            newVec[3] = rotatedVec1[0] + firstVec[0];
            newVec[4] = rotatedVec1[1] + firstVec[1];
            newVecs.add(newVec);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**绘制线头
     * @param isHead 是否曲线头部添加线帽,否则视为曲线尾部添加线帽**/
    private int lineCap(boolean isHead, @NonNull float firstVec[], @NonNull float secVec[], int color) {
        if (null == firstVec) {
            return -1;
        }
        if (mHeadPointBuf == null) {
            mHeadCapPointByteBuffer = ByteBuffer.allocateDirect(mHeadInitVertexCount * 4);    //顶点数 * sizeof(float)
            mHeadCapPointByteBuffer.order(ByteOrder.nativeOrder());
            mHeadPointBuf = mHeadCapPointByteBuffer.asFloatBuffer();
            mHeadPointBuf.position(0);
            mHeadCapPointBufferPos = 0;
        }
        //按初始化大小初始化RGBA字节数组和RGBA数组
        if (mHeadColorBuf == null) {
            mHeadCapColorByteBuffer = ByteBuffer.allocateDirect(mHeadInitColorCount * 4);
            mHeadCapColorByteBuffer.order(ByteOrder.nativeOrder());
            mHeadColorBuf = mHeadCapColorByteBuffer.asFloatBuffer();
            mHeadColorBuf.position(0);
            mHeadCapColorBufferPos = 0;
        }
        /**1、了解线条开始的方向,将半径线条绕旋转该方向与标准测量用向量的夹角的角度量
         * 2、旋转180度时按照一定步进产生多个顶点,todo 但怎么确定旋转的方向是顺时针还是逆时针?以什么为依据判断?以传入向量方向为参考,但具体怎么做?*/
        float initVert[] = new float[] { //初始时左端点的坐标,初始时在原点两侧,然后以传入的顶点作为偏移量
                -mLineWidth / 2f, 0
        };
        //旋转并在过程中产生顶点
        float actualVec[] = new float[3];
        actualVec[0] = secVec[0] - firstVec[0];
        actualVec[1] = secVec[1] - firstVec[1];
        double angle = calcAngleOfVectorsOnXYPanel(mStandardVec, actualVec); //对比基准向量旋转了多少度
        int step = 6; //改成只有90度可以得到一个尖头笔帽
        List<float[]> newVecs = new LinkedList<>();

        if (!isHead) {
            //给曲线结尾加一段和线宽等长的边
            lineCapAddBorder(angle, firstVec, newVecs);
        }

        //半圆线头
        for (double degreeBias = angle; degreeBias <= 180 + angle; degreeBias += step) {
                try {
                float rotatedVec[] = rotate2d(initVert, degreeBias);
                float newVec[] = new float[6];
                //偏移到对应位置
                newVec[0] = rotatedVec[0] + firstVec[0];
                newVec[1] = rotatedVec[1] + firstVec[1];
                newVec[3] += firstVec[0];
                newVec[4] += firstVec[1];
                newVecs.add(newVec);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        if (isHead) {
            //给曲线开头加一段和线宽等长的边
            lineCapAddBorder(angle, firstVec, newVecs);
        }

        for (float[] newVec : newVecs) {
            for (int i = 0; i < newVec.length; i++) {
                checkCapacity();
                mPointBuf.put(mPointBufferPos++, newVec[i]);
            }
            for (int i = 0; i < newVec.length / 3; i++) {
                checkCapacity();
                //写入颜色值r,g,b,a
                float alpha = (float) (((color & 0xFF000000) >> 24) & 0x000000FF) / 255f;
                float blue = (float) ((color & 0x000000FF)) / 255f;
                float green = (float) ((color & 0x0000FF00) >> 8) / 255f;
                float red = (float) ((color & 0x00FF0000) >> 16) / 255f;
                mColorBuf.put(mColorBufferPos++, red);
                mColorBuf.put(mColorBufferPos++, green);
                mColorBuf.put(mColorBufferPos++, blue);
                mColorBuf.put(mColorBufferPos++, alpha);
            }
        }
        return newVecs.size() * newVecs.get(0).length;
    }

最后效果:

旋转步进设定为90度,因此能显示尖头效果:

 设定为15度,则可以形成非常圆润的线头:

以线条方式绘制,即可看到顶点构成如下图:

 基本再现了Android path + paint的大部分线条效果了。

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

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

相关文章

成功的项目管理的关键之一——时间计划

在现实的项目管理中&#xff0c;由于时间管理控制不力&#xff0c;导致项目拖期交付使用而使各相关方蒙受损失的案例屡见不鲜&#xff0c;究其原因&#xff0c;不完善的项目时间计划安排是一个重要的方面。成功的项目管理的关键之一就是成功的时间管理&#xff0c;而成功的时间…

Docker中如何限制容器可用的 CPU

默认情况下容器可以使用的主机 CPU 资源是不受限制的。和内存资源的使用一样&#xff0c;如果不对容器可以使用的 CPU 资源进行限制&#xff0c;一旦发生容器内程序异常使用 CPU 的情况&#xff0c;很可能把整个主机的 CPU 资源耗尽&#xff0c;从而导致更大的灾难。本文将介绍…

FileInputFormat的实现类

FileINputFormat的切片机制 FileInputFormat是MapReduce中用于处理文件输入的基类&#xff0c;它定义了输入文件的切片规则&#xff0c;并提供了默认的切片实现。具体来说&#xff0c;FileInputFormat会根据输入文件的大小和块大小等因素计算出每个切片的起始位置和长度&#…

【机器学习】多元线性回归详解和特征压缩

注意⚠️阅读本文前&#xff0c;你应该需要掌握&#xff1a;机器学习线性回归模型、高等数学微积分部分内容、线性代数矩阵部分内容 前情提要&#xff1a;https://blog.csdn.net/weixin_45434953/article/details/130593910 一、多元线性回归的假设函数 首先我们考虑以下的例…

linux Ubuntu Python 3.10 环境报错与解决方案集合

环境配置参考文章&#xff1a;使用Alpaca-Lora基于LLaMA(7B)二十分钟完成微调 1.报错.nvidia/cublas/lib/libcublas.so.11: undefined symbol: cublasLtHSHMatmulAlgoInit, version libcublasLt.so.11 解决方法&#xff1a; pip uninstall nvidia_cublas_cu112.CUDA版本对应…

Guitar Pro8优秀的自动扒谱软件

对于一些技术娴熟的音乐人来说&#xff0c;不仅需要演奏已有的乐谱&#xff0c;有时还需要从听到的其他音乐中将谱子扒下来。扒谱时可以借助扒谱软件&#xff0c;比如Guitar Pro&#xff0c;就是一款优秀的扒谱软件。下面就和大家分享一下guitar pro能自动扒谱吗&#xff0c;gu…

基于Java+SpringBoot+Vue餐厅点餐管理系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

spring boot与asp.net core区别联系

之前一直使用C#编写网站&#xff0c;最近也在了解学习java&#xff0c;根据目前我了解的和学习到的做一个总结分析&#xff0c;写的不好&#xff0c;大家见谅。 联系 名称javac#DIspringasp.net core、Autofac、UnityAOPspringasp.net coreORMmubatis、HibernateEntityFramew…

【MySQL】MySQL索引之最左前缀优化

文章目录 一、联合索引联合索引执行示例 二、索引的 order by优化MySQL中的排序方式数据准备无索引有索引where子句索引字段顺序不一致order by索引字段顺序不一致索引字段升降序不一致 三、总结 一、联合索引 对主键建立的索引叫做聚簇索引, 对普通字段建立的索引叫做二级索引…

Linux实操篇---常用的基本命令1(跟文件操作相关的命令)

一、常用的基本命令 1.常用的shell命令 Shell可以看作是一个命令解释器&#xff0c;为我们提供了交互式的文本控制台界面。 目前的发行版本&#xff1a;在bin/sh 最早的版本Unix&#xff1a;Bourne shell—>Bourne Again Shell 取了 B A Sh。因此目前Linux的发行版大多数…

PieCloudDB Database 与多家基础架构软件厂商完成产品兼容性认证

数据库作为数字经济建设的重要基础&#xff0c;扮演着产业数字化和数据价值释放的基石角色。然而&#xff0c;数据库的发展不能仅仅依赖于自身的技术和创新&#xff0c;也需要建立一个良好的生态系统&#xff0c;与各方合作共同推进数据库技术的进步与创新。 拓数派&#xff08…

港联证券|受两大消息刺激,美最大太阳能公司股价创十年最大日涨幅

因两大利好消息&#xff0c;美国第一太阳能公司&#xff08;FirstSolar&#xff0c;下称第一太阳能&#xff09;股价大涨。 5月12日&#xff0c;第一太阳能宣布&#xff0c;拟最高支付8000万美元收购瑞典钙钛矿企业Evolar AB。其中包括交易完成时支付3800万美元&#xff0c;以及…

SpringSecurity-从入门到精通学习笔记

SpringSecurity从入门到精通 课程介绍 0. 简介 ​ Spring Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro&#xff0c;它提供了更丰富的功能&#xff0c;社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。…

基于qt5的应用程序在windows和linux环境下修改图标及制定后缀关联

基于qt5的应用程序在windows和linux环境下修改图标及制定后缀关联 1、windows 1.1 修改应用程序图标 方式一&#xff1a; 使用qmake来生成makefile文件&#xff0c;只需要在.pro中添加&#xff1a; RC_ICONS logo.ico 然后&#xff0c;重新生成makefile文件和应用程序&…

MySQL学习---15、流程控制、游标

1、流程控制 解决复杂问题不可能是通过一个SQL语句完成&#xff0c;我们需要执行多个SQL操作。流程控制语句的作用就是控制存储过程中SQL语句的执行顺序&#xff0c;是我们完成复杂操作必不可少的一部分。只要是执行的程序&#xff0c;流程就分为三大类&#xff1a; 1、顺序结…

MMM(Master-Master replication manager for MySQL)

MMM&#xff08;Master-Master replication manager for MySQL&#xff0c;MySQL主主复制管理器&#xff09; 是一套支持双主故障切换和双主日常管理的脚本程序。MMM 使用 Perl 语言开发&#xff0c;主要用来监控和管理 MySQL Master-Master &#xff08;双主&#xff09;复制&…

【计算机视觉】CLIP:连接文本和图像(关于CLIP的一些补充说明)

文章目录 一、前言二、背景及相关工作三、方法3.1 Costly datasets3.2 Narrow3.3 Poor real-world performance 四、要点4.1 CLIP is highly efficient4.2 CLIP is flexible and general 五、限制六、更广泛的影响七、结论 一、前言 我们推出了一个名为CLIP的神经网络&#xf…

原神服务端搭建架设教程win系统(附客户端+服务端+环境配置)

原神服务端搭建架设教程win系统(附客户端服务端环境配置) 大家好&#xff0c;我是艾西原神一款开放世界冒险3D游戏以七种元素&#xff08;分别为风、雷、岩、火、水、草、冰&#xff09;交汇的幻想世界“提瓦特”创造的游戏世界&#xff0c;以角色扮演的RPG游戏还是有非常多的玩…

Prompt工程师指南[应用篇]:Prompt应用、ChatGPT|Midjouney Prompt Engineering

Prompt工程师指南[应用篇]&#xff1a;Prompt应用、ChatGPT|Midjouney Prompt Engineering 1.ChatGPT Prompt Engineering 主题&#xff1a; 与 ChatGPT 对话 Python 笔记本 Topics: ChatGPT介绍审查对话任务与ChatGPT对话Python笔记本 ChatGPT介绍 ChatGPT是OpenAI训练的…

(数字图像处理MATLAB+Python)第七章图像锐化-第三节:高斯滤波与边缘检测

文章目录 一&#xff1a;高斯函数&#xff08;1&#xff09;定义&#xff08;2&#xff09;特点 二&#xff1a;LOG算子&#xff08;1&#xff09;定义&#xff08;2&#xff09;程序 三&#xff1a;Canny算子&#xff08;1&#xff09;最优边缘检测&#xff08;2&#xff09;C…