C/C++ 两个凸多边形之间的切线(Tangents between two Convex Polygons)

给定两个凸多边形,我们的目标是确定连接它们的下切线和上切线。

如下图所示,T RLT LR分别代表上切线和下切线。

如果您喜欢此文章,请收藏、点赞、评论,谢谢,祝您快乐每一天。

例子:

输入: 第一个多边形:[[2, 2], [3, 3], [5, 2], [4, 0], [3, 1]]

第二个多边形:[[-1, 0], [0, 1], [1, 0], [0, -2]].
输出: 上切线 - 连接 (0,1) 和 (3,3) 的线

下切线 - 连接 (0,-2) 和 (4,0) 的线
****解释:****该图像清晰地显示了连接两个多边形的结构和切线

方法:

为了找到上切线,我们首先选择两个点:多边形a的最右边的点和多边形 b 的最左边的点。连接这两点的线标记为线 1 。由于这条线穿过多边形b (即,它没有完全位于其上方),我们沿逆时针方向移动到b 上的下一个点,形成线 2 。这条线现在位于多边形b 上方,这很好。但是,它与多边形a 相交,因此我们沿顺时针方向移动到a 上的下一个点,创建线 3线 3 仍然与多边形a 相交,促使再次移动到线 4 。然而,线 4与多边形 b 相交,因此我们继续到线 5 。最后,线 5不与任何一个多边形相交,使其成为给定多边形的正确上切线。

为了找到下切线,我们需要反向移动多边形,即,如果直线穿过多边形 b,则我们接下来顺时针移动,如果直线穿过多边形 a,则我们接下来逆时针移动。

上切线算法:

L 连接 a 最右边点和 b 最左边点的线。while (L 穿过任意多边形) { while(L 穿过 b) L L' : b 上的点向上移动。while(L 穿过 a) L L' : a 上的点向上移动。}

下切线算法:

L 连接 a 最右边点和 b 最左边点的线。 while (L 穿过任意多边形) { while (L 穿过 b) L L' : b 上的点向下移动。 while (L 穿过 a) L L' : a 上的点向下移动。 }

注意,上面的代码只计算了上切线。类似的方法也可以用来计算下切线。

示例代码:

#include <bits/stdc++.h>

using namespace std;

// Determines the quadrant of a point relative to origin

int quad(vector<int> p) {

if (p[0] >= 0 && p[1] >= 0)

return 1;

if (p[0] <= 0 && p[1] >= 0)

return 2;

if (p[0] <= 0 && p[1] <= 0)

return 3;

return 4;

}

// Returns the orientation of ordered triplet (a, b, c)

// 0 -> Collinear, 1 -> Clockwise, -1 -> Counterclockwise

int orientation(vector<int> a, vector<int> b, vector<int> c) {

int res = (b[1] - a[1]) * (c[0] - b[0]) -

(c[1] - b[1]) * (b[0] - a[0]);

if (res == 0)

return 0;

if (res > 0)

return 1;

return -1;

}

// Compare function to sort points counter-clockwise around center

bool compare(vector<int> p1, vector<int> q1, vector<int> mid) {

vector<int> p = {p1[0] - mid[0], p1[1] - mid[1]};

vector<int> q = {q1[0] - mid[0], q1[1] - mid[1]};

int one = quad(p);

int two = quad(q);

if (one != two)

return (one < two);

return (p[1] * q[0] < q[1] * p[0]);

}

// Sorts the polygon points counter-clockwise

vector<vector<int>> sortPoints(vector<vector<int>> polygon) {

vector<int> mid = {0, 0};

int n = polygon.size();

// Calculate center (centroid) of the polygon

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

mid[0] += polygon[i][0];

mid[1] += polygon[i][1];

polygon[i][0] *= n;

polygon[i][1] *= n;

}

// Sort points based on their angle from the center

sort(polygon.begin(), polygon.end(),

mid\](vector\ p1, vector\ p2) { return compare(p1, p2, mid); }); // Divide back to original coordinates for (int i = 0; i \< n; i++) { polygon\[i\]\[0\] /= n; polygon\[i\]\[1\] /= n; } return polygon; } // Finds the upper tangent between two convex polygons a and b // Returns two points forming the upper tangent vector\\> findUpperTangent(vector\\> a, vector\\> b) { int n1 = a.size(), n2 = b.size(); // Find the rightmost point of polygon a and leftmost point of polygon b int maxa = INT_MIN; for (auto\& p : a) maxa = max(maxa, p\[0\]); int minb = INT_MAX; for (auto\& p : b) minb = min(minb, p\[0\]); // Sort both polygons counter-clockwise a = sortPoints(a); b = sortPoints(b); // Ensure polygon a is to the left of polygon b if (minb \< maxa) swap(a, b); n1 = a.size(); n2 = b.size(); // Find the rightmost point in a int ia = 0, ib = 0; for (int i = 1; i \< n1; i++) if (a\[i\]\[0\] \> a\[ia\]\[0\]) ia = i; // Find the leftmost point in b for (int i = 1; i \< n2; i++) if (b\[i\]\[0\] \< b\[ib\]\[0\]) ib = i; // Initialize starting points int inda = ia, indb = ib; bool done = false; // Find upper tangent using orientation checks while (!done) { done = true; // Move to next point in a if necessary while (orientation(b\[indb\], a\[inda\], a\[(inda + 1) % n1\]) \> 0) inda = (inda + 1) % n1; // Move to previous point in b if necessary while (orientation(a\[inda\], b\[indb\], b\[(n2 + indb - 1) % n2\]) \< 0) { indb = (n2 + indb - 1) % n2; done = false; } } // Return the points forming the upper tangent return {a\[inda\], b\[indb\]}; } // Main driver code int main() { vector\\> a = {{2, 2}, {3, 1}, {3, 3}, {5, 2}, {4, 0}}; vector\\> b = {{0, 1}, {1, 0}, {0, -2}, {-1, 0}}; vector\\> tangent = findUpperTangent(a, b); for(auto it:tangent){ cout\<\

相关推荐
lclin_20207 分钟前
大恒Galaxy SDK MFC开发(1):枚举、打开、开始_停止采集基础流程(无画面版)
c++·机器视觉·工业相机·大恒相机·galaxysdk
itman30112 分钟前
C语言printf输出格式:%d %f %s等用法详解
c语言·字符串·printf·格式化输出·整数
初圣魔门首席弟子16 分钟前
bug20260415
c++·bug
luoganttcc22 分钟前
CUDA grid/block 到矩阵映射示例(矩阵加法)
人工智能·算法·机器学习
我不是懒洋洋24 分钟前
【经典题目】链表OJ(相交链表、环形链表、环形链表II、随机链表的复制)
c语言·开发语言·数据结构·链表·ecmascript·visual studio
YuanDaima204828 分钟前
Python 数据结构与语法速查笔记
开发语言·数据结构·人工智能·python·算法
m0_7167652340 分钟前
数据结构--循环链表、双向链表的插入、删除、查找详解
开发语言·数据结构·c++·学习·链表·青少年编程·visual studio
聆风吟º41 分钟前
【C标准库】深入理解C语言strstr函数:子字符串查找的实用指南
c语言·开发语言·库函数·strstr
XY_墨莲伊41 分钟前
【编译原理】实验一:基于正则文法的词法分析器设计与实现
开发语言·数据结构·算法
剑挑星河月1 小时前
394.字符串解码
数据结构·算法·leetcode