001/* 002 003*/ 004 005package renderer.models; 006import renderer.scene.*; 007 008/** 009 Create a wireframe model of a partial sphere centered at the origin 010<p> 011 See <a href="https://en.wikipedia.org/wiki/Sphere" target="_top"> 012 https://en.wikipedia.org/wiki/Sphere</a> 013<p> 014 By a partial sphere we mean cutting a hole in the sphere around 015 either the north or the south pole (that is, removing a spherical 016 cap from either the top or bottom of the sphere) and also cutting 017 from the sphere a spherical wedge between two lines of longitude. 018<p> 019 Notice that we can use this model to both model a spherical wedge 020 and to model a sphere with a spherical wedge removed from it. 021<p> 022 Similarly, we can use this model to both model a spherical cap 023 and to model a sphere with a spherical cap removed from it. 024<p> 025 See <a href="https://en.wikipedia.org/wiki/Spherical_cap" target="_top"> 026 https://en.wikipedia.org/wiki/Spherical_cap</a> 027<p> 028 See <a href="https://en.wikipedia.org/wiki/Spherical_segment" target="_top"> 029 https://en.wikipedia.org/wiki/Spherical_segment</a> 030<p> 031 See <a href="https://en.wikipedia.org/wiki/Spherical_wedge" target="_top"> 032 https://en.wikipedia.org/wiki/Spherical_wedge</a> 033<p> 034 The whole sphere of radius {@code r} is the surface of revolution generated 035 by revolving the right half-circle in the xy-plane with radius {@code r} and 036 center {@code (0,0,0)} all the way around the y-axis. 037<p> 038 Here are parametric equations for the right half-circle in the xy-plane with 039 radius {@code r} and center {@code (0,0,0)}, parameterized from the top down. 040 <pre>{@code 041 x(phi) = r * sin(phi) \ 042 y(phi) = r * cos(phi) |- 0 <= phi <= PI 043 z(phi) = 0 / 044 }</pre> 045 Here is the 3D rotation matrix that rotates around the y-axis 046 by {@code theta} radians, {@code 0 <= theta <= 2*PI} 047 <pre>{@code 048 [ cos(theta) 0 sin(theta)] 049 [ 0 1 0 ] 050 [-sin(theta) 0 cos(theta)] 051 }</pre> 052 If we multiply the rotation matrix with the half-circle 053 parameterization, we get a parameterization of the sphere. 054 <pre>{@code 055 [ cos(theta) 0 sin(theta)] [r * sin(phi)] 056 [ 0 1 0 ] * [r * cos(phi)] 057 [-sin(theta) 0 cos(theta)] [ 0 ] 058 059 = ( r * sin(phi) * cos(theta). \ 060 r * cos(phi), |- 0<=theta<=2*PI, 0<=phi<=PI 061 -r * sin(phi) * sin(theta) ) / 062 }</pre> 063 See 064 <a href="https://en.wikipedia.org/wiki/Sphere#Equations_in_three-dimensional_space" target="_top"> 065 https://en.wikipedia.org/wiki/Sphere#Equations_in_three-dimensional_space</a> 066 067 @see Sphere 068*/ 069public class SphereSector extends Model 070{ 071 /** 072 Create half of a sphere of radius 1 centered at the origin. 073 */ 074 public SphereSector() 075 { 076 this(1, Math.PI/2, 3*Math.PI/2, 15, 8); 077 } 078 079 080 /** 081 Create a part of the sphere of radius r centered at the origin. 082 <p> 083 If {@code theta1 > 0} or {@code theta2 < 2*PI}, then a spherical 084 wedge is removed from the model. In other words, the (partial) 085 circles of latitude in the model extend from angle {@code theta1} 086 to angle {@code theta2}. 087 <p> 088 The last two parameters determine the number of half circles of 089 longitude and the number of (partial) circles of latitude in the model. 090 <p> 091 Notice that if there are {@code k} half circles of longitude, then 092 each (partial) circle of latitude will have {@code k-1} line segments. 093 If there are {@code n} circles of latitude, then each half circle of 094 longitude will have {@code n+1} line segments. 095 <p> 096 There must be at least four half circles of longitude and 097 at least one circle of latitude. 098 099 @param r radius of the sphere 100 @param theta1 beginning longitude angle of the spherical wedge 101 @param theta2 ending longitude angle of the spherical wedge 102 @param n number of circles of latitude 103 @param k number of lines of longitude, not counting the edges of a spherical wedge 104 */ 105 public SphereSector(double r, double theta1, double theta2, 106 int n, int k) 107 { 108 this(r, theta1, theta2, 0, Math.PI, n+2, k); 109 } 110 111 112 /** 113 Create a part of the sphere of radius r centered at the origin. 114 <p> 115 If {@code phi1 > 0}, then there is hole in the sphere around its 116 north pole. Similarly, if {@code phi2 < PI}, then there is a hole 117 in the sphere around its south pole. In other words, in spherical 118 coordinates, lines of longitude in the model extend from angle 119 {@code phi1} to angle {@code phi2}. 120 <p> 121 If {@code theta1 > 0} or {@code theta2 < 2*PI}, then a spherical 122 wedge is removed from the model. In other words, the (partial) 123 circles of latitude in the model extend from angle {@code theta1} 124 to angle {@code theta2}. 125 <p> 126 The last two parameters determine the number of lines of longitude 127 and the number of (partial) circles of latitude in the model. 128 <p> 129 Notice that if there are {@code k} lines of longitude, then each 130 (partial) circle of latitude will have {@code k-1} line segments. 131 If there are {@code n} circles of latitude (including the edges of 132 the removed spherical caps), then each line of longitude will have 133 {@code n-1} line segments. 134 <p> 135 There must be at least four lines of longitude and at least 136 three circles of latitude. 137 138 @param r radius of the sphere 139 @param theta1 beginning longitude angle of the spherical wedge 140 @param theta2 ending longitude angle of the spherical wedge 141 @param phi1 beginning latitude angle of the spherical segment 142 @param phi2 ending latitude angle of the spherical segment 143 @param n number of circles of latitude, not counting the edges of a spherical segment 144 @param k number of lines of longitude, not counting one edge of a spherical wedge 145 */ 146 public SphereSector(double r, 147 double theta1, double theta2, 148 double phi1, double phi2, 149 int n, int k) 150 { 151 super(); 152 153 if (n < 3) n = 3; 154 if (k < 4) k = 4; 155 156 // Create the sphere section's geometry. 157 158 double deltaPhi = (phi2 - phi1) / (n - 1); 159 double deltaTheta = (theta2 - theta1) / (k - 1); 160 161 // An array of vertices to be used to create line segments. 162 Vertex[][] v = new Vertex[n][k]; 163 164 // Create all the vertices. 165 for (int j = 0; j < k; j++) // choose an angle of longitude 166 { 167 double c1 = Math.cos(theta1 + j * deltaTheta); 168 double s1 = Math.sin(theta1 + j * deltaTheta); 169 for (int i = 0; i < n; i++) // choose an angle of latitude 170 { 171 double c2 = Math.cos(phi1 + i * deltaPhi); 172 double s2 = Math.sin(phi1 + i * deltaPhi); 173 v[i][j] = new Vertex( r * s2 * c1, 174 r * c2, 175 -r * s2 * s1 ); 176 } 177 } 178 179 // Create the horizontal (partial) circles of latitude around the sphere. 180 for (int i = 0; i < n; i++) 181 { 182 for (int j = 0; j < k - 1; j++) 183 { 184 addLineSegment(v[i][j], v[i][j+1]); 185 } 186 } 187 188 // Create the vertical lines of longitude from the top edge to the bottom edge. 189 for (int j = 0; j < k; j++) 190 { 191 for (int i = 0; i < n - 1; i++) 192 { 193 addLineSegment(v[i][j], v[i+1][j]); 194 } 195 } 196 } 197}//SphereSector