//------------TNTBumpyCircle ------------------ function TNTBumpyCircle(center, r, d, b, n, fcolr, stroke, rotn) { this.center = center; //center TNTPoint this.r = r; //radius of circle this.b = b; //frequency factor of radius oscillation this.d = d; //amplitude of radius oscillation this.n = n; //power on radius oscillation this.fcolr = fcolr; this.stroke = stroke; this.rotn = rotn; //rotation about the x-axis this.vertexStyle = "smooth"; this.drawTNTBumpyCircle = drawTNTBumpyCircle; this.setCenter = setCenter; this.setLineCapStyle = setLineCapStyle; } function drawTNTBumpyCircle(context) { if (this.vertexStyle == "smooth") { this.lineCapStyle = "round"; this.joinStyle = "round"; } else if (this.vertexStyle == "beveled") { this.lineCapStyle = "butt"; this.joinStyle = "bevel"; } else //sharp is default { this.lineCapStyle = "square"; this.miterLimit = this.miterLimit; this.joinStyle = "miter"; } setLineCapStyle(this.lineCapStyle); context.lineJoin = this.joinStyle; context.miterLimit = this.miterLimit; context.beginPath(); var rFlux = this.r; var x, y; var rotPt; var xprime, yprime; var twoPi = 2 * Math.PI; var r; var x0, y0; var inc = 1000; var delta = twoPi / inc; var i = 0; var myB = this.b; rFlux = this.r + this.d * Math.sin(myB * i); x = rFlux * Math.cos(i); y = rFlux * Math.sin(i); rotPt = new TNTPoint(x, y); rotPt = rotatePointAboutOrigin(rotPt, this.rotn); xprime = rotPt.x + this.center.x; yprime = rotPt.y + this.center.y; x0 = xprime; y0 = yprime; var dist = 100; var epsilon = .000001; context.moveTo(x0, y0); //because it is impossible to figure the period of this image //we stop when the distance between a new point and the original point is less //than an epsilon away var period; if (myB != 0) period = twoPi / myB; else period = twoPi; var n = Math.round(this.n); n = Math.abs(n); //arbitrary condition on i to make sure we go around enough times while (Math.abs(dist) > epsilon || i < 90 * period) { i += delta; if (n != 0) rFlux = this.r + this.d * Math.pow(Math.sin(myB * i), n); else rFlux = this.r; x = rFlux * Math.cos(i); y = rFlux * Math.sin(i); rotPt = new TNTPoint(x, y); rotPt = rotatePointAboutOrigin(rotPt, this.rotn); xprime = rotPt.x + this.center.x; yprime = rotPt.y + this.center.y; context.lineTo(xprime, yprime); dist = Math.sqrt(Math.pow(xprime - x0, 2) + Math.pow(yprime - y0, 2)); } //point below already rotated, dont do it again context.lineTo(x0, y0); context.closePath(); if (this.fcolr != null) { context.fillStyle = this.fcolr.hex; context.fill(); } if (this.stroke != null) { context.strokeStyle = this.stroke.scolr; context.lineWidth = this.stroke.lineWidth; context.stroke(); } } //---------- End TNTBumpyCircle ---------------