Engin
Engin

Reputation: 166

Calculating the apparent area of a polygon from a view point

I want to calculate the apparent area of a polygon from a view point. Say, you are looking at a 2 x 2 meters square from across, the apparent area for you would be 4 m2.

Now image the square is rotated somehow, then the apparent area would be smaller. To do this, I figured I could use the following logic:

V3_c (center of mass of the polygon)

V3_v (viewer's position)

  1. Construct a plane that goes through V3_v with the normal of (V3_c - V3_v).normalize()
  2. Project the polygon onto this plane and calculate the area

How can I do this in CGAL?

enter image description here

enter image description here

UPDATE:

Upon @mgimeno's suggestions I've used the following (almost pseudo) code.

#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;
}

The output is:

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

I'm not sure how to_2d works but certainly not the way I hope it would. The computed area is 20 instead of the actual 100.

BTW, I've also begin to realize that this goal could be achieved by simple computing the angle between the viewing direction (V_c - V_v) and normal ofthe polyong. sin a * original_area should give the area.

Upvotes: 2

Views: 239

Answers (1)

mgimeno
mgimeno

Reputation: 726

To compute the centroid of your polygon you can use CGAL::centroid(). Then to construct your plane you can use the constructor of Plane_3 that takes a point and a normal. After that you can project each point of your polygon using Plane_3::projection(), and then I'd propose to use to_2D() on those new points to get Point_2, and be able to use area_2().

Upvotes: 1

Related Questions