新闻详情

新闻详情

首页 / 资讯中心 / 详情

内蒙古路网shp数据处理实战:从坐标系到格式转换全解析

发布时间:2026/9/25 3:37:15来源:尧图网络
内蒙古路网shp数据处理实战:从坐标系到格式转换全解析
简介内蒙古路网矢量数据shp格式是一份面向GIS开发者、交通规划师与科研工作者的空间数据集以线矢量要素完整描绘自治区内高速、国道、省道、县道等道路网络的几何路径与属性信息可用于地图制图、交通流量分析、环境影响评估及导航路径规划等场景。压缩包共7个文件约34.32MB包含.shp几何数据、.dbf属性表、.prj坐标系统、.shx索引以及.sbn/.sbx空间索引等配合ArcGIS或QGIS可完成加载、查询、编辑与密度分析等操作。该数据目前已吸引764人学习下载能有效支撑区域路网结构研究、道路规划辅助决策和专业教学演示。使用者既能获取道路等级、名称、限速等基础属性也可结合人口、土地利用等图层做综合叠加分析还可据此生成高精度道路专题地图是理解内蒙古交通格局的实用基础数据。1. 内蒙古路网矢量数据是什么拿到shp文件只是开始内蒙古路网矢量数据shp格式——这个标题乍看像一句资源下载描述但真正拿到手的任一个shp文件背后都藏着一整套从坐标系、字段设计到拓扑整理的工作。内蒙古东西跨度大路网通常按公路等级分层高速、国道、省道、县道混在一个工程里来源可能是公开下载的shp文件、规划院所发也可能是从CAD图纸用dwg转shp得到的。这个标题能解决的诉求很具体做交通规划、物流可达性分析、地图可视化或者国土项目套图时需要一套能直接用、能跟别的图层叠加、能导出给非GIS同事核对的路网数据。适合读这篇文章的是正在整理或者将要整理内蒙古路网数据的一线GIS从业者。下面按数据构成、坐标系处理、格式转换和常见坑逐一拆开讲。2. 内蒙古路网shp数据构成与选型要素类、字段、坐标系一个都不能少shp格式不是单个文件而是.shp、.shx、.dbf、.prj等一组文件的集合缺了.shx打不开缺了.dbf属性表为空缺了.prj坐标系信息丢失。选型时先要弄清三个问题要素几何类型是什么、属性字段有哪些、坐标系有没有定义。网上下载的内蒙古路网数据往往是别人从某张总图里按盟市切出来的字段可能被删过坐标系也可能在转换中被剥离拿到手先做数据体检别急着开始出图。2.1 要素几何类型与字段设计先理清路网能做什么分析内蒙古路网shp里最常见的要素是LineString也就是线要素用来表示道路中心线收费站、桥梁、里程桩可能是Point点要素服务区、互通区偶尔会做成Polygon面要素。做路网通达性分析用线做设施覆盖用点做事权划分用面三者混在一个shp里会给后续处理带来很大麻烦。传统Shapefile标准本身就不允许点线面混合存如果供应商给了一个“全要素”shp多半是把几何拆分后又强行拼装的读取时经常报错。拿到数据第一步不是打开ArcGIS看符号而是跑一段脚本快速体检。我用Python的geopandas比较多它对中文路径和GBK编码的支持比直接读dbf省事得多。import geopandas as gpd # 读取内蒙古路网shp注意dbf编码Windows下常见GBK gdf gpd.read_file(neimenggu_road.shp, encodinggbk) # 看几何类型与坐标系 print(gdf.geom_type.unique()) print(gdf.crs) # 看字段名与空值情况 print(gdf.columns.tolist()) print(gdf.isna().sum()) # 如果发现要素几何类型混杂拆分导出 roads gdf[gdf.geom_type LineString].copy() points gdf[gdf.geom_type Point].copy() roads.to_file(roads_linestring.shp, encodingutf-8) points.to_file(roads_point.shp, encodingutf-8)这段代码的逻辑是read_file把整个shp读成GeoDataFramegeom_type.unique()列出所有几何类型crs输出坐标系定义。如果crs显示为None说明.prj文件缺失后续叠加一定会出问题。isna().sum()逐列统计空值Name、RoadCode这类字段如果空得离谱得退回数据源确认是不是导出时字段映射丢了。参数上需要留意encodinggbk针对Windows下ArcGIS写的dbfLinux或QGIS另存的数据可能已经是UTF-8读出来乱码就换编码重读。拆分导出时to_file的encodingutf-8是给输出dbf用的ArcGIS打开如果中文变乱码再在QGIS里转一次GBK或者直接用后续的字段处理流程统一清洗。2.2 字段清洗与道路等级归一化地图配色与查询都靠它内蒙古路网shp的字段设计通常包含FID、Shape、ROADNAME、ROADCODE、GRADE、LENGTH、ADCODE这几类。实际数据里最乱的是GRADE字段同一份数据里能同时出现“高速”“高速公路”“高等级公路”“国道”“省道”“縣道”等写法。如果不归一化之后做分级配图、按等级统计里程、按路网做路径规划权重设置全都会因为字段取值不统一而翻车。我一般会把道路等级和道路编号一起清洗写成独立字段保留原值避免覆盖原始数据后想改没有后悔药。import pandas as pd grade_map { 高速: 高速公路, 高等级公路: 高速公路, 国道: 国道, 省道: 省道, 县道: 县道, 乡道: 乡道, } gdf[grade_std] gdf[grade].map(grade_map).fillna(gdf[grade]) # 纯数字道路编码统一补零到8位含字母编码原样保留 gdf[roadcode_std] gdf[roadcode].apply( lambda x: str(x).zfill(8) if str(x).isdigit() else str(x) ) gdf.to_file(road_clean.shp, encodingutf-8)逻辑说明map把不规范的等级名称映射成统一值fillna保留未匹配到的原始文本这样新出现的“国道G331”写法不会被误删。roadcode字段的清洗稍复杂纯数字编码像“101”会补成“00000101”方便与国省道编码表关联但“G6”“S105”这类含字母的编码如果强行zfill会变成“0000G6”反而破坏编号含义所以要先用isdigit判断。这段代码同时演示了一个重要习惯清洗结果写进新字段grade_std、roadcode_std而不是覆盖旧字段。国道、省道、县道混在一张表里时后续所有按等级的筛选、统计、配图都基于新字段原始字段留作审计对照。3. 坐标系与基础预处理CGCS2000、WGS84和投影分带怎么选内蒙古路网数据最常见的坐标系问题不是“错”而是“没定义”。供应商发来的shp经常只带.shp、.shx、.dbf没有.prj文件。ArcGIS Pro打开后软件只能凭坐标范围猜猜错后底图与路网永远叠不拢。先花十分钟确认坐标系能省掉后面所有重投影返工。3.1 判断与定义坐标系为什么两张图叠不拢内蒙古东西跨度大跨越多个高斯三度带分带不同来源数据的投影带可能不同。市面上下载的内蒙古路网shp多数已经是CGCS2000经纬度坐标也就是EPSG:4490但也会有数据源在WGS84地理坐标EPSG:4326下制作。二者在内蒙古区域平面差异虽然只有几十厘米到米级看起来不大但一旦做RTK采集点叠加或高精度断面分析差异就会暴露。判断坐标系不能只看属性表里的坐标范围必须读.prj文件或者用GDAL工具看元信息。# 查看原始shp的坐标系描述与要素类型 ogrinfo -al -so neimenggu_road.shp # 将未知坐标系强制定义为CGCS2000地理坐标系 ogr2ogr -s_srs EPSG:4490 -t_srs EPSG:4490 neimenggu_road_4490.shp neimenggu_road.shp # 直接重投影到Web墨卡托用于底图叠加 ogr2ogr -t_srs EPSG:3857 neimenggu_road_3857.shp neimenggu_road_4490.shpogrinfo -al -so只输出图层概要不遍历要素速度快它会在Layer SRS行显示坐标系名称。如果显示“UNKNOWN”说明.prj缺失。中间的ogr2ogr把源坐标系设为EPSG:4490同时目标也设为EPSG:4490作用是强制给shp打上坐标系标签几何坐标本身不变。第三句把4490重投影到EPSG:3857适合直接叠加到Web地图底图。这里有一个容易忽略的参数点EPSG:4490是CGCS2000地理坐标系单位是度直接计算道路长度会得到“度”而不是米。要做公里数统计必须把数据投影到高斯三度带或UTM。内蒙古从东到西常用的三度带中央经线在102、105、108、111、114、117、120、123、126度附近对应带号不同具体用哪个带要看数据覆盖范围。全自治区范围分析时我一般用CGCS2000 / 3-degree Gauss-Kruger CM 117E这一类大范围投影或者直接转成Albers等积投影先确保面积和长度不被扭曲到离谱。3.2 按盟市与旗县过滤属性筛选和空间裁剪两种做法内蒙古路网数据常见形态是全国路网裁出来的原图面铺得很大真正做项目时往往只需要呼伦贝尔、鄂尔多斯或者某一个旗县。此时不要用鼠标框选再导出那样容易漏边线而且不可复现。建议用属性筛选或空间裁剪生成子集保留完整处理链。# 只提取呼伦贝尔市境内的高速公路 ogr2ogr -where adcode LIKE 1507% AND grade_std 高速公路 -lco ENCODINGUTF-8 hulunbuir_highway.shp road_clean.shp # 按旗县边界空间裁剪 ogr2ogr -clipsrc erdos_border.shp -clipsrcsql SELECT * FROM erdos_border ordos_road.shp road_clean.shp-where后面的SQL过滤条件是通用做法adcode是旗县行政区划代码内蒙古各盟市有固定前缀1507开头是呼伦贝尔市1506是鄂尔多斯市这个前缀匹配比手工圈选可靠。LIKE配合%通配符能一次筛出整个盟市。空间裁剪则用-clipsrc指定一个边界shp得到严格落在边界内的路网要素。两个参数要特别说明-clipsrc裁剪后的线要素可能会在边界处被打断如果业务上需要保留完整道路线形不能直接用这个结果做连通性分析-clipsrcsql配合-clipsrc时可以只裁剪边界里某个图层避免把边界文件里的辅助线也带进来。第一次跑这种命令前我习惯先用ogrinfo确认源数据的属性字段名大小写ADCODE和adcode在dbf里不区分大小写但在SQL表达式里保持与字段定义一致最稳妥。4. 从dwg、json、excel、kml到shp四种转换实操与参数设置内蒙古路网shp很少直接以成品形态交付更多时候需要从其他格式转换而来。设计院给dwg平台导json台账放在excel外业采集发kml。每一类转换都有自己的坑下面按频率从高到低讲。4.1 dwg转shp从CAD图纸到干净路网线层做道路勘察设计的内蒙古项目原始数据基本都是CAD图纸。图纸里的道路中心线可能是多段线、样条线标注是文字块高程点是无名块。直接全图转换会把文字、标注、填充全部带进shp属性表一团糟。dwg转shp前先让设计确认分层道路中心线在哪一层、现状道路在哪一层、规划道路在哪一层。ArcGIS Pro里有“CAD转地理数据库”工具QGIS里也可以直接拖dwg加载后导出。命令行方案我反而更常用因为可以反复执行图纸更新后重新跑一遍即可。# 第一步把dwg里的道路层转成GeoPackage中间格式 ogr2ogr -f SQLite temp_road.gpkg highway.dwg Roads -nlt LINESTRING -skipfailures # 第二步从中间格式转成标准shp ogr2ogr -f ESRI Shapefile highway_road.shp temp_road.gpkg -nlt LINESTRING -lco ENCODINGUTF-8这个做法的逻辑是GDAL读取dwg时依赖Open Design Alliance驱动对复杂实体支持有限直接dwg转shp遇到无法解析的实体经常中断先转SQLite/GeoPackage中间格式再转shp可以绕开dbf对字段名的10字符限制同时保留更多几何信息。-nlt LINESTRING强制输出线要素避免图纸里的点、块参照混入结果-skipfailures跳过损坏实体让转换继续而不是整个失败。参数说明dwg里的图层名“Roads”需要在转换前用ogrinfo确认很多图纸图层叫“0”“道路中心线”或拼音图层名不匹配时输出的可能是空文件。-lco ENCODINGUTF-8解决中文属性乱码但CAD里用SHX字体写的文字块在转换后基本不可读别指望shp属性能完美保存所有标注内容。4.2 json转shp与excel点转shp两个高频轻量数据源互联网上下载的路网接口数据常常是GeoJSON格式也就是json转shp这个搜索词背后的需求。GeoJSON本身是WGS84经纬度坐标转shp后要注意坐标系重投影如果数据太大先不要急着转先用JQ或Python截取研究区范围再转换性能会好很多。import geopandas as gpd # GeoJSON转shp gdf gpd.read_file(neimenggu_road.geojson, encodingutf-8) gdf.to_file(neimenggu_road_from_json.shp, encodingutf-8, crsEPSG:4326)这段代码极简但有一个关键点to_file里的crsEPSG:4326只是给输出shp写.prj不会自动改变几何坐标。如果源GeoJSON坐标是CGCS2000经纬度但没写坐标系你要先通过to_crs转换否则几何值不变、标签错误这个错误在后续叠图时很难查出来。excel点转shp是另一个高频场景设计院发来一个收费站、服务区坐标表带“经度”“纬度”两列要转成点shp参与路网叠加。import pandas as pd import geopandas as gpd from shapely.geometry import Point # 读取Excel坐标表 df pd.read_excel(station.xlsx) geometry [Point(lon, lat) for lon, lat in zip(df[经度], df[纬度])] gdf gpd.GeoDataFrame(df, geometrygeometry, crsEPSG:4326) gdf.to_file(station.shp, encodingutf-8)逻辑说明Point(lon, lat)构造点时先经度后纬度这与“纬度在前”的常见思维相反是Excel点转shp最容易出错的点。GeoDataFrame直接从DataFrame加geometry列构建crs参数标记坐标类型不参与坐标变换。如果Excel里的经纬度是度分秒字符串必须先解析成十进制度数比如“114°3000”要转成114.5否则Point会报错或产生异常坐标。4.3 kml转shp与shp转txt反向转换的边界条件Google Earth和外业采集App导出的KML数据是公路植被调查、沿线设施采集常见的交换格式。KML坐标系一定是WGS84经纬度转shp后要重投影到CGCS2000再做空间分析。# KML转shp强制输出线要素 ogr2ogr -f ESRI Shapefile road_from_kml.shp road.kml -nlt LINESTRING -lco ENCODINGUTF-8 # shp转txt先转CSV携带WKT几何和属性 ogr2ogr -f CSV road_attr.csv road_clean.shp -lco GEOMETRYAS_WKTKML转shp时如果KML里同时混有线和面-nlt LINESTRING会强制把面退化成线这不是想要的结果稳妥做法是先转GeoPackage再按geom_type拆分。shp转txt用CSV过渡是最稳的路线-lco GEOMETRYAS_WKT把几何写成WKT文本属性字段正常输出之后用Excel另存为txt或交给内业核对。-shp转txt参数有一个容易被忽略的点CSV默认UTF-8编码Excel直接双击打开中文会乱码需要用Excel的“从文本/CSV导入”功能并选择UTF-8编码。如果数据要交给不熟悉GIS的同事我会额外用Python把属性表写成GBK编码的txt避免这一层沟通成本。5. 内蒙古路网shp踩坑记录坐标系、编码、拓扑和重复图层这一章写的是做内蒙古路网数据时反复出现的四类问题。每一条都是真实发生过的现象按“现象—原因—解决”的顺序写方便你遇到同类问题时快速定位。5.1 坑位一坐标范围正常但图层位置乱飞现象打开内蒙古路网shp属性表里的坐标值在东经110度、北纬40度附近但叠加到底图上却出现在海里或者非洲。原因原始数据是CGCS2000地理坐标系但导出时.prj文件丢失ArcGIS Pro按未知坐标系处理动态投影时无法判断于是按默认的WGS84 Web墨卡托渲染。还有一种可能是数据本身是投影坐标却被错误标记成了经纬度两道工序都叠加在一起。解决先用ogrinfo确认坐标范围如果坐标绝对值在100到130之间且是小数按经纬度处理如果坐标值在几万到几十万量级按高斯投影处理。再用前面第3章的ogr2ogr命令打上正确坐标系。注意不要在ArcGIS Pro里手动勾选“WGS 1984 Web Mercator”就完事那个只是显示投影不改变源数据坐标系定义。5.2 坑位二dbf字段中文乱码现象属性表里的道路名称显示成“璁捐矾”或者“锟斤拷”部分字段完全不可读但几何位置正常。原因Shapefile的dbf属性表在ArcGIS传统工作流下默认用GBK编码写入数据交换到QGIS或Python环境时按UTF-8解码导致乱码。反过来如果数据在QGIS里用UTF-8写入Windows版ArcGIS打开也可能乱码。解决读取时先试encodingutf-8发现乱码就换encodinggbk。输出时统一用-lco ENCODINGUTF-8并把字段名控制成英文中文内容作为属性值。这个做法能最大程度保证不同软件间流通。还有个小技巧转换后的shp最好再用QGIS打开看一遍属性表QGIS对编码处理比ArcGIS宽容能早发现乱码问题。5.3 坑位三道路在交叉口没断开现象在路网上做最短路分析一条国道和一条县道在十字路口相交设置起点和终点后路径却从外面绕了一大圈明显不对。原因dwg转shp或人工矢量化时道路线在交叉口没有打断。ArcGIS里看起来两条线交叉了但实际上它们是两条独立线段在交点处并没有共用的节点。网络分析要求路网在连通点必须有节点没有节点就等于物理上不相交。解决用ArcGIS Pro的“打断相交线”工具或者在PostGIS里用ST_Node统一打断再导出。SQL方式适合数据量大、阶段性生产的场景SELECT (ST_Dump(ST_LineMerge(ST_Node(ST_Collect(geom))))).geom AS geom FROM road_clean;这段SQL的逻辑是ST_Collect把全表线要素拼成一个MultiLineStringST_Node在所有自相交处打上节点ST_LineMerge再把相连接线段合并成更长的线ST_Dump把合并结果拆回单线。执行完后导出shp做一次网络拓扑检查确认交点处有节点。这里血泪经验是打断后要重新重建拓扑否则ArcGIS网络数据集还是可能不识别连通性。5.4 坑位四合并后道路长度翻倍现象把呼伦贝尔、包头等多盟市的shp合并成全自治区路网后统计某条国道总里程结果比官方里程数据多出将近一倍。原因分幅数据在盟市接边处存在重叠段。呼和浩特与包头交界处同一条G6高速在两个分幅里都画到了边界线合并时重复段被当作两条路统计。单纯用ArcGIS的“合并”工具不会自动去重重复几何在属性查询里也查不出来。解决合并前先按道路编码排序检查边界附近是否存在重复几何合并后用“删除相同项”工具或按空间位置删除完全重叠的要素。更稳妥的做法是合并前先用按位置选择找出与相邻盟市边界相交的线手动裁掉一侧的重叠段再执行合并。这个步骤没法完全自动化因为不同数据源的接边形式不同有的重叠几十米有的重叠几百米。6. 合并、裁切与shp转3dtiles内蒙古路网数据的进阶用法路网shp清洗完成后下一步通常是做省级拼图或按旗县切片还有一部分需求是把shp转成前端可视化用的轻量格式。多个盟市shp合并是全自治区路网拼图的基础操作。ArcGIS Pro的“合并”工具可以直接把多个shp追加进一个目标但字段结构不一致时需要先做字段映射。用Python批量处理更灵活可以顺带统一坐标系和字段编码。import glob import geopandas as gpd # 合并全自治区分幅路网 shp_list glob.glob(盟市/*.shp) gdf_list [gpd.read_file(f, encodinggbk) for f in shp_list if f.endswith(.shp)] merged gpd.pd.concat(gdf_list, ignore_indexTrue) # 按旗县边界做空间裁切并分文件夹输出 for idx, row in border.iterrows(): clipped gpd.clip(merged, row.geometry) clipped.to_file(fcounty/{row[MC]}_road.shp, encodingutf-8)这段逻辑很直白concat把多个GeoDataFrame纵向拼接gpd.clip按单个旗县边界裁切路网输出到独立文件夹。concat前必须确保所有输入的crs一致否则GeoPandas会直接抛异常如果不一致先用to_crs统一。glob匹配时要注意目录下可能有临时生成的隐藏文件用endswith过滤更保险。裁切有一个容易被业务质疑的细节跨旗县的连续道路被边界切成了两段统计每个旗县路网里程时每段都算边界处的完整里程。这在做路网密度分析时可能被评审质疑需要另外保留一条不做空间裁切、只按属性归属的版本。shp转txt的落地路径还是CSV过渡给内业同事一份带坐标的台账具体命令在第4章写过了。shp转3dtiles是这两年用得多的新方向内蒙古高速路段的三维展示场景需要把路网线转成b3dm格式。常见做法是先转GeoJSON再用CesiumLab桌面工具切片或者用py3dtiles开源库做命令行批量转换。线要素转3dtiles前要确认有没有高度字段路面是否贴合地形没有高程属性的路网只能贴地渲染不能做立交桥分层效果。初次切片建议只取一个旗县试跑参数调顺了再处理全自治区一次全量转出来的数据量容易把前端拖垮。做内蒙古路网数据这几年我最大的教训是坐标系和编码这两件事永远不能在第一步省省掉的每一步最后都会以返工补回来。每次数据交接我的习惯是先导出一张带编码字段的属性检查表发给数据提供方确认再开下一步处理比自己闷头清洗快很多。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

CEF 89 Windows32编译包与Qt 5.14.2集成:从sln到产品化实战 2026/9/25 4:12:28

CEF 89 Windows32编译包与Qt 5.14.2集成:从sln到产品化实战

简介:面向VS2017与Qt5.14.2环境的CEF二进制89版Windows 32位编译包,适合需要在Qt客户端中嵌入Chromium浏览器的C开发者。包内已通过CMake生成.sln解决方案,可直接打开运行,省去手动配置编译的繁琐步骤。资源共2275个文件&#xff…

阅读更多 →
UnityModManager安装教程:3步为游戏启用Mod支持(附5个常见坑) 2026/9/25 4:12:27

UnityModManager安装教程:3步为游戏启用Mod支持(附5个常见坑)

UnityModManager安装教程:3步为游戏启用Mod支持(附5个常见坑) 【免费下载链接】unity-mod-manager UnityModManager 项目地址: https://gitcode.com/gh_mirrors/un/unity-mod-manager UnityModManager(常简称 UMM&#xff…

阅读更多 →
ArknightsGameResource战斗系统数据解析:buff_template、battle表与[uc]lua热更脚本 2026/9/25 4:12:26

ArknightsGameResource战斗系统数据解析:buff_template、battle表与[uc]lua热更脚本

ArknightsGameResource战斗系统数据解析:buff_template、battle表与[uc]lua热更脚本 【免费下载链接】ArknightsGameResource 明日方舟客户端素材 项目地址: https://gitcode.com/gh_mirrors/ar/ArknightsGameResource ArknightsGameResource 是明日方舟客户…

阅读更多 →
AI辅助论文写作全指南:8款工具分工实测与查重率真相 2026/9/25 4:12:20

AI辅助论文写作全指南:8款工具分工实测与查重率真相

前阵子有个师弟半夜发消息问我:"师兄,网上那些AI写论文神器靠谱吗?查重率低、原创度高,真有这么神?"我反问他:你打算让AI帮你干什么?他回了一句"帮我把摘要和文献综述写了&#…

阅读更多 →
使用 AWS SDK for JavaScript (v3) 创建 AWS CodeBuild 构建项目:从示例到集成测试的实战指南 2026/9/25 4:12:20

使用 AWS SDK for JavaScript (v3) 创建 AWS CodeBuild 构建项目:从示例到集成测试的实战指南

示例工程教程后端 【免费下载链接】aws-doc-sdk-examples Welcome to the AWS Code Examples Repository. This repo contains code examples used in the AWS documentation, AWS SDK Developer Guides, and more. For more information, see the Readme.md file below. 项目地…

阅读更多 →
RSuite Affix 组件固定位置实战:top 属性、容器约束与滚动固定的底层逻辑 2026/9/25 4:12:13

RSuite Affix 组件固定位置实战:top 属性、容器约束与滚动固定的底层逻辑

前端UI组件 【免费下载链接】rsuite 🧱 A suite of React components . 项目地址: https://gitcode.com/gh_mirrors/rs/rsuite 点击查看 免费下载 导读 本文围绕 RSuite 组件库中 Affix 固定位置组件的 top 属性展开:它是 Affix 最常用的配…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉