001/*
002
003*/
004
005package renderer.models;
006import  renderer.scene.*;
007
008/**
009   Create a wireframe model of a frustum of a right circular cone
010   with its base in the xz-plane.
011<p>
012   See <a href="https://en.wikipedia.org/wiki/Frustum" target="_top">
013                https://en.wikipedia.org/wiki/Frustum</a>
014
015   @see Cone
016   @see ConeSector
017*/
018public class ConeFrustum extends Model
019{
020   /**
021      Create a frustum of a right circular cone with its base in the
022      xz-plane, a base radius of 1, top radius of 1/2, and height 1/2.
023   */
024   public ConeFrustum( )
025   {
026      this(1.0, 0.5, 0.5, 7, 16);
027   }
028
029
030   /**
031      Create a frustum of a right circular cone with its base in the
032      xz-plane, a base radius of {@code r1}, top radius of {@code r2},
033      and height {@code h}.
034   <p>
035      Notice that this model works with either {@code r1 > r2} or
036      {@code r1 < r2}. In other words, the frustum can have its "apex"
037      either above or below the xz-plane.
038   <p>
039      There must be at least three lines of longitude and at least
040      two circles of latitude.
041
042      @param r1  radius of the base of the frustum
043      @param r2  radius of the top of the frustum
044      @param h   height of the frustum
045      @param n   number of circles of latitude
046      @param k   number of lines of longitude
047   */
048   public ConeFrustum(double r1, double r2, double h, int n, int k)
049   {
050      super();
051
052      if (n < 2) n = 2;
053      if (k < 3) k = 3;
054
055      // Create the frustum's geometry.
056
057      double deltaTheta = (2 * Math.PI) / k;
058
059      // An array of vertices to be used to create line segments.
060      Vertex[][] v = new Vertex[n][k];
061
062      // Create all the vertices.
063      for (int j = 0; j < k; j++) // choose an angle of longitude
064      {
065         double c = Math.cos(j * deltaTheta);
066         double s = Math.sin(j * deltaTheta);
067         for (int i = 0; i < n; i++) // choose a circle of latitude
068         {
069            double slantRadius = (i/(double)(n-1)) * r1 + ((n-1-i)/(double)(n-1)) * r2;
070            v[i][j] = new Vertex( slantRadius * c,
071                                  h - (i*h)/(n-1),
072                                  slantRadius * s );
073         }
074      }
075      Vertex topCenter = new Vertex(0, h, 0);
076      Vertex bottomCenter = new Vertex(0, 0, 0);
077
078      // Create all the horizontal circles of latitude around the frustum wall.
079      for (int i = 0; i < n; i++)
080      {
081         for (int j = 0; j < k-1; j++)
082         {
083            addLineSegment(v[i][j], v[i][j+1]);
084         }
085         // close the circle
086         addLineSegment(v[i][k-1], v[i][0]);
087      }
088
089      // Create the vertical half-trapazoids of longitude from north to south pole.
090      for (int j = 0; j < k; j++)
091      {
092         // Create the triangle fan at the top.
093         addLineSegment(topCenter, v[0][j]);
094         // Create the slant lines from the top to the base.
095         addLineSegment(v[0][j], v[n-1][j]);
096         // Create the triangle fan at the base.
097         addLineSegment(v[n-1][j], bottomCenter);
098      }
099   }
100}//ConeFrustum