1 //-------------------------------------------------------------------------- 2 // Drawing "spirograph" curves - epitrochoids, cycolids, roulettes 3 //-------------------------------------------------------------------------- 4 // 5 //-------------------------------------------------------------------------- 6 // Copyright (C) 2007 Arjen Markus 7 // Copyright (C) 2008 Andrew Ross 8 // 9 // This file is part of PLplot. 10 // 11 // PLplot is free software; you can redistribute it and/or modify 12 // it under the terms of the GNU Library General Public License as published by 13 // the Free Software Foundation; version 2 of the License. 14 // 15 // PLplot is distributed in the hope that it will be useful, 16 // but WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU Library General Public License for more details. 19 // 20 // You should have received a copy of the GNU Library General Public License 21 // along with PLplot; if not, write to the Free Software 22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 23 24 //-------------------------------------------------------------------------- 25 // Implementation of PLplot example 27 in Java. 26 //-------------------------------------------------------------------------- 27 28 package plplot.examples; 29 30 import plplot.core.*; 31 import static plplot.core.plplotjavacConstants.*; 32 33 import java.lang.Math; 34 35 class x27 { 36 PLStream pls = new PLStream(); 37 main( String[] args )38 public static void main( String[] args ) 39 { 40 new x27( args ); 41 } 42 43 //-------------------------------------------------------------------- 44 // Generates two kinds of plots: 45 // - construction of a cycloid (animated) 46 // - series of epitrochoids and hypotrochoids 47 //-------------------------------------------------------------------- 48 x27( String[] args )49 public x27( String[] args ) 50 { 51 // R, r, p, N 52 // R and r should be integers to give correct termination of the 53 // angle loop using gcd. 54 // N.B. N is just a place holder since it is no longer used 55 // (because we now have proper termination of the angle loop). 56 double params[][] = { 57 { 21.0, 7.0, 7.0, 3.0 }, // Deltoid 58 { 21.0, 7.0, 10.0, 3.0 }, 59 { 21.0, -7.0, 10.0, 3.0 }, 60 { 20.0, 3.0, 7.0, 20.0 }, 61 { 20.0, 3.0, 10.0, 20.0 }, 62 { 20.0, -3.0, 10.0, 20.0 }, 63 { 20.0, 13.0, 7.0, 20.0 }, 64 { 20.0, 13.0, 20.0, 20.0 }, 65 { 20.0, -13.0, 20.0, 20.0 } }; 66 67 int i; 68 boolean fill; 69 70 // plplot initialization 71 72 // Parse and process command line arguments 73 pls.parseopts( args, PL_PARSE_FULL | PL_PARSE_NOPROGRAM ); 74 75 // Initialize plplot 76 pls.init(); 77 78 // Illustrate the construction of a cycloid 79 cycloid(); 80 81 // Loop over the various curves 82 // First an overview, then all curves one by one 83 pls.ssub( 3, 3 ); // Three by three window 84 85 fill = false; 86 for ( i = 0; i < 9; i++ ) 87 { 88 pls.adv( 0 ); 89 pls.vpor( 0.0, 1.0, 0.0, 1.0 ); 90 spiro( params[i], fill ); 91 } 92 93 pls.adv( 0 ); 94 pls.ssub( 1, 1 ); // One window per curve 95 96 for ( i = 0; i < 9; i++ ) 97 { 98 pls.adv( 0 ); 99 pls.vpor( 0.0, 1.0, 0.0, 1.0 ); 100 spiro( params[i], fill ); 101 } 102 103 // Fill the curves 104 fill = true; 105 106 pls.adv( 0 ); 107 pls.ssub( 1, 1 ); // One window per curve 108 109 for ( i = 0; i < 9; i++ ) 110 { 111 pls.adv( 0 ); 112 pls.vpor( 0.0, 1.0, 0.0, 1.0 ); 113 spiro( params[i], fill ); 114 } 115 116 // Finally, an example to test out plarc capabilities 117 arcs(); 118 119 pls.end(); 120 } 121 122 //-------------------------------------------------------------------------- 123 // Calculate greatest common divisor following pseudo-code for the 124 // Euclidian algorithm at http://en.wikipedia.org/wiki/Euclidean_algorithm 125 gcd( int a, int b )126 int gcd( int a, int b ) 127 { 128 int t; 129 a = Math.abs( a ); 130 b = Math.abs( b ); 131 while ( b != 0 ) 132 { 133 t = b; 134 b = a % b; 135 a = t; 136 } 137 return a; 138 } 139 140 // =============================================================== 141 cycloid()142 void cycloid() 143 { 144 // TODO 145 } 146 147 // =============================================================== 148 spiro( double params[], boolean fill )149 void spiro( double params[], boolean fill ) 150 { 151 int NPNT = 2000; 152 double xcoord[]; 153 double ycoord[]; 154 155 int windings; 156 int steps; 157 int i; 158 double phi; 159 double phiw; 160 double dphi; 161 // Initialize to quiet java compiler errors about the possibility 162 // these variables are not initialized in the code below. 163 double xmin = 0.; 164 double xmax = 0.; 165 double ymin = 0.; 166 double ymax = 0.; 167 double xrange_adjust; 168 double yrange_adjust; 169 170 // Fill the coordinates 171 172 // Proper termination of the angle loop very near the beginning 173 // point, see 174 // http://mathforum.org/mathimages/index.php/Hypotrochoid. 175 windings = (int) Math.abs( params[1] ) / gcd( (int) params[0], (int) params[1] ); 176 steps = NPNT / windings; 177 dphi = 2.0 * Math.PI / steps; 178 179 xcoord = new double[windings * steps + 1]; 180 ycoord = new double[windings * steps + 1]; 181 182 for ( i = 0; i <= windings * steps; i++ ) 183 { 184 phi = i * dphi; 185 phiw = ( params[0] - params[1] ) / params[1] * phi; 186 xcoord[i] = ( params[0] - params[1] ) * Math.cos( phi ) + params[2] * Math.cos( phiw ); 187 ycoord[i] = ( params[0] - params[1] ) * Math.sin( phi ) - params[2] * Math.sin( phiw ); 188 189 if ( i == 0 ) 190 { 191 xmin = xcoord[i]; 192 xmax = xcoord[i]; 193 ymin = ycoord[i]; 194 ymax = ycoord[i]; 195 } 196 if ( xmin > xcoord[i] ) xmin = xcoord[i]; 197 if ( xmax < xcoord[i] ) xmax = xcoord[i]; 198 if ( ymin > ycoord[i] ) ymin = ycoord[i]; 199 if ( ymax < ycoord[i] ) ymax = ycoord[i]; 200 } 201 202 xrange_adjust = 0.15 * ( xmax - xmin ); 203 xmin -= xrange_adjust; 204 xmax += xrange_adjust; 205 yrange_adjust = 0.15 * ( ymax - ymin ); 206 ymin -= yrange_adjust; 207 ymax += yrange_adjust; 208 209 pls.wind( xmin, xmax, ymin, ymax ); 210 211 pls.col0( 1 ); 212 213 if ( fill ) 214 pls.fill( xcoord, ycoord ); 215 else 216 pls.line( xcoord, ycoord ); 217 } 218 arcs()219 void arcs() 220 { 221 int NSEG = 8; 222 int i; 223 double theta, dtheta; 224 double a, b; 225 226 theta = 0.0; 227 dtheta = 360.0 / NSEG; 228 pls.env( -10.0, 10.0, -10.0, 10.0, 1, 0 ); 229 230 // Plot segments of circle in different colors 231 for ( i = 0; i < NSEG; i++ ) 232 { 233 pls.col0( i % 2 + 1 ); 234 pls.arc( 0.0, 0.0, 8.0, 8.0, theta, theta + dtheta, 0.0, false ); 235 theta = theta + dtheta; 236 } 237 238 // Draw several filled ellipses inside the circle at different 239 // angles. 240 a = 3.0; 241 b = a * Math.tan( ( dtheta / 180.0 * Math.PI ) / 2.0 ); 242 theta = dtheta / 2.0; 243 for ( i = 0; i < NSEG; i++ ) 244 { 245 pls.col0( 2 - i % 2 ); 246 pls.arc( a * Math.cos( theta / 180.0 * Math.PI ), a * Math.sin( theta / 180.0 * Math.PI ), a, b, 0.0, 360.0, theta, true ); 247 theta = theta + dtheta; 248 } 249 } 250 } 251 252 //-------------------------------------------------------------------------- 253 // End of x27.java 254 //-------------------------------------------------------------------------- 255