通过图形学实现在凸多边形内生成覆盖路径

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
TODO:写完再整理

文章目录

  • 系列文章目录
  • 前言
  • 通过图形学实现在凸多边形内生成覆盖路径
    • 核心原理
    • 代码实现


前言

认知有限,望大家多多包涵,有什么问题也希望能够与大家多交流,共同成长!

本文先对通过图形学实现在凸多边形内生成覆盖路径做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章


提示:以下是本篇文章正文内容

通过图形学实现在凸多边形内生成覆盖路径

核心原理

1、先对复杂的障碍物和地图进行精确单元分解(梯形单元分解,牛耕单元分解),得到凸多边形cell
2、在凸多边形cell中,使用图形学计算的方法,依次生成覆盖式路径

生成覆盖式路径的步骤:
(1)先寻找凸多边形cell中最长的一条边,并判断覆盖方向式往该最长边的上方还是下方
(2)根据覆盖式路径的间距,依次计算最长边所在的直线,该直线与凸多边形cell相交的部分就是覆盖式路径,把当前覆盖式路径设置为最长边
(3)重复步骤二,直到凸多边形cell的所有顶点都在最长边所在的直线的一侧,结束覆盖路径规划

代码实现

from helpers.geometry import *
import math
import matplotlib.pyplot as plt
# return list of points
def sweep(vertexes):WIDTH = 2 #覆盖路径的宽度edges = []# 凸多边形cell的边maxLength = -1maxIndex = -1for i in range(len(vertexes)):point0 = vertexes[i]point1 = vertexes[(i + 1) % len(vertexes)]edges.append(Line.getLineFromTwoPoints(point0, point1))if edges[i].length() > maxLength:maxLength = edges[i].length()maxIndex = ilongestEdge = edges.pop(maxIndex)# 计算凸多边形cell的最长的边longestEdge.setToInfinite()intersections = []# intersections.append(vertexes[maxIndex])# intersections.append(vertexes[(maxIndex + 1) % len(vertexes)])# 计算覆盖路径的间距及方向direct = 0for vertex in vertexes:if longestEdge.relativePosition(vertex) != 0:direct = longestEdge.relativePosition(vertex)breakWIDTH = WIDTH * direct#当遍历凸多边形cell的所有顶点是否都在当前最长的覆盖线段的一边时,代表覆盖路径生成完毕while not longestEdge.allOnOneSide(vertexes):newIntersect = []for edge in edges:inter = longestEdge.getIntersection(edge)#计算交线,该交线就是中间的覆盖路径if inter is not None:newIntersect.append(inter)intersections.extend(newIntersect)longestEdge = longestEdge.shift(WIDTH)# 不断根据算覆盖路径的间距及方向进行直线偏移for i in intersections:print(i)reorderIntersections(edges, intersections)print("-----------------------")for i in intersections:print(i)return intersectionsdef reorderIntersections(edges, intersections):interCount = []for i in range(len(edges)):interCount.append(0)for inter in intersections:for i in range(len(edges)):if edges[i].relativePosition(inter) == 0:interCount[i] = interCount[i] + 1breakmajorEdge = Nonefor i in range(len(interCount)):if interCount[i] == len(intersections) / 2:majorEdge = edges[i]breakdirect = 1i = 0# direct == 1, intersection on major edge at the front# direct == -1, intersection on major edge at the backwhile i < len(intersections):if direct == 1 & majorEdge.relativePosition(intersections[i]) != 0:temp = intersections[i]intersections[i] = intersections[i + 1]intersections[i + 1] = tempelif direct == -1 & majorEdge.relativePosition(intersections[i + 1]) != 0:temp = intersections[i]intersections[i] = intersections[i + 1]intersections[i + 1] = tempdirect = 0 - directi = i + 2class Line:def __init__(self, vertical, x, k = -1, b = -1, minX = -1, minY = -1, maxX = -1, maxY = -1):self.vertical = verticalself.x = xself.k = kself.b = bself.minX = minXself.minY = minYself.maxX = maxXself.maxY = maxYdef equals(self, line1):if self.vertical & line1.vertical:return self.x == line1.xelif self.vertical | line1.vertical:return Falseelse:return self.k == line1.k & self.b == line1.b@staticmethoddef getLineFromTwoPoints(point1, point2):x1 = point1.xy1 = point1.yx2 = point2.xy2 = point2.yif x1 == x2:return Line(True, x1, -1, -1, min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))else:k = (y1 - y2) / (x1 - x2)b = (x1 * y2 - x2 * y1) / (x1 - x2)return Line(False, -1, k, b, min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))# a infinite line call this function to intersect with finite linedef getIntersection(self, line2):k1 = self.kb1 = self.bk2 = line2.kb2 = line2.bif self.vertical & line2.vertical:return Noneelif self.vertical | line2.vertical:if self.vertical:x = self.xy = round(line2.k * x + line2.b, 2)else:x = line2.xy = round(self.k * x + self.b, 2)else:if k1 == k2: return Nonex = round((b2 - b1) / (k1 - k2), 2)y = round((b2 * k1 - b1 * k2) / (k1 - k2), 2)if (x >= line2.minX) & (x <= line2.maxX) & (y >= line2.minY) & (y <= line2.maxY):return point(x, y)else:return None# return 1 if point is above the line# -1 if point is below the line# 0 if point is on the linedef relativePosition(self, point0):if self.vertical:if point0.x > self.x: return 1elif point0.x < self.x: return -1else: return 0else:yOfLine = round(self.k * point0.x + self.b, 2)yOfPoint = point0.yif yOfPoint > yOfLine: return 1elif yOfPoint < yOfLine: return -1else: return 0def allOnOneSide(self, listOfPoints):position0 = self.relativePosition(listOfPoints[0])for i in range(1, len(listOfPoints)):if(self.relativePosition(listOfPoints[i]) != position0):return Falsereturn True# return a new Line# width > 0, shift up or right# width < 0, shift down or leftdef shift(self, width):if self.vertical:return Line(True, self.x + width)else:delta = math.sqrt(1 + self.k * self.k) * widthnewB = self.b + deltareturn Line(False, -1, self.k, newB)def length(self):if self.minX == -1 & self.minY == -1 & self.maxX == -1 & self.maxY == -1:return -1else:return math.sqrt((self.maxX - self.minX) ** 2 + (self.maxY - self.minY) ** 2)def setToInfinite(self):self.minX = -1self.minY = -1self.maxX = -1self.maxY = -1def getLine():
# 输出一个凸多边形cellpoint0 = point(3, 2)point1 = point(9, 8)point2 = point(2, 9)
#     point3 = point(1, 8)p_list = []p_list.append(point0)p_list.append(point1)p_list.append(point2)
#     list.append(point3)# 可视化该凸多边形cellx_bndy = [pnt.x for pnt in p_list]y_bndy = [pnt.y for pnt in p_list]x_bndy.append(x_bndy[0])y_bndy.append(y_bndy[0])plt.plot(x_bndy, y_bndy)# 在凸多边形cell内部生成覆盖路径pnts = sweep(p_list)# 可视化覆盖路径x = [pnt.x for pnt in pnts]y = [pnt.y for pnt in pnts]plt.plot(x, y)getLine()#从一个凸多边形cell中生成等距的覆盖式路径

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

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

相关文章

go 安装依赖超时

一、配置代理 go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.io,direct go get github.com/unidoc/unioffice

对象关系映射ORM

目录 ORM【重要】 1、 什么是ORM 2、 实体类 3、 ORM改造登录案例 ORM【重要】 1、 什么是ORM 目前使用JDBC完成了CRUD,但是现在是进行CRUD,增删改方法要设计很多参数,查询的方法需要设计集合才能返回. 在实际开发中,我们需要将零散的数据封装到对象处理. ORM (Object Rela…

十九、石英晶体振荡电路

石英晶体振荡电路 1、石英晶体的特点、等效电路、特性曲线; 2、石英晶体振动器的特点&#xff0c; 3、石英晶体振动器的振荡频率

软考(中级-软件设计师)计算机系统篇(0921)

六、计算机系统组成&#xff08;五大部件&#xff09; &#xff08;冯.诺依曼) 冯.诺依曼计算机的特点&#xff1a; 计算机有五大部件组成&#xff1a;输入设别&#xff0c;输出设备&#xff0c;控制器&#xff0c;运算器&#xff0c;存储器;指令和疏忽都以同等地位存于存储器…

为什么年轻人都热衷找搭子,而不是找对象?

在繁华的都市中&#xff0c;有一个名叫晓悦的年轻人。晓悦每天穿梭于忙碌的工作和快节奏的生活之间&#xff0c;渐渐地&#xff0c;她发现身边的朋友们都开始找起了 “搭子”。 有一天&#xff0c;晓悦结束了一天疲惫的工作&#xff0c;坐在咖啡店里&#xff0c;看着窗外匆匆而…

为写论文头疼?推荐4款ai写毕业论文初稿的软件

写论文对于许多学生来说是一项既重要又具挑战性的任务。为了帮助大家更高效地完成这一过程&#xff0c;我将推荐四款优秀的AI写毕业论文初稿的软件&#xff0c;并详细介绍它们的功能和优势。 传送门&#xff1a;https://www.aipaperpass.com?piclLGw 千笔-AIPassPaper是一款功…

面向对象例题之例题的特性

答案&#xff1a;C 解析&#xff1a;对象里面的方法和属性数量是不确定的&#xff0c;可以不断扩展写多个属性和方法 清洗的边界是对象必备的&#xff0c;哪些是这个类的&#xff0c;哪些是其他类的都有体现。 良好的定义行为一般指定义良好的属性和方法 可扩展性指的是子类…

【问题随记】在使用 AuthenticationManager 的时候,出现循环依赖问题 —— `java.lang.StackOverflowError`

问题随记 在使用 AuthenticationManager 的时候&#xff0c;出现循环依赖问题 —— java.lang.StackOverflowError&#xff0c;查资料查了两天半&#xff0c;终于找到原因。 2024-06-16T17:54:19.48708:00 ERROR 20672 --- [nio-8789-exec-1] o.a.c.c.C.[.[.[/].[dispatcherS…

波分技术基础 -- FEC

信号在传输过程中&#xff0c;不可避免的会出现劣化、误码&#xff0c;FEC (Forward error correction) 技术确保通信系统在噪声和其他损伤的影响下&#xff0c;依然能够实现无错误传输。 应用场景&#xff1a;长途密集波分系统&#xff08;DWDM&#xff09;实现方式&#xff…

LED显示屏迎来革新:GOB封装技术引领行业新风尚

在我们日常生活中&#xff0c;LED显示屏无处不在&#xff0c;从繁华的街头广告牌到家庭娱乐中心的大屏幕电视&#xff0c;它们都以鲜明的色彩和清晰的画质吸引着我们的目光。然而&#xff0c;在LED显示屏技术日新月异的今天&#xff0c;一种名为GOB&#xff08;Glue On Board&a…

python:给1个整数,你怎么判断是否等于2的幂次方?

最近在csdn上刷到一个比较简单的题目&#xff0c;题目要求不使用循环和递归来实现检查1个整数是否等于2的幂次方&#xff0c;题目如下&#xff1a; 题目的答案如下&#xff1a; def isPowerofTwo(n):z bin(n)[2:]print(bin(n))if z[0] ! 1:return Falsefor i in z[1:]:if i !…

华为全联接大会HUAWEI Connect 2024印象(二):昇腾AI端侧推理

此次参加HUAWEI Connect 2024最主要目标是了解昇腾AI端侧推理技术&#xff0c;希望将其融合到我现在嵌入式系统课程中&#xff0c;不过刚开始在一楼找到一个小展台&#xff0c;看到了香橙派Orange Pi。香橙派是深圳迅龙的一个品牌&#xff0c;他们和很多芯片厂商都合作过&#…

IPsec-VPN中文解释

网络括谱图 IPSec-VPN 配置思路 1 配置IP地址 FWA:IP地址的配置 [FW1000-A]interface GigabitEthernet 1/0/0 [FW1000-A-GigabitEthernet1/0/0]ip address 10.1.1.1 24 //配置IP地址 [FW1000-A]interface GigabitEthernet 1/0/2 [FW1000-A-GigabitEthernet1/0/2]ip a…

计算机毕业设计 基于Python的美术馆预约系统的设计与实现 Python+Django+Vue 前后端分离 附源码 讲解 文档

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

【笔记】第三节 组织与性能

3.1 基本成分 3.2 微观组织特征 0.6-0.8C%碳素钢的组织为珠光体和少量的铁素体。 如何把组织和性能联系起来&#xff1f;德国克虏伯公司的研究——珠光体片间距与渗碳体片层厚度成比例&#xff1a; t s 0 ( ρ 15 ( C % ) − 1 ) ts_0(\frac{\rho}{15(C\%)}-1) ts0​(15(C%)…

【Web】PolarCTF2024秋季个人挑战赛wp

EZ_Host 一眼丁真命令注入 payload: ?host127.0.0.1;catf* 序列一下 exp: <?phpclass Polar{public $lt;public $b; } $pnew Polar(); $p->lt"system"; $p->b"tac /f*"; echo serialize($p);payload: xO:5:"Polar":2:{s:2:"…

我的AI工具箱Tauri版-VideoDuplication视频素材去重

本教程基于自研的AI工具箱Tauri版进行VideoDuplication视频素材去重。 该项目是基于自研的AI工具箱Tauri版的视频素材去重工具&#xff0c;用于高效地处理和去除重复视频内容。用户可以通过搜索关键词"去重"或通过路径导航到"Python音频技术/视频tools"模…

MySQL高阶1907-按分类统计薪水

目录 题目 准备数据 分析数据 总结 题目 结果表 必须 包含所有三个类别。 如果某个类别中没有帐户&#xff0c;则报告 0 。 按 任意顺序 返回结果表。 查询每个工资类别的银行账户数量。 工资类别如下&#xff1a; "Low Salary"&#xff1a;所有工资 严格低于…

MQ入门(4)

Erlang&#xff1a;面向高并发的 单机的吞吐量就是并发性&#xff1a;Rabbitmq是10w左右&#xff08;现实项目中已经足够用了&#xff09;&#xff0c;RocketMQ是10w到20w&#xff0c;Kafka是100w左右。 公司里的并发&#xff08;QPS&#xff09; 大部分的公司每天的QPS大概…

自动化测试框架设计详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、引言 随着IT技术的快速发展&#xff0c;软件开发变得越来越快速和复杂化。在这种背景下&#xff0c;传统的手工测试方式已经无法满足测试需求&#xff0c;而自…