当前位置:首页 > 文章列表 > Golang > Go教程 > Go go-geom 怎样计算几何对象的坐标包围盒

Go go-geom 怎样计算几何对象的坐标包围盒

来源:17golang原创 2026-10-31 01:56:13 0浏览 收藏

使用 go-geom 计算几何对象的坐标包围盒,核心是调用 g.Bounds(),确认 IsEmpty() 为假后,再读取各维度的 Min 与 Max。二维 XY 对象的常用顺序是 [minX, minY, maxX, maxY]。这个范围与坐标轴平行,适合表达视图范围或作粗筛选。

例如,一条配送线路已经用平面坐标表示,需要给地图视图提供覆盖范围。这里先解决四个极值的取得,不加入空间索引、投影转换或最小旋转矩形算法。示例固定依赖 v1.6.1,该标签的 go.mod 声明 Go 1.22;选定版本是为了让接口依据明确,不表示它是最新版本。

项目官方仓库:https://github.com/twpayne/go-geom

先用四个极值描述二维范围

LineString 表示折线,XY 规定两个坐标分量的含义;Bounds 保存各维最小值与最大值。维度0对应X,维度1对应Y。因此,X极值来自 Min(0)、Max(0),Y极值来自 Min(1)、Max(1)。IsEmpty 则是范围对象的空状态判断。接口定义可见包文档的 Bounds 部分。

LineString与XY布局及Bounds极值字段关系
图1:几何对象与范围字段的静态结构说明图,连线表示所属或方法关系,不表示执行顺序。
取值含义
Min(0)全部坐标中的最小X
Min(1)全部坐标中的最小Y
Max(0)全部坐标中的最大X
Max(1)全部坐标中的最大Y

把有效折线转换成四个数

在新建的示例目录中初始化模块并固定依赖;已有项目跳过初始化。以下是供读者运行的示例,不是本文实际运行记录。

# 新示例目录初始化;已有 go.mod 的项目不再执行这一行
go mod init example.com/geometrybox
# 使用与本文依据一致的依赖标签
go get github.com/twpayne/go-geom@v1.6.1
# 把下方完整程序保存为 main.go 后执行
go run .

函数刻意只接收 *geom.LineString,把输入限制在二维有限坐标折线。SetCoords 的错误用于发现坐标分量数不合布局的问题;数值是否有限由示例另外处理,不把这些责任都交给包围盒方法。

package main

import (
    "fmt"
    "log"
    "math"

    "github.com/twpayne/go-geom"
)

// lineBoxXY 只接收二维折线,拒绝非有限坐标和空范围。
func lineBoxXY(line *geom.LineString) ([4]float64, error) {
    var box [4]float64
    if line == nil {
        return box, fmt.Errorf("折线不能为空指针")
    }
    if line.Layout() != geom.XY {
        return box, fmt.Errorf("需要 XY 布局,实际为 %v", line.Layout())
    }
    for i, value := range line.FlatCoords() {
        if math.IsNaN(value) || math.IsInf(value, 0) {
            return box, fmt.Errorf("坐标分量 %d 不是有限数", i)
        }
    }
    bounds := line.Bounds()
    // 空对象没有可以交给视图使用的有限极值。
    if bounds.IsEmpty() {
        return box, fmt.Errorf("折线没有坐标")
    }
    box = [4]float64{
        bounds.Min(0), bounds.Min(1),
        bounds.Max(0), bounds.Max(1),
    }
    return box, nil
}

func main() {
    // 示例使用同一平面坐标系中的三个 XY 点。
    line, err := geom.NewLineString(geom.XY).SetCoords([]geom.Coord{
        {12, 8}, {-4, 17}, {7, -3},
    })
    if err != nil {
        log.Fatal(err)
    }
    box, err := lineBoxXY(line)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("minX=%g minY=%g maxX=%g maxY=%g\n",
        box[0], box[1], box[2], box[3])
}

按给出的三个点手工推算,X范围为-4至12,Y范围为-3至17。由此可预期程序打印下列文字;这组数值是示例推导,未在本轮执行程序。

minX=-4 minY=-3 maxX=12 maxY=17

空范围和零宽、零高不是一回事

新建但尚未扩展的范围没有有效坐标。v1.6.1 的实现用正无穷初始化最小值、负无穷初始化最大值,并通过极值关系判断空状态。所以先判断空,再向外提供数字;不要把没有坐标的范围序列化成正常视图参数。依据:固定标签的 bounds.go。

一个有效点的最小值和最大值可以相等;一条竖直折线的X跨度也可以为零。这类范围不等于没有数据。如果视图需要最小显示宽度,应由调用方按业务单位增加留白,不要把零跨度当空对象丢弃。对于 NaN 或无穷值,示例入口直接返回错误,避免让异常值进入后续矩形计算。

多条折线如何合并范围

几条折线共享一个范围时,可以创建 geom.NewBounds(geom.XY),再用 Extend 扩展。此处的折线集合必须满足XY布局、同一坐标系、有限坐标三项输入约束;Extend 关联的是已有范围及待包含的几何,合并Bounds保留所有有效坐标的极值。

折线集合输入约束与Extend和合并Bounds的关系
图2:多条二维折线与共享包围盒的静态关系说明图,不是运行结果。
// 以下片段放在 main 内,接在已经创建 line 的代码之后。
other, err := geom.NewLineString(geom.XY).SetCoords([]geom.Coord{
    {20, 5}, {22, 11},
})
if err != nil {
    log.Fatal(err)
}
combined := geom.NewBounds(geom.XY)
for _, item := range []*geom.LineString{line, other} {
    // 复用上面的输入约束;空折线在本例中直接跳过。
    if item == nil {
        log.Fatal("待合并折线不能为空指针")
    }
    if item.Empty() {
        continue
    }
    if _, err := lineBoxXY(item); err != nil {
        log.Fatal(err)
    }
    combined.Extend(item)
}
if combined.IsEmpty() {
    log.Fatal("没有可用的几何坐标")
}
fmt.Printf("合并范围:[%g,%g,%g,%g]\n",
    combined.Min(0), combined.Min(1),
    combined.Max(0), combined.Max(1))

把追加折线的两个点纳入计算后,预期合并范围为 [-4,-3,22,17]。这个扩展会修改 combined;如果需要保留旧范围供另一处使用,应先复制范围对象,不要只复制指针变量。

应用到其他几何时注意什么

包提供统一的几何接口,Point、Polygon等类型也可取得各自的Bounds。这里的辅助函数只针对折线,替换类型时要重新安排输入约束,不能把函数签名直接当通用处理器。普通几何的坐标存储和范围计算关系可参考项目的几何基础实现。

布局与坐标系分开看。XY只说明有X、Y分量;同为XY不代表单位和投影相同。设置SRID也不能替代实际坐标转换。经纬度数据直接取极值,是输入数值的矩形范围;跨越经度接缝时,它未必是视觉上最紧的地理覆盖区域。

多维输入先明确要哪一层范围。XYZ多了高度,XYM第三个分量是M而非高度;如果只要地图二维范围,就明确读取前两维并单独制定输入策略。不要默认维度2始终代表Z。布局及维度含义见项目的 Layout 定义。

相关问题

包围盒重叠就意味着原几何相交吗?

不能据此作精确相交结论。矩形范围适合粗筛,原始几何的形状仍需另行判断。

Bounds是不是面积最小的旋转矩形?

不是。这里按坐标轴逐维取得极值,没有搜索矩形旋转角度。

几何坐标改了,之前保存的范围会自动变吗?

不要依赖这种联动。需要新范围时重新调用几何对象的Bounds;缓存范围的失效由调用方管理。对视图参数而言,先确认输入,再判断空状态,最后读取四个极值,是最容易维护的一种写法。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go go-geom 怎样用平铺坐标构造二维折线Go go-geom 怎样用平铺坐标构造二维折线
上一篇
Go go-geom 怎样用平铺坐标构造二维折线
Redis LFU频率计数为什么不等于精确访问次数
下一篇
Redis LFU频率计数为什么不等于精确访问次数
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    801次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    792次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    879次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    849次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    680次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码