官网:https://www.openstreetmap.org/
1、导出按钮
2、手动选择区域
3、导出文件为osm,举例结构为
<osm version="0.6" generator="Overpass API">
<node id="1" lat="52.51631" lon="13.37777">
<tag k="amenity" v="restaurant"/>
</node>
<node id="2" lat="52.51629" lon="13.37827"/>
<node id="3" lat="52.51620" lon="13.37829"/>
<way id="1">
<nd ref="2"/>
<nd ref="3"/>
<tag k="highway" v="residential"/>
</way>
<relation id="1" visible="true" version="6" changeset="147492225" timestamp="2024-02-15T13:40:43Z" user="hdThomas" uid="9010216">
<member type="relation" ref="2" role=""/>
<member type="relation" ref="3" role=""/>
<tag k="name" v="test"/>
<tag k="network" v="hello"/>
</relation>
</osm>
4、如何通过java去进行解析
package com.jcl.birthdaydemo;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.jcl.birthdaydemo.entity.Book;
import com.jcl.birthdaydemo.entity.Category;
import com.jcl.birthdaydemo.entity.OrgPointGeo;
import com.jcl.birthdaydemo.service.IBookService;
import com.jcl.birthdaydemo.service.ICategoryService;
import com.jcl.birthdaydemo.service.service.IOrgPointGeoService;
import org.apache.commons.lang3.ObjectUtils;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 节点(Nodes):
* <p>
* 节点是 OSM 数据的基本单位,代表地图上的一个具体点。每个节点都有一个唯一的 ID 和一对经纬度坐标。
* 节点可以表示独立的地理要素,如路标、树木、邮筒等,也可以是更复杂要素(如道路、建筑物)的组成部分。
* 路径(Ways):
* <p>
* 路径是由多个节点按顺序连接而成的线性要素,可以表示道路、河流、边界等。
* 闭合的路径(首尾节点相同)通常表示面状要素,如建筑物、湖泊、公园等。
* 关系(Relations):
* <p>
* 关系用于表示更复杂的地理要素或多个要素之间的关系。一个关系可以包含多个节点和路径,并定义它们之间的关系。
* 例如,关系可以表示公交线路(由多个路径组成)或多边形(由多个路径组成的复杂区域)。
* 标签(Tags):
* <p>
* 每个节点、路径和关系都可以有若干标签,用于描述它们的属性。标签由键值对组成,例如 highway=residential 表示住宅区道路,building=yes 表示建筑物。
*/
@SpringBootTest
public class OSM {
private final static String path = "C:\\Users\\lin\\Desktop\\test.osm";
@Autowired
private IOrgPointGeoService pointGeoService;
@Test
void main() throws JsonProcessingException {
System.out.println("开始解析OSM文件...");
function4End();
}
public void function4End() {
try {
// 1. 解析XML文件
File inputFile = new File(path);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
org.w3c.dom.Document doc = builder.parse(inputFile);
// 2. 解析并写入node信息
writeNodesToFile(doc);
// 3. 解析并写入way信息
writeWaysToFile(doc);
//
// // 4. 解析并写入relation信息
writeRelationsToFile(doc);
System.out.println("OSM文件解析完成,生成了node.txt、way.txt和relation.txt文件。");
} catch (ParserConfigurationException | SAXException | IOException e) {
e.printStackTrace();
}
}
// 解析并写入node信息
public void writeNodesToFile(org.w3c.dom.Document doc) throws IOException {
FileWriter writer = new FileWriter("node-test.txt");
FileWriter writer2 = new FileWriter("node-test-sql.txt");
NodeList nodes = doc.getElementsByTagName("node");
for (int i = 0; i < nodes.getLength(); i++) {
org.w3c.dom.Element node = (org.w3c.dom.Element) nodes.item(i);
String nodeId = node.getAttribute("id");
String lat = node.getAttribute("lat");
String lon = node.getAttribute("lon");
writer.write("Node id: " + nodeId + ", lat: " + lat + ", lon: " + lon + "\n");
String nodeSql = "INSERT INTO `bodf1`.`org_point_geo`( `lat`, `lng`, `nid`) VALUES ( " + lat + ", " + lon + ", " + nodeId + ");\n";
writer2.write(nodeSql + "\n");
// 获取节点的标签(tags)
NodeList tags = node.getElementsByTagName("tag");
for (int j = 0; j < tags.getLength(); j++) {
org.w3c.dom.Element tag = (org.w3c.dom.Element) tags.item(j);
String key = tag.getAttribute("k");
String value = tag.getAttribute("v");
writer.write(" Tag key: " + key + ", value: " + value + "\n");
}
}
writer.close();
writer2.close();
}
// 解析并写入way信息
public void writeWaysToFile(org.w3c.dom.Document doc) throws IOException {
FileWriter writer = new FileWriter("way-test.txt");
FileWriter writerSql = new FileWriter("way-test-sql.txt");
FileWriter writerSql2 = new FileWriter("way-test2.txt");
NodeList ways = doc.getElementsByTagName("way");
for (int i = 0; i < ways.getLength(); i++) {
String title = null;
String bpoint = null;
String epoint = null;
boolean type = true;
StringBuilder lineInfo = new StringBuilder();
org.w3c.dom.Element way = (org.w3c.dom.Element) ways.item(i);
String wayId = way.getAttribute("id");
writer.write("Way id: " + wayId + "\n");
// 获取way的子节点(nd)
NodeList nds = way.getElementsByTagName("nd");
lineInfo.append("[");
for (int j = 0; j < nds.getLength(); j++) {
org.w3c.dom.Element nd = (org.w3c.dom.Element) nds.item(j);
String ref = nd.getAttribute("ref");
// writer.write(" Nd ref: " + ref + "\n");
LambdaQueryWrapper<OrgPointGeo> queryWrapper = new LambdaQueryWrapper<>();
OrgPointGeo pointGeoServiceOne = pointGeoService.getOne(queryWrapper.eq(OrgPointGeo::getNid, ref));
if (j == 0) {
bpoint = pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat();
} else if (j == nds.getLength() - 1) {
epoint = pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat();
lineInfo.append("[" + pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat() + "]");
} else {
lineInfo.append("[" + pointGeoServiceOne.getLng() + "," + pointGeoServiceOne.getLat() + "],");
}
}
lineInfo.append("]");
// 获取way的标签(tags)
NodeList tags = way.getElementsByTagName("tag");
for (int j = 0; j < tags.getLength(); j++) {
org.w3c.dom.Element tag = (org.w3c.dom.Element) tags.item(j);
String key = tag.getAttribute("k");
String value = tag.getAttribute("v");
writer.write(
" Tag key: " + key + ", value: " + value + "\n");
if(key.equals("name")){
title = value;
}
switch (key) {
case "highway":
type = true;
break;
case "landuse":
case "building":
case "leisure":
case "amenity":
type = false;
break;
default:
break;
}
}
String waySql;
writerSql2.write("wayId:"+wayId + " type:"+type+ " title:"+title+ " bpoint:"+bpoint+ " epoint:"+epoint + " lineInfo:"+lineInfo + "\n");
if (type) {
waySql = "INSERT INTO `bodf1`.`org_ways`( `title`, `bpoint`, `epoint`, `weight`, `lineInfo`) " +
"VALUES ( '" + title + "', '" + bpoint + "', '" + epoint + "', '0.0', '" + lineInfo + "');\n";
} else {
waySql = "INSERT INTO `bodf1`.`org_buildings`( `title`, `bpoint`, `epoint`, `weight`, `lineInfo`) " +
"VALUES ( '" + title + "', '" + bpoint + "', '" + epoint + "', '0.0', '" + lineInfo + "');\n";
}
writerSql.write(waySql);
}
writer.close();
writerSql.close();
writerSql2.close();
}
// 解析并写入relation信息
public void writeRelationsToFile(Document doc) throws IOException {
FileWriter writer = new FileWriter("relation-test.txt");
NodeList relations = doc.getElementsByTagName("relation");
for (int i = 0; i < relations.getLength(); i++) {
org.w3c.dom.Element relation = (org.w3c.dom.Element) relations.item(i);
String relationId = relation.getAttribute("id");
String visible = relation.getAttribute("visible");
String version = relation.getAttribute("version");
String changeset = relation.getAttribute("changeset");
String timestamp = relation.getAttribute("timestamp");
String user = relation.getAttribute("user");
String uid = relation.getAttribute("uid");
writer.write("Relation id: " + relationId + ", visible: " + visible + ", version: " + version +
", changeset: " + changeset + ", timestamp: " + timestamp + ", user: " + user + ", uid: " + uid + "\n");
// 获取relation的成员(members)
NodeList members = relation.getElementsByTagName("member");
for (int j = 0; j < members.getLength(); j++) {
org.w3c.dom.Element member = (org.w3c.dom.Element) members.item(j);
String type = member.getAttribute("type");
String ref = member.getAttribute("ref");
String role = member.getAttribute("role");
writer.write(" Member type: " + type + ", ref: " + ref + ", role: " + role + "\n");
}
// 获取relation的标签(tags)
NodeList tags = relation.getElementsByTagName("tag");
for (int j = 0; j < tags.getLength(); j++) {
org.w3c.dom.Element tag = (Element) tags.item(j);
String key = tag.getAttribute("k");
String value = tag.getAttribute("v");
writer.write(" Tag key: " + key + ", value: " + value + "\n");
}
}
writer.close();
}
}
5、数据库表结构sql
CREATE TABLE `org_ways` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(50) DEFAULT NULL COMMENT '名称',
`bpoint` varchar(50) DEFAULT NULL COMMENT '起始',
`epoint` varchar(50) DEFAULT NULL COMMENT '结束',
`weight` varchar(50) DEFAULT NULL COMMENT '权重',
`lineInfo` varchar(6000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '路线',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=939 DEFAULT CHARSET=utf8mb3;
CREATE TABLE `org_buildings` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(50) DEFAULT NULL COMMENT '名称',
`bpoint` varchar(50) DEFAULT NULL COMMENT '起始',
`epoint` varchar(50) DEFAULT NULL COMMENT '结束',
`weight` varchar(50) DEFAULT NULL COMMENT '权重',
`lineInfo` varchar(6000) CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci DEFAULT NULL COMMENT '路线',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=827 DEFAULT CHARSET=utf8mb3 COMMENT='建筑物信息';
CREATE TABLE `org_point_geo` (
`id` int NOT NULL AUTO_INCREMENT,
`lat` double DEFAULT NULL COMMENT '经度',
`lng` double DEFAULT NULL COMMENT '纬度',
`nid` varchar(299) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1437 DEFAULT CHARSET=utf8mb3;