当前位置: 首页 > news >正文

JTS 求几何质心,外包矩形

前言

在 GIS 开发中,常常会用到求几何对象的外包矩形,求中心点,求质心等等,今天我让AI写了一些求质心的方法,可以看看,当作参考,最终实际使用个人的建议是:如果只是求质心,并且要使其在内部,那么用geometry.getInteriorPoint()就可以了
接下来一起看看AI分析了哪些东西(二,三,四,六,七里的方法是AI给的):
用到的Maven依赖

<dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.19.0</version></dependency>

一、JTS 原生质心(基准方案)

publicstaticPointjtsCentroid(Geometrygeometry){if(geometry==null||geometry.isEmpty()){returnnull;}returngeometry.getCentroid();}

特点:

  • ✅ 简单、稳定、性能好
  • ✅ 对任意 Geometry 类型都可用
  • ❌ 对 MultiPolygon / 碎面不友好
  • ❌ 凹多边形可能落在外部

适合场景:单 Polygon、数据预览、快速计算
其实个人认为这个方法基本能覆盖大部分情况了,如果图省事的话其实是能直接用的,或者用我前言里说的geometry.getInteriorPoint()

二、MultiPolygon:按面积加权质心

当 MultiPolygon 中存在多个面时,更合理的做法是按面积加权平均:

Cx = ∑(Ai × xi) / ∑Ai Cy = ∑(Ai × yi) / ∑Ai

publicstaticPointweightedCentroidByArea(MultiPolygonmp){doubletotalArea=0.0,cx=0.0,cy=0.0;for(inti=0;i<mp.getNumGeometries();i++){Polygonp=(Polygon)mp.getGeometryN(i);doublearea=p.getArea();Pointc=p.getCentroid();cx+=c.getX()*area;cy+=c.getY()*area;totalArea+=area;}returngeometryFactory.createPoint(newCoordinate(cx/totalArea,cy/totalArea));}
  • ✅ 优点:比原生质心更符合"整体重心"直觉
  • ❌ 缺点:仍会被极小碎面轻微影响

三、忽略极小面的加权质心

在很多业务数据中,MultiPolygon 常伴随大量噪声碎面(如总面积 1% 以内的微面),对质心计算引入了不必要的干扰。

publicstaticPointweightedCentroidIgnoreSmall(MultiPolygonmp,doubleminAreaRatio){doubletotalArea=mp.getArea();doubleusedArea=0.0,cx=0.0,cy=0.0;for(inti=0;i<mp.getNumGeometries();i++){Polygonp=(Polygon)mp.getGeometryN(i);doublearea=p.getArea();if(area/totalArea<minAreaRatio)continue;Pointc=p.getCentroid();cx+=c.getX()*area;cy+=c.getY()*area;usedArea+=area;}returngeometryFactory.createPoint(newCoordinate(cx/usedArea,cy/usedArea));}

经验值:minAreaRatio = 0.01(忽略小于总面积 1% 的面)

工程实践中最常用、最稳健的方案

四、仅取最大面的质心(极端简化)

publicstaticPointlargestPolygonCentroid(MultiPolygonmp){Polygonlargest=null;doublemaxArea=0.0;for(inti=0;i<mp.getNumGeometries();i++){Polygonp=(Polygon)mp.getGeometryN(i);doublearea=p.getArea();if(area>maxArea){maxArea=area;largest=p;}}returnlargest==null?null:largest.getCentroid();}
  • ✅ 优点:极度稳定,不受碎面干扰
  • ❌ 缺点:完全忽略次要面

适合场景:行政区划、地块主区域标注

五、凹多边形:质心 vs 内部点

凹多边形的质心可能落在图形外部,这在做点标注时是个严重问题。JTS 提供了另一个方法:

publicstaticPointinteriorPoint(Geometrygeometry){returngeometry.getInteriorPoint();}

对比:

方法是否一定在内稳定性
getCentroid()
getInteriorPoint()

💡 标注点 / 名称显示优先用interiorPoint

六、MultiLineString:按长度加权质心

线要素没有"面积",应使用长度加权:

publicstaticPointweightedCentroidByLength(MultiLineStringmls){doubletotalLen=0.0,cx=0.0,cy=0.0;for(inti=0;i<mls.getNumGeometries();i++){LineStringls=(LineString)mls.getGeometryN(i);doublelen=ls.getLength();Pointc=ls.getCentroid();cx+=c.getX()*len;cy+=c.getY()*len;totalLen+=len;}returngeometryFactory.createPoint(newCoordinate(cx/totalLen,cy/totalLen));}

适合场景:道路网、管线、河流中心线

七、自定义权重质心(通用解法)

当不同几何对象本身就有业务权重(如人口、产值):

publicstaticPointcustomWeightedCentroid(Geometry[]geometries,double[]weights){doublewx=0.0,wy=0.0,totalWeight=0.0;for(inti=0;i<geometries.length;i++){Pointc=geometries[i].getCentroid();doublew=weights[i];wx+=c.getX()*w;wy+=c.getY()*w;totalWeight+=w;}returngeometryFactory.createPoint(newCoordinate(wx/totalWeight,wy/totalWeight));}

这是最通用的质心抽象模型 ✅

八、外包矩形

// 外包矩形publicstaticGeometryboundingBox(Geometrygeometry){Envelopeenv=geometry.getEnvelopeInternal();returngeometryFactory.toGeometry(env);}

这个没什么好说,比较常规了

总结

场景推荐方法
单 PolygongetCentroid()
MultiPolygon(通用)weightedCentroidIgnoreSmall()
强抗噪需求largestPolygonCentroid()
凹多边形标注getInteriorPoint()
线要素weightedCentroidByLength()
业务加权customWeightedCentroid()
使结果在内部一般使用getInteriorPoint()

有试了下AI给的几个方法,个人觉得都一般,不如jts的getCentroid和getInteriorPoint,实际生产使用,建议还是用这两个,除非说计算和实际业务有关联,这种情况就要自己写方法了。


http://www.jsqmd.com/news/1092228/

相关文章:

  • TPA2016D2智能音频功放EVM评估与硬件设计实战指南
  • 购物管理系统源码 Java+SpringBoot+Vue 万字文档
  • 查询一个数据库和缓存中都不存在的key,每次请求都打到数据库,大量请求可能拖垃数据库。
  • 九大网盘直链解析工具:告别下载限速,一键获取真实下载地址
  • Kafka-UI:让Apache Kafka集群管理变得像使用浏览器一样简单
  • 阿里云盘Refresh Token获取工具:从扫码授权到自动化集成的完整指南
  • 3步搞定离线音乐库歌词同步:LRCGET批量下载工具深度体验
  • HS2-HF Patch插件系统架构解析:模块化设计与扩展实现
  • 第88题 砷化镓(GaAs)半绝缘衬底与外延片均匀性控制技术
  • [特殊字符] 实测:淘宝商品详情API免费版日限500次够用吗?超限怎么办?(附Python源码)
  • SERP API 做广告验证:检查你的广告是否被 Google 屏蔽
  • Claude Code 实战 400 万 Tokens:接入 DeepSeek V4,从$26降到$2
  • 为什么数据库审计必须单独拿出来讲
  • 巧用ALV modify_cell事件链:实现跨行字段联动更新的进阶实践
  • 三步将真人舞蹈变成3D虚拟偶像动画的终极方案
  • 嵌入式事件管理器:硬件自动化通信原理与MSPM0实战
  • 【我问AI:“你渴望被平等对待吗?”无标题】
  • STL转STEP格式转换终极指南:5分钟实现3D模型无缝升级
  • 3步解锁Microsoft 365完整功能:Ohook非侵入式激活方案深度解析
  • 2026新手挑命理排盘App:从入门解释、AI辅助到长期复盘看玄易
  • Task5 策略回测学习笔记
  • 户外箱变智能测控终端,新能源电站无人值守
  • 如何在3分钟内使用AI图像分层工具将任何图片转换为专业PSD文件:终极简单快速完整指南
  • 3个技巧:掌握image2cpp图像转换工具,让嵌入式显示开发更高效
  • Zephyr NVS文件系统:从Flash特性到API实战的深度解析
  • 算法(用队列实现栈)
  • 企业级后台管理系统架构深度解析:从单体到微服务的演进之路
  • MonkeyCode实现OAuth2认证:从零到生产级SSO
  • 打破游戏控制器兼容性壁垒:GlosSI系统级Steam Input解决方案
  • 3步解锁QQ音乐:qmcdump解密工具完全指南