31.Boost.Geometry 几何模型接口详解:线串、多边形集、矩形盒、环、线段和引用线段

Boost.Geometry 库提供了一系列标准的几何模型(Models),用于表示各种几何对象。这些模型遵循 OGC(开放地理空间联盟)标准,并实现了相应的概念(Concepts),使得开发者可以方便地进行几何计算、空间分析和数据转换。本文将详细介绍 multi_linestringmulti_polygonboxringsegmentreferring_segment 这六种核心几何模型的接口定义、功能描述及参数说明。


1. 多线串 (model::multi_linestring)

功能描述

multi_linestring 用于表示一组线串(linestring)的集合。它适用于需要将多条独立的线段逻辑上归为一组的场景,例如表示一条被中断的高速公路、河流系统或复杂的道路网络。该模型实现了 MultiLineString 概念。

类原型

template <
    typename LineString, 
    template <typename, typename> class Container = std::vector, 
    template <typename> class Allocator = std::allocator
>
class model::multi_linestring : public std::vector<LineString, std::allocator<LineString>> {
    // ...
};

模板参数说明

参数默认值描述
LineString(无)线串的类型,通常是 model::linestring<Point>
Containerstd::vector底层容器类型,用于存储线串集合。
Allocatorstd::allocator内存分配器类型。

构造函数

函数原型描述参数说明
multi_linestring()默认构造函数,创建一个空的多线串对象。
multi_linestring(std::initializer_list<LineString> l)初始化列表构造函数,使用给定的线串列表填充多线串。l: LineString 类型的初始化列表。

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/multi_linestring.hpp>

2. 多边形集合 (model::multi_polygon)

功能描述

multi_polygon 用于表示一组多边形(polygon)的集合。它常用于表示由多个不连续区域组成的地理实体,例如群岛(如夏威夷)、分散的行政区或多个独立的地块。该模型实现了 MultiPolygon 概念。

类原型

template <
    typename Polygon, 
    template <typename, typename> class Container = std::vector, 
    template <typename> class Allocator = std::allocator
>
class model::multi_polygon : public std::vector<Polygon, std::allocator<Polygon>> {
    // ...
};

模板参数说明

参数默认值描述
Polygon(无)多边形的类型,通常是 model::polygon<Point>
Containerstd::vector底层容器类型,用于存储多边形集合。
Allocatorstd::allocator内存分配器类型。

构造函数

函数原型描述参数说明
multi_polygon()默认构造函数,创建一个空的多边形集合。
multi_polygon(std::initializer_list<Polygon> l)初始化列表构造函数,使用给定的多边形列表填充集合。l: Polygon 类型的初始化列表。

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/multi_polygon.hpp>

3. 矩形盒 (model::box)

功能描述

box 定义了一个由两个对角点(最小角点和最大角点)描述的轴对齐矩形(或超矩形)。它是进行空间索引(如 R-Tree)和快速边界检查(Bounding Box Check)的基础数据结构。与通用的多边形不同,box 始终由最小和最大坐标定义,效率更高。该模型实现了 Box 概念。

类原型

template <typename Point>
class model::box {
    // ...
};

模板参数说明

参数描述
Point点类型。可以是 2D、3D 或更高维度的点,也可以是地理坐标(经纬度)点。

构造函数

函数原型描述参数说明
box()默认构造函数,不进行初始化。
box(Point const& min_corner, Point const& max_corner)构造函数,通过指定最小角点和最大角点来创建矩形。min_corner: 最小坐标点。max_corner: 最大坐标点。

成员函数

函数原型描述返回值
constexpr Point const& min_corner()获取最小角点的常量引用。Point const&
constexpr Point const& max_corner()获取最大角点的常量引用。Point const&
Point& min_corner()获取最小角点的非常量引用,用于修改。Point&
Point& max_corner()获取最大角点的非常量引用,用于修改。Point&

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/box.hpp>

4. 环 (model::ring)

功能描述

ring(也称为线性环 linear ring)是一个闭合的线串,通常不自交。它是构成多边形外边界或内孔(洞)的基本单元。环可以是顺时针或逆时针方向,且可以选择是否显式闭合(即首尾点坐标相同)。该模型实现了 Ring 概念。

类原型

template <
    typename Point, 
    bool ClockWise = true, 
    bool Closed = true, 
    template <typename, typename> class Container = std::vector, 
    template <typename> class Allocator = std::allocator
>
class model::ring : public std::vector<Point, std::allocator<Point>> {
    // ...
};

模板参数说明

参数默认值描述
Point(无)点类型。
ClockWisetrue方向标识。true 表示顺时针,false 表示逆时针。
Closedtrue闭合标识。true 表示闭合多边形(最后一个点等于第一个点),false 表示开放。
Containerstd::vector底层容器类型。
Allocatorstd::allocator内存分配器类型。

构造函数

函数原型描述参数说明
ring()默认构造函数,创建一个空的环。
ring(Iterator begin, Iterator end)迭代器构造函数,使用指定范围的点填充环。begin: 起始迭代器。end: 结束迭代器。
ring(std::initializer_list<Point> l)初始化列表构造函数,使用点列表填充环。l: Point 类型的初始化列表。

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/ring.hpp>

5. 线段 (model::segment)

功能描述

segment 是一个包含两个端点的小型类,表示几何中的线段。线段由两个不同的端点界定,并包含这两点之间的所有点。它常用于距离计算、相交测试等基础几何操作。该模型实现了 Segment 概念,底层继承自 std::pair<Point, Point>

类原型

template <typename Point>
class model::segment : public std::pair<Point, Point> {
    // ...
};

模板参数说明

参数描述
Point点类型,表示线段的端点。

构造函数

函数原型描述参数说明
segment()默认构造函数,不进行初始化。
segment(Point const& p1, Point const& p2)构造函数,通过指定起点和终点创建线段。p1: 第一个点(起点)。p2: 第二个点(终点)。

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/segment.hpp>

6. 引用线段 (model::referring_segment)

功能描述

referring_segmentsegment 类似,但它不拥有点的副本,而是持有两个点的引用。这使得它非常适合用于临时计算或算法中,避免不必要的数据拷贝,特别是当点数据已经存在于其他结构中时。它可以引用非常量点或常量点。

类原型

template <typename ConstOrNonConstPoint>
class model::referring_segment {
    // ...
};

模板参数说明

参数描述
ConstOrNonConstPoint点类型,可以是 Point&const Point&,决定了引用的可变性。

构造函数

函数原型描述参数说明
referring_segment(point_type& p1, point_type& p2)构造函数,通过引用两个现有点来创建线段视图。p1: 第一个点的引用。p2: 第二个点的引用。

头文件

#include <boost/geometry/geometries/geometries.hpp>
// 或
#include <boost/geometry/geometries/segment.hpp>

7.示例代码

#include <iostream>
#include <vector>
#include <string>

// 引入 Boost.Geometry 核心头文件
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point.hpp>
#include <boost/geometry/geometries/linestring.hpp>
#include <boost/geometry/geometries/ring.hpp>
#include <boost/geometry/geometries/polygon.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/segment.hpp>
#include <boost/geometry/geometries/multi_linestring.hpp>
#include <boost/geometry/geometries/multi_polygon.hpp>

// 定义命名空间别名,简化代码
namespace bg = boost::geometry;
namespace model = bg::model;

void DemoModel() {
    // ------------------------------------------------------------------
    // 1. 定义基础几何类型
    // ------------------------------------------------------------------
    // 定义一个二维笛卡尔坐标系的点 (double 类型)
    using point_t = model::point<double, 2, bg::cs::cartesian>;

    // 定义线串、环、多边形等基于该点类型的几何体
    using linestring_t = model::linestring<point_t>;
    using ring_t = model::ring<point_t>;
    using polygon_t = model::polygon<point_t>;

    // ------------------------------------------------------------------
    // 2. Segment (线段) 的使用
    // ------------------------------------------------------------------
    std::cout << "--- Testing Segment ---" << std::endl;

    // 创建两个端点
    point_t p1(0.0, 0.0);
    point_t p2(3.0, 4.0);

    // 构造线段:连接 p1 和 p2
    model::segment<point_t> seg(p1, p2);

    // 计算线段长度 (勾股定理: 3-4-5 三角形,长度应为 5)
    double length = bg::length(seg);
    std::cout << "Segment length: " << length << std::endl;

    // 获取线段的边界框 (Envelope)
    model::box<point_t> env = bg::return_envelope<model::box<point_t>>(seg);
    std::cout << "Segment envelope min: ("
              << bg::get<0>(env.min_corner()) << ", " << bg::get<1>(env.min_corner()) << ")" << std::endl;
    std::cout << "Segment envelope max: ("
              << bg::get<0>(env.max_corner()) << ", " << bg::get<1>(env.max_corner()) << ")" << std::endl;

    // ------------------------------------------------------------------
    // 3. Referring Segment (引用线段) 的使用
    // ------------------------------------------------------------------
    std::cout << "\n--- Testing Referring Segment ---" << std::endl;

    // 修改原始点 p2 的坐标
    bg::set<0>(p2, 6.0);
    bg::set<1>(p2, 8.0);

    // 创建引用线段:它不复制点,而是引用 p1 和 p2
    // 当 p1 或 p2 改变时,ref_seg 看到的值也会改变
    model::referring_segment<point_t> ref_seg(p1, p2);

    double ref_length = bg::length(ref_seg);
    // 此时长度应基于新坐标 (0,0) 到 (6,8),长度为 10
    std::cout << "Referring Segment length (after moving point): " << ref_length << std::endl;
    std::cout << "Note: Referring segment reflects changes in original points without copying." << std::endl;

    // ------------------------------------------------------------------
    // 4. Box (矩形盒) 的使用
    // ------------------------------------------------------------------
    std::cout << "\n--- Testing Box ---" << std::endl;

    // 定义左下角和右上角
    point_t min_point(1.0, 1.0);
    point_t max_point(5.0, 5.0);

    // 构造矩形盒
    model::box<point_t> box(min_point, max_point);

    // 计算矩形的面积
    double area = bg::area(box);
    std::cout << "Box area: " << area << std::endl; // 应为 16.0

    // 检查点是否在矩形内
    point_t test_point(3.0, 3.0);
    bool within = bg::within(test_point, box);
    std::cout << "Point (3,3) is within box: " << (within ? "true" : "false") << std::endl;

    // ------------------------------------------------------------------
    // 5. Ring (环) 的使用
    // ------------------------------------------------------------------
    std::cout << "\n--- Testing Ring ---" << std::endl;

    // 创建一个环 (默认顺时针,闭合)
    ring_t ring;
    // 添加点构成一个正方形
    bg::append(ring, point_t(0.0, 0.0));
    bg::append(ring, point_t(0.0, 4.0));
    bg::append(ring, point_t(4.0, 4.0));
    bg::append(ring, point_t(4.0, 0.0));
    // 注意:model::ring 默认 Closed=true,Boost 可能会自动处理闭合点,
    // 但显式添加首点以确保闭合也是常见做法(取决于具体配置)
    bg::append(ring, point_t(0.0, 0.0));

    // 校正环的方向和闭合性 (确保符合 OGC 标准)
    bg::correct(ring);

    double ring_area = bg::area(ring);
    std::cout << "Ring area: " << ring_area << std::endl; // 应为 16.0

    // ------------------------------------------------------------------
    // 6. Multi_Linestring (多线串) 的使用
    // ------------------------------------------------------------------
    std::cout << "\n--- Testing Multi_Linestring ---" << std::endl;

    // 定义多线串类型:包含多个 linestring_t
    using multi_ls_t = model::multi_linestring<linestring_t>;
    multi_ls_t multi_ls;

    // 创建第一条线
    linestring_t ls1;
    bg::append(ls1, point_t(0.0, 0.0));
    bg::append(ls1, point_t(1.0, 1.0));

    // 创建第二条线
    linestring_t ls2;
    bg::append(ls2, point_t(2.0, 2.0));
    bg::append(ls2, point_t(3.0, 3.0));

    // 将线串添加到集合中
    multi_ls.push_back(ls1);
    multi_ls.push_back(ls2);

    // 计算总长度
    double total_len = bg::length(multi_ls);
    std::cout << "Multi_Linestring total length: " << total_len << std::endl;
    std::cout << "Number of linestrings in collection: " << multi_ls.size() << std::endl;

    // ------------------------------------------------------------------
    // 7. Multi_Polygon (多边形集合) 的使用
    // ------------------------------------------------------------------
    std::cout << "\n--- Testing Multi_Polygon ---" << std::endl;

    // 定义多边形集合类型
    using multi_poly_t = model::multi_polygon<polygon_t>;
    multi_poly_t multi_poly;

    // 创建第一个多边形 (外环)
    polygon_t poly1;
    ring_t& outer1 = poly1.outer();
    bg::append(outer1, point_t(0.0, 0.0));
    bg::append(outer1, point_t(0.0, 2.0));
    bg::append(outer1, point_t(2.0, 2.0));
    bg::append(outer1, point_t(2.0, 0.0));
    bg::append(outer1, point_t(0.0, 0.0));
    bg::correct(poly1); // 校正方向

    // 创建第二个多边形
    polygon_t poly2;
    ring_t& outer2 = poly2.outer();
    bg::append(outer2, point_t(3.0, 3.0));
    bg::append(outer2, point_t(3.0, 5.0));
    bg::append(outer2, point_t(5.0, 5.0));
    bg::append(outer2, point_t(5.0, 3.0));
    bg::append(outer2, point_t(3.0, 3.0));
    bg::correct(poly2);

    // 添加到集合
    multi_poly.push_back(poly1);
    multi_poly.push_back(poly2);

    // 计算总面积
    double total_area = bg::area(multi_poly);
    std::cout << "Multi_Polygon total area: " << total_area << std::endl; // 应为 4.0 + 4.0 = 8.0

    // 计算整个集合的边界框
    model::box<point_t> multi_env = bg::return_envelope<model::box<point_t>>(multi_poly);
    std::cout << "Multi_Polygon envelope covers from ("
              << bg::get<0>(multi_env.min_corner()) << ", " << bg::get<1>(multi_env.min_corner()) << ") to ("
              << bg::get<0>(multi_env.max_corner()) << ", " << bg::get<1>(multi_env.max_corner()) << ")" << std::endl;

    std::cout << "\nAll tests completed successfully." << std::endl;

}

输出

--- Testing Segment ---
Segment length: 5
Segment envelope min: (0, 0)
Segment envelope max: (3, 4)

--- Testing Referring Segment ---
Referring Segment length (after moving point): 10
Note: Referring segment reflects changes in original points without copying.

--- Testing Box ---
Box area: 16
Point (3,3) is within box: true

--- Testing Ring ---
Ring area: 16

--- Testing Multi_Linestring ---
Multi_Linestring total length: 2.82843
Number of linestrings in collection: 2

--- Testing Multi_Polygon ---
Multi_Polygon total area: 8
Multi_Polygon envelope covers from (0, 0) to (5, 5)

All tests completed successfully.

总结

Boost.Geometry 的这些模型提供了灵活且高效的几何数据表示方式:

  • 组合型模型multi_linestring, multi_polygon)允许将多个基本几何体逻辑分组,适合处理复杂地理实体。
  • 基础结构模型box, ring, segment)构成了更复杂几何体(如多边形)的基石,并针对特定计算场景进行了优化。
  • 引用模型referring_segment)提供了零拷贝的几何视图,提升了算法执行效率。

在使用时,开发者应根据具体的应用场景(如是否需要拥有数据、维度要求、方向要求等)选择合适的模板参数进行实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值