1 #include <cmath>
2 #include <cstring>
3 #include <map>
4 #include <sstream>
5 #include <string>
6 using namespace std;
7
8 #include "body.h"
9 #include "findFile.h"
10 #include "Map.h"
11 #include "Options.h"
12 #include "PlanetProperties.h"
13 #include "Ring.h"
14 #include "xpUtil.h"
15
16 #include "libimage/Image.h"
17 #include "libplanet/Planet.h"
18
19 extern void
20 loadSSEC(Image *&image, const unsigned char *&rgb, string &imageFile,
21 const int imageWidth, const int imageHeight);
22
23 static void
loadRGB(Image * & image,const unsigned char * & rgb,string & imageFile,const string & name,const int imageWidth,const int imageHeight,const int shift)24 loadRGB(Image *&image, const unsigned char *&rgb, string &imageFile,
25 const string &name, const int imageWidth, const int imageHeight,
26 const int shift)
27 {
28 bool foundFile = findFile(imageFile, "images");
29 if (foundFile)
30 {
31 image = new Image;
32 foundFile = image->Read(imageFile.c_str());
33 }
34
35 if (foundFile)
36 {
37 if ((image->Width() != imageWidth)
38 || (image->Height() != imageHeight))
39 {
40 ostringstream errStr;
41 errStr << "Resizing " << name << " map\n"
42 << "For better performance, all image maps should "
43 << "be the same size as the day map\n";
44 xpWarn(errStr.str(), __FILE__, __LINE__);
45 image->Resize(imageWidth, imageHeight);
46 }
47 if (shift != 0) image->Shift(shift);
48 rgb = image->getRGBData();
49 }
50 else
51 {
52 ostringstream errStr;
53 errStr << "Can't load map file " << imageFile << "\n";
54 xpWarn(errStr.str(), __FILE__, __LINE__);
55 }
56 }
57
58 Map *
createMap(const double sLat,const double sLon,const double obsLat,const double obsLon,const int width,const int height,const double pR,Planet * planet,Ring * ring,map<double,Planet * > & planetsFromSunMap,PlanetProperties * planetProperties)59 createMap(const double sLat, const double sLon,
60 const double obsLat, const double obsLon,
61 const int width, const int height,
62 const double pR,
63 Planet *planet, Ring *ring,
64 map<double, Planet *> &planetsFromSunMap,
65 PlanetProperties *planetProperties)
66 {
67 Map *m = NULL;
68
69 string imageFile(planetProperties->DayMap());
70
71 Image *day = new Image;
72
73 bool foundFile = false;
74 if (imageFile.compare("none") != 0)
75 {
76 findFile(imageFile, "images");
77 foundFile = day->Read(imageFile.c_str());
78 }
79
80 if (!foundFile)
81 {
82 // If the day map isn't found, assume the other maps won't be
83 // found either
84
85 int xsize = (int) (pR*4);
86 if (xsize < 128) xsize = 128;
87 if (xsize > width) xsize = width;
88 int ysize = xsize / 2;
89 m = new Map(xsize, ysize, sLat, sLon,
90 planet, planetProperties,
91 ring, planetsFromSunMap);
92 }
93 else
94 {
95 int imageWidth = day->Width();
96 int imageHeight = day->Height();
97
98 int ishift = 0;
99 Options *options = Options::getInstance();
100 if (options->GRSSet() && planet->Index() == JUPITER)
101 {
102 double shift = (fmod(planet->Flipped()
103 * (options->GRSLon()/360
104 + 0.5), 1.0));
105 shift *= imageWidth;
106 ishift = static_cast<int> (-shift);
107 if (ishift != 0 && day != NULL) day->Shift(ishift);
108 }
109
110 const unsigned char *dayRGB = day->getRGBData();
111
112 Image *night = NULL;
113 const unsigned char *nightRGB = NULL;
114 Image *bump = NULL;
115 const unsigned char *bumpRGB = NULL;
116 Image *cloud = NULL;
117 const unsigned char *cloudRGB = NULL;
118 Image *specular = NULL;
119 const unsigned char *specularRGB = NULL;
120
121 imageFile = planetProperties->NightMap();
122 if (!imageFile.empty() && planetProperties->Shade() < 1)
123 loadRGB(night, nightRGB, imageFile, "night",
124 imageWidth, imageHeight, ishift);
125
126 imageFile = planetProperties->BumpMap();
127 if (!imageFile.empty())
128 loadRGB(bump, bumpRGB, imageFile, "bump",
129 imageWidth, imageHeight, ishift);
130
131 imageFile = planetProperties->SpecularMap();
132 if (!imageFile.empty())
133 loadRGB(specular, specularRGB, imageFile, "specular",
134 imageWidth, imageHeight, ishift);
135
136 imageFile = planetProperties->CloudMap();
137 if (!imageFile.empty())
138 {
139 if (planetProperties->SSECMap())
140 {
141 loadSSEC(cloud, cloudRGB, imageFile, imageWidth, imageHeight);
142 }
143 else
144 {
145 loadRGB(cloud, cloudRGB, imageFile, "cloud",
146 imageWidth, imageHeight, ishift);
147 }
148 }
149
150 m = new Map(imageWidth, imageHeight,
151 sLat, sLon, obsLat, obsLon,
152 dayRGB, nightRGB, bumpRGB, specularRGB, cloudRGB,
153 planet, planetProperties, ring, planetsFromSunMap);
154
155 delete night;
156 delete bump;
157 delete cloud;
158 delete specular;
159
160 // If the map dimensions are each a power of two, the map size
161 // will be reduced to get rid of high-frequency noise
162 const double log2 = log(2.0);
163 double e = log((double) imageWidth) / log2;
164 double remainder = fabs(e - floor(e+0.5));
165 if (remainder < 1e-3)
166 {
167 e = log((double) imageHeight) / log2;
168 remainder = fabs(e - floor(e+0.5));
169 if (remainder < 1e-3)
170 {
171 // optimal size for image is about 4*pR x 2*pR
172 const double ratio = day->Height()/pR;
173 const int factor = (int) (log(ratio)/log2) - 1;
174 m->Reduce(factor);
175 }
176 }
177 }
178
179 delete day;
180
181 return(m);
182 }
183