001/*
002 * Renderer Models. The MIT License.
003 * Copyright (c) 2022 rlkraft@pnw.edu
004 * See LICENSE for details.
005*/
006
007package renderer.models_L;
008
009import renderer.scene.*;
010import renderer.scene.primitives.*;
011
012/**
013   Create a wireframe model of a right equilateral triangular prism
014   with the y-axis as its central axis.
015<p>
016   See <a href="https://en.wikipedia.org/wiki/Triangular_prism" target="_top">
017                https://en.wikipedia.org/wiki/Triangular_prism</a>
018<p>
019   See <a href="https://en.wikipedia.org/wiki/Prism_(geometry)" target="_top">
020                https://en.wikipedia.org/wiki/Prism_(geometry)</a>
021<p>
022   Attach to each triangular end of the prism a tetrahedron.
023*/
024public class TriangularPrism extends Model
025{
026   /**
027      Create a right equilateral triangular prism with a
028      regular tetrahedrons attached to each end so that
029      the total length runs from -1 to 1 along the y-axis.
030   */
031   public TriangularPrism( )
032   {
033      this(0.5, 0.6);
034   }
035
036
037   /**
038      Create an equilateral triangular prism that runs
039      from {@code -h} to {@code h} along the y-axis, has
040      triangle side length {@code s}, and has a regular
041      tetrahedron attached to each end.
042
043      @param s  the length of the triangle's sides
044      @param h  the body of the prism runs from -h to h along the y-axis
045   */
046   public TriangularPrism(final double s, final double h)
047   {
048      this(s, h, 0);
049   }
050
051
052   /**
053      Create an equilateral triangular prism that runs
054      from {@code -h} to {@code h} along the y-axis, has
055      triangle side length {@code s}, has a regular
056      tetrahedron attached to each end, and has {@code n}
057      lines of latitude around the body of the prism.
058
059      @param s  the length of the triangle's sides
060      @param h  the body of the prism runs from -h to h along the y-axis
061      @param n  number of lines of latitude around the body of the prism
062      @throws IllegalArgumentException if {@code n} is less than 0
063   */
064   public TriangularPrism(final double s, final double h,
065                          final int n)
066   {
067      this(s/Math.sqrt(3), h, Math.atan(Math.sqrt(2)), n);
068   }
069
070
071   /**
072      Create an equilateral triangular prism that runs
073      from {@code -h} to {@code h} along the y-axis, with
074      the triangle inscribed in a circle of radius {@code r},
075      has a tetrahedron attached to each end where the
076      face-edge-face angle of each tetrahedron is {@code theta}
077      (with theta in radians!), and has {@code n} lines of
078      latitude around the body of the prism.
079   <p>
080      If {@code theta = 0}, then there are no tetrahedrons at the ends of the prism.
081   <p>
082      If {@code theta = arctan(sqrt(2)) = 54.736°}, then the tetrahedrons are regular.
083
084      @param r      radius of circle in xz-plane that the equilateral triangle is inscribed in
085      @param h      the body of the prism runs from -h to h along the y-axis
086      @param theta  slant angle of each tetrahedron at the ends of the prism
087      @param n      number of lines of latitude around the body of the prism
088      @throws IllegalArgumentException if {@code n} is less than 0
089   */
090   public TriangularPrism(final double r, final double h, final double theta,
091                          final int n)
092   {
093      this(r, h, r*Math.tan(theta), n, true);
094   }
095
096
097   /**
098      Create an equilateral triangular prism that runs
099      from {@code -h} to {@code h} along the y-axis, with
100      the triangle inscribed in a circle of radius {@code r},
101      has a tetrahedron attached to each end where the height
102      of each tetrahedron is {@code h2}, and has {@code n} lines
103      of latitude around the body of the prism.
104   <p>
105      So the total height is {@code 2*(h + h2)}.
106
107      @param r   radius of circle in xz-plane that the equilateral triangle is inscribed in
108      @param h   the body of the prism runs from h to -h in the y-direction
109      @param h2  height of each tetrahedron at the ends of the prism
110      @param n   number of lines of latitude around the body of the prism
111      @param bothHalves  determines if both halves or only the top half gets created
112      @throws IllegalArgumentException if {@code n} is less than 0
113   */
114   public TriangularPrism(final double r,
115                          final double h, final double h2,
116                          final int n,
117                          final boolean bothHalves)
118   {
119      super(String.format("Triangular Prism(%.2f,%.2f,%.2f,%d)", r, h, h2, n));
120
121      if (n < 0)
122         throw new IllegalArgumentException("n must be greater than or equal to 0");
123
124      // Create the prism's geometry.
125      final double sqrt3 = Math.sqrt(3.0);
126
127      final Vertex v0, v1, v2, v3, v4, v5, v6, v7;
128      // Three vertices around the top.
129      v0 = new Vertex( r,    h,    0);
130      v1 = new Vertex(-r/2,  h,  r*0.5*sqrt3);
131      v2 = new Vertex(-r/2,  h, -r*0.5*sqrt3);
132
133      // Three vertices around the bottom.
134      if (bothHalves)
135      {
136         v3 = new Vertex( r,   -h,    0);
137         v4 = new Vertex(-r/2, -h,  r*0.5*sqrt3);
138         v5 = new Vertex(-r/2, -h, -r*0.5*sqrt3);
139      }
140      else // ! bothHalves, so cut off the bottom half
141      {
142         v3 = new Vertex( r,    0,    0);
143         v4 = new Vertex(-r/2,  0,  r*0.5*sqrt3);
144         v5 = new Vertex(-r/2,  0, -r*0.5*sqrt3);
145      }
146
147      v6 = new Vertex(0,  h+h2, 0);  // vertex at the top
148      if (bothHalves)
149      {
150         v7 = new Vertex(0, -h-h2, 0);  // vertex at the bottom
151      }
152      else // ! bothHalves, so cut off the bottom half
153      {
154         v7 = new Vertex(0, 0, 0);   // vertex at the bottom
155      }
156      addVertex(v0, v1, v2, v3, v4, v5, v6, v7);
157      int index = 8;
158
159      // Create 15 line segments.
160      // 3 top faces
161      addPrimitive(new LineSegment(6, 0),
162                   new LineSegment(6, 1),
163                   new LineSegment(6, 2));
164      // the top edge
165      addPrimitive(new LineSegment(0, 1),
166                   new LineSegment(1, 2),
167                   new LineSegment(2, 0));
168      // three vertical edges
169      addPrimitive(new LineSegment(0, 3),
170                   new LineSegment(1, 4),
171                   new LineSegment(2, 5));
172      // the bottom edge
173      addPrimitive(new LineSegment(3, 4),
174                   new LineSegment(4, 5),
175                   new LineSegment(5, 3));
176      // 3 bottom faces
177      addPrimitive(new LineSegment(7, 3),
178                   new LineSegment(7, 4),
179                   new LineSegment(7, 5));
180
181      // Create n lines of latitude around the prism.
182      if (n > 0)
183      {
184         double delta_y = 2.0*h/(n+1);
185         if (! bothHalves)  // cut off the bottom half
186         {
187            delta_y = h/(n+1);
188         }
189
190         for (int j = 0; j < n; ++j)
191         {
192            double y = -h + (j+1) * delta_y;
193            if (! bothHalves)  // cut off the bottom half
194            {
195               y = (j+1) * delta_y;
196            }
197
198            addVertex(new Vertex( r,    y,    0),
199                      new Vertex(-r/2,  y,  r*0.5*sqrt3),
200                      new Vertex(-r/2,  y, -r*0.5*sqrt3));
201
202            addPrimitive(new LineSegment(index+0, index+1),
203                         new LineSegment(index+1, index+2),
204                         new LineSegment(index+2, index+0));
205            index += 3;
206         }
207      }
208   }
209}//TriangularPrism