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