/** This file converts between x,y coordinates and "track" coordinates for Womens' Flat-Track Roller Derby. The layout for the track is specified in the document: Appendix A: WFTDA Track Design and Specifications, which is available at: http://static.wftda.com/rules/wftda-rules-appendix-a-track-design.pdf The [x,y] coordinates are coordinates obtained from looking down on the track from above, with the curves at top and bottom, as demonstrated in Figure 1 of the above document, with the center of the track at [0,0] and the jammer and pivot lines on the right. The [x,y] coordinates are in feet, with x increasing to the right, and y increasing downwards. The [w,d] coordinates are values of my own devising where w is the sideways distance along the track, going from w=0 on the inside of the in-bounds track to w=1 on the outside of the in-bounds track. The d coordinate is the distance along the track in feet, with the nominal distance around curves being defined in an interesting and not-very-obvious way that falls out of the track definition rules. This will be discussed in more detail later. The jammer line is at d=5. The pivot line is at d=35, which is the exact beginning of the "first curve". In the [w,d] coordinate system, the first straightaway has its beginning at d=0, which is 5 feet behind the jammer line. The "first curve" means the entire first curved section of the track after this, or the top curve in Figure 1 or 2 of the aforementioned WFTDA document. In the [w,d] coordinate system: * The first straightaway runs from d=0 to Derby.d1 * The first curve runs from Derby.d1 to Derby.d2 * The second straightaway runs from Derby.d2 to Derby.d3 * The second curve runs from Derby.d3 to Derby.d4 (Exact constants for these distances can be obtained from the program below.) This file contains conversion routines for converting between [x,y] and [w,d] coordinate systems. The [x,y] system is useful for, say, determining where to draw a skater on the track, or finding out where a user clicked, and the [w,d] coordinates are good for simulating motion along the in-bounds section of the track. The side-to-side position along the track is given by varying w from 0 to 1, and the forward motion along the track is given by varying d from 0 to Derby.d4, which indicates a complete loop around the track. Many more explanations of the coordinate systems and the internal variables are forthcoming. These may require a vast treatise on the oddities that the track layout rules imply. Thanks very much to Denise Dambrackas/"Fawn Stalking" of the Denver Roller Dolls for expert discussion of rules and layout, and general awesomeness. */ class Derby { /** Length of a straightaway. */ class var straightaway = 35 /** Inner radius of curves. */ class var inR = 12.5 /** Length of inner arc */ class var inArc = inR pi /** This is the angle that is generated between 10 foot lines in curves if the rules in Appendix B: WFTDA Track Design and Specifications are followed. Calculated value = 32.71940 degrees. */ class var tenFootAngle = 2 arcsin[((7 feet + 1/2 in)/feet)/(2 inR)] /** This calculation reverse-engineers the radius of the track for which the 10-foot lines in the curves are actually 10 feet apart. Calculated value: 17.511254 ft */ class var effectiveRadius = 10 / tenFootAngle /** This is the effective length of each curve if you follow a path where the 10-foot lines in the curves are actually 10 feet apart. Calculated value: 55.0132277 ft */ class var midArc = effectiveRadius pi /** This is the effective w-coordinate of the effective 10-foot-line. Calculated value: 0.3579467 */ class var effectiveW = (effectiveRadius-inR)/14 /** d of end of first straightaway. Calculated value: d1 = 35 */ class var d1 = straightaway /** d of end of first curve. Calculated value: d2 = 90.0132277 */ class var d2 = d1 + midArc /** d of end of second straightaway. Calculated value: d3 = 125.0132277 */ class var d3 = d2 + straightaway /** d of end of second curve Calculated value: d4 = 180.0264554 This is the effective length of the track if you follow the "effectiveW" path where the 10-foot lines are actually spaced at 10-foot intervals around the curve. */ class var d4 = d3 + midArc /** Convert from x,y coordinates to w,d coordinates */ class XYtoWD[x,y] := { if y < -17.5 // First curve { theta = arctan[-(y+17.5), x] r = sqrt[x^2 + (y+17.5)^2] w = (r - 12.5) / (13 + 2 theta / pi) d = d1 + effectiveRadius theta return [w, d] } if y > 17.5 // Second curve { theta = arctan[y-17.5,-x] r = sqrt[x^2 + (y-17.5)^2] w = (r-12.5) / (13 + 2 theta / pi) d = d3 + effectiveRadius theta return [w, d] } if x > 0 // First straight return [(x-12.5)/(y/17.5 + 14), // w 17.5 - y] // d else // second straight return [-(12.5 + x) / (-y/17.5 + 14), // w d2 + y + 17.5] // d } /** Convert from w,d coordinates to x,y coordinates. */ class WDtoXY[w, d] := { d = d mod d4 // First straight if d < d1 return [12.5 + (15 - d/17.5) w, // x 17.5 - d] // y // First curve if d < d2 { theta = (d - d1) / effectiveRadius r = 12.5 + w (13 + 2 theta/pi) inside = cos[theta]^2 sqrt[r^2 sec[theta]^2 tan[theta]^2] // Cotangent goes to infinity around 0 and pi, so work around it if abs[theta] < 1e-6 return[12.5 + 13 w, -17.5] if abs[theta-pi] < 1e-6 return[-12.5 - 15 w, -17.5] x = cot[theta] inside y = -17.5 - inside return [x,y] } // Second straight if (d < d3) { x = -12.5 + 1/35 (2 d - 2 d2 - 525) w y = d - d2 - 17.5 return [x,y] } // Second curve theta = (d - d3) / effectiveRadius // Cotangent goes to infinity around 0 and pi, so work around it if abs[theta] < 1e-6 return[-12.5 - 13 w, 17.5] if abs[theta-pi] < 1e-6 return[12.5 + 15 w, 17.5] r = 12.5 + w (13 + 2 theta/pi) inside = cos[theta]^2 sqrt[r^2 sec[theta]^2 tan[theta]^2] x = -cot[theta] inside y = 17.5 + inside return [x,y] } }