我试图在3d空间中获得2d多边形的区域。 Boost :: Geometry有没有办法做到这一点?这是我的实现,但它一直返回0:
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace bg = boost::geometry;
typedef bg::model::point<double, 3, bg::cs::cartesian> point3d;
int main()
{
bg::model::multi_point<point3d> square;
bg::read_wkt("MULTIPOINT((0 0 0), (0 2 0), (0 2 2), (0 0 2), (0 0 0))", square);
double area = bg::area(square);
std::cout << "Area: " << area << std::endl;
return 0;
}
UPD :实际上,我对简单的2d多点广场有同样的问题:
#include <iostream>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/io/wkt/wkt.hpp>
namespace bg = boost::geometry;
typedef bg::model::point<double, 2, bg::cs::cartesian> point2d;
int main()
{
bg::model::multi_point<point2d> square;
bg::read_wkt("MULTIPOINT((0 0), (2 0), (2 2), (0 2))", square);
double area = bg::area(square);
std::cout << "Area: " << area << std::endl;
return 0;
}
结果如下:
$ ./test_area
Area: 0
UPD :看起来boost::geometry
中的区域计算仅适用于2维多边形。
答案 0 :(得分:2)
我不希望一组积分有一个区域。您需要等效的model::polygon<poind3d>
,但目前似乎不支持。
如果保证点是共面的并且线段不相互交叉,则可以将多边形分解为一系列三角形,并使用一点线性代数计算区域,基于以下公式对于三角形区域:
在非凸多边形的情况下,需要调整面积之和以减去多边形外的区域。实现这一目标的最简单方法是使用三角形的有符号区域,包括右手三角形的正贡献和左手三角形的负贡献:
请注意,似乎有一些计划在Boost中包含cross_product
实现,但从版本1.56开始,它似乎不包括在内。以下替换应该适用于您的用例:
point3d cross_product(const point3d& p1, const point3d& p2)
{
double x = bg::get<0>(p1);
double y = bg::get<1>(p1);
double z = bg::get<2>(p1);
double u = bg::get<0>(p2);
double v = bg::get<1>(p2);
double w = bg::get<2>(p2);
return point3d(y*w-z*v, z*u-x*w, x*v-y*u);
}
point3d cross_product(const bg::model::segment<point3d>& p1
, const bg::model::segment<point3d>& p2)
{
point3d v1(p1.second);
point3d v2(p2.second);
bg::subtract_point(v1, p1.first);
bg::subtract_point(v2, p2.first);
return cross_product(v1, v2);
}
然后可以使用以下内容计算区域:
// compute the are of a collection of 3D points interpreted as a 3D polygon
// Note that there are no checks as to whether or not the points are
// indeed co-planar.
double area(bg::model::multi_point<point3d>& polygon)
{
if (polygon.size()<3) return 0;
bg::model::segment<point3d> v1(polygon[1], polygon[0]);
bg::model::segment<point3d> v2(polygon[2], polygon[0]);
// Compute the cross product for the first pair of points, to handle
// shapes that are not convex.
point3d n1 = cross_product(v1, v2);
double normSquared = bg::dot_product(n1, n1);
if (normSquared > 0)
{
bg::multiply_value(n1, 1.0/sqrt(normSquared));
}
// sum signed areas of triangles
double result = 0.0;
for (size_t i=1; i<polygon.size(); ++i)
{
bg::model::segment<point3d> v1(polygon[0], polygon[i-1]);
bg::model::segment<point3d> v2(polygon[0], polygon[i]);
result += bg::dot_product(cross_product(v1, v2), n1);
}
result *= 0.5;
return abs(result);
}
答案 1 :(得分:1)
我不熟悉boost的几何部分,但凭借我对几何学的了解,我可以说3D在3D方面没有太大差别。虽然可能已经有了一些提升,但您可以编写自己的方法来轻松完成这项工作。
编辑:
da code monkey指出shoelace formula以这种方式会更有效率,因为它不那么复杂,而且速度更快。
以下原创意见:
为了计算这个,我首先将多边形镶嵌成三角形,因为任何多边形都可以分割成许多三角形。我将采用这些三角形中的每一个,并计算每个三角形的面积。要在3d空间中执行此操作,相同的概念适用。为了得到基数,你取△ABC并任意指定-AB作为基数,-BC作为高度,-CA作为斜边。做(-AB * -BC)/ 2。只需将每个三角形的区域相加即可。
我不知道boost是否有内置的tessellate方法,这在c ++中实现起来相当困难,但你可能想要创建某种三角形扇形。 (注意:这仅适用于凸多边形)。如果你有一个凹多边形,你应该看看这个:http://www.cs.unc.edu/~dm/CODE/GEM/chapter.html我将把它放到c ++作为练习,但过程相当简单。