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.*; 011import renderer.scene.util.MeshMaker; 012 013/** 014 Create a wireframe model of a regular octahedron 015 with its center at the origin, having side length 016 {@code sqrt(2) = 1.4142},with its center plane given 017 by the four vertices {@code (±1, 0, ±1)}. and with 018 the top and bottom vertices being {@code (0, ±1, 0)}. 019<p> 020 See <a href="https://en.wikipedia.org/wiki/Octahedron" target="_top"> 021 https://en.wikipedia.org/wiki/Octahedron</a> 022 023 @see Tetrahedron 024 @see Cube 025 @see Icosahedron 026 @see Dodecahedron 027*/ 028public class Octahedron extends Model implements MeshMaker 029{ 030 public final int n1; 031 public final int n2; 032 public final int n3; 033 034 /** 035 Create a regular octahedron with its center at the 036 origin, having side length {@code sqrt(2) = 1.4142}, 037 with its center plane given by the four vertices 038 {@code (±1, 0, ±1)}. and with the top and bottom 039 vertices being {@code (0, ±1, 0)}. 040 */ 041 public Octahedron() 042 { 043 super("Octahedron"); 044 045 this.n1 = 0; 046 this.n2 = 0; 047 this.n3 = 0; 048 049 // Create the octahedron's geometry. 050 // It has 6 vertices and 12 edges. 051 addVertex(new Vertex( 1, 0, 0), // 4 vertices around the center plane 052 new Vertex( 0, 0, -1), 053 new Vertex(-1, 0, 0), 054 new Vertex( 0, 0, 1), 055 new Vertex( 0, 1, 0), // vertex at the top 056 new Vertex( 0, -1, 0)); // vertex at the bottom 057/* 058 // These vertices create an Octahedron with side length 1. 059 final double sqrt3 = Math.sqrt(3.0); 060 final double sqrt2 = Math.sqrt(2.0); 061 addVertex(new Vertex( 0.5, 0, 0.5), // 4 vertices around the center plane 062 new Vertex(-0.5, 0, 0.5), 063 new Vertex(-0.5, 0, -0.5), 064 new Vertex( 0.5, 0, -0.5), 065 new Vertex( 0, 1/sqrt2, 0), // vertex at the top 066 new Vertex( 0, -1/sqrt2, 0)); // vertex at the bottom 067*/ 068 // Create 12 line segments. 069 // Four line segments around the center plane. 070 addPrimitive(new LineSegment(0, 1), 071 new LineSegment(1, 2), 072 new LineSegment(2, 3), 073 new LineSegment(3, 0)); 074 // Edges going to the top vertex. 075 addPrimitive(new LineSegment(0, 4), 076 new LineSegment(1, 4), 077 new LineSegment(2, 4), 078 new LineSegment(3, 4)); 079 // Edges going to the bottom vertex. 080 addPrimitive(new LineSegment(0, 5), 081 new LineSegment(1, 5), 082 new LineSegment(2, 5), 083 new LineSegment(3, 5)); 084 } 085 086 087 /** 088 Create a regular octahedron with its center at the 089 origin, having side length {@code sqrt(2) = 1.4142}, 090 with its center plane given by the four vertices 091 {@code (±1, 0, ±1)}. and with the top and bottom 092 vertices being {@code (0, ±1, 0)}. 093 <p> 094 Add line segments fanning out from the top and bottom 095 vertices to the sides around the center plane. 096 097 @param n number of lines fanning out from the top and bottom on each side of the octahedron 098 @throws IllegalArgumentException if {@code n1} is less than 0 099 @throws IllegalArgumentException if {@code n2} is less than 0 100 */ 101 public Octahedron(final int n) 102 { 103 this(n, 0, 0); 104 } 105 106 107 /** 108 Create a regular octahedron with its center at the 109 origin, having side length {@code sqrt(2) = 1.4142}, 110 with its center plane given by the four vertices 111 {@code (±1, 0, ±1)}. and with the top and bottom 112 vertices being {@code (0, ±1, 0)}. 113 <p> 114 Add line segments fanning out from each vertex to 115 its opposite sides. 116 117 @param n1 number of lines fanning out from the top and bottom on each side of the octahedron 118 @param n2 number of lines fanning out from v0 and v2 on each side of the octahedron 119 @param n3 number of lines fanning out from v1 and v3 on each side of the octahedron 120 @throws IllegalArgumentException if {@code n1} is less than 0 121 @throws IllegalArgumentException if {@code n2} is less than 0 122 @throws IllegalArgumentException if {@code n3} is less than 0 123 */ 124 public Octahedron(final int n1, final int n2, final int n3) 125 { 126 this(n1, n1, n2, n2, n3, n3); 127 } 128 129 130 /** 131 Create a regular octahedron with its center at the 132 origin, having side length {@code sqrt(2) = 1.4142}, 133 with its center plane given by the four vertices 134 {@code (±1, 0, ±1)}. and with the top and bottom 135 vertices being {@code (0, ±1, 0)}. 136 <p> 137 Add line segments fanning out from each vertex to 138 its opposite sides. 139 140 @param n1a number of lines fanning out from the top on each side of the octahedron 141 @param n1b number of lines fanning out from the bottom on each side of the octahedron 142 @param n2a number of lines fanning out from v0 on each side of the octahedron 143 @param n2b number of lines fanning out from v1 on each side of the octahedron 144 @param n3a number of lines fanning out from v2 on each side of the octahedron 145 @param n3b number of lines fanning out from v3 on each side of the octahedron 146 @throws IllegalArgumentException if {@code n1a} is less than 0 147 @throws IllegalArgumentException if {@code n1b} is less than 0 148 @throws IllegalArgumentException if {@code n2a} is less than 0 149 @throws IllegalArgumentException if {@code n2b} is less than 0 150 @throws IllegalArgumentException if {@code n3a} is less than 0 151 @throws IllegalArgumentException if {@code n3b} is less than 0 152 */ 153 public Octahedron(final int n1a, final int n1b, 154 final int n2a, final int n2b, 155 final int n3a, final int n3b) 156 { 157 super(String.format("Octahedron(%d,%d,%d,%d,%d,%d)",n1a,n1b,n2a,n2b,n3a,n3b)); 158 159 if (n1a < 0) 160 throw new IllegalArgumentException("n1 must be greater than or equal to 0"); 161 if (n1b < 0) 162 throw new IllegalArgumentException("n1 must be greater than or equal to 0"); 163 if (n2a < 0) 164 throw new IllegalArgumentException("n2 must be greater than or equal to 0"); 165 if (n2b < 0) 166 throw new IllegalArgumentException("n2 must be greater than or equal to 0"); 167 if (n3a < 0) 168 throw new IllegalArgumentException("n3 must be greater than or equal to 0"); 169 if (n3b < 0) 170 throw new IllegalArgumentException("n3 must be greater than or equal to 0"); 171 172 this.n1 = n1a; 173 this.n2 = n2a; 174 this.n3 = n3a; 175 176 // Create the octahedron's geometry. 177 // It has 6 vertices and 12 edges. 178 final Vertex v0 = new Vertex( 1, 0, 0); // 4 vertices around the center plane 179 final Vertex v1 = new Vertex( 0, 0, -1); 180 final Vertex v2 = new Vertex(-1, 0, 0); 181 final Vertex v3 = new Vertex( 0, 0, 1); 182 final Vertex v4 = new Vertex( 0, 1, 0); // vertex at the top 183 final Vertex v5 = new Vertex( 0, -1, 0); // vertex at the bottom 184 addVertex(v0, v1, v2, v3, v4, v5); 185/* 186 // These vertices create an Octahedron with side length 1. 187 final double sqrt3 = Math.sqrt(3.0); 188 final double sqrt2 = Math.sqrt(2.0); 189 final Vertex v0 = new Vertex( 0.5, 0, 0.5); // 4 vertices around the center plane 190 final Vertex v1 = new Vertex(-0.5, 0, 0.5); 191 final Vertex v2 = new Vertex(-0.5, 0, -0.5); 192 final Vertex v3 = new Vertex( 0.5, 0, -0.5); 193 final Vertex v4 = new Vertex( 0, 1/sqrt2, 0); // vertex at the top 194 final Vertex v5 = new Vertex( 0, -1/sqrt2, 0); // vertex at the bottom 195 addVertex(v0, v1, v2, v3, v4, v5); 196*/ 197 // Create 12 line segments. 198 // four line segments around the center plane 199 addPrimitive(new LineSegment(0, 1), 200 new LineSegment(1, 2), 201 new LineSegment(2, 3), 202 new LineSegment(3, 0)); 203 // edges going to the top vertex 204 addPrimitive(new LineSegment(0, 4), 205 new LineSegment(1, 4), 206 new LineSegment(2, 4), 207 new LineSegment(3, 4)); 208 // edges going to the bottom vertex 209 addPrimitive(new LineSegment(0, 5), 210 new LineSegment(1, 5), 211 new LineSegment(2, 5), 212 new LineSegment(3, 5)); 213 214 fan(n1a, 4, v0, v1, v2, v3); // fan out from v4 (top) 215 fan(n1b, 5, v0, v1, v2, v3); // fan out from v5 (bottom) 216 fan(n2a, 0, v3, v4, v1, v5); // fan out from v0 217 fan(n3a, 1, v0, v4, v2, v5); // fan out from v1 218 fan(n2b, 2, v1, v4, v3, v5); // fan out from v2 219 fan(n3b, 3, v2, v4, v0, v5); // fan out from v3 220 } 221 222 223 /** 224 Create {@code n} line segments fanning out from {@link Vertex} 225 {@code v0} towards the four edges spanned by the other four 226 vertices. 227 228 @param n number of lines fanning out from {@link Vertex} {@code v0} 229 @param v0 index in the {@link Vertex} list of the vertex to fan out from 230 @param v1 a {@link Vertex} opposite to {@code v0} 231 @param v2 a {@link Vertex} opposite to {@code v0} 232 @param v3 a {@link Vertex} opposite to {@code v0} 233 @param v4 a {@link Vertex} opposite to {@code v0} 234 */ 235 private void fan(final int n, final int v0, final Vertex v1, 236 final Vertex v2, 237 final Vertex v3, 238 final Vertex v4) 239 { 240 for (int i = 0; i < n; ++i) 241 { 242 // Use linear interpolation (lerp). 243 final double t = (double)(i+1) / (double)(n+1); 244 final double x = (1-t) * v1.x + t * v2.x; 245 final double y = (1-t) * v1.y + t * v2.y; 246 final double z = (1-t) * v1.z + t * v2.z; 247 final Vertex v = new Vertex(x, y, z); 248 final int index = vertexList.size(); 249 addVertex(v); 250 addPrimitive(new LineSegment(v0, index)); 251 } 252 for (int i = 0; i < n; ++i) 253 { 254 // Use linear interpolation (lerp). 255 final double t = (double)(i+1) / (double)(n+1); 256 final double x = (1-t) * v2.x + t * v3.x; 257 final double y = (1-t) * v2.y + t * v3.y; 258 final double z = (1-t) * v2.z + t * v3.z; 259 final Vertex v = new Vertex(x, y, z); 260 final int index = vertexList.size(); 261 addVertex(v); 262 addPrimitive(new LineSegment(v0, index)); 263 } 264 for (int i = 0; i < n; ++i) 265 { 266 // Use linear interpolation (lerp). 267 final double t = (double)(i+1) / (double)(n+1); 268 final double x = (1-t) * v3.x + t * v4.x; 269 final double y = (1-t) * v3.y + t * v4.y; 270 final double z = (1-t) * v3.z + t * v4.z; 271 final Vertex v = new Vertex(x, y, z); 272 final int index = vertexList.size(); 273 addVertex(v); 274 addPrimitive(new LineSegment(v0, index)); 275 } 276 for (int i = 0; i < n; ++i) 277 { 278 // Use linear interpolation (lerp). 279 final double t = (double)(i+1) / (double)(n+1); 280 final double x = (1-t) * v4.x + t * v1.x; 281 final double y = (1-t) * v4.y + t * v1.y; 282 final double z = (1-t) * v4.z + t * v1.z; 283 final Vertex v = new Vertex(x, y, z); 284 final int index = vertexList.size(); 285 addVertex(v); 286 addPrimitive(new LineSegment(v0, index)); 287 } 288 } 289 290 291 292 // Implement the MeshMaker interface (three methods). 293 @Override public int getHorzCount() {return this.n1;} 294 295 @Override public int getVertCount() {return this.n2;} 296 297 @Override 298 public Octahedron remake(final int n, final int k) 299 { 300 return new Octahedron(n, k, this.n3); 301 } 302}//Octahedron