Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
map to kml
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Léo-Paul Géneau
map to kml
Commits
adcb2289
Commit
adcb2289
authored
Apr 02, 2024
by
Léo-Paul Géneau
👾
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Initial commit
parents
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
186 additions
and
0 deletions
+186
-0
map_to_kml.py
map_to_kml.py
+186
-0
No files found.
map_to_kml.py
0 → 100644
View file @
adcb2289
#!/usr/bin/env python3
"""Convert a simulator JSON map file into a klm file."""
import
argparse
import
json
import
math
import
os
import
xml.etree.ElementTree
as
ET
style_map_dict
=
{
'terrain'
:
{
'line'
:
'ff000000'
,
'poly'
:
'00ffff55'
,
},
'obstacle'
:
{
'line'
:
'ff58eeff'
,
'poly'
:
'ff58eeff'
,
},
'flag'
:
{
'line'
:
'ff7fff00'
,
'poly'
:
'ff00aa00'
,
},
}
def
lat_lon_distance
(
lat1
,
lon1
,
lat2
,
lon2
):
"""Return the distance in meters between 2 coordinates."""
q1
=
lat1
*
math
.
pi
/
180
q2
=
lat2
*
math
.
pi
/
180
dq
=
(
lat2
-
lat1
)
*
math
.
pi
/
180
dl
=
(
lon2
-
lon1
)
*
math
.
pi
/
180
a
=
math
.
sin
(
dq
/
2
)
*
math
.
sin
(
dq
/
2
)
\
+
math
.
cos
(
q1
)
*
math
.
cos
(
q2
)
*
math
.
sin
(
dl
/
2
)
*
math
.
sin
(
dl
/
2
)
c
=
2
*
math
.
atan2
(
math
.
sqrt
(
a
),
math
.
sqrt
(
1
-
a
))
return
6371e3
*
c
def
longitude_to_X
(
lon
,
map_size
):
"""Mercator projection of longitude."""
return
(
map_size
/
360
)
*
(
180
+
lon
)
def
latitude_to_Y
(
lat
,
map_size
):
"""Mercator projection latitude."""
return
(
map_size
/
180
)
*
(
90
-
lat
)
def
convert_to_local_coordinates
(
latitude
,
longitude
,
map_info
,
map_size
):
"""Convert coordinates into local values."""
x
=
longitude_to_X
(
longitude
,
map_size
)
y
=
latitude_to_Y
(
latitude
,
map_size
)
local_x
=
((
x
-
map_info
[
'min_x'
])
/
(
map_info
[
'max_x'
]
-
map_info
[
'min_x'
]))
\
*
1000
-
map_size
/
2
local_y
=
((
y
-
map_info
[
'min_y'
])
/
(
map_info
[
'max_y'
]
-
map_info
[
'min_y'
]))
\
*
1000
-
map_size
/
2
return
local_x
,
local_y
def
convert_to_geo_coordinates
(
x
,
y
,
map_info
,
map_size
):
"""Convert local values to coordinates."""
lon
=
(
x
+
map_size
/
2
)
/
1000
lon
=
lon
*
(
map_info
[
'max_x'
]
-
map_info
[
'min_x'
])
+
map_info
[
'min_x'
]
lon
=
lon
/
(
map_size
/
360
)
-
180
lat
=
(
y
+
map_size
/
2
)
/
1000
lat
=
lat
*
(
map_info
[
'max_y'
]
-
map_info
[
'min_y'
])
+
map_info
[
'min_y'
]
lat
=
90
-
lat
/
(
map_size
/
180
)
return
lon
,
lat
def
add_style_map_pair
(
style_map
,
k
,
name
):
"""Declare a style key."""
pair
=
ET
.
SubElement
(
style_map
,
'Pair'
)
key
=
ET
.
SubElement
(
pair
,
'key'
)
key
.
text
=
k
style_url
=
ET
.
SubElement
(
pair
,
'styleUrl'
)
style_url
.
text
=
'#'
+
name
def
add_style_map
(
root
,
name
,
style_dict
):
"""Define a style."""
style_map
=
ET
.
SubElement
(
root
,
'StyleMap'
,
attrib
=
{
'id'
:
name
})
for
key
in
(
'normal'
,
'highlight'
):
style_id
=
'_'
.
join
((
name
,
key
))
add_style_map_pair
(
style_map
,
key
,
style_id
)
style
=
ET
.
SubElement
(
root
,
'Style'
,
attrib
=
{
'id'
:
style_id
})
line_style
=
ET
.
SubElement
(
style
,
'LineStyle'
)
line_color
=
ET
.
SubElement
(
line_style
,
'color'
)
line_color
.
text
=
style_dict
[
'line'
]
poly_style
=
ET
.
SubElement
(
style
,
'PolyStyle'
)
poly_color
=
ET
.
SubElement
(
poly_style
,
'color'
)
poly_color
.
text
=
style_dict
[
'poly'
]
def
add_polygone
(
root
,
coordinate_tuple_list
,
style_map_id
):
"""Add a polygone to the map."""
placemark
=
ET
.
SubElement
(
root
,
'Placemark'
)
style_url
=
ET
.
SubElement
(
placemark
,
'styleUrl'
)
style_url
.
text
=
'#'
+
style_map_id
polygon
=
ET
.
SubElement
(
placemark
,
'Polygon'
)
if
coordinate_tuple_list
[
0
][
-
1
]
>
0
:
extrude
=
ET
.
SubElement
(
polygon
,
'extrude'
)
extrude
.
text
=
'1'
altitude_mode
=
ET
.
SubElement
(
polygon
,
'altitudeMode'
)
altitude_mode
.
text
=
'relativeToGround'
outer_boundary
=
ET
.
SubElement
(
polygon
,
'outerBoundaryIs'
)
linear_ring
=
ET
.
SubElement
(
outer_boundary
,
'LinearRing'
)
coordinates
=
ET
.
SubElement
(
linear_ring
,
'coordinates'
)
coordinates
.
text
=
' '
.
join
(
(
','
.
join
(
str
(
x
)
for
x
in
coor_tuple
)
for
coor_tuple
in
coordinate_tuple_list
))
def
build_rectangle
(
root
,
lat
,
lon
,
length
,
width
,
height
,
style_map_id
,
map_info
,
map_size
):
"""Build a rectangle."""
local_x
,
local_y
=
convert_to_local_coordinates
(
lat
,
lon
,
map_info
,
map_size
)
max_lon
,
_
=
convert_to_geo_coordinates
(
local_x
+
length
,
local_y
,
map_info
,
map_size
)
_
,
max_lat
=
convert_to_geo_coordinates
(
local_x
,
local_y
+
width
,
map_info
,
map_size
)
add_polygone
(
root
,
(
(
lat
,
lon
,
height
),
(
lat
,
max_lon
,
height
),
(
max_lat
,
max_lon
,
height
),
(
max_lat
,
lon
,
height
),
(
lat
,
lon
,
height
),
),
style_map_id
)
def
write_kml
(
filename
,
map_dict
):
"""Write kml file."""
root
=
ET
.
Element
(
'kml'
,
attrib
=
{
'xmlns'
:
'http://www.opengis.net/kml/2.2'
})
document
=
ET
.
SubElement
(
root
,
'Document'
)
name
=
ET
.
SubElement
(
document
,
'name'
)
name
.
text
=
filename
for
name
,
style_dict
in
style_map_dict
.
items
():
add_style_map
(
document
,
name
,
style_dict
)
add_polygone
(
document
,
(
(
map_dict
[
'min_lat'
],
map_dict
[
'min_lon'
],
0
),
(
map_dict
[
'min_lat'
],
map_dict
[
'max_lon'
],
0
),
(
map_dict
[
'max_lat'
],
map_dict
[
'max_lon'
],
0
),
(
map_dict
[
'max_lat'
],
map_dict
[
'min_lon'
],
0
),
(
map_dict
[
'min_lat'
],
map_dict
[
'min_lon'
],
0
),
),
'terrain'
)
map_size
=
math
.
ceil
(
max
(
lat_lon_distance
(
map_dict
[
'min_lat'
],
map_dict
[
'min_lon'
],
map_dict
[
'min_lat'
],
map_dict
[
'max_lon'
]),
lat_lon_distance
(
map_dict
[
'min_lat'
],
map_dict
[
'min_lon'
],
map_dict
[
'max_lat'
],
map_dict
[
'min_lon'
]),
))
map_info
=
{
'min_x'
:
longitude_to_X
(
map_dict
[
'min_lon'
],
map_size
),
'min_y'
:
latitude_to_Y
(
map_dict
[
'min_lat'
],
map_size
),
'max_x'
:
longitude_to_X
(
map_dict
[
'max_lon'
],
map_size
),
'max_y'
:
latitude_to_Y
(
map_dict
[
'max_lat'
],
map_size
),
}
for
obstacle
in
map_dict
[
'obstacle_list'
]:
position
=
obstacle
[
'position'
]
scale
=
obstacle
[
'scale'
]
rotation
=
obstacle
[
'rotation'
][
'z'
]
*
math
.
pi
/
180
build_rectangle
(
document
,
position
[
'latitude'
],
position
[
'longitude'
],
scale
[
'x'
]
*
math
.
cos
(
rotation
)
+
scale
[
'y'
]
*
math
.
sin
(
rotation
),
-
scale
[
'x'
]
*
math
.
sin
(
rotation
)
+
scale
[
'y'
]
*
math
.
cos
(
rotation
),
position
[
'altitude'
]
+
scale
[
'z'
],
'obstacle'
,
map_info
,
map_size
,
)
for
flag
in
map_dict
[
'flag_list'
]:
position
=
flag
[
'position'
]
build_rectangle
(
document
,
position
[
'latitude'
],
position
[
'longitude'
],
1
,
1
,
position
[
'altitude'
],
'flag'
,
map_info
,
map_size
)
tree
=
ET
.
ElementTree
(
root
)
ET
.
indent
(
tree
,
' '
)
tree
.
write
(
'.'
.
join
((
filename
,
'kml'
)),
encoding
=
'UTF-8'
,
xml_declaration
=
True
)
parser
=
argparse
.
ArgumentParser
(
prog
=
'map_to_kml'
,
description
=
'convert a simulator map into kml format'
)
parser
.
add_argument
(
'map_path'
)
args
=
parser
.
parse_args
()
map_filename
,
_
=
os
.
path
.
basename
(
args
.
map_path
).
split
(
'.'
)
with
open
(
args
.
map_path
)
as
map_json
:
map_json_dict
=
json
.
load
(
map_json
)
write_kml
(
map_filename
,
map_json_dict
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment