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 (p0 >= 0 && p1 >= 0)

return 1;

if (p0 <= 0 && p1 >= 0)

return 2;

if (p0 <= 0 && p1 <= 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 = (b1 - a1) * (c0 - b0) -

(c1 - b1) * (b0 - a0);

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 = {p10 - mid0, p11 - mid1};

vector<int> q = {q10 - mid0, q11 - mid1};

int one = quad(p);

int two = quad(q);

if (one != two)

return (one < two);

return (p1 * q0 < q1 * p0);

}

// 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++) {

mid0 += polygoni0;

mid1 += polygoni1;

polygoni0 *= n;

polygoni1 *= n;

}

// Sort points based on their angle from the center

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

mid(vector<int> p1, vector<int> p2) {

return compare(p1, p2, mid);

});

// Divide back to original coordinates

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

polygoni0 /= n;

polygoni1 /= n;

}

return polygon;

}

// Finds the upper tangent between two convex polygons a and b

// Returns two points forming the upper tangent

vector<vector<int>> findUpperTangent(vector<vector<int>> a,

vector<vector<int>> 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, p0);

int minb = INT_MAX;

for (auto& p : b)

minb = min(minb, p0);

// 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 (ai0 > aia0)

ia = i;

// Find the leftmost point in b

for (int i = 1; i < n2; i++)

if (bi0 < bib0)

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(bindb, ainda, a(inda + 1) % n1) > 0)

inda = (inda + 1) % n1;

// Move to previous point in b if necessary

while (orientation(ainda, bindb,

b(n2 + indb - 1) % n2) < 0) {

indb = (n2 + indb - 1) % n2;

done = false;

}

}

// Return the points forming the upper tangent

return {ainda, bindb};

}

// Main driver code

int main() {

vector<vector<int>> a = {{2, 2}, {3, 1}, {3, 3}, {5, 2}, {4, 0}};

vector<vector<int>> b = {{0, 1}, {1, 0}, {0, -2}, {-1, 0}};

vector<vector<int>> tangent = findUpperTangent(a, b);

for(auto it:tangent){

cout<<it0<<" "<<it1<<"\n";

}

return 0;

}
输出
上切线 (0,1) (3,3)

时间复杂度: O(n1 log (n1) + n2 log(n2))

辅助空间: O(1)

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

相关推荐
复杂网络1 小时前
Stable Diffusion 视觉大模型微调技术深度调研
算法
复杂网络1 小时前
基于 Stable Diffusion 架构的视觉大模型代表性工作与原理深度解析
算法
MrZhao4001 小时前
Agent Loop 如何用 Hook 扩展:权限、日志与工具拦截
算法
MrZhao4001 小时前
Agent 为什么需要 Skills:别把所有知识都塞进 system prompt
算法
JieE2121 天前
LeetCode 101. 对称二叉树|JS 递归 + 迭代双解法,彻底搞懂镜像判断
javascript·算法
JieE2122 天前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
Jack203 天前
HarmonyOS开发中错误处理策略:网络异常统一处理
算法
小小杨树3 天前
读懂色彩:拍照调色不再难
算法·计算机视觉·配色
JieE2123 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2124 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法