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