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(new LineSegment(new Vertex(v[i][j]),
127                                           new Vertex(v[i][j+1])));
128         }
129         // close the circle
130         addLineSegment(new LineSegment(new Vertex(v[i][k-1]),
131                                        new Vertex(v[i][0])));
132      }
133
134      // Create the vertical half-circles of longitude from north to south pole.
135      for (int j = 0; j < k; j++)
136      {
137         addLineSegment(new LineSegment(new Vertex(northPole),
138                                        new Vertex(v[0][j])));
139
140         for (int i = 0; i < n - 1; i++)
141         {
142            addLineSegment(new LineSegment(new Vertex(v[i][j]),
143                                           new Vertex(v[i+1][j])));
144         }
145
146         addLineSegment(new LineSegment(new Vertex(v[n-1][j]),
147                                        new Vertex(southPole)));
148      }
149   }
150}//Sphere