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)

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

相关推荐
weixin_468466851 分钟前
支持向量机新手实战指南
人工智能·python·算法·机器学习·支持向量机
Lumbrologist10 分钟前
【C++】零基础入门 · 第 12 节:模板与 STL 入门
开发语言·c++
weixin_468466851 小时前
机器学习之决策树新手实战指南
人工智能·python·算法·决策树·机器学习·ai
wanghu20241 小时前
ABC460_E题题解
c++·算法
z200509301 小时前
今日算法(回溯子集)
数据结构·算法·leetcode
Hesionberger1 小时前
巧用异或找出唯一数字(多解)
java·数据结构·python·算法·leetcode
小何code1 小时前
C语言【初阶】第1节,初识C语言
c语言·开发语言
莫陌尛.1 小时前
Fuzzy C-Mean Clustering (FCM)
c语言·开发语言
变量未定义~1 小时前
阶乘的约数和、斐波那契数列、数列区间最大值(ST表)
数据结构·算法
智者知已应修善业1 小时前
【51单片机象棋快棋赛 电子裁判器】2023-12-27
c++·经验分享·笔记·算法·51单片机