#include <cmath>
#include <map>
#include <sstream>
#include <string>
using namespace std;
#include "body.h"
#include "findFile.h"
#include "Map.h"
#include "Options.h"
#include "PlanetProperties.h"
#include "Ring.h"
#include "xpUtil.h"
#include "libimage/Image.h"
#include "libplanet/Planet.h"
extern void
loadSSEC(Image *&image, const unsigned char *&rgb, string &imageFile,
const int imageWidth, const int imageHeight);
static void
loadRGB(Image *&image, const unsigned char *&rgb, string &imageFile,
const string &name, const int imageWidth, const int imageHeight,
const int shift)
{
bool foundFile = findFile(imageFile, "images");
if (foundFile)
{
image = new Image;
foundFile = image->Read(imageFile.c_str());
}
if (foundFile)
{
if ((image->Width() != imageWidth)
|| (image->Height() != imageHeight))
{
ostringstream errStr;
errStr << "Resizing " << name << " map\n"
<< "For better performance, all image maps should "
<< "be the same size as the day map\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
image->Resize(imageWidth, imageHeight);
}
if (shift != 0) image->Shift(shift);
rgb = image->getRGBData();
}
else
{
ostringstream errStr;
errStr << "Can't load map file " << imageFile << "\n";
xpWarn(errStr.str(), __FILE__, __LINE__);
}
}
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)
{
Map *m = NULL;
string imageFile(planetProperties->DayMap());
bool foundFile = findFile(imageFile, "images");
if (!foundFile)
{
string errMsg("Can't find map file ");
errMsg += imageFile;
errMsg += "\n";
xpWarn(errMsg, __FILE__, __LINE__);
}
Image *day = new Image;
foundFile = day->Read(imageFile.c_str());
if (!foundFile)
{
string errMsg("Can't load map file ");
errMsg += imageFile;
errMsg += "\n";
xpWarn(errMsg, __FILE__, __LINE__);
// If the day map isn't found, assume the other maps won't be
// found either
int xsize = (int) (pR*4);
if (xsize < 128) xsize = 128;
if (xsize > width) xsize = width;
int ysize = xsize / 2;
m = new Map(xsize, ysize, sLat, sLon,
planet, planetProperties,
ring, planetsFromSunMap);
}
else
{
int imageWidth = day->Width();
int imageHeight = day->Height();
int ishift = 0;
Options *options = Options::getInstance();
if (options->GRSSet() && planet->Index() == JUPITER)
{
double shift = (fmod(planet->Flipped()
* (options->GRSLon()/360
+ 0.5), 1.0));
shift *= imageWidth;
ishift = static_cast<int> (-shift);
if (ishift != 0 && day != NULL) day->Shift(ishift);
}
const unsigned char *dayRGB = day->getRGBData();
Image *night = NULL;
const unsigned char *nightRGB = NULL;
Image *bump = NULL;
const unsigned char *bumpRGB = NULL;
Image *cloud = NULL;
const unsigned char *cloudRGB = NULL;
Image *specular = NULL;
const unsigned char *specularRGB = NULL;
imageFile = planetProperties->NightMap();
if (!imageFile.empty() && planetProperties->Shade() < 1)
loadRGB(night, nightRGB, imageFile, "night",
imageWidth, imageHeight, ishift);
imageFile = planetProperties->BumpMap();
if (!imageFile.empty())
loadRGB(bump, bumpRGB, imageFile, "bump",
imageWidth, imageHeight, ishift);
imageFile = planetProperties->SpecularMap();
if (!imageFile.empty())
loadRGB(specular, specularRGB, imageFile, "specular",
imageWidth, imageHeight, ishift);
imageFile = planetProperties->CloudMap();
if (!imageFile.empty())
{
if (planetProperties->SSECMap())
{
loadSSEC(cloud, cloudRGB, imageFile, imageWidth, imageHeight);
}
else
{
loadRGB(cloud, cloudRGB, imageFile, "cloud",
imageWidth, imageHeight, ishift);
}
}
m = new Map(imageWidth, imageHeight,
sLat, sLon, obsLat, obsLon,
dayRGB, nightRGB, bumpRGB, specularRGB, cloudRGB,
planet, planetProperties, ring, planetsFromSunMap);
delete night;
delete bump;
delete cloud;
delete specular;
// If the map dimensions are each a power of two, the map size
// will be reduced to get rid of high-frequency noise
const double log2 = log(2.0);
double e = log((double) imageWidth) / log2;
double remainder = fabs(e - floor(e+0.5));
if (remainder < 1e-3)
{
e = log((double) imageHeight) / log2;
remainder = fabs(e - floor(e+0.5));
if (remainder < 1e-3)
{
// optimal size for image is about 4*pR x 2*pR
const double ratio = day->Height()/pR;
const int factor = (int) (log(ratio)/log2) - 1;
m->Reduce(factor);
}
}
}
delete day;
return(m);
}
syntax highlighted by Code2HTML, v. 0.9.1