package com.xiaopeng.map.utils;
|
|
import com.google.protobuf.CodedOutputStream;
|
import com.xiaopeng.map.dto.MapAreaDataDto;
|
import com.xiaopeng.map.dto.OddAreaDto;
|
import com.xiaopeng.map.dto.OddPointDto;
|
|
import java.io.FileOutputStream;
|
import java.io.IOException;
|
import java.io.OutputStream;
|
import java.util.List;
|
|
/**
|
* 将 MapAreaDataDto 序列化为与 map_area_data.proto 兼容的 Protobuf 二进制格式。
|
*/
|
public final class MapAreaDataProtoWriter {
|
|
private MapAreaDataProtoWriter() {
|
}
|
|
public static void writeTo(MapAreaDataDto data, OutputStream out) throws IOException {
|
byte[] bytes = toByteArray(data);
|
out.write(bytes);
|
}
|
|
public static byte[] toByteArray(MapAreaDataDto data) throws IOException {
|
int size = computeSize(data);
|
byte[] buf = new byte[size];
|
CodedOutputStream cos = CodedOutputStream.newInstance(buf);
|
writeMapAreaData(cos, data);
|
cos.checkNoSpaceLeft();
|
return buf;
|
}
|
|
private static int computeSize(MapAreaDataDto data) {
|
int size = 0;
|
if (data.getVersion() != 0) {
|
size += CodedOutputStream.computeUInt32Size(1, data.getVersion());
|
}
|
for (OddAreaDto area : data.getOddAreas()) {
|
int areaSize = computeOddAreaSize(area);
|
size += CodedOutputStream.computeTagSize(2) + CodedOutputStream.computeRawVarint32Size(areaSize) + areaSize;
|
}
|
return size;
|
}
|
|
private static int computeOddAreaSize(OddAreaDto area) {
|
int size = 0;
|
if (area.getOddId() != 0) {
|
size += CodedOutputStream.computeUInt32Size(1, area.getOddId());
|
}
|
for (OddPointDto pt : area.getOddPoints()) {
|
int ptSize = computeOddPointSize(pt);
|
size += CodedOutputStream.computeTagSize(2) + CodedOutputStream.computeRawVarint32Size(ptSize) + ptSize;
|
}
|
if (area.isBlacklist()) {
|
size += CodedOutputStream.computeBoolSize(3, true);
|
}
|
return size;
|
}
|
|
private static int computeOddPointSize(OddPointDto pt) {
|
int size = 0;
|
if (pt.getLatitude() != 0.0) {
|
size += CodedOutputStream.computeDoubleSize(1, pt.getLatitude());
|
}
|
if (pt.getLongitude() != 0.0) {
|
size += CodedOutputStream.computeDoubleSize(2, pt.getLongitude());
|
}
|
return size;
|
}
|
|
private static void writeMapAreaData(CodedOutputStream cos, MapAreaDataDto data) throws IOException {
|
cos.writeUInt32(1, data.getVersion());
|
for (OddAreaDto area : data.getOddAreas()) {
|
cos.writeTag(2, 2); // field 2, wire type length-delimited
|
int areaSize = computeOddAreaSize(area);
|
cos.writeRawVarint32(areaSize);
|
writeOddArea(cos, area);
|
}
|
}
|
|
private static void writeOddArea(CodedOutputStream cos, OddAreaDto area) throws IOException {
|
cos.writeUInt32(1, area.getOddId());
|
List<OddPointDto> points = area.getOddPoints();
|
for (OddPointDto pt : points) {
|
cos.writeTag(2, 2);
|
int ptSize = computeOddPointSize(pt);
|
cos.writeRawVarint32(ptSize);
|
writeOddPoint(cos, pt);
|
}
|
if (area.isBlacklist()) {
|
cos.writeBool(3, true);
|
}
|
}
|
|
private static void writeOddPoint(CodedOutputStream cos, OddPointDto pt) throws IOException {
|
cos.writeDouble(1, pt.getLatitude());
|
cos.writeDouble(2, pt.getLongitude());
|
}
|
|
/**
|
* 测试入口:使用 XngpAreaRTreeFbsUtil 的示例 GCL 数据生成 map_area_data 文件。
|
*/
|
public static void main(String[] args) {
|
String gcl = "104.06249657558965_30.583221674855963," +
|
"104.06244328689024_30.58049965528362," +
|
"104.06640444191817_30.580606702069797," +
|
"104.06496563619123_30.58420035984882," +
|
"104.06249657558965_30.583221674855963";
|
|
List<XngpAreaRTreeFbsUtil.LonLat> points = XngpAreaRTreeFbsUtil.parseGcl(gcl);
|
if (points.isEmpty()) {
|
System.err.println("parseGcl failed: no points");
|
return;
|
}
|
|
OddAreaDto oddArea = OddAreaDto.builder()
|
.oddId(1)
|
.isBlacklist(false)
|
.build();
|
for (XngpAreaRTreeFbsUtil.LonLat p : points) {
|
oddArea.getOddPoints().add(OddPointDto.builder()
|
.latitude(p.getLat())
|
.longitude(p.getLon())
|
.build());
|
}
|
|
MapAreaDataDto data = MapAreaDataDto.builder()
|
.version(1)
|
.oddAreas(java.util.Collections.singletonList(oddArea))
|
.build();
|
|
String outFile = "map_area_data_test.bin";
|
try (FileOutputStream fos = new FileOutputStream(outFile)) {
|
MapAreaDataProtoWriter.writeTo(data, fos);
|
System.out.println("MapAreaDataProtoWriter success, outFile=" + outFile);
|
} catch (IOException e) {
|
System.err.println("MapAreaDataProtoWriter failed: " + e.getMessage());
|
}
|
}
|
}
|