MySQL的Geometry数据处理之WKB方案

MySQL的Geometry数据处理之WKT方案:https://blog.csdn.net/qq_42402854/article/details/140134357

MySQL的Geometry数据处理之WKT方案中,介绍WTK方案的优点,也感受到它的繁琐和缺陷。比如:

  • 需要借助 ST_GeomFromText和 ST_AsText,让 SQL语句显得复杂。
select id, ST_AsText(geometry) AS geometry, update_time, create_time from geometry_data
  • 没有一种GeomFromText方案可以覆盖所有的Geometry结构,使得类似的SQL要写多份。比如:ST_GeomFromText不是万能的。针对"几何信息集合"(GeometryCollection)则需要使用ST_GeomCollFromText来转换。
insert into geometry_data(id, geometry, update_time, create_time) values(#{id}, ST_GeomFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())insert into geometry_data(id, geometry, update_time, create_time) values(#{id}, ST_GeomCollFromText(#{geometry, jdbcType=BLOB, typeHandler=org.example.typehandlers.GeometryTypeWKTHandler}), now(), now())
  • 没有针对LinearRing(一种特殊的LineString)的处理方法。

MySQL的Geometry数据处理之WKB方案,则可以解决上述问题。

WKB全程Well-Known Binary,它是一种二进制存储几何信息的方法。

WKT方法,可以用字符串形式表达几何信息,如POINT (1 -1)。

WKB方法则表达为:0101000000000000000000F03F000000000000F0BF

这段二进制的拆解如下:
在这里插入图片描述

  1. byte order:可以是0或者1,它表示是大顶堆(0)还是小顶堆(1)存储。
  2. WKB type:表示几何类型。值的对应关系如下:
    ○ 1 Point
    ○ 2 LineString
    ○ 3 Polygon
    ○ 4 MultiPoint
    ○ 5 MultiLineString
    ○ 6 MultiPolygon
    ○ 7 GeometryCollection
  3. 剩下的是坐标信息。

虽然这个结构已经很基础,但是 MySQL的Geometry结构并不是WKB。准确的说,WKB只是 MySQL的Geometry结构中的一部分。它们的差异是,MySQL的Geometry结构是在WKB之前加了4个字节,用于存储SRID。

在这里插入图片描述

还有一点需要注意的是,MySQL存储Geometry数据使用的是小顶堆。所以WKB的Byte order字段值一定是1。 有了这些知识,我们就可以定义WKB类型的TypeHandler了。

一般我们会使用 org.locationtech.jts的 Geometry类来表达几何信息。

引入依赖:

        <!--Geometry工具库依赖--><dependency><groupId>org.locationtech.jts</groupId><artifactId>jts-core</artifactId><version>1.19.0</version></dependency>

一、自定义类型处理器

项目中使用 MyBatis-Plus,自定义字段类型处理器来实现MySQL的Geometry数据处理之WKB方案。
MyBatis-Plus字段类型处理器:https://baomidou.com/guides/type-handler/

在 MyBatis 中,类型处理器(TypeHandler)扮演着 JavaType 与 JdbcType 之间转换的桥梁角色。它们用于在执行 SQL 语句时,将 Java 对象的值设置到 PreparedStatement 中,或者从 ResultSet 或 CallableStatement 中取出值。

1、完整TypeHandler类

@MappedTypes({Geometry.class})
@MappedJdbcTypes(JdbcType.BLOB)
public class GeometryTypeWKBHandler extends BaseTypeHandler<Geometry> {//private static final PrecisionModel PRECISION_MODEL = new PrecisionModel(PrecisionModel.FIXED); // 保留整数private static final PrecisionModel PRECISION_MODEL = new PrecisionModel(PrecisionModel.FLOATING); // 保留小数private static final Map<Integer, GeometryFactory> GEOMETRY_FACTORIES = new ConcurrentHashMap<>();@Overridepublic void setNonNullParameter(PreparedStatement ps, int i, Geometry parameter, JdbcType jdbcType) throws SQLException {byte[] bytes = serializeGeometry(parameter);ps.setBytes(i, bytes);}@Overridepublic Geometry getNullableResult(ResultSet rs, String columnName) throws SQLException {byte[] bytes = rs.getBytes(columnName);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}@Overridepublic Geometry getNullableResult(ResultSet rs, int columnIndex) throws SQLException {byte[] bytes = rs.getBytes(columnIndex);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}@Overridepublic Geometry getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {byte[] bytes = cs.getBytes(columnIndex);try {return deserializeGeometry(bytes);} catch (ParseException e) {throw new SQLException(e);}}/*** 序列化** @param geometry* @return*/private byte[] serializeGeometry(Geometry geometry) {int srid = geometry.getSRID();byte[] bytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN).write(geometry);return ByteBuffer.allocate(bytes.length + 4).order(ByteOrder.LITTLE_ENDIAN).putInt(srid).put(bytes).array();}/*** 反序列化** @param bytes* @return* @throws ParseException*/private static Geometry deserializeGeometry(byte[] bytes) throws ParseException {if (bytes == null) {return null;}ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);int srid = buffer.getInt();byte[] geometryBytes = new byte[buffer.remaining()];buffer.get(geometryBytes);GeometryFactory geometryFactory = GEOMETRY_FACTORIES.computeIfAbsent(srid, i -> new GeometryFactory(PRECISION_MODEL, i));WKBReader reader = new WKBReader(geometryFactory);return reader.read(geometryBytes);}}

2、序列化方法

    private byte[] serializeGeometry(Geometry geometry) {int srid = geometry.getSRID();byte[] bytes = new WKBWriter(2, ByteOrderValues.LITTLE_ENDIAN).write(geometry);return ByteBuffer.allocate(bytes.length + 4).order(ByteOrder.LITTLE_ENDIAN).putInt(srid).put(bytes).array();}

这段代码先从org.locationtech.jts.geom.Geometry中获取SRID码;

然后以小顶堆模式,使用WKBWriter将几何信息保存为WKB的二进制码。

然后申请比WKB大4个字节的空间,分别填入SRID和WKB。

这样整个内存结构就匹配Mysql内部的Geometry内存结构了。

3、反序列化方法

    private static Geometry deserializeGeometry(byte[] bytes) throws ParseException {if (bytes == null) {return null;}ByteBuffer buffer = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN);int srid = buffer.getInt();byte[] geometryBytes = new byte[buffer.remaining()];buffer.get(geometryBytes);GeometryFactory geometryFactory = GEOMETRY_FACTORIES.computeIfAbsent(srid, i -> new GeometryFactory(PRECISION_MODEL, i));WKBReader reader = new WKBReader(geometryFactory);return reader.read(geometryBytes);}

这段代码会将Mysql内部的Geometry内存结构读出来,转换成小顶堆模式。

然后获取SRID,并以此创建GeometryFactory。

剩下的内容就是WKB的内存了,最后使用WKBReader将这段内存转换成org.locationtech.jts.geom.Geometry。

二、使用自定义类型处理器

在实体类中,通过 @TableField注解指定自定义的类型处理器。

确保 @TableField注解中的属性配置正确无误,特别是value属性是否匹配数据库的实际字段名,以及
jdbcType是否正确设置为JdbcType.BLOB,因为地理空间数据通常以BLOB形式存储。

创建表SQL语句:

CREATE TABLE `t_geo_wkb` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'ID',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',`del_flag` char(1)  DEFAULT '0' COMMENT '删除标记,0未删除,1已删除',`name` varchar(255) DEFAULT NULL COMMENT '名称',`geo_type` varchar(255) DEFAULT NULL COMMENT 'geo_type',`geo` geometry NOT NULL COMMENT 'geo几何数据-GCJ02',PRIMARY KEY (`id`),SPATIAL KEY `idx_geo` (`geo`) COMMENT '空间数据索引'
) ENGINE=InnoDB  COMMENT='几何数据wkb表';

1、DO类

几何数据使用 org.locationtech.jts.geom.Geometry类型。

@Getter
@Setter
@TableName("t_geo_wkb")
public class GeoWkbDO implements Serializable {private static final long serialVersionUID = 1L;/*** ID*/@TableId(value = "id", type = IdType.AUTO)private Long id;/*** 创建时间*/@TableField("create_time")private LocalDateTime createTime;/*** 修改时间*/@TableField("update_time")private LocalDateTime updateTime;/*** 删除标记,0未删除,1已删除*/@TableField("del_flag")private String delFlag;/*** 名称*/@TableField("name")private String name;/*** geo_type*/@TableField("geo_type")private String geoType;/*** geo几何数据-GCJ02*/@TableField(value = "geo", typeHandler = GeometryTypeWKBHandler.class, jdbcType = JdbcType.BLOB)private Geometry geo;}

2、Mapper.xml

在 Mapper文件中指定 typeHandler, jdbcType。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.charge.ws.core.mapper.GeoWkbMapper"><!-- 通用查询映射结果 --><resultMap id="BaseResultMap" type="com.charge.ws.core.entity.GeoWkbDO"><id column="id" property="id"/><result column="create_time" property="createTime"/><result column="update_time" property="updateTime"/><result column="del_flag" property="delFlag"/><result column="name" property="name"/><result column="geo_type" property="geoType"/><result column="geo" property="geo" typeHandler="com.charge.ws.handler.jts.GeometryTypeWKBHandler"jdbcType="BLOB"/></resultMap><!-- 通用查询结果列 --><sql id="Base_Column_List">id, create_time, update_time, del_flag, name, geo_type, geo</sql></mapper>

使用了WKB模式,SQL就会写的很简洁,而不需要使用ST_GeomFromText和ST_AsText转来转去。可以见得WKB模式让 SQL XML变得简单。

三、注册自定义类型处理器

如果使用 @TableField注解指定自定义类型处理器没有被执行,我们就需要显式注册自定义TypeHandler。

即在配置文件或启动类中 通过 TypeHandlerRegistry注册自定义的类型处理器。

@Configuration
@MapperScan("com.xxx.mapper")
public class MyBatisPlusConfig {@Autowiredprivate SqlSessionFactory sqlSessionFactory;@Beanpublic void registerCustomTypeHandlers() {sqlSessionFactory.getConfiguration().getTypeHandlerRegistry().register(Geometry.class, // JavaTypeJdbcType.BLOB, // JdbcTypeGeometryTypeWKBHandler.class // 自定义TypeHandler);}}

四、示例测试

1、单元测试

    @Autowiredprivate GeoWkbService geoWkbService;@Autowiredprivate GeoWkbMapper geoWkbMapper;@Testpublic void testListAll() {List<GeoWkbDO> doList = geoWkbService.listAll();System.out.println(doList);}@Testpublic void testInsert1() {// 点GeometryFactory geometryFactory = new GeometryFactory();Geometry point = geometryFactory.createPoint(new Coordinate(108.939645, 34.343205));GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("点");saveDO.setGeoType("1");saveDO.setGeo(point);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert2() {// 点集合GeometryFactory geometryFactory = new GeometryFactory();LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207),new Coordinate(1, 1)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("点集合");saveDO.setGeoType("2");saveDO.setGeo(lineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert3() {// 线GeometryFactory geometryFactory = new GeometryFactory();LineString lineString = geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207),new Coordinate(2, 2), new Coordinate(3, 3)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("线");saveDO.setGeoType("3");saveDO.setGeo(lineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert4() {// 线集合GeometryFactory geometryFactory = new GeometryFactory();MultiLineString multiLineString = geometryFactory.createMultiLineString(new LineString[]{geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939645, 34.343205), new Coordinate(108.939647, 34.343207)}),geometryFactory.createLineString(new Coordinate[]{new Coordinate(108.939648, 34.343208), new Coordinate(108.939649, 34.343209)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("线集合");saveDO.setGeoType("4");saveDO.setGeo(multiLineString);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert5() {// 面GeometryFactory geometryFactory = new GeometryFactory();Polygon polygon = geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1),new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面");saveDO.setGeoType("5");saveDO.setGeo(polygon);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert6() {// 面集合GeometryFactory geometryFactory = new GeometryFactory();MultiPolygon multiPolygon = geometryFactory.createMultiPolygon(new Polygon[]{geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2),new Coordinate(3, 3), new Coordinate(1, 1)}),geometryFactory.createPolygon(new Coordinate[]{new Coordinate(4, 4), new Coordinate(5, 5),new Coordinate(6, 6), new Coordinate(4, 4)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面集合");saveDO.setGeoType("6");saveDO.setGeo(multiPolygon);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert7() {// 几何信息集合GeometryFactory geometryFactory = new GeometryFactory();GeometryCollection geometryCollection = geometryFactory.createGeometryCollection(new Geometry[]{geometryFactory.createPoint(new Coordinate(1, 1)),geometryFactory.createLineString(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2)}),geometryFactory.createPolygon(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2),new Coordinate(3, 3), new Coordinate(1, 1)})});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("几何信息集合");saveDO.setGeoType("7");saveDO.setGeo(geometryCollection);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert8() {// 面-点集合GeometryFactory geometryFactory = new GeometryFactory();MultiPoint multiPoint = geometryFactory.createMultiPointFromCoords(new Coordinate[]{new Coordinate(1, 1), new Coordinate(2, 2), new Coordinate(3, 3)});GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("面-点集合");saveDO.setGeoType("8");saveDO.setGeo(multiPoint);geoWkbMapper.insert(saveDO);}@Testpublic void testInsert9() {// linearRingGeometryFactory geometryFactory = new GeometryFactory();LinearRing linearRing = geometryFactory.createLinearRing(new Coordinate[] { new Coordinate(1, 1),new Coordinate(2, 2), new Coordinate(3, 3), new Coordinate(1, 1) });GeoWkbDO saveDO = new GeoWkbDO();saveDO.setDelFlag(CommonConstants.DELETE_FLAG_NORMAL);saveDO.setName("linearRing");saveDO.setGeoType("9");saveDO.setGeo(linearRing);geoWkbMapper.insert(saveDO);}@Testpublic void testUpdateById() {GeometryFactory geometryFactory = new GeometryFactory();Coordinate coordinate = new Coordinate(2, 2);Geometry point = geometryFactory.createPoint(coordinate);GeoWkbDO updateDO = new GeoWkbDO();updateDO.setId(1L);updateDO.setGeo(point);geoWkbMapper.updateById(updateDO);}

在这里插入图片描述

2、返回VO序列化

因为 DO定义的是 Geometry类型,业务中流转没问题,但是我们希望返回的 VO对象的这个字段为字符串格式的内容。所以,我们需要指定字段的序列化器,下面我们自定义序列化器。

(1)自定义序列化器

public class GeometrySerializer extends JsonSerializer<Object> {@Overridepublic void serialize(Object obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if (obj != null) {jsonGenerator.writeString(obj.toString());}}
}

(2)VO对象上添加序列化器

    @ApiModelProperty("geo几何数据-GCJ02")@JsonSerialize(using = GeometrySerializer.class)private Geometry geo;

在这里插入图片描述

参考文章:

  • Mysql的Geometry数据处理之WKB方案:https://fangliang.blog.csdn.net/article/details/139097706

— 求知若饥,虚心若愚。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/40662.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

qt结合vs2022安装

进入清华大学开源软件&#xff1a; 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 下载完成后&#xff0c;双击进行安装&#xff1a; 进入邮箱进行验证&#xff1a; 可能是因为网络问题&#xff0c;无法安装。 重新安装5.12.12版本。 安装后启动失败&#xff0c;重新…

横截面交易策略:概念与示例

数量技术宅团队在CSDN学院推出了量化投资系列课程 欢迎有兴趣系统学习量化投资的同学&#xff0c;点击下方链接报名&#xff1a; 量化投资速成营&#xff08;入门课程&#xff09; Python股票量化投资 Python期货量化投资 Python数字货币量化投资 C语言CTP期货交易系统开…

数据结构--单链表实现

欢迎光顾我的homepage 前言 链表和顺序表都是线性表的一种&#xff0c;但是顺序表在物理结构和逻辑结构上都是连续的&#xff0c;但链表在逻辑结构上是连续的&#xff0c;而在物理结构上不一定连续&#xff1b;来看以下图片来认识链表与顺序表的差别 这里以动态顺序表…

WGAN(Wassertein GAN)

WGAN E x ∼ P g [ log ⁡ ( 1 − D ( x ) ) ] E x ∼ P g [ − log ⁡ D ( x ) ] \begin{aligned} & \mathbb{E}_{x \sim P_g}[\log (1-D(x))] \\ & \mathbb{E}_{x \sim P_g}[-\log D(x)] \end{aligned} ​Ex∼Pg​​[log(1−D(x))]Ex∼Pg​​[−logD(x)]​ 原始 GAN …

springboot基于Java的超市进销存系统+ LW+ PPT+源码+讲解

第三章系统分析与设计 3.1 可行性分析 一个完整的系统&#xff0c;可行性分析是必须要有的&#xff0c;因为他关系到系统生存问题&#xff0c;对开发的意义进行分析&#xff0c;能否通过本网站来补充线下超市进销存管理模式中的缺限&#xff0c;去解决其中的不足等&#xff0c…

6域名系统DNS

《计算机网络》第7版&#xff0c;谢希仁 每次记不清楚的知识点&#xff0c;通过上网查找&#xff0c;总是只能看到很零碎的答案。最后还是最喜欢看这个版本的书&#xff0c;一看就回忆起来了&#xff0c;逻辑严谨&#xff0c;循循善诱&#xff0c;知识讲解的全面又清晰&#xf…

架构师应该在团队中发挥怎样的作用?

架构师分为5种&#xff1a; 1.企业架构师EA(Enterprise Architect) EA的职责是决定整个公司的技术路线和技术发展方向。 2.基础结构架构师IA(Infrastructure Architect) IA的工作就是提炼和优化技术方面积累和沉淀形成的基础性的、公共的、可复用的框架和组件&#xff0c;这…

Qt 基础组件速学 鼠标和键盘事件

学习目标&#xff1a; 鼠标事件和键盘事件应用 前置环境 运行环境:qt creator 4.12 学习内容和效果演示&#xff1a; 1.鼠标事件 根据鼠标的坐标位置&#xff0c;做出对应的事件。 2.键盘事件 根据键盘的输入做出对应操作 详细主要代码 1.鼠标事件 #include "main…

一文读懂轻量日志收集系统Loki工作原理

Loki 是由 Grafana Labs 开发的日志聚合系统&#xff0c;设计目标是提供一种高效、低成本的日志收集和查询解决方案。与传统的日志系统&#xff08;如 ELK Stack&#xff09;不同&#xff0c;Loki 不会对日志内容进行索引&#xff0c;而是仅对日志的元数据进行索引&#xff0c;…

FTP、http 、tcp

HTTP VS FTP HTTP &#xff1a;HyperText Transfer Protocol 超文本传输协议&#xff0c;是基于TCP协议 FTP&#xff1a; File Transfer Protocol 文件传输协议&#xff0c; 基于TCP协议&#xff0c; 基于UDP协议的FTP 叫做 TFTP HTTP 协议 通过一个SOCKET连接传输依次会话数…

FIND_IN_SET使用案例--[sql语句根据多ids筛选出对应数据]

一 FIND_IN_SET select id,system_ids from intellect_client_info where FIND_IN_SET(5, system_ids) > 0;

Spring Boot 中的监视器是什么?有什么作用?

前言&#xff1a; 监听器相信熟悉 Spring、Spring Boot 的都知道&#xff0c;但是监视器又是什么&#xff1f;估计很多人一脸懵的状态&#xff0c;本篇分享一下 Spring Boot 的监视器。 Spring Boot 系列文章传送门 Spring Boot 启动流程源码分析&#xff08;2&#xff09; …

Apache DolphinScheduler 与 AWS 的 EMR/Redshift 集成实践分享

引言 这篇文章将给大家讲解关于DolphinScheduler与AWS的EMR和Redshift的集成实践&#xff0c;通过本文希望大家能更深入地了解AWS智能湖仓架构&#xff0c;以及DolphinScheduler在实际应用中的重要性。 AWS智能湖仓架构 首先&#xff0c;我们来看一下AWS经典的智能湖仓架构图…

高考选专业,兴趣与就业前景该如何平衡?

从高考结束的那一刻开始&#xff0c;有些家长和学生就已经变得焦虑了&#xff0c;因为他们不知道成绩出来的时候学生应该如何填报志愿&#xff0c;也不知道选择什么样的专业&#xff0c;毕竟大学里面的专业丰富多彩&#xff0c;如何选择确实是一门学问&#xff0c;而对于学生们…

乐清网站建设规划书

乐清是位于浙江省温州市的一个县级市&#xff0c;拥有悠久的历史和丰富的文化底蕴。随着互联网的快速发展&#xff0c;网站建设成为推动乐清经济和文化发展的重要手段。因此&#xff0c;我们认为有必要制定一个全面的乐清网站建设规划书&#xff0c;以促进乐清的经济繁荣和文化…

东芝 TB5128FTG 强大性能的步进电机驱动器

TB5128FTG它以高精度和高效能为设计理念&#xff0c;采用 PWM 斩波方法&#xff0c;并内置时钟解码器。通过先进的 BiCD 工艺制造&#xff0c;这款驱动器提供高达 50V 和 5.0A 的输出额定值&#xff0c;成为广泛应用场景中的强劲解决方案。 主要特性 TB5128FTG 拥有众多确保高…

SAP PS学习笔记01 - PS概述,创建Project和WBS

本章开始学习PS&#xff08;Project System&#xff09;。 1&#xff0c;PS的概述 PS&#xff08;Project System&#xff09;是SAP企业资源规划系统中的一个关键模块&#xff0c;主要用于项目管理。 它提供了一个全面的框架来规划、控制和执行项目&#xff0c;涵盖了从项目启…

竞赛选题 卷积神经网络手写字符识别 - 深度学习

文章目录 0 前言1 简介2 LeNet-5 模型的介绍2.1 结构解析2.2 C1层2.3 S2层S2层和C3层连接 2.4 F6与C5层 3 写数字识别算法模型的构建3.1 输入层设计3.2 激活函数的选取3.3 卷积层设计3.4 降采样层3.5 输出层设计 4 网络模型的总体结构5 部分实现代码6 在线手写识别7 最后 0 前言…

C++内存的一些知识点

一、内存分区 在C中&#xff0c;内存主要分为以下几个区域&#xff1a; 代码区&#xff1a;存放函数体的二进制代码。 全局/静态存储区&#xff1a;存放全局变量和静态变量&#xff0c;这些变量在程序的整个运行期间都存在。常量存储区&#xff1a;存放常量&#xff0c;这些值…

WPF UI 界面布局 魔术棒 文字笔记识别 技能提升 布局功能扩展与自定义 继承Panel的对象,测量与排列 系列七

应用开发第一步 功能分类&#xff1a;页面上的功能区域划分。。。。需求分析 业务逻辑 数据流 功能模块 UI/UX 编码 测试 发布 功能开发与布局 不用显式的方式设定元素的尺寸 不使用屏幕坐标来指定位置 Grid 功能最强大&#xff0c;布局最灵活的容器…