/** This program renders a track for womens' flat-track roller derby. Main rules page: http://wftda.com/rules Appendix B specifies track layout process: http://wftda.com/rules/wftda-rules-appendix-b-track-design.pdf Note that the inner boundary is symmetrical about the x and y axes, but the outer boundary is not. The entry to the curves is 2 feet narrower than the exits to the curves. */ use geometry.frink use Derby.frink g = new graphics g.color[.5,.5,.5] p = new filledGeneralPath // Draw inside ring p.moveTo[12.5, -17.5] p.lineTo[12.5, 17.5] p.circularArc[0, 17.5, -180 degrees] p.lineTo[-12.5, -17.5] p.circularArc[0, -17.5, -180 degrees] p.close[] // Draw outside ring (in opposite winding direction.) p.moveTo[25.5, -17.5] p.circularArc[-1, -17.5, 180 degrees] p.lineTo[-25.5, 17.5] p.circularArc[1, 17.5, 180 degrees] p.close[] g.add[p] g.color[1, .4, .4, .7] g.stroke[3/12] y = -17.5 xo = 25.5 // The track narrows by 2 feet along the direction of travel in straightaways, // which are 35 feet long. sideslope = 35/2 // Draw lines on right side. First is pivot line for n = 1 to 4 { g.line[12.5, y, xo, y] y = y + 10 xo = xo + 10 / sideslope } // Draw lines on left side. y = 17.5 xo = -25.5 for n = 1 to 4 { g.line[-12.5, y, xo, y] y = y - 10 xo = xo - 10 / sideslope } // Draw lines in curves rin = 12.5 rout1 = 25.5 rout2 = 27.5 c = (7 feet + 1/2 in) / feet // Center of the inner ring cx = 0 cy = -17.5 // Center of the outer ring, which is offset from the inner ring. cx1 = -1 cy1 = -17.5 r1 = 26.5 for n = 1 to 5 { theta = 2 n arcsin[c/(2 rin)] // Translate the chord to angle. x1 = rin cos[theta] + cx y1 = cy - rin sin[theta] sols = circleLineIntersections[cx, cy, x1, y1, cx1, cy1, r1] g.line[ x1, y1, sols@1@0, sols@1@1] g.line[-x1, -y1, -sols@1@0, -sols@1@1] } /** This program draws and tests the roller derby coordinate system defined in Derby.frink. */ black = new color[0,0,0] blue = new color[0,0,1] gray = new color[0,0,0,.5] for d = 0 to Derby.d4 step 1 // This gives one entire loop of the track { g.color[black] [x,y] = Derby.WDtoXY[0,d] // Inside of track // println["\$x \$y"] g.fillEllipseCenter[x,y,.5,.5] [x,y] = Derby.WDtoXY[1,d] // Outside of track // println["1 \$d \$x \$y"] g.fillEllipseCenter[x,y,.5,.5] g.color[gray] [x,y] = Derby.WDtoXY[0.5,d] // Middle of track // println["\$x \$y"] g.fillEllipseCenter[x,y,.5,.5] g.color[blue] [x,y] = Derby.WDtoXY[Derby.effectiveW, d] // Effective middle of track. g.fillEllipseCenter[x,y,.5,.5] } /* Draw 10-foot lines all the way around the track. Note that the jammer line is at d=5 so we start there. */ for d=5 to Derby.d4+5 step 10 { [x1,y1] = Derby.WDtoXY[0, d] [x2,y2] = Derby.WDtoXY[1, d] g.line[x1, y1, x2, y2] } // Redraw the jammer line and pivot line in red. g.color[1,0,0,.8] // Jammer line is w=[0,1], d=5. [x1,y1] = Derby.WDtoXY[0,5] [x2,y2] = Derby.WDtoXY[1,5] g.line[x1,y1,x2,y2] // Pivot line is w=[0,1], d=35. [x1,y1] = Derby.WDtoXY[0,35] [x2,y2] = Derby.WDtoXY[1,35] g.line[x1,y1,x2,y2] g.show[] g.write["derbytrack.html", 800, 1000] browse["derbytrack.html"]