001/* 002 003*/ 004 005package renderer.models; 006import renderer.scene.*; 007 008/** 009 Create a wireframe model of a 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 A sphere of radius {@code r} is the surface of revolution generated by 015 revolving a half-circle in the xy-plane with radius {@code r} and center 016 {@code (0,0,0)} around the y-axis. 017<p> 018 Here are parametric equations for the right half-circle in the xy-plane with 019 radius {@code r} and center {@code (0,0,0)}, parameterized from the top down. 020 <pre>{@code 021 x(phi) = r * sin(phi) \ 022 y(phi) = r * cos(phi) |- 0 <= phi <= PI 023 z(phi) = 0 / 024 }</pre> 025 Here is the 3D rotation matrix that rotates around the y-axis 026 by {@code theta} radians, {@code 0 <= theta <= 2*PI} 027 <pre>{@code 028 [ cos(theta) 0 sin(theta)] 029 [ 0 1 0 ] 030 [-sin(theta) 0 cos(theta)] 031 }</pre> 032 If we multiply the rotation matrix with the half-circle 033 parameterization, we get a parameterization of the sphere. 034 <pre>{@code 035 [ cos(theta) 0 sin(theta)] [r * sin(phi)] 036 [ 0 1 0 ] * [r * cos(phi)] 037 [-sin(theta) 0 cos(theta)] [ 0 ] 038 039 = ( r * sin(phi) * cos(theta). \ 040 r * cos(phi), |- 0<=theta<=2*PI, 0<=phi<=PI 041 -r * sin(phi) * sin(theta) ) / 042 }</pre> 043 See 044 <a href="https://en.wikipedia.org/wiki/Sphere#Equations_in_three-dimensional_space" target="_top"> 045 https://en.wikipedia.org/wiki/Sphere#Equations_in_three-dimensional_space</a> 046 047 @see SphereSector 048*/ 049public class Sphere extends Model 050{ 051 /** 052 Create a sphere of radius 1 centered at the origin. 053 */ 054 public Sphere( ) 055 { 056 this(1, 15, 16); 057 } 058 059 060 /** 061 Create a sphere of radius {@code r} centered at the origin. 062 063 @param r radius of the sphere 064 */ 065 public Sphere(double r) 066 { 067 this(r, 15, 16); 068 } 069 070 071 /** 072 Create a sphere of radius {@code r} centered at the origin. 073 <p> 074 The last two parameters determine the number of half circles 075 of longitude and the number of circles of latitude in the model. 076 <p> 077 Notice that if there are {@code k} half circles of longitude, 078 then each circle of latitude will have {@code k} line segments. 079 If there are {@code n} circles of latitude, then each half circle 080 of longitude will have {@code n+1} line segments. 081 <p> 082 There must be at least three half circles of longitude and 083 at least one circle of latitude. 084 085 @param r radius of the sphere 086 @param n number of circles of latitude 087 @param k number of half circles of longitude 088 */ 089 public Sphere(double r, int n, int k) 090 { 091 super(); 092 093 if (n < 1) n = 1; 094 if (k < 3) k = 3; 095 096 // Create the sphere's geometry. 097 098 double deltaPhi = Math.PI / (n + 1); 099 double deltaTheta = (2 * Math.PI) / k; 100 101 // An array of vertices to be used to create line segments. 102 Vertex[][] v = new Vertex[n][k]; 103 104 // Create all the vertices. 105 for (int j = 0; j < k; j++) // choose an angle of longitude 106 { 107 double c1 = Math.cos(j * deltaTheta); 108 double s1 = Math.sin(j * deltaTheta); 109 for (int i = 0; i < n; i++) // choose an angle of latitude 110 { 111 double c2 = Math.cos(deltaPhi + i * deltaPhi); 112 double s2 = Math.sin(deltaPhi + i * deltaPhi); 113 v[i][j] = new Vertex( r * s2 * c1, 114 r * c2, 115 -r * s2 * s1 ); 116 } 117 } 118 Vertex northPole = new Vertex(0, r, 0); 119 Vertex southPole = new Vertex(0, -r, 0); 120 121 // Create the horizontal circles of latitude around the sphere. 122 for (int i = 0; i < n; i++) 123 { 124 for (int j = 0; j < k - 1; j++) 125 { 126 addLineSegment(v[i][j], v[i][j+1]); 127 } 128 // close the circle 129 addLineSegment(v[i][k-1], v[i][0]); 130 } 131 132 // Create the vertical half-circles of longitude from north to south pole. 133 for (int j = 0; j < k; j++) 134 { 135 addLineSegment(northPole, v[0][j]); 136 137 for (int i = 0; i < n - 1; i++) 138 { 139 addLineSegment(v[i][j], v[i+1][j]); 140 } 141 142 addLineSegment(v[n-1][j], southPole); 143 } 144 } 145}//Sphere