-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMapExporter.cpp
183 lines (114 loc) · 5.69 KB
/
MapExporter.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <fstream>
#include <QImageWriter>
#include <QUrl>
#include <QDir>
#include "MapDB.h"
#include "config.h"
#include "MapExporter.h"
class KmzFile
{
public:
struct LayerData
{
float north_limit; // limits of the zone
float south_limit;
float east_limit;
float west_limit;
float rotation ; // rotation angle of the zone
QString image_name;
};
void writeToFile(const QString &fname) const ;
std::vector<LayerData> layers ;
};
void KmzFile::writeToFile(const QString& fname) const
{
std::ofstream o(fname.toStdString().c_str());
o << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>" << std::endl;
o << "<kml xmlns=\"http://www.opengis.net/kml/2.2\">" << std::endl;
o << " <Folder>" << std::endl;
o << " <name>Layer</name>" << std::endl;
for(uint32_t i=0;i<layers.size();++i)
{
char output[50] ;
sprintf(output,"%04d",i) ;
o << " <GroundOverlay>" << std::endl;
o << " <name>Layer " << i+1 << "</name>" << std::endl;
o << " <Icon>" << std::endl;
o << " <href>files/" << layers[i].image_name.toStdString() << "</href>" << std::endl;
o << " <drawOrder>50<drawOrder>" << std::endl; // means the map will be drawn *on top* of the existing maps
o << " </Icon>" << std::endl;
o << " <LatLonBox>" << std::endl;
o << " <north>" << layers[i].north_limit << "</north>" << std::endl;
o << " <south>" << layers[i].south_limit << "</south>" << std::endl;
o << " <east>" << layers[i].east_limit << "</east>" << std::endl;
o << " <west>" << layers[i].west_limit << "</west>" << std::endl;
o << " <rotation>" << layers[i].rotation << "</rotation>" << std::endl;
o << " </LatLonBox>" << std::endl;
o << " </GroundOverlay>" << std::endl;
}
o << " <open>1</open>" << std::endl;
o << " </Folder>" << std::endl;
o << "</kml>" << std::endl;
o.close();
}
bool MapExporter::exportMap(const MapDB::ImageSpaceCoord& bottom_left_corner,const MapDB::ImageSpaceCoord& top_right_corner,const QString& output_directory,void (*progress)(float,void*),void *data)
{
std::cerr << "Exporting map to Kmz file. Bottom left: " << bottom_left_corner << ", top right: " << top_right_corner << std::endl;
// 1 - determine how many tiles we need using the following constraints:
// * each tile should be 1024x1024 at most
// * the map accessor will teel us what is the approximate virtual resolution of the window
progress(0.0,data);
if(top_right_corner.x <= bottom_left_corner.x) return false ;
if(top_right_corner.y <= bottom_left_corner.y) return false ;
KmzFile kmzfile ;
uint32_t total_map_W = top_right_corner.x - bottom_left_corner.x ;
uint32_t total_map_H = top_right_corner.y - bottom_left_corner.y ;
if(!QDir(output_directory).mkdir("files"))
{
std::cerr << "Cannot create directory " << (output_directory+"/files/").toStdString() << std::endl;
return false;
}
float tile_size = 1024 ;
int n_tiles_x = (total_map_W + tile_size)/tile_size;
int n_tiles_y = (total_map_H + tile_size)/tile_size;
std::cerr << " Total map resolution: " << total_map_W << " x " << total_map_H << " which means " << n_tiles_x << " x " << n_tiles_y << " tiles" << std::endl;
std::cerr << " Tile size : " << tile_size << std::endl;
// 2 - re-sample each tile, write it into a file in a temporary directory
int n=0;
for(int i=0;i<n_tiles_x;++i)
for(int j=0;j<n_tiles_y;++j,++n)
{
progress((j + i*n_tiles_y)/float(n_tiles_x*n_tiles_y),data);
KmzFile::LayerData ld ;
MapDB::GPSCoord g1 ;
MapDB::GPSCoord g2 ;
MapDB::ImageSpaceCoord bottom_left(bottom_left_corner.x + i * tile_size,bottom_left_corner.y + j * tile_size);
MapDB::ImageSpaceCoord top_right (bottom_left_corner.x + (i+1) * tile_size,bottom_left_corner.y + (j+1) * tile_size);
mA.mapDB().imageSpaceCoordinatesToGPSCoordinates(bottom_left,g1) ;
mA.mapDB().imageSpaceCoordinatesToGPSCoordinates(top_right ,g2) ;
ld.west_limit = g1.lon; // limits of the zone
ld.east_limit = g2.lon;
ld.south_limit = g1.lat;
ld.north_limit = g2.lat;
ld.rotation = 0.0; // rotation angle of the zone
QImage img = mA.extractTile(bottom_left,top_right,1024,1024);
std::cerr << "Extracted " << img.width() << " x " << img.height() << " tile " << i << "," << j << " : Lat: " << g2.lat << " -> " << g1.lat << " Lon: " << g1.lon << " -> " << g2.lon << std::endl;
ld.image_name = QString("image_data_%1.jpg").arg(static_cast<int>(n),4,10,QChar('0'));
QString path = QUrl("file://"+ output_directory + "/files/" + ld.image_name).path();
if(! img.save(path,"jpg"))
std::cerr << "ERROR: Cannot save file " << path.toStdString() << std::endl;
kmzfile.layers.push_back(ld);
}
// 3 - make the zip file
kmzfile.writeToFile(output_directory + "/doc.kml");
// also export a global view of the entire zone
int ww = top_right_corner.x - bottom_left_corner.x ;
int hh = top_right_corner.y - bottom_left_corner.y ;
if(ww > 2048) { hh *= 2048/(float)ww ; ww = 2048; }
if(hh > 2048) { ww *= 2048/(float)hh ; hh = 2048; }
QImage img = mA.extractTile(bottom_left_corner,top_right_corner,ww,hh);
if(! img.save(output_directory+".jpg","jpg"))
std::cerr << "ERROR: Cannot save file " << (output_directory+".jpg").toStdString() << std::endl;
progress(1.0,data);
return true;
}