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 ring (an annulus) 015 in the xy-plane centered at the origin. 016<p> 017 See <a href="https://en.wikipedia.org/wiki/Annulus_(mathematics)" target="_top"> 018 https://en.wikipedia.org/wiki/Annulus_(mathematics)</a> 019 020 @see RingSector 021*/ 022public class Ring extends Model implements MeshMaker 023{ 024 public final double r1; 025 public final double r2; 026 public final int n; 027 public final int k; 028 029 /** 030 Create a ring (annulus) in the xy-plane with outer 031 radius 1 and with inner radius 0.33, with 12 spokes 032 coming out of the center, and with 5 concentric circles. 033 */ 034 public Ring( ) 035 { 036 this(1.0, 0.33, 4, 12); 037 } 038 039 040 /** 041 Create a ring (annulus) in the xy-plane with outer 042 radius {@code r1} and with inner radius {@code r2}, 043 with 12 spokes coming out of the center, and with 044 5 concentric circles. 045 046 @param r1 outer radius of the ring 047 @param r2 inner radius of the ring 048 */ 049 public Ring(final double r1, final double r2) 050 { 051 this(r1, r2, 4, 12); 052 } 053 054 055 /** 056 Create a ring (annulus) in the xy-plane with outer 057 radius {@code r1} and with inner radius {@code r2}, 058 with {@code k} spokes coming out of the center, and 059 with {@code n} concentric circles (not counting the 060 inner most circle). 061 <p> 062 If there are {@code k} spokes, then each circle around 063 the center will have {@code k} line segments. If there 064 are {@code n} concentric circles around the center (not 065 counting the inner most circle), then each spoke will 066 have {@code n} line segments. 067 <p> 068 There must be at least three spokes and at least one concentric circle. 069 070 @param r1 outer radius of the ring 071 @param r2 inner radius of the ring 072 @param n number of concentric circles 073 @param k number of spokes in the ring 074 @throws IllegalArgumentException if {@code n} is less than 1 075 @throws IllegalArgumentException if {@code k} is less than 3 076 */ 077 public Ring(final double r1, final double r2, 078 final int n, final int k) 079 { 080 super(String.format("Ring(%.2f,%.2f,%d,%d)", r1, r2, n, k)); 081 082 if (n < 1) 083 throw new IllegalArgumentException("n must be greater than 0"); 084 if (k < 3) 085 throw new IllegalArgumentException("k must be greater than 2"); 086 087 this.r1 = r1; 088 this.r2 = r2; 089 this.n = n; 090 this.k = k; 091 092 // Create the rings's geometry. 093 094 final double deltaR = (r1 - r2) / n, 095 deltaTheta = (2 * Math.PI) / k; 096 097 // An array of vertices to be used to create line segments. 098 final Vertex[][] v = new Vertex[n+1][k]; 099 100 // Create all the vertices. 101 for (int j = 0; j < k; ++j) // choose a spoke (an angle) 102 { 103 final double c = Math.cos(j * deltaTheta), 104 s = Math.sin(j * deltaTheta); 105 for (int i = 0; i < n + 1; ++i) // move along the spoke 106 { 107 final double ri = r2 + i * deltaR; 108 v[i][j] = new Vertex(ri * c, 109 ri * s, 110 0); 111 } 112 } 113 114 // Add all of the vertices to this model. 115 for (int i = 0; i < n + 1; ++i) 116 { 117 for (int j = 0; j < k; ++j) 118 { 119 addVertex( v[i][j] ); 120 } 121 } 122 123 // Create line segments around each concentric ring. 124 for (int i = 0; i < n + 1; ++i) // choose a ring 125 { 126 for (int j = 0; j < k - 1; ++j) 127 { // v[i][[j] v[i][j+1] 128 addPrimitive(new LineSegment( (i * k) + j, (i * k) + (j+1) )); 129 } 130 // close the circle 131 addPrimitive(new LineSegment( (i * k) + (k-1), (i * k) + 0 )); 132 } // v[i][k-1] v[i][0] 133 134 // Create the spokes.connecting the inner circle to the outer circle. 135 for (int j = 0; j < k; ++j) // choose a spoke 136 { 137 for (int i = 0; i < n; ++i) 138 { // v[i][j] v[i+1][j] 139 addPrimitive(new LineSegment( (i * k) + j, ((i+1) * k) + j )); 140 } 141 } 142 } 143 144 145 146 // Implement the MeshMaker interface (three methods). 147 @Override public int getHorzCount() {return n;} 148 149 @Override public int getVertCount() {return k;} 150 151 @Override 152 public Ring remake(final int n, final int k) 153 { 154 return new Ring(this.r1, this.r2, 155 n, k); 156 } 157}//Ring