【问题标题】:Calculating the apparent area of a polygon from a view point从视点计算多边形的视面积
【发布时间】:2020-01-28 11:32:20
【问题描述】:

我想从一个视点计算多边形的视面积。假设您从对面看一个 2 x 2 平方米的正方形,您的视面积为 4 平方米。

现在图像以某种方式旋转了正方形,那么明显的区域会更小。为此,我想我可以使用以下逻辑:

V3_c(多边形的质心)

V3_v(观看者位置)

  1. 用 (V3_c - V3_v).normalize() 的法线构造一个通过 V3_v 的平面
  2. 将多边形投影到这个平面上并计算面积

如何在 CGAL 中做到这一点?

更新:

根据@mgimeno 的建议,我使用了以下(几乎是伪)代码。

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/centroid.h>

#include <iostream>
#include <vector>

#include "print_utils.h"

typedef CGAL::Exact_predicates_inexact_constructions_kernel  Kernel;
typedef CGAL::Polygon_with_holes_2<Kernel>                   Polygon_with_holes_2;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Point_3                                      Point_3;
typedef Kernel::Plane_3 Plane_3;
typedef Kernel::Vector_3 Vector_3;
typedef Kernel::FT ValueType;
using namespace std;

int main(int argc, char* argv[])
{
  Point_3 viewer(0, 0, 0);
  cout << "Viewer: " << viewer << endl;

  Point_3 a(-5, -5, 5);
  Point_3 b(-5, -5, -5);
  Point_3 c(5, -5, -5);
  Point_3 d(5, -5, 5);
  cout << "Surface: " << a << ", " << b << ", " << c << ", " << d << endl;

  std::vector<Point_3> vertices;
  vertices.push_back(a);
  vertices.push_back(b);
  vertices.push_back(c);
  vertices.push_back(d);
  Point_3 center = CGAL::centroid(vertices.begin(), vertices.end(), CGAL::Dimension_tag<0>());
  cout << "Center of surface: " << center << endl;

  Vector_3 normal = center - viewer;
  Plane_3 plane(viewer, normal);
  cout << "Plane passing thorough viewer orthogonal to surface: " << plane << endl;

  Point_3 pa = plane.projection(a);
  Point_3 pb = plane.projection(b);
  Point_3 pc = plane.projection(c);
  Point_3 pd = plane.projection(d);

  cout << "Projected surface onto the plane: " << pa << ", " << pb << ", " << pc << ", " << pd << endl;

  Point_2 pa2 = plane.to_2d(pa);
  Point_2 pb2 = plane.to_2d(pb);
  Point_2 pc2 = plane.to_2d(pc);
  Point_2 pd2 = plane.to_2d(pd);

  cout << "to_2d of the projected plane: " << pa2 << ", " << pb2 << ", " << pc2 << ", " << pd2 << endl;
  std::vector<Point_2> vertices2;
  vertices2.push_back(pa2);
  vertices2.push_back(pb2);
  vertices2.push_back(pc2);
  vertices2.push_back(pd2);

  ValueType result;
  CGAL::area_2(vertices2.begin(), vertices2.end(), result);

  cout << "Area of to_2d'ed vertices: " << result << endl;
  return EXIT_SUCCESS;
}

输出是:

Viewer: 0 0 0
Surface: -5 -5 5, -5 -5 -5, 5 -5 -5, 5 -5 5
Center of surface: 0 -5 0
Plane passing thorough viewer orthogonal to surface: 0 -5 0 0
Projected surface onto the plane: -5 0 5, -5 0 -5, 5 0 -5, 5 0 5
to_2d of the projected plane: -5 1, -5 -1, 5 -1, 5 1
Area of to_2d'ed vertices: 20

我不确定 to_2d 是如何工作的,但肯定不是我希望的那样。计算的面积是 20 而不是实际的 100。

顺便说一句,我也开始意识到这个目标可以通过简单地计算观察方向 (V_c - V_v) 和多边形法线之间的角度来实现。 sin a * original_area 应该给出面积。

【问题讨论】:

    标签: cgal


    【解决方案1】:

    要计算多边形的质心,您可以使用CGAL::centroid()。 然后要构建你的飞机,你可以使用the constructor of Plane_3 that takes a point and a normal。 之后,您可以使用Plane_3::projection() 投影多边形的每个点,然后我建议在这些新点上使用to_2D() 以获得Point_2,并能够使用area_2()

    【讨论】:

    • 非常感谢@mgimeno 的指点。除了 to_2d 之外,所有这些都按预期工作,它扭曲了形状,并且区域与我预期的不同。我已经更新了问题。
    • 确实,平面的基础是不规范的,所以不能使用to_2d()。我的错。相反,我认为您必须对投影多边形进行三角测量并使用squared_area()
    • 我最终通过三角剖分计算了原始多边形的面积(它已经被三角剖分),然后通过三角函数计算投影面积 |Cos(angle_between_viewing_direction_and_surface_normal)|*original_area
    猜你喜欢
    • 2013-11-13
    • 2013-10-24
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 2012-04-07
    • 2020-08-23
    相关资源
    最近更新 更多