QT实现凸凹边形等距缩放

news2025/3/15 11:34:13

参考:https://blog.csdn.net/weixin_39383896/article/details/99615371和https://blog.csdn.net/qq_15821883/article/details/117421400
在这里插入图片描述

在这里插入图片描述
代码逻辑思路:
1、获取向量AB、BC的坐标。
2、计算向量AB、BC的长度。
3、根据点乘获取cosθ大小。
4、根据cosθ大小判断夹角为钝角还是锐角。
5、如果小于等于90度,根据缩放距离、夹角和等间距求缩放后的点位置。
6、如果大于90度,根据叉积公式判断多边形为凸边形还是凹变形。
7、判断凸凹边形后,根据缩放距离、夹角和等间距求缩放后的点位置。
实现结果:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

Qt实现代码:

QVector<QPointF> Widget::calcPoint(const QVector<QPointF> &datas, int sec_dis)
{
    QVector<double> x;
    QVector<double> y;

    int number = datas.size();
    if (number < 3)
    {
        return QVector<QPointF>();
    }

    for (int i = 0; i < number; ++i)
    {
        x.append(datas[i].x());
        y.append(datas[i].y());
    }
    QVector<QPointF> points;
    for (int i = 0; i < number; ++i)
    {
        // 向量AB
        double x1 = x[i % number] - x[(i - 1 + number) % number];
        double y1 = y[i % number] - y[(i - 1 + number) % number];

        // 向量BC
        double x2 = x[i % number] - x[(i + 1)% number];
        double y2 = y[i % number] - y[(i + 1)% number];

        // 求线段的长度
        double d1 = sqrt(x1*x1 + y1 * y1);
        double d2 = sqrt(x2*x2 + y2 * y2);

        // 点乘
        double ab = x1 * x2 + y1 * y2;

        // cosθ = A * B / (|A| * |B|)
        double cosA = ab / (d1 * d2);

        // 求sinA
        double sinA;
        if (cosA  > 0) // 表示夹角0-90度 锐角
        {
            sinA = sqrt(1 - cosA * cosA);

            double dv1 = sec_dis / sinA;
            // # 向量V1,V2的坐标
            double v1_x = (dv1 / d1) * x1;
            double v1_y = (dv1 / d1) * y1;
            double v2_x = (dv1 / d2) * x2;
            double v2_y = (dv1 / d2) * y2;

            double PiQi_x = v1_x + v2_x;
            double PiQi_y = v1_y + v2_y;
            double Qi_x = PiQi_x + x[i];
            double Qi_y = PiQi_y + y[i];

            points.append(QPointF(Qi_x, Qi_y));
        }
        else if(cosA < 0) // 钝角  钝角分为外钝角和 内钝角
        {
            // 判断凹凸点(叉积)
            double P1P3_x = x[(i + 1) % number] - x[i];
            double P1P3_y = y[(i + 1) % number] - y[i];
            double P1P2_x = x[i] - x[(i - 1 + number) % number];
            double P1P2_y = y[i] - y[(i - 1 + number) % number];
            double P = (P1P3_y*P1P2_x) - (P1P3_x*P1P2_y);

            // 为凹
            if (P < 0)
            {
                sinA = -sqrt(1 - cosA * cosA);
                double dv1 = sec_dis / sinA;

                double v1_x = (dv1 / d1) * x1;
                double v1_y = (dv1 / d1) * y1;

                double v2_x = (dv1 / d2) * x2;
                double v2_y = (dv1 / d2) * y2;

                double PiQi_x = v1_x + v2_x;
                double PiQi_y = v1_y + v2_y;
                double Qi_x = PiQi_x + x[i];
                double Qi_y = PiQi_y + y[i];

                points.append(QPointF(Qi_x, Qi_y));
            }
            else if (P > 0) // 为凸
            {
                sinA = -sqrt(1 - cosA * cosA);

                double dv1 = -sec_dis / sinA;

                double v1_x = (dv1 / d1) * x1;
                double v1_y = (dv1 / d1) * y1;

                double v2_x = (dv1 / d2) * x2;
                double v2_y = (dv1 / d2) * y2;

                double PiQi_x = v1_x + v2_x;
                double PiQi_y = v1_y + v2_y;
                double Qi_x = PiQi_x + x[i];
                double Qi_y = PiQi_y + y[i];

                points.append(QPointF(Qi_x, Qi_y));
            }
            else // error
            {
                return QVector<QPointF>();
            }
        }
        else if(cosA == 0)
        {
            sinA = 1;
            double dv1 = sec_dis / sinA;

            double v1_x = (dv1 / d1) * x1;
            double v1_y = (dv1 / d1) * y1;

            double v2_x = (dv1 / d2) * x2;
            double v2_y = (dv1 / d2) * y2;

            double PiQi_x = v1_x + v2_x;
            double PiQi_y = v1_y + v2_y;
            double Qi_x = PiQi_x + x[i];
            double Qi_y = PiQi_y + y[i];

            points.append(QPointF(Qi_x, Qi_y));
        }
    }

    return points;
}

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

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

相关文章

LeetCode 高频题目分类列表

&#x1f4a1; LeetCode 高频面试题分类列表&#xff0c;总共24类&#xff0c;312道题目&#xff01; 图 133.克隆图 207.课程表 210.课程表 II 399.除法求值 547.省份数量 684.冗余连接 743.网络延迟时间 785.判断二分图 堆 215.数组中的第K个最大元素 295.数据流的中位数 26…

【性能测试篇1】初识性能测试

目录 性能测试定义 性能测试和功能测试有什么区别 测试工具上面&#xff1a; 特殊业务场景下&#xff1a; 性能测试常见概念&#xff1a; ①用户相关&#xff1a; 1.1并发用户数&#xff1a; 1.2在线用户数&#xff1a; 1.3系统用户数量&#xff1a; ②响应时间相关&…

Golang操作数据库简单示例

目录 准备工作准备数据创建项目连接数据库查询数据修改数据插入数据删除数据释放资源完整代码最终执行结果 准备工作 在开始之前&#xff0c;你需要确保自己安装了Golang的编程环境&#xff0c;安装MySQL数据库&#xff0c;有一个可以用于编写代码的编辑器或IDE工具。我在这里…

大型公共建筑能耗监测与信息管理系统研究及产品选型

摘要&#xff1a;文章通过阐述大型公共建筑能耗现状&#xff0c;突出大型公共建筑实施节能监管的必要性&#xff0c;并在系统总结运用技术手段实施建筑能耗监测的基础上&#xff0c;介绍了江苏省建筑能耗监测系统研究过程中的技术创新和应用情况。 关键词&#xff1a;公共建筑…

深度学习——含并行连接的网络(GoogLeNet)

深度学习——含并行连接的网络&#xff08;GoogLeNet&#xff09; 文章目录 前言一、Inception块二、GoogLeNet模型三、训练模型总结 前言 上篇文章中学习了NIN&#xff0c;而GoogLeNet吸收了NIN中串联网络的思想&#xff0c;并在此基础上做了改进。该论文中的一个观点是&…

PyQt5基础学习(一)

从PyQt5最基础的内容开始学习 import sysfrom PyQt5.QtGui import QIcon from PyQt5.QtWidgets import QWidget, QApplication, QTextBrowserclass Example(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):self.resize(300, 300)self.setWind…

数据结构之单链表的模拟实现

&#x1f495;"你笑的次数越多越好&#xff0c;因为你只有用笑才能不怀恶意地消灭罪恶。"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;数据结构之单链表的模拟实现 MyArrayList /*** Created with IntelliJ IDEA.* Description:* User: 绿字* …

F5.5G落进现实:目标网带来的光之路

数字化与智能化的世界将走向何方&#xff1f;这个问题有着非常复杂的答案&#xff0c;但其中有一个答案已经十分清晰。那就是智能化的下一步&#xff0c;必将走向泛在万兆的世界。 网络是算力联接的底座&#xff0c;是智能演化的基础。纵观每一代数字化升级&#xff0c;都可以发…

2023秋招华为技术岗线上面试经历

2023/10/16 个人情况&#xff1a;博士&#xff0c;预计2024年毕业&#xff0c;参加了2023秋招&#xff0c;华为应聘到3面主管面。 下面按招聘流程顺序&#xff0c;记录我的面试经历。因为想写详细一点的独立文章&#xff0c;所以想来想去还是放到CSDN上。 1. 宣讲会 宣讲会…

kr 第三阶段(一)16 位汇编

为什么要学习 16 位汇编&#xff1f; 16 位汇编包含了大部分 32 位汇编的知识点。有助于在学习内核的两种模式。 实模式&#xff1a;访问真实的物理内存保护模式&#xff1a;访问虚拟内存 有助于提升调试能力&#xff0c;调试命令与 OllyDbg 和 WinDebug 通用。可以学习实现反…

spring boot整合MongoDB 一

MongoDB介绍 应用场景 传统的关系型数据库&#xff08;如MySQL&#xff09;&#xff0c;在数据操作的“三高”需求以及应对Web2.0的网站需求面前&#xff0c;显得力不从心。 解释&#xff1a;“三高”需求&#xff1a; • High performance - 对数据库高并发读写的需求。 • …

制作.a静态库 (封盒)

//云库房间 1.GitHub上创建开源框架项目须包含文件&#xff1a; LICENSE:开源许可证&#xff1b;README.md:仓库说明文件&#xff1b;开源项目&#xff1b;(登录GitHub官网) 2. 云仓储库构建成功(此时云库中没有内容三方框架)&#xff01;&#xff01;&#xff01; 3. 4.5. //…

数仓建设(二)

1) 指标梳理 指标口径的不一致使得数据使用的成本极高&#xff0c;经常出现口径打架、反复核对数据的问题。在数据治理中&#xff0c;我们将需求梳理到的所有指标进行进一步梳理&#xff0c;明确其口径&#xff0c;如果存在两个指标名称相同&#xff0c;但口径不一致&#xff0…

项目管理之生命周期管理

项目生命周期管理矩阵是项目管理中一个重要的概念&#xff0c;它包括了项目从准备到收尾的各个阶段。项目生命周期管理矩阵以四个主要管理阶段为基础&#xff0c;分别为准备阶段、启动阶段、执行阶段和收尾阶段。这四个阶段在项目管理中有着明确的目标和职责&#xff0c;贯穿了…

【LeetCode】35. 搜索插入位置

1 问题 给定一个排序数组和一个目标值&#xff0c;在数组中找到目标值&#xff0c;并返回其索引。如果目标值不存在于数组中&#xff0c;返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 示例 1: 输入: nums [1,3,5,6], target 5 输出: 2 示例…

GPT4 Plugins 插件 WebPilot 生成抖音文案

1. 生成抖音文案 1.1. 准备1篇优秀的抖音文案范例 1.2. Promept公式 你是一个有1000万粉丝的抖音主播&#xff0c; 请模仿下面的抖音脚本文案&#xff0c;重新改与一篇文章改写成2分钟的抖音视频脚本&#xff0c; 要求前一部分是十分有争议性的内容&#xff0c;并且能够引发…

linux进程间通讯--信号量

1.认识信号量 方便理解&#xff1a;信号量就是一个计数器。当它大于0能用&#xff0c;小于等于0&#xff0c;用不了&#xff0c;这个值自己给。 2.特点&#xff1a; 信号量用于进程间同步&#xff0c;若要在进程间传递数据需要结合共享内存。信号量基于操作系统的 PV 操作&am…

GitHub仓库的README文件无法显示图片问题-非域名污染原因

之前上自己仓库就偶然发现图片不显示现象&#xff0c;当时以为是网络问题就没有留意这事。但是一直不显示就有问题了&#xff01;于是网上搜了一遭&#xff0c;看见大家遇到此现象的原因普遍归于DNS污染1而我的问题原来是MarkDown格式&#xff01; 在图片语法前不要加分区语法…

linux部署gitlab

1. 配置yum源&#xff1a; vim /etc/yum.repos.d/gitlab-ce.repo [gitlab-ce] nameGitlab CE Repository baseurlhttps://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el$releasever/ gpgcheck0 enabled1 2. 更新本地缓存 sudo yum install -y gitlab-ce 3. 安装相关依赖 yum …

RT-Thread学习笔记(三):线程管理

线程管理 线程管理相关概念什么是时间片轮转调度器锁线程运行机制线程的五种状态 动态和静态创建线程区别动态和静态创建线程优缺点RT-Thread动态线程管理函数动态创建线程动态删除线程 RT-Thread静态线程管理函数静态创建线程 线程其他操作线程启动线程延时获得当前执行的线程…