如何能找到含有预定点的面部时,我具有嵌入的平面上的平面图形(How can a find a fac

2019-09-17 19:54发布

我有嵌入在一个平面上(平面曲线)的平面图和要搜索其面。 该图未连接,而是由几个连通图,其是未单独adressable的(例如一个子可以被包含在另一个图形的面)我想找到的多边形(面),其包括特定的2D点。 多边形是由曲线图的面形成。 由于面的数量是相当大的,我想,以避免他们决定提前。 什么是这样的搜索,什么C的一般复杂++库/编码方法,我可以用它来完成它。

更新澄清:我指的图形在xy平面这里

Answer 1:

你提出了一个有趣的挑战。 一个相对简单的解决方案是可能的,如果多边形碰巧始终是凸的,因为在这种情况下,一个只需要问的关注点是否位于同一侧面(无论是向左或向右)所有多边形的边。 虽然我知道,一般情况下,没有特别简单的解决方案,下面的代码似乎对任何,任意多边形工作,由柯西著名的积分公式间接启发。

你不需要熟悉柯西跟随代码,代码中的注释说明该技术。

#include <vector>
#include <cstddef>
#include <cstdlib>
#include <cmath>
#include <iostream>

// This program takes its data from the standard input
// stream like this:
//
//      1.2  0.5
//     -0.1 -0.2
//      2.7 -0.3
//      2.5  2.9
//      0.1  2.8
//
// Given such input, the program answers whether the
// point (1.2, 0.5) does not lie within the polygon
// whose vertices, in sequence, are (-0.1, -0.2),
// (2.7, -0.3), (2.5, 2.9) and (0.1, 2.8).  Naturally,
// the program wants at least three vertices, so it
// requires the input of at least eight numbers (where
// the example has four vertices and thus ten numbers).
//
// This code lacks really robust error handling, which
// could however be added without too much trouble.
// Also, its function angle_swept() could be shortened
// at cost to readability; but this is not done here,
// since the function is already hard enough to grasp as
// it stands.
//
//

const double TWOPI = 8.0 * atan2(1.0, 1.0); // two times pi, or 360 deg

namespace {

    struct Point {
        double x;
        double y;
        Point(const double x0 = 0.0, const double y0 = 0.0)
          : x(x0), y(y0) {}
    };

    // As it happens, for the present code's purpose,
    // a Point and a Vector want exactly the same
    // members and operations; thus, make the one a
    // synonym for the other.
    typedef Point Vector;

    std::istream &operator>>(std::istream &ist, Point &point) {
        double x1, y1;
        if(ist >> x1 >> y1) point = Point(x1, y1);
        return ist;
    }

    // Calculate the vector from one point to another.
    Vector operator-(const Point &point2, const Point &point1) {
        return Vector(point2.x - point1.x, point2.y - point1.y);
    }

    // Calculate the dot product of two Vectors.
    // Overload the "*" operator for this purpose.
    double operator*(const Vector &vector1, const Vector &vector2) {
        return vector1.x*vector2.x + vector1.y*vector2.y;
    }

    // Calculate the (two-dimensional) cross product of two Vectors.
    // Overload the "%" operator for this purpose.
    double operator%(const Vector &vector1, const Vector &vector2) {
        return vector1.x*vector2.y - vector1.y*vector2.x;
    }

    // Calculate a Vector's magnitude or length.
    double abs(const Vector &vector) {
        return std::sqrt(vector.x*vector.x + vector.y*vector.y);
    }

    // Normalize a vector to unit length.
    Vector unit(const Vector &vector) {
        const double abs1 = abs(vector);
        return Vector(vector.x/abs1, vector.y/abs1);
    }

    // Imagine standing in the plane at the point of
    // interest, facing toward a vertex.  Then imagine
    // turning to face the next vertex without leaving
    // the point.  Answer this question: through what
    // angle did you just turn, measured in radians?
    double angle_swept(
        const Point &point, const Point &vertex1, const Point &vertex2
    ) {
        const Vector unit1 = unit(vertex1 - point);
        const Vector unit2 = unit(vertex2 - point);
        const double dot_product   = unit1 * unit2;
        const double cross_product = unit1 % unit2;
        // (Here we must be careful.  Either the dot
        // product or the cross product could in theory
        // be used to extract the angle but, in
        // practice, either the one or the other may be
        // numerically problematical.  Use whichever
        // delivers the better accuracy.)
        return (fabs(dot_product) <= fabs(cross_product)) ? (
            (cross_product >= 0.0) ? (
                // The angle lies between 45 and 135 degrees.
                acos(dot_product)
            ) : (
                // The angle lies between -45 and -135 degrees.
                -acos(dot_product)
            )
        ) : (
            (dot_product >= 0.0) ? (
                // The angle lies between -45 and 45 degrees.
                asin(cross_product)
            ) : (
                // The angle lies between 135 and 180 degrees
                // or between -135 and -180 degrees.
                ((cross_product >= 0.0) ? TWOPI/2.0 : -TWOPI/2.0)
                  - asin(cross_product)
            )
        );
    }

}

int main(const int, char **const argv) {

    // Read the x and y coordinates of the point of
    // interest, followed by the x and y coordinates of
    // each vertex in sequence, from std. input.
    // Observe that whether the sequence of vertices
    // runs clockwise or counterclockwise does
    // not matter.
    Point point;
    std::vector<Point> vertex;
    std::cin >> point;
    {
        Point point1;
        while (std::cin >> point1) vertex.push_back(point1);
    }
    if (vertex.size() < 3) {
        std::cerr << argv[0]
          << ": a polygon wants at least three vertices\n";
        std::exit(1);
    }

    // Standing as it were at the point of interest,
    // turn to face each vertex in sequence.  Keep
    // track of the total angle through which you
    // have turned.
    double cumulative_angle_swept = 0.0;
    for (size_t i = 0; i < vertex.size(); ++i) {
        // In an N-sided polygon, vertex N is again
        // vertex 0.  Since j==N is out of range,
        // if i==N-1, then let j=0.  Otherwise,
        // let j=i+1.
        const size_t j = (i+1) % vertex.size();
        cumulative_angle_swept +=
          angle_swept(point, vertex[i], vertex[j]);
    }


    // Judge the point of interest to lie within the
    // polygon if you have turned a complete circuit.
    const bool does_the_point_lie_within_the_polygon =
      fabs(cumulative_angle_swept) >= TWOPI/2.0;

    // Output.
    std::cout
      << "The angle swept by the polygon's vertices about the point\n"
      << "of interest is " << cumulative_angle_swept << " radians ("
      << ((360.0/TWOPI)*cumulative_angle_swept) << " degrees).\n"
      << "Therefore, the point lies "
      << (
        does_the_point_lie_within_the_polygon
          ? "within" : "outside of"
      )
      << " the polygon.\n";

    return !does_the_point_lie_within_the_polygon;

}

当然,上面的代码只是我写的,因为你的挑战很有趣,我想看看我是否能满足它。 如果你的应用是很重要的,那么你应该测试和检查代码,并请修改回到这里您发现任何错误。 我已经测试的代码针对两种或三种情况下,它似乎工作,但重要的职责,将需要更多详尽的测试。

祝你好运与您的应用程序。



文章来源: How can a find a face containing a predefined point when i have a planar graph embedded on a plane