📜  两个凸多边形之间的切线

📅  最后修改于: 2021-10-23 08:33:36             🧑  作者: Mango

给定两个凸多边形,我们需要找到这些多边形的上下切线。
如下图所示, T_{RL}  T_{LR}  分别显示上切线和下切线。

切线

例子:

Input : First Polygon  : {(2, 2), (3, 3), (5, 2), (4, 0), (3, 1)} 
        Second Polygon : {(-1, 0), (0, 1), (1, 0), (0, -2)}.
Output : Upper Tangent - line joining (0,1) and (3,3)
         Lower Tangent - line joining (0,-2) and (4,0)

概述:
让我们有两个凸多边形,如图所示,

切线2

为了找到上切线,我们首先取两点。 a 的最右边点和 b 的最左边点。连接它们的线被标记为 1。因为这条线穿过多边形 b(不在多边形 b 上方)所以我们在 b 上逆时针取下一个点,线被标记为 2。现在线在多边形 b 上方, 美好的!但是这条线穿过多边形 a,所以我们顺时针移动到下一个点,在图中标记为 3。这又与多边形 a 相交,因此我们移至第 4 行。这条线与 b 相交,因此我们移至第 5 行。现在这条线没有与任何一点相交。所以这是给定多边形的上切线。
为了找到下切线,我们需要逆向移动通过多边形,即如果线与多边形 b 相交,我们接下来顺时针移动,如果线与多边形 a 相交,则接下来逆时针移动。
上切线算法:

L <- line joining the rightmost point of a
     and leftmost point of b. 
while (L crosses any of the polygons)
{
    while(L crosses b)
        L <- L' : the point on b moves up.
    while(L crosses a)
        L <- L' : the point on a moves up.
}

下切线算法:

L <- line joining the rightmost point of a 
      and leftmost point of b. 
while (L crosses any of the polygons)
{
    while (L crosses b)
       L <- L' : the point on b moves down.
    while (L crosses a)
       L <- L' : the point on a moves down.
}

例子 :

CPP
// C++ program to find upper tangent of two polygons.
#include
using namespace std;
 
// stores the center of polygon (It is made
// global because it is used in compare function)
pair mid;
 
// determines the quadrant of a point
// (used in compare())
int quad(pair p)
{
    if (p.first >= 0 && p.second >= 0)
        return 1;
    if (p.first <= 0 && p.second >= 0)
        return 2;
    if (p.first <= 0 && p.second <= 0)
        return 3;
    return 4;
}
 
// Checks whether the line is crossing the polygon
int orientation(pair a, pair b,
                                 pair c)
{
    int res = (b.second-a.second)*(c.first-b.first) -
              (c.second-b.second)*(b.first-a.first);
 
    if (res == 0)
        return 0;
    if (res > 0)
        return 1;
    return -1;
}
 
// compare function for sorting
bool compare(pair p1, pair q1)
{
    pair p = make_pair(p1.first - mid.first,
                                p1.second - mid.second);
    pair q = make_pair(q1.first - mid.first,
                                q1.second - mid.second);
 
    int one = quad(p);
    int two = quad(q);
 
    if (one != two)
        return (one < two);
    return (p.second*q.first < q.second*p.first);
}
 
// Finds upper tangent of two polygons 'a' and 'b'
// represented as two vectors.
void findUpperTangent(vector > a,
                      vector > b)
{
    // n1 -> number of points in polygon a
    // n2 -> number of points in polygon b
    int n1 = a.size(), n2 = b.size();
 
    // To find a point inside the convex polygon(centroid),
    // we sum up all the coordinates and then divide  by
    // n(number of points). But this would be a floating-point
    // value. So to get rid of this we multiply points
    // initially with n1 and then find the centre and
    // then divided it by n1 again.
    // Similarly we do divide and multiply for n2 (i.e.,
    // elements of b)
 
    // maxa and minb are used to check if polygon a
    // is left of b.
    int maxa = INT_MIN;
    for (int i=0; i rightmost point of a
    int ia = 0, ib = 0;
    for (int i=1; i a[ia].first)
            ia = i;
 
    // ib -> leftmost point of b
    for (int i=1; i 0)
            inda = (inda + 1) % n1;
 
        while (orientation(a[inda], b[indb], b[(n2+indb-1)%n2]) < 0)
        {
            indb = (n2+indb-1)%n2;
            done = 0;
        }
    }
 
    cout << "upper tangent (" << a[inda].first << ","
        << a[inda].second << ") (" << b[indb].first
        << "," << b[indb].second << ")\n";
}
 
// Driver code
int main()
{
    vector > a;
    a.push_back({2, 2});
    a.push_back({3, 1});
    a.push_back({3, 3});
    a.push_back({5, 2});
    a.push_back({4, 0});
 
    vector > b;
    b.push_back({0, 1});
    b.push_back({1, 0});
    b.push_back({0, -2});
    b.push_back({-1, 0});
 
    findUpperTangent(a, b);
 
    return 0;
}


输出:

Upper tangent (0,1) (3,3)

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程。