6
#include "libdisplay/libdisplay.h"
7
#include "libplanet/Planet.h"
10
drawEllipsoid(const double pX, const double pY, const double pR,
11
const double oX, const double oY, const double oZ,
12
const double X, const double Y, const double Z,
14
const View *view, const Map *map, Planet *planet,
15
const double planetRadius)
18
unsigned char color[3];
21
const int j1 = display->Height();
23
const int i1 = display->Width();
25
// P1 (Observer) is at (oX, oY, oZ), or (0, 0, 0) in view
27
// P2 (current pixel) is on the line from P1 to (vX, vY, vZ)
28
// P3 (Planet center) is at (X, Y, Z) in heliocentric rectangular
29
// Now find the intersection of the line with the planet's ellipsoid.
31
// Define a new coordinate system: planetary XYZ
32
// X = 0 lon, Z = north pole, Y = Z x X
33
// Convert P1, P2, P3 to planetary XYZ:
34
// 1) Convert to planetocentric
35
// 2) Convert to planetary XYZ (units of planetary radius)
37
double p1X = 0, p1Y = 0, p1Z = 0;
38
double p2X = 0, p2Y = 0, p2Z = 0;
39
double p3X = 0, p3Y = 0, p3Z = 0;
41
const double ratio = 1/(1 - planet->Flattening());
43
planet->XYZToPlanetaryXYZ(oX, oY, oZ, p1X, p1Y, p1Z);
46
const double c = 2 * (dot(p1X - p3X, p1Y - p3Y, p1Z - p3Z,
47
p1X - p3X, p1Y - p3Y, p1Z - p3Z)
48
- planetRadius * planetRadius);
50
Options *options = Options::getInstance();
52
// compute the value of the determinant at the center of the body
53
view->PixelToViewCoordinates(options->getCenterX() - pX,
54
options->getCenterY() - pY,
57
view->RotateToXYZ(p2X, p2Y, p2Z, p2X, p2Y, p2Z);
58
planet->XYZToPlanetaryXYZ(p2X, p2Y, p2Z, p2X, p2Y, p2Z);
60
const double centerA = 2 * (dot(p2X - p1X, p2Y - p1Y, p2Z - p1Z,
61
p2X - p1X, p2Y - p1Y, p2Z - p1Z));
62
const double centerB = 2 * (dot(p2X - p1X, p2Y - p1Y, p2Z - p1Z,
63
p1X - p3X, p1Y - p3Y, p1Z - p3Z));
64
const double centerDet = centerB * centerB - centerA * c;
66
for (int j = j0; j < j1; j++)
68
for (int i = i0; i < i1; i++)
70
const double dX = options->getCenterX() - i;
71
const double dY = options->getCenterY() - j;
73
view->PixelToViewCoordinates(dX, dY, p2X, p2Y, p2Z);
75
view->RotateToXYZ(p2X, p2Y, p2Z, p2X, p2Y, p2Z);
76
planet->XYZToPlanetaryXYZ(p2X, p2Y, p2Z, p2X, p2Y, p2Z);
79
const double a = 2 * (dot(p2X - p1X, p2Y - p1Y, p2Z - p1Z,
80
p2X - p1X, p2Y - p1Y, p2Z - p1Z));
81
const double b = 2 * (dot(p2X - p1X, p2Y - p1Y, p2Z - p1Z,
82
p1X - p3X, p1Y - p3Y, p1Z - p3Z));
83
const double determinant = b*b - a * c;
85
if (determinant < 0) continue;
87
double u = -(b + sqrt(determinant));
90
// coordinates of the intersection point
92
iX = p1X + u * (p2X - p1X);
93
iY = p1Y + u * (p2Y - p1Y);
94
iZ = p1Z + u * (p2Z - p1Z);
98
planet->PlanetaryXYZToXYZ(iX, iY, iZ, iX, iY, iZ);
99
planet->XYZToPlanetographic(iX, iY, iZ, lat, lon);
101
map->GetPixel(lat, lon, color);
102
double darkening = ndot(X - iX, Y - iY, Z - iZ,
103
X - oX, Y - oY, Z - oZ);
107
darkening = sqrt(darkening);
109
for (int k = 0; k < 3; k++)
110
color[k] = static_cast<unsigned char> (color[k]
113
if (pR * determinant/centerDet < 10)
115
opacity = 1 - pow(1-determinant/centerDet, pR);
117
display->setPixel(i, j, color, opacity);