在循环中重复使用 boost::geometry:::交集

Repeated use of boost::geometry::intersection in a loop

本文关键字:boost geometry 交集 循环      更新时间:2023-10-16

我有一个基本的多多边形B和许多其他多多边形p_0, p_1, p_2, ...每个多边形都有一个权重w_0, w_1, w_2, ...

我想:

  • 计算Bp_0的交点面积,并将该面积乘以w_0
  • 差值Bp_0形成一个新的多多边形B_1,该多边形Bp_0从中切出。
  • 计算B_1p_1的交点面积,并将该面积乘以w_1
  • B_1p_1形成一个新的多多边形B_2,该多边形B_1从中切出p_1
  • 等等...

我正在尝试使用 boost::p olygon 库来做到这一点。他们有一个如何在这里做交叉点的例子,在这里做差异。

交集函数定义如下:

bool intersection(Geometry1 const & geometry1, Geometry2 const & geometry2, GeometryOut & geometry_out)

为了在循环中使用intersection并测量面积,我认为我需要将GeometryOut类型转换为Geometry1类型。目前尚不清楚如何做到这一点。

到目前为止,我的代码的简化版本是:

#include <boost/polygon/polygon.hpp>
#include <boost/geometry/geometry.hpp>
#include <boost/geometry/multi/geometries/multi_polygon.hpp>
#include <iostream>
#include <vector>
#include <cstdlib>
namespace gtl = boost::polygon;
typedef gtl::polygon_data<float> Polygon;
Polygon MakeBox(float xmin, float ymin, float xmax, float ymax){
  typedef gtl::polygon_traits<Polygon>::point_type Point;
  Point pts[] = {
    gtl::construct<Point>(xmin, ymin),
    gtl::construct<Point>(xmin, ymax),
    gtl::construct<Point>(xmax, ymax),
    gtl::construct<Point>(xmax, ymin)
  };
  Polygon poly;
  gtl::set_points(poly, pts, pts+4);
  return poly;
}
double GetValue(const Polygon &base, const std::vector<Polygon> &polys, const std::vector<double> &vals){
  double value     = 0;
  double base_area = gtl::area(base);
  boost::geometry::model::multi_polygon<Polygon> multipoly, isect, multipolynew;
  //I've also tried the following line in place of the line above: doesn't work.
  //std::deque<Polygon> multipoly, isect, multipolynew;
  multipoly.push_back(base);
  for(int i=0;i<polys.size();i++){
    boost::geometry::intersection(multipoly, polys[i], isect);
    value    += gtl::area(isect)/base_area*vals[i];
    boost::geometry::difference(multipoly,polys[i],multipolynew);
    multipoly = multipolynew;
  }
  return value;
}
int main() {
  Polygon base = MakeBox(0,0,10,10); //Base polygon
  std::vector<Polygon> polys;
  std::vector<double>  vals;
  //Set up some random input
  for(int i=0;i<3;i++){
    int xmin=rand()%10;
    int xmax=xmin+rand()%10;
    int ymin=rand()%10;
    int ymax=ymin+rand()%10;
    polys.push_back(MakeBox(xmin,ymin,xmax,ymax));
    vals.push_back(rand()%100);
  }
  std::cout<<GetValue(base,polys,vals)<<std::endl;
}

从各个角度来看,我得出的结论是,这是增强多边形类型的增强几何适应的限制。

即使将"原版"环型(boost::polygon_data<>)替换为Boost Polygon(boost::polygon_with_holes_data<>)中功能更全的多边形概念实现,也不允许在boost::geometry::multi_poygon<T>实例化中使用适应的多边形。

如果您有兴趣,我在搜索过程中发现了更多信息:

    使用"提升
  1. 几何"模型而不是"提升多边形"类型时,您可以根据需要执行任何操作。直接将multi_polygon用作几何体没有问题:

    住在科里鲁

    #include <fstream>
    #include <boost/geometry/geometry.hpp>
    #include <boost/geometry/io/io.hpp>
    #include <boost/geometry/geometries/geometries.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <boost/foreach.hpp>
    typedef boost::geometry::model::d2::point_xy<double> PointType;
    using Polygon = boost::geometry::model::polygon<PointType>;
    Polygon MakeBox(float xmin, float ymin, float xmax, float ymax){
        Polygon poly;
        poly.outer().assign({
            {xmin, ymin},
            {xmin, ymax},
            {xmax, ymax},
            {xmax, ymin}
        });
        return poly;
    }
    double GetValue(const Polygon &base, const std::vector<Polygon> &polys, const std::vector<double> &vals){
        double value     = 0;
        double base_area = boost::geometry::area(base);
        boost::geometry::model::multi_polygon<Polygon> multipoly, isect, multipolynew;
        multipoly.push_back(base);
        for(size_t i=0;i<polys.size();i++){
            boost::geometry::intersection(multipoly, polys[i], isect);
            value += boost::geometry::area(isect)/base_area*vals[i];
            boost::geometry::difference(multipoly,polys[i],multipolynew);
            multipoly = multipolynew;
        }
        return value;
    }
    int main()
    {
        Polygon base = MakeBox(0,0,10,10); //Base polygon
        std::vector<Polygon> polys;
        std::vector<double>  vals;
        //Set up some random input
        for(int i=0;i<3;i++){
            int xmin=rand()%10;
            int xmax=xmin+rand()%10;
            int ymin=rand()%10;
            int ymax=ymin+rand()%10;
            polys.push_back(MakeBox(xmin,ymin,xmax,ymax));
            vals.push_back(rand()%100);
        }
        std::cout<<GetValue(base,polys,vals)<<std::endl;
    }
    
  2. 或者,您可以实现相交的 O(n log n) 访问版本,该版本与多边形的两个集合(例如向量)相交,即使它们不是单个几何体。

    这个

    邮件列表交换精确地详细说明了这个 http://boost-geometry.203548.n3.nabble.com/intersection-of-two-vectors-of-polygons-tp2875513p2880997.html(即使这里的用例是使单个多边形可以与唯一的信息位(id s)相关联,这很难用multi_polygon s做到)。

    这是该代码的简化改编,适用于交叉点。我想您需要对difference调用(?我将把它留给读者作为练习。

    住在科里鲁

    另一个相关线程可能 http://boost-geometry.203548.n3.nabble.com/Unioning-many-polygons-td3405482.html