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