~ubuntu-branches/ubuntu/warty/xplanet/warty

« back to all changes in this revision

Viewing changes to src/Ring.cpp

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones
  • Date: 2004-08-24 07:14:00 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20040824071400-2dr4qnjbjmm8z3ia
Tags: 1.0.6-1ubuntu1
Build-depend: libtiff4-dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include <cstdlib>
 
2
#include <cmath>
 
3
using namespace std;
 
4
 
 
5
#include "Options.h"
 
6
#include "Ring.h"
 
7
#include "xpUtil.h"
 
8
 
 
9
#include "libplanet/Planet.h"
 
10
 
 
11
Ring::Ring(const double inner_radius, const double outer_radius, 
 
12
           const double planet_radius, 
 
13
           const double *ring_brightness, const int num_bright,
 
14
           const double *ring_transparency, const int num_trans,
 
15
           const double sunlon, const double sunlat,
 
16
           const double shade, 
 
17
           Planet *p) : planet_(p), shade_(shade)
 
18
{
 
19
    r_out = outer_radius/planet_radius;
 
20
    dr_b = (outer_radius - inner_radius) / (num_bright * planet_radius);
 
21
    dr_t = (outer_radius - inner_radius) / (num_trans * planet_radius);
 
22
 
 
23
    const int innerPadding = 100;
 
24
    const int outerPadding = 20;
 
25
    num_b = outerPadding + num_bright + innerPadding;
 
26
    num_t = outerPadding + num_trans + innerPadding;
 
27
 
 
28
    // brightness and transparency arrays are from the outside in
 
29
    radius_b = new double[num_b];
 
30
    for (int i = 0; i < num_b; i++) 
 
31
        radius_b[i] = r_out - i * dr_b;
 
32
 
 
33
    brightness = new double[num_b];
 
34
    // drop the brightness to 0 at the outer radius
 
35
    for (int i = 0; i < outerPadding; i++)
 
36
    {
 
37
        double weight = ((double) i) / (outerPadding - 1);
 
38
        brightness[i] = weight * ring_brightness[0];
 
39
    }
 
40
 
 
41
    for (int i = 0; i < num_bright; i++) 
 
42
        brightness[i + outerPadding] = ring_brightness[i];
 
43
 
 
44
    for (int i = 0; i < innerPadding; i++)
 
45
        brightness[outerPadding + num_bright + i] = ring_brightness[num_bright-1];
 
46
 
 
47
    const double cos_sun_lat = cos(sunlat);
 
48
    for (int i = 0; i < num_b; i++)
 
49
        brightness[i] *= cos_sun_lat;
 
50
 
 
51
    radius_t = new double[num_t];
 
52
    for (int i = 0; i < num_t; i++) 
 
53
        radius_t[i] = r_out - i * dr_t;
 
54
 
 
55
    transparency = new double[num_t];
 
56
    // bring the transparency up to 1 at the outer radius
 
57
    for (int i = 0; i < outerPadding; i++)
 
58
    {
 
59
        double weight = ((double) i) / (outerPadding - 1);
 
60
        transparency[i] = (1 - (1 - ring_transparency[0]) * weight);
 
61
    }
 
62
 
 
63
    for (int i = 0; i < num_trans; i++) 
 
64
        transparency[i + outerPadding] = ring_transparency[i];
 
65
 
 
66
    // bring the transparency up to 1 at the inner radius
 
67
    for (int i = 0; i < innerPadding; i++)
 
68
    {
 
69
        double weight = 1 - ((double) i) / (innerPadding - 1);
 
70
        transparency[outerPadding + num_trans + i] = (1 - (1-ring_transparency[num_trans-1]) 
 
71
                                                    * weight);
 
72
    }
 
73
 
 
74
    planet_->XYZToPlanetaryXYZ(0, 0, 0, sunX_, sunY_, sunZ_);
 
75
 
 
76
    sun_lon = sunlon;
 
77
    sun_lat = sunlat;
 
78
 
 
79
    ellipseCoeffC_ = sunZ_ / (1 - planet_->Flattening());
 
80
    ellipseCoeffC_ *= ellipseCoeffC_;
 
81
    ellipseCoeffC_ += sunY_ * sunY_;
 
82
    ellipseCoeffC_ += sunX_ * sunX_;
 
83
    ellipseCoeffC_ -= 1;
 
84
}
 
85
 
 
86
Ring::~Ring()
 
87
{
 
88
    delete [] radius_b;
 
89
    delete [] brightness;
 
90
 
 
91
    delete [] radius_t;
 
92
    delete [] transparency;
 
93
}
 
94
 
 
95
/*
 
96
  Given a subsolar point and a location on the planet surface, check
 
97
  if the surface location can be in shadow by the rings, and if so,
 
98
  return the ring radius.
 
99
*/
 
100
double
 
101
Ring::getShadowRadius(double lat, double lon)
 
102
{
 
103
    // If this point is on the same side of the rings as the sun,
 
104
    // there's no shadow.
 
105
    if(sun_lat * lat >= 0) return(-1);
 
106
 
 
107
    const double rad = planet_->Radius(lat);
 
108
    planet_->PlanetographicToPlanetocentric(lat, lon);
 
109
 
 
110
    const double x = rad * cos(lat) * cos(lon);
 
111
    const double y = rad * cos(lat) * sin(lon);
 
112
    const double z = rad * sin(lat);
 
113
 
 
114
    const double dist = z/sunZ_;
 
115
 
 
116
    const double dx = x - sunX_ * dist;
 
117
    const double dy = y - sunY_ * dist;
 
118
    
 
119
    return(sqrt(dx * dx + dy * dy));
 
120
}
 
121
 
 
122
double 
 
123
Ring::getBrightness(const double lon, const double r)
 
124
{
 
125
    return(getValue(brightness, num_b, window_b, dr_b, r, lon));
 
126
}
 
127
 
 
128
double 
 
129
Ring::getBrightness(const double lon, const double r, const double t)
 
130
{
 
131
    double returnval;
 
132
    if (t == 1.0) 
 
133
    {
 
134
        returnval = 0;
 
135
    }
 
136
    else 
 
137
    {
 
138
        returnval = getValue(transparency, num_t, window_t, dr_t, r, lon);
 
139
    }
 
140
    return(returnval);
 
141
}
 
142
 
 
143
double
 
144
Ring::getTransparency(const double r)
 
145
{
 
146
    return(getValue(transparency, num_t, window_t, dr_t, r));
 
147
}
 
148
 
 
149
double
 
150
Ring::getValue(const double *array, const int size, const int window,
 
151
               const double dr, const double r)
 
152
{
 
153
    int i = (int) ((r_out - r)/dr);
 
154
 
 
155
    if (i < 0 || i >= size) return(-1.0);
 
156
 
 
157
    int j1 = i - window;
 
158
    int j2 = i + window;
 
159
    if (j1 < 0) j1 = 0;
 
160
    if (j2 >= size) j2 = size - 1;
 
161
 
 
162
    double sum = 0;
 
163
    for (int j = j1; j < j2; j++) sum += array[j];
 
164
    sum /= (j2 - j1);
 
165
 
 
166
    return(sum);
 
167
}
 
168
 
 
169
double
 
170
Ring::getValue(const double *array, const int size, const int window,
 
171
               const double dr, const double r, const double lon)
 
172
{
 
173
    double cos_lon = cos(lon-sun_lon);
 
174
    if (cos_lon > -0.45) return(getValue(array, size, window, dr, r));
 
175
    
 
176
    int i = static_cast<int> ((r_out - r)/dr);
 
177
 
 
178
    if (i < 0 || i >= size) return(-1.0);
 
179
 
 
180
    int j1 = i - window;
 
181
    int j2 = i + window;
 
182
    const int interval = j2 - j1;
 
183
 
 
184
    if (j1 < 0) j1 = 0;
 
185
    if (j2 >= size) j2 = size - 1;
 
186
 
 
187
    double r0 = r;
 
188
    double sum = 0;
 
189
    for (int j = j1; j < j2; j++) 
 
190
    {
 
191
        const double x = r0 * cos(-lon);
 
192
        const double y = r0 * sin(-lon);
 
193
        const double z = 0;
 
194
 
 
195
        if (planet_->IsInMyShadow(x, y, z))
 
196
            sum += (shade_ * array[j]);
 
197
        else
 
198
            sum += array[j];
 
199
 
 
200
        r0 += dr;
 
201
    }
 
202
    sum /= interval;
 
203
 
 
204
    return(sum);
 
205
}
 
206
 
 
207
// units for dist_per_pixel is planetary radii
 
208
void
 
209
Ring::setDistPerPixel(const double dist_per_pixel)
 
210
{
 
211
    window_b = static_cast<int> (dist_per_pixel / dr_b + 0.5);
 
212
    window_t = static_cast<int> (dist_per_pixel / dr_t + 0.5);
 
213
 
 
214
    window_b = window_b/2 + 1;
 
215
    window_t = window_t/2 + 1;
 
216
}
 
217