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\<\

相关推荐
会周易的程序员14 小时前
aiDgeScanner 工业设备网络扫描与管理工具
网络·c++·物联网·架构·electron·node.js·iot
叼烟扛炮14 小时前
C++ 知识点17 友元
开发语言·c++·算法·友员
计算机安禾15 小时前
【c++面向对象编程】第2篇:类与对象(一):定义第一个类——成员变量与成员函数
开发语言·c++
richard_yuu15 小时前
数据结构|二叉树高阶进阶-经典算法
数据结构·c++·算法
不知名的忻15 小时前
Dijkstra算法(朴素版&堆优化版)
java·数据结构·算法··dijkstra算法
兩尛15 小时前
c++知识点5
开发语言·c++
澈20715 小时前
C++内存管理:new/delete与内存泄漏实战
开发语言·c++·内存分区
星星码️15 小时前
LeetCode刷题简单篇之反转字母
c++·算法·leetcode
其实防守也摸鱼15 小时前
VS code怎么使用 Conda 安装预编译包
开发语言·网络·c++·vscode·安全·web安全·conda
Hello.Reader15 小时前
ds4.c 深度解析为 DeepSeek V4 Flash 打造的本地推理引擎
c语言·开发语言