diff --git a/README.md b/README.md index b69c711..1091b3e 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ the same model that moves the parts. Left alone, each page plays a guided tour; | | The machine | What drives it | Checked by | |---|---|---|---| +| [**Radial**](machines/radial) | The Pratt & Whitney R-2800 Double Wasp, an 18-cylinder twin-row radial: the starter, the first firings missed then caught, the firing order going round the star, one row in section with its master rod and eight articulated rods (whose pistons do not quite follow the master's law), the rows pulled apart, a cam ring lifting a valve, the climb to 2,700 rpm. A C-series CB16 after public sources; not affiliated with Pratt & Whitney. | The crank angle, integrated once from a planned run of the engine speed. Power, torque and manifold pressure follow from it. | `machines/radial/check.mjs` | | [**Quantum**](machines/quantum) | A photonic quantum computer: a quantum dot emits one photon per laser pulse, fibre delay lines bring them onto a 24-mode chip together, 276 Mach-Zehnder interferometers mix them, superconducting detectors click. A Hong-Ou-Mandel test on one coupler, the Perceval program behind the heaters. Modelled on the public figures of Quandela's Belenos; not affiliated with Quandela. | The physical time τ of the shot, in nanoseconds. The output distribution is computed from the permanents of the chip's unitary. | `machines/quantum/check.mjs` | | [**Spindl**](machines/spindl) | A 3.5-inch 7,200 rpm desktop hard drive (2 platters, 4 heads): spin-up, the heads loading off the ramp, a seek drawn live, the rotational wait, the 3 nm flying height, the emergency park. A model of a typical drive, not a specific product. | The drive time τ. A request queue (LBA → zone, cylinder, head, sector) is planned once. | `machines/spindl/check.mjs` | @@ -66,8 +67,8 @@ Content-Security-Policy that allows the pages' inline scripts by their hashes, c ## Credits Built with Claude Code (Claude Opus 5.5) and the teardown skill, whose kit, frame capture and sound engine come from -[whaleyxbt/claude-motion](https://github.com/whaleyxbt/claude-motion) (MIT). three.js (MIT). Inter, JetBrains Mono and -Instrument Serif (SIL Open Font License). +[whaleyxbt/claude-motion](https://github.com/whaleyxbt/claude-motion) (MIT). three.js (MIT). Inter, JetBrains Mono, +Instrument Serif, Barlow Condensed and Saira Stencil One (SIL Open Font License). ## License diff --git a/machines/radial/FILM.md b/machines/radial/FILM.md new file mode 100644 index 0000000..ed01b87 --- /dev/null +++ b/machines/radial/FILM.md @@ -0,0 +1,31 @@ +# The film + +The tour (40 s) is recorded frame by frame from `machines/radial/r2800-film`, the same code as the page, with the +capture tools of the teardown skill ([whaleyxbt/claude-motion](https://github.com/whaleyxbt/claude-motion)). They need +the skill installed (`SKILL_DIR`), headless Chrome with a real GPU, `ffmpeg` and Python 3. + +```sh +cd machines/radial +node r2800-shared/make-timeline.mjs # r2800-film/timeline.json (beats) and events.json (every spark, the run at 100 Hz) +node "$SKILL_DIR/sims/build.mjs" ./r2800-film +echo '{"lang":"en"}' > /tmp/en.json # or fr / es +node "$SKILL_DIR/sims/capture.mjs" r2800-film --timeline r2800-film/timeline.json --config /tmp/en.json --size 1600x900 --dpr 1.2 --stills beats --cols 3 --out teardown-out/beats.png +node "$SKILL_DIR/sims/capture.mjs" r2800-film --timeline r2800-film/timeline.json --config /tmp/en.json --size 1600x900 --dpr 1.2 --out teardown-out/silent.mp4 +python3 "$SKILL_DIR/run_sfx.py" r2800-shared/score.py # teardown-out/radial-score.wav, mastered to −14 LUFS +ffmpeg -y -i teardown-out/silent.mp4 -i teardown-out/radial-score.wav -map 0:v -map 1:a -c:v copy -c:a aac -b:a 256k -shortest -movflags +faststart teardown-out/radial-en.mp4 +``` + +The share card is a frame of the film without the console, the star from the front at idle: + +```sh +echo '{"lang":"en","clean":true}' > /tmp/clean.json +node "$SKILL_DIR/sims/capture.mjs" r2800-film --config /tmp/clean.json --size 1600x900 --dpr 1.2 --still 11 --out teardown-out/og-src.png +ffmpeg -y -i teardown-out/og-src.png -vf "scale=1200:-1,crop=1200:630:0:(ih-630)/2" -map_metadata -1 og.png +``` + +On macOS, Playwright's headless shell may get no WebGL context; point the capture at Chrome: +`CHROMIUM="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"`. + +The sound is built on the same timeline: the starter's whine, a cough for each spark that lights while the engine +catches (the missed ones stay silent), a thud per firing while they come slower than ~12 a second on screen, then a +growl whose pulse is the firing rate on screen, and the propeller's wash. diff --git a/machines/radial/REFERENCES.md b/machines/radial/REFERENCES.md new file mode 100644 index 0000000..fd58fbb --- /dev/null +++ b/machines/radial/REFERENCES.md @@ -0,0 +1,87 @@ +# Radial: references + +Radial is a model of a Pratt & Whitney R-2800 Double Wasp, the 18-cylinder twin-row radial of the F6F Hellcat, the +F4U Corsair, the P-47 and, after the war, the Douglas DC-6. It is built from public sources, as a **C-series CB16** +(the DC-6B's engine, single-stage two-speed supercharger, 0.45 : 1 propeller gear), and it is not affiliated with +Pratt & Whitney. Where a figure is not public, the model uses a plausible value, listed below under **[E]**. + +The letters match the comments in [`r2800-shared/engine.js`](r2800-shared/engine.js), the one file every pose, +gauge and sound reads its numbers from. + +## Sources + +- **[F]** FAA, Type Certificate Data Sheet **6A3**, Douglas DC-6A / DC-6B, revision 28 + ([copy on enginehistory.org](https://www.enginehistory.org/Operations/WaterInjServErrors/6A3Rev28.pdf)). Engine + limits of the P&W Double Wasp CB-16: take-off (two minutes, dry) 2,050 hp at 2,700 rpm and 55.0 inHg; take-off wet + (water-alcohol) 2,400 hp at 2,800 rpm and 59.5 inHg; maximum continuous 1,800 hp at 2,600 rpm and 48.5 inHg; + impeller gear ratios 7.29 : 1 (low) and 8.58 : 1 (high); ".45:1 propeller reduction gearing". The film climbs to + the dry take-off point. +- **[N]** Smithsonian National Air and Space Museum, + [Pratt & Whitney Double Wasp R-2800 CB16](https://airandspace.si.edu/collection-objects/pratt-whitney-double-wasp-r-2800-cb16-2-row-radial-18-engine/nasm_A19580058000) + (A19580058000): weight 1,068 kg (2,350 lb), diameter 52.8 in, length 81.4 in, gear-driven single-stage two-speed + supercharger, 2,400 hp at 2,800 rpm. +- **[W]** K. McCutcheon, [Pratt & Whitney Double Wasp (R-2800)](https://enginehistory.org/Piston/P&W/R-2800/r-2800.shtml), + Aircraft Engine Historical Society: bore 5.75 in, stroke 6.000 in, 2,804.5 in³; two master rod assemblies, each a + one-piece master rod and eight "I"-section articulated rods on knuckle pins; a crankshaft of three steel forgings + joined at the crankpins; forged aluminium heads screwed and shrunk on forged steel barrels, finned aluminium muffs; + one inlet and one exhaust valve per cylinder; valve gear and ignition "substantially the same as the Twin Wasp". + The C series' compression ratio, 6.75 : 1, is from the + [R-2800 article](https://en.wikipedia.org/wiki/Pratt_%26_Whitney_R-2800_Double_Wasp) (Wikipedia, citing the + manufacturer's data). +- **[H]** FAA, *Aviation Maintenance Technician Handbook, Powerplant* (FAA-H-8083-32), the chapters on radial + engines: the firing order numbers of an 18-cylinder twin-row radial are **+11 and −7**, which gives + 1-12-5-16-9-2-13-6-17-10-3-14-7-18-11-4-15-8; cylinders numbered clockwise from the top of the rear row, seen from + the rear, odd in the rear row; a nine-cylinder row's cam ring has 4 lobes per track and turns against the crank + (a lobe every 90°, at ⅛ crank speed). Copies of those pages: + [firing order](https://www.aircraftsystemstech.com/p/firingorder-firing-order-of-engine-is.html), + [valve operating mechanism](https://aircraftsystemstech.com/p/valveoperating-mechanism-for.html). + +The geometry was built against photographs of real engines (Wikimedia Commons): +[a sectioned R-2800](https://commons.wikimedia.org/wiki/File:Cross_Section_of_a_Pratt_and_Whitney_R2800_Double_Wasp.JPG) +(the profile in section: nose case and reduction gear, both rows, master rods, crank, impeller), +[an R-2800 on its stand](https://commons.wikimedia.org/wiki/File:HARP_Pratt_%26_Whitney_R-2800_Double_Wasp.JPG) +(nose, magnetos, harness ring, pushrod tubes, baffles), +[the R-2800-21 at the National Museum of the USAF](https://commons.wikimedia.org/wiki/File:Pratt_%26_Whitney_R-2800-21_USAF.jpg) +(the star from the front, black intake pipes, aluminium rocker boxes) and +[an R-2800 in profile](https://commons.wikimedia.org/wiki/File:20-09-083-R_2800.jpg) (the long supercharger and +accessory section). They belong to their authors and are not in this repository. + +## Estimates **[E]** + +Not public, or not found in a primary source; chosen to be plausible: + +| Figure | Value | Why | +|---|---|---| +| Master rod, crankpin to piston pin | 292 mm (11.5 in) | about 3.8 crank throws; fits the 1,341 mm diameter with the heads and rocker boxes | +| Knuckle-pin circle | 60.3 mm (2.375 in) | just outside the 92 mm crankpin and its bearing | +| Articulated rod | 231.7 mm (master − knuckle circle) | the usual first choice; the knuckle pins sit at exactly 40° steps (see below) | +| Master rods in cylinders | 13 (rear row), 8 (front row) | not found in the sources above | +| Row spacing along the axis | 210 mm | the reference photos | +| Valve timing | inlet 20° BTDC – 60° ABDC, exhaust 50° BBDC – 20° ATDC | typical of the period; lift 15.9 mm | +| Spark | 25° before top centre | typical | +| Idle, starter cranking | 700 rpm, 140 rpm | typical | +| Propeller | three blades, 4.0 m | a Hamilton Standard of the DC-6B's size | +| Power at other speeds | the propeller absorbs P ∝ N³ through the run, 2,050 hp at 2,700 rpm | a fixed-pitch law; inertia neglected | +| Manifold pressure | bmep = k · MAP − friction (1.2 + 0.6 (N/2,700)² bar) − pumping | k set so that 2,050 hp needs 55.0 inHg exactly; the same law gives 1,702 hp at the METO point (1,800 hp [F], −5.4 %) | +| Reduction gear layout | sun 72 teeth on the crank, ring 88 fixed, carrier on the shaft | gives 0.45 exactly; P&W's tooth counts are not public | + +## The model, by hand + +- π/4 × 5.75² × 6 × 18 = **2,804.5 in³** (45.96 L). +- 2,050 hp = 1,528.7 kW at 2,700 rpm (282.7 rad/s): **5,407 N·m** at the crank, a brake mean effective pressure of + 14.8 bar. +- 18 firings in two turns: 9 × 2,700 / 60 = **405 firings a second**, one every 40° of crank. +- Mean piston speed 2 × 0.1524 m × 45 rev/s = **13.7 m/s**. Propeller 0.45 × 2,700 = 1,215 rpm; impeller + 7.29 × 2,700 = 19,683 rpm. +- The cam ring: each tappet needs one lift in 720° of crank; 4 lobes on a ring turning at ⅛ crank speed against it + bring one every 90° × 8 = 720°. The model reads every valve's lift off the turning ring and check.mjs verifies it + equals the valve timing for all 36 valves. +- **The articulated rods.** The master rod's piston follows the plain slider-crank law: stroke 152.40 mm, top centre + when its crankpin points at it. An articulated rod hangs on a knuckle pin that orbits on the master rod's big end, + an ellipse rather than a circle, so its piston does not: with the knuckle pins at exact 40° steps the model gives + strokes from 152.41 to **153.08 mm**, top centres up to **3.7°** early or late and up to 2.45 mm lower, so a + compression ratio down to 6.27 against the master's 6.75. Real engines trim the knuckle-pin positions to even this + out; how P&W did it for the R-2800 is not in the public sources, so the page shows the uncorrected geometry and + says so. + +`node machines/radial/check.mjs` recomputes each of these from the code. diff --git a/machines/radial/check.mjs b/machines/radial/check.mjs new file mode 100644 index 0000000..117694e --- /dev/null +++ b/machines/radial/check.mjs @@ -0,0 +1,99 @@ +// Recomputes, from the same functions the page draws with, every figure Radial shows, and fails if one leaves the +// range its source gives. node machines/radial/check.mjs (CI runs it on every push). +import {CAM, CYL, DISPL_IN3, DISPL_L, E, FIRE, GEAR, hpOf, LAW, lift, liftFromTiming, ORDER, pinAngle, RATING, ROWS, stateAt} from './r2800-shared/engine.js'; +import {DURATION, rpmAt, sparkList, thetaAt} from './r2800-shared/schedule.js'; + +let bad = 0; +const near = (name, v, lo, hi, unit = '') => { + const ok = v >= lo && v <= hi; + if (!ok) bad++; + console.log(`${ok ? 'ok ' : 'BAD'} ${name.padEnd(52)} ${Number(v.toPrecision(6))} ${unit} [${lo} … ${hi}]`); +}; +const mod = (a, m) => ((a % m) + m) % m; + +// displacement: π/4 × 5.75² × 6 × 18 = 2,804.5 in³ [W] +near('displacement', DISPL_IN3, 2804, 2805, 'in³'); +near('displacement', DISPL_L, 45.9, 46.0, 'L'); + +// the firing order: +11, −7 [H], each cylinder once in 720°, 40° apart, the rows alternating +const BRIEF = '1-12-5-16-9-2-13-6-17-10-3-14-7-18-11-4-15-8'; +near('firing order is ' + BRIEF, ORDER.join('-') === BRIEF ? 1 : 0, 1, 1); +near('cylinders in the order, each once', new Set(ORDER).size, 18, 18); +let alt = 0; +for (let i = 0; i < 18; i++) if (CYL[ORDER[i] - 1].row !== CYL[ORDER[(i + 1) % 18] - 1].row) alt++; +near('consecutive firings in different rows', alt, 18, 18); +const gaps = ORDER.map((c, i) => mod(FIRE[ORDER[(i + 1) % 18]] - FIRE[c], 720)); +near('interval between firings (min)', Math.min(...gaps), 40, 40, '°'); +near('interval between firings (max)', Math.max(...gaps), 40, 40, '°'); +// at its firing TDC the row's crankpin points at the cylinder (the geometry agrees with the order) +let miss = 0; +for (const cy of CYL) miss = Math.max(miss, Math.abs(((mod(pinAngle(cy.row, FIRE[cy.c]) - cy.angle, 360) + 180) % 360) - 180)); +near('crankpin on the cylinder at its firing', miss, 0, 1e-9, '°'); +// every spark of the film, counted per cylinder over the running part: once per two turns +{ + const sp = sparkList(); + const t0 = 8; + const t1 = DURATION - 0.5; + const turns = (thetaAt(t1) - thetaAt(t0)) / 360; + const per = CYL.map((cy) => sp.filter((s) => s[1] === cy.c && s[0] >= t0 && s[0] < t1).length); + near('sparks per cylinder per 2 turns (film)', Math.min(...per) / (turns / 2), 0.98, 1.02); + near('', Math.max(...per) / (turns / 2), 0.98, 1.02); +} + +// the master rod and the articulated rods, exact: the master's piston follows the plain slider-crank law +const mF = LAW[E.master.front]; +near('master stroke (2 × crank throw)', mF.stroke, 152.399, 152.401, 'mm'); +near('master TDC at its pin angle', Math.abs(mF.tdcLag), 0, 0.05, '°'); +const arts = CYL.filter((c) => c.c !== E.master.front && c.c !== E.master.rear).map((c) => LAW[c.c]); +near('articulated strokes, shortest', Math.min(...arts.map((a) => a.stroke)), 152.4, 153.5, 'mm'); +near('articulated strokes, longest', Math.max(...arts.map((a) => a.stroke)), 152.4, 153.5, 'mm'); +near('articulated TDC, largest shift', Math.max(...arts.map((a) => Math.abs(a.tdcLag))), 0.1, 6, '°'); +near('articulated TDC, lowest below the master', -Math.min(...arts.map((a) => a.dTDC)), 0, 4, 'mm'); +near('compression ratio, master', mF.cr, 6.7499, 6.7501); +near('compression ratio, lowest articulated', Math.min(...arts.map((a) => a.cr)), 6.0, 6.75); +for (const row of ['rear', 'front']) { + const ws = ROWS[row].filter((c) => c.c !== E.master[row]).sort((a, b) => Math.abs(LAW[b.c].tdcLag) - Math.abs(LAW[a.c].tdcLag))[0]; + const x = LAW[ws.c]; + console.log(` ${row} row: master ${E.master[row]}, most different ${ws.c}: stroke ${x.stroke.toFixed(3)} mm, TDC ${x.tdcLag.toFixed(2)}°, ${(-x.dTDC).toFixed(2)} mm lower, CR ${x.cr.toFixed(3)}`); +} + +// the cam rings: 4 lobes at ⅛ crank speed against the crank [H]; the lift read off the ring equals the valve timing +near('cam ring speed', CAM.ratio, -0.125, -0.125); +near('lobes × 2 × speed = once per two turns', CAM.lobes * 2 * Math.abs(CAM.ratio), 1, 1); +let err = 0; +let opens = 0; +for (const cy of CYL) + for (const ev of ['in', 'ex']) { + let prev = lift(cy.c, ev, -0.5); + for (let th = 0; th < 720; th += 0.5) { + const a = lift(cy.c, ev, th); + err = Math.max(err, Math.abs(a - liftFromTiming(cy.c, ev, th))); + if (a > 0.5 && prev <= 0.5) opens++; + prev = a; + } + } +near('cam lift vs valve timing (max error)', err, 0, 1e-9); +near('valve openings in 720° (36 valves)', opens, 36, 36); + +// power: the take-off point is exact [F], the maximum-continuous point within 7 % +const to = stateAt(RATING.takeoff.rpm); +near('take-off power at 2,700 rpm', to.hp, 2049.9, 2050.1, 'hp'); +near('take-off manifold pressure', to.map, 54.99, 55.01, 'inHg'); +near('METO 1,800 hp at 2,600 rpm, 48.5″ (model)', hpOf(RATING.meto.map, RATING.meto.rpm), 1800 * 0.93, 1800 * 1.07, 'hp'); +near('take-off torque', to.torque, 5400, 5415, 'N·m'); +near('firing frequency at 2,700 rpm', to.fireHz, 405, 405, 'Hz'); +near('mean piston speed at 2,700 rpm', to.pistonMs, 13.71, 13.72, 'm/s'); +near('propeller at 2,700 rpm (0.45 : 1)', to.propRpm, 1215, 1215, 'rpm'); +near('impeller at 2,700 rpm (7.29 : 1)', to.impRpm, 19683, 19683, 'rpm'); +near('drawn reduction gear 72 / (72 + 88)', 72 / (72 + 88), GEAR.prop, GEAR.prop); +near('idle manifold pressure (model)', stateAt(RATING.idle).map, 8, 16, 'inHg'); + +// the film's run reaches take-off rpm and comes back to idle +near('film: peak rpm', Math.max(...Array.from({length: 400}, (_, i) => rpmAt(i / 10))), 2690, 2701, 'rpm'); +near('film: rpm at the end', rpmAt(DURATION), RATING.idle - 5, RATING.idle + 5, 'rpm'); + +if (bad) { + console.error(`\n${bad} figure(s) out of range`); + process.exit(1); +} +console.log('\nevery figure in range'); diff --git a/machines/radial/og.png b/machines/radial/og.png new file mode 100644 index 0000000..2221eb4 Binary files /dev/null and b/machines/radial/og.png differ diff --git a/machines/radial/r2800-film/events.json b/machines/radial/r2800-film/events.json new file mode 100644 index 0000000..65eb309 --- /dev/null +++ b/machines/radial/r2800-film/events.json @@ -0,0 +1 @@ +{"rate":100,"fields":["rpm","slow","map","fireHzScreen","theta"],"samples":[[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0,1,29.92,0,6],[0.001,1,29.92,0,6],[0.011,1,29.92,0,6],[0.036,1,29.92,0,6.002],[0.084,1,29.919,0,6.005],[0.162,1,29.919,0,6.012],[0.276,1,29.918,0,6.025],[0.431,1,29.916,0,6.046],[0.634,1,29.914,0,6.078],[0.888,1,29.912,0,6.123],[1.198,1,29.909,0,6.186],[1.569,1,29.906,0,6.268],[2.005,1,29.902,0,6.375],[2.507,1,29.897,0,6.51],[3.08,1,29.892,0,6.678],[3.726,1,29.886,0,6.881],[4.446,1,29.88,0,7.126],[5.244,1,29.873,0,7.416],[6.119,1,29.865,0,7.757],[7.074,1,29.856,0,8.152],[8.109,1,29.847,0,8.607],[9.224,1,29.837,0,9.127],[10.421,1,29.826,0,9.716],[11.698,1,29.815,0,10.379],[13.055,1,29.803,0,11.121],[14.492,1,29.79,0,11.947],[16.008,1,29.776,0,12.862],[17.601,1,29.762,0,13.87],[19.271,1,29.747,0,14.976],[21.015,1,29.731,0,16.184],[22.831,1,29.715,0,17.499],[24.718,1,29.698,0,18.925],[26.674,1,29.68,0,20.466],[28.695,1,29.662,0,22.127],[30.779,1,29.643,0,23.911],[32.924,1,29.624,0,25.822],[35.126,1,29.604,0,27.863],[37.382,1,29.584,0,30.038],[39.689,1,29.563,0,32.35],[42.043,1,29.542,0,34.801],[44.442,1,29.52,0,37.396],[46.88,1,29.498,0,40.135],[49.356,1,29.476,0,43.022],[51.864,1,29.453,0,46.059],[54.401,1,29.43,0,49.246],[56.962,1,29.407,0,52.587],[59.545,1,29.384,0,56.082],[62.144,1,29.361,0,59.733],[64.756,1,29.337,0,63.54],[67.376,1,29.314,0,67.504],[70,1,29.29,0,71.625],[72.624,1,29.266,0,75.904],[75.244,1,29.243,0,80.34],[77.856,1,29.219,0,84.933],[80.455,1,29.196,0,89.682],[83.038,1,29.173,0,94.587],[85.599,1,29.15,0,99.646],[88.136,1,29.127,0,104.859],[90.644,1,29.104,0,110.222],[93.12,1,29.082,0,115.735],[95.558,1,29.06,0,121.396],[97.957,1,29.038,0,127.201],[100.311,1,29.02,0,133.15],[102.618,1,29.02,0,139.238],[104.874,1,29.02,0,145.463],[107.076,1,29.02,0,151.822],[109.221,1,29.02,0,158.311],[111.305,1,29.02,0,164.927],[113.326,1,29.02,0,171.666],[115.282,1,29.02,0,178.525],[117.169,1,29.02,0,185.499],[118.985,1,29.02,0,192.584],[120.729,1,29.02,0,199.776],[122.399,1,29.02,0,207.07],[123.992,1,29.02,0,214.462],[125.508,1,29.02,0,221.947],[126.945,1,29.02,0,229.521],[128.302,1,29.02,0,237.179],[129.579,1,29.02,0,244.916],[130.776,1,29.02,0,252.727],[131.891,1,29.02,0,260.607],[132.926,1,29.02,0,268.552],[133.881,1,29.02,0,276.557],[134.756,1,29.02,0,284.616],[135.554,1,29.02,0,292.726],[136.274,1,29.02,0,300.881],[136.92,1,29.02,0,309.078],[137.493,1,29.02,0,317.31],[137.995,1,29.02,0,325.575],[138.431,1,29.02,0,333.868],[138.802,1,29.02,0,342.186],[139.112,1,29.02,0,350.523],[139.366,1,29.02,0,358.878],[139.569,1,29.02,0,367.246],[139.724,1,29.02,0,375.625],[139.838,1,29.02,0,384.012],[139.916,1,29.02,0,392.405],[139.964,1,29.02,0,400.802],[139.989,1,29.02,0,409.2],[139.999,1,29.02,0,417.6],[140,1,29.02,0,426],[140,1,29.02,0,434.4],[140,1,29.02,0,442.8],[140,1,29.02,0,451.2],[140,1,29.02,0,459.6],[140,1,29.02,0,468],[140,1,29.02,0,476.4],[140,1,29.02,0,484.8],[140,1,29.02,0,493.2],[140,1,29.02,0,501.6],[140,1,29.02,0,510],[140,1,29.02,0,518.4],[140,1,29.02,0,526.8],[140,1,29.02,0,535.2],[140,1,29.02,0,543.6],[140,1,29.02,0,552],[140,1,29.02,0,560.4],[140,1,29.02,0,568.8],[140,1,29.02,0,577.2],[140,1,29.02,0,585.6],[140,1,29.02,0,594],[140,1,29.02,0,602.4],[140,1,29.02,0,610.8],[140,1,29.02,0,619.2],[140,1,29.02,0,627.6],[140,1,29.02,0,636],[140,1,29.02,0,644.4],[140,1,29.02,0,652.8],[140,1,29.02,0,661.2],[140,1,29.02,0,669.6],[140,1,29.02,0,678],[140,1,29.02,0,686.4],[140,1,29.02,0,694.8],[140,1,29.02,0,703.2],[140,1,29.02,0,711.6],[140,1,29.02,0,720],[140,1,29.02,0,728.4],[140,1,29.02,0,736.8],[140,1,29.02,0,745.2],[140,1,29.02,0,753.6],[140,1,29.02,0,762],[140,1,29.02,0,770.4],[140,1,29.02,0,778.8],[140,1,29.02,0,787.2],[140,1,29.02,0,795.6],[140,1,29.02,0,804],[140,1,29.02,0,812.4],[140,1,29.02,0,820.8],[140,1,29.02,0,829.2],[140,1,29.02,0,837.6],[140,1,29.02,0,846],[140,1,29.02,0,854.4],[140,1,29.02,0,862.8],[140,1,29.02,0,871.2],[140,1,29.02,0,879.6],[140,1,29.02,0,888],[140,1,29.02,0,896.4],[140,1,29.02,0,904.8],[140,1,29.02,0,913.2],[140,1,29.02,0,921.6],[140,1,29.02,0,930],[140,1,29.02,0,938.4],[140,1,29.02,0,946.8],[140,1,29.02,0,955.2],[140,1,29.02,0,963.6],[140,1,29.02,0,972],[140,1,29.02,0,980.4],[140,1,29.02,0,988.8],[140,1,29.02,0,997.2],[140,1,29.02,0,1005.6],[140,1,29.02,0,1014],[140,1,29.02,0,1022.4],[140,1,29.02,0,1030.8],[140,1,29.02,0,1039.2],[140,1,29.02,0,1047.6],[140,1,29.02,0,1056],[140,1,29.02,0,1064.4],[140,1,29.02,0,1072.8],[140,1,29.02,0,1081.2],[140,1,29.02,0,1089.6],[140,1,29.02,0,1098],[140,1,29.02,0,1106.4],[140,1,29.02,0,1114.8],[140,1,29.02,0,1123.2],[140,1,29.02,0,1131.6],[140,1,29.02,0,1140],[140,1,29.02,0,1148.4],[140,1,29.02,0,1156.8],[140,1,29.02,0,1165.2],[140,1,29.02,0,1173.6],[140,1,29.02,0,1182],[140,1,29.02,0,1190.4],[140,1,29.02,0,1198.8],[140,1,29.02,0,1207.2],[140,1,29.02,0,1215.6],[140,1,29.02,0,1224],[140,1,29.02,0,1232.4],[140,1,29.02,0,1240.8],[140,1,29.02,0,1249.2],[140,1,29.02,0,1257.6],[140,1,29.02,0,1266],[140,1,29.02,0,1274.4],[140,1,29.02,0,1282.8],[140,1,29.02,0,1291.2],[140,1,29.02,0,1299.6],[140,1,29.02,0,1308],[140,1,29.02,0,1316.4],[140,1,29.02,0,1324.8],[140,1,29.02,0,1333.2],[140,1,29.02,0,1341.6],[140,1,29.02,0,1350],[140,1,29.02,0,1358.4],[140,1,29.02,0,1366.8],[140,1,29.02,0,1375.2],[140,1,29.02,0,1383.6],[140,1,29.02,0,1392],[140,1,29.02,0,1400.4],[140,1,29.02,0,1408.8],[140,1,29.02,0,1417.2],[140,1,29.02,0,1425.6],[140,1,29.02,0,1434],[140,1,29.02,0,1442.4],[140,1,29.02,0,1450.8],[140,1,29.02,0,1459.2],[140,1,29.02,0,1467.6],[140,1,29.02,0,1476],[140,1,29.02,0,1484.4],[140,1,29.02,0,1492.8],[140,1,29.02,0,1501.2],[140,1,29.02,0,1509.6],[140,1,29.02,0,1518],[140,1,29.02,0,1526.4],[140,1,29.018,0.002,1534.8],[140,1,29.014,0.005,1543.2],[140,1,29.007,0.013,1551.6],[140,1,28.995,0.024,1560],[140,1,28.977,0.041,1568.4],[140,1,28.952,0.065,1576.8],[140,1,28.921,0.095,1585.2],[140,1,28.881,0.133,1593.6],[140,1,28.832,0.18,1602],[140,1,28.774,0.235,1610.4],[140,1,28.705,0.301,1618.8],[140,1,28.626,0.376,1627.2],[140,1,28.537,0.462,1635.6],[140,1,28.435,0.559,1644],[140,1,28.322,0.667,1652.4],[140,1,28.197,0.787,1660.8],[140,1,28.06,0.918,1669.2],[140,1,27.91,1.061,1677.6],[140,1,27.747,1.216,1686],[140,1,27.572,1.384,1694.4],[140,1,27.384,1.563,1702.8],[140,1,27.184,1.755,1711.2],[140,1,26.971,1.958,1719.6],[140,1,26.745,2.174,1728],[140.009,1,26.508,2.401,1736.4],[140.071,1,26.257,2.642,1744.802],[140.235,1,25.995,2.895,1753.211],[140.548,1,25.722,3.165,1761.633],[141.054,1,25.437,3.45,1770.08],[141.793,1,25.141,3.755,1778.564],[142.803,1,24.835,4.081,1787.101],[144.118,1,24.518,4.431,1795.707],[145.771,1,24.192,4.807,1804.402],[147.79,1,23.856,5.213,1813.207],[150.202,1,23.512,5.653,1822.144],[153.03,1,23.16,6.129,1831.239],[156.297,1,22.8,6.646,1840.517],[160.02,1,22.433,7.208,1850.004],[164.217,1,22.06,7.819,1859.729],[168.9,1,21.682,8.484,1869.72],[174.083,1,21.298,9.206,1880.007],[179.774,1,20.911,9.99,1890.62],[185.98,1,20.52,10.84,1901.59],[192.707,1,20.127,11.761,1912.948],[199.958,1,19.732,12.757,1924.725],[207.735,1,19.335,13.832,1936.953],[216.036,1,18.939,14.989,1949.664],[224.859,1,18.544,16.232,1962.888],[234.199,1,18.15,17.565,1976.657],[244.052,1,17.758,18.99,1991.002],[254.408,1,17.37,20.51,2005.953],[265.26,1,16.987,22.127,2021.541],[276.595,1,16.608,23.843,2037.794],[288.403,1,16.236,25.659,2054.742],[300.669,1,15.871,27.575,2072.412],[313.379,1,15.513,29.593,2090.831],[326.516,1,15.165,31.711,2110.026],[340.064,1,14.826,33.929,2130.021],[354.004,1,14.498,36.244,2150.841],[368.317,1,14.181,38.656,2172.509],[382.981,1,13.876,41.161,2195.046],[397.977,1,13.585,43.757,2218.473],[413.281,1,13.307,46.438,2242.81],[428.87,1,13.043,49.202,2268.073],[444.722,1,12.794,52.042,2294.279],[460.812,1,12.561,54.954,2321.444],[477.114,1,12.344,57.932,2349.581],[493.604,1,12.143,60.968,2378.702],[510.255,1,11.959,64.056,2408.817],[527.041,1,11.792,67.189,2439.935],[543.935,1,11.643,70.36,2472.064],[560.911,1,11.511,73.559,2505.209],[577.942,1,11.396,76.779,2539.374],[595,1,11.299,80.011,2574.562],[612.058,1,11.219,83.247,2610.774],[629.089,1,11.156,86.479,2648.009],[646.065,1,11.111,89.696,2686.264],[662.959,1,11.082,92.892,2725.535],[679.745,1,11.069,96.056,2765.817],[696.396,1,11.071,99.181,2807.102],[712.886,1,11.089,102.259,2849.381],[729.188,1,11.121,105.282,2892.644],[745.278,1,11.167,108.241,2936.879],[761.13,1,11.225,111.131,2982.073],[776.719,1,11.295,113.945,3028.21],[792.023,1,11.377,116.676,3075.273],[807.019,1,11.468,119.319,3123.246],[821.683,1,11.568,121.871,3172.109],[835.996,1,11.677,124.326,3221.841],[849.936,1,11.792,126.682,3272.421],[863.484,1,11.913,128.936,3323.826],[876.621,1,12.038,131.088,3376.031],[889.331,1,12.167,133.137,3429.012],[901.597,1,12.298,135.083,3482.742],[913.405,1,12.43,136.928,3537.194],[924.74,1,12.562,138.675,3592.341],[935.592,1,12.692,140.328,3648.153],[945.948,1,12.82,141.891,3704.602],[955.801,1,12.943,143.37,3761.657],[965.141,1,13.061,144.771,3819.288],[973.964,1,13.174,146.095,3877.464],[982.265,1,13.281,147.34,3936.153],[990.042,1,13.382,148.506,3995.325],[997.293,1,13.477,149.594,4054.948],[1004.02,1,13.566,150.603,4114.99],[1010.226,1,13.649,151.534,4175.42],[1015.917,1,13.725,152.388,4236.207],[1021.1,1,13.794,153.165,4297.32],[1025.783,1,13.858,153.867,4358.729],[1029.98,1,13.915,154.497,4420.404],[1033.703,1,13.965,155.055,4482.317],[1036.97,1,14.01,155.545,4544.439],[1039.798,1,14.049,155.97,4606.744],[1042.21,1,14.082,156.332,4669.207],[1044.229,1,14.11,156.634,4731.802],[1045.882,1,14.132,156.882,4794.507],[1047.197,1,14.15,157.08,4857.301],[1048.207,1,14.164,157.231,4920.164],[1048.946,1,14.175,157.342,4983.08],[1049.452,1,14.182,157.418,5046.033],[1049.765,1,14.186,157.465,5109.011],[1049.929,1,14.188,157.489,5172.002],[1049.991,1,14.189,157.499,5235],[1050,1,14.189,157.5,5298],[1049.998,1,14.189,157.5,5361],[1049.982,1,14.189,157.497,5423.999],[1049.94,1,14.188,157.491,5486.997],[1049.86,1,14.187,157.479,5549.992],[1049.731,1,14.185,157.46,5612.98],[1049.541,1,14.183,157.431,5675.958],[1049.281,1,14.179,157.392,5738.923],[1048.941,1,14.175,157.341,5801.87],[1048.513,1,14.169,157.277,5864.794],[1047.988,1,14.161,157.198,5927.69],[1047.36,1,14.153,157.104,5990.551],[1046.62,1,14.142,156.993,6053.371],[1045.763,1,14.131,156.864,6116.143],[1044.782,1,14.117,156.717,6178.86],[1043.673,1,14.102,156.551,6241.514],[1042.432,1,14.085,156.365,6304.098],[1041.052,1,14.066,156.158,6366.603],[1039.533,1,14.045,155.93,6429.021],[1037.869,1,14.022,155.68,6491.344],[1036.058,1,13.997,155.409,6553.563],[1034.099,1,13.971,155.115,6615.668],[1031.989,1,13.942,154.798,6677.652],[1029.728,1,13.911,154.459,6739.504],[1027.314,1,13.878,154.097,6801.216],[1024.748,1,13.844,153.712,6862.779],[1022.029,1,13.807,153.304,6924.183],[1019.158,1,13.768,152.874,6985.419],[1016.135,1,13.728,152.42,7046.478],[1012.962,1,13.685,151.944,7107.352],[1009.641,1,13.641,151.446,7168.031],[1006.174,1,13.595,150.926,7228.506],[1002.563,1,13.547,150.384,7288.769],[998.81,1,13.497,149.821,7348.811],[994.919,1,13.446,149.238,7408.623],[990.892,1,13.394,148.634,7468.198],[986.734,1,13.339,148.01,7527.528],[982.449,1,13.284,147.367,7586.604],[978.04,1,13.227,146.706,7645.419],[973.511,1,13.168,146.027,7703.966],[968.869,1,13.109,145.33,7762.238],[964.116,1,13.048,144.617,7820.228],[959.26,1,12.987,143.889,7877.93],[954.304,1,12.924,143.146,7935.338],[949.254,1,12.861,142.388,7992.445],[944.116,1,12.797,141.617,8049.246],[938.896,1,12.732,140.834,8105.737],[933.6,1,12.666,140.04,8161.912],[928.233,1,12.6,139.235,8217.768],[922.803,1,12.534,138.421,8273.299],[917.316,1,12.468,137.597,8328.503],[911.778,1,12.401,136.767,8383.376],[906.195,1,12.334,135.929,8437.915],[900.575,1,12.267,135.086,8492.119],[894.924,1,12.2,134.239,8545.984],[889.248,1,12.133,133.387,8599.509],[883.556,1,12.067,132.533,8652.693],[877.853,1,12,131.678,8705.535],[872.147,1,11.934,130.822,8758.035],[866.444,1,11.869,129.967,8810.193],[860.752,1,11.804,129.113,8862.009],[855.076,1,11.74,128.261,8913.484],[849.425,1,11.676,127.414,8964.619],[843.805,1,11.614,126.571,9015.415],[838.222,1,11.552,125.733,9065.876],[832.684,1,11.491,124.903,9116.003],[827.197,1,11.431,124.079,9165.799],[821.767,1,11.372,123.265,9215.268],[816.4,1,11.314,122.46,9264.412],[811.104,1,11.257,121.666,9313.237],[805.884,1,11.201,120.883,9361.746],[800.746,1,11.147,120.112,9409.945],[795.696,1,11.093,119.354,9457.838],[790.74,1,11.042,118.611,9505.43],[785.884,1,10.991,117.883,9552.728],[781.131,1,10.942,117.17,9599.738],[776.489,1,10.894,116.473,9646.466],[771.96,1,10.848,115.794,9692.919],[767.551,1,10.803,115.133,9739.104],[763.266,1,10.76,114.49,9785.028],[759.108,1,10.718,113.866,9830.698],[755.081,1,10.678,113.262,9876.123],[751.19,1,10.639,112.679,9921.311],[747.437,1,10.602,112.116,9966.269],[743.826,1,10.567,111.574,10011.006],[740.359,1,10.533,111.054,10055.531],[737.038,1,10.5,110.556,10099.852],[733.865,1,10.47,110.08,10143.978],[730.842,1,10.44,109.626,10187.919],[727.971,1,10.413,109.196,10231.683],[725.252,1,10.387,108.788,10275.279],[722.686,1,10.362,108.403,10318.716],[720.272,1,10.339,108.041,10362.004],[718.011,1,10.318,107.702,10405.152],[715.901,1,10.298,107.385,10448.168],[713.942,1,10.279,107.091,10491.063],[712.131,1,10.262,106.82,10533.844],[710.467,1,10.247,106.57,10576.521],[708.948,1,10.233,106.342,10619.103],[707.568,1,10.22,106.135,10661.598],[706.327,1,10.208,105.949,10704.014],[705.218,1,10.198,105.783,10746.36],[704.237,1,10.189,105.636,10788.643],[703.38,1,10.181,105.507,10830.871],[702.64,1,10.174,105.396,10873.051],[702.012,1,10.168,105.302,10915.19],[701.487,1,10.163,105.223,10957.294],[701.059,1,10.159,105.159,10999.37],[700.719,1,10.156,105.108,11041.423],[700.459,1,10.154,105.069,11083.458],[700.269,1,10.152,105.04,11125.48],[700.14,1,10.151,105.021,11167.492],[700.06,1,10.15,105.009,11209.497],[700.018,1,10.15,105.003,11251.499],[700.002,1,10.149,105,11293.5],[700,1,10.149,105,11335.5],[700,1,10.149,105,11377.5],[700,1,10.149,105,11419.5],[700,1,10.149,105,11461.5],[700,1,10.149,105,11503.5],[700,1,10.149,105,11545.5],[700,1,10.149,105,11587.5],[700,1,10.149,105,11629.5],[700,1,10.149,105,11671.5],[700,1,10.149,105,11713.5],[700,1,10.149,105,11755.5],[700,1,10.149,104.998,11797.5],[700,1,10.149,104.985,11839.497],[700,1,10.149,104.949,11881.485],[700,0.999,10.149,104.881,11923.452],[700,0.998,10.149,104.771,11965.384],[700,0.996,10.149,104.609,12007.262],[700,0.994,10.149,104.388,12049.063],[700,0.991,10.149,104.1,12090.763],[700,0.988,10.149,103.737,12132.333],[700,0.984,10.149,103.294,12173.743],[700,0.979,10.149,102.766,12214.958],[700,0.973,10.149,102.146,12255.943],[700,0.966,10.149,101.433,12296.662],[700,0.958,10.149,100.622,12337.076],[700,0.95,10.149,99.712,12377.147],[700,0.94,10.149,98.702,12416.833],[700,0.929,10.149,97.591,12456.095],[700,0.918,10.149,96.38,12494.893],[700,0.905,10.149,95.07,12533.186],[700,0.892,10.149,93.664,12570.936],[700,0.878,10.149,92.163,12608.104],[700,0.863,10.149,90.573,12644.655],[700,0.847,10.149,88.897,12680.552],[700,0.83,10.149,87.141,12715.762],[700,0.812,10.149,85.309,12750.254],[700,0.794,10.149,83.408,12784],[700,0.776,10.149,81.444,12816.972],[700,0.756,10.149,79.424,12849.147],[700,0.737,10.149,77.356,12880.505],[700,0.717,10.149,75.246,12911.027],[700,0.696,10.149,73.101,12940.697],[700,0.676,10.149,70.929,12969.504],[700,0.655,10.149,68.738,12997.438],[700,0.634,10.149,66.534,13024.492],[700,0.613,10.149,64.325,13050.664],[700,0.592,10.149,62.117,13075.952],[700,0.571,10.149,59.918,13100.359],[700,0.55,10.149,57.733,13123.889],[700,0.529,10.149,55.569,13146.548],[700,0.509,10.149,53.431,13168.348],[700,0.489,10.149,51.324,13189.298],[700,0.469,10.149,49.253,13209.412],[700,0.45,10.149,47.223,13228.706],[700,0.431,10.149,45.237,13247.196],[700,0.412,10.149,43.298,13264.901],[700,0.394,10.149,41.41,13281.841],[700,0.377,10.149,39.574,13298.036],[700,0.36,10.149,37.794,13313.508],[700,0.344,10.149,36.071,13328.279],[700,0.328,10.149,34.406,13342.373],[700,0.312,10.149,32.8,13355.812],[700,0.298,10.149,31.254,13368.621],[700,0.283,10.149,29.767,13380.823],[700,0.27,10.149,28.34,13392.442],[700,0.257,10.149,26.973,13403.503],[700,0.244,10.149,25.664,13414.028],[700,0.233,10.149,24.414,13424.042],[700,0.221,10.149,23.221,13433.567],[700,0.21,10.149,22.083,13442.626],[700,0.2,10.149,21,13451.241],[700,0.19,10.149,19.97,13459.433],[700,0.181,10.149,18.992,13467.224],[700,0.172,10.149,18.063,13474.633],[700,0.164,10.149,17.183,13481.681],[700,0.156,10.149,16.35,13488.386],[700,0.148,10.149,15.561,13494.767],[700,0.141,10.149,14.815,13500.84],[700,0.134,10.149,14.11,13506.624],[700,0.128,10.149,13.445,13512.134],[700,0.122,10.149,12.817,13517.385],[700,0.116,10.149,12.226,13522.393],[700,0.111,10.149,11.668,13527.17],[700,0.106,10.149,11.144,13531.732],[700,0.101,10.149,10.65,13536.089],[700,0.097,10.149,10.185,13540.256],[700,0.093,10.149,9.749,13544.241],[700,0.089,10.149,9.339,13548.058],[700,0.085,10.149,8.954,13551.716],[700,0.082,10.149,8.592,13555.224],[700,0.079,10.149,8.254,13558.593],[700,0.076,10.149,7.936,13561.83],[700,0.073,10.149,7.639,13564.944],[700,0.07,10.149,7.36,13567.943],[700,0.068,10.149,7.099,13570.835],[700,0.065,10.149,6.856,13573.625],[700,0.063,10.149,6.628,13576.321],[700,0.061,10.149,6.416,13578.93],[700,0.059,10.149,6.217,13581.456],[700,0.057,10.149,6.033,13583.905],[700,0.056,10.149,5.861,13586.284],[700,0.054,10.149,5.701,13588.596],[700,0.053,10.149,5.552,13590.846],[700,0.052,10.149,5.415,13593.039],[700,0.05,10.149,5.287,13595.179],[700,0.049,10.149,5.169,13597.27],[700,0.048,10.149,5.061,13599.316],[700,0.047,10.149,4.961,13601.32],[700,0.046,10.149,4.869,13603.286],[700,0.046,10.149,4.785,13605.216],[700,0.045,10.149,4.708,13607.115],[700,0.044,10.149,4.639,13608.984],[700,0.044,10.149,4.576,13610.826],[700,0.043,10.149,4.519,13612.645],[700,0.043,10.149,4.468,13614.442],[700,0.042,10.149,4.423,13616.22],[700,0.042,10.149,4.383,13617.981],[700,0.041,10.149,4.348,13619.727],[700,0.041,10.149,4.317,13621.46],[700,0.041,10.149,4.291,13623.182],[700,0.041,10.149,4.269,13624.894],[700,0.04,10.149,4.251,13626.597],[700,0.04,10.149,4.236,13628.295],[700,0.04,10.149,4.225,13629.987],[700,0.04,10.149,4.216,13631.675],[700,0.04,10.149,4.209,13633.36],[700,0.04,10.149,4.205,13635.043],[700,0.04,10.149,4.202,13636.724],[700,0.04,10.149,4.201,13638.404],[700,0.04,10.149,4.2,13640.084],[700,0.04,10.149,4.2,13641.764],[700,0.04,10.149,4.2,13643.444],[700,0.04,10.149,4.2,13645.124],[700,0.04,10.149,4.2,13646.804],[700,0.04,10.149,4.2,13648.484],[700,0.04,10.149,4.2,13650.164],[700,0.04,10.149,4.2,13651.844],[700,0.04,10.149,4.2,13653.524],[700,0.04,10.149,4.2,13655.204],[700,0.04,10.149,4.2,13656.884],[700,0.04,10.149,4.2,13658.564],[700,0.04,10.149,4.2,13660.244],[700,0.04,10.149,4.2,13661.924],[700,0.04,10.149,4.2,13663.604],[700,0.04,10.149,4.2,13665.284],[700,0.04,10.149,4.2,13666.964],[700,0.04,10.149,4.2,13668.644],[700,0.04,10.149,4.2,13670.324],[700,0.04,10.149,4.2,13672.004],[700,0.04,10.149,4.2,13673.684],[700,0.04,10.149,4.2,13675.364],[700,0.04,10.149,4.2,13677.044],[700,0.04,10.149,4.2,13678.724],[700,0.04,10.149,4.2,13680.404],[700,0.04,10.149,4.2,13682.084],[700,0.04,10.149,4.2,13683.764],[700,0.04,10.149,4.2,13685.444],[700,0.04,10.149,4.2,13687.124],[700,0.04,10.149,4.2,13688.804],[700,0.04,10.149,4.2,13690.484],[700,0.04,10.149,4.2,13692.164],[700,0.04,10.149,4.2,13693.844],[700,0.04,10.149,4.2,13695.524],[700,0.04,10.149,4.2,13697.204],[700,0.04,10.149,4.2,13698.884],[700,0.04,10.149,4.2,13700.564],[700,0.04,10.149,4.2,13702.244],[700,0.04,10.149,4.2,13703.924],[700,0.04,10.149,4.2,13705.604],[700,0.04,10.149,4.2,13707.284],[700,0.04,10.149,4.2,13708.964],[700,0.04,10.149,4.2,13710.644],[700,0.04,10.149,4.2,13712.324],[700,0.04,10.149,4.2,13714.004],[700,0.04,10.149,4.2,13715.684],[700,0.04,10.149,4.2,13717.364],[700,0.04,10.149,4.2,13719.044],[700,0.04,10.149,4.2,13720.724],[700,0.04,10.149,4.2,13722.404],[700,0.04,10.149,4.2,13724.084],[700,0.04,10.149,4.2,13725.764],[700,0.04,10.149,4.2,13727.444],[700,0.04,10.149,4.2,13729.124],[700,0.04,10.149,4.2,13730.804],[700,0.04,10.149,4.2,13732.484],[700,0.04,10.149,4.2,13734.164],[700,0.04,10.149,4.2,13735.844],[700,0.04,10.149,4.2,13737.524],[700,0.04,10.149,4.2,13739.204],[700,0.04,10.149,4.2,13740.884],[700,0.04,10.149,4.2,13742.564],[700,0.04,10.149,4.2,13744.244],[700,0.04,10.149,4.2,13745.924],[700,0.04,10.149,4.2,13747.604],[700,0.04,10.149,4.2,13749.284],[700,0.04,10.149,4.2,13750.964],[700,0.04,10.149,4.2,13752.644],[700,0.04,10.149,4.2,13754.324],[700,0.04,10.149,4.2,13756.004],[700,0.04,10.149,4.2,13757.684],[700,0.04,10.149,4.2,13759.364],[700,0.04,10.149,4.2,13761.044],[700,0.04,10.149,4.2,13762.724],[700,0.04,10.149,4.2,13764.404],[700,0.04,10.149,4.2,13766.084],[700,0.04,10.149,4.2,13767.764],[700,0.04,10.149,4.2,13769.444],[700,0.04,10.149,4.2,13771.124],[700,0.04,10.149,4.2,13772.804],[700,0.04,10.149,4.2,13774.484],[700,0.04,10.149,4.2,13776.164],[700,0.04,10.149,4.2,13777.844],[700,0.04,10.149,4.2,13779.524],[700,0.04,10.149,4.2,13781.204],[700,0.04,10.149,4.2,13782.884],[700,0.04,10.149,4.2,13784.564],[700,0.04,10.149,4.2,13786.244],[700,0.04,10.149,4.2,13787.924],[700,0.04,10.149,4.2,13789.604],[700,0.04,10.149,4.2,13791.284],[700,0.04,10.149,4.2,13792.964],[700,0.04,10.149,4.2,13794.644],[700,0.04,10.149,4.2,13796.324],[700,0.04,10.149,4.2,13798.004],[700,0.04,10.149,4.2,13799.684],[700,0.04,10.149,4.2,13801.364],[700,0.04,10.149,4.2,13803.044],[700,0.04,10.149,4.2,13804.724],[700,0.04,10.149,4.2,13806.404],[700,0.04,10.149,4.2,13808.084],[700,0.04,10.149,4.2,13809.764],[700,0.04,10.149,4.2,13811.444],[700,0.04,10.149,4.2,13813.124],[700,0.04,10.149,4.2,13814.804],[700,0.04,10.149,4.2,13816.484],[700,0.04,10.149,4.2,13818.164],[700,0.04,10.149,4.2,13819.844],[700,0.04,10.149,4.2,13821.524],[700,0.04,10.149,4.2,13823.204],[700,0.04,10.149,4.2,13824.884],[700,0.04,10.149,4.2,13826.564],[700,0.04,10.149,4.2,13828.244],[700,0.04,10.149,4.2,13829.924],[700,0.04,10.149,4.2,13831.604],[700,0.04,10.149,4.2,13833.284],[700,0.04,10.149,4.2,13834.964],[700,0.04,10.149,4.2,13836.644],[700,0.04,10.149,4.2,13838.324],[700,0.04,10.149,4.2,13840.004],[700,0.04,10.149,4.2,13841.684],[700,0.04,10.149,4.2,13843.364],[700,0.04,10.149,4.2,13845.044],[700,0.04,10.149,4.2,13846.724],[700,0.04,10.149,4.2,13848.404],[700,0.04,10.149,4.2,13850.084],[700,0.04,10.149,4.2,13851.764],[700,0.04,10.149,4.2,13853.444],[700,0.04,10.149,4.2,13855.124],[700,0.04,10.149,4.2,13856.804],[700,0.04,10.149,4.2,13858.484],[700,0.04,10.149,4.2,13860.164],[700,0.04,10.149,4.2,13861.844],[700,0.04,10.149,4.2,13863.524],[700,0.04,10.149,4.2,13865.204],[700,0.04,10.149,4.2,13866.884],[700,0.04,10.149,4.2,13868.564],[700,0.04,10.149,4.2,13870.244],[700,0.04,10.149,4.2,13871.924],[700,0.04,10.149,4.2,13873.604],[700,0.04,10.149,4.2,13875.284],[700,0.04,10.149,4.2,13876.964],[700,0.04,10.149,4.2,13878.644],[700,0.04,10.149,4.2,13880.324],[700,0.04,10.149,4.2,13882.004],[700,0.04,10.149,4.2,13883.684],[700,0.04,10.149,4.2,13885.364],[700,0.04,10.149,4.2,13887.044],[700,0.04,10.149,4.2,13888.724],[700,0.04,10.149,4.2,13890.404],[700,0.04,10.149,4.2,13892.084],[700,0.04,10.149,4.2,13893.764],[700,0.04,10.149,4.2,13895.444],[700,0.04,10.149,4.2,13897.124],[700,0.04,10.149,4.2,13898.804],[700,0.04,10.149,4.2,13900.484],[700,0.04,10.149,4.2,13902.164],[700,0.04,10.149,4.2,13903.844],[700,0.04,10.149,4.2,13905.524],[700,0.04,10.149,4.2,13907.204],[700,0.04,10.149,4.2,13908.884],[700,0.04,10.149,4.2,13910.564],[700,0.04,10.149,4.2,13912.244],[700,0.04,10.149,4.2,13913.924],[700,0.04,10.149,4.2,13915.604],[700,0.04,10.149,4.2,13917.284],[700,0.04,10.149,4.2,13918.964],[700,0.04,10.149,4.2,13920.644],[700,0.04,10.149,4.2,13922.324],[700,0.04,10.149,4.2,13924.004],[700,0.04,10.149,4.2,13925.684],[700,0.04,10.149,4.2,13927.364],[700,0.04,10.149,4.2,13929.044],[700,0.04,10.149,4.2,13930.724],[700,0.04,10.149,4.2,13932.404],[700,0.04,10.149,4.2,13934.084],[700,0.04,10.149,4.2,13935.764],[700,0.04,10.149,4.2,13937.444],[700,0.04,10.149,4.2,13939.124],[700,0.04,10.149,4.2,13940.804],[700,0.04,10.149,4.2,13942.484],[700,0.04,10.149,4.2,13944.164],[700,0.04,10.149,4.2,13945.844],[700,0.04,10.149,4.2,13947.524],[700,0.04,10.149,4.2,13949.204],[700,0.04,10.149,4.2,13950.884],[700,0.04,10.149,4.2,13952.564],[700,0.04,10.149,4.2,13954.244],[700,0.04,10.149,4.2,13955.924],[700,0.04,10.149,4.2,13957.604],[700,0.04,10.149,4.2,13959.284],[700,0.04,10.149,4.2,13960.964],[700,0.04,10.149,4.2,13962.644],[700,0.04,10.149,4.2,13964.324],[700,0.04,10.149,4.2,13966.004],[700,0.04,10.149,4.2,13967.684],[700,0.04,10.149,4.2,13969.364],[700,0.04,10.149,4.2,13971.044],[700,0.04,10.149,4.2,13972.724],[700,0.04,10.149,4.2,13974.404],[700,0.04,10.149,4.2,13976.084],[700,0.04,10.149,4.2,13977.764],[700,0.04,10.149,4.2,13979.444],[700,0.04,10.149,4.2,13981.124],[700,0.04,10.149,4.2,13982.804],[700,0.04,10.149,4.2,13984.484],[700,0.04,10.149,4.2,13986.164],[700,0.04,10.149,4.2,13987.844],[700,0.04,10.149,4.2,13989.524],[700,0.04,10.149,4.2,13991.204],[700,0.04,10.149,4.2,13992.884],[700,0.04,10.149,4.2,13994.564],[700,0.04,10.149,4.2,13996.244],[700,0.04,10.149,4.2,13997.924],[700,0.04,10.149,4.2,13999.604],[700,0.04,10.149,4.2,14001.284],[700,0.04,10.149,4.2,14002.964],[700,0.04,10.149,4.2,14004.644],[700,0.04,10.149,4.2,14006.324],[700,0.04,10.149,4.2,14008.004],[700,0.04,10.149,4.2,14009.684],[700,0.04,10.149,4.2,14011.364],[700,0.04,10.149,4.2,14013.044],[700,0.04,10.149,4.2,14014.724],[700,0.04,10.149,4.2,14016.404],[700,0.04,10.149,4.2,14018.084],[700,0.04,10.149,4.2,14019.764],[700,0.04,10.149,4.2,14021.444],[700,0.04,10.149,4.2,14023.124],[700,0.04,10.149,4.2,14024.804],[700,0.04,10.149,4.2,14026.484],[700,0.04,10.149,4.2,14028.164],[700,0.04,10.149,4.2,14029.844],[700,0.04,10.149,4.2,14031.524],[700,0.04,10.149,4.2,14033.204],[700,0.04,10.149,4.2,14034.884],[700,0.04,10.149,4.2,14036.564],[700,0.04,10.149,4.2,14038.244],[700,0.04,10.149,4.2,14039.924],[700,0.04,10.149,4.2,14041.604],[700,0.04,10.149,4.2,14043.284],[700,0.04,10.149,4.2,14044.964],[700,0.04,10.149,4.2,14046.644],[700,0.04,10.149,4.2,14048.324],[700,0.04,10.149,4.2,14050.004],[700,0.04,10.149,4.2,14051.684],[700,0.04,10.149,4.2,14053.364],[700,0.04,10.149,4.2,14055.044],[700,0.04,10.149,4.2,14056.724],[700,0.04,10.149,4.2,14058.404],[700,0.04,10.149,4.2,14060.084],[700,0.04,10.149,4.2,14061.764],[700,0.04,10.149,4.2,14063.444],[700,0.04,10.149,4.2,14065.124],[700,0.04,10.149,4.2,14066.804],[700,0.04,10.149,4.2,14068.484],[700,0.04,10.149,4.2,14070.164],[700,0.04,10.149,4.2,14071.844],[700,0.04,10.149,4.2,14073.524],[700,0.04,10.149,4.2,14075.204],[700,0.04,10.149,4.2,14076.884],[700,0.04,10.149,4.2,14078.564],[700,0.04,10.149,4.2,14080.244],[700,0.04,10.149,4.2,14081.924],[700,0.04,10.149,4.2,14083.604],[700,0.04,10.149,4.2,14085.284],[700,0.04,10.149,4.2,14086.964],[700,0.04,10.149,4.2,14088.644],[700,0.04,10.149,4.2,14090.324],[700,0.04,10.149,4.2,14092.004],[700,0.04,10.149,4.2,14093.684],[700,0.04,10.149,4.2,14095.364],[700,0.04,10.149,4.2,14097.044],[700,0.04,10.149,4.2,14098.724],[700,0.04,10.149,4.2,14100.404],[700,0.04,10.149,4.2,14102.084],[700,0.04,10.149,4.2,14103.764],[700,0.04,10.149,4.2,14105.444],[700,0.04,10.149,4.2,14107.124],[700,0.04,10.149,4.2,14108.804],[700,0.04,10.149,4.2,14110.484],[700,0.04,10.149,4.2,14112.164],[700,0.04,10.149,4.2,14113.844],[700,0.04,10.149,4.2,14115.524],[700,0.04,10.149,4.2,14117.204],[700,0.04,10.149,4.2,14118.884],[700,0.04,10.149,4.2,14120.564],[700,0.04,10.149,4.2,14122.244],[700,0.04,10.149,4.2,14123.924],[700,0.04,10.149,4.2,14125.604],[700,0.04,10.149,4.2,14127.284],[700,0.04,10.149,4.2,14128.964],[700,0.04,10.149,4.2,14130.644],[700,0.04,10.149,4.2,14132.324],[700,0.04,10.149,4.2,14134.004],[700,0.04,10.149,4.2,14135.684],[700,0.04,10.149,4.2,14137.364],[700,0.04,10.149,4.2,14139.044],[700,0.04,10.149,4.2,14140.724],[700,0.04,10.149,4.2,14142.404],[700,0.04,10.149,4.2,14144.084],[700,0.04,10.149,4.2,14145.764],[700,0.04,10.149,4.2,14147.444],[700,0.04,10.149,4.2,14149.124],[700,0.04,10.149,4.2,14150.804],[700,0.04,10.149,4.2,14152.484],[700,0.04,10.149,4.2,14154.164],[700,0.04,10.149,4.2,14155.844],[700,0.04,10.149,4.2,14157.524],[700,0.04,10.149,4.2,14159.204],[700,0.04,10.149,4.2,14160.884],[700,0.04,10.149,4.2,14162.564],[700,0.04,10.149,4.2,14164.244],[700,0.04,10.149,4.2,14165.924],[700,0.04,10.149,4.2,14167.604],[700,0.04,10.149,4.2,14169.284],[700,0.04,10.149,4.2,14170.964],[700,0.04,10.149,4.2,14172.644],[700,0.04,10.149,4.2,14174.324],[700,0.04,10.149,4.2,14176.004],[700,0.04,10.149,4.2,14177.684],[700,0.04,10.149,4.2,14179.364],[700,0.04,10.149,4.2,14181.044],[700,0.04,10.149,4.2,14182.724],[700,0.04,10.149,4.2,14184.404],[700,0.04,10.149,4.2,14186.084],[700,0.04,10.149,4.2,14187.764],[700,0.04,10.149,4.2,14189.444],[700,0.04,10.149,4.2,14191.124],[700,0.04,10.149,4.2,14192.804],[700,0.04,10.149,4.2,14194.484],[700,0.04,10.149,4.2,14196.164],[700,0.04,10.149,4.2,14197.844],[700,0.04,10.149,4.2,14199.524],[700,0.04,10.149,4.2,14201.204],[700,0.04,10.149,4.2,14202.884],[700,0.04,10.149,4.2,14204.564],[700,0.04,10.149,4.2,14206.244],[700,0.04,10.149,4.2,14207.924],[700,0.04,10.149,4.2,14209.604],[700,0.04,10.149,4.2,14211.284],[700,0.04,10.149,4.2,14212.964],[700,0.04,10.149,4.2,14214.644],[700,0.04,10.149,4.2,14216.324],[700,0.04,10.149,4.2,14218.004],[700,0.04,10.149,4.2,14219.684],[700,0.04,10.149,4.2,14221.364],[700,0.04,10.149,4.2,14223.044],[700,0.04,10.149,4.2,14224.724],[700,0.04,10.149,4.2,14226.404],[700,0.04,10.149,4.2,14228.084],[700,0.04,10.149,4.2,14229.764],[700,0.04,10.149,4.2,14231.444],[700,0.04,10.149,4.2,14233.124],[700,0.04,10.149,4.2,14234.804],[700,0.04,10.149,4.2,14236.484],[700,0.04,10.149,4.2,14238.164],[700,0.04,10.149,4.2,14239.844],[700,0.04,10.149,4.2,14241.524],[700,0.04,10.149,4.2,14243.204],[700,0.04,10.149,4.2,14244.884],[700,0.04,10.149,4.2,14246.564],[700,0.04,10.149,4.2,14248.244],[700,0.04,10.149,4.2,14249.924],[700,0.04,10.149,4.2,14251.604],[700,0.04,10.149,4.2,14253.284],[700,0.04,10.149,4.2,14254.964],[700,0.04,10.149,4.2,14256.644],[700,0.04,10.149,4.2,14258.324],[700,0.04,10.149,4.2,14260.004],[700,0.04,10.149,4.2,14261.684],[700,0.04,10.149,4.2,14263.364],[700,0.04,10.149,4.2,14265.044],[700,0.04,10.149,4.2,14266.724],[700,0.04,10.149,4.2,14268.404],[700,0.04,10.149,4.2,14270.084],[700,0.04,10.149,4.2,14271.764],[700,0.04,10.149,4.2,14273.444],[700,0.04,10.149,4.2,14275.124],[700,0.04,10.149,4.2,14276.804],[700,0.04,10.149,4.2,14278.484],[700,0.04,10.149,4.2,14280.164],[700,0.04,10.149,4.2,14281.844],[700,0.04,10.149,4.2,14283.524],[700,0.04,10.149,4.2,14285.204],[700,0.04,10.149,4.2,14286.884],[700,0.04,10.149,4.2,14288.564],[700,0.04,10.149,4.2,14290.244],[700,0.04,10.149,4.2,14291.924],[700,0.04,10.149,4.2,14293.604],[700,0.04,10.149,4.2,14295.284],[700,0.04,10.149,4.2,14296.964],[700,0.04,10.149,4.2,14298.644],[700,0.04,10.149,4.2,14300.324],[700,0.04,10.149,4.2,14302.004],[700,0.04,10.149,4.2,14303.684],[700,0.04,10.149,4.2,14305.364],[700,0.04,10.149,4.2,14307.044],[700,0.04,10.149,4.2,14308.724],[700,0.04,10.149,4.2,14310.404],[700,0.04,10.149,4.2,14312.084],[700,0.04,10.149,4.2,14313.764],[700,0.04,10.149,4.2,14315.444],[700,0.04,10.149,4.2,14317.124],[700,0.04,10.149,4.2,14318.804],[700,0.04,10.149,4.2,14320.484],[700,0.04,10.149,4.2,14322.164],[700,0.04,10.149,4.2,14323.844],[700,0.04,10.149,4.2,14325.524],[700,0.04,10.149,4.2,14327.204],[700,0.04,10.149,4.2,14328.884],[700,0.04,10.149,4.2,14330.564],[700,0.04,10.149,4.2,14332.244],[700,0.04,10.149,4.2,14333.924],[700,0.04,10.149,4.2,14335.604],[700,0.04,10.149,4.2,14337.284],[700,0.04,10.149,4.2,14338.964],[700,0.04,10.149,4.2,14340.644],[700,0.04,10.149,4.2,14342.324],[700,0.04,10.149,4.2,14344.004],[700,0.04,10.149,4.2,14345.684],[700,0.04,10.149,4.2,14347.364],[700,0.04,10.149,4.2,14349.044],[700,0.04,10.149,4.2,14350.724],[700,0.04,10.149,4.2,14352.404],[700,0.04,10.149,4.2,14354.084],[700,0.04,10.149,4.2,14355.764],[700,0.04,10.149,4.2,14357.444],[700,0.04,10.149,4.2,14359.124],[700,0.04,10.149,4.2,14360.804],[700,0.04,10.149,4.2,14362.484],[700,0.04,10.149,4.2,14364.164],[700,0.04,10.149,4.2,14365.844],[700,0.04,10.149,4.2,14367.524],[700,0.04,10.149,4.2,14369.204],[700,0.04,10.149,4.2,14370.884],[700,0.04,10.149,4.2,14372.564],[700,0.04,10.149,4.2,14374.244],[700,0.04,10.149,4.2,14375.924],[700,0.04,10.149,4.2,14377.604],[700,0.04,10.149,4.2,14379.284],[700,0.04,10.149,4.2,14380.964],[700,0.04,10.149,4.2,14382.644],[700,0.04,10.149,4.2,14384.324],[700,0.04,10.149,4.2,14386.004],[700,0.04,10.149,4.2,14387.684],[700,0.04,10.149,4.2,14389.364],[700,0.04,10.149,4.2,14391.044],[700,0.04,10.149,4.2,14392.724],[700,0.04,10.149,4.2,14394.404],[700,0.04,10.149,4.2,14396.084],[700,0.04,10.149,4.2,14397.764],[700,0.04,10.149,4.2,14399.444],[700,0.04,10.149,4.2,14401.124],[700,0.04,10.149,4.2,14402.804],[700,0.04,10.149,4.2,14404.484],[700,0.04,10.149,4.2,14406.164],[700,0.04,10.149,4.2,14407.844],[700,0.04,10.149,4.2,14409.524],[700,0.04,10.149,4.2,14411.204],[700,0.04,10.149,4.2,14412.884],[700,0.04,10.149,4.2,14414.564],[700,0.04,10.149,4.2,14416.244],[700,0.04,10.149,4.2,14417.924],[700,0.04,10.149,4.2,14419.604],[700,0.04,10.149,4.2,14421.284],[700,0.04,10.149,4.2,14422.964],[700,0.04,10.149,4.2,14424.644],[700,0.04,10.149,4.2,14426.324],[700,0.04,10.149,4.2,14428.004],[700,0.04,10.149,4.2,14429.684],[700,0.04,10.149,4.2,14431.364],[700,0.04,10.149,4.2,14433.044],[700,0.04,10.149,4.2,14434.724],[700,0.04,10.149,4.2,14436.404],[700,0.04,10.149,4.2,14438.084],[700,0.04,10.149,4.2,14439.764],[700,0.04,10.149,4.2,14441.444],[700,0.04,10.149,4.2,14443.124],[700,0.04,10.149,4.2,14444.804],[700,0.04,10.149,4.2,14446.484],[700,0.04,10.149,4.2,14448.164],[700,0.04,10.149,4.2,14449.844],[700,0.04,10.149,4.2,14451.524],[700,0.04,10.149,4.2,14453.204],[700,0.04,10.149,4.2,14454.884],[700,0.04,10.149,4.2,14456.564],[700,0.04,10.149,4.2,14458.244],[700,0.04,10.149,4.2,14459.924],[700,0.04,10.149,4.2,14461.604],[700,0.04,10.149,4.2,14463.284],[700,0.04,10.149,4.2,14464.964],[700,0.04,10.149,4.2,14466.644],[700,0.04,10.149,4.2,14468.324],[700,0.04,10.149,4.2,14470.004],[700,0.04,10.149,4.2,14471.684],[700,0.04,10.149,4.2,14473.364],[700,0.04,10.149,4.2,14475.044],[700,0.04,10.149,4.2,14476.724],[700,0.04,10.149,4.2,14478.404],[700,0.04,10.149,4.2,14480.084],[700,0.04,10.149,4.2,14481.764],[700,0.04,10.149,4.2,14483.444],[700,0.04,10.149,4.2,14485.124],[700,0.04,10.149,4.199,14486.804],[700,0.04,10.149,4.198,14488.484],[700,0.04,10.149,4.196,14490.162],[700,0.04,10.149,4.193,14491.84],[700,0.04,10.149,4.188,14493.516],[700,0.04,10.149,4.183,14495.191],[700,0.04,10.149,4.176,14496.863],[700,0.04,10.149,4.168,14498.532],[700,0.04,10.149,4.159,14500.197],[700,0.04,10.149,4.148,14501.858],[700,0.039,10.149,4.135,14503.515],[700,0.039,10.149,4.121,14505.166],[700,0.039,10.149,4.105,14506.811],[700,0.039,10.149,4.087,14508.45],[700,0.039,10.149,4.068,14510.081],[700,0.039,10.149,4.047,14511.704],[700,0.038,10.149,4.025,14513.318],[700,0.038,10.149,4.001,14514.924],[700,0.038,10.149,3.975,14516.519],[700,0.038,10.149,3.948,14518.103],[700,0.037,10.149,3.92,14519.677],[700,0.037,10.149,3.89,14521.239],[700,0.037,10.149,3.859,14522.789],[700,0.036,10.149,3.827,14524.326],[700,0.036,10.149,3.794,14525.851],[700,0.036,10.149,3.761,14527.362],[700,0.035,10.149,3.726,14528.859],[700,0.035,10.149,3.69,14530.342],[700,0.035,10.149,3.654,14531.811],[700,0.034,10.149,3.618,14533.266],[700,0.034,10.149,3.581,14534.705],[700,0.034,10.149,3.544,14536.13],[700,0.033,10.149,3.506,14537.54],[700,0.033,10.149,3.469,14538.936],[700,0.033,10.149,3.432,14540.316],[700,0.032,10.149,3.394,14541.681],[700,0.032,10.149,3.357,14543.031],[700,0.032,10.149,3.32,14544.367],[700,0.031,10.149,3.284,14545.687],[700,0.031,10.149,3.248,14546.994],[700,0.031,10.149,3.213,14548.286],[700,0.03,10.149,3.178,14549.564],[700,0.03,10.149,3.144,14550.829],[700,0.03,10.149,3.111,14552.08],[700,0.029,10.149,3.079,14553.318],[700,0.029,10.149,3.047,14554.543],[700,0.029,10.149,3.017,14555.756],[700,0.028,10.149,2.987,14556.956],[700,0.028,10.149,2.959,14558.146],[700,0.028,10.149,2.932,14559.324],[700,0.028,10.149,2.906,14560.491],[700,0.027,10.149,2.881,14561.649],[700,0.027,10.149,2.857,14562.796],[700,0.027,10.149,2.834,14563.934],[700,0.027,10.149,2.813,14565.063],[700,0.027,10.149,2.793,14566.184],[700,0.026,10.149,2.774,14567.298],[700,0.026,10.149,2.756,14568.403],[700,0.026,10.149,2.739,14569.502],[700,0.026,10.149,2.724,14570.595],[700,0.026,10.149,2.71,14571.682],[700,0.026,10.149,2.697,14572.763],[700,0.026,10.149,2.686,14573.84],[700,0.025,10.149,2.675,14574.912],[700,0.025,10.149,2.666,14575.981],[700,0.025,10.149,2.658,14577.045],[700,0.025,10.149,2.651,14578.107],[700,0.025,10.149,2.645,14579.166],[700,0.025,10.149,2.64,14580.223],[700,0.025,10.149,2.636,14581.278],[700,0.025,10.149,2.632,14582.332],[700,0.025,10.149,2.63,14583.384],[700,0.025,10.149,2.628,14584.436],[700,0.025,10.149,2.626,14585.486],[700,0.025,10.149,2.626,14586.537],[700,0.025,10.149,2.625,14587.587],[700,0.025,10.149,2.625,14588.637],[700,0.025,10.149,2.625,14589.687],[700,0.025,10.149,2.625,14590.737],[700,0.025,10.149,2.625,14591.787],[700,0.025,10.149,2.625,14592.837],[700,0.025,10.149,2.625,14593.887],[700,0.025,10.149,2.625,14594.937],[700,0.025,10.149,2.625,14595.987],[700,0.025,10.149,2.625,14597.037],[700,0.025,10.149,2.625,14598.087],[700,0.025,10.149,2.625,14599.137],[700,0.025,10.149,2.625,14600.187],[700,0.025,10.149,2.625,14601.237],[700,0.025,10.149,2.625,14602.287],[700,0.025,10.149,2.625,14603.337],[700,0.025,10.149,2.625,14604.387],[700,0.025,10.149,2.625,14605.437],[700,0.025,10.149,2.625,14606.487],[700,0.025,10.149,2.625,14607.537],[700,0.025,10.149,2.625,14608.587],[700,0.025,10.149,2.625,14609.637],[700,0.025,10.149,2.625,14610.687],[700,0.025,10.149,2.625,14611.737],[700,0.025,10.149,2.625,14612.787],[700,0.025,10.149,2.625,14613.837],[700,0.025,10.149,2.625,14614.887],[700,0.025,10.149,2.625,14615.937],[700,0.025,10.149,2.625,14616.987],[700,0.025,10.149,2.625,14618.037],[700,0.025,10.149,2.625,14619.087],[700,0.025,10.149,2.625,14620.137],[700,0.025,10.149,2.625,14621.187],[700,0.025,10.149,2.625,14622.237],[700,0.025,10.149,2.625,14623.287],[700,0.025,10.149,2.625,14624.337],[700,0.025,10.149,2.625,14625.387],[700,0.025,10.149,2.625,14626.437],[700,0.025,10.149,2.625,14627.487],[700,0.025,10.149,2.625,14628.537],[700,0.025,10.149,2.625,14629.587],[700,0.025,10.149,2.625,14630.637],[700,0.025,10.149,2.625,14631.687],[700,0.025,10.149,2.625,14632.737],[700,0.025,10.149,2.625,14633.787],[700,0.025,10.149,2.625,14634.837],[700,0.025,10.149,2.625,14635.887],[700,0.025,10.149,2.625,14636.937],[700,0.025,10.149,2.625,14637.987],[700,0.025,10.149,2.625,14639.037],[700,0.025,10.149,2.625,14640.087],[700,0.025,10.149,2.625,14641.137],[700,0.025,10.149,2.625,14642.187],[700,0.025,10.149,2.625,14643.237],[700,0.025,10.149,2.625,14644.287],[700,0.025,10.149,2.625,14645.337],[700,0.025,10.149,2.625,14646.387],[700,0.025,10.149,2.625,14647.437],[700,0.025,10.149,2.625,14648.487],[700,0.025,10.149,2.625,14649.537],[700,0.025,10.149,2.625,14650.587],[700,0.025,10.149,2.625,14651.637],[700,0.025,10.149,2.625,14652.687],[700,0.025,10.149,2.625,14653.737],[700,0.025,10.149,2.625,14654.787],[700,0.025,10.149,2.625,14655.837],[700,0.025,10.149,2.625,14656.887],[700,0.025,10.149,2.625,14657.937],[700,0.025,10.149,2.625,14658.987],[700,0.025,10.149,2.625,14660.037],[700,0.025,10.149,2.625,14661.087],[700,0.025,10.149,2.625,14662.137],[700,0.025,10.149,2.625,14663.187],[700,0.025,10.149,2.625,14664.237],[700,0.025,10.149,2.625,14665.287],[700,0.025,10.149,2.625,14666.337],[700,0.025,10.149,2.625,14667.387],[700,0.025,10.149,2.625,14668.437],[700,0.025,10.149,2.625,14669.487],[700,0.025,10.149,2.625,14670.537],[700,0.025,10.149,2.625,14671.587],[700,0.025,10.149,2.625,14672.637],[700,0.025,10.149,2.625,14673.687],[700,0.025,10.149,2.625,14674.737],[700,0.025,10.149,2.625,14675.787],[700,0.025,10.149,2.625,14676.837],[700,0.025,10.149,2.625,14677.887],[700,0.025,10.149,2.625,14678.937],[700,0.025,10.149,2.625,14679.987],[700,0.025,10.149,2.625,14681.037],[700,0.025,10.149,2.625,14682.087],[700,0.025,10.149,2.625,14683.137],[700,0.025,10.149,2.625,14684.187],[700,0.025,10.149,2.625,14685.237],[700,0.025,10.149,2.625,14686.287],[700,0.025,10.149,2.625,14687.337],[700,0.025,10.149,2.625,14688.387],[700,0.025,10.149,2.625,14689.437],[700,0.025,10.149,2.625,14690.487],[700,0.025,10.149,2.625,14691.537],[700,0.025,10.149,2.625,14692.587],[700,0.025,10.149,2.625,14693.637],[700,0.025,10.149,2.625,14694.687],[700,0.025,10.149,2.625,14695.737],[700,0.025,10.149,2.625,14696.787],[700,0.025,10.149,2.625,14697.837],[700,0.025,10.149,2.625,14698.887],[700,0.025,10.149,2.625,14699.937],[700,0.025,10.149,2.625,14700.987],[700,0.025,10.149,2.625,14702.037],[700,0.025,10.149,2.625,14703.087],[700,0.025,10.149,2.625,14704.137],[700,0.025,10.149,2.625,14705.187],[700,0.025,10.149,2.625,14706.237],[700,0.025,10.149,2.625,14707.287],[700,0.025,10.149,2.625,14708.337],[700,0.025,10.149,2.625,14709.387],[700,0.025,10.149,2.625,14710.437],[700,0.025,10.149,2.625,14711.487],[700,0.025,10.149,2.625,14712.537],[700,0.025,10.149,2.625,14713.587],[700,0.025,10.149,2.625,14714.637],[700,0.025,10.149,2.625,14715.687],[700,0.025,10.149,2.625,14716.737],[700,0.025,10.149,2.625,14717.787],[700,0.025,10.149,2.625,14718.837],[700,0.025,10.149,2.625,14719.887],[700,0.025,10.149,2.625,14720.937],[700,0.025,10.149,2.625,14721.987],[700,0.025,10.149,2.625,14723.037],[700,0.025,10.149,2.625,14724.087],[700,0.025,10.149,2.625,14725.137],[700,0.025,10.149,2.625,14726.187],[700,0.025,10.149,2.625,14727.237],[700,0.025,10.149,2.625,14728.287],[700,0.025,10.149,2.625,14729.337],[700,0.025,10.149,2.625,14730.387],[700,0.025,10.149,2.625,14731.437],[700,0.025,10.149,2.625,14732.487],[700,0.025,10.149,2.625,14733.537],[700,0.025,10.149,2.625,14734.587],[700,0.025,10.149,2.625,14735.637],[700,0.025,10.149,2.625,14736.687],[700,0.025,10.149,2.625,14737.737],[700,0.025,10.149,2.625,14738.787],[700,0.025,10.149,2.625,14739.837],[700,0.025,10.149,2.625,14740.887],[700,0.025,10.149,2.625,14741.937],[700,0.025,10.149,2.625,14742.987],[700,0.025,10.149,2.625,14744.037],[700,0.025,10.149,2.625,14745.087],[700,0.025,10.149,2.625,14746.137],[700,0.025,10.149,2.625,14747.187],[700,0.025,10.149,2.625,14748.237],[700,0.025,10.149,2.625,14749.287],[700,0.025,10.149,2.625,14750.337],[700,0.025,10.149,2.625,14751.387],[700,0.025,10.149,2.625,14752.437],[700,0.025,10.149,2.625,14753.487],[700,0.025,10.149,2.625,14754.537],[700,0.025,10.149,2.625,14755.587],[700,0.025,10.149,2.625,14756.637],[700,0.025,10.149,2.625,14757.687],[700,0.025,10.149,2.625,14758.737],[700,0.025,10.149,2.625,14759.787],[700,0.025,10.149,2.625,14760.837],[700,0.025,10.149,2.625,14761.887],[700,0.025,10.149,2.625,14762.937],[700,0.025,10.149,2.625,14763.987],[700,0.025,10.149,2.625,14765.037],[700,0.025,10.149,2.625,14766.087],[700,0.025,10.149,2.625,14767.137],[700,0.025,10.149,2.625,14768.187],[700,0.025,10.149,2.625,14769.237],[700,0.025,10.149,2.625,14770.287],[700,0.025,10.149,2.625,14771.337],[700,0.025,10.149,2.625,14772.387],[700,0.025,10.149,2.625,14773.437],[700,0.025,10.149,2.625,14774.487],[700,0.025,10.149,2.625,14775.537],[700,0.025,10.149,2.625,14776.587],[700,0.025,10.149,2.625,14777.637],[700,0.025,10.149,2.625,14778.687],[700,0.025,10.149,2.625,14779.737],[700,0.025,10.149,2.625,14780.787],[700,0.025,10.149,2.625,14781.837],[700,0.025,10.149,2.625,14782.887],[700,0.025,10.149,2.625,14783.937],[700,0.025,10.149,2.625,14784.987],[700,0.025,10.149,2.625,14786.037],[700,0.025,10.149,2.625,14787.087],[700,0.025,10.149,2.625,14788.137],[700,0.025,10.149,2.625,14789.187],[700,0.025,10.149,2.625,14790.237],[700,0.025,10.149,2.625,14791.287],[700,0.025,10.149,2.625,14792.337],[700,0.025,10.149,2.625,14793.387],[700,0.025,10.149,2.625,14794.437],[700,0.025,10.149,2.625,14795.487],[700,0.025,10.149,2.625,14796.537],[700,0.025,10.149,2.625,14797.587],[700,0.025,10.149,2.625,14798.637],[700,0.025,10.149,2.625,14799.687],[700,0.025,10.149,2.625,14800.737],[700,0.025,10.149,2.625,14801.787],[700,0.025,10.149,2.625,14802.837],[700,0.025,10.149,2.625,14803.887],[700,0.025,10.149,2.625,14804.937],[700,0.025,10.149,2.625,14805.987],[700,0.025,10.149,2.625,14807.037],[700,0.025,10.149,2.625,14808.087],[700,0.025,10.149,2.625,14809.137],[700,0.025,10.149,2.625,14810.187],[700,0.025,10.149,2.625,14811.237],[700,0.025,10.149,2.625,14812.287],[700,0.025,10.149,2.625,14813.337],[700,0.025,10.149,2.625,14814.387],[700,0.025,10.149,2.625,14815.437],[700,0.025,10.149,2.625,14816.487],[700,0.025,10.149,2.625,14817.537],[700,0.025,10.149,2.625,14818.587],[700,0.025,10.149,2.625,14819.637],[700,0.025,10.149,2.625,14820.687],[700,0.025,10.149,2.625,14821.737],[700,0.025,10.149,2.625,14822.787],[700,0.025,10.149,2.625,14823.837],[700,0.025,10.149,2.625,14824.887],[700,0.025,10.149,2.625,14825.937],[700,0.025,10.149,2.625,14826.987],[700,0.025,10.149,2.625,14828.037],[700,0.025,10.149,2.625,14829.087],[700,0.025,10.149,2.625,14830.137],[700,0.025,10.149,2.625,14831.187],[700,0.025,10.149,2.625,14832.237],[700,0.025,10.149,2.625,14833.287],[700,0.025,10.149,2.625,14834.337],[700,0.025,10.149,2.625,14835.387],[700,0.025,10.149,2.625,14836.437],[700,0.025,10.149,2.625,14837.487],[700,0.025,10.149,2.625,14838.537],[700,0.025,10.149,2.625,14839.587],[700,0.025,10.149,2.625,14840.637],[700,0.025,10.149,2.625,14841.687],[700,0.025,10.149,2.625,14842.737],[700,0.025,10.149,2.625,14843.787],[700,0.025,10.149,2.625,14844.837],[700,0.025,10.149,2.625,14845.887],[700,0.025,10.149,2.625,14846.937],[700,0.025,10.149,2.625,14847.987],[700,0.025,10.149,2.625,14849.037],[700,0.025,10.149,2.625,14850.087],[700,0.025,10.149,2.625,14851.137],[700,0.025,10.149,2.625,14852.187],[700,0.025,10.149,2.625,14853.237],[700,0.025,10.149,2.625,14854.287],[700,0.025,10.149,2.625,14855.337],[700,0.025,10.149,2.625,14856.387],[700,0.025,10.149,2.625,14857.437],[700,0.025,10.149,2.625,14858.487],[700,0.025,10.149,2.625,14859.537],[700,0.025,10.149,2.625,14860.587],[700,0.025,10.149,2.625,14861.637],[700,0.025,10.149,2.625,14862.687],[700,0.025,10.149,2.625,14863.737],[700,0.025,10.149,2.625,14864.787],[700,0.025,10.149,2.625,14865.837],[700,0.025,10.149,2.625,14866.887],[700,0.025,10.149,2.625,14867.937],[700,0.025,10.149,2.625,14868.987],[700,0.025,10.149,2.625,14870.037],[700,0.025,10.149,2.625,14871.087],[700,0.025,10.149,2.625,14872.137],[700,0.025,10.149,2.625,14873.187],[700,0.025,10.149,2.625,14874.237],[700,0.025,10.149,2.625,14875.287],[700,0.025,10.149,2.625,14876.337],[700,0.025,10.149,2.625,14877.387],[700,0.025,10.149,2.625,14878.437],[700,0.025,10.149,2.625,14879.487],[700,0.025,10.149,2.625,14880.537],[700,0.025,10.149,2.625,14881.587],[700,0.025,10.149,2.625,14882.637],[700,0.025,10.149,2.625,14883.687],[700,0.025,10.149,2.625,14884.737],[700,0.025,10.149,2.625,14885.787],[700,0.025,10.149,2.625,14886.837],[700,0.025,10.149,2.625,14887.887],[700,0.025,10.149,2.625,14888.937],[700,0.025,10.149,2.625,14889.987],[700,0.025,10.149,2.625,14891.037],[700,0.025,10.149,2.625,14892.087],[700,0.025,10.149,2.625,14893.137],[700,0.025,10.149,2.625,14894.187],[700,0.025,10.149,2.625,14895.237],[700,0.025,10.149,2.625,14896.287],[700,0.025,10.149,2.625,14897.337],[700,0.025,10.149,2.625,14898.387],[700,0.025,10.149,2.625,14899.437],[700,0.025,10.149,2.625,14900.487],[700,0.025,10.149,2.625,14901.537],[700,0.025,10.149,2.625,14902.587],[700,0.025,10.149,2.625,14903.637],[700,0.025,10.149,2.625,14904.687],[700,0.025,10.149,2.625,14905.737],[700,0.025,10.149,2.625,14906.787],[700,0.025,10.149,2.625,14907.837],[700,0.025,10.149,2.625,14908.887],[700,0.025,10.149,2.625,14909.937],[700,0.025,10.149,2.625,14910.987],[700,0.025,10.149,2.625,14912.037],[700,0.025,10.149,2.625,14913.087],[700,0.025,10.149,2.625,14914.137],[700,0.025,10.149,2.625,14915.187],[700,0.025,10.149,2.625,14916.237],[700,0.025,10.149,2.625,14917.287],[700,0.025,10.149,2.625,14918.337],[700,0.025,10.149,2.625,14919.387],[700,0.025,10.149,2.625,14920.437],[700,0.025,10.149,2.625,14921.487],[700,0.025,10.149,2.625,14922.537],[700,0.025,10.149,2.625,14923.587],[700,0.025,10.149,2.625,14924.637],[700,0.025,10.149,2.625,14925.687],[700,0.025,10.149,2.625,14926.737],[700,0.025,10.149,2.625,14927.787],[700,0.025,10.149,2.625,14928.837],[700,0.025,10.149,2.625,14929.887],[700,0.025,10.149,2.625,14930.937],[700,0.025,10.149,2.625,14931.987],[700,0.025,10.149,2.625,14933.037],[700,0.025,10.149,2.625,14934.087],[700,0.025,10.149,2.625,14935.137],[700,0.025,10.149,2.625,14936.187],[700,0.025,10.149,2.625,14937.237],[700,0.025,10.149,2.625,14938.287],[700,0.025,10.149,2.625,14939.337],[700,0.025,10.149,2.625,14940.387],[700,0.025,10.149,2.625,14941.437],[700,0.025,10.149,2.625,14942.487],[700,0.025,10.149,2.625,14943.537],[700,0.025,10.149,2.625,14944.587],[700,0.025,10.149,2.625,14945.637],[700,0.025,10.149,2.625,14946.687],[700,0.025,10.149,2.625,14947.737],[700,0.025,10.149,2.625,14948.787],[700,0.025,10.149,2.625,14949.837],[700,0.025,10.149,2.625,14950.887],[700,0.025,10.149,2.625,14951.937],[700,0.025,10.149,2.625,14952.987],[700,0.025,10.149,2.625,14954.037],[700,0.025,10.149,2.625,14955.087],[700,0.025,10.149,2.625,14956.137],[700,0.025,10.149,2.625,14957.187],[700,0.025,10.149,2.625,14958.237],[700,0.025,10.149,2.625,14959.287],[700,0.025,10.149,2.625,14960.337],[700,0.025,10.149,2.625,14961.387],[700,0.025,10.149,2.625,14962.437],[700,0.025,10.149,2.625,14963.487],[700,0.025,10.149,2.625,14964.537],[700,0.025,10.149,2.625,14965.587],[700,0.025,10.149,2.625,14966.637],[700,0.025,10.149,2.625,14967.687],[700,0.025,10.149,2.625,14968.737],[700,0.025,10.149,2.625,14969.787],[700,0.025,10.149,2.625,14970.837],[700,0.025,10.149,2.625,14971.887],[700,0.025,10.149,2.625,14972.937],[700,0.025,10.149,2.625,14973.987],[700,0.025,10.149,2.625,14975.037],[700,0.025,10.149,2.625,14976.087],[700,0.025,10.149,2.625,14977.137],[700,0.025,10.149,2.625,14978.187],[700,0.025,10.149,2.625,14979.237],[700,0.025,10.149,2.625,14980.287],[700,0.025,10.149,2.625,14981.337],[700,0.025,10.149,2.625,14982.387],[700,0.025,10.149,2.625,14983.437],[700,0.025,10.149,2.625,14984.487],[700,0.025,10.149,2.625,14985.537],[700,0.025,10.149,2.625,14986.587],[700,0.025,10.149,2.625,14987.637],[700,0.025,10.149,2.625,14988.687],[700,0.025,10.149,2.625,14989.737],[700,0.025,10.149,2.625,14990.787],[700,0.025,10.149,2.625,14991.837],[700,0.025,10.149,2.625,14992.887],[700,0.025,10.149,2.625,14993.937],[700,0.025,10.149,2.625,14994.987],[700,0.025,10.149,2.625,14996.037],[700,0.025,10.149,2.625,14997.087],[700,0.025,10.149,2.625,14998.137],[700,0.025,10.149,2.625,14999.187],[700,0.025,10.149,2.625,15000.237],[700,0.025,10.149,2.625,15001.287],[700,0.025,10.149,2.625,15002.337],[700,0.025,10.149,2.625,15003.387],[700,0.025,10.149,2.625,15004.437],[700,0.025,10.149,2.625,15005.487],[700,0.025,10.149,2.625,15006.537],[700,0.025,10.149,2.625,15007.587],[700,0.025,10.149,2.625,15008.637],[700,0.025,10.149,2.625,15009.687],[700,0.025,10.149,2.625,15010.737],[700,0.025,10.149,2.625,15011.787],[700,0.025,10.149,2.625,15012.837],[700,0.025,10.149,2.625,15013.887],[700,0.025,10.149,2.625,15014.937],[700,0.025,10.149,2.625,15015.987],[700,0.025,10.149,2.625,15017.037],[700,0.025,10.149,2.625,15018.087],[700,0.025,10.149,2.625,15019.137],[700,0.025,10.149,2.625,15020.187],[700,0.025,10.149,2.625,15021.237],[700,0.025,10.149,2.625,15022.287],[700,0.025,10.149,2.625,15023.337],[700,0.025,10.149,2.625,15024.387],[700,0.025,10.149,2.625,15025.437],[700,0.025,10.149,2.625,15026.487],[700,0.025,10.149,2.625,15027.537],[700,0.025,10.149,2.625,15028.587],[700,0.025,10.149,2.625,15029.637],[700,0.025,10.149,2.625,15030.687],[700,0.025,10.149,2.625,15031.737],[700,0.025,10.149,2.625,15032.787],[700,0.025,10.149,2.625,15033.837],[700,0.025,10.149,2.625,15034.887],[700,0.025,10.149,2.625,15035.937],[700,0.025,10.149,2.625,15036.987],[700,0.025,10.149,2.625,15038.037],[700,0.025,10.149,2.625,15039.087],[700,0.025,10.149,2.625,15040.137],[700,0.025,10.149,2.625,15041.187],[700,0.025,10.149,2.625,15042.237],[700,0.025,10.149,2.625,15043.287],[700,0.025,10.149,2.625,15044.337],[700,0.025,10.149,2.625,15045.387],[700,0.025,10.149,2.625,15046.437],[700,0.025,10.149,2.625,15047.487],[700,0.025,10.149,2.625,15048.537],[700,0.025,10.149,2.625,15049.587],[700,0.025,10.149,2.625,15050.637],[700,0.025,10.149,2.625,15051.687],[700,0.025,10.149,2.625,15052.737],[700,0.025,10.149,2.625,15053.787],[700,0.025,10.149,2.625,15054.837],[700,0.025,10.149,2.625,15055.887],[700,0.025,10.149,2.625,15056.937],[700,0.025,10.149,2.625,15057.987],[700,0.025,10.149,2.625,15059.037],[700,0.025,10.149,2.625,15060.087],[700,0.025,10.149,2.625,15061.137],[700,0.025,10.149,2.625,15062.187],[700,0.025,10.149,2.625,15063.237],[700,0.025,10.149,2.625,15064.287],[700,0.025,10.149,2.625,15065.337],[700,0.025,10.149,2.625,15066.387],[700,0.025,10.149,2.625,15067.437],[700,0.025,10.149,2.625,15068.487],[700,0.025,10.149,2.625,15069.537],[700,0.025,10.149,2.625,15070.587],[700,0.025,10.149,2.625,15071.637],[700,0.025,10.149,2.625,15072.687],[700,0.025,10.149,2.625,15073.737],[700,0.025,10.149,2.625,15074.787],[700,0.025,10.149,2.625,15075.837],[700,0.025,10.149,2.625,15076.887],[700,0.025,10.149,2.625,15077.937],[700,0.025,10.149,2.625,15078.987],[700,0.025,10.149,2.625,15080.037],[700,0.025,10.149,2.625,15081.087],[700,0.025,10.149,2.625,15082.137],[700,0.025,10.149,2.625,15083.187],[700,0.025,10.149,2.625,15084.237],[700,0.025,10.149,2.625,15085.287],[700,0.025,10.149,2.625,15086.337],[700,0.025,10.149,2.625,15087.387],[700,0.025,10.149,2.625,15088.437],[700,0.025,10.149,2.625,15089.487],[700,0.025,10.149,2.625,15090.537],[700,0.025,10.149,2.625,15091.587],[700,0.025,10.149,2.625,15092.637],[700,0.025,10.149,2.625,15093.687],[700,0.025,10.149,2.625,15094.737],[700,0.025,10.149,2.625,15095.787],[700,0.025,10.149,2.625,15096.837],[700,0.025,10.149,2.625,15097.887],[700,0.025,10.149,2.625,15098.937],[700,0.025,10.149,2.625,15099.987],[700,0.025,10.149,2.625,15101.037],[700,0.025,10.149,2.625,15102.087],[700,0.025,10.149,2.625,15103.137],[700,0.025,10.149,2.625,15104.187],[700,0.025,10.149,2.625,15105.237],[700,0.025,10.149,2.625,15106.287],[700,0.025,10.149,2.625,15107.337],[700,0.025,10.149,2.625,15108.387],[700,0.025,10.149,2.625,15109.437],[700,0.025,10.149,2.625,15110.487],[700,0.025,10.149,2.625,15111.537],[700,0.025,10.149,2.625,15112.587],[700,0.025,10.149,2.625,15113.637],[700,0.025,10.149,2.625,15114.687],[700,0.025,10.149,2.625,15115.737],[700,0.025,10.149,2.625,15116.787],[700,0.025,10.149,2.625,15117.837],[700,0.025,10.149,2.625,15118.887],[700,0.025,10.149,2.625,15119.937],[700,0.025,10.149,2.625,15120.987],[700,0.025,10.149,2.625,15122.037],[700,0.025,10.149,2.625,15123.087],[700,0.025,10.149,2.625,15124.137],[700,0.025,10.149,2.625,15125.187],[700,0.025,10.149,2.625,15126.237],[700,0.025,10.149,2.625,15127.287],[700,0.025,10.149,2.625,15128.337],[700,0.025,10.149,2.625,15129.387],[700,0.025,10.149,2.625,15130.437],[700,0.025,10.149,2.625,15131.487],[700,0.025,10.149,2.625,15132.537],[700,0.025,10.149,2.625,15133.587],[700,0.025,10.149,2.625,15134.637],[700,0.025,10.149,2.625,15135.687],[700,0.025,10.149,2.625,15136.737],[700,0.025,10.149,2.625,15137.787],[700,0.025,10.149,2.625,15138.837],[700,0.025,10.149,2.625,15139.887],[700,0.025,10.149,2.625,15140.937],[700,0.025,10.149,2.625,15141.987],[700,0.025,10.149,2.625,15143.037],[700,0.025,10.149,2.625,15144.087],[700,0.025,10.149,2.625,15145.137],[700,0.025,10.149,2.625,15146.187],[700,0.025,10.149,2.625,15147.237],[700,0.025,10.149,2.625,15148.287],[700,0.025,10.149,2.625,15149.337],[700,0.025,10.149,2.625,15150.387],[700,0.025,10.149,2.625,15151.437],[700,0.025,10.149,2.625,15152.487],[700,0.025,10.149,2.625,15153.537],[700,0.025,10.149,2.625,15154.587],[700,0.025,10.149,2.625,15155.637],[700,0.025,10.149,2.625,15156.687],[700,0.025,10.149,2.625,15157.737],[700,0.025,10.149,2.625,15158.787],[700,0.025,10.149,2.625,15159.837],[700,0.025,10.149,2.625,15160.887],[700,0.025,10.149,2.625,15161.937],[700,0.025,10.149,2.625,15162.987],[700,0.025,10.149,2.625,15164.037],[700,0.025,10.149,2.625,15165.087],[700,0.025,10.149,2.625,15166.137],[700,0.025,10.149,2.625,15167.187],[700,0.025,10.149,2.625,15168.237],[700,0.025,10.149,2.625,15169.287],[700,0.025,10.149,2.625,15170.337],[700,0.025,10.149,2.625,15171.387],[700,0.025,10.149,2.625,15172.437],[700,0.025,10.149,2.625,15173.487],[700,0.025,10.149,2.625,15174.537],[700,0.025,10.149,2.625,15175.587],[700,0.025,10.149,2.625,15176.637],[700,0.025,10.149,2.625,15177.687],[700,0.025,10.149,2.625,15178.737],[700,0.025,10.149,2.625,15179.787],[700,0.025,10.149,2.625,15180.837],[700,0.025,10.149,2.625,15181.887],[700,0.025,10.149,2.625,15182.937],[700,0.025,10.149,2.625,15183.987],[700,0.025,10.149,2.625,15185.037],[700,0.025,10.149,2.625,15186.087],[700,0.025,10.149,2.625,15187.137],[700,0.025,10.149,2.625,15188.187],[700,0.025,10.149,2.625,15189.237],[700,0.025,10.149,2.625,15190.287],[700,0.025,10.149,2.625,15191.337],[700,0.025,10.149,2.625,15192.387],[700,0.025,10.149,2.625,15193.437],[700,0.025,10.149,2.625,15194.487],[700,0.025,10.149,2.625,15195.537],[700,0.025,10.149,2.625,15196.587],[700,0.025,10.149,2.625,15197.637],[700,0.025,10.149,2.625,15198.687],[700,0.025,10.149,2.625,15199.737],[700,0.025,10.149,2.625,15200.787],[700,0.025,10.149,2.625,15201.837],[700,0.025,10.149,2.625,15202.887],[700,0.025,10.149,2.625,15203.937],[700,0.025,10.149,2.625,15204.987],[700,0.025,10.149,2.625,15206.037],[700,0.025,10.149,2.625,15207.087],[700,0.025,10.149,2.625,15208.137],[700,0.025,10.149,2.625,15209.187],[700,0.025,10.149,2.625,15210.237],[700,0.025,10.149,2.625,15211.287],[700,0.025,10.149,2.625,15212.337],[700,0.025,10.149,2.625,15213.387],[700,0.025,10.149,2.625,15214.437],[700,0.025,10.149,2.625,15215.487],[700,0.025,10.149,2.625,15216.537],[700,0.025,10.149,2.625,15217.587],[700,0.025,10.149,2.625,15218.637],[700,0.025,10.149,2.625,15219.687],[700,0.025,10.149,2.625,15220.737],[700,0.025,10.149,2.625,15221.787],[700,0.025,10.149,2.625,15222.837],[700,0.025,10.149,2.625,15223.887],[700,0.025,10.149,2.625,15224.937],[700,0.025,10.149,2.625,15225.987],[700,0.025,10.149,2.625,15227.037],[700,0.025,10.149,2.625,15228.087],[700,0.025,10.149,2.625,15229.137],[700,0.025,10.149,2.625,15230.187],[700,0.025,10.149,2.625,15231.237],[700,0.025,10.149,2.625,15232.287],[700,0.025,10.149,2.625,15233.337],[700,0.025,10.149,2.625,15234.387],[700,0.025,10.149,2.625,15235.437],[700,0.025,10.149,2.625,15236.487],[700,0.025,10.149,2.625,15237.537],[700,0.025,10.149,2.625,15238.587],[700,0.025,10.149,2.625,15239.637],[700,0.025,10.149,2.625,15240.687],[700,0.025,10.149,2.625,15241.737],[700,0.025,10.149,2.625,15242.787],[700,0.025,10.149,2.625,15243.837],[700,0.025,10.149,2.625,15244.887],[700,0.025,10.149,2.625,15245.937],[700,0.025,10.149,2.625,15246.987],[700,0.025,10.149,2.625,15248.037],[700,0.025,10.149,2.625,15249.087],[700,0.025,10.149,2.625,15250.137],[700,0.025,10.149,2.625,15251.187],[700,0.025,10.149,2.625,15252.237],[700,0.025,10.149,2.625,15253.287],[700,0.025,10.149,2.625,15254.337],[700,0.025,10.149,2.625,15255.387],[700,0.025,10.149,2.625,15256.437],[700,0.025,10.149,2.625,15257.487],[700,0.025,10.149,2.625,15258.537],[700,0.025,10.149,2.625,15259.587],[700,0.025,10.149,2.625,15260.637],[700,0.025,10.149,2.625,15261.687],[700,0.025,10.149,2.625,15262.737],[700,0.025,10.149,2.625,15263.787],[700,0.025,10.149,2.625,15264.837],[700,0.025,10.149,2.625,15265.887],[700,0.025,10.149,2.625,15266.937],[700,0.025,10.149,2.625,15267.987],[700,0.025,10.149,2.625,15269.037],[700,0.025,10.149,2.625,15270.087],[700,0.025,10.149,2.625,15271.137],[700,0.025,10.149,2.625,15272.187],[700,0.025,10.149,2.625,15273.237],[700,0.025,10.149,2.625,15274.287],[700,0.025,10.149,2.625,15275.337],[700,0.025,10.149,2.625,15276.387],[700,0.025,10.149,2.625,15277.437],[700,0.025,10.149,2.625,15278.487],[700,0.025,10.149,2.625,15279.537],[700,0.025,10.149,2.625,15280.587],[700,0.025,10.149,2.625,15281.637],[700,0.025,10.149,2.625,15282.687],[700,0.025,10.149,2.625,15283.737],[700,0.025,10.149,2.625,15284.787],[700,0.025,10.149,2.625,15285.837],[700,0.025,10.149,2.625,15286.887],[700,0.025,10.149,2.625,15287.937],[700,0.025,10.149,2.625,15288.987],[700,0.025,10.149,2.625,15290.037],[700,0.025,10.149,2.625,15291.087],[700,0.025,10.149,2.625,15292.137],[700,0.025,10.149,2.625,15293.187],[700,0.025,10.149,2.625,15294.237],[700,0.025,10.149,2.625,15295.287],[700,0.025,10.149,2.625,15296.337],[700,0.025,10.149,2.625,15297.387],[700,0.025,10.149,2.625,15298.437],[700,0.025,10.149,2.625,15299.487],[700,0.025,10.149,2.625,15300.537],[700,0.025,10.149,2.625,15301.587],[700,0.025,10.149,2.625,15302.637],[700,0.025,10.149,2.625,15303.687],[700,0.025,10.149,2.625,15304.737],[700,0.025,10.149,2.625,15305.787],[700,0.025,10.149,2.625,15306.837],[700,0.025,10.149,2.625,15307.887],[700,0.025,10.149,2.625,15308.937],[700,0.025,10.149,2.625,15309.987],[700,0.025,10.149,2.625,15311.037],[700,0.025,10.149,2.625,15312.087],[700,0.025,10.149,2.625,15313.137],[700,0.025,10.149,2.625,15314.187],[700,0.025,10.149,2.625,15315.237],[700,0.025,10.149,2.625,15316.287],[700,0.025,10.149,2.625,15317.337],[700,0.025,10.149,2.625,15318.387],[700,0.025,10.149,2.625,15319.437],[700,0.025,10.149,2.625,15320.487],[700,0.025,10.149,2.625,15321.537],[700,0.025,10.149,2.625,15322.587],[700,0.025,10.149,2.625,15323.637],[700,0.025,10.149,2.625,15324.687],[700,0.025,10.149,2.625,15325.737],[700,0.025,10.149,2.625,15326.787],[700,0.025,10.149,2.625,15327.837],[700,0.025,10.149,2.625,15328.887],[700,0.025,10.149,2.625,15329.937],[700,0.025,10.149,2.625,15330.987],[700,0.025,10.149,2.625,15332.037],[700,0.025,10.149,2.625,15333.087],[700,0.025,10.149,2.625,15334.137],[700,0.025,10.149,2.625,15335.187],[700,0.025,10.149,2.625,15336.237],[700,0.025,10.149,2.625,15337.287],[700,0.025,10.149,2.625,15338.337],[700,0.025,10.149,2.625,15339.387],[700,0.025,10.149,2.625,15340.437],[700,0.025,10.149,2.625,15341.487],[700,0.025,10.149,2.625,15342.537],[700,0.025,10.149,2.625,15343.587],[700,0.025,10.149,2.625,15344.637],[700,0.025,10.149,2.625,15345.687],[700,0.025,10.149,2.625,15346.737],[700,0.025,10.149,2.625,15347.787],[700,0.025,10.149,2.625,15348.837],[700,0.025,10.149,2.625,15349.887],[700,0.025,10.149,2.625,15350.937],[700,0.025,10.149,2.625,15351.987],[700,0.025,10.149,2.625,15353.037],[700,0.025,10.149,2.625,15354.087],[700,0.025,10.149,2.625,15355.137],[700,0.025,10.149,2.625,15356.187],[700,0.025,10.149,2.625,15357.237],[700,0.025,10.149,2.625,15358.287],[700,0.025,10.149,2.625,15359.337],[700,0.025,10.149,2.625,15360.387],[700,0.025,10.149,2.625,15361.437],[700,0.025,10.149,2.625,15362.487],[700,0.025,10.149,2.625,15363.537],[700,0.025,10.149,2.625,15364.587],[700,0.025,10.149,2.625,15365.637],[700,0.025,10.149,2.625,15366.687],[700,0.025,10.149,2.625,15367.737],[700,0.025,10.149,2.625,15368.787],[700,0.025,10.149,2.625,15369.837],[700,0.025,10.149,2.625,15370.887],[700,0.025,10.149,2.625,15371.937],[700,0.025,10.149,2.625,15372.987],[700,0.025,10.149,2.625,15374.037],[700,0.025,10.149,2.625,15375.087],[700,0.025,10.149,2.625,15376.137],[700,0.025,10.149,2.625,15377.187],[700,0.025,10.149,2.625,15378.237],[700,0.025,10.149,2.625,15379.287],[700,0.025,10.149,2.625,15380.337],[700,0.025,10.149,2.625,15381.387],[700,0.025,10.149,2.625,15382.437],[700,0.025,10.149,2.625,15383.487],[700,0.025,10.149,2.625,15384.537],[700,0.025,10.149,2.625,15385.587],[700,0.025,10.149,2.625,15386.637],[700,0.025,10.149,2.625,15387.687],[700,0.025,10.149,2.625,15388.737],[700,0.025,10.149,2.625,15389.787],[700,0.025,10.149,2.625,15390.837],[700,0.025,10.149,2.625,15391.887],[700,0.025,10.149,2.625,15392.937],[700,0.025,10.149,2.625,15393.987],[700,0.025,10.149,2.625,15395.037],[700,0.025,10.149,2.625,15396.087],[700,0.025,10.149,2.625,15397.137],[700,0.025,10.149,2.625,15398.187],[700,0.025,10.149,2.625,15399.237],[700,0.025,10.149,2.625,15400.287],[700,0.025,10.149,2.625,15401.337],[700,0.025,10.149,2.625,15402.387],[700,0.025,10.149,2.625,15403.437],[700,0.025,10.149,2.625,15404.487],[700,0.025,10.149,2.625,15405.537],[700,0.025,10.149,2.625,15406.587],[700,0.025,10.149,2.625,15407.637],[700,0.025,10.149,2.625,15408.687],[700,0.025,10.149,2.625,15409.737],[700,0.025,10.149,2.625,15410.787],[700,0.025,10.149,2.625,15411.837],[700,0.025,10.149,2.625,15412.887],[700,0.025,10.149,2.625,15413.937],[700,0.025,10.149,2.625,15414.987],[700,0.025,10.149,2.625,15416.037],[700,0.025,10.149,2.625,15417.087],[700,0.025,10.149,2.625,15418.137],[700,0.025,10.149,2.625,15419.187],[700,0.025,10.149,2.625,15420.237],[700,0.025,10.149,2.625,15421.287],[700,0.025,10.149,2.625,15422.337],[700,0.025,10.149,2.625,15423.387],[700,0.025,10.149,2.625,15424.437],[700,0.025,10.149,2.625,15425.487],[700,0.025,10.149,2.625,15426.537],[700,0.025,10.149,2.625,15427.587],[700,0.025,10.149,2.625,15428.637],[700,0.025,10.149,2.625,15429.687],[700,0.025,10.149,2.625,15430.737],[700,0.025,10.149,2.625,15431.787],[700,0.025,10.149,2.625,15432.837],[700,0.025,10.149,2.625,15433.887],[700,0.025,10.149,2.625,15434.937],[700,0.025,10.149,2.625,15435.987],[700,0.025,10.149,2.625,15437.037],[700,0.025,10.149,2.625,15438.087],[700,0.025,10.149,2.625,15439.137],[700,0.025,10.149,2.625,15440.187],[700,0.025,10.149,2.625,15441.237],[700,0.025,10.149,2.625,15442.287],[700,0.025,10.149,2.625,15443.337],[700,0.025,10.149,2.625,15444.387],[700,0.025,10.149,2.625,15445.437],[700,0.025,10.149,2.625,15446.487],[700,0.025,10.149,2.625,15447.537],[700,0.025,10.149,2.625,15448.587],[700,0.025,10.149,2.625,15449.637],[700,0.025,10.149,2.625,15450.687],[700,0.025,10.149,2.625,15451.737],[700,0.025,10.149,2.625,15452.787],[700,0.025,10.149,2.625,15453.837],[700,0.025,10.149,2.625,15454.887],[700,0.025,10.149,2.625,15455.937],[700,0.025,10.149,2.625,15456.987],[700,0.025,10.149,2.625,15458.037],[700,0.025,10.149,2.625,15459.087],[700,0.025,10.149,2.625,15460.137],[700,0.025,10.149,2.625,15461.187],[700,0.025,10.149,2.625,15462.237],[700,0.025,10.149,2.625,15463.287],[700,0.025,10.149,2.625,15464.337],[700,0.025,10.149,2.625,15465.387],[700,0.025,10.149,2.625,15466.437],[700,0.025,10.149,2.625,15467.487],[700,0.025,10.149,2.625,15468.537],[700,0.025,10.149,2.625,15469.587],[700,0.025,10.149,2.625,15470.637],[700,0.025,10.149,2.625,15471.687],[700,0.025,10.149,2.625,15472.737],[700,0.025,10.149,2.625,15473.787],[700,0.025,10.149,2.625,15474.837],[700,0.025,10.149,2.625,15475.887],[700,0.025,10.149,2.625,15476.937],[700,0.025,10.149,2.625,15477.987],[700,0.025,10.149,2.625,15479.037],[700,0.025,10.149,2.625,15480.087],[700,0.025,10.149,2.625,15481.137],[700,0.025,10.149,2.625,15482.187],[700,0.025,10.149,2.625,15483.237],[700,0.025,10.149,2.625,15484.287],[700,0.025,10.149,2.625,15485.337],[700,0.025,10.149,2.625,15486.387],[700,0.025,10.149,2.625,15487.437],[700,0.025,10.149,2.625,15488.487],[700,0.025,10.149,2.625,15489.537],[700,0.025,10.149,2.625,15490.587],[700,0.025,10.149,2.625,15491.637],[700,0.025,10.149,2.625,15492.687],[700,0.025,10.149,2.625,15493.737],[700,0.025,10.149,2.625,15494.787],[700,0.025,10.149,2.625,15495.837],[700,0.025,10.149,2.625,15496.887],[700,0.025,10.149,2.625,15497.937],[700,0.025,10.149,2.625,15498.987],[700,0.025,10.149,2.625,15500.037],[700,0.025,10.149,2.625,15501.087],[700,0.025,10.149,2.625,15502.137],[700,0.025,10.149,2.625,15503.187],[700,0.025,10.149,2.625,15504.237],[700,0.025,10.149,2.625,15505.287],[700,0.025,10.149,2.625,15506.337],[700,0.025,10.149,2.625,15507.387],[700,0.025,10.149,2.625,15508.437],[700,0.025,10.149,2.625,15509.487],[700,0.025,10.149,2.625,15510.537],[700,0.025,10.149,2.625,15511.587],[700,0.025,10.149,2.625,15512.637],[700,0.025,10.149,2.625,15513.687],[700,0.025,10.149,2.625,15514.737],[700,0.025,10.149,2.625,15515.787],[700,0.025,10.149,2.625,15516.837],[700,0.025,10.149,2.625,15517.887],[700,0.025,10.149,2.625,15518.937],[700,0.025,10.149,2.625,15519.987],[700,0.025,10.149,2.625,15521.037],[700,0.025,10.149,2.625,15522.087],[700,0.025,10.149,2.625,15523.137],[700,0.025,10.149,2.625,15524.187],[700,0.025,10.149,2.625,15525.237],[700,0.025,10.149,2.625,15526.287],[700,0.025,10.149,2.625,15527.337],[700,0.025,10.149,2.625,15528.387],[700,0.025,10.149,2.625,15529.437],[700,0.025,10.149,2.625,15530.487],[700,0.025,10.149,2.625,15531.537],[700,0.025,10.149,2.625,15532.587],[700,0.025,10.149,2.625,15533.637],[700,0.025,10.149,2.625,15534.687],[700,0.025,10.149,2.625,15535.737],[700,0.025,10.149,2.625,15536.787],[700,0.025,10.149,2.625,15537.837],[700,0.025,10.149,2.625,15538.887],[700,0.025,10.149,2.625,15539.937],[700,0.025,10.149,2.625,15540.987],[700,0.025,10.149,2.625,15542.037],[700,0.025,10.149,2.625,15543.087],[700,0.025,10.149,2.625,15544.137],[700,0.025,10.149,2.625,15545.187],[700,0.025,10.149,2.625,15546.237],[700,0.025,10.149,2.625,15547.287],[700,0.025,10.149,2.625,15548.337],[700,0.025,10.149,2.625,15549.387],[700,0.025,10.149,2.625,15550.437],[700,0.025,10.149,2.625,15551.487],[700,0.025,10.149,2.625,15552.537],[700,0.025,10.149,2.625,15553.587],[700,0.025,10.149,2.625,15554.637],[700,0.025,10.149,2.625,15555.687],[700,0.025,10.149,2.625,15556.737],[700,0.025,10.149,2.625,15557.787],[700,0.025,10.149,2.625,15558.837],[700,0.025,10.149,2.625,15559.887],[700,0.025,10.149,2.625,15560.937],[700,0.025,10.149,2.625,15561.987],[700,0.025,10.149,2.625,15563.037],[700,0.025,10.149,2.625,15564.087],[700,0.025,10.149,2.625,15565.137],[700,0.025,10.149,2.625,15566.187],[700,0.025,10.149,2.625,15567.237],[700,0.025,10.149,2.625,15568.287],[700,0.025,10.149,2.625,15569.337],[700,0.025,10.149,2.625,15570.387],[700,0.025,10.149,2.625,15571.437],[700,0.025,10.149,2.625,15572.487],[700,0.025,10.149,2.625,15573.537],[700,0.025,10.149,2.625,15574.587],[700,0.025,10.149,2.625,15575.637],[700,0.025,10.149,2.625,15576.687],[700,0.025,10.149,2.625,15577.737],[700,0.025,10.149,2.625,15578.787],[700,0.025,10.149,2.625,15579.837],[700,0.025,10.149,2.625,15580.887],[700,0.025,10.149,2.625,15581.937],[700,0.025,10.149,2.625,15582.987],[700,0.025,10.149,2.625,15584.037],[700,0.025,10.149,2.625,15585.087],[700,0.025,10.149,2.625,15586.137],[700,0.025,10.149,2.625,15587.187],[700,0.025,10.149,2.625,15588.237],[700,0.025,10.149,2.625,15589.287],[700,0.025,10.149,2.625,15590.337],[700,0.025,10.149,2.625,15591.387],[700,0.025,10.149,2.625,15592.437],[700,0.025,10.149,2.625,15593.487],[700,0.025,10.149,2.625,15594.537],[700,0.025,10.149,2.625,15595.587],[700,0.025,10.149,2.625,15596.637],[700,0.025,10.149,2.625,15597.687],[700,0.025,10.149,2.625,15598.737],[700,0.025,10.149,2.625,15599.787],[700,0.025,10.149,2.625,15600.837],[700,0.025,10.149,2.625,15601.887],[700,0.025,10.149,2.625,15602.937],[700,0.025,10.149,2.625,15603.987],[700,0.025,10.149,2.625,15605.037],[700,0.025,10.149,2.625,15606.087],[700,0.025,10.149,2.625,15607.137],[700,0.025,10.149,2.625,15608.187],[700,0.025,10.149,2.625,15609.237],[700,0.025,10.149,2.625,15610.287],[700,0.025,10.149,2.625,15611.337],[700,0.025,10.149,2.625,15612.387],[700,0.025,10.149,2.625,15613.437],[700,0.025,10.149,2.625,15614.487],[700,0.025,10.149,2.625,15615.537],[700,0.025,10.149,2.625,15616.587],[700,0.025,10.149,2.625,15617.637],[700,0.025,10.149,2.625,15618.687],[700,0.025,10.149,2.625,15619.737],[700,0.025,10.149,2.625,15620.787],[700,0.025,10.149,2.625,15621.837],[700,0.025,10.149,2.625,15622.887],[700,0.025,10.149,2.625,15623.937],[700,0.025,10.149,2.625,15624.987],[700,0.025,10.149,2.625,15626.037],[700,0.025,10.149,2.625,15627.087],[700,0.025,10.149,2.625,15628.137],[700,0.025,10.149,2.625,15629.187],[700,0.025,10.149,2.625,15630.237],[700,0.025,10.149,2.625,15631.287],[700,0.025,10.149,2.625,15632.337],[700,0.025,10.149,2.625,15633.387],[700,0.025,10.149,2.625,15634.437],[700,0.025,10.149,2.625,15635.487],[700,0.025,10.149,2.625,15636.537],[700,0.025,10.149,2.625,15637.587],[700,0.025,10.149,2.625,15638.637],[700,0.025,10.149,2.625,15639.687],[700,0.025,10.149,2.625,15640.737],[700,0.025,10.149,2.625,15641.787],[700,0.025,10.149,2.625,15642.837],[700,0.025,10.149,2.625,15643.887],[700,0.025,10.149,2.625,15644.937],[700,0.025,10.149,2.625,15645.987],[700,0.025,10.149,2.625,15647.037],[700,0.025,10.149,2.625,15648.087],[700,0.025,10.149,2.625,15649.137],[700,0.025,10.149,2.625,15650.187],[700,0.025,10.149,2.625,15651.237],[700,0.025,10.149,2.625,15652.287],[700,0.025,10.149,2.625,15653.337],[700,0.025,10.149,2.625,15654.387],[700,0.025,10.149,2.625,15655.437],[700,0.025,10.149,2.625,15656.487],[700,0.025,10.149,2.625,15657.537],[700,0.025,10.149,2.625,15658.587],[700,0.025,10.149,2.625,15659.637],[700,0.025,10.149,2.625,15660.687],[700,0.025,10.149,2.625,15661.737],[700,0.025,10.149,2.625,15662.787],[700,0.025,10.149,2.626,15663.837],[700,0.025,10.149,2.628,15664.888],[700,0.025,10.149,2.631,15665.94],[700,0.025,10.149,2.635,15666.993],[700,0.025,10.149,2.641,15668.049],[700,0.025,10.149,2.649,15669.107],[700,0.025,10.149,2.658,15670.168],[700,0.025,10.149,2.67,15671.233],[700,0.026,10.149,2.683,15672.304],[700,0.026,10.149,2.699,15673.38],[700,0.026,10.149,2.718,15674.464],[700,0.026,10.149,2.739,15675.555],[700,0.026,10.149,2.763,15676.655],[700,0.027,10.149,2.79,15677.766],[700,0.027,10.149,2.819,15678.887],[700,0.027,10.149,2.852,15680.021],[700,0.027,10.149,2.887,15681.169],[700,0.028,10.149,2.926,15682.332],[700,0.028,10.149,2.968,15683.511],[700,0.029,10.149,3.014,15684.707],[700,0.029,10.149,3.063,15685.922],[700,0.03,10.149,3.115,15687.158],[700,0.03,10.149,3.171,15688.415],[700,0.031,10.149,3.23,15689.695],[700,0.031,10.149,3.293,15691],[700,0.032,10.149,3.36,15692.33],[700,0.033,10.149,3.43,15693.688],[700,0.033,10.149,3.504,15695.075],[700,0.034,10.149,3.582,15696.492],[700,0.035,10.149,3.663,15697.941],[700,0.036,10.149,3.748,15699.423],[700,0.037,10.149,3.836,15700.94],[700,0.037,10.149,3.928,15702.493],[700,0.038,10.149,4.024,15704.083],[700,0.039,10.149,4.122,15705.712],[700,0.04,10.149,4.224,15707.382],[700,0.041,10.149,4.329,15709.092],[700,0.042,10.149,4.437,15710.845],[700,0.043,10.149,4.548,15712.642],[700,0.044,10.149,4.66,15714.484],[700,0.045,10.149,4.776,15716.371],[700,0.047,10.149,4.893,15718.305],[700,0.048,10.149,5.012,15720.285],[700,0.049,10.149,5.132,15722.314],[700,0.05,10.149,5.253,15724.391],[700,0.051,10.149,5.374,15726.516],[700,0.052,10.149,5.496,15728.69],[700,0.054,10.149,5.618,15730.913],[700,0.055,10.149,5.739,15733.185],[700,0.056,10.149,5.859,15735.504],[700,0.057,10.149,5.978,15737.872],[700,0.058,10.149,6.094,15740.286],[700,0.059,10.149,6.209,15742.747],[700,0.06,10.149,6.32,15745.253],[700,0.061,10.149,6.428,15747.803],[700,0.062,10.149,6.532,15750.395],[700,0.063,10.149,6.632,15753.028],[700,0.064,10.149,6.728,15755.7],[700,0.065,10.149,6.818,15758.409],[700,0.066,10.149,6.904,15761.154],[700,0.067,10.149,6.983,15763.931],[700,0.067,10.149,7.058,15766.74],[700,0.068,10.149,7.126,15769.577],[700,0.068,10.149,7.188,15772.439],[700,0.069,10.149,7.244,15775.326],[700,0.069,10.149,7.293,15778.234],[700,0.07,10.149,7.337,15781.16],[700,0.07,10.149,7.375,15784.102],[700,0.071,10.149,7.407,15787.059],[700,0.071,10.149,7.433,15790.027],[700,0.071,10.149,7.454,15793.004],[700,0.071,10.149,7.47,15795.989],[700,0.071,10.149,7.483,15798.98],[700,0.071,10.149,7.491,15801.975],[700,0.071,10.149,7.496,15804.972],[700,0.071,10.149,7.499,15807.972],[700,0.071,10.149,7.5,15810.971],[700,0.071,10.149,7.5,15813.971],[700,0.071,10.149,7.5,15816.971],[700,0.071,10.149,7.5,15819.971],[700,0.071,10.149,7.5,15822.971],[700,0.071,10.149,7.5,15825.971],[700,0.071,10.149,7.5,15828.971],[700,0.071,10.149,7.5,15831.971],[700,0.071,10.149,7.5,15834.971],[700,0.071,10.149,7.5,15837.971],[700,0.071,10.149,7.5,15840.971],[700,0.071,10.149,7.5,15843.971],[700,0.071,10.149,7.5,15846.971],[700,0.071,10.149,7.5,15849.971],[700,0.071,10.149,7.5,15852.971],[700,0.071,10.149,7.5,15855.971],[700,0.071,10.149,7.5,15858.971],[700,0.071,10.149,7.5,15861.971],[700,0.071,10.149,7.5,15864.971],[700,0.071,10.149,7.5,15867.971],[700,0.071,10.149,7.5,15870.971],[700,0.071,10.149,7.5,15873.971],[700,0.071,10.149,7.5,15876.971],[700,0.071,10.149,7.5,15879.971],[700,0.071,10.149,7.5,15882.971],[700,0.071,10.149,7.5,15885.971],[700,0.071,10.149,7.5,15888.971],[700,0.071,10.149,7.5,15891.971],[700,0.071,10.149,7.5,15894.971],[700,0.071,10.149,7.5,15897.971],[700,0.071,10.149,7.5,15900.971],[700,0.071,10.149,7.5,15903.971],[700,0.071,10.149,7.5,15906.971],[700,0.071,10.149,7.5,15909.971],[700,0.071,10.149,7.5,15912.971],[700,0.071,10.149,7.5,15915.971],[700,0.071,10.149,7.5,15918.971],[700,0.071,10.149,7.5,15921.971],[700,0.071,10.149,7.5,15924.971],[700,0.071,10.149,7.5,15927.971],[700,0.071,10.149,7.5,15930.971],[700,0.071,10.149,7.5,15933.971],[700,0.071,10.149,7.5,15936.971],[700,0.071,10.149,7.5,15939.971],[700,0.071,10.149,7.5,15942.971],[700,0.071,10.149,7.5,15945.971],[700,0.071,10.149,7.5,15948.971],[700,0.071,10.149,7.5,15951.971],[700,0.071,10.149,7.5,15954.971],[700,0.071,10.149,7.5,15957.971],[700,0.071,10.149,7.5,15960.971],[700,0.071,10.149,7.5,15963.971],[700,0.071,10.149,7.5,15966.971],[700,0.071,10.149,7.5,15969.971],[700,0.071,10.149,7.5,15972.971],[700,0.071,10.149,7.5,15975.971],[700,0.071,10.149,7.5,15978.971],[700,0.071,10.149,7.5,15981.971],[700,0.071,10.149,7.5,15984.971],[700,0.071,10.149,7.5,15987.971],[700,0.071,10.149,7.5,15990.971],[700,0.071,10.149,7.5,15993.971],[700,0.071,10.149,7.5,15996.971],[700,0.071,10.149,7.5,15999.971],[700,0.071,10.149,7.5,16002.971],[700,0.071,10.149,7.5,16005.971],[700,0.071,10.149,7.5,16008.971],[700,0.071,10.149,7.5,16011.971],[700,0.071,10.149,7.5,16014.971],[700,0.071,10.149,7.5,16017.971],[700,0.071,10.149,7.5,16020.971],[700,0.071,10.149,7.5,16023.971],[700,0.071,10.149,7.5,16026.971],[700,0.071,10.149,7.5,16029.971],[700,0.071,10.149,7.5,16032.971],[700,0.071,10.149,7.5,16035.971],[700,0.071,10.149,7.5,16038.971],[700,0.071,10.149,7.5,16041.971],[700,0.071,10.149,7.5,16044.971],[700,0.071,10.149,7.5,16047.971],[700,0.071,10.149,7.5,16050.971],[700,0.071,10.149,7.5,16053.971],[700,0.071,10.149,7.5,16056.971],[700,0.071,10.149,7.5,16059.971],[700,0.071,10.149,7.5,16062.971],[700,0.071,10.149,7.5,16065.971],[700,0.071,10.149,7.5,16068.971],[700,0.071,10.149,7.5,16071.971],[700,0.071,10.149,7.5,16074.971],[700,0.071,10.149,7.5,16077.971],[700,0.071,10.149,7.5,16080.971],[700,0.071,10.149,7.5,16083.971],[700,0.071,10.149,7.5,16086.971],[700,0.071,10.149,7.5,16089.971],[700,0.071,10.149,7.5,16092.971],[700,0.071,10.149,7.5,16095.971],[700,0.071,10.149,7.5,16098.971],[700,0.071,10.149,7.5,16101.971],[700,0.071,10.149,7.5,16104.971],[700,0.071,10.149,7.5,16107.971],[700,0.071,10.149,7.5,16110.971],[700,0.071,10.149,7.5,16113.971],[700,0.071,10.149,7.5,16116.971],[700,0.071,10.149,7.5,16119.971],[700,0.071,10.149,7.5,16122.971],[700,0.071,10.149,7.5,16125.971],[700,0.071,10.149,7.5,16128.971],[700,0.071,10.149,7.5,16131.971],[700,0.071,10.149,7.5,16134.971],[700,0.071,10.149,7.5,16137.971],[700,0.071,10.149,7.5,16140.971],[700,0.071,10.149,7.5,16143.971],[700,0.071,10.149,7.5,16146.971],[700,0.071,10.149,7.5,16149.971],[700,0.071,10.149,7.5,16152.971],[700,0.071,10.149,7.5,16155.971],[700,0.071,10.149,7.5,16158.971],[700,0.071,10.149,7.5,16161.971],[700,0.071,10.149,7.5,16164.971],[700,0.071,10.149,7.5,16167.971],[700,0.071,10.149,7.5,16170.971],[700,0.071,10.149,7.5,16173.971],[700,0.071,10.149,7.5,16176.971],[700,0.071,10.149,7.5,16179.971],[700,0.071,10.149,7.5,16182.971],[700,0.071,10.149,7.5,16185.971],[700,0.071,10.149,7.5,16188.971],[700,0.071,10.149,7.5,16191.971],[700,0.071,10.149,7.5,16194.971],[700,0.071,10.149,7.5,16197.971],[700,0.071,10.149,7.5,16200.971],[700,0.071,10.149,7.5,16203.971],[700,0.071,10.149,7.5,16206.971],[700,0.071,10.149,7.5,16209.971],[700,0.071,10.149,7.5,16212.971],[700,0.071,10.149,7.5,16215.971],[700,0.071,10.149,7.5,16218.971],[700,0.071,10.149,7.5,16221.971],[700,0.071,10.149,7.5,16224.971],[700,0.071,10.149,7.5,16227.971],[700,0.071,10.149,7.5,16230.971],[700,0.071,10.149,7.5,16233.971],[700,0.071,10.149,7.5,16236.971],[700,0.071,10.149,7.5,16239.971],[700,0.071,10.149,7.5,16242.971],[700,0.071,10.149,7.5,16245.971],[700,0.071,10.149,7.5,16248.971],[700,0.071,10.149,7.5,16251.971],[700,0.071,10.149,7.5,16254.971],[700,0.071,10.149,7.5,16257.971],[700,0.071,10.149,7.5,16260.971],[700,0.071,10.149,7.5,16263.971],[700,0.071,10.149,7.5,16266.971],[700,0.071,10.149,7.5,16269.971],[700,0.071,10.149,7.5,16272.971],[700,0.071,10.149,7.5,16275.971],[700,0.071,10.149,7.5,16278.971],[700,0.071,10.149,7.5,16281.971],[700,0.071,10.149,7.5,16284.971],[700,0.071,10.149,7.5,16287.971],[700,0.071,10.149,7.5,16290.971],[700,0.071,10.149,7.5,16293.971],[700,0.071,10.149,7.5,16296.971],[700,0.071,10.149,7.5,16299.971],[700,0.071,10.149,7.5,16302.971],[700,0.071,10.149,7.5,16305.971],[700,0.071,10.149,7.5,16308.971],[700,0.071,10.149,7.5,16311.971],[700,0.071,10.149,7.5,16314.971],[700,0.071,10.149,7.5,16317.971],[700,0.071,10.149,7.5,16320.971],[700,0.071,10.149,7.5,16323.971],[700,0.071,10.149,7.5,16326.971],[700,0.071,10.149,7.5,16329.971],[700,0.071,10.149,7.5,16332.971],[700,0.071,10.149,7.5,16335.971],[700,0.071,10.149,7.5,16338.971],[700,0.071,10.149,7.5,16341.971],[700,0.071,10.149,7.5,16344.971],[700,0.071,10.149,7.5,16347.971],[700,0.071,10.149,7.5,16350.971],[700,0.071,10.149,7.5,16353.971],[700,0.071,10.149,7.5,16356.971],[700,0.071,10.149,7.5,16359.971],[700,0.071,10.149,7.5,16362.971],[700,0.071,10.149,7.5,16365.971],[700,0.071,10.149,7.5,16368.971],[700,0.071,10.149,7.5,16371.971],[700,0.071,10.149,7.5,16374.971],[700,0.071,10.149,7.5,16377.971],[700,0.071,10.149,7.5,16380.971],[700,0.071,10.149,7.5,16383.971],[700,0.071,10.149,7.5,16386.971],[700,0.071,10.149,7.5,16389.971],[700,0.071,10.149,7.5,16392.971],[700,0.071,10.149,7.5,16395.971],[700,0.071,10.149,7.5,16398.971],[700,0.071,10.149,7.5,16401.971],[700,0.071,10.149,7.5,16404.971],[700,0.071,10.149,7.5,16407.971],[700,0.071,10.149,7.5,16410.971],[700,0.071,10.149,7.5,16413.971],[700,0.071,10.149,7.5,16416.971],[700,0.071,10.149,7.5,16419.971],[700,0.071,10.149,7.5,16422.971],[700,0.071,10.149,7.5,16425.971],[700,0.071,10.149,7.5,16428.971],[700,0.071,10.149,7.5,16431.971],[700,0.071,10.149,7.5,16434.971],[700,0.071,10.149,7.5,16437.971],[700,0.071,10.149,7.5,16440.971],[700,0.071,10.149,7.5,16443.971],[700,0.071,10.149,7.5,16446.971],[700,0.071,10.149,7.5,16449.971],[700,0.071,10.149,7.5,16452.971],[700,0.071,10.149,7.5,16455.971],[700,0.071,10.149,7.5,16458.971],[700,0.071,10.149,7.5,16461.971],[700,0.071,10.149,7.5,16464.971],[700,0.071,10.149,7.5,16467.971],[700,0.071,10.149,7.5,16470.971],[700,0.071,10.149,7.5,16473.971],[700,0.071,10.149,7.5,16476.971],[700,0.071,10.149,7.5,16479.971],[700,0.071,10.149,7.5,16482.971],[700,0.071,10.149,7.5,16485.971],[700,0.071,10.149,7.5,16488.971],[700,0.071,10.149,7.5,16491.971],[700,0.071,10.149,7.5,16494.971],[700,0.071,10.149,7.5,16497.971],[700,0.071,10.149,7.5,16500.971],[700,0.071,10.149,7.5,16503.971],[700,0.071,10.149,7.5,16506.971],[700,0.071,10.149,7.5,16509.971],[700,0.071,10.149,7.5,16512.971],[700,0.071,10.149,7.5,16515.971],[700,0.071,10.149,7.5,16518.971],[700,0.071,10.149,7.5,16521.971],[700,0.071,10.149,7.5,16524.971],[700,0.071,10.149,7.5,16527.971],[700,0.071,10.149,7.5,16530.971],[700,0.071,10.149,7.5,16533.971],[700,0.071,10.149,7.5,16536.971],[700,0.071,10.149,7.5,16539.971],[700,0.071,10.149,7.5,16542.971],[700,0.071,10.149,7.5,16545.971],[700,0.071,10.149,7.5,16548.971],[700,0.071,10.149,7.5,16551.971],[700,0.071,10.149,7.5,16554.971],[700,0.071,10.149,7.5,16557.971],[700,0.071,10.149,7.5,16560.971],[700,0.071,10.149,7.5,16563.971],[700,0.071,10.149,7.5,16566.971],[700,0.071,10.149,7.5,16569.971],[700,0.071,10.149,7.5,16572.971],[700,0.071,10.149,7.5,16575.971],[700,0.071,10.149,7.5,16578.971],[700,0.071,10.149,7.5,16581.971],[700,0.071,10.149,7.5,16584.971],[700,0.071,10.149,7.5,16587.971],[700,0.071,10.149,7.5,16590.971],[700,0.071,10.149,7.5,16593.971],[700,0.071,10.149,7.5,16596.971],[700,0.071,10.149,7.5,16599.971],[700,0.071,10.149,7.5,16602.971],[700,0.071,10.149,7.5,16605.971],[700,0.071,10.149,7.5,16608.971],[700,0.071,10.149,7.5,16611.971],[700,0.071,10.149,7.5,16614.971],[700,0.071,10.149,7.5,16617.971],[700,0.071,10.149,7.5,16620.971],[700,0.071,10.149,7.5,16623.971],[700,0.071,10.149,7.5,16626.971],[700,0.071,10.149,7.5,16629.971],[700,0.071,10.149,7.5,16632.971],[700,0.071,10.149,7.5,16635.971],[700,0.071,10.149,7.5,16638.971],[700,0.071,10.149,7.5,16641.971],[700,0.071,10.149,7.5,16644.971],[700,0.071,10.149,7.5,16647.971],[700,0.071,10.149,7.5,16650.971],[700,0.071,10.149,7.5,16653.971],[700,0.071,10.149,7.5,16656.971],[700,0.071,10.149,7.5,16659.971],[700,0.071,10.149,7.5,16662.971],[700,0.071,10.149,7.5,16665.971],[700,0.071,10.149,7.5,16668.971],[700,0.071,10.149,7.5,16671.971],[700,0.071,10.149,7.5,16674.971],[700,0.071,10.149,7.5,16677.971],[700,0.071,10.149,7.5,16680.971],[700,0.071,10.149,7.5,16683.971],[700,0.071,10.149,7.5,16686.971],[700,0.071,10.149,7.5,16689.971],[700,0.071,10.149,7.5,16692.971],[700,0.071,10.149,7.5,16695.971],[700,0.071,10.149,7.5,16698.971],[700,0.071,10.149,7.5,16701.971],[700,0.071,10.149,7.5,16704.971],[700,0.071,10.149,7.5,16707.971],[700,0.071,10.149,7.5,16710.971],[700,0.071,10.149,7.5,16713.971],[700,0.071,10.149,7.5,16716.971],[700,0.071,10.149,7.5,16719.971],[700,0.071,10.149,7.5,16722.971],[700,0.071,10.149,7.5,16725.971],[700,0.071,10.149,7.5,16728.971],[700,0.071,10.149,7.5,16731.971],[700,0.071,10.149,7.5,16734.971],[700,0.071,10.149,7.5,16737.971],[700,0.071,10.149,7.5,16740.971],[700,0.071,10.149,7.5,16743.971],[700,0.071,10.149,7.5,16746.971],[700,0.071,10.149,7.5,16749.971],[700,0.071,10.149,7.5,16752.971],[700,0.071,10.149,7.5,16755.971],[700,0.071,10.149,7.5,16758.971],[700,0.071,10.149,7.5,16761.971],[700,0.071,10.149,7.5,16764.971],[700,0.071,10.149,7.5,16767.971],[700,0.071,10.149,7.5,16770.971],[700,0.071,10.149,7.5,16773.971],[700,0.071,10.149,7.5,16776.971],[700,0.071,10.149,7.5,16779.971],[700,0.071,10.149,7.5,16782.971],[700,0.071,10.149,7.5,16785.971],[700,0.071,10.149,7.5,16788.971],[700,0.071,10.149,7.5,16791.971],[700,0.071,10.149,7.5,16794.971],[700,0.071,10.149,7.5,16797.971],[700,0.071,10.149,7.5,16800.971],[700,0.071,10.149,7.5,16803.971],[700,0.071,10.149,7.5,16806.971],[700,0.071,10.149,7.5,16809.971],[700,0.071,10.149,7.5,16812.971],[700,0.071,10.149,7.5,16815.971],[700,0.071,10.149,7.5,16818.971],[700,0.071,10.149,7.5,16821.971],[700,0.071,10.149,7.5,16824.971],[700,0.071,10.149,7.5,16827.971],[700,0.071,10.149,7.5,16830.971],[700,0.071,10.149,7.5,16833.971],[700,0.071,10.149,7.5,16836.971],[700,0.071,10.149,7.5,16839.971],[700,0.071,10.149,7.5,16842.971],[700,0.071,10.149,7.5,16845.971],[700,0.071,10.149,7.5,16848.971],[700,0.071,10.149,7.5,16851.971],[700,0.071,10.149,7.5,16854.971],[700,0.071,10.149,7.5,16857.971],[700,0.071,10.149,7.5,16860.971],[700,0.071,10.149,7.5,16863.971],[700,0.071,10.149,7.5,16866.971],[700,0.071,10.149,7.5,16869.971],[700,0.071,10.149,7.5,16872.971],[700,0.071,10.149,7.5,16875.971],[700,0.071,10.149,7.5,16878.971],[700,0.071,10.149,7.5,16881.971],[700,0.071,10.149,7.5,16884.971],[700,0.071,10.149,7.5,16887.971],[700,0.071,10.149,7.5,16890.971],[700,0.071,10.149,7.5,16893.971],[700,0.071,10.149,7.5,16896.971],[700,0.071,10.149,7.5,16899.971],[700,0.071,10.149,7.5,16902.971],[700,0.071,10.149,7.5,16905.971],[700,0.071,10.149,7.5,16908.971],[700,0.071,10.149,7.5,16911.971],[700,0.071,10.149,7.5,16914.971],[700,0.071,10.149,7.5,16917.971],[700,0.071,10.149,7.5,16920.971],[700,0.071,10.149,7.5,16923.971],[700,0.071,10.149,7.5,16926.971],[700,0.071,10.149,7.5,16929.971],[700,0.071,10.149,7.5,16932.971],[700,0.071,10.149,7.5,16935.971],[700,0.071,10.149,7.5,16938.971],[700,0.071,10.149,7.5,16941.971],[700,0.071,10.149,7.5,16944.971],[700,0.071,10.149,7.5,16947.971],[700,0.071,10.149,7.5,16950.971],[700,0.071,10.149,7.5,16953.971],[700,0.071,10.149,7.5,16956.971],[700,0.071,10.149,7.5,16959.971],[700,0.071,10.149,7.5,16962.971],[700,0.071,10.149,7.5,16965.971],[700,0.071,10.149,7.5,16968.971],[700,0.071,10.149,7.5,16971.971],[700,0.071,10.149,7.5,16974.971],[700,0.071,10.149,7.5,16977.971],[700,0.071,10.149,7.5,16980.971],[700,0.071,10.149,7.5,16983.971],[700,0.071,10.149,7.5,16986.971],[700,0.071,10.149,7.5,16989.971],[700,0.071,10.149,7.5,16992.971],[700,0.071,10.149,7.5,16995.971],[700,0.071,10.149,7.5,16998.971],[700,0.071,10.149,7.5,17001.971],[700,0.071,10.149,7.5,17004.971],[700,0.071,10.149,7.5,17007.971],[700,0.071,10.149,7.5,17010.971],[700,0.071,10.149,7.5,17013.971],[700,0.071,10.149,7.5,17016.971],[700,0.071,10.149,7.501,17019.971],[700,0.071,10.149,7.503,17022.972],[700,0.071,10.149,7.507,17025.974],[700,0.072,10.149,7.513,17028.978],[700,0.072,10.149,7.523,17031.985],[700,0.072,10.149,7.536,17034.997],[700,0.072,10.149,7.553,17038.015],[700,0.072,10.149,7.575,17041.04],[700,0.072,10.149,7.601,17044.075],[700,0.073,10.149,7.633,17047.122],[700,0.073,10.149,7.671,17050.183],[700,0.073,10.149,7.716,17053.26],[700,0.074,10.149,7.766,17056.356],[700,0.075,10.149,7.825,17059.474],[700,0.075,10.149,7.89,17062.617],[700,0.076,10.149,7.964,17065.787],[700,0.077,10.149,8.046,17068.989],[700,0.077,10.149,8.136,17072.225],[700,0.078,10.149,8.236,17075.499],[700,0.079,10.149,8.346,17078.815],[700,0.081,10.149,8.466,17082.177],[700,0.082,10.149,8.597,17085.59],[700,0.083,10.149,8.739,17089.056],[700,0.085,10.149,8.892,17092.582],[700,0.086,10.149,9.058,17096.172],[700,0.088,10.149,9.237,17099.83],[700,0.09,10.149,9.429,17103.563],[700,0.092,10.149,9.635,17107.375],[700,0.094,10.149,9.856,17111.273],[700,0.096,10.149,10.093,17115.262],[700,0.099,10.149,10.345,17119.349],[700,0.101,10.149,10.615,17123.541],[700,0.104,10.149,10.902,17127.843],[700,0.107,10.149,11.208,17132.265],[700,0.11,10.149,11.534,17136.813],[700,0.113,10.149,11.88,17141.495],[700,0.117,10.149,12.247,17146.319],[700,0.12,10.149,12.637,17151.295],[700,0.124,10.149,13.05,17156.432],[700,0.128,10.149,13.487,17161.738],[700,0.133,10.149,13.951,17167.225],[700,0.138,10.149,14.441,17172.902],[700,0.142,10.149,14.958,17178.781],[700,0.148,10.149,15.505,17184.873],[700,0.153,10.149,16.083,17191.19],[700,0.159,10.149,16.692,17197.744],[700,0.165,10.149,17.334,17204.547],[700,0.172,10.149,18.01,17211.615],[700,0.178,10.149,18.721,17218.96],[700,0.185,10.149,19.469,17226.597],[700,0.193,10.149,20.256,17234.54],[700,0.201,10.149,21.081,17242.807],[700,0.209,10.149,21.948,17251.411],[700,0.218,10.149,22.856,17260.37],[700,0.227,10.149,23.807,17269.701],[700,0.236,10.149,24.802,17279.422],[700,0.246,10.149,25.843,17289.549],[700,0.256,10.149,26.929,17300.102],[700,0.267,10.149,28.062,17311.099],[700,0.279,10.149,29.244,17322.558],[700,0.29,10.149,30.473,17334.5],[700,0.302,10.149,31.751,17346.943],[700,0.315,10.149,33.079,17359.907],[700,0.328,10.149,34.455,17373.413],[700,0.342,10.149,35.881,17387.478],[700,0.356,10.149,37.355,17402.124],[700,0.37,10.149,38.878,17417.369],[700,0.385,10.149,40.448,17433.232],[700,0.401,10.149,42.065,17449.733],[700,0.416,10.149,43.727,17466.89],[700,0.433,10.149,45.432,17484.72],[700,0.449,10.149,47.179,17503.241],[700,0.466,10.149,48.965,17522.469],[700,0.484,10.149,50.789,17542.418],[700,0.501,10.149,52.646,17563.104],[700,0.519,10.149,54.534,17584.539],[700,0.538,10.149,56.449,17606.735],[700,0.556,10.149,58.387,17629.701],[700,0.575,10.149,60.345,17653.447],[700,0.594,10.149,62.318,17677.98],[700,0.612,10.149,64.301,17703.303],[700,0.631,10.149,66.289,17729.421],[700,0.65,10.149,68.278,17756.335],[700,0.669,10.149,70.261,17784.043],[700,0.688,10.149,72.233,17812.542],[700,0.707,10.149,74.189,17841.827],[700,0.725,10.149,76.122,17871.89],[700,0.743,10.149,78.028,17902.721],[700,0.761,10.149,79.9,17934.308],[700,0.778,10.149,81.733,17966.636],[700,0.795,10.149,83.52,17999.688],[700,0.812,10.149,85.258,18033.445],[700,0.828,10.149,86.939,18067.887],[700,0.843,10.149,88.561,18102.989],[700,0.858,10.149,90.117,18138.727],[700,0.872,10.149,91.603,18175.073],[700,0.886,10.149,93.017,18212],[700,0.899,10.149,94.354,18249.476],[700,0.911,10.149,95.611,18287.472],[700,0.922,10.149,96.787,18325.955],[700,0.932,10.149,97.879,18364.89],[700,0.942,10.149,98.886,18404.246],[700,0.951,10.149,99.808,18443.988],[700,0.959,10.149,100.645,18484.081],[700,0.966,10.149,101.397,18524.493],[700,0.972,10.149,102.066,18565.188],[700,0.978,10.149,102.655,18606.135],[700,0.983,10.149,103.165,18647.301],[700,0.987,10.149,103.6,18688.657],[700,0.99,10.149,103.964,18730.172],[700,0.993,10.149,104.261,18771.819],[700,0.995,10.149,104.498,18813.573],[700,0.997,10.149,104.68,18855.41],[700,0.998,10.149,104.812,18897.31],[700,0.999,10.149,104.902,18939.254],[700,1,10.149,104.958,18981.227],[700,1,10.149,104.987,19023.217],[700,1,10.149,104.998,19065.215],[700,1,10.149,105,19107.215],[700,1,10.149,105,19149.215],[700,1,10.149,105,19191.215],[700,1,10.149,105,19233.215],[700,1,10.149,105,19275.215],[700,1,10.149,105,19317.215],[700,1,10.149,105,19359.215],[700,1,10.149,105,19401.215],[700,1,10.149,105,19443.215],[700,1,10.149,105,19485.215],[700,1,10.149,105,19527.215],[700.001,1,10.149,105,19569.215],[700.006,1,10.149,105.001,19611.215],[700.02,1,10.15,105.003,19653.215],[700.046,1,10.15,105.007,19695.217],[700.09,1,10.15,105.014,19737.221],[700.155,1,10.151,105.023,19779.229],[700.245,1,10.152,105.037,19821.24],[700.364,1,10.153,105.055,19863.259],[700.516,1,10.154,105.077,19905.285],[700.704,1,10.156,105.106,19947.321],[700.932,1,10.158,105.14,19989.37],[701.204,1,10.16,105.181,20031.434],[701.523,1,10.163,105.229,20073.516],[701.893,1,10.167,105.284,20115.618],[702.316,1,10.171,105.347,20157.744],[702.797,1,10.175,105.419,20199.897],[703.337,1,10.18,105.501,20242.081],[703.941,1,10.186,105.591,20284.299],[704.61,1,10.192,105.692,20326.555],[705.349,1,10.199,105.802,20368.853],[706.16,1,10.206,105.924,20411.198],[707.045,1,10.215,106.057,20453.594],[708.008,1,10.224,106.201,20496.045],[709.051,1,10.233,106.358,20538.556],[710.176,1,10.244,106.526,20581.133],[711.385,1,10.255,106.708,20623.779],[712.683,1,10.268,106.902,20666.501],[714.069,1,10.281,107.11,20709.303],[715.548,1,10.295,107.332,20752.191],[717.12,1,10.309,107.568,20795.17],[718.788,1,10.325,107.818,20838.247],[720.555,1,10.342,108.083,20881.427],[722.421,1,10.36,108.363,20924.716],[724.389,1,10.378,108.658,20968.12],[726.461,1,10.398,108.969,21011.645],[728.638,1,10.419,109.296,21055.297],[730.922,1,10.441,109.638,21099.083],[733.314,1,10.464,109.997,21143.01],[735.817,1,10.489,110.373,21187.083],[738.432,1,10.514,110.765,21231.31],[741.159,1,10.541,111.174,21275.697],[744.001,1,10.568,111.6,21320.251],[746.958,1,10.598,112.044,21364.98],[750.032,1,10.628,112.505,21409.889],[753.224,1,10.66,112.984,21454.986],[756.535,1,10.692,113.48,21500.278],[759.966,1,10.727,113.995,21545.772],[763.517,1,10.762,114.528,21591.476],[767.191,1,10.8,115.079,21637.397],[770.988,1,10.838,115.648,21683.542],[774.908,1,10.878,116.236,21729.918],[778.952,1,10.92,116.843,21776.533],[783.12,1,10.962,117.468,21823.395],[787.415,1,11.007,118.112,21870.51],[791.835,1,11.053,118.775,21917.887],[796.382,1,11.101,119.457,21965.533],[801.055,1,11.15,120.158,22013.455],[805.856,1,11.201,120.878,22061.662],[810.784,1,11.253,121.618,22110.16],[815.84,1,11.308,122.376,22158.958],[821.024,1,11.363,123.154,22208.064],[826.336,1,11.421,123.95,22257.484],[831.777,1,11.481,124.766,22307.227],[837.345,1,11.542,125.602,22357.3],[843.042,1,11.605,126.456,22407.711],[848.868,1,11.67,127.33,22458.467],[854.821,1,11.737,128.223,22509.577],[860.902,1,11.806,129.135,22561.048],[867.111,1,11.877,130.067,22612.888],[873.448,1,11.949,131.017,22665.104],[879.912,1,12.024,131.987,22717.704],[886.502,1,12.101,132.975,22770.696],[893.219,1,12.18,133.983,22824.087],[900.063,1,12.261,135.009,22877.885],[907.031,1,12.344,136.055,22932.097],[914.125,1,12.429,137.119,22986.731],[921.343,1,12.516,138.201,23041.795],[928.685,1,12.606,139.303,23097.295],[936.15,1,12.698,140.422,23153.239],[943.737,1,12.792,141.561,23209.635],[951.446,1,12.888,142.717,23266.49],[959.276,1,12.987,143.891,23323.811],[967.226,1,13.088,145.084,23381.606],[975.296,1,13.191,146.294,23439.881],[983.483,1,13.297,147.522,23498.644],[991.788,1,13.405,148.768,23557.901],[1000.209,1,13.516,150.031,23617.66],[1008.746,1,13.629,151.312,23677.929],[1017.396,1,13.745,152.609,23738.712],[1026.16,1,13.863,153.924,23800.018],[1035.036,1,13.983,155.255,23861.854],[1044.022,1,14.107,156.603,23924.225],[1053.119,1,14.232,157.968,23987.139],[1062.323,1,14.361,159.348,24050.601],[1071.635,1,14.492,160.745,24114.619],[1081.053,1,14.626,162.158,24179.2],[1090.574,1,14.762,163.586,24244.348],[1100.199,1,14.901,165.03,24310.071],[1109.926,1,15.043,166.489,24376.374],[1119.753,1,15.187,167.963,24443.264],[1129.679,1,15.335,169.452,24510.746],[1139.702,1,15.485,170.955,24578.827],[1149.82,1,15.638,172.473,24647.512],[1160.033,1,15.793,174.005,24716.807],[1170.339,1,15.952,175.551,24786.718],[1180.735,1,16.113,177.11,24857.25],[1191.221,1,16.277,178.683,24928.408],[1201.795,1,16.444,180.269,25000.198],[1212.454,1,16.613,181.868,25072.625],[1223.198,1,16.786,183.48,25145.694],[1234.024,1,16.961,185.104,25219.411],[1244.932,1,17.14,186.74,25293.779],[1255.918,1,17.321,188.388,25368.804],[1266.981,1,17.505,190.047,25444.491],[1278.12,1,17.692,191.718,25520.843],[1289.333,1,17.882,193.4,25597.867],[1300.617,1,18.075,195.093,25675.565],[1311.971,1,18.27,196.796,25753.942],[1323.392,1,18.469,198.509,25833.002],[1334.88,1,18.67,200.232,25912.75],[1346.432,1,18.875,201.965,25993.189],[1358.045,1,19.082,203.707,26074.323],[1369.719,1,19.292,205.458,26156.156],[1381.451,1,19.505,207.218,26238.691],[1393.239,1,19.72,208.986,26321.931],[1405.081,1,19.939,210.762,26405.881],[1416.975,1,20.16,212.546,26490.542],[1428.918,1,20.385,214.338,26575.918],[1440.91,1,20.612,216.136,26662.013],[1452.947,1,20.841,217.942,26748.829],[1465.028,1,21.074,219.754,26836.368],[1477.151,1,21.309,221.573,26924.633],[1489.313,1,21.547,223.397,27013.626],[1501.512,1,21.788,225.227,27103.351],[1513.746,1,22.031,227.062,27193.809],[1526.014,1,22.277,228.902,27285.001],[1538.312,1,22.526,230.747,27376.931],[1550.639,1,22.777,232.596,27469.599],[1562.992,1,23.03,234.449,27563.008],[1575.37,1,23.287,236.305,27657.159],[1587.77,1,23.545,238.165,27752.053],[1600.189,1,23.806,240.028,27847.692],[1612.627,1,24.07,241.894,27944.076],[1625.08,1,24.336,243.762,28041.207],[1637.546,1,24.604,245.632,28139.086],[1650.024,1,24.875,247.504,28237.713],[1662.51,1,25.148,249.376,28337.089],[1675.003,1,25.423,251.25,28437.214],[1687.5,1,25.7,253.125,28538.089],[1700,1,25.979,255,28639.714],[1712.5,1,26.26,256.875,28742.089],[1724.997,1,26.544,258.75,28845.214],[1737.49,1,26.829,260.624,28949.089],[1749.976,1,27.116,262.496,29053.713],[1762.454,1,27.405,264.368,29159.086],[1774.92,1,27.696,266.238,29265.207],[1787.373,1,27.989,268.106,29372.076],[1799.811,1,28.283,269.972,29479.692],[1812.23,1,28.579,271.835,29588.053],[1824.63,1,28.876,273.695,29697.159],[1837.008,1,29.175,275.551,29807.008],[1849.361,1,29.476,277.404,29917.599],[1861.688,1,29.777,279.253,30028.931],[1873.986,1,30.08,281.098,30141.001],[1886.254,1,30.385,282.938,30253.809],[1898.488,1,30.69,284.773,30367.351],[1910.687,1,30.997,286.603,30481.626],[1922.849,1,31.304,288.427,30596.633],[1934.972,1,31.612,290.246,30712.368],[1947.053,1,31.922,292.058,30828.829],[1959.09,1,32.232,293.864,30946.013],[1971.082,1,32.543,295.662,31063.918],[1983.025,1,32.854,297.454,31182.542],[1994.919,1,33.166,299.238,31301.881],[2006.761,1,33.479,301.014,31421.931],[2018.549,1,33.792,302.782,31542.691],[2030.281,1,34.105,304.542,31664.156],[2041.955,1,34.419,306.293,31786.323],[2053.568,1,34.732,308.035,31909.189],[2065.12,1,35.046,309.768,32032.75],[2076.608,1,35.36,311.491,32157.002],[2088.029,1,35.674,313.204,32281.942],[2099.383,1,35.987,314.907,32407.565],[2110.667,1,36.301,316.6,32533.867],[2121.88,1,36.614,318.282,32660.843],[2133.019,1,36.926,319.953,32788.491],[2144.082,1,37.238,321.612,32916.804],[2155.068,1,37.55,323.26,33045.779],[2165.976,1,37.861,324.896,33175.411],[2176.802,1,38.171,326.52,33305.694],[2187.546,1,38.48,328.132,33436.625],[2198.205,1,38.789,329.731,33568.198],[2208.779,1,39.096,331.317,33700.408],[2219.265,1,39.402,332.89,33833.25],[2229.661,1,39.707,334.449,33966.718],[2239.967,1,40.011,335.995,34100.807],[2250.18,1,40.313,337.527,34235.512],[2260.298,1,40.614,339.045,34370.827],[2270.321,1,40.914,340.548,34506.746],[2280.247,1,41.212,342.037,34643.264],[2290.074,1,41.508,343.511,34780.374],[2299.801,1,41.803,344.97,34918.071],[2309.426,1,42.095,346.414,35056.348],[2318.947,1,42.386,347.842,35195.2],[2328.365,1,42.675,349.255,35334.619],[2337.677,1,42.961,350.652,35474.601],[2346.881,1,43.246,352.032,35615.139],[2355.978,1,43.528,353.397,35756.225],[2364.964,1,43.807,354.745,35897.854],[2373.84,1,44.085,356.076,36040.018],[2382.604,1,44.36,357.391,36182.712],[2391.254,1,44.632,358.688,36325.929],[2399.791,1,44.902,359.969,36469.66],[2408.212,1,45.169,361.232,36613.901],[2416.517,1,45.433,362.478,36758.644],[2424.704,1,45.695,363.706,36903.881],[2432.774,1,45.953,364.916,37049.606],[2440.724,1,46.209,366.109,37195.811],[2448.554,1,46.461,367.283,37342.49],[2456.263,1,46.711,368.439,37489.635],[2463.85,1,46.957,369.578,37637.239],[2471.315,1,47.2,370.697,37785.295],[2478.657,1,47.44,371.799,37933.795],[2485.875,1,47.676,372.881,38082.731],[2492.969,1,47.909,373.945,38232.097],[2499.937,1,48.138,374.991,38381.885],[2506.781,1,48.364,376.017,38532.087],[2513.498,1,48.587,377.025,38682.696],[2520.088,1,48.806,378.013,38833.704],[2526.552,1,49.021,378.983,38985.104],[2532.889,1,49.232,379.933,39136.888],[2539.098,1,49.44,380.865,39289.048],[2545.179,1,49.644,381.777,39441.577],[2551.132,1,49.844,382.67,39594.467],[2556.958,1,50.04,383.544,39747.711],[2562.655,1,50.233,384.398,39901.3],[2568.223,1,50.421,385.234,40055.227],[2573.664,1,50.606,386.05,40209.484],[2578.976,1,50.786,386.846,40364.064],[2584.16,1,50.963,387.624,40518.958],[2589.216,1,51.135,388.382,40674.16],[2594.144,1,51.304,389.122,40829.662],[2598.945,1,51.468,389.842,40985.455],[2603.618,1,51.628,390.543,41141.533],[2608.165,1,51.785,391.225,41297.887],[2612.585,1,51.937,391.888,41454.51],[2616.88,1,52.085,392.532,41611.395],[2621.048,1,52.229,393.157,41768.533],[2625.092,1,52.369,393.764,41925.918],[2629.012,1,52.505,394.352,42083.542],[2632.809,1,52.637,394.921,42241.397],[2636.483,1,52.764,395.472,42399.476],[2640.034,1,52.888,396.005,42557.772],[2643.465,1,53.008,396.52,42716.278],[2646.776,1,53.123,397.016,42874.986],[2649.968,1,53.235,397.495,43033.889],[2653.042,1,53.342,397.956,43192.98],[2655.999,1,53.446,398.4,43352.251],[2658.841,1,53.545,398.826,43511.697],[2661.568,1,53.641,399.235,43671.31],[2664.183,1,53.733,399.627,43831.083],[2666.686,1,53.821,400.003,43991.01],[2669.078,1,53.905,400.362,44151.083],[2671.362,1,53.985,400.704,44311.297],[2673.539,1,54.062,401.031,44471.645],[2675.611,1,54.135,401.342,44632.12],[2677.579,1,54.205,401.637,44792.716],[2679.445,1,54.271,401.917,44953.427],[2681.212,1,54.333,402.182,45114.247],[2682.88,1,54.392,402.432,45275.17],[2684.452,1,54.448,402.668,45436.191],[2685.931,1,54.5,402.89,45597.303],[2687.317,1,54.549,403.098,45758.501],[2688.615,1,54.595,403.292,45919.779],[2689.824,1,54.638,403.474,46081.133],[2690.949,1,54.678,403.642,46242.556],[2691.992,1,54.715,403.799,46404.045],[2692.955,1,54.749,403.943,46565.594],[2693.84,1,54.781,404.076,46727.198],[2694.651,1,54.81,404.198,46888.853],[2695.39,1,54.836,404.308,47050.555],[2696.059,1,54.86,404.409,47212.299],[2696.663,1,54.881,404.499,47374.081],[2697.203,1,54.9,404.581,47535.897],[2697.684,1,54.918,404.653,47697.744],[2698.107,1,54.933,404.716,47859.618],[2698.477,1,54.946,404.771,48021.516],[2698.796,1,54.957,404.819,48183.434],[2699.068,1,54.967,404.86,48345.37],[2699.296,1,54.975,404.894,48507.321],[2699.484,1,54.982,404.923,48669.285],[2699.636,1,54.987,404.945,48831.259],[2699.755,1,54.991,404.963,48993.24],[2699.845,1,54.994,404.977,49155.229],[2699.91,1,54.997,404.986,49317.221],[2699.954,1,54.998,404.993,49479.217],[2699.98,1,54.999,404.997,49641.215],[2699.994,1,55,404.999,49803.215],[2699.999,1,55,405,49965.215],[2700,1,55,405,50127.215],[2700,1,55,405,50289.215],[2700,1,55,405,50451.215],[2700,1,55,405,50613.215],[2700,1,55,405,50775.215],[2700,1,55,405,50937.215],[2700,1,55,405,51099.215],[2700,1,55,405,51261.215],[2700,1,55,405,51423.215],[2700,1,55,405,51585.215],[2700,1,55,405,51747.215],[2700,1,55,405,51909.215],[2700,1,55,405,52071.215],[2700,1,55,405,52233.215],[2700,1,55,405,52395.215],[2700,1,55,405,52557.215],[2700,1,55,405,52719.215],[2700,1,55,405,52881.215],[2700,1,55,405,53043.215],[2700,1,55,405,53205.215],[2700,1,55,405,53367.215],[2700,1,55,405,53529.215],[2700,1,55,405,53691.215],[2700,1,55,405,53853.215],[2700,1,55,405,54015.215],[2700,1,55,405,54177.215],[2700,1,55,405,54339.215],[2700,1,55,405,54501.215],[2700,1,55,405,54663.215],[2700,1,55,405,54825.215],[2700,1,55,405,54987.215],[2700,1,55,405,55149.215],[2700,1,55,405,55311.215],[2700,1,55,405,55473.215],[2700,1,55,405,55635.215],[2700,1,55,405,55797.215],[2700,1,55,405,55959.215],[2700,1,55,405,56121.215],[2700,1,55,405,56283.215],[2700,1,55,405,56445.215],[2700,1,55,405,56607.215],[2700,1,55,405,56769.215],[2700,1,55,405,56931.215],[2700,1,55,405,57093.215],[2700,1,55,405,57255.215],[2700,1,55,405,57417.215],[2700,1,55,405,57579.215],[2700,1,55,405,57741.215],[2700,1,55,405,57903.215],[2700,1,55,405,58065.215],[2700,1,55,405,58227.215],[2700,1,55,405,58389.215],[2700,1,55,405,58551.215],[2700,1,55,405,58713.215],[2700,1,55,405,58875.215],[2700,1,55,405,59037.215],[2700,1,55,405,59199.215],[2700,1,55,405,59361.215],[2700,1,55,405,59523.215],[2700,1,55,405,59685.215],[2700,1,55,405,59847.215],[2700,1,55,405,60009.215],[2700,1,55,405,60171.215],[2700,1,55,405,60333.215],[2700,1,55,405,60495.215],[2700,1,55,405,60657.215],[2700,1,55,405,60819.215],[2700,1,55,405,60981.215],[2700,1,55,405,61143.215],[2700,1,55,405,61305.215],[2700,1,55,405,61467.215],[2700,1,55,405,61629.215],[2700,1,55,405,61791.215],[2700,1,55,405,61953.215],[2700,1,55,405,62115.215],[2700,1,55,405,62277.215],[2700,1,55,405,62439.215],[2700,1,55,405,62601.215],[2700,1,55,405,62763.215],[2700,1,55,405,62925.215],[2700,1,55,405,63087.215],[2700,1,55,405,63249.215],[2700,1,55,405,63411.215],[2700,1,55,405,63573.215],[2700,1,55,405,63735.215],[2700,1,55,405,63897.215],[2700,1,55,405,64059.215],[2700,1,55,405,64221.215],[2700,1,55,405,64383.215],[2700,1,55,405,64545.215],[2700,1,55,405,64707.215],[2700,1,55,405,64869.215],[2700,1,55,405,65031.215],[2700,1,55,405,65193.215],[2700,1,55,405,65355.215],[2700,1,55,405,65517.215],[2700,1,55,405,65679.215],[2700,1,55,405,65841.215],[2700,1,55,405,66003.215],[2700,1,55,405,66165.215],[2700,1,55,405,66327.215],[2700,1,55,405,66489.215],[2700,1,55,405,66651.215],[2700,1,55,405,66813.215],[2700,1,55,405,66975.215],[2700,1,55,405,67137.215],[2700,1,55,405,67299.215],[2700,1,55,405,67461.215],[2700,1,55,405,67623.215],[2700,1,55,405,67785.215],[2700,1,55,405,67947.215],[2700,1,55,405,68109.215],[2700,1,55,405,68271.215],[2700,1,55,405,68433.215],[2700,1,55,405,68595.215],[2700,1,55,405,68757.215],[2700,1,55,405,68919.215],[2700,1,55,405,69081.215],[2700,1,55,405,69243.215],[2700,1,55,405,69405.215],[2700,1,55,405,69567.215],[2700,1,55,405,69729.215],[2700,1,55,405,69891.215],[2700,1,55,405,70053.215],[2700,1,55,405,70215.215],[2700,1,55,405,70377.215],[2700,1,55,405,70539.215],[2700,1,55,405,70701.215],[2700,1,55,405,70863.215],[2700,1,55,405,71025.215],[2700,1,55,405,71187.215],[2700,1,55,405,71349.215],[2700,1,55,405,71511.215],[2700,1,55,405,71673.215],[2700,1,55,405,71835.215],[2700,1,55,405,71997.215],[2700,1,55,405,72159.215],[2700,1,55,405,72321.215],[2700,1,55,405,72483.215],[2700,1,55,405,72645.215],[2700,1,55,405,72807.215],[2700,1,55,405,72969.215],[2700,1,55,405,73131.215],[2700,1,55,405,73293.215],[2700,1,55,405,73455.215],[2700,1,55,405,73617.215],[2700,1,55,405,73779.215],[2700,1,55,405,73941.215],[2700,1,55,405,74103.215],[2700,1,55,405,74265.215],[2700,1,55,405,74427.215],[2700,1,55,405,74589.215],[2700,1,55,405,74751.215],[2700,1,55,405,74913.215],[2700,1,55,405,75075.215],[2700,1,55,405,75237.215],[2700,1,55,405,75399.215],[2700,1,55,405,75561.215],[2700,1,55,405,75723.215],[2700,1,55,405,75885.215],[2700,1,55,405,76047.215],[2700,1,55,405,76209.215],[2700,1,55,405,76371.215],[2700,1,55,405,76533.215],[2700,1,55,405,76695.215],[2700,1,55,405,76857.215],[2700,1,55,405,77019.215],[2700,1,55,405,77181.215],[2700,1,55,405,77343.215],[2700,1,55,405,77505.215],[2700,1,55,405,77667.215],[2700,1,55,405,77829.215],[2700,1,55,405,77991.215],[2700,1,55,405,78153.215],[2700,1,55,405,78315.215],[2700,1,55,405,78477.215],[2700,1,55,405,78639.215],[2700,1,55,405,78801.215],[2700,1,55,405,78963.215],[2700,1,55,405,79125.215],[2700,1,55,405,79287.215],[2700,1,55,405,79449.215],[2700,1,55,405,79611.215],[2700,1,55,405,79773.215],[2700,1,55,405,79935.215],[2700,1,55,405,80097.215],[2700,1,55,405,80259.215],[2700,1,55,405,80421.215],[2700,1,55,405,80583.215],[2700,1,55,405,80745.215],[2700,1,55,405,80907.215],[2700,1,55,405,81069.215],[2700,1,55,405,81231.215],[2700,1,55,405,81393.215],[2700,1,55,405,81555.215],[2700,1,55,405,81717.215],[2700,1,55,405,81879.215],[2700,1,55,405,82041.215],[2700,1,55,405,82203.215],[2700,1,55,405,82365.215],[2700,1,55,405,82527.215],[2700,1,55,405,82689.215],[2700,1,55,405,82851.215],[2700,1,55,405,83013.215],[2700,1,55,405,83175.215],[2700,1,55,405,83337.215],[2700,1,55,405,83499.215],[2700,1,55,405,83661.215],[2700,1,55,405,83823.215],[2700,1,55,405,83985.215],[2700,1,55,405,84147.215],[2700,1,55,405,84309.215],[2700,1,55,405,84471.215],[2700,1,55,405,84633.215],[2700,1,55,405,84795.215],[2700,1,55,405,84957.215],[2700,1,55,405,85119.215],[2700,1,55,405,85281.215],[2700,1,55,405,85443.215],[2700,1,55,405,85605.215],[2700,1,55,405,85767.215],[2700,1,55,405,85929.215],[2700,1,55,405,86091.215],[2700,1,55,405,86253.215],[2700,1,55,405,86415.215],[2700,1,55,405,86577.215],[2700,1,55,405,86739.215],[2700,1,55,405,86901.215],[2700,1,55,405,87063.215],[2700,1,55,405,87225.215],[2700,1,55,405,87387.215],[2700,1,55,405,87549.215],[2700,1,55,405,87711.215],[2700,1,55,405,87873.215],[2700,1,55,405,88035.215],[2700,1,55,405,88197.215],[2700,1,55,405,88359.215],[2700,1,55,405,88521.215],[2700,1,55,405,88683.215],[2700,1,55,405,88845.215],[2700,1,55,405,89007.215],[2700,1,55,405,89169.215],[2700,1,55,405,89331.215],[2700,1,55,405,89493.215],[2700,1,55,405,89655.215],[2700,1,55,405,89817.215],[2700,1,55,405,89979.215],[2700,1,55,405,90141.215],[2700,1,55,405,90303.215],[2700,1,55,405,90465.215],[2700,1,55,405,90627.215],[2700,1,55,405,90789.215],[2700,1,55,405,90951.215],[2700,1,55,405,91113.215],[2700,1,55,405,91275.215],[2700,1,55,405,91437.215],[2700,1,55,405,91599.215],[2700,1,55,405,91761.215],[2700,1,55,405,91923.215],[2700,1,55,405,92085.215],[2700,1,55,405,92247.215],[2700,1,55,405,92409.215],[2700,1,55,405,92571.215],[2700,1,55,405,92733.215],[2700,1,55,405,92895.215],[2700,1,55,405,93057.215],[2700,1,55,405,93219.215],[2700,1,55,405,93381.215],[2700,1,55,405,93543.215],[2700,1,55,405,93705.215],[2700,1,55,405,93867.215],[2700,1,55,405,94029.215],[2700,1,55,405,94191.215],[2700,1,55,405,94353.215],[2700,1,55,405,94515.215],[2700,1,55,405,94677.215],[2700,1,55,405,94839.215],[2700,1,55,405,95001.215],[2700,1,55,405,95163.215],[2700,1,55,405,95325.215],[2700,1,55,405,95487.215],[2700,1,55,405,95649.215],[2700,1,55,405,95811.215],[2700,1,55,405,95973.215],[2700,1,55,405,96135.215],[2700,1,55,405,96297.215],[2700,1,55,405,96459.215],[2700,1,55,405,96621.215],[2700,1,55,405,96783.215],[2700,1,55,405,96945.215],[2700,1,55,405,97107.215],[2699.999,1,55,405,97269.214],[2699.994,1,55,404.999,97431.214],[2699.98,1,54.999,404.997,97593.214],[2699.954,1,54.998,404.993,97755.212],[2699.91,1,54.997,404.986,97917.208],[2699.845,1,54.994,404.977,98079.2],[2699.755,1,54.991,404.963,98241.189],[2699.636,1,54.987,404.945,98403.17],[2699.484,1,54.982,404.923,98565.144],[2699.296,1,54.975,404.894,98727.108],[2699.068,1,54.967,404.86,98889.059],[2698.796,1,54.957,404.819,99050.995],[2698.477,1,54.946,404.771,99212.913],[2698.107,1,54.933,404.716,99374.811],[2697.684,1,54.918,404.653,99536.685],[2697.203,1,54.9,404.581,99698.532],[2696.663,1,54.881,404.499,99860.348],[2696.059,1,54.86,404.409,100022.13],[2695.39,1,54.836,404.308,100183.874],[2694.651,1,54.81,404.198,100345.576],[2693.84,1,54.781,404.076,100507.231],[2692.955,1,54.749,403.943,100668.835],[2691.992,1,54.715,403.799,100830.384],[2690.949,1,54.678,403.642,100991.873],[2689.824,1,54.638,403.474,101153.296],[2688.615,1,54.595,403.292,101314.65],[2687.317,1,54.549,403.098,101475.928],[2685.931,1,54.5,402.89,101637.126],[2684.452,1,54.448,402.668,101798.238],[2682.88,1,54.392,402.432,101959.259],[2681.212,1,54.333,402.182,102120.182],[2679.445,1,54.271,401.917,102281.002],[2677.579,1,54.205,401.637,102441.713],[2675.611,1,54.135,401.342,102602.309],[2673.539,1,54.062,401.031,102762.784],[2671.362,1,53.985,400.704,102923.132],[2669.078,1,53.905,400.362,103083.346],[2666.686,1,53.821,400.003,103243.419],[2664.183,1,53.733,399.627,103403.346],[2661.568,1,53.641,399.235,103563.119],[2658.841,1,53.545,398.826,103722.732],[2655.999,1,53.446,398.4,103882.178],[2653.042,1,53.342,397.956,104041.449],[2649.968,1,53.235,397.495,104200.54],[2646.776,1,53.123,397.016,104359.443],[2643.465,1,53.008,396.52,104518.151],[2640.034,1,52.888,396.005,104676.657],[2636.483,1,52.764,395.472,104834.953],[2632.809,1,52.637,394.921,104993.032],[2629.012,1,52.505,394.352,105150.887],[2625.092,1,52.369,393.764,105308.511],[2621.048,1,52.229,393.157,105465.896],[2616.88,1,52.085,392.532,105623.034],[2612.585,1,51.937,391.888,105779.919],[2608.165,1,51.785,391.225,105936.542],[2603.618,1,51.628,390.543,106092.896],[2598.945,1,51.468,389.842,106248.974],[2594.144,1,51.304,389.122,106404.767],[2589.216,1,51.135,388.382,106560.269],[2584.16,1,50.963,387.624,106715.471],[2578.976,1,50.786,386.846,106870.365],[2573.664,1,50.606,386.05,107024.945],[2568.223,1,50.421,385.234,107179.202],[2562.655,1,50.233,384.398,107333.129],[2556.958,1,50.04,383.544,107486.718],[2551.132,1,49.844,382.67,107639.962],[2545.179,1,49.644,381.777,107792.852],[2539.098,1,49.44,380.865,107945.381],[2532.889,1,49.232,379.933,108097.541],[2526.552,1,49.021,378.983,108249.325],[2520.088,1,48.806,378.013,108400.725],[2513.498,1,48.587,377.025,108551.733],[2506.781,1,48.364,376.017,108702.342],[2499.937,1,48.138,374.991,108852.544],[2492.969,1,47.909,373.945,109002.332],[2485.875,1,47.676,372.881,109151.698],[2478.657,1,47.44,371.799,109300.634],[2471.315,1,47.2,370.697,109449.134],[2463.85,1,46.957,369.578,109597.19],[2456.263,1,46.711,368.439,109744.794],[2448.554,1,46.461,367.283,109891.939],[2440.724,1,46.209,366.109,110038.618],[2432.774,1,45.953,364.916,110184.823],[2424.704,1,45.695,363.706,110330.548],[2416.517,1,45.433,362.478,110475.785],[2408.212,1,45.169,361.232,110620.528],[2399.791,1,44.902,359.969,110764.769],[2391.254,1,44.632,358.688,110908.5],[2382.604,1,44.36,357.391,111051.717],[2373.84,1,44.085,356.076,111194.411],[2364.964,1,43.807,354.745,111336.575],[2355.978,1,43.528,353.397,111478.204],[2346.881,1,43.246,352.032,111619.29],[2337.677,1,42.961,350.652,111759.828],[2328.365,1,42.675,349.255,111899.81],[2318.947,1,42.386,347.842,112039.229],[2309.426,1,42.095,346.414,112178.081],[2299.801,1,41.803,344.97,112316.358],[2290.074,1,41.508,343.511,112454.055],[2280.247,1,41.212,342.037,112591.165],[2270.321,1,40.914,340.548,112727.683],[2260.298,1,40.614,339.045,112863.602],[2250.18,1,40.313,337.527,112998.917],[2239.967,1,40.011,335.995,113133.622],[2229.661,1,39.707,334.449,113267.711],[2219.265,1,39.402,332.89,113401.179],[2208.779,1,39.096,331.317,113534.021],[2198.205,1,38.789,329.731,113666.231],[2187.546,1,38.48,328.132,113797.804],[2176.802,1,38.171,326.52,113928.735],[2165.976,1,37.861,324.896,114059.018],[2155.068,1,37.55,323.26,114188.65],[2144.082,1,37.238,321.612,114317.625],[2133.019,1,36.926,319.953,114445.938],[2121.88,1,36.614,318.282,114573.586],[2110.667,1,36.301,316.6,114700.563],[2099.383,1,35.987,314.907,114826.864],[2088.029,1,35.674,313.204,114952.487],[2076.608,1,35.36,311.491,115077.427],[2065.12,1,35.046,309.768,115201.679],[2053.568,1,34.732,308.035,115325.24],[2041.955,1,34.419,306.293,115448.106],[2030.281,1,34.105,304.542,115570.273],[2018.549,1,33.792,302.782,115691.738],[2006.761,1,33.479,301.014,115812.498],[1994.919,1,33.166,299.238,115932.548],[1983.025,1,32.854,297.454,116051.887],[1971.082,1,32.543,295.662,116170.511],[1959.09,1,32.232,293.864,116288.416],[1947.053,1,31.922,292.058,116405.6],[1934.972,1,31.612,290.246,116522.061],[1922.849,1,31.304,288.427,116637.796],[1910.687,1,30.997,286.603,116752.803],[1898.488,1,30.69,284.773,116867.078],[1886.254,1,30.385,282.938,116980.62],[1873.986,1,30.08,281.098,117093.428],[1861.688,1,29.777,279.253,117205.498],[1849.361,1,29.476,277.404,117316.83],[1837.008,1,29.175,275.551,117427.421],[1824.63,1,28.876,273.695,117537.27],[1812.23,1,28.579,271.835,117646.376],[1799.811,1,28.283,269.972,117754.737],[1787.373,1,27.989,268.106,117862.353],[1774.92,1,27.696,266.238,117969.222],[1762.454,1,27.405,264.368,118075.343],[1749.976,1,27.116,262.496,118180.716],[1737.49,1,26.829,260.624,118285.34],[1724.997,1,26.544,258.75,118389.215],[1712.5,1,26.26,256.875,118492.34],[1700,1,25.979,255,118594.715],[1687.5,1,25.7,253.125,118696.34],[1675.003,1,25.423,251.25,118797.215],[1662.51,1,25.148,249.376,118897.34],[1650.024,1,24.875,247.504,118996.716],[1637.546,1,24.604,245.632,119095.343],[1625.08,1,24.336,243.762,119193.222],[1612.627,1,24.07,241.894,119290.353],[1600.189,1,23.806,240.028,119386.737],[1587.77,1,23.545,238.165,119482.376],[1575.37,1,23.287,236.305,119577.27],[1562.992,1,23.03,234.449,119671.421],[1550.639,1,22.777,232.596,119764.83],[1538.312,1,22.526,230.747,119857.498],[1526.014,1,22.277,228.902,119949.428],[1513.746,1,22.031,227.062,120040.62],[1501.512,1,21.788,225.227,120131.078],[1489.313,1,21.547,223.397,120220.803],[1477.151,1,21.309,221.573,120309.796],[1465.028,1,21.074,219.754,120398.061],[1452.947,1,20.841,217.942,120485.6],[1440.91,1,20.612,216.136,120572.416],[1428.918,1,20.385,214.338,120658.511],[1416.975,1,20.16,212.546,120743.887],[1405.081,1,19.939,210.762,120828.548],[1393.239,1,19.72,208.986,120912.498],[1381.451,1,19.505,207.218,120995.738],[1369.719,1,19.292,205.458,121078.273],[1358.045,1,19.082,203.707,121160.106],[1346.432,1,18.875,201.965,121241.24],[1334.88,1,18.67,200.232,121321.679],[1323.392,1,18.469,198.509,121401.427],[1311.971,1,18.27,196.796,121480.487],[1300.617,1,18.075,195.093,121558.864],[1289.333,1,17.882,193.4,121636.563],[1278.12,1,17.692,191.718,121713.586],[1266.981,1,17.505,190.047,121789.938],[1255.918,1,17.321,188.388,121865.625],[1244.932,1,17.14,186.74,121940.65],[1234.024,1,16.961,185.104,122015.018],[1223.198,1,16.786,183.48,122088.735],[1212.454,1,16.613,181.868,122161.804],[1201.795,1,16.444,180.269,122234.231],[1191.221,1,16.277,178.683,122306.021],[1180.735,1,16.113,177.11,122377.179],[1170.339,1,15.952,175.551,122447.711],[1160.033,1,15.793,174.005,122517.622],[1149.82,1,15.638,172.473,122586.917],[1139.702,1,15.485,170.955,122655.602],[1129.679,1,15.335,169.452,122723.683],[1119.753,1,15.187,167.963,122791.165],[1109.926,1,15.043,166.489,122858.055],[1100.199,1,14.901,165.03,122924.358],[1090.574,1,14.762,163.586,122990.081],[1081.053,1,14.626,162.158,123055.229],[1071.635,1,14.492,160.745,123119.81],[1062.323,1,14.361,159.348,123183.828],[1053.119,1,14.232,157.968,123247.29],[1044.022,1,14.107,156.603,123310.204],[1035.036,1,13.983,155.255,123372.575],[1026.16,1,13.863,153.924,123434.411],[1017.396,1,13.745,152.609,123495.717],[1008.746,1,13.629,151.312,123556.5],[1000.209,1,13.516,150.031,123616.769],[991.788,1,13.405,148.768,123676.528],[983.483,1,13.297,147.522,123735.785],[975.296,1,13.191,146.294,123794.548],[967.226,1,13.088,145.084,123852.823],[959.276,1,12.987,143.891,123910.618],[951.446,1,12.888,142.717,123967.939],[943.737,1,12.792,141.561,124024.794],[936.15,1,12.698,140.422,124081.19],[928.685,1,12.606,139.303,124137.134],[921.343,1,12.516,138.201,124192.634],[914.125,1,12.429,137.119,124247.698],[907.031,1,12.344,136.055,124302.332],[900.063,1,12.261,135.009,124356.544],[893.219,1,12.18,133.983,124410.342],[886.502,1,12.101,132.975,124463.733],[879.912,1,12.024,131.987,124516.725],[873.448,1,11.949,131.017,124569.325],[867.111,1,11.877,130.067,124621.541],[860.902,1,11.806,129.135,124673.381],[854.821,1,11.737,128.223,124724.852],[848.868,1,11.67,127.33,124775.962],[843.042,1,11.605,126.456,124826.718],[837.345,1,11.542,125.602,124877.129],[831.777,1,11.481,124.766,124927.202],[826.336,1,11.421,123.95,124976.945],[821.024,1,11.363,123.154,125026.365],[815.84,1,11.308,122.376,125075.471],[810.784,1,11.253,121.618,125124.269],[805.856,1,11.201,120.878,125172.767],[801.055,1,11.15,120.158,125220.974],[796.382,1,11.101,119.457,125268.896],[791.835,1,11.053,118.775,125316.542],[787.415,1,11.007,118.112,125363.919],[783.12,1,10.962,117.468,125411.034],[778.952,1,10.92,116.843,125457.896],[774.908,1,10.878,116.236,125504.511],[770.988,1,10.838,115.648,125550.887],[767.191,1,10.8,115.079,125597.032],[763.517,1,10.762,114.528,125642.953],[759.966,1,10.727,113.995,125688.657],[756.535,1,10.692,113.48,125734.151],[753.224,1,10.66,112.984,125779.443],[750.032,1,10.628,112.505,125824.54],[746.958,1,10.598,112.044,125869.449],[744.001,1,10.568,111.6,125914.178],[741.159,1,10.541,111.174,125958.732],[738.432,1,10.514,110.765,126003.119],[735.817,1,10.489,110.373,126047.346],[733.314,1,10.464,109.997,126091.419],[730.922,1,10.441,109.638,126135.346],[728.638,1,10.419,109.296,126179.132],[726.461,1,10.398,108.969,126222.784],[724.389,1,10.378,108.658,126266.309],[722.421,1,10.36,108.363,126309.713],[720.555,1,10.342,108.083,126353.002],[718.788,1,10.325,107.818,126396.182],[717.12,1,10.309,107.568,126439.259],[715.548,1,10.295,107.332,126482.238],[714.069,1,10.281,107.11,126525.126],[712.683,1,10.268,106.902,126567.928],[711.385,1,10.255,106.708,126610.65],[710.176,1,10.244,106.526,126653.296],[709.051,1,10.233,106.358,126695.873],[708.008,1,10.224,106.201,126738.384],[707.045,1,10.215,106.057,126780.835],[706.16,1,10.206,105.924,126823.231],[705.349,1,10.199,105.802,126865.576],[704.61,1,10.192,105.692,126907.874],[703.941,1,10.186,105.591,126950.13],[703.337,1,10.18,105.501,126992.348],[702.797,1,10.175,105.419,127034.532],[702.316,1,10.171,105.347,127076.685],[701.893,1,10.167,105.284,127118.811],[701.523,1,10.163,105.229,127160.913],[701.204,1,10.16,105.181,127202.995],[700.932,1,10.158,105.14,127245.059],[700.704,1,10.156,105.106,127287.108],[700.516,1,10.154,105.077,127329.144],[700.364,1,10.153,105.055,127371.17],[700.245,1,10.152,105.037,127413.189],[700.155,1,10.151,105.023,127455.2],[700.09,1,10.15,105.014,127497.208],[700.046,1,10.15,105.007,127539.212],[700.02,1,10.15,105.003,127581.214],[700.006,1,10.149,105.001,127623.214],[700.001,1,10.149,105,127665.214],[700,1,10.149,105,127707.215],[700,1,10.149,105,127749.215],[700,1,10.149,105,127791.215],[700,1,10.149,105,127833.215],[700,1,10.149,105,127875.215],[700,1,10.149,105,127917.215],[700,1,10.149,105,127959.215],[700,1,10.149,105,128001.215],[700,1,10.149,105,128043.215],[700,1,10.149,105,128085.215],[700,1,10.149,105,128127.215],[700,1,10.149,105,128169.215],[700,1,10.149,105,128211.215],[700,1,10.149,105,128253.215],[700,1,10.149,105,128295.215],[700,1,10.149,105,128337.215],[700,1,10.149,105,128379.215],[700,1,10.149,105,128421.215],[700,1,10.149,105,128463.215],[700,1,10.149,105,128505.215],[700,1,10.149,105,128547.215],[700,1,10.149,105,128589.215],[700,1,10.149,105,128631.215],[700,1,10.149,105,128673.215],[700,1,10.149,105,128715.215],[700,1,10.149,105,128757.215],[700,1,10.149,105,128799.215],[700,1,10.149,105,128841.215],[700,1,10.149,105,128883.215],[700,1,10.149,105,128925.215],[700,1,10.149,105,128967.215],[700,1,10.149,105,129009.215],[700,1,10.149,105,129051.215],[700,1,10.149,105,129093.215],[700,1,10.149,105,129135.215],[700,1,10.149,105,129177.215],[700,1,10.149,105,129219.215],[700,1,10.149,105,129261.215],[700,1,10.149,105,129303.215],[700,1,10.149,105,129345.215],[700,1,10.149,105,129387.215],[700,1,10.149,105,129429.215],[700,1,10.149,105,129471.215],[700,1,10.149,105,129513.215],[700,1,10.149,105,129555.215],[700,1,10.149,105,129597.215],[700,1,10.149,105,129639.215],[700,1,10.149,105,129681.215],[700,1,10.149,105,129723.215],[700,1,10.149,105,129765.215],[700,1,10.149,105,129807.215],[700,1,10.149,105,129849.215],[700,1,10.149,105,129891.215],[700,1,10.149,105,129933.215],[700,1,10.149,105,129975.215],[700,1,10.149,105,130017.215],[700,1,10.149,105,130059.215],[700,1,10.149,105,130101.215],[700,1,10.149,105,130143.215],[700,1,10.149,105,130185.215],[700,1,10.149,105,130227.215],[700,1,10.149,105,130269.215],[700,1,10.149,105,130311.215],[700,1,10.149,105,130353.215],[700,1,10.149,105,130395.215],[700,1,10.149,105,130437.215],[700,1,10.149,105,130479.215],[700,1,10.149,105,130521.215],[700,1,10.149,105,130563.215],[700,1,10.149,105,130605.215],[700,1,10.149,105,130647.215],[700,1,10.149,105,130689.215],[700,1,10.149,105,130731.215],[700,1,10.149,105,130773.215],[700,1,10.149,105,130815.215],[700,1,10.149,105,130857.215],[700,1,10.149,105,130899.215],[700,1,10.149,105,130941.215],[700,1,10.149,105,130983.215],[700,1,10.149,105,131025.215],[700,1,10.149,105,131067.215],[700,1,10.149,105,131109.215],[700,1,10.149,105,131151.215],[700,1,10.149,105,131193.215],[700,1,10.149,105,131235.215],[700,1,10.149,105,131277.215],[700,1,10.149,105,131319.215],[700,1,10.149,105,131361.215],[700,1,10.149,105,131403.215],[700,1,10.149,105,131445.215],[700,1,10.149,105,131487.215],[700,1,10.149,105,131529.215],[700,1,10.149,105,131571.215],[700,1,10.149,105,131613.215],[700,1,10.149,105,131655.215],[700,1,10.149,105,131697.215],[700,1,10.149,105,131739.215],[700,1,10.149,105,131781.215],[700,1,10.149,105,131823.215],[700,1,10.149,105,131865.215],[700,1,10.149,105,131907.215],[700,1,10.149,105,131949.215],[700,1,10.149,105,131991.215],[700,1,10.149,105,132033.215],[700,1,10.149,105,132075.215],[700,1,10.149,105,132117.215],[700,1,10.149,105,132159.215],[700,1,10.149,105,132201.215],[700,1,10.149,105,132243.215],[700,1,10.149,105,132285.215],[700,1,10.149,105,132327.215],[700,1,10.149,105,132369.215],[700,1,10.149,105,132411.215],[700,1,10.149,105,132453.215],[700,1,10.149,105,132495.215],[700,1,10.149,105,132537.215],[700,1,10.149,105,132579.215],[700,1,10.149,105,132621.215],[700,1,10.149,105,132663.215],[700,1,10.149,105,132705.215],[700,1,10.149,105,132747.215],[700,1,10.149,105,132789.215],[700,1,10.149,105,132831.215],[700,1,10.149,105,132873.215],[700,1,10.149,105,132915.215],[700,1,10.149,105,132957.215],[700,1,10.149,105,132999.215],[700,1,10.149,105,133041.215],[700,1,10.149,105,133083.215],[700,1,10.149,105,133125.215],[700,1,10.149,105,133167.215],[700,1,10.149,105,133209.215],[700,1,10.149,105,133251.215],[700,1,10.149,105,133293.215],[700,1,10.149,105,133335.215],[700,1,10.149,105,133377.215],[700,1,10.149,105,133419.215],[700,1,10.149,105,133461.215],[700,1,10.149,105,133503.215],[700,1,10.149,105,133545.215],[700,1,10.149,105,133587.215]],"sparks":[[3.3012,17,0],[3.3488,10,0],[3.3964,3,1],[3.444,14,0],[3.4917,7,1],[3.5393,18,0],[3.5869,11,0],[3.6345,4,0],[3.6821,15,0],[3.7298,8,0],[3.7774,1,0],[3.825,12,0],[3.8726,5,0],[3.9202,16,0],[3.9679,9,1],[4.0155,2,1],[4.0631,13,1],[4.1107,6,1],[4.1583,17,1],[4.2058,10,1],[4.252,3,1],[4.2952,14,1],[4.334,7,1],[4.3684,18,1],[4.3988,11,1],[4.4259,4,1],[4.4501,15,1],[4.4722,8,1],[4.4924,1,1],[4.5111,12,1],[4.5285,5,1],[4.5449,16,1],[4.5603,9,1],[4.5749,2,1],[4.5887,13,1],[4.602,6,1],[4.6147,17,1],[4.627,10,1],[4.6387,3,1],[4.6501,14,1],[4.6611,7,1],[4.6718,18,1],[4.6822,11,1],[4.6924,4,1],[4.7022,15,1],[4.7119,8,1],[4.7213,1,1],[4.7305,12,1],[4.7396,5,1],[4.7484,16,1],[4.7572,9,1],[4.7657,2,1],[4.7741,13,1],[4.7824,6,1],[4.7906,17,1],[4.7986,10,1],[4.8066,3,1],[4.8144,14,1],[4.8222,7,1],[4.8298,18,1],[4.8374,11,1],[4.8449,4,1],[4.8523,15,1],[4.8596,8,1],[4.8669,1,1],[4.8741,12,1],[4.8812,5,1],[4.8883,16,1],[4.8953,9,1],[4.9023,2,1],[4.9093,13,1],[4.9161,6,1],[4.923,17,1],[4.9298,10,1],[4.9366,3,1],[4.9433,14,1],[4.95,7,1],[4.9567,18,1],[4.9633,11,1],[4.9699,4,1],[4.9765,15,1],[4.9831,8,1],[4.9896,1,1],[4.9961,12,1],[5.0026,5,1],[5.0091,16,1],[5.0156,9,1],[5.022,2,1],[5.0285,13,1],[5.0349,6,1],[5.0413,17,1],[5.0477,10,1],[5.0541,3,1],[5.0605,14,1],[5.0669,7,1],[5.0733,18,1],[5.0796,11,1],[5.086,4,1],[5.0924,15,1],[5.0987,8,1],[5.1051,1,1],[5.1114,12,1],[5.1178,5,1],[5.1241,16,1],[5.1305,9,1],[5.1368,2,1],[5.1432,13,1],[5.1495,6,1],[5.1559,17,1],[5.1622,10,1],[5.1686,3,1],[5.1749,14,1],[5.1813,7,1],[5.1876,18,1],[5.194,11,1],[5.2003,4,1],[5.2067,15,1],[5.213,8,1],[5.2194,1,1],[5.2257,12,1],[5.2321,5,1],[5.2384,16,1],[5.2448,9,1],[5.2512,2,1],[5.2575,13,1],[5.2639,6,1],[5.2703,17,1],[5.2766,10,1],[5.283,3,1],[5.2894,14,1],[5.2958,7,1],[5.3022,18,1],[5.3085,11,1],[5.3149,4,1],[5.3213,15,1],[5.3278,8,1],[5.3342,1,1],[5.3406,12,1],[5.347,5,1],[5.3534,16,1],[5.3599,9,1],[5.3663,2,1],[5.3728,13,1],[5.3793,6,1],[5.3857,17,1],[5.3922,10,1],[5.3987,3,1],[5.4052,14,1],[5.4118,7,1],[5.4183,18,1],[5.4248,11,1],[5.4314,4,1],[5.438,15,1],[5.4446,8,1],[5.4512,1,1],[5.4578,12,1],[5.4644,5,1],[5.471,16,1],[5.4777,9,1],[5.4844,2,1],[5.4911,13,1],[5.4978,6,1],[5.5045,17,1],[5.5113,10,1],[5.518,3,1],[5.5248,14,1],[5.5316,7,1],[5.5385,18,1],[5.5453,11,1],[5.5522,4,1],[5.5591,15,1],[5.566,8,1],[5.573,1,1],[5.5799,12,1],[5.5869,5,1],[5.594,16,1],[5.601,9,1],[5.6081,2,1],[5.6152,13,1],[5.6223,6,1],[5.6295,17,1],[5.6367,10,1],[5.6439,3,1],[5.6512,14,1],[5.6585,7,1],[5.6658,18,1],[5.6731,11,1],[5.6805,4,1],[5.688,15,1],[5.6954,8,1],[5.7029,1,1],[5.7104,12,1],[5.718,5,1],[5.7256,16,1],[5.7332,9,1],[5.7409,2,1],[5.7486,13,1],[5.7564,6,1],[5.7642,17,1],[5.772,10,1],[5.7799,3,1],[5.7878,14,1],[5.7958,7,1],[5.8038,18,1],[5.8119,11,1],[5.8199,4,1],[5.8281,15,1],[5.8363,8,1],[5.8445,1,1],[5.8527,12,1],[5.8611,5,1],[5.8694,16,1],[5.8778,9,1],[5.8862,2,1],[5.8947,13,1],[5.9033,6,1],[5.9118,17,1],[5.9204,10,1],[5.9291,3,1],[5.9378,14,1],[5.9466,7,1],[5.9553,18,1],[5.9642,11,1],[5.973,4,1],[5.9819,15,1],[5.9909,8,1],[5.9999,1,1],[6.0089,12,1],[6.018,5,1],[6.0271,16,1],[6.0362,9,1],[6.0453,2,1],[6.0545,13,1],[6.0638,6,1],[6.073,17,1],[6.0823,10,1],[6.0916,3,1],[6.1009,14,1],[6.1103,7,1],[6.1196,18,1],[6.129,11,1],[6.1384,4,1],[6.1479,15,1],[6.1573,8,1],[6.1668,1,1],[6.1762,12,1],[6.1857,5,1],[6.1952,16,1],[6.2047,9,1],[6.2142,2,1],[6.2237,13,1],[6.2332,6,1],[6.2427,17,1],[6.2523,10,1],[6.2618,3,1],[6.2713,14,1],[6.2808,7,1],[6.2904,18,1],[6.2999,11,1],[6.3094,4,1],[6.3189,15,1],[6.3285,8,1],[6.338,1,1],[6.3475,12,1],[6.357,5,1],[6.3665,16,1],[6.3761,9,1],[6.3856,2,1],[6.3951,13,1],[6.4046,6,1],[6.4142,17,1],[6.4237,10,1],[6.4332,3,1],[6.4428,14,1],[6.4523,7,1],[6.4618,18,1],[6.4714,11,1],[6.481,4,1],[6.4906,15,1],[6.5003,8,1],[6.51,1,1],[6.5198,12,1],[6.5296,5,1],[6.5395,16,1],[6.5495,9,1],[6.5595,2,1],[6.5697,13,1],[6.58,6,1],[6.5905,17,1],[6.6011,10,1],[6.6119,3,1],[6.6229,14,1],[6.6341,7,1],[6.6456,18,1],[6.6573,11,1],[6.6694,4,1],[6.6818,15,1],[6.6947,8,1],[6.7081,1,1],[6.7219,12,1],[6.7365,5,1],[6.7517,16,1],[6.7678,9,1],[6.7849,2,1],[6.8031,13,1],[6.8229,6,1],[6.8444,17,1],[6.8681,10,1],[6.8947,3,1],[6.9252,14,1],[6.9609,7,1],[7.0045,18,1],[7.0604,11,1],[7.1375,4,1],[7.2551,15,1],[7.4431,8,1],[7.6788,1,1],[7.9169,12,1],[8.155,5,1],[8.3931,16,1],[8.6312,9,1],[8.8693,2,1],[9.1074,13,1],[9.3454,6,1],[9.5835,17,1],[9.8216,10,1],[10.0597,3,1],[10.2978,14,1],[10.5359,7,1],[10.774,18,1],[11.0121,11,1],[11.2502,4,1],[11.4883,15,1],[11.7264,8,1],[11.9645,1,1],[12.2026,12,1],[12.4407,5,1],[12.6789,16,1],[12.9321,9,1],[13.2608,2,1],[13.6411,13,1],[14.022,6,1],[14.403,17,1],[14.7839,10,1],[15.1649,3,1],[15.5458,14,1],[15.9268,7,1],[16.3077,18,1],[16.6887,11,1],[17.0696,4,1],[17.4506,15,1],[17.8316,8,1],[18.2125,1,1],[18.5935,12,1],[18.9744,5,1],[19.3554,16,1],[19.7363,9,1],[20.1173,2,1],[20.4982,13,1],[20.8792,6,1],[21.2601,17,1],[21.6411,10,1],[22.022,3,1],[22.403,14,1],[22.7839,7,1],[23.1649,18,1],[23.5458,11,1],[23.8995,4,1],[24.1178,15,1],[24.2689,8,1],[24.4034,1,1],[24.5368,12,1],[24.6701,5,1],[24.8034,16,1],[24.9368,9,1],[25.0701,2,1],[25.2034,13,1],[25.3368,6,1],[25.4701,17,1],[25.6034,10,1],[25.7368,3,1],[25.8701,14,1],[26.0034,7,1],[26.1368,18,1],[26.2701,11,1],[26.4034,4,1],[26.5368,15,1],[26.6701,8,1],[26.8034,1,1],[26.9368,12,1],[27.0701,5,1],[27.2034,16,1],[27.3368,9,1],[27.4701,2,1],[27.6034,13,1],[27.7368,6,1],[27.8701,17,1],[28.0034,10,1],[28.1368,3,1],[28.2701,14,1],[28.4034,7,1],[28.5356,18,1],[28.6568,11,1],[28.756,4,1],[28.8336,15,1],[28.8947,8,1],[28.9441,1,1],[28.9852,12,1],[29.0204,5,1],[29.0511,16,1],[29.0785,9,1],[29.1031,2,1],[29.1256,13,1],[29.1463,6,1],[29.1656,17,1],[29.1836,10,1],[29.2006,3,1],[29.2168,14,1],[29.2321,7,1],[29.2468,18,1],[29.2608,11,1],[29.2744,4,1],[29.2875,15,1],[29.3002,8,1],[29.3126,1,1],[29.3246,12,1],[29.3363,5,1],[29.3477,16,1],[29.359,9,1],[29.37,2,1],[29.3808,13,1],[29.3915,6,1],[29.402,17,1],[29.4123,10,1],[29.4226,3,1],[29.4327,14,1],[29.4428,7,1],[29.4527,18,1],[29.4626,11,1],[29.4724,4,1],[29.4822,15,1],[29.4919,8,1],[29.5015,1,1],[29.5112,12,1],[29.5208,5,1],[29.5303,16,1],[29.5399,9,1],[29.5494,2,1],[29.559,13,1],[29.5685,6,1],[29.578,17,1],[29.5876,10,1],[29.5971,3,1],[29.6066,14,1],[29.6161,7,1],[29.6257,18,1],[29.6352,11,1],[29.6447,4,1],[29.6542,15,1],[29.6638,8,1],[29.6733,1,1],[29.6828,12,1],[29.6923,5,1],[29.7019,16,1],[29.7114,9,1],[29.7209,2,1],[29.7304,13,1],[29.7399,6,1],[29.7495,17,1],[29.759,10,1],[29.7685,3,1],[29.778,14,1],[29.7876,7,1],[29.7971,18,1],[29.8066,11,1],[29.8161,4,1],[29.8256,15,1],[29.8351,8,1],[29.8446,1,1],[29.8541,12,1],[29.8636,5,1],[29.8731,16,1],[29.8825,9,1],[29.892,2,1],[29.9015,13,1],[29.9109,6,1],[29.9203,17,1],[29.9298,10,1],[29.9392,3,1],[29.9486,14,1],[29.9579,7,1],[29.9673,18,1],[29.9767,11,1],[29.986,4,1],[29.9953,15,1],[30.0046,8,1],[30.0139,1,1],[30.0231,12,1],[30.0324,5,1],[30.0416,16,1],[30.0508,9,1],[30.0599,2,1],[30.0691,13,1],[30.0782,6,1],[30.0873,17,1],[30.0963,10,1],[30.1053,3,1],[30.1143,14,1],[30.1233,7,1],[30.1322,18,1],[30.1411,11,1],[30.15,4,1],[30.1588,15,1],[30.1676,8,1],[30.1764,1,1],[30.1851,12,1],[30.1938,5,1],[30.2025,16,1],[30.2111,9,1],[30.2197,2,1],[30.2282,13,1],[30.2367,6,1],[30.2452,17,1],[30.2536,10,1],[30.262,3,1],[30.2703,14,1],[30.2786,7,1],[30.2869,18,1],[30.2951,11,1],[30.3033,4,1],[30.3114,15,1],[30.3195,8,1],[30.3275,1,1],[30.3356,12,1],[30.3435,5,1],[30.3514,16,1],[30.3593,9,1],[30.3672,2,1],[30.3749,13,1],[30.3827,6,1],[30.3904,17,1],[30.3981,10,1],[30.4057,3,1],[30.4133,14,1],[30.4208,7,1],[30.4283,18,1],[30.4358,11,1],[30.4432,4,1],[30.4505,15,1],[30.4579,8,1],[30.4651,1,1],[30.4724,12,1],[30.4796,5,1],[30.4867,16,1],[30.4939,9,1],[30.5009,2,1],[30.508,13,1],[30.515,6,1],[30.5219,17,1],[30.5289,10,1],[30.5357,3,1],[30.5426,14,1],[30.5494,7,1],[30.5561,18,1],[30.5629,11,1],[30.5696,4,1],[30.5762,15,1],[30.5828,8,1],[30.5894,1,1],[30.5959,12,1],[30.6024,5,1],[30.6089,16,1],[30.6153,9,1],[30.6217,2,1],[30.6281,13,1],[30.6344,6,1],[30.6407,17,1],[30.6469,10,1],[30.6532,3,1],[30.6594,14,1],[30.6655,7,1],[30.6716,18,1],[30.6777,11,1],[30.6838,4,1],[30.6898,15,1],[30.6958,8,1],[30.7017,1,1],[30.7077,12,1],[30.7136,5,1],[30.7194,16,1],[30.7253,9,1],[30.7311,2,1],[30.7369,13,1],[30.7426,6,1],[30.7483,17,1],[30.754,10,1],[30.7597,3,1],[30.7653,14,1],[30.7709,7,1],[30.7765,18,1],[30.7821,11,1],[30.7876,4,1],[30.7931,15,1],[30.7985,8,1],[30.804,1,1],[30.8094,12,1],[30.8148,5,1],[30.8202,16,1],[30.8255,9,1],[30.8308,2,1],[30.8361,13,1],[30.8414,6,1],[30.8466,17,1],[30.8518,10,1],[30.857,3,1],[30.8622,14,1],[30.8674,7,1],[30.8725,18,1],[30.8776,11,1],[30.8827,4,1],[30.8877,15,1],[30.8928,8,1],[30.8978,1,1],[30.9028,12,1],[30.9077,5,1],[30.9127,16,1],[30.9176,9,1],[30.9225,2,1],[30.9274,13,1],[30.9323,6,1],[30.9371,17,1],[30.942,10,1],[30.9468,3,1],[30.9516,14,1],[30.9563,7,1],[30.9611,18,1],[30.9658,11,1],[30.9705,4,1],[30.9752,15,1],[30.9799,8,1],[30.9845,1,1],[30.9892,12,1],[30.9938,5,1],[30.9984,16,1],[31.003,9,1],[31.0076,2,1],[31.0121,13,1],[31.0167,6,1],[31.0212,17,1],[31.0257,10,1],[31.0302,3,1],[31.0346,14,1],[31.0391,7,1],[31.0435,18,1],[31.0479,11,1],[31.0523,4,1],[31.0567,15,1],[31.0611,8,1],[31.0654,1,1],[31.0698,12,1],[31.0741,5,1],[31.0784,16,1],[31.0827,9,1],[31.087,2,1],[31.0913,13,1],[31.0955,6,1],[31.0998,17,1],[31.104,10,1],[31.1082,3,1],[31.1124,14,1],[31.1166,7,1],[31.1208,18,1],[31.1249,11,1],[31.1291,4,1],[31.1332,15,1],[31.1373,8,1],[31.1414,1,1],[31.1455,12,1],[31.1496,5,1],[31.1537,16,1],[31.1577,9,1],[31.1617,2,1],[31.1658,13,1],[31.1698,6,1],[31.1738,17,1],[31.1778,10,1],[31.1818,3,1],[31.1857,14,1],[31.1897,7,1],[31.1936,18,1],[31.1976,11,1],[31.2015,4,1],[31.2054,15,1],[31.2093,8,1],[31.2132,1,1],[31.2171,12,1],[31.2209,5,1],[31.2248,16,1],[31.2286,9,1],[31.2325,2,1],[31.2363,13,1],[31.2401,6,1],[31.2439,17,1],[31.2477,10,1],[31.2515,3,1],[31.2553,14,1],[31.259,7,1],[31.2628,18,1],[31.2665,11,1],[31.2703,4,1],[31.274,15,1],[31.2777,8,1],[31.2814,1,1],[31.2851,12,1],[31.2888,5,1],[31.2925,16,1],[31.2961,9,1],[31.2998,2,1],[31.3035,13,1],[31.3071,6,1],[31.3107,17,1],[31.3143,10,1],[31.318,3,1],[31.3216,14,1],[31.3252,7,1],[31.3288,18,1],[31.3323,11,1],[31.3359,4,1],[31.3395,15,1],[31.343,8,1],[31.3466,1,1],[31.3501,12,1],[31.3536,5,1],[31.3572,16,1],[31.3607,9,1],[31.3642,2,1],[31.3677,13,1],[31.3712,6,1],[31.3746,17,1],[31.3781,10,1],[31.3816,3,1],[31.3851,14,1],[31.3885,7,1],[31.3919,18,1],[31.3954,11,1],[31.3988,4,1],[31.4022,15,1],[31.4057,8,1],[31.4091,1,1],[31.4125,12,1],[31.4159,5,1],[31.4192,16,1],[31.4226,9,1],[31.426,2,1],[31.4294,13,1],[31.4327,6,1],[31.4361,17,1],[31.4394,10,1],[31.4428,3,1],[31.4461,14,1],[31.4494,7,1],[31.4527,18,1],[31.4561,11,1],[31.4594,4,1],[31.4627,15,1],[31.466,8,1],[31.4692,1,1],[31.4725,12,1],[31.4758,5,1],[31.4791,16,1],[31.4823,9,1],[31.4856,2,1],[31.4888,13,1],[31.4921,6,1],[31.4953,17,1],[31.4986,10,1],[31.5018,3,1],[31.505,14,1],[31.5082,7,1],[31.5114,18,1],[31.5146,11,1],[31.5178,4,1],[31.521,15,1],[31.5242,8,1],[31.5274,1,1],[31.5306,12,1],[31.5338,5,1],[31.5369,16,1],[31.5401,9,1],[31.5432,2,1],[31.5464,13,1],[31.5495,6,1],[31.5527,17,1],[31.5558,10,1],[31.5589,3,1],[31.5621,14,1],[31.5652,7,1],[31.5683,18,1],[31.5714,11,1],[31.5745,4,1],[31.5776,15,1],[31.5807,8,1],[31.5838,1,1],[31.5869,12,1],[31.59,5,1],[31.593,16,1],[31.5961,9,1],[31.5992,2,1],[31.6022,13,1],[31.6053,6,1],[31.6084,17,1],[31.6114,10,1],[31.6144,3,1],[31.6175,14,1],[31.6205,7,1],[31.6235,18,1],[31.6266,11,1],[31.6296,4,1],[31.6326,15,1],[31.6356,8,1],[31.6386,1,1],[31.6416,12,1],[31.6446,5,1],[31.6476,16,1],[31.6506,9,1],[31.6536,2,1],[31.6566,13,1],[31.6596,6,1],[31.6625,17,1],[31.6655,10,1],[31.6685,3,1],[31.6714,14,1],[31.6744,7,1],[31.6774,18,1],[31.6803,11,1],[31.6833,4,1],[31.6862,15,1],[31.6891,8,1],[31.6921,1,1],[31.695,12,1],[31.6979,5,1],[31.7009,16,1],[31.7038,9,1],[31.7067,2,1],[31.7096,13,1],[31.7125,6,1],[31.7154,17,1],[31.7183,10,1],[31.7212,3,1],[31.7241,14,1],[31.727,7,1],[31.7299,18,1],[31.7328,11,1],[31.7357,4,1],[31.7385,15,1],[31.7414,8,1],[31.7443,1,1],[31.7472,12,1],[31.75,5,1],[31.7529,16,1],[31.7557,9,1],[31.7586,2,1],[31.7615,13,1],[31.7643,6,1],[31.7671,17,1],[31.77,10,1],[31.7728,3,1],[31.7757,14,1],[31.7785,7,1],[31.7813,18,1],[31.7842,11,1],[31.787,4,1],[31.7898,15,1],[31.7926,8,1],[31.7954,1,1],[31.7982,12,1],[31.8011,5,1],[31.8039,16,1],[31.8067,9,1],[31.8095,2,1],[31.8123,13,1],[31.8151,6,1],[31.8178,17,1],[31.8206,10,1],[31.8234,3,1],[31.8262,14,1],[31.829,7,1],[31.8318,18,1],[31.8345,11,1],[31.8373,4,1],[31.8401,15,1],[31.8428,8,1],[31.8456,1,1],[31.8484,12,1],[31.8511,5,1],[31.8539,16,1],[31.8566,9,1],[31.8594,2,1],[31.8621,13,1],[31.8649,6,1],[31.8676,17,1],[31.8704,10,1],[31.8731,3,1],[31.8758,14,1],[31.8786,7,1],[31.8813,18,1],[31.884,11,1],[31.8868,4,1],[31.8895,15,1],[31.8922,8,1],[31.8949,1,1],[31.8976,12,1],[31.9004,5,1],[31.9031,16,1],[31.9058,9,1],[31.9085,2,1],[31.9112,13,1],[31.9139,6,1],[31.9166,17,1],[31.9193,10,1],[31.922,3,1],[31.9247,14,1],[31.9274,7,1],[31.9301,18,1],[31.9328,11,1],[31.9355,4,1],[31.9381,15,1],[31.9408,8,1],[31.9435,1,1],[31.9462,12,1],[31.9489,5,1],[31.9515,16,1],[31.9542,9,1],[31.9569,2,1],[31.9595,13,1],[31.9622,6,1],[31.9649,17,1],[31.9675,10,1],[31.9702,3,1],[31.9729,14,1],[31.9755,7,1],[31.9782,18,1],[31.9808,11,1],[31.9835,4,1],[31.9861,15,1],[31.9888,8,1],[31.9914,1,1],[31.9941,12,1],[31.9967,5,1],[31.9993,16,1],[32.002,9,1],[32.0046,2,1],[32.0072,13,1],[32.0099,6,1],[32.0125,17,1],[32.0151,10,1],[32.0178,3,1],[32.0204,14,1],[32.023,7,1],[32.0256,18,1],[32.0283,11,1],[32.0309,4,1],[32.0335,15,1],[32.0361,8,1],[32.0387,1,1],[32.0413,12,1],[32.044,5,1],[32.0466,16,1],[32.0492,9,1],[32.0518,2,1],[32.0544,13,1],[32.057,6,1],[32.0596,17,1],[32.0622,10,1],[32.0648,3,1],[32.0674,14,1],[32.07,7,1],[32.0726,18,1],[32.0752,11,1],[32.0778,4,1],[32.0804,15,1],[32.0829,8,1],[32.0855,1,1],[32.0881,12,1],[32.0907,5,1],[32.0933,16,1],[32.0959,9,1],[32.0985,2,1],[32.101,13,1],[32.1036,6,1],[32.1062,17,1],[32.1088,10,1],[32.1113,3,1],[32.1139,14,1],[32.1165,7,1],[32.1191,18,1],[32.1216,11,1],[32.1242,4,1],[32.1268,15,1],[32.1293,8,1],[32.1319,1,1],[32.1345,12,1],[32.137,5,1],[32.1396,16,1],[32.1421,9,1],[32.1447,2,1],[32.1473,13,1],[32.1498,6,1],[32.1524,17,1],[32.1549,10,1],[32.1575,3,1],[32.16,14,1],[32.1626,7,1],[32.1651,18,1],[32.1677,11,1],[32.1702,4,1],[32.1728,15,1],[32.1753,8,1],[32.1779,1,1],[32.1804,12,1],[32.183,5,1],[32.1855,16,1],[32.188,9,1],[32.1906,2,1],[32.1931,13,1],[32.1957,6,1],[32.1982,17,1],[32.2007,10,1],[32.2033,3,1],[32.2058,14,1],[32.2083,7,1],[32.2109,18,1],[32.2134,11,1],[32.2159,4,1],[32.2185,15,1],[32.221,8,1],[32.2235,1,1],[32.226,12,1],[32.2286,5,1],[32.2311,16,1],[32.2336,9,1],[32.2361,2,1],[32.2387,13,1],[32.2412,6,1],[32.2437,17,1],[32.2462,10,1],[32.2487,3,1],[32.2513,14,1],[32.2538,7,1],[32.2563,18,1],[32.2588,11,1],[32.2613,4,1],[32.2638,15,1],[32.2664,8,1],[32.2689,1,1],[32.2714,12,1],[32.2739,5,1],[32.2764,16,1],[32.2789,9,1],[32.2814,2,1],[32.2839,13,1],[32.2864,6,1],[32.289,17,1],[32.2915,10,1],[32.294,3,1],[32.2965,14,1],[32.299,7,1],[32.3015,18,1],[32.304,11,1],[32.3065,4,1],[32.309,15,1],[32.3115,8,1],[32.314,1,1],[32.3165,12,1],[32.319,5,1],[32.3215,16,1],[32.324,9,1],[32.3265,2,1],[32.329,13,1],[32.3315,6,1],[32.334,17,1],[32.3365,10,1],[32.339,3,1],[32.3415,14,1],[32.344,7,1],[32.3465,18,1],[32.349,11,1],[32.3515,4,1],[32.3539,15,1],[32.3564,8,1],[32.3589,1,1],[32.3614,12,1],[32.3639,5,1],[32.3664,16,1],[32.3689,9,1],[32.3714,2,1],[32.3739,13,1],[32.3764,6,1],[32.3789,17,1],[32.3813,10,1],[32.3838,3,1],[32.3863,14,1],[32.3888,7,1],[32.3913,18,1],[32.3938,11,1],[32.3963,4,1],[32.3987,15,1],[32.4012,8,1],[32.4037,1,1],[32.4062,12,1],[32.4087,5,1],[32.4112,16,1],[32.4137,9,1],[32.4161,2,1],[32.4186,13,1],[32.4211,6,1],[32.4236,17,1],[32.4261,10,1],[32.4285,3,1],[32.431,14,1],[32.4335,7,1],[32.436,18,1],[32.4385,11,1],[32.4409,4,1],[32.4434,15,1],[32.4459,8,1],[32.4484,1,1],[32.4509,12,1],[32.4533,5,1],[32.4558,16,1],[32.4583,9,1],[32.4608,2,1],[32.4632,13,1],[32.4657,6,1],[32.4682,17,1],[32.4707,10,1],[32.4732,3,1],[32.4756,14,1],[32.4781,7,1],[32.4806,18,1],[32.4831,11,1],[32.4855,4,1],[32.488,15,1],[32.4905,8,1],[32.493,1,1],[32.4954,12,1],[32.4979,5,1],[32.5004,16,1],[32.5029,9,1],[32.5053,2,1],[32.5078,13,1],[32.5103,6,1],[32.5127,17,1],[32.5152,10,1],[32.5177,3,1],[32.5202,14,1],[32.5226,7,1],[32.5251,18,1],[32.5276,11,1],[32.5301,4,1],[32.5325,15,1],[32.535,8,1],[32.5375,1,1],[32.5399,12,1],[32.5424,5,1],[32.5449,16,1],[32.5474,9,1],[32.5498,2,1],[32.5523,13,1],[32.5548,6,1],[32.5572,17,1],[32.5597,10,1],[32.5622,3,1],[32.5647,14,1],[32.5671,7,1],[32.5696,18,1],[32.5721,11,1],[32.5745,4,1],[32.577,15,1],[32.5795,8,1],[32.5819,1,1],[32.5844,12,1],[32.5869,5,1],[32.5894,16,1],[32.5918,9,1],[32.5943,2,1],[32.5968,13,1],[32.5992,6,1],[32.6017,17,1],[32.6042,10,1],[32.6066,3,1],[32.6091,14,1],[32.6116,7,1],[32.6141,18,1],[32.6165,11,1],[32.619,4,1],[32.6215,15,1],[32.6239,8,1],[32.6264,1,1],[32.6289,12,1],[32.6313,5,1],[32.6338,16,1],[32.6363,9,1],[32.6388,2,1],[32.6412,13,1],[32.6437,6,1],[32.6462,17,1],[32.6486,10,1],[32.6511,3,1],[32.6536,14,1],[32.656,7,1],[32.6585,18,1],[32.661,11,1],[32.6634,4,1],[32.6659,15,1],[32.6684,8,1],[32.6709,1,1],[32.6733,12,1],[32.6758,5,1],[32.6783,16,1],[32.6807,9,1],[32.6832,2,1],[32.6857,13,1],[32.6881,6,1],[32.6906,17,1],[32.6931,10,1],[32.6955,3,1],[32.698,14,1],[32.7005,7,1],[32.7029,18,1],[32.7054,11,1],[32.7079,4,1],[32.7104,15,1],[32.7128,8,1],[32.7153,1,1],[32.7178,12,1],[32.7202,5,1],[32.7227,16,1],[32.7252,9,1],[32.7276,2,1],[32.7301,13,1],[32.7326,6,1],[32.735,17,1],[32.7375,10,1],[32.74,3,1],[32.7425,14,1],[32.7449,7,1],[32.7474,18,1],[32.7499,11,1],[32.7523,4,1],[32.7548,15,1],[32.7573,8,1],[32.7597,1,1],[32.7622,12,1],[32.7647,5,1],[32.7671,16,1],[32.7696,9,1],[32.7721,2,1],[32.7746,13,1],[32.777,6,1],[32.7795,17,1],[32.782,10,1],[32.7844,3,1],[32.7869,14,1],[32.7894,7,1],[32.7918,18,1],[32.7943,11,1],[32.7968,4,1],[32.7992,15,1],[32.8017,8,1],[32.8042,1,1],[32.8067,12,1],[32.8091,5,1],[32.8116,16,1],[32.8141,9,1],[32.8165,2,1],[32.819,13,1],[32.8215,6,1],[32.8239,17,1],[32.8264,10,1],[32.8289,3,1],[32.8313,14,1],[32.8338,7,1],[32.8363,18,1],[32.8388,11,1],[32.8412,4,1],[32.8437,15,1],[32.8462,8,1],[32.8486,1,1],[32.8511,12,1],[32.8536,5,1],[32.856,16,1],[32.8585,9,1],[32.861,2,1],[32.8634,13,1],[32.8659,6,1],[32.8684,17,1],[32.8709,10,1],[32.8733,3,1],[32.8758,14,1],[32.8783,7,1],[32.8807,18,1],[32.8832,11,1],[32.8857,4,1],[32.8881,15,1],[32.8906,8,1],[32.8931,1,1],[32.8955,12,1],[32.898,5,1],[32.9005,16,1],[32.9029,9,1],[32.9054,2,1],[32.9079,13,1],[32.9104,6,1],[32.9128,17,1],[32.9153,10,1],[32.9178,3,1],[32.9202,14,1],[32.9227,7,1],[32.9252,18,1],[32.9276,11,1],[32.9301,4,1],[32.9326,15,1],[32.935,8,1],[32.9375,1,1],[32.94,12,1],[32.9425,5,1],[32.9449,16,1],[32.9474,9,1],[32.9499,2,1],[32.9523,13,1],[32.9548,6,1],[32.9573,17,1],[32.9597,10,1],[32.9622,3,1],[32.9647,14,1],[32.9671,7,1],[32.9696,18,1],[32.9721,11,1],[32.9746,4,1],[32.977,15,1],[32.9795,8,1],[32.982,1,1],[32.9844,12,1],[32.9869,5,1],[32.9894,16,1],[32.9918,9,1],[32.9943,2,1],[32.9968,13,1],[32.9992,6,1],[33.0017,17,1],[33.0042,10,1],[33.0067,3,1],[33.0091,14,1],[33.0116,7,1],[33.0141,18,1],[33.0165,11,1],[33.019,4,1],[33.0215,15,1],[33.0239,8,1],[33.0264,1,1],[33.0289,12,1],[33.0313,5,1],[33.0338,16,1],[33.0363,9,1],[33.0388,2,1],[33.0412,13,1],[33.0437,6,1],[33.0462,17,1],[33.0486,10,1],[33.0511,3,1],[33.0536,14,1],[33.056,7,1],[33.0585,18,1],[33.061,11,1],[33.0634,4,1],[33.0659,15,1],[33.0684,8,1],[33.0709,1,1],[33.0733,12,1],[33.0758,5,1],[33.0783,16,1],[33.0807,9,1],[33.0832,2,1],[33.0857,13,1],[33.0881,6,1],[33.0906,17,1],[33.0931,10,1],[33.0955,3,1],[33.098,14,1],[33.1005,7,1],[33.1029,18,1],[33.1054,11,1],[33.1079,4,1],[33.1104,15,1],[33.1128,8,1],[33.1153,1,1],[33.1178,12,1],[33.1202,5,1],[33.1227,16,1],[33.1252,9,1],[33.1276,2,1],[33.1301,13,1],[33.1326,6,1],[33.135,17,1],[33.1375,10,1],[33.14,3,1],[33.1425,14,1],[33.1449,7,1],[33.1474,18,1],[33.1499,11,1],[33.1523,4,1],[33.1548,15,1],[33.1573,8,1],[33.1597,1,1],[33.1622,12,1],[33.1647,5,1],[33.1671,16,1],[33.1696,9,1],[33.1721,2,1],[33.1746,13,1],[33.177,6,1],[33.1795,17,1],[33.182,10,1],[33.1844,3,1],[33.1869,14,1],[33.1894,7,1],[33.1918,18,1],[33.1943,11,1],[33.1968,4,1],[33.1992,15,1],[33.2017,8,1],[33.2042,1,1],[33.2067,12,1],[33.2091,5,1],[33.2116,16,1],[33.2141,9,1],[33.2165,2,1],[33.219,13,1],[33.2215,6,1],[33.2239,17,1],[33.2264,10,1],[33.2289,3,1],[33.2313,14,1],[33.2338,7,1],[33.2363,18,1],[33.2388,11,1],[33.2412,4,1],[33.2437,15,1],[33.2462,8,1],[33.2486,1,1],[33.2511,12,1],[33.2536,5,1],[33.256,16,1],[33.2585,9,1],[33.261,2,1],[33.2634,13,1],[33.2659,6,1],[33.2684,17,1],[33.2709,10,1],[33.2733,3,1],[33.2758,14,1],[33.2783,7,1],[33.2807,18,1],[33.2832,11,1],[33.2857,4,1],[33.2881,15,1],[33.2906,8,1],[33.2931,1,1],[33.2955,12,1],[33.298,5,1],[33.3005,16,1],[33.3029,9,1],[33.3054,2,1],[33.3079,13,1],[33.3104,6,1],[33.3128,17,1],[33.3153,10,1],[33.3178,3,1],[33.3202,14,1],[33.3227,7,1],[33.3252,18,1],[33.3276,11,1],[33.3301,4,1],[33.3326,15,1],[33.335,8,1],[33.3375,1,1],[33.34,12,1],[33.3425,5,1],[33.3449,16,1],[33.3474,9,1],[33.3499,2,1],[33.3523,13,1],[33.3548,6,1],[33.3573,17,1],[33.3597,10,1],[33.3622,3,1],[33.3647,14,1],[33.3671,7,1],[33.3696,18,1],[33.3721,11,1],[33.3746,4,1],[33.377,15,1],[33.3795,8,1],[33.382,1,1],[33.3844,12,1],[33.3869,5,1],[33.3894,16,1],[33.3918,9,1],[33.3943,2,1],[33.3968,13,1],[33.3992,6,1],[33.4017,17,1],[33.4042,10,1],[33.4067,3,1],[33.4091,14,1],[33.4116,7,1],[33.4141,18,1],[33.4165,11,1],[33.419,4,1],[33.4215,15,1],[33.4239,8,1],[33.4264,1,1],[33.4289,12,1],[33.4313,5,1],[33.4338,16,1],[33.4363,9,1],[33.4388,2,1],[33.4412,13,1],[33.4437,6,1],[33.4462,17,1],[33.4486,10,1],[33.4511,3,1],[33.4536,14,1],[33.456,7,1],[33.4585,18,1],[33.461,11,1],[33.4634,4,1],[33.4659,15,1],[33.4684,8,1],[33.4709,1,1],[33.4733,12,1],[33.4758,5,1],[33.4783,16,1],[33.4807,9,1],[33.4832,2,1],[33.4857,13,1],[33.4881,6,1],[33.4906,17,1],[33.4931,10,1],[33.4955,3,1],[33.498,14,1],[33.5005,7,1],[33.5029,18,1],[33.5054,11,1],[33.5079,4,1],[33.5104,15,1],[33.5128,8,1],[33.5153,1,1],[33.5178,12,1],[33.5202,5,1],[33.5227,16,1],[33.5252,9,1],[33.5276,2,1],[33.5301,13,1],[33.5326,6,1],[33.535,17,1],[33.5375,10,1],[33.54,3,1],[33.5425,14,1],[33.5449,7,1],[33.5474,18,1],[33.5499,11,1],[33.5523,4,1],[33.5548,15,1],[33.5573,8,1],[33.5597,1,1],[33.5622,12,1],[33.5647,5,1],[33.5671,16,1],[33.5696,9,1],[33.5721,2,1],[33.5746,13,1],[33.577,6,1],[33.5795,17,1],[33.582,10,1],[33.5844,3,1],[33.5869,14,1],[33.5894,7,1],[33.5918,18,1],[33.5943,11,1],[33.5968,4,1],[33.5992,15,1],[33.6017,8,1],[33.6042,1,1],[33.6067,12,1],[33.6091,5,1],[33.6116,16,1],[33.6141,9,1],[33.6165,2,1],[33.619,13,1],[33.6215,6,1],[33.6239,17,1],[33.6264,10,1],[33.6289,3,1],[33.6313,14,1],[33.6338,7,1],[33.6363,18,1],[33.6388,11,1],[33.6412,4,1],[33.6437,15,1],[33.6462,8,1],[33.6486,1,1],[33.6511,12,1],[33.6536,5,1],[33.656,16,1],[33.6585,9,1],[33.661,2,1],[33.6634,13,1],[33.6659,6,1],[33.6684,17,1],[33.6709,10,1],[33.6733,3,1],[33.6758,14,1],[33.6783,7,1],[33.6807,18,1],[33.6832,11,1],[33.6857,4,1],[33.6881,15,1],[33.6906,8,1],[33.6931,1,1],[33.6955,12,1],[33.698,5,1],[33.7005,16,1],[33.7029,9,1],[33.7054,2,1],[33.7079,13,1],[33.7104,6,1],[33.7128,17,1],[33.7153,10,1],[33.7178,3,1],[33.7202,14,1],[33.7227,7,1],[33.7252,18,1],[33.7276,11,1],[33.7301,4,1],[33.7326,15,1],[33.735,8,1],[33.7375,1,1],[33.74,12,1],[33.7425,5,1],[33.7449,16,1],[33.7474,9,1],[33.7499,2,1],[33.7523,13,1],[33.7548,6,1],[33.7573,17,1],[33.7597,10,1],[33.7622,3,1],[33.7647,14,1],[33.7671,7,1],[33.7696,18,1],[33.7721,11,1],[33.7746,4,1],[33.777,15,1],[33.7795,8,1],[33.782,1,1],[33.7844,12,1],[33.7869,5,1],[33.7894,16,1],[33.7918,9,1],[33.7943,2,1],[33.7968,13,1],[33.7992,6,1],[33.8017,17,1],[33.8042,10,1],[33.8067,3,1],[33.8091,14,1],[33.8116,7,1],[33.8141,18,1],[33.8165,11,1],[33.819,4,1],[33.8215,15,1],[33.8239,8,1],[33.8264,1,1],[33.8289,12,1],[33.8313,5,1],[33.8338,16,1],[33.8363,9,1],[33.8388,2,1],[33.8412,13,1],[33.8437,6,1],[33.8462,17,1],[33.8486,10,1],[33.8511,3,1],[33.8536,14,1],[33.856,7,1],[33.8585,18,1],[33.861,11,1],[33.8634,4,1],[33.8659,15,1],[33.8684,8,1],[33.8709,1,1],[33.8733,12,1],[33.8758,5,1],[33.8783,16,1],[33.8807,9,1],[33.8832,2,1],[33.8857,13,1],[33.8881,6,1],[33.8906,17,1],[33.8931,10,1],[33.8955,3,1],[33.898,14,1],[33.9005,7,1],[33.9029,18,1],[33.9054,11,1],[33.9079,4,1],[33.9104,15,1],[33.9128,8,1],[33.9153,1,1],[33.9178,12,1],[33.9202,5,1],[33.9227,16,1],[33.9252,9,1],[33.9276,2,1],[33.9301,13,1],[33.9326,6,1],[33.935,17,1],[33.9375,10,1],[33.94,3,1],[33.9425,14,1],[33.9449,7,1],[33.9474,18,1],[33.9499,11,1],[33.9523,4,1],[33.9548,15,1],[33.9573,8,1],[33.9597,1,1],[33.9622,12,1],[33.9647,5,1],[33.9671,16,1],[33.9696,9,1],[33.9721,2,1],[33.9746,13,1],[33.977,6,1],[33.9795,17,1],[33.982,10,1],[33.9844,3,1],[33.9869,14,1],[33.9894,7,1],[33.9918,18,1],[33.9943,11,1],[33.9968,4,1],[33.9992,15,1],[34.0017,8,1],[34.0042,1,1],[34.0067,12,1],[34.0091,5,1],[34.0116,16,1],[34.0141,9,1],[34.0165,2,1],[34.019,13,1],[34.0215,6,1],[34.0239,17,1],[34.0264,10,1],[34.0289,3,1],[34.0313,14,1],[34.0338,7,1],[34.0363,18,1],[34.0388,11,1],[34.0412,4,1],[34.0437,15,1],[34.0462,8,1],[34.0486,1,1],[34.0511,12,1],[34.0536,5,1],[34.056,16,1],[34.0585,9,1],[34.061,2,1],[34.0634,13,1],[34.0659,6,1],[34.0684,17,1],[34.0709,10,1],[34.0733,3,1],[34.0758,14,1],[34.0783,7,1],[34.0807,18,1],[34.0832,11,1],[34.0857,4,1],[34.0881,15,1],[34.0906,8,1],[34.0931,1,1],[34.0955,12,1],[34.098,5,1],[34.1005,16,1],[34.1029,9,1],[34.1054,2,1],[34.1079,13,1],[34.1104,6,1],[34.1128,17,1],[34.1153,10,1],[34.1178,3,1],[34.1202,14,1],[34.1227,7,1],[34.1252,18,1],[34.1276,11,1],[34.1301,4,1],[34.1326,15,1],[34.135,8,1],[34.1375,1,1],[34.14,12,1],[34.1425,5,1],[34.1449,16,1],[34.1474,9,1],[34.1499,2,1],[34.1523,13,1],[34.1548,6,1],[34.1573,17,1],[34.1597,10,1],[34.1622,3,1],[34.1647,14,1],[34.1671,7,1],[34.1696,18,1],[34.1721,11,1],[34.1746,4,1],[34.177,15,1],[34.1795,8,1],[34.182,1,1],[34.1844,12,1],[34.1869,5,1],[34.1894,16,1],[34.1918,9,1],[34.1943,2,1],[34.1968,13,1],[34.1992,6,1],[34.2017,17,1],[34.2042,10,1],[34.2067,3,1],[34.2091,14,1],[34.2116,7,1],[34.2141,18,1],[34.2165,11,1],[34.219,4,1],[34.2215,15,1],[34.2239,8,1],[34.2264,1,1],[34.2289,12,1],[34.2313,5,1],[34.2338,16,1],[34.2363,9,1],[34.2388,2,1],[34.2412,13,1],[34.2437,6,1],[34.2462,17,1],[34.2486,10,1],[34.2511,3,1],[34.2536,14,1],[34.256,7,1],[34.2585,18,1],[34.261,11,1],[34.2634,4,1],[34.2659,15,1],[34.2684,8,1],[34.2709,1,1],[34.2733,12,1],[34.2758,5,1],[34.2783,16,1],[34.2807,9,1],[34.2832,2,1],[34.2857,13,1],[34.2881,6,1],[34.2906,17,1],[34.2931,10,1],[34.2955,3,1],[34.298,14,1],[34.3005,7,1],[34.3029,18,1],[34.3054,11,1],[34.3079,4,1],[34.3104,15,1],[34.3128,8,1],[34.3153,1,1],[34.3178,12,1],[34.3202,5,1],[34.3227,16,1],[34.3252,9,1],[34.3276,2,1],[34.3301,13,1],[34.3326,6,1],[34.335,17,1],[34.3375,10,1],[34.34,3,1],[34.3425,14,1],[34.3449,7,1],[34.3474,18,1],[34.3499,11,1],[34.3523,4,1],[34.3548,15,1],[34.3573,8,1],[34.3597,1,1],[34.3622,12,1],[34.3647,5,1],[34.3671,16,1],[34.3696,9,1],[34.3721,2,1],[34.3746,13,1],[34.377,6,1],[34.3795,17,1],[34.382,10,1],[34.3844,3,1],[34.3869,14,1],[34.3894,7,1],[34.3918,18,1],[34.3943,11,1],[34.3968,4,1],[34.3992,15,1],[34.4017,8,1],[34.4042,1,1],[34.4067,12,1],[34.4091,5,1],[34.4116,16,1],[34.4141,9,1],[34.4165,2,1],[34.419,13,1],[34.4215,6,1],[34.4239,17,1],[34.4264,10,1],[34.4289,3,1],[34.4313,14,1],[34.4338,7,1],[34.4363,18,1],[34.4388,11,1],[34.4412,4,1],[34.4437,15,1],[34.4462,8,1],[34.4486,1,1],[34.4511,12,1],[34.4536,5,1],[34.456,16,1],[34.4585,9,1],[34.461,2,1],[34.4634,13,1],[34.4659,6,1],[34.4684,17,1],[34.4709,10,1],[34.4733,3,1],[34.4758,14,1],[34.4783,7,1],[34.4807,18,1],[34.4832,11,1],[34.4857,4,1],[34.4881,15,1],[34.4906,8,1],[34.4931,1,1],[34.4955,12,1],[34.498,5,1],[34.5005,16,1],[34.5029,9,1],[34.5054,2,1],[34.5079,13,1],[34.5104,6,1],[34.5128,17,1],[34.5153,10,1],[34.5178,3,1],[34.5202,14,1],[34.5227,7,1],[34.5252,18,1],[34.5276,11,1],[34.5301,4,1],[34.5326,15,1],[34.535,8,1],[34.5375,1,1],[34.54,12,1],[34.5425,5,1],[34.5449,16,1],[34.5474,9,1],[34.5499,2,1],[34.5523,13,1],[34.5548,6,1],[34.5573,17,1],[34.5597,10,1],[34.5622,3,1],[34.5647,14,1],[34.5671,7,1],[34.5696,18,1],[34.5721,11,1],[34.5746,4,1],[34.577,15,1],[34.5795,8,1],[34.582,1,1],[34.5844,12,1],[34.5869,5,1],[34.5894,16,1],[34.5918,9,1],[34.5943,2,1],[34.5968,13,1],[34.5992,6,1],[34.6017,17,1],[34.6042,10,1],[34.6067,3,1],[34.6091,14,1],[34.6116,7,1],[34.6141,18,1],[34.6165,11,1],[34.619,4,1],[34.6215,15,1],[34.6239,8,1],[34.6264,1,1],[34.6289,12,1],[34.6313,5,1],[34.6338,16,1],[34.6363,9,1],[34.6388,2,1],[34.6412,13,1],[34.6437,6,1],[34.6462,17,1],[34.6486,10,1],[34.6511,3,1],[34.6536,14,1],[34.656,7,1],[34.6585,18,1],[34.661,11,1],[34.6634,4,1],[34.6659,15,1],[34.6684,8,1],[34.6709,1,1],[34.6733,12,1],[34.6758,5,1],[34.6783,16,1],[34.6807,9,1],[34.6832,2,1],[34.6857,13,1],[34.6881,6,1],[34.6906,17,1],[34.6931,10,1],[34.6955,3,1],[34.698,14,1],[34.7005,7,1],[34.7029,18,1],[34.7054,11,1],[34.7079,4,1],[34.7104,15,1],[34.7128,8,1],[34.7153,1,1],[34.7178,12,1],[34.7202,5,1],[34.7227,16,1],[34.7252,9,1],[34.7276,2,1],[34.7301,13,1],[34.7326,6,1],[34.735,17,1],[34.7375,10,1],[34.74,3,1],[34.7425,14,1],[34.7449,7,1],[34.7474,18,1],[34.7499,11,1],[34.7523,4,1],[34.7548,15,1],[34.7573,8,1],[34.7597,1,1],[34.7622,12,1],[34.7647,5,1],[34.7671,16,1],[34.7696,9,1],[34.7721,2,1],[34.7746,13,1],[34.777,6,1],[34.7795,17,1],[34.782,10,1],[34.7844,3,1],[34.7869,14,1],[34.7894,7,1],[34.7918,18,1],[34.7943,11,1],[34.7968,4,1],[34.7992,15,1],[34.8017,8,1],[34.8042,1,1],[34.8067,12,1],[34.8091,5,1],[34.8116,16,1],[34.8141,9,1],[34.8165,2,1],[34.819,13,1],[34.8215,6,1],[34.8239,17,1],[34.8264,10,1],[34.8289,3,1],[34.8313,14,1],[34.8338,7,1],[34.8363,18,1],[34.8388,11,1],[34.8412,4,1],[34.8437,15,1],[34.8462,8,1],[34.8486,1,1],[34.8511,12,1],[34.8536,5,1],[34.856,16,1],[34.8585,9,1],[34.861,2,1],[34.8634,13,1],[34.8659,6,1],[34.8684,17,1],[34.8709,10,1],[34.8733,3,1],[34.8758,14,1],[34.8783,7,1],[34.8807,18,1],[34.8832,11,1],[34.8857,4,1],[34.8881,15,1],[34.8906,8,1],[34.8931,1,1],[34.8955,12,1],[34.898,5,1],[34.9005,16,1],[34.9029,9,1],[34.9054,2,1],[34.9079,13,1],[34.9104,6,1],[34.9128,17,1],[34.9153,10,1],[34.9178,3,1],[34.9202,14,1],[34.9227,7,1],[34.9252,18,1],[34.9276,11,1],[34.9301,4,1],[34.9326,15,1],[34.935,8,1],[34.9375,1,1],[34.94,12,1],[34.9425,5,1],[34.9449,16,1],[34.9474,9,1],[34.9499,2,1],[34.9523,13,1],[34.9548,6,1],[34.9573,17,1],[34.9597,10,1],[34.9622,3,1],[34.9647,14,1],[34.9671,7,1],[34.9696,18,1],[34.9721,11,1],[34.9746,4,1],[34.977,15,1],[34.9795,8,1],[34.982,1,1],[34.9844,12,1],[34.9869,5,1],[34.9894,16,1],[34.9918,9,1],[34.9943,2,1],[34.9968,13,1],[34.9992,6,1],[35.0017,17,1],[35.0042,10,1],[35.0067,3,1],[35.0091,14,1],[35.0116,7,1],[35.0141,18,1],[35.0165,11,1],[35.019,4,1],[35.0215,15,1],[35.0239,8,1],[35.0264,1,1],[35.0289,12,1],[35.0313,5,1],[35.0338,16,1],[35.0363,9,1],[35.0388,2,1],[35.0412,13,1],[35.0437,6,1],[35.0462,17,1],[35.0486,10,1],[35.0511,3,1],[35.0536,14,1],[35.056,7,1],[35.0585,18,1],[35.061,11,1],[35.0634,4,1],[35.0659,15,1],[35.0684,8,1],[35.0709,1,1],[35.0733,12,1],[35.0758,5,1],[35.0783,16,1],[35.0807,9,1],[35.0832,2,1],[35.0857,13,1],[35.0881,6,1],[35.0906,17,1],[35.0931,10,1],[35.0955,3,1],[35.098,14,1],[35.1005,7,1],[35.1029,18,1],[35.1054,11,1],[35.1079,4,1],[35.1104,15,1],[35.1128,8,1],[35.1153,1,1],[35.1178,12,1],[35.1202,5,1],[35.1227,16,1],[35.1252,9,1],[35.1276,2,1],[35.1301,13,1],[35.1326,6,1],[35.135,17,1],[35.1375,10,1],[35.14,3,1],[35.1425,14,1],[35.1449,7,1],[35.1474,18,1],[35.1499,11,1],[35.1523,4,1],[35.1548,15,1],[35.1573,8,1],[35.1597,1,1],[35.1622,12,1],[35.1647,5,1],[35.1671,16,1],[35.1696,9,1],[35.1721,2,1],[35.1746,13,1],[35.177,6,1],[35.1795,17,1],[35.182,10,1],[35.1844,3,1],[35.1869,14,1],[35.1894,7,1],[35.1918,18,1],[35.1943,11,1],[35.1968,4,1],[35.1992,15,1],[35.2017,8,1],[35.2042,1,1],[35.2067,12,1],[35.2091,5,1],[35.2116,16,1],[35.2141,9,1],[35.2165,2,1],[35.219,13,1],[35.2215,6,1],[35.2239,17,1],[35.2264,10,1],[35.2289,3,1],[35.2313,14,1],[35.2338,7,1],[35.2363,18,1],[35.2388,11,1],[35.2412,4,1],[35.2437,15,1],[35.2462,8,1],[35.2486,1,1],[35.2511,12,1],[35.2536,5,1],[35.256,16,1],[35.2585,9,1],[35.261,2,1],[35.2634,13,1],[35.2659,6,1],[35.2684,17,1],[35.2709,10,1],[35.2733,3,1],[35.2758,14,1],[35.2783,7,1],[35.2807,18,1],[35.2832,11,1],[35.2857,4,1],[35.2881,15,1],[35.2906,8,1],[35.2931,1,1],[35.2955,12,1],[35.298,5,1],[35.3005,16,1],[35.3029,9,1],[35.3054,2,1],[35.3079,13,1],[35.3104,6,1],[35.3128,17,1],[35.3153,10,1],[35.3178,3,1],[35.3202,14,1],[35.3227,7,1],[35.3252,18,1],[35.3276,11,1],[35.3301,4,1],[35.3326,15,1],[35.335,8,1],[35.3375,1,1],[35.34,12,1],[35.3425,5,1],[35.3449,16,1],[35.3474,9,1],[35.3499,2,1],[35.3523,13,1],[35.3548,6,1],[35.3573,17,1],[35.3597,10,1],[35.3622,3,1],[35.3647,14,1],[35.3671,7,1],[35.3696,18,1],[35.3721,11,1],[35.3746,4,1],[35.377,15,1],[35.3795,8,1],[35.382,1,1],[35.3844,12,1],[35.3869,5,1],[35.3894,16,1],[35.3918,9,1],[35.3943,2,1],[35.3968,13,1],[35.3992,6,1],[35.4017,17,1],[35.4042,10,1],[35.4067,3,1],[35.4091,14,1],[35.4116,7,1],[35.4141,18,1],[35.4165,11,1],[35.419,4,1],[35.4215,15,1],[35.4239,8,1],[35.4264,1,1],[35.4289,12,1],[35.4313,5,1],[35.4338,16,1],[35.4363,9,1],[35.4388,2,1],[35.4412,13,1],[35.4437,6,1],[35.4462,17,1],[35.4486,10,1],[35.4511,3,1],[35.4536,14,1],[35.456,7,1],[35.4585,18,1],[35.461,11,1],[35.4634,4,1],[35.4659,15,1],[35.4684,8,1],[35.4709,1,1],[35.4733,12,1],[35.4758,5,1],[35.4783,16,1],[35.4807,9,1],[35.4832,2,1],[35.4857,13,1],[35.4881,6,1],[35.4906,17,1],[35.4931,10,1],[35.4955,3,1],[35.498,14,1],[35.5005,7,1],[35.5029,18,1],[35.5054,11,1],[35.5079,4,1],[35.5104,15,1],[35.5128,8,1],[35.5153,1,1],[35.5178,12,1],[35.5202,5,1],[35.5227,16,1],[35.5252,9,1],[35.5276,2,1],[35.5301,13,1],[35.5326,6,1],[35.535,17,1],[35.5375,10,1],[35.54,3,1],[35.5425,14,1],[35.5449,7,1],[35.5474,18,1],[35.5499,11,1],[35.5523,4,1],[35.5548,15,1],[35.5573,8,1],[35.5597,1,1],[35.5622,12,1],[35.5647,5,1],[35.5671,16,1],[35.5696,9,1],[35.5721,2,1],[35.5746,13,1],[35.577,6,1],[35.5795,17,1],[35.582,10,1],[35.5844,3,1],[35.5869,14,1],[35.5894,7,1],[35.5918,18,1],[35.5943,11,1],[35.5968,4,1],[35.5992,15,1],[35.6017,8,1],[35.6042,1,1],[35.6067,12,1],[35.6091,5,1],[35.6116,16,1],[35.6141,9,1],[35.6165,2,1],[35.619,13,1],[35.6215,6,1],[35.6239,17,1],[35.6264,10,1],[35.6289,3,1],[35.6313,14,1],[35.6338,7,1],[35.6363,18,1],[35.6388,11,1],[35.6412,4,1],[35.6437,15,1],[35.6462,8,1],[35.6486,1,1],[35.6511,12,1],[35.6536,5,1],[35.656,16,1],[35.6585,9,1],[35.661,2,1],[35.6634,13,1],[35.6659,6,1],[35.6684,17,1],[35.6709,10,1],[35.6733,3,1],[35.6758,14,1],[35.6783,7,1],[35.6807,18,1],[35.6832,11,1],[35.6857,4,1],[35.6881,15,1],[35.6906,8,1],[35.6931,1,1],[35.6955,12,1],[35.698,5,1],[35.7005,16,1],[35.703,9,1],[35.7054,2,1],[35.7079,13,1],[35.7104,6,1],[35.7128,17,1],[35.7153,10,1],[35.7178,3,1],[35.7202,14,1],[35.7227,7,1],[35.7252,18,1],[35.7277,11,1],[35.7301,4,1],[35.7326,15,1],[35.7351,8,1],[35.7375,1,1],[35.74,12,1],[35.7425,5,1],[35.745,16,1],[35.7474,9,1],[35.7499,2,1],[35.7524,13,1],[35.7548,6,1],[35.7573,17,1],[35.7598,10,1],[35.7623,3,1],[35.7647,14,1],[35.7672,7,1],[35.7697,18,1],[35.7721,11,1],[35.7746,4,1],[35.7771,15,1],[35.7796,8,1],[35.782,1,1],[35.7845,12,1],[35.787,5,1],[35.7895,16,1],[35.7919,9,1],[35.7944,2,1],[35.7969,13,1],[35.7993,6,1],[35.8018,17,1],[35.8043,10,1],[35.8068,3,1],[35.8092,14,1],[35.8117,7,1],[35.8142,18,1],[35.8167,11,1],[35.8191,4,1],[35.8216,15,1],[35.8241,8,1],[35.8266,1,1],[35.829,12,1],[35.8315,5,1],[35.834,16,1],[35.8365,9,1],[35.839,2,1],[35.8414,13,1],[35.8439,6,1],[35.8464,17,1],[35.8489,10,1],[35.8513,3,1],[35.8538,14,1],[35.8563,7,1],[35.8588,18,1],[35.8613,11,1],[35.8637,4,1],[35.8662,15,1],[35.8687,8,1],[35.8712,1,1],[35.8737,12,1],[35.8761,5,1],[35.8786,16,1],[35.8811,9,1],[35.8836,2,1],[35.8861,13,1],[35.8886,6,1],[35.891,17,1],[35.8935,10,1],[35.896,3,1],[35.8985,14,1],[35.901,7,1],[35.9035,18,1],[35.9059,11,1],[35.9084,4,1],[35.9109,15,1],[35.9134,8,1],[35.9159,1,1],[35.9184,12,1],[35.9209,5,1],[35.9234,16,1],[35.9258,9,1],[35.9283,2,1],[35.9308,13,1],[35.9333,6,1],[35.9358,17,1],[35.9383,10,1],[35.9408,3,1],[35.9433,14,1],[35.9458,7,1],[35.9483,18,1],[35.9508,11,1],[35.9533,4,1],[35.9557,15,1],[35.9582,8,1],[35.9607,1,1],[35.9632,12,1],[35.9657,5,1],[35.9682,16,1],[35.9707,9,1],[35.9732,2,1],[35.9757,13,1],[35.9782,6,1],[35.9807,17,1],[35.9832,10,1],[35.9857,3,1],[35.9882,14,1],[35.9907,7,1],[35.9932,18,1],[35.9957,11,1],[35.9982,4,1],[36.0007,15,1],[36.0032,8,1],[36.0058,1,1],[36.0083,12,1],[36.0108,5,1],[36.0133,16,1],[36.0158,9,1],[36.0183,2,1],[36.0208,13,1],[36.0233,6,1],[36.0258,17,1],[36.0283,10,1],[36.0309,3,1],[36.0334,14,1],[36.0359,7,1],[36.0384,18,1],[36.0409,11,1],[36.0434,4,1],[36.0459,15,1],[36.0485,8,1],[36.051,1,1],[36.0535,12,1],[36.056,5,1],[36.0585,16,1],[36.0611,9,1],[36.0636,2,1],[36.0661,13,1],[36.0686,6,1],[36.0712,17,1],[36.0737,10,1],[36.0762,3,1],[36.0787,14,1],[36.0813,7,1],[36.0838,18,1],[36.0863,11,1],[36.0889,4,1],[36.0914,15,1],[36.0939,8,1],[36.0965,1,1],[36.099,12,1],[36.1015,5,1],[36.1041,16,1],[36.1066,9,1],[36.1091,2,1],[36.1117,13,1],[36.1142,6,1],[36.1168,17,1],[36.1193,10,1],[36.1219,3,1],[36.1244,14,1],[36.1269,7,1],[36.1295,18,1],[36.132,11,1],[36.1346,4,1],[36.1371,15,1],[36.1397,8,1],[36.1422,1,1],[36.1448,12,1],[36.1473,5,1],[36.1499,16,1],[36.1525,9,1],[36.155,2,1],[36.1576,13,1],[36.1601,6,1],[36.1627,17,1],[36.1653,10,1],[36.1678,3,1],[36.1704,14,1],[36.173,7,1],[36.1755,18,1],[36.1781,11,1],[36.1807,4,1],[36.1832,15,1],[36.1858,8,1],[36.1884,1,1],[36.1909,12,1],[36.1935,5,1],[36.1961,16,1],[36.1987,9,1],[36.2013,2,1],[36.2038,13,1],[36.2064,6,1],[36.209,17,1],[36.2116,10,1],[36.2142,3,1],[36.2168,14,1],[36.2194,7,1],[36.2219,18,1],[36.2245,11,1],[36.2271,4,1],[36.2297,15,1],[36.2323,8,1],[36.2349,1,1],[36.2375,12,1],[36.2401,5,1],[36.2427,16,1],[36.2453,9,1],[36.2479,2,1],[36.2505,13,1],[36.2531,6,1],[36.2558,17,1],[36.2584,10,1],[36.261,3,1],[36.2636,14,1],[36.2662,7,1],[36.2688,18,1],[36.2715,11,1],[36.2741,4,1],[36.2767,15,1],[36.2793,8,1],[36.2819,1,1],[36.2846,12,1],[36.2872,5,1],[36.2898,16,1],[36.2925,9,1],[36.2951,2,1],[36.2977,13,1],[36.3004,6,1],[36.303,17,1],[36.3057,10,1],[36.3083,3,1],[36.3109,14,1],[36.3136,7,1],[36.3162,18,1],[36.3189,11,1],[36.3215,4,1],[36.3242,15,1],[36.3269,8,1],[36.3295,1,1],[36.3322,12,1],[36.3348,5,1],[36.3375,16,1],[36.3402,9,1],[36.3428,2,1],[36.3455,13,1],[36.3482,6,1],[36.3508,17,1],[36.3535,10,1],[36.3562,3,1],[36.3589,14,1],[36.3616,7,1],[36.3642,18,1],[36.3669,11,1],[36.3696,4,1],[36.3723,15,1],[36.375,8,1],[36.3777,1,1],[36.3804,12,1],[36.3831,5,1],[36.3858,16,1],[36.3885,9,1],[36.3912,2,1],[36.3939,13,1],[36.3966,6,1],[36.3993,17,1],[36.4021,10,1],[36.4048,3,1],[36.4075,14,1],[36.4102,7,1],[36.4129,18,1],[36.4157,11,1],[36.4184,4,1],[36.4211,15,1],[36.4239,8,1],[36.4266,1,1],[36.4293,12,1],[36.4321,5,1],[36.4348,16,1],[36.4376,9,1],[36.4403,2,1],[36.4431,13,1],[36.4458,6,1],[36.4486,17,1],[36.4513,10,1],[36.4541,3,1],[36.4569,14,1],[36.4596,7,1],[36.4624,18,1],[36.4652,11,1],[36.4679,4,1],[36.4707,15,1],[36.4735,8,1],[36.4763,1,1],[36.4791,12,1],[36.4818,5,1],[36.4846,16,1],[36.4874,9,1],[36.4902,2,1],[36.493,13,1],[36.4958,6,1],[36.4986,17,1],[36.5014,10,1],[36.5043,3,1],[36.5071,14,1],[36.5099,7,1],[36.5127,18,1],[36.5155,11,1],[36.5184,4,1],[36.5212,15,1],[36.524,8,1],[36.5269,1,1],[36.5297,12,1],[36.5325,5,1],[36.5354,16,1],[36.5382,9,1],[36.5411,2,1],[36.5439,13,1],[36.5468,6,1],[36.5497,17,1],[36.5525,10,1],[36.5554,3,1],[36.5583,14,1],[36.5611,7,1],[36.564,18,1],[36.5669,11,1],[36.5698,4,1],[36.5727,15,1],[36.5756,8,1],[36.5785,1,1],[36.5814,12,1],[36.5843,5,1],[36.5872,16,1],[36.5901,9,1],[36.593,2,1],[36.5959,13,1],[36.5988,6,1],[36.6017,17,1],[36.6047,10,1],[36.6076,3,1],[36.6105,14,1],[36.6135,7,1],[36.6164,18,1],[36.6194,11,1],[36.6223,4,1],[36.6253,15,1],[36.6282,8,1],[36.6312,1,1],[36.6342,12,1],[36.6371,5,1],[36.6401,16,1],[36.6431,9,1],[36.6461,2,1],[36.6491,13,1],[36.652,6,1],[36.655,17,1],[36.658,10,1],[36.661,3,1],[36.664,14,1],[36.6671,7,1],[36.6701,18,1],[36.6731,11,1],[36.6761,4,1],[36.6791,15,1],[36.6822,8,1],[36.6852,1,1],[36.6883,12,1],[36.6913,5,1],[36.6944,16,1],[36.6974,9,1],[36.7005,2,1],[36.7035,13,1],[36.7066,6,1],[36.7097,17,1],[36.7128,10,1],[36.7159,3,1],[36.7189,14,1],[36.722,7,1],[36.7251,18,1],[36.7282,11,1],[36.7314,4,1],[36.7345,15,1],[36.7376,8,1],[36.7407,1,1],[36.7438,12,1],[36.747,5,1],[36.7501,16,1],[36.7533,9,1],[36.7564,2,1],[36.7596,13,1],[36.7627,6,1],[36.7659,17,1],[36.7691,10,1],[36.7722,3,1],[36.7754,14,1],[36.7786,7,1],[36.7818,18,1],[36.785,11,1],[36.7882,4,1],[36.7914,15,1],[36.7946,8,1],[36.7978,1,1],[36.8011,12,1],[36.8043,5,1],[36.8075,16,1],[36.8108,9,1],[36.814,2,1],[36.8173,13,1],[36.8206,6,1],[36.8238,17,1],[36.8271,10,1],[36.8304,3,1],[36.8337,14,1],[36.837,7,1],[36.8403,18,1],[36.8436,11,1],[36.8469,4,1],[36.8502,15,1],[36.8535,8,1],[36.8569,1,1],[36.8602,12,1],[36.8636,5,1],[36.8669,16,1],[36.8703,9,1],[36.8736,2,1],[36.877,13,1],[36.8804,6,1],[36.8838,17,1],[36.8872,10,1],[36.8906,3,1],[36.894,14,1],[36.8974,7,1],[36.9008,18,1],[36.9042,11,1],[36.9077,4,1],[36.9111,15,1],[36.9146,8,1],[36.918,1,1],[36.9215,12,1],[36.925,5,1],[36.9284,16,1],[36.9319,9,1],[36.9354,2,1],[36.9389,13,1],[36.9425,6,1],[36.946,17,1],[36.9495,10,1],[36.953,3,1],[36.9566,14,1],[36.9601,7,1],[36.9637,18,1],[36.9673,11,1],[36.9709,4,1],[36.9744,15,1],[36.978,8,1],[36.9816,1,1],[36.9853,12,1],[36.9889,5,1],[36.9925,16,1],[36.9961,9,1],[36.9998,2,1],[37.0035,13,1],[37.0071,6,1],[37.0108,17,1],[37.0145,10,1],[37.0182,3,1],[37.0219,14,1],[37.0256,7,1],[37.0293,18,1],[37.033,11,1],[37.0368,4,1],[37.0405,15,1],[37.0443,8,1],[37.0481,1,1],[37.0519,12,1],[37.0557,5,1],[37.0595,16,1],[37.0633,9,1],[37.0671,2,1],[37.0709,13,1],[37.0748,6,1],[37.0786,17,1],[37.0825,10,1],[37.0864,3,1],[37.0903,14,1],[37.0942,7,1],[37.0981,18,1],[37.102,11,1],[37.1059,4,1],[37.1099,15,1],[37.1138,8,1],[37.1178,1,1],[37.1218,12,1],[37.1258,5,1],[37.1298,16,1],[37.1338,9,1],[37.1378,2,1],[37.1418,13,1],[37.1459,6,1],[37.15,17,1],[37.154,10,1],[37.1581,3,1],[37.1622,14,1],[37.1664,7,1],[37.1705,18,1],[37.1746,11,1],[37.1788,4,1],[37.1829,15,1],[37.1871,8,1],[37.1913,1,1],[37.1955,12,1],[37.1998,5,1],[37.204,16,1],[37.2083,9,1],[37.2125,2,1],[37.2168,13,1],[37.2211,6,1],[37.2254,17,1],[37.2297,10,1],[37.2341,3,1],[37.2384,14,1],[37.2428,7,1],[37.2472,18,1],[37.2516,11,1],[37.256,4,1],[37.2604,15,1],[37.2649,8,1],[37.2694,1,1],[37.2738,12,1],[37.2783,5,1],[37.2828,16,1],[37.2874,9,1],[37.2919,2,1],[37.2965,13,1],[37.3011,6,1],[37.3057,17,1],[37.3103,10,1],[37.3149,3,1],[37.3196,14,1],[37.3243,7,1],[37.329,18,1],[37.3337,11,1],[37.3384,4,1],[37.3431,15,1],[37.3479,8,1],[37.3527,1,1],[37.3575,12,1],[37.3623,5,1],[37.3672,16,1],[37.372,9,1],[37.3769,2,1],[37.3818,13,1],[37.3868,6,1],[37.3917,17,1],[37.3967,10,1],[37.4017,3,1],[37.4067,14,1],[37.4117,7,1],[37.4168,18,1],[37.4218,11,1],[37.4269,4,1],[37.4321,15,1],[37.4372,8,1],[37.4424,1,1],[37.4476,12,1],[37.4528,5,1],[37.458,16,1],[37.4633,9,1],[37.4686,2,1],[37.4739,13,1],[37.4792,6,1],[37.4846,17,1],[37.49,10,1],[37.4954,3,1],[37.5009,14,1],[37.5063,7,1],[37.5118,18,1],[37.5173,11,1],[37.5229,4,1],[37.5285,15,1],[37.5341,8,1],[37.5397,1,1],[37.5454,12,1],[37.551,5,1],[37.5568,16,1],[37.5625,9,1],[37.5683,2,1],[37.5741,13,1],[37.5799,6,1],[37.5858,17,1],[37.5917,10,1],[37.5976,3,1],[37.6036,14,1],[37.6095,7,1],[37.6156,18,1],[37.6216,11,1],[37.6277,4,1],[37.6338,15,1],[37.64,8,1],[37.6461,1,1],[37.6524,12,1],[37.6586,5,1],[37.6649,16,1],[37.6712,9,1],[37.6776,2,1],[37.684,13,1],[37.6904,6,1],[37.6969,17,1],[37.7033,10,1],[37.7099,3,1],[37.7165,14,1],[37.7231,7,1],[37.7297,18,1],[37.7364,11,1],[37.7431,4,1],[37.7499,15,1],[37.7567,8,1],[37.7635,1,1],[37.7704,12,1],[37.7773,5,1],[37.7842,16,1],[37.7912,9,1],[37.7983,2,1],[37.8053,13,1],[37.8125,6,1],[37.8196,17,1],[37.8268,10,1],[37.8341,3,1],[37.8413,14,1],[37.8487,7,1],[37.856,18,1],[37.8634,11,1],[37.8709,4,1],[37.8784,15,1],[37.8859,8,1],[37.8935,1,1],[37.9011,12,1],[37.9087,5,1],[37.9164,16,1],[37.9242,9,1],[37.932,2,1],[37.9398,13,1],[37.9477,6,1],[37.9556,17,1],[37.9636,10,1],[37.9716,3,1],[37.9796,14,1],[37.9877,7,1],[37.9958,18,1],[38.004,11,1],[38.0122,4,1],[38.0205,15,1],[38.0288,8,1],[38.0371,1,1],[38.0455,12,1],[38.0539,5,1],[38.0623,16,1],[38.0708,9,1],[38.0794,2,1],[38.088,13,1],[38.0966,6,1],[38.1052,17,1],[38.1139,10,1],[38.1226,3,1],[38.1314,14,1],[38.1402,7,1],[38.149,18,1],[38.1579,11,1],[38.1668,4,1],[38.1757,15,1],[38.1847,8,1],[38.1937,1,1],[38.2027,12,1],[38.2117,5,1],[38.2208,16,1],[38.2299,9,1],[38.2391,2,1],[38.2482,13,1],[38.2574,6,1],[38.2666,17,1],[38.2758,10,1],[38.2851,3,1],[38.2944,14,1],[38.3037,7,1],[38.313,18,1],[38.3223,11,1],[38.3317,4,1],[38.341,15,1],[38.3504,8,1],[38.3598,1,1],[38.3692,12,1],[38.3786,5,1],[38.3881,16,1],[38.3975,9,1],[38.407,2,1],[38.4164,13,1],[38.4259,6,1],[38.4354,17,1],[38.4449,10,1],[38.4543,3,1],[38.4638,14,1],[38.4733,7,1],[38.4829,18,1],[38.4924,11,1],[38.5019,4,1],[38.5114,15,1],[38.5209,8,1],[38.5304,1,1],[38.54,12,1],[38.5495,5,1],[38.559,16,1],[38.5685,9,1],[38.578,2,1],[38.5876,13,1],[38.5971,6,1],[38.6066,17,1],[38.6161,10,1],[38.6257,3,1],[38.6352,14,1],[38.6447,7,1],[38.6542,18,1],[38.6638,11,1],[38.6733,4,1],[38.6828,15,1],[38.6923,8,1],[38.7019,1,1],[38.7114,12,1],[38.7209,5,1],[38.7304,16,1],[38.7399,9,1],[38.7495,2,1],[38.759,13,1],[38.7685,6,1],[38.778,17,1],[38.7876,10,1],[38.7971,3,1],[38.8066,14,1],[38.8161,7,1],[38.8257,18,1],[38.8352,11,1],[38.8447,4,1],[38.8542,15,1],[38.8638,8,1],[38.8733,1,1],[38.8828,12,1],[38.8923,5,1],[38.9019,16,1],[38.9114,9,1],[38.9209,2,1],[38.9304,13,1],[38.9399,6,1],[38.9495,17,1],[38.959,10,1],[38.9685,3,1],[38.978,14,1],[38.9876,7,1],[38.9971,18,1],[39.0066,11,1],[39.0161,4,1],[39.0257,15,1],[39.0352,8,1],[39.0447,1,1],[39.0542,12,1],[39.0638,5,1],[39.0733,16,1],[39.0828,9,1],[39.0923,2,1],[39.1019,13,1],[39.1114,6,1],[39.1209,17,1],[39.1304,10,1],[39.1399,3,1],[39.1495,14,1],[39.159,7,1],[39.1685,18,1],[39.178,11,1],[39.1876,4,1],[39.1971,15,1],[39.2066,8,1],[39.2161,1,1],[39.2257,12,1],[39.2352,5,1],[39.2447,16,1],[39.2542,9,1],[39.2638,2,1],[39.2733,13,1],[39.2828,6,1],[39.2923,17,1],[39.3019,10,1],[39.3114,3,1],[39.3209,14,1],[39.3304,7,1],[39.3399,18,1],[39.3495,11,1],[39.359,4,1],[39.3685,15,1],[39.378,8,1],[39.3876,1,1],[39.3971,12,1],[39.4066,5,1],[39.4161,16,1],[39.4257,9,1],[39.4352,2,1],[39.4447,13,1],[39.4542,6,1],[39.4638,17,1],[39.4733,10,1],[39.4828,3,1],[39.4923,14,1],[39.5019,7,1],[39.5114,18,1],[39.5209,11,1],[39.5304,4,1],[39.5399,15,1],[39.5495,8,1],[39.559,1,1],[39.5685,12,1],[39.578,5,1],[39.5876,16,1],[39.5971,9,1],[39.6066,2,1],[39.6161,13,1],[39.6257,6,1],[39.6352,17,1],[39.6447,10,1],[39.6542,3,1],[39.6638,14,1],[39.6733,7,1],[39.6828,18,1],[39.6923,11,1],[39.7019,4,1],[39.7114,15,1],[39.7209,8,1],[39.7304,1,1],[39.7399,12,1],[39.7495,5,1],[39.759,16,1],[39.7685,9,1],[39.778,2,1],[39.7876,13,1],[39.7971,6,1],[39.8066,17,1],[39.8161,10,1],[39.8257,3,1],[39.8352,14,1],[39.8447,7,1],[39.8542,18,1],[39.8638,11,1],[39.8733,4,1],[39.8828,15,1],[39.8923,8,1],[39.9019,1,1],[39.9114,12,1],[39.9209,5,1],[39.9304,16,1],[39.9399,9,1],[39.9495,2,1],[39.959,13,1],[39.9685,6,1],[39.978,17,1],[39.9876,10,1],[39.9971,3,1]]} \ No newline at end of file diff --git a/machines/radial/r2800-film/main.js b/machines/radial/r2800-film/main.js new file mode 100644 index 0000000..86d3364 --- /dev/null +++ b/machines/radial/r2800-film/main.js @@ -0,0 +1,4 @@ +// Radial, the R-2800 film. Shared code in ../r2800-shared. +import {run} from '../r2800-shared/film.js'; + +run(); diff --git a/machines/radial/r2800-film/timeline.json b/machines/radial/r2800-film/timeline.json new file mode 100644 index 0000000..5b015db --- /dev/null +++ b/machines/radial/r2800-film/timeline.json @@ -0,0 +1 @@ +{"duration":40,"beats":{"views":[1.6,3.3,6.4,12.6,18.6,23.6,28.4,32.6,35.4],"presses":[1.6,3.3,28.4,35.4],"starter":1.6,"ignition":3.3,"disengage":4.6,"climb":29.7,"full":32.7,"back":35.6,"idleAgain":38.6}} \ No newline at end of file diff --git a/machines/radial/r2800-live/main.js b/machines/radial/r2800-live/main.js new file mode 100644 index 0000000..9a82e5d --- /dev/null +++ b/machines/radial/r2800-live/main.js @@ -0,0 +1,5 @@ +import {runLive} from '../r2800-shared/live.js'; + +// Radial as an interactive page: starter, magnetos, throttle, slow motion, seven subsystems, cutaways, four views, +// orbit and zoom, and an auto tour when left alone. +runLive(); diff --git a/machines/radial/r2800-shared/console.js b/machines/radial/r2800-shared/console.js new file mode 100644 index 0000000..9827c42 --- /dev/null +++ b/machines/radial/r2800-shared/console.js @@ -0,0 +1,400 @@ +// Radial's overlay, a plate from a period technical manual: paper panels with a double rule, figure numbers, a +// condensed grotesque and a stencil title. Left: the title, three round dials drawn from the model (rpm, manifold +// pressure, brake power) with the torque and the piston speed under them, the engine's data plate, the run (phase and +// slow motion). Right: the firing-order star turning with the crank, a context figure (the piston law of a master +// and an articulated rod, the cam ring, the throws, the take-off curve), the subsystem, cutaway, view and layer +// buttons. Callouts with thin leaders. Fixed 1600 x 900 CSS layout; update(s) redraws every live part. +import {ACCENT} from './model.js'; +import {CAM, CYL, DISPL_IN3, DISPL_L, E, FIRE, GEAR, LAW, lift, MASS_KG, ORDER, RATING, ROWS, pistonS, propHp, stateAt, VALVE} from './engine.js'; +import {FONT} from './fonts.js'; +import {nf, T as tr} from './i18n.js'; + +export const C = {ink: '#22262b', mute: '#777b80', faint: '#b9b6ad', rule: '#2b2f34', paper: 'rgba(246,243,234,.95)', paperSolid: '#f6f3ea', acc: ACCENT, accSoft: 'rgba(10,143,224,.16)', red: '#b8322a'}; +export const SUBS = ['crank', 'cyl', 'valve', 'ign', 'air', 'prop', 'oil']; +export const CUTS = ['glass', 'section', 'solid']; +export const CAMS = ['face', 'hero', 'profile', 'inside']; +export const LAYERS = ['cowl', 'callouts']; +const CSS = ` +#app{font-family:${FONT.cond};color:${C.ink};-webkit-font-smoothing:antialiased;font-variant-numeric:tabular-nums} +.ui{position:absolute;inset:0;pointer-events:none} +.pl{position:absolute;background:${C.paper};border:1.5px solid ${C.rule};box-shadow:0 1px 0 rgba(0,0,0,.05)} +.pl::after{content:'';position:absolute;inset:3px;border:.75px solid rgba(34,38,43,.45);pointer-events:none} +.fig{position:absolute;font-weight:700;font-size:13px;letter-spacing:1.6px;text-transform:uppercase;white-space:nowrap} +.fig i{font-style:normal;color:${C.mute};font-weight:500;margin-right:6px} +.mu{color:${C.mute}} +.tb{position:absolute;height:22px;padding:0 7px;display:flex;align-items:center;justify-content:center;font-size:12.5px;font-weight:700;letter-spacing:1.1px;text-transform:uppercase;border:1.2px solid ${C.rule};background:${C.paperSolid};color:${C.ink};white-space:nowrap;box-sizing:border-box} +.tb.on{background:${C.ink};color:${C.paperSolid}} +.call{position:absolute;white-space:nowrap;background:rgba(246,243,234,.88);padding:3px 7px 4px;border-left:2px solid ${C.rule}} +.call.r{border-left:0;border-right:2px solid ${C.rule}} +.call b{display:block;font-size:24px;font-weight:700;letter-spacing:.2px;line-height:1} +.call span{display:block;font-size:12.5px;font-weight:500;letter-spacing:1.2px;color:${C.mute};text-transform:uppercase;margin-top:2px} +.cur{position:absolute;left:0;top:0;z-index:50;filter:drop-shadow(0 1px 2px rgba(0,0,0,.3))} +.ring{position:absolute;width:36px;height:36px;margin:-18px 0 0 -18px;border-radius:50%;border:2px solid ${C.ink};opacity:0;z-index:49} +.row{position:absolute;display:flex;justify-content:space-between;font-size:13.5px;letter-spacing:.3px} +.row span:first-child{color:${C.mute};text-transform:uppercase;letter-spacing:1px;font-size:12px;font-weight:500} +.row b{font-weight:700} +svg text{font-family:${FONT.cond}} +`; +const el = (h) => { + const d = document.createElement('div'); + d.innerHTML = h.trim(); + return d.firstElementChild; +}; +const fInt = (x) => nf(Math.round(x)); +const D2R = Math.PI / 180; + +/** a round dial: the face and ticks are drawn once, the needle every frame */ +function dial(svg, {cx, cy, r, min, max, major, minor, label, unit, scaleTxt = (v) => nf(v), red, skipEnds = false}) { + const a0 = -225; + const a1 = 45; + const ang = (v) => a0 + ((v - min) / (max - min)) * (a1 - a0); + const P = (a, rr) => [cx + Math.cos(a * D2R) * rr, cy + Math.sin(a * D2R) * rr]; + let h = ``; + for (let v = min; v <= max + 1e-6; v += minor) { + const isMaj = Math.abs(((v - min) / major) % 1) < 1e-6 || Math.abs(((v - min) / major) % 1 - 1) < 1e-6; + const [x0, y0] = P(ang(v), r - 6); + const [x1, y1] = P(ang(v), r - (isMaj ? 15 : 10)); + h += ``; + if (isMaj && !(skipEnds && (Math.abs(v - min) < 1e-6 || Math.abs(v - max) < 1e-6))) { + const [tx, ty] = P(ang(v), r - (r > 60 ? 26 : 23)); + h += `${scaleTxt(v)}`; + } + } + if (red !== undefined) { + const [x0, y0] = P(ang(red), r - 5); + const [x1, y1] = P(ang(red), r - 18); + h += ``; + } + const ly = cy + r * (r > 60 ? 0.42 : 0.66); + h += `${label}`; + h += `${unit}`; + h += ``; + svg.insertAdjacentHTML('beforeend', h); + const ndl = svg.lastElementChild.previousElementSibling; + return (v) => ndl.setAttribute('transform', `rotate(${ang(Math.min(max, Math.max(min, v))) + 90} ${cx} ${cy})`); +} + +export function createConsole(app) { + const style = document.createElement('style'); + style.textContent = CSS; + document.head.appendChild(style); + const ui = el(`
`); + app.appendChild(ui); + const add = (h) => { + const n = el(h); + ui.appendChild(n); + return n; + }; + + // ------------------------------------------------------------ title plate + add(`
`); + add(`
RADIAL
`); + add(`
${tr('subtitle')}
`); + add(`
${tr('model')}
`); + + // ------------------------------------------------------------ instruments + add(`
`); + add(`
${tr('fig', 1)}${tr('figInstr')}
`); + const dsvg = add(``); + const setRpm = dial(dsvg, {cx: 84, cy: 108, r: 76, min: 0, max: 3000, major: 500, minor: 100, label: tr('dRpm'), unit: tr('dRpmU'), scaleTxt: (v) => nf(v / 100), red: RATING.takeoff.rpm}); + const setMap = dial(dsvg, {cx: 222, cy: 56, r: 52, min: 10, max: 70, major: 20, minor: 5, label: tr('dMap'), unit: 'IN HG', red: RATING.takeoff.map, skipEnds: true}); + const setHp = dial(dsvg, {cx: 222, cy: 164, r: 52, min: 0, max: 2500, major: 500, minor: 250, label: tr('dHp'), unit: 'HP × 100', scaleTxt: (v) => nf(v / 100), red: RATING.takeoff.hp, skipEnds: true}); + const readTop = 382; + const rowsTxt = ['rTorque', 'rPiston', 'rProp'].map((k, i) => + add(`
${tr(k)}
`).querySelector('b'), + ); + + // ------------------------------------------------------------ data plate + add(`
`); + add(`
${tr('fig', 2)}${tr('figData')}
`); + const data = [ + ['pBore', `${nf(5.75, 2)} × ${nf(6, 2)} in`], + ['pDispl', `${fInt(DISPL_IN3)} in³ · ${nf(DISPL_L, 1)} L`], + ['pCr', `${nf(E.cr, 2)} : 1`], + ['pTo', `${fInt(RATING.takeoff.hp)} hp · ${fInt(RATING.takeoff.rpm)} · ${nf(RATING.takeoff.map, 1)}″`], + ['pWet', `${fInt(RATING.wet.hp)} hp · ${fInt(RATING.wet.rpm)} · ${nf(RATING.wet.map, 1)}″`], + ['pRed', `${nf(GEAR.prop, 2)} : 1`], + ['pSc', tr('pScV', nf(GEAR.impLow, 2), nf(GEAR.impHigh, 2))], + ['pMass', `${fInt(MASS_KG)} kg`], + ['pCam', tr('pCamV')], + ['pIgn', tr('pIgnV')], + ]; + data.forEach(([k, v], i) => add(`
${tr(k)}${v}
`)); + + // ------------------------------------------------------------ the run: phase, slow motion, live controls + add(`
`); + add(`
${tr('fig', 3)}${tr('figRun')}
`); + const phaseTxt = add(`
`); + const slowTxt = add(`
`); + const btn = {}; + ['starter', 'ignition', 'slowmo', 'pause'].forEach((k, i) => { + btn[k] = add(`
${tr({starter: 'bStarter', ignition: 'bIgnition', slowmo: 'bSlow', pause: 'pause'}[k])}
`); + }); + add(`
${tr('throttle')}
`); + const thrVal = add(`
`); + const SL = {x: 44, w: 260}; + add(`
`); + const thrKnob = add(`
`); + + + // ------------------------------------------------------------ firing-order star + add(`
`); + add(`
${tr('fig', 4)}${tr('figStar')}
`); + add(`
${tr('starSub')}
`); + const SC = {cx: 146, cy: 112, rr: 64, rf: 92}; + const star = add(``); + const sp = (a, r) => [SC.cx - Math.sin(a * D2R) * r, SC.cy - Math.cos(a * D2R) * r]; + { + let h = ``; + h += ``; + for (const cy of CYL) { + const [x, y] = sp(cy.angle, cy.row === 'rear' ? SC.rr : SC.rf); + h += ``; + h += `${cy.c}`; + } + h += ``; + h += `${tr('starKey')}`; + star.innerHTML = h; + } + const starDots = Object.fromEntries(CYL.map((cy) => [cy.c, star.querySelector(`[data-c="${cy.c}"]`)])); + const starTxt = Object.fromEntries(CYL.map((cy) => [cy.c, star.querySelector(`[data-t="${cy.c}"]`)])); + const pins = star.querySelector('.pins'); + const orderBox = add(`
`); + orderBox.innerHTML = ORDER.map((c) => `${c}`).join(''); + const orderSpans = Object.fromEntries(ORDER.map((c) => [c, orderBox.querySelector(`[data-o="${c}"]`)])); + const starFoot = add(`
`); + + // ------------------------------------------------------------ context figure + add(`
`); + const ctxTitle = add(`
`); + const ctxSvg = add(``); + const ctxTxt = add(`
`); + + // ------------------------------------------------------------ subsystems, cutaways, views, layers + add(`
`); + const spots = {}; + const group = (title, keys, y, label, cols) => { + add(`
${title}
`); + const W = 264; + const gap = 4; + const w = (W - gap * (cols - 1)) / cols; + keys.forEach((k, i) => { + const x = 1294 + (i % cols) * (w + gap); + const yy = y + 15 + Math.floor(i / cols) * 25; + btn[k] = add(`
${label(k)}
`); + spots[k] = [x + w / 2, yy + 11]; + }); + return y + 15 + Math.ceil(keys.length / cols) * 25 + 4; + }; + let y = group(tr('grpSub'), SUBS, 628, (k) => tr('sub:' + k), 2); + y = group(tr('grpCut'), CUTS, y, (k) => tr('cut:' + k), 3); + y = group(tr('grpView'), CAMS, y, (k) => tr('cam:' + k), 4); + group(tr('grpLayer'), LAYERS, y, (k) => tr('lay:' + k), 2); + ['starter', 'ignition', 'slowmo', 'pause'].forEach((k, i) => (spots[k] = [42 + i * 66.5 + 31, 813])); + spots.throttle = [SL.x + SL.w * 0.15, 853]; + spots.throttleBack = [SL.x + SL.w, 853]; + + // ------------------------------------------------------------ caption, callouts, cursor + const cap = add(`
`); + const leaders = add(``); + const callPool = []; + const cursor = add(``); + const ring = add(`
`); + + // ------------------------------------------------------------ context figures + const plot = (pts, x0, y0, w, h, xr, yr, color, width = 1.6, dash = '') => { + const X = (x) => x0 + ((x - xr[0]) / (xr[1] - xr[0])) * w; + const Y = (v) => y0 + h - ((v - yr[0]) / (yr[1] - yr[0])) * h; + return ``; + }; + const axes = (x0, y0, w, h, xl, yl) => + `` + + `${xl}${yl}`; + // the piston law: master against its most different articulated rod, the difference magnified + const lawCyl = (row) => ROWS[row].filter((c) => c.c !== E.master[row]).reduce((a, b) => (Math.abs(LAW[b.c].tdcLag) > Math.abs(LAW[a.c].tdcLag) ? b : a)).c; + const lawStatic = {}; + const lawFig = (row) => { + if (lawStatic[row]) return lawStatic[row]; + const m = E.master[row]; + const a = lawCyl(row); + const dm = CYL[a - 1].angle - CYL[m - 1].angle; + const t0 = LAW[m].thTDC; + const ptsD = []; + for (let i = 0; i <= 180; i++) { + const x = i * 2; + ptsD.push([x, pistonS(a, t0 + x + dm) - pistonS(m, t0 + x)]); + } + const lo = Math.min(...ptsD.map((p) => p[1])); + const hi = Math.max(...ptsD.map((p) => p[1])); + const ym = Math.max(Math.abs(lo), Math.abs(hi)) * 1.15; + const h = + axes(30, 6, 236, 100, tr('lawX'), tr('lawY')) + + `` + + plot(ptsD, 30, 6, 236, 100, [0, 360], [-ym, ym], C.acc, 2.2) + + `+${nf(ym, 1)}−${nf(ym, 1)}`; + lawStatic[row] = {h, m, a, dm, ym, t0}; + return lawStatic[row]; + }; + const camFig = {}; + const camFigFor = (c) => { + if (camFig[c]) return camFig[c]; + const pi = []; + const pe = []; + for (let i = 0; i <= 240; i++) { + const th = FIRE[c] + i * 3; + pi.push([i * 3, lift(c, 'in', th)]); + pe.push([i * 3, lift(c, 'ex', th)]); + } + const h = axes(30, 6, 236, 96, tr('camX'), tr('camY')) + plot(pe, 30, 6, 236, 96, [0, 720], [0, 1.15], C.ink, 1.8, '4 3') + plot(pi, 30, 6, 236, 96, [0, 720], [0, 1.15], C.ink, 2) + [180, 360, 540].map((x) => ``).join('') + ['power', 'exhaust', 'intake', 'compression'].map((k, i) => `${tr('st:' + k)}`).join(''); + camFig[c] = h; + return h; + }; + const toFig = (() => { + const pts = []; + for (let N = 600; N <= 2800; N += 50) pts.push([N, propHp(N)]); + const tq = []; + for (let N = 600; N <= 2800; N += 50) tq.push([N, stateAt(N).torque]); + return axes(30, 6, 236, 100, tr('toX'), tr('toY')) + plot(pts, 30, 6, 236, 100, [600, 2800], [0, 2500], C.ink, 2) + plot(tq.map(([a, b]) => [a, b / 2.4]), 30, 6, 236, 100, [600, 2800], [0, 2500], C.ink, 1.6, '4 3') + ``; + })(); + let ctxKey = ''; + + const update = (s) => { + // dials and readouts + setRpm(s.N); + setMap(s.map); + setHp(s.hp); + rowsTxt[0].textContent = `${fInt(s.torque)} N·m · ${fInt(s.torque * 0.7376)} lb·ft`; + rowsTxt[1].textContent = `${nf(s.pistonMs, 1)} m/s`; + rowsTxt[2].textContent = `${fInt(s.propRpm)} · ${fInt(s.impRpm)}`; + // the run + phaseTxt.textContent = tr('ph:' + s.phase); + slowTxt.innerHTML = s.rate < 0.98 ? tr('slow', nf(1000 * s.rate, 0), nf(1 / s.rate, 0)) : tr('realtime'); + thrVal.textContent = `${fInt(s.thrRpm ?? s.N)} ${tr('rpmShort')}`; + thrKnob.style.left = `${SL.x + SL.w * Math.min(1, Math.max(0, ((s.thrRpm ?? s.N) - RATING.idle) / (RATING.takeoff.rpm - RATING.idle)))}px`; + btn.starter.classList.toggle('on', !!s.starter); + btn.ignition.classList.toggle('on', !!s.ignition); + btn.pause.classList.toggle('on', !!s.paused); + btn.slowmo.classList.toggle('on', s.rate < 0.98); + // the star: the crank pins turn, the cylinder that fires lights + pins.setAttribute('transform', `rotate(${-s.th} ${SC.cx} ${SC.cy})`); + let best = 0; + let bestC = 0; + for (const cy of CYL) { + const g = s.lit[cy.c - 1]; + const dot = starDots[cy.c]; + const k = Math.min(1, g * 1.6); + dot.setAttribute('fill', k > 0.02 ? `rgba(10,143,224,${(0.2 + 0.8 * k).toFixed(3)})` : cy.row === 'rear' ? '#e7e3d8' : '#fbf9f3'); + dot.setAttribute('stroke', k > 0.3 ? C.acc : C.ink); + starTxt[cy.c].setAttribute('fill', k > 0.5 ? '#fff' : C.ink); + if (g > best) [best, bestC] = [g, cy.c]; + } + for (const c of ORDER) { + const on = c === bestC && best > 0.15; + orderSpans[c].style.color = on ? '#fff' : C.ink; + orderSpans[c].style.background = on ? C.acc : 'transparent'; + } + starFoot.innerHTML = tr('starFoot', nf(s.fireHz, 0)); + // context figure + const key = s.ctx + ':' + (s.ctxArg ?? ''); + if (key !== ctxKey) { + ctxKey = key; + ctxTitle.innerHTML = `${tr('fig', 5)}${tr('ctx:' + s.ctx)}`; + if (s.ctx === 'law') ctxSvg.innerHTML = lawFig(s.ctxArg || 'front').h + ``; + else if (s.ctx === 'cam') ctxSvg.innerHTML = camFigFor(s.ctxArg) + ``; + else if (s.ctx === 'takeoff') ctxSvg.innerHTML = toFig + ``; + else if (s.ctx === 'throws') ctxSvg.innerHTML = ``; + else ctxSvg.innerHTML = ``; + } + const cur1 = ctxSvg.querySelector('.cur1'); + if (s.ctx === 'law') { + const L = lawFig(s.ctxArg || 'front'); + const m = LAW[L.m]; + const a = LAW[L.a]; + const th = (((s.th - L.t0) % 360) + 360) % 360; + const x = 30 + (th / 360) * 236; + const d = pistonS(L.a, s.th + L.dm) - pistonS(L.m, s.th); + cur1.innerHTML = ``; + ctxTxt.innerHTML = tr('lawTxt', L.m, L.a, nf(m.stroke, 2), nf(a.stroke, 2), nf(Math.abs(a.tdcLag), 1), nf(-a.dTDC, 2), nf(m.cr, 2), nf(a.cr, 2), a.tdcLag > 0); + } else if (s.ctx === 'cam') { + const c = s.ctxArg; + const ph = (((s.th - FIRE[c]) % 720) + 720) % 720; + const x = 30 + (ph / 720) * 236; + cur1.innerHTML = ``; + ctxTxt.innerHTML = tr('camTxt', c, CAM.lobes, nf(CAM.liftMm, 1), nf(lift(c, 'in', s.th) * CAM.liftMm, 1), nf(lift(c, 'ex', s.th) * CAM.liftMm, 1), VALVE.in, VALVE.ex); + } else if (s.ctx === 'takeoff') { + const x = 30 + ((Math.min(2800, Math.max(600, s.N)) - 600) / 2200) * 236; + const yv = 6 + 100 - (Math.min(2500, s.hp) / 2500) * 100; + cur1.innerHTML = ``; + ctxTxt.innerHTML = tr('toTxt', fInt(s.hp), fInt(s.N), nf(s.map, 1), fInt(s.torque)); + } else if (s.ctx === 'throws') { + // the two crankpins seen from the front, and the rows + const cx = 70; + const cy = 66; + const rr = s.th * D2R; + const p = (a, r) => [cx - Math.sin(a) * r, cy - Math.cos(a) * r]; + const [x1, y1] = p(rr, 34); + const [x2, y2] = p(rr + Math.PI, 34); + cur1.innerHTML = `${tr('throwKey')}` + + `${tr('throwA')}${tr('throwA2')}${tr('throwB')}${tr('throwB2')}`; + ctxTxt.innerHTML = tr('throwTxt'); + } else if (s.ctx === 'ign') { + cur1.innerHTML = ''; + ctxTxt.innerHTML = tr('ignTxt'); + } else { + cur1.innerHTML = ''; + ctxTxt.innerHTML = tr('ctxTxt:' + s.ctx); + } + const plain = !['law', 'cam', 'takeoff', 'throws'].includes(s.ctx); + ctxTxt.style.top = plain ? '418px' : '548px'; + ctxTxt.style.fontSize = plain ? '15px' : '13px'; + // buttons + for (const k of SUBS) btn[k].classList.toggle('on', s.sub === k); + for (const k of CUTS) btn[k].classList.toggle('on', s.cut === k); + for (const k of CAMS) btn[k].classList.toggle('on', s.camBtn === k); + btn.cowl.classList.toggle('on', !!s.layers?.cowl); + btn.callouts.classList.toggle('on', !!s.layers?.callouts); + // caption + cap.textContent = s.caption || ''; + cap.style.display = s.caption ? '' : 'none'; + // callouts + const list = s.callouts || []; + let lh = ''; + list.forEach((c, i) => { + let d = callPool[i]; + if (!d) { + d = add(`
`); + callPool[i] = d; + } + const o = c.o ?? 1; + if (!c.at || o < 0.02) { + d.style.display = 'none'; + return; + } + d.style.display = ''; + d.style.opacity = o; + d.querySelector('b').textContent = c.name; + d.querySelector('span').textContent = c.sub || ''; + const right = c.w < 0; + const [lx, ly] = c.label; + d.style.left = right ? '' : `${lx}px`; + d.style.right = right ? `${1600 - lx}px` : ''; + d.style.textAlign = right ? 'right' : 'left'; + d.classList.toggle('r', right); + d.style.top = `${ly - 17}px`; + const ex = lx; + const kx = ex + (right ? 1 : -1) * Math.abs(c.w) * 0.25; + lh += ``; + }); + for (let i = list.length; i < callPool.length; i++) callPool[i].style.display = 'none'; + leaders.innerHTML = lh; + // cursor + const cu = s.cursor || {x: -99, y: -99}; + cursor.style.transform = `translate(${cu.x - 3}px, ${cu.y - 2}px) scale(${cu.press ? 0.9 : 1})`; + ring.style.left = `${cu.ringX ?? 0}px`; + ring.style.top = `${cu.ringY ?? 0}px`; + ring.style.opacity = cu.ring ?? 0; + ring.style.transform = `scale(${1.6 - 0.6 * (cu.ring ?? 0)})`; + }; + return {root: ui, btn, spots, update, SL, thrKnob}; +} +void DISPL_IN3; diff --git a/machines/radial/r2800-shared/engine.js b/machines/radial/r2800-shared/engine.js new file mode 100644 index 0000000..34b6b4b --- /dev/null +++ b/machines/radial/r2800-shared/engine.js @@ -0,0 +1,222 @@ +// The R-2800 Double Wasp, the numbers: one source for every figure the page shows and every pose the 3D takes. +// Modelled on a C-series R-2800 CB16 (Douglas DC-6B, Convair 340) from public sources; not affiliated with Pratt & +// Whitney. The letters match REFERENCES.md: [F] the FAA type certificate data sheet 6A3, [N] the Smithsonian NASM +// record, [H] the FAA powerplant handbook, [W] the published series description, [E] an estimate (not public). +// +// No three.js in here: node imports it for check.mjs, the timeline and the score. Units are millimetres and degrees. +// Angles around the engine are measured clockwise from the top, seen from the rear (the pilot's side); the crankshaft +// turns clockwise seen from the rear, the usual US "right-hand tractor". + +export const E = { + bore: 146.05, // 5.75 in [W] + stroke: 152.4, // 6.0 in [W] + r: 76.2, // crank throw, half the stroke + L: 292, // master rod, crankpin centre to piston pin [E] + rk: 60.3, // knuckle-pin circle on the master rod's big end, 2.375 in [E] + l: 231.7, // articulated rod, knuckle pin to piston pin: L - rk [E] + cr: 6.75, // compression ratio of the C series [W] + compH: 66, // piston pin to crown [E] + rowZ: {rear: -105, front: 105}, // the two rows along the axis [E] + master: {rear: 13, front: 8}, // the cylinders that carry the master rods [E] +}; +export const DISPL_IN3 = (Math.PI / 4) * 5.75 ** 2 * 6 * 18; // 2,804.5 in³ +export const DISPL_L = DISPL_IN3 * 0.016387064; // 45.96 L +export const RATING = { + takeoff: {hp: 2050, rpm: 2700, map: 55.0}, // dry, two minutes, low blower [F] + wet: {hp: 2400, rpm: 2800, map: 59.5}, // water-alcohol injection [F] + meto: {hp: 1800, rpm: 2600, map: 48.5}, // maximum continuous [F] + idle: 700, // [E] + crank: 140, // starter cranking speed [E] +}; +export const GEAR = {prop: 0.45, impLow: 7.29, impHigh: 8.58}; // [F] +export const MASS_KG = 1068; // 2,350 lb [N] +export const DIAMETER_MM = 1341; // 52.8 in [N] +export const LENGTH_MM = 2068; // 81.4 in [N] +export const PROP_D = 4.0; // m, a three-blade Hamilton Standard [E] + +// ------------------------------------------------------------ cylinders, numbering and firing order +// 1 at the top of the rear row, then clockwise seen from the rear: odd numbers in the rear row, even in the front, +// the front row turned 20° from the rear one [H]. 18 cylinders, 20° apart, 40° within a row. +export const CYL = Array.from({length: 18}, (_, i) => { + const c = i + 1; + const row = c % 2 ? 'rear' : 'front'; + return {c, row, k: Math.floor(i / 2), angle: 20 * i, z: E.rowZ[row]}; +}); +export const ROWS = {rear: CYL.filter((x) => x.row === 'rear'), front: CYL.filter((x) => x.row === 'front')}; +// the firing order numbers of an 18-cylinder twin-row radial are +11 and -7 [H] +export const ORDER = (() => { + const o = [1]; + while (o.length < 18) { + const a = o[o.length - 1] + 11; + o.push(a <= 18 ? a : o[o.length - 1] - 7); + } + return o; +})(); +export const INTERVAL = 720 / 18; // 40° of crank between firings +export const FIRE = Object.fromEntries(ORDER.map((c, i) => [c, i * INTERVAL])); // crank angle of each firing TDC +export const SPARK_ADV = 25; // ° before TDC [E] +const mod = (a, m) => ((a % m) + m) % m; +export const wrap180 = (a) => mod(a + 180, 360) - 180; +/** four-stroke phase of cylinder c, degrees after its firing TDC: 0-180 power, 180-360 exhaust, 360-540 intake, 540-720 compression */ +export const psi = (c, th) => mod(th - FIRE[c], 720); +export const STROKES = ['power', 'exhaust', 'intake', 'compression']; +export const strokeOf = (ps) => STROKES[Math.floor(mod(ps, 720) / 180)]; + +// ------------------------------------------------------------ the crank and the rods, exact +const vec = (a) => [Math.sin((a * Math.PI) / 180), Math.cos((a * Math.PI) / 180)]; +const rotCW = ([x, y], a) => { + const c = Math.cos((a * Math.PI) / 180); + const s = Math.sin((a * Math.PI) / 180); + return [x * c + y * s, -x * s + y * c]; +}; +const dot = (a, b) => a[0] * b[0] + a[1] * b[1]; +const cross = (a, b) => a[0] * b[1] - a[1] * b[0]; +/** the crankpin of a row: the rear one at θ, the front one at θ + 180° */ +export const pinAngle = (row, th) => (row === 'rear' ? th : th + 180); +/** + * every rod of one row at crank angle th: the crankpin C, the master rod's direction d, and for each cylinder its + * piston pin distance from the axis s (mm), its knuckle pin K (the master's own is C) and its piston pin P, in the + * plane of the row seen from the rear (x right, y up) + */ +export function rowPose(row, th) { + const C = vec(pinAngle(row, th)).map((v) => v * E.r); + const m = CYL[E.master[row] - 1]; + const um = vec(m.angle); + const sm = dot(C, um) + Math.sqrt(E.L * E.L - cross(C, um) ** 2); + const Pm = [um[0] * sm, um[1] * sm]; + const d = [(Pm[0] - C[0]) / E.L, (Pm[1] - C[1]) / E.L]; + const out = {C, d, cyl: {}}; + for (const cy of ROWS[row]) { + const u = vec(cy.angle); + if (cy.c === m.c) { + out.cyl[cy.c] = {s: sm, K: C, P: Pm, master: true}; + continue; + } + const kd = rotCW(d, cy.angle - m.angle); + const K = [C[0] + kd[0] * E.rk, C[1] + kd[1] * E.rk]; + const s = dot(K, u) + Math.sqrt(E.l * E.l - cross(K, u) ** 2); + out.cyl[cy.c] = {s, K, P: [u[0] * s, u[1] * s], master: false}; + } + return out; +} +export const pistonS = (c, th) => rowPose(CYL[c - 1].row, th).cyl[c].s; + +// the law of each piston, sampled once at 0.05°: stroke, TDC height and where TDC falls, against the ideal +// slider-crank of the master rod +export const LAW = (() => { + const out = {}; + for (const cy of CYL) { + let max = -1e9; + let min = 1e9; + let thMax = 0; + let thMin = 0; + for (let i = 0; i < 7200; i++) { + const th = i * 0.05; + const s = pistonS(cy.c, th); + if (s > max) [max, thMax] = [s, th]; + if (s < min) [min, thMin] = [s, th]; + } + // the crank angle at which the pin points at this cylinder: TDC for a plain slider-crank + const ideal = mod(cy.angle - (cy.row === 'rear' ? 0 : 180), 360); + const A = (Math.PI / 4) * E.bore * E.bore; + out[cy.c] = {sTDC: max, sBDC: min, stroke: max - min, thTDC: thMax, thBDC: thMin, tdcLag: wrap180(thMax - ideal), bdcLag: wrap180(thMin - ideal - 180), A}; + } + // clearance volume: set by the master's compression ratio; a piston that stops lower leaves a bigger chamber + for (const row of ['rear', 'front']) { + const m = out[E.master[row]]; + const Vc = (m.A * m.stroke) / (E.cr - 1); + for (const cy of ROWS[row]) { + const x = out[cy.c]; + x.Vc = Vc + x.A * (m.sTDC - x.sTDC); + x.cr = (x.Vc + x.A * x.stroke) / x.Vc; + x.dTDC = x.sTDC - m.sTDC; + } + } + return out; +})(); +export const MASTER_STROKE = LAW[E.master.front].stroke; + +// ------------------------------------------------------------ valves: two cam rings, no camshaft +// one ring per row, two tracks (inlet, exhaust), 4 lobes 90° apart, turning at 1/8 crank speed against the crank: +// a lobe reaches each tappet once every 720° of crank [H]. Valve events in crank degrees after the firing TDC [E]. +export const CAM = {lobes: 4, ratio: -1 / 8, liftMm: 15.9, zOff: 88}; +export const VALVE = {in: [340, 600], ex: [130, 380]}; // inlet opens 20° BTDC, closes 60° ABDC; exhaust 50° BBDC to 20° ATDC +const centre = ([a, b]) => (a + b) / 2; +const halfCam = ([a, b]) => (b - a) / 16; // the event's half-width in cam degrees (crank ÷ 8 ÷ 2) +// each track's phase, derived from the firing order: the lobe is centred on cylinder c's tappet when the crank is at +// the centre of c's event. The same constant holds for every cylinder of a row (check.mjs verifies it). +const phaseOf = (row, ev) => { + const c = ROWS[row][0]; + return mod(c.angle + (FIRE[c.c] + centre(VALVE[ev])) / 8, 90); +}; +export const CAM_PHASE = {rear: {in: phaseOf('rear', 'in'), ex: phaseOf('rear', 'ex')}, front: {in: phaseOf('front', 'in'), ex: phaseOf('front', 'ex')}}; +/** the ring's rotation (degrees, clockwise from the rear) at crank angle th: it turns against the crank at 1/8 */ +export const camAngle = (th) => th * CAM.ratio; +/** a lobe's offset in front of cylinder c's tappet, cam degrees, in [-45, 45) */ +export const lobeOffset = (c, ev, th) => { + const cy = CYL[c - 1]; + return mod(cy.angle - camAngle(th) - CAM_PHASE[cy.row][ev] + 45, 90) - 45; +}; +/** the lobe's rise under a tappet: 0..1, a smooth bump over the event's width */ +export const lobeRise = (x, half) => { + const u = Math.abs(x) / half; + return u >= 1 ? 0 : 0.5 + 0.5 * Math.cos(Math.PI * u); +}; +/** valve lift of cylinder c (0..1 of CAM.liftMm), read off the cam ring at crank angle th */ +export const lift = (c, ev, th) => lobeRise(lobeOffset(c, ev, th), halfCam(VALVE[ev])); +/** the same lift from the valve timing alone, for check.mjs */ +export const liftFromTiming = (c, ev, th) => { + const ps = psi(c, th); + const [a, b] = VALVE[ev]; + const x = mod(ps - centre([a, b]) + 360, 720) - 360; + return lobeRise(x / 8, halfCam([a, b])); +}; + +// ------------------------------------------------------------ ignition +// 2 plugs per cylinder (36), 2 magnetos each feeding one plug of every cylinder; a distributor turns at half crank +// speed so each plug fires once in two turns [W] +export const IGN = {plugs: 36, magnetos: 2, distRatio: 0.5}; +/** how long ago (crank degrees) cylinder c's plugs last fired, at th; the flame lights from the spark to ~70° ATDC */ +export const sinceSpark = (c, th) => mod(th - (FIRE[c] - SPARK_ADV), 720); + +// ------------------------------------------------------------ power, from the rpm alone +// quasi-steady: the propeller at fine pitch absorbs P ∝ N³, set to the take-off rating at 2,700 rpm [E]. The power +// needs a brake mean effective pressure; manifold pressure follows from bmep = k·MAP − friction − pumping, k set so +// that the take-off point is exact (2,050 hp needs 55.0 inHg [F]). check.mjs holds the METO point within 7 %. +const HP = 745.7; +const INHG = 0.033864; // bar per inHg +const AMB = 29.92; +export const fmep = (N) => 1.2 + 0.6 * (N / 2700) ** 2; // bar [E] +export const propHp = (N) => RATING.takeoff.hp * (N / RATING.takeoff.rpm) ** 3; +/** bmep in bar for a brake power (hp) at N rpm */ +export const bmepOf = (hp, N) => (N > 1 ? (2 * hp * HP) / ((DISPL_L / 1000) * (N / 60)) / 1e5 : 0); +export const K_MAP = (() => { + const {hp, rpm, map} = RATING.takeoff; + return (bmepOf(hp, rpm) + fmep(rpm) + (AMB - map) * INHG) / map; +})(); +/** brake power from MAP and N (the inverse) */ +export const hpOf = (map, N) => (Math.max(0, K_MAP * map - fmep(N) - (AMB - map) * INHG) * 1e5 * (DISPL_L / 1000) * (N / 60)) / 2 / HP; +/** + * the engine's state at N rpm. run 0..1: how far the engine has caught (0 on the starter, 1 running). Returns + * manifold pressure (inHg), brake power (hp), crank torque (N·m), firing frequency (Hz), mean piston speed (m/s), + * propeller and impeller rpm. + */ +export function stateAt(N, run = 1) { + const hp = run * propHp(N); + const mapRun = N > 1 ? (bmepOf(propHp(N), N) + fmep(N) + AMB * INHG) / (K_MAP + INHG) : AMB; + const mapCrank = AMB - 0.9 * Math.min(1, N / 100); + const map = mapCrank + (mapRun - mapCrank) * run; + const w = (N * 2 * Math.PI) / 60; + return { + N, + map, + hp, + kw: hp * HP * 1e-3, + torque: w > 0.1 ? (hp * HP) / w : 0, + fireHz: (N / 60) * 9, + pistonMs: (2 * E.stroke * 1e-3 * N) / 60, + propRpm: N * GEAR.prop, + impRpm: N * GEAR.impLow, + }; +} +export const AMBIENT_INHG = AMB; diff --git a/machines/radial/r2800-shared/film.js b/machines/radial/r2800-shared/film.js new file mode 100644 index 0000000..70bf3bd --- /dev/null +++ b/machines/radial/r2800-shared/film.js @@ -0,0 +1,298 @@ +// Radial, the film: the R-2800 (model.js) on its run-up stand (stage.js) under the manual-plate overlay (console.js). +// One input, the crank angle θ(t) integrated once from the planned run (schedule.js), poses every piston, rod, cam, +// valve, magneto, gear and the propeller, lights each spark, and drives every gauge. The operator starts the engine, +// watches the firing order go round the star, cuts a row, pulls the rows apart, looks at a cam ring lifting a valve, +// opens the throttle to take-off rpm and closes it again. A pure function of t. +import * as THREE from 'three'; +import {runSim} from 'teardown-kit/runtime.js'; +import {createConsole} from './console.js'; +import {CYL, E, lift, ROWS, stateAt, wrap180} from './engine.js'; +import {loadFonts} from './fonts.js'; +import {T as tr} from './i18n.js'; +import {airAt, camAtName, camSince, DURATION, lastSpark, rateAt, rpmAt, RUN, runAtTau, SCRIPT, starterAtTau, tauAt, thetaAt} from './schedule.js'; +import {createStage} from './stage.js'; + +export {DURATION, SCRIPT}; +export const DEFAULTS = {duration: DURATION, fps: 60, theme: 'light', hud: {enabled: false, title: 'radial', subtitle: ''}, director: {enabled: false}, watermark: ''}; +const D2R = Math.PI / 180; +export const smoother = (x) => { + const u = Math.min(1, Math.max(0, x)); + return u * u * u * (u * (u * 6 - 15) + 10); +}; +export const ss = (a, b, t) => smoother((t - a) / (b - a)); + +// the cylinder the cam view watches: the front-row cylinder near the top whose inlet valve opens mid-hold +export const CAM_CYL = (() => { + const t0 = 24.4; + const t1 = 28.0; + let best = ROWS.front[0].c; + let score = -1e9; + for (const cy of ROWS.front) { + let peak = 0; + let tp = 0; + for (let t = t0; t <= t1; t += 0.02) { + const L = lift(cy.c, 'in', thetaAt(t)); + if (L > peak) [peak, tp] = [L, t]; + } + const top = Math.cos(cy.angle * D2R); + const s = peak * 2 + top * 1.2 - Math.abs(tp - 26.2) * 0.6; + if (s > score) [score, best] = [s, cy.c]; + } + return best; +})(); + +// ------------------------------------------------------------ views, each a function of u (seconds since it came on) +const camAng = CYL[CAM_CYL - 1].angle; +export const VIEW_FN = { + hero: (u) => ({tx: 0, ty: -0.04, tz: 0.04, az: 36 + 1.0 * Math.min(u, 8), el: 9 + 0.3 * Math.min(u, 8), d: 4.7 - 0.05 * Math.min(u, 8), sx: 0, sy: 0}), + face: (u) => ({tx: 0, ty: 0, tz: 0, az: 0, el: 1.5, d: 4.35 - 0.06 * Math.min(u, 6), sx: 0, sy: 0}), + faceFull: (u) => ({tx: 0, ty: 0, tz: 0, az: -4 + 1.2 * u, el: 2, d: 4.5 - 0.04 * u, sx: 0, sy: 0}), + rowcut: (u) => ({tx: 0, ty: 0, tz: 0.1, az: 0, el: 0, d: 3.7 - 0.12 * Math.min(u, 6), sx: 0, sy: 0}), + apart: (u) => ({tx: 0, ty: 0.02, tz: 0.03, az: 58 + 1.6 * u, el: 18, d: 3.4, sx: 0, sy: 0}), + cam: (u) => { + // beside the watched cylinder, looking across it: the cam ring, the tappet, the tube, the rocker, the valve + const a = camAng * D2R; + const ur = [-Math.sin(a), Math.cos(a), 0]; + const ut = [Math.cos(a), Math.sin(a), 0]; + const sw = 0.1 * Math.sin(u * 0.35); + const dir = [0, 1, 2].map((i) => (0.82 + sw) * ut[i] + 0.5 * (i === 2 ? 1 : 0) + 0.22 * ur[i]); + const n = Math.hypot(...dir); + const [dx, dy, dz] = dir.map((v) => v / n); + const R = 0.31; + return {tx: ur[0] * R, ty: ur[1] * R, tz: 0.105 + 0.11, az: Math.atan2(dx, dz) / D2R, el: Math.asin(dy) / D2R, d: 1.8 - 0.02 * u, sx: 0, sy: 0}; + }, + takeoff: (u) => ({tx: 0, ty: -0.05, tz: -0.12, az: 64 + 5.5 * u, el: 7, d: 5.3, sx: 0, sy: 0}), + heroEnd: (u) => ({...VIEW_FN.hero(u), d: 4.8 - 0.03 * u}), + // live-only + profile: () => ({tx: 0, ty: 0, tz: -0.25, az: 90, el: 2, d: 5.4, sx: 0, sy: 0}), + inside: () => { + // across the cut through cylinder 2's axis: the piston, the chamber, both valves and both plugs + const a = CYL[1].angle * D2R; + const ur = [-Math.sin(a), Math.cos(a)]; + const ut = [Math.cos(a), Math.sin(a)]; + const dir = [ut[0] * 0.93 + ur[0] * 0.2, ut[1] * 0.93 + ur[1] * 0.2, 0.3]; + const n = Math.hypot(...dir); + return {tx: ur[0] * 0.47, ty: ur[1] * 0.47, tz: 0.105, az: Math.atan2(dir[0] / n, dir[2] / n) / D2R, el: Math.asin(dir[1] / n) / D2R, d: 0.95, fov: 34, sx: 0, sy: 0}; + }, +}; +const VIEWS = SCRIPT.filter((e) => e.cam).map((e) => [e.t, e.cam]); +export function blend(a, b, k) { + const o = {}; + for (const key in b) o[key] = key === 'az' ? a.az + wrap180(b.az - a.az) * k : key === 'd' ? Math.exp(Math.log(a.d) + (Math.log(b.d) - Math.log(a.d)) * k) : (a[key] ?? b[key]) + (b[key] - (a[key] ?? b[key])) * k; + return o; +} +export const camAt = (t) => { + let i = 0; + while (i < VIEWS.length - 1 && VIEWS[i + 1][0] <= t) i++; + const view = (k) => VIEW_FN[VIEWS[k][1]](t - VIEWS[k][0]); + const cur = view(i); + if (i === 0) return cur; + const k = ss(VIEWS[i][0], VIEWS[i][0] + 1.6, t); + if (k >= 1) return cur; + return blend(view(i - 1), cur, k); +}; + +// ------------------------------------------------------------ what each view shows: subsystem opacity, cut, rows +const ALL = {case: 1, crank: 1, cyl: 1, valve: 1, ign: 1, air: 1, prop: 1, nose: 1, oil: 1, stand: 1, cowl: 0, baffle: 1}; +export const LOOK = { + hero: {vis: ALL}, + face: {vis: {...ALL, prop: 0.3}}, + faceFull: {vis: ALL}, + heroEnd: {vis: ALL}, + takeoff: {vis: ALL}, + rowcut: {vis: {...ALL, prop: 0, ign: 0, air: 0, valve: 0, baffle: 0, oil: 0, cowl: 0}, cut: 'rowcut', hideRear: 1}, + apart: {vis: {...ALL, case: 0, prop: 0, nose: 0, ign: 0, air: 0, valve: 0, baffle: 0, oil: 0, stand: 0, cyl: 0}, apart: 1}, + cam: {vis: {...ALL, case: 0.12, cyl: 0.3, crank: 0, prop: 0, nose: 0, ign: 0, air: 0, baffle: 0, oil: 0, stand: 0}, hideRear: 1, focusK: 1}, +}; +const lookAt = (name) => LOOK[name] || LOOK.hero; +/** the looks of two views, blended: opacities, the apart offset, the hidden rear row */ +export function blendLook(a, b, k) { + const vis = {}; + for (const g of Object.keys(ALL)) vis[g] = (a.vis[g] ?? 1) + ((b.vis[g] ?? 1) - (a.vis[g] ?? 1)) * k; + return {vis, apart: (a.apart || 0) + ((b.apart || 0) - (a.apart || 0)) * k, hideRear: (a.hideRear || 0) + ((b.hideRear || 0) - (a.hideRear || 0)) * k, cut: k < 0.5 ? a.cut : b.cut, focusK: (a.focusK || 0) + ((b.focusK || 0) - (a.focusK || 0)) * k, focus: a.focusK || b.focusK ? CAM_CYL : 0}; +} +export const lookAtT = (t) => { + let i = 0; + while (i < VIEWS.length - 1 && VIEWS[i + 1][0] <= t) i++; + const cur = lookAt(VIEWS[i][1]); + if (i === 0) return blendLook(cur, cur, 1); + const prev = lookAt(VIEWS[i - 1][1]); + return blendLook(prev, cur, ss(VIEWS[i][0] + 0.1, VIEWS[i][0] + 1.1, t)); +}; + +// ------------------------------------------------------------ the operator's pointer: a click on the button of each beat +const REST = [[860, 520], [720, 430], [900, 560], [760, 380]]; +const SPOT_OF = {face: 'face', faceFull: 'face', rowcut: 'section', apart: 'crank', cam: 'valve', takeoff: 'throttle', heroEnd: 'throttleBack'}; +export function makeCursor(ui, script = SCRIPT) { + const EV = script.filter((e) => e.t > 0).map((e) => ({t: e.t, spot: ui.spots[e.press || SPOT_OF[e.cam]] || ui.spots.hero})); + const WP = [[0, 980, 640]]; + EV.forEach((e, i) => { + WP.push([e.t - 0.16, ...e.spot]); + WP.push([e.t + 0.24, ...e.spot]); + WP.push([e.t + 1.6, ...REST[i % REST.length]]); + }); + WP.sort((a, b) => a[0] - b[0]); + return (t) => { + let i = 0; + while (i < WP.length - 2 && t > WP[i + 1][0]) i++; + const [t0, x0, y0] = WP[i]; + const [t1, x1, y1] = WP[i + 1]; + const k = ss(t0, t1, t); + const len = Math.hypot(x1 - x0, y1 - y0); + const bow = Math.sin(Math.PI * k) * Math.min(24, len * 0.07); + let press = false; + let ring = 0; + let rx = 0; + let ry = 0; + for (const e of EV) { + if (t >= e.t - 0.07 && t < e.t + 0.09) press = true; + if (t >= e.t && t < e.t + 0.55) { + ring = 1 - (t - e.t) / 0.55; + [rx, ry] = e.spot; + } + } + return {x: x0 + (x1 - x0) * k + (len ? (-(y1 - y0) / len) * bow : 0), y: y0 + (y1 - y0) * k + (len ? ((x1 - x0) / len) * bow : 0), press, ring, ringX: rx, ringY: ry}; + }; +} + +// ------------------------------------------------------------ sparks to light: from the last spark of each cylinder +/** + * glow of each chamber, 0..1: lit sparks only, fading over ~0.35 s of screen time and ~100° of crank. When the + * firings come faster than the eye (more than ~12 a second on screen) the lights merge into a steady low glow. + * spark(c) → {t (screen s), th (crank °), lit}; now: screen time; th: crank; fireHzScreen: firings per screen second + */ +export function glowOf(spark, now, th, fireHzScreen) { + const merge = ss(12, 60, fireHzScreen); + return CYL.map((cy) => { + const s = spark(cy.c); + if (!s || !s.lit) return 0.22 * merge; + const age = now - s.t; + const dth = th - s.th; + const g = Math.exp(-Math.max(0, age) / 0.35) * (dth < 110 ? 1 : Math.exp(-(dth - 110) / 50)); + return g * (1 - merge) + 0.22 * merge; + }); +} +/** the propeller's blur: how far a blade turns between two frames */ +export const blurOf = (propRpm, rate, fps = 60) => ss(5, 28, (propRpm * 6 * rate) / fps); +export const phaseOf = (tau) => { + const R = RUN; + if (tau < R.starter) return 'stopped'; + if (tau < R.ign) return 'starter'; + if (tau < R.disengage + 0.6) return 'ignition'; + if (tau < R.climb) return 'idle'; + if (tau < R.climb + R.climbLen + 0.3) return 'climb'; + if (tau < R.back) return 'takeoff'; + if (tau < R.back + R.backLen) return 'back'; + return 'idle'; +}; + +// ------------------------------------------------------------ callouts per view, label spots on the 1600 x 900 layout +export function calloutsFor(view, st, vis) { + const P3 = (v) => st.project(v); + const A = st.eng.A; + const out = []; + const c = (key, at, label, w, o = 1) => { + const [name, sub] = tr(key); + out.push({name, sub, at: P3(at), label, w, o: vis * o}); + }; + if (view === 'hero' || view === 'heroEnd') { + c('cProp', A.blade(), [372, 168], 120); + c('cMagneto', A.magneto(), [372, 300], 140); + c('cHarness', A.harness(), [372, 420], 120); + c('cHead', A.head(), [1232, 150], -130); + c('cFins', A.fins(), [1232, 268], -120); + c('cPushrod', A.pushrod(), [1232, 390], -140); + c('cPipe', A.pipe(), [1232, 520], -110); + } else if (view === 'face' || view === 'faceFull') { + c('cStarFront', A.cylAt(2, 560), [372, 200], 160); + c('cStarRear', A.cylAt(5, 560), [372, 610], 160); + c('cNose', A.nose(), [1232, 200], -140); + } else if (view === 'rowcut') { + c('cMaster', A.master('front'), [372, 200], 150); + c('cArt', A.art('front', 12), [1232, 230], -150); + c('cKnuckle', A.pin('front'), [372, 610], 170); + c('cPiston', A.piston(2), [1232, 560], -150); + } else if (view === 'apart') { + c('cPinRear', A.pin('rear'), [372, 220], 150); + c('cPinFront', A.pin('front'), [372, 600], 150); + c('cRows', A.piston(1), [1232, 220], -140); + } else if (view === 'cam') { + c('cCam', A.camRing('front'), [372, 610], 160); + c('cTappet', A.tappet(CAM_CYL, 'in'), [372, 320], 160); + c('cRocker', A.rocker(CAM_CYL, 'in'), [1232, 200], -150); + c('cValve', A.valve(CAM_CYL, 'in'), [1232, 470], -150); + } else if (view === 'takeoff') { + c('cSuper', A.impeller(), [1232, 640], -140); + c('cCarb', A.carb(), [1232, 190], -150); + c('cGear', A.nose(), [372, 190], 130); + c('cStarter', A.starter(), [1232, 470], -130); + } + return out; +} +export const CTX_OF = {hero: 'run', heroEnd: 'run', face: 'ign', faceFull: 'takeoff', rowcut: 'law', apart: 'throws', cam: 'cam', takeoff: 'takeoff'}; +export const BTN_OF = {hero: 'hero', heroEnd: 'hero', face: 'face', faceFull: 'face', rowcut: 'face', apart: 'hero', cam: 'hero', takeoff: 'profile'}; +export const SUB_OF = {rowcut: 'crank', apart: 'crank', cam: 'valve', face: 'ign'}; + +/** one frame of everything from the crank angle and the run's state. Shared by the film and the live tour. */ +export function engineFrame({th, N, run, rate, spark, now}) { + const s = stateAt(N, run); + const fireScreen = s.fireHz * rate; + const lit = glowOf(spark, now, th, fireScreen); + return {s, lit, blur: blurOf(s.propRpm, rate)}; +} + +// ------------------------------------------------------------ the film +export function makeFilm() { + return async ({canvas, capture}) => { + await loadFonts(); + const st = createStage({canvas}); + const resize = () => st.resize(1600, 900, capture ? devicePixelRatio || 1 : Math.min(devicePixelRatio || 1, 2)); + resize(); + const ui = createConsole(document.getElementById('app')); + const cursorAt = makeCursor(ui); + if (window.__SIM_CONFIG?.clean) ui.root.style.display = 'none'; + window.R2800 = {st}; + return { + resize, + render(t) { + const th = thetaAt(t); + const tau = tauAt(t); + const N = rpmAt(t); + const run = runAtTau(tau); + const rate = rateAt(t); + const {s, lit, blur} = engineFrame({th, N, run, rate, spark: (c) => lastSpark(c, t), now: t}); + const view = camAtName(t); + const since = camSince(t); + const look = lookAtT(t); + st.setCut(look.cut ? 'section' : 'solid', look.cut || 'profile'); + const camHi = look.focusK > 0.5 ? CYL.map((cy) => (cy.c === CAM_CYL ? {in: lift(cy.c, 'in', th), ex: lift(cy.c, 'ex', th)} : {in: 0, ex: 0})) : null; + const fx = {th, vis: look.vis, apart: look.apart, hideRear: look.hideRear, focus: look.focus, focusK: look.focusK, glow: lit, headGlow: lit.map((g) => g * 0.85 * (1 - look.focusK)), blur, camHi, air: airAt(t), airK: 0, oil: th / 1440, oilK: 0}; + const c = camAt(t); + st.frame(fx, {...c, az: c.az * D2R, el: c.el * D2R}); + const phase = phaseOf(tau); + ui.update({ + ...s, + th, + lit, + rate, + phase, + starter: starterAtTau(tau) > 0, + ignition: tau >= RUN.ign, + thrRpm: N, + ctx: CTX_OF[view] || 'run', + ctxArg: view === 'cam' ? 0 + CAM_CYL : view === 'rowcut' ? 'front' : undefined, + sub: SUB_OF[view] || '', + cut: look.cut ? 'section' : 'solid', + camBtn: BTN_OF[view], + layers: {cowl: false, callouts: true}, + caption: tr('cap:' + (view === 'hero' && phase !== 'stopped' ? phase : view)), + callouts: calloutsFor(view, st, ss(1.2, 2.0, since) * (view === 'hero' && t > 1.5 ? 1 - ss(1.5, 2.0, t) : 1)), + cursor: cursorAt(t), + }); + return {}; + }, + }; + }; +} +void E; +export const run = () => runSim(DEFAULTS, makeFilm()); diff --git a/machines/radial/r2800-shared/fonts.js b/machines/radial/r2800-shared/fonts.js new file mode 100644 index 0000000..a533605 --- /dev/null +++ b/machines/radial/r2800-shared/fonts.js @@ -0,0 +1,24 @@ +// Radial's own type, inlined (latin subsets, SIL Open Font License): Barlow Condensed, a condensed grotesque in the +// spirit of the period's technical manuals, and Saira Stencil One for the title, the stencil of a crate or a cowling. +// Both builds (the skill's and the site's) load .woff2 as base64. +import b500 from '@fontsource/barlow-condensed/files/barlow-condensed-latin-500-normal.woff2'; +import b700 from '@fontsource/barlow-condensed/files/barlow-condensed-latin-700-normal.woff2'; +import stencil from '@fontsource/saira-stencil-one/files/saira-stencil-one-latin-400-normal.woff2'; + +export const FONT = {cond: "'Barlow Condensed', 'Arial Narrow', sans-serif", stencil: "'Saira Stencil One', 'Barlow Condensed', sans-serif"}; + +let ready = null; +/** registers the faces and resolves when they are usable (the first frame waits on it) */ +export function loadFonts() { + if (ready) return ready; + const face = (family, b64, weight) => { + const bin = atob(b64); + const buf = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) buf[i] = bin.charCodeAt(i); + const f = new FontFace(family, buf, {weight: String(weight), display: 'block'}); + document.fonts.add(f); + return f.load(); + }; + ready = Promise.all([face('Barlow Condensed', b500, 500), face('Barlow Condensed', b700, 700), face('Saira Stencil One', stencil, 400)]).catch(() => {}); + return ready; +} diff --git a/machines/radial/r2800-shared/i18n.js b/machines/radial/r2800-shared/i18n.js new file mode 100644 index 0000000..3ef65c1 --- /dev/null +++ b/machines/radial/r2800-shared/i18n.js @@ -0,0 +1,220 @@ +// Every word on screen, in English (the default), French and Spanish. The language itself, the number format and the +// strings of the page's header and footer are shared by the collection (../../../shared/i18n.js). +import {LANG, LANGS, makeT, nf} from '../../../shared/i18n.js'; + +export {LANG, LANGS, nf}; + +const S = { + // ------------------------------------------------------------ title + subtitle: {en: 'PRATT & WHITNEY R-2800 DOUBLE WASP', fr: 'PRATT & WHITNEY R-2800 DOUBLE WASP', es: 'PRATT & WHITNEY R-2800 DOUBLE WASP'}, + model: { + en: '18 cylinders, two rows · a C-series CB16 after public sources · not affiliated with P&W', + fr: '18 cylindres, deux rangées · un CB16 de série C d’après les sources publiques · sans lien avec P&W', + es: '18 cilindros, dos filas · un CB16 de la serie C según fuentes públicas · sin relación con P&W', + }, + fig: {en: (n) => `FIG. ${n}`, fr: (n) => `FIG. ${n}`, es: (n) => `FIG. ${n}`}, + // ------------------------------------------------------------ instruments + figInstr: {en: 'Instruments', fr: 'Instruments', es: 'Instrumentos'}, + dRpm: {en: 'RPM', fr: 'TR/MIN', es: 'RPM'}, + dRpmU: {en: '× 100', fr: '× 100', es: '× 100'}, + dMap: {en: 'MANIFOLD', fr: 'ADMISSION', es: 'ADMISIÓN'}, + dHp: {en: 'POWER', fr: 'PUISSANCE', es: 'POTENCIA'}, + rTorque: {en: 'Crank torque', fr: 'Couple au vilebrequin', es: 'Par en el cigüeñal'}, + rPiston: {en: 'Mean piston speed', fr: 'Vitesse moyenne de piston', es: 'Velocidad media del pistón'}, + rFire: {en: 'Firings', fr: 'Allumages', es: 'Encendidos'}, + rFireV: {en: (h) => `${h} per second`, fr: (h) => `${h} par seconde`, es: (h) => `${h} por segundo`}, + rProp: {en: 'Propeller · impeller rpm', fr: 'Hélice · rouet, tr/min', es: 'Hélice · rodete, rpm'}, + // ------------------------------------------------------------ data plate + figData: {en: 'Engine data', fr: 'Caractéristiques', es: 'Datos del motor'}, + pBore: {en: 'Bore × stroke', fr: 'Alésage × course', es: 'Diámetro × carrera'}, + pDispl: {en: 'Displacement', fr: 'Cylindrée', es: 'Cilindrada'}, + pCr: {en: 'Compression', fr: 'Compression', es: 'Compresión'}, + pTo: {en: 'Take-off, dry', fr: 'Décollage, sec', es: 'Despegue, seco'}, + pWet: {en: 'Take-off, wet', fr: 'Décollage, injection', es: 'Despegue, inyección'}, + pRed: {en: 'Propeller gear', fr: 'Réducteur', es: 'Reductora'}, + pSc: {en: 'Supercharger', fr: 'Compresseur', es: 'Compresor'}, + pScV: {en: (a, b) => `1 stage, ${a} / ${b} : 1`, fr: (a, b) => `1 étage, ${a} / ${b} : 1`, es: (a, b) => `1 etapa, ${a} / ${b} : 1`}, + pMass: {en: 'Dry weight', fr: 'Masse à sec', es: 'Peso en seco'}, + pCam: {en: 'Valves', fr: 'Distribution', es: 'Distribución'}, + pCamV: {en: '2 cam rings, 4 lobes', fr: '2 anneaux à cames, 4 lobes', es: '2 anillos de levas, 4 lóbulos'}, + pIgn: {en: 'Ignition', fr: 'Allumage', es: 'Encendido'}, + pIgnV: {en: '2 magnetos, 36 plugs', fr: '2 magnétos, 36 bougies', es: '2 magnetos, 36 bujías'}, + // ------------------------------------------------------------ the run + figRun: {en: 'The run', fr: 'La marche', es: 'La marcha'}, + 'ph:stopped': {en: 'STOPPED', fr: 'À L’ARRÊT', es: 'PARADO'}, + 'ph:starter': {en: 'STARTER', fr: 'DÉMARREUR', es: 'ARRANQUE'}, + 'ph:ignition': {en: 'IGNITION', fr: 'ALLUMAGE', es: 'ENCENDIDO'}, + 'ph:idle': {en: 'IDLE', fr: 'RALENTI', es: 'RALENTÍ'}, + 'ph:climb': {en: 'THROTTLE OPEN', fr: 'PLEIN GAZ', es: 'GASES A FONDO'}, + 'ph:takeoff': {en: 'TAKE-OFF RPM', fr: 'RÉGIME DÉCOLLAGE', es: 'RÉGIMEN DE DESPEGUE'}, + 'ph:back': {en: 'THROTTLE BACK', fr: 'RÉDUCTION', es: 'REDUCCIÓN'}, + slow: {en: (ms, x) => `1 s on screen = ${ms} ms · slowed ×${x}`, fr: (ms, x) => `1 s à l’écran = ${ms} ms · ralenti ×${x}`, es: (ms, x) => `1 s en pantalla = ${ms} ms · ralentizado ×${x}`}, + realtime: {en: 'Real time', fr: 'Temps réel', es: 'Tiempo real'}, + bStarter: {en: 'Starter', fr: 'Démarreur', es: 'Arranque'}, + bIgnition: {en: 'Magnetos', fr: 'Magnétos', es: 'Magnetos'}, + pause: {en: 'Pause', fr: 'Pause', es: 'Pausa'}, + bSlow: {en: 'Slow-mo', fr: 'Ralenti', es: 'Lento'}, + throttle: {en: 'THROTTLE · TARGET RPM', fr: 'MANETTE · RÉGIME VISÉ', es: 'ACELERADOR · RÉGIMEN'}, + rpmShort: {en: 'rpm', fr: 'tr/min', es: 'rpm'}, + // ------------------------------------------------------------ the star + figStar: {en: 'Firing order', fr: 'Ordre d’allumage', es: 'Orden de encendido'}, + starSub: {en: 'SEEN FROM THE FRONT · 1 AT THE TOP OF THE REAR ROW', fr: 'VU DE FACE · 1 EN HAUT DE LA RANGÉE ARRIÈRE', es: 'VISTO DE FRENTE · 1 ARRIBA EN LA FILA TRASERA'}, + starKey: {en: 'INSIDE: REAR ROW (ODD) · OUTSIDE: FRONT ROW (EVEN)', fr: 'DEDANS : ARRIÈRE (IMPAIRS) · DEHORS : AVANT (PAIRS)', es: 'DENTRO: TRASERA (IMPARES) · FUERA: DELANTERA (PARES)'}, + starFoot: {en: (h) => `+11, −7 · every 40° · 18 in 2 turns · ${h} /s`, fr: (h) => `+11, −7 · tous les 40° · 18 en 2 tours · ${h} /s`, es: (h) => `+11, −7 · cada 40° · 18 en 2 vueltas · ${h} /s`}, + // ------------------------------------------------------------ the context figure + 'ctx:run': {en: 'The engine', fr: 'Le moteur', es: 'El motor'}, + 'ctxTxt:run': { + en: 'Two rows of nine cylinders, 20° apart, on one two-throw crankshaft. Each row drives its crankpin through one master rod and eight articulated rods.', + fr: 'Deux rangées de neuf cylindres décalées de 20°, sur un vilebrequin à deux manetons. Chaque rangée attaque son maneton par une bielle maîtresse et huit biellettes.', + es: 'Dos filas de nueve cilindros desfasadas 20°, sobre un cigüeñal de dos codos. Cada fila mueve su muñequilla con una biela maestra y ocho bielas articuladas.', + }, + 'ctx:ign': {en: 'Ignition', fr: 'Allumage', es: 'Encendido'}, + ignTxt: { + en: 'Two magnetos, each firing one of the two plugs in every cylinder: 36 plugs. The spark comes 25° before top centre (est.); the distributors turn at half crank speed.', + fr: 'Deux magnétos, chacune allume une des deux bougies de chaque cylindre : 36 bougies. L’étincelle jaillit 25° avant le point mort haut (estim.) ; les distributeurs tournent à mi-régime.', + es: 'Dos magnetos, cada uno enciende una de las dos bujías de cada cilindro: 36 bujías. La chispa salta 25° antes del punto muerto superior (est.); los distribuidores giran a media velocidad.', + }, + 'ctx:law': {en: 'Master and articulated', fr: 'Maîtresse et biellette', es: 'Maestra y articulada'}, + lawX: {en: 'CRANK °', fr: 'VILEBREQUIN °', es: 'CIGÜEÑAL °'}, + lawY: {en: 'DIFFERENCE, MM', fr: 'ÉCART, MM', es: 'DIFERENCIA, MM'}, + lawTxt: { + en: (m, a, sm, sa, lag, dz, cm, ca, late) => `Stroke ${sm} mm (master, ${m}) vs ${sa} mm (${a}). Its top centre comes ${lag}° ${late ? 'late' : 'early'} and ${dz} mm lower: compression ${cm} vs ${ca}.`, + fr: (m, a, sm, sa, lag, dz, cm, ca, late) => `Course ${sm} mm (maîtresse, ${m}) contre ${sa} mm (${a}). Son PMH arrive ${lag}° ${late ? 'plus tard' : 'plus tôt'} et ${dz} mm plus bas : compression ${cm} contre ${ca}.`, + es: (m, a, sm, sa, lag, dz, cm, ca, late) => `Carrera ${sm} mm (maestra, ${m}) frente a ${sa} mm (${a}). Su PMS llega ${lag}° ${late ? 'más tarde' : 'antes'} y ${dz} mm más abajo: compresión ${cm} frente a ${ca}.`, + }, + 'ctx:throws': {en: 'Two throws at 180°', fr: 'Deux manetons à 180°', es: 'Dos codos a 180°'}, + throwKey: {en: 'SEEN FROM THE FRONT', fr: 'VU DE FACE', es: 'VISTO DE FRENTE'}, + throwA: {en: 'REAR ROW PIN', fr: 'MANETON ARRIÈRE', es: 'MUÑEQUILLA TRASERA'}, + throwA2: {en: 'cylinders 1, 3, 5 … 17', fr: 'cylindres 1, 3, 5 … 17', es: 'cilindros 1, 3, 5 … 17'}, + throwB: {en: 'FRONT ROW PIN', fr: 'MANETON AVANT', es: 'MUÑEQUILLA DELANTERA'}, + throwB2: {en: 'cylinders 2, 4, 6 … 18', fr: 'cylindres 2, 4, 6 … 18', es: 'cilindros 2, 4, 6 … 18'}, + throwTxt: { + en: 'The rows are turned 20° and their pins 180°: the firings alternate row to row, 40° apart, so no row fires twice in a row.', + fr: 'Les rangées sont décalées de 20° et leurs manetons de 180° : les allumages alternent d’une rangée à l’autre, tous les 40°.', + es: 'Las filas están desfasadas 20° y sus muñequillas 180°: los encendidos alternan de fila en fila, cada 40°.', + }, + 'ctx:cam': {en: 'Cam ring', fr: 'Anneau à cames', es: 'Anillo de levas'}, + camX: {en: 'CRANK ° AFTER FIRING', fr: 'VILEBREQUIN ° APRÈS ALLUMAGE', es: 'CIGÜEÑAL ° TRAS ENCENDIDO'}, + camY: {en: 'LIFT', fr: 'LEVÉE', es: 'ALZADA'}, + 'st:power': {en: 'POWER', fr: 'DÉTENTE', es: 'EXPANSIÓN'}, + 'st:exhaust': {en: 'EXHAUST', fr: 'ÉCHAPPEMENT', es: 'ESCAPE'}, + 'st:intake': {en: 'INTAKE', fr: 'ADMISSION', es: 'ADMISIÓN'}, + 'st:compression': {en: 'COMPRESSION', fr: 'COMPRESSION', es: 'COMPRESIÓN'}, + camTxt: { + en: (c, n, L, li, le) => `Cylinder ${c}. ${n} lobes per track, the ring at ⅛ crank speed, against it. Inlet ${li} mm, exhaust ${le} mm of ${L} (est.).`, + fr: (c, n, L, li, le) => `Cylindre ${c}. ${n} lobes par piste, l’anneau à ⅛ du régime, en sens inverse. Admission ${li} mm, échappement ${le} mm sur ${L} (estim.).`, + es: (c, n, L, li, le) => `Cilindro ${c}. ${n} lóbulos por pista, el anillo a ⅛ de la velocidad, en sentido contrario. Admisión ${li} mm, escape ${le} mm de ${L} (est.).`, + }, + 'ctx:takeoff': {en: 'Power and torque', fr: 'Puissance et couple', es: 'Potencia y par'}, + toX: {en: 'RPM', fr: 'TR/MIN', es: 'RPM'}, + toY: {en: 'HP · TORQUE (DASHED)', fr: 'CH · COUPLE (TIRETS)', es: 'CV · PAR (TRAZOS)'}, + toTxt: { + en: (hp, n, map, tq) => `${hp} hp at ${n} rpm and ${map} inHg, ${tq} N·m. The FAA rates the CB16 at 2,050 hp, 2,700 rpm, 55.0″ (circle).`, + fr: (hp, n, map, tq) => `${hp} ch à ${n} tr/min et ${map} inHg, ${tq} N·m. La FAA donne au CB16 2 050 ch, 2 700 tr/min, 55,0″ (cercle).`, + es: (hp, n, map, tq) => `${hp} CV a ${n} rpm y ${map} inHg, ${tq} N·m. La FAA certifica el CB16 a 2050 CV, 2700 rpm, 55,0″ (círculo).`, + }, + 'ctx:cyl': {en: 'Cylinders and fins', fr: 'Cylindres et ailettes', es: 'Cilindros y aletas'}, + 'ctxTxt:cyl': { + en: 'Steel barrels under finned aluminium muffs, forged aluminium heads with fins cut from the solid. Black baffles force the air through the fins.', + fr: 'Fûts en acier sous des manchons d’aluminium à ailettes, culasses en aluminium forgé aux ailettes taillées dans la masse. Les déflecteurs noirs forcent l’air entre les ailettes.', + es: 'Camisas de acero bajo manguitos de aluminio con aletas, culatas de aluminio forjado con aletas talladas en la masa. Los deflectores negros obligan al aire a pasar por las aletas.', + }, + 'ctx:air': {en: 'Supercharger', fr: 'Compresseur', es: 'Compresor'}, + 'ctxTxt:air': { + en: 'The carburettor feeds the impeller’s eye; the impeller (7.29 × crank speed) throws the charge into the diffuser and out through 18 pipes, one per cylinder.', + fr: 'Le carburateur alimente l’ouïe du rouet ; le rouet (7,29 × le régime) projette le mélange dans le diffuseur puis dans 18 pipes, une par cylindre.', + es: 'El carburador alimenta el ojo del rodete; el rodete (7,29 × el régimen) lanza la mezcla al difusor y a 18 tubos, uno por cilindro.', + }, + 'ctx:prop': {en: 'Reduction gear', fr: 'Réducteur', es: 'Reductora'}, + 'ctxTxt:prop': { + en: 'A planetary gear in the nose: the sun on the crankshaft, the ring fixed, the carrier on the propeller shaft. 0.45 turn of the propeller per turn of the crank.', + fr: 'Un train planétaire dans le nez : le planétaire sur le vilebrequin, la couronne fixe, le porte-satellites sur l’arbre d’hélice. 0,45 tour d’hélice par tour de vilebrequin.', + es: 'Un tren planetario en el morro: el planeta en el cigüeñal, la corona fija, el portasatélites en el eje de la hélice. 0,45 vueltas de hélice por vuelta de cigüeñal.', + }, + 'ctx:oil': {en: 'Lubrication', fr: 'Lubrification', es: 'Lubricación'}, + 'ctxTxt:oil': { + en: 'Dry sump: the pressure pump at the rear feeds the crankshaft through its journals and drillings to the crankpins and knuckle pins; scavenge pumps return the oil to the tank.', + fr: 'Carter sec : la pompe de pression, à l’arrière, alimente le vilebrequin par ses tourillons et ses perçages jusqu’aux manetons et aux axes de biellettes ; les pompes de récupération renvoient l’huile au réservoir.', + es: 'Cárter seco: la bomba de presión, atrás, alimenta el cigüeñal por sus apoyos y taladros hasta las muñequillas y los bulones; las bombas de recuperación devuelven el aceite al depósito.', + }, + // ------------------------------------------------------------ buttons + grpSub: {en: 'SUBSYSTEMS', fr: 'SOUS-ENSEMBLES', es: 'SUBSISTEMAS'}, + grpCut: {en: 'CUTAWAY', fr: 'COUPE', es: 'CORTE'}, + grpView: {en: 'VIEW', fr: 'VUE', es: 'VISTA'}, + grpLayer: {en: 'LAYERS', fr: 'CALQUES', es: 'CAPAS'}, + 'sub:crank': {en: 'Rods & crank', fr: 'Embiellage', es: 'Bielas y cigüeñal'}, + 'sub:cyl': {en: 'Cylinders & fins', fr: 'Cylindres & ailettes', es: 'Cilindros y aletas'}, + 'sub:valve': {en: 'Cam rings', fr: 'Distribution', es: 'Distribución'}, + 'sub:ign': {en: 'Ignition', fr: 'Allumage', es: 'Encendido'}, + 'sub:air': {en: 'Supercharger', fr: 'Compresseur', es: 'Compresor'}, + 'sub:prop': {en: 'Gear & propeller', fr: 'Réducteur & hélice', es: 'Reductora y hélice'}, + 'sub:oil': {en: 'Lubrication', fr: 'Lubrification', es: 'Lubricación'}, + 'cut:glass': {en: 'Glass', fr: 'Verre', es: 'Cristal'}, + 'cut:section': {en: 'Section', fr: 'Section', es: 'Sección'}, + 'cut:solid': {en: 'Solid', fr: 'Pleine', es: 'Sólido'}, + 'cam:face': {en: 'Face', fr: 'Face', es: 'Frente'}, + 'cam:hero': {en: '¾ front', fr: '¾ avant', es: '¾ frontal'}, + 'cam:profile': {en: 'Profile', fr: 'Profil', es: 'Perfil'}, + 'cam:inside': {en: 'Inside', fr: 'Intérieur', es: 'Interior'}, + 'lay:cowl': {en: 'Cowling', fr: 'Capot', es: 'Capó'}, + 'lay:callouts': {en: 'Labels', fr: 'Légendes', es: 'Rótulos'}, + // ------------------------------------------------------------ captions + 'cap:hero': {en: 'On its run-up stand, propeller stopped', fr: 'Sur son banc d’essai, hélice arrêtée', es: 'En su banco de pruebas, hélice parada'}, + 'cap:stopped': {en: 'On its run-up stand, propeller stopped', fr: 'Sur son banc d’essai, hélice arrêtée', es: 'En su banco de pruebas, hélice parada'}, + 'cap:starter': {en: 'The starter turns the crank, no spark yet', fr: 'Le démarreur entraîne le vilebrequin, pas encore d’étincelle', es: 'El arranque gira el cigüeñal, aún sin chispa'}, + 'cap:ignition': {en: 'Magnetos on: the first firings miss, then catch', fr: 'Magnétos en marche : les premiers allumages ratent, puis prennent', es: 'Magnetos activos: los primeros encendidos fallan y luego prenden'}, + 'cap:idle': {en: 'Running on its own', fr: 'Il tourne seul', es: 'Gira solo'}, + 'cap:face': {en: 'Idle, from the front: the firing order goes round the star', fr: 'Ralenti, de face : l’ordre d’allumage parcourt l’étoile', es: 'Ralentí, de frente: el orden de encendido recorre la estrella'}, + 'cap:rowcut': {en: 'One row in section: a master rod and eight articulated rods', fr: 'Une rangée en coupe : une bielle maîtresse et huit biellettes', es: 'Una fila en sección: una biela maestra y ocho articuladas'}, + 'cap:apart': {en: 'The rows pulled apart: turned 20°, pins at 180°', fr: 'Les rangées écartées : décalées de 20°, manetons à 180°', es: 'Las filas separadas: desfasadas 20°, muñequillas a 180°'}, + 'cap:cam': {en: 'A cam ring lifts a valve, no camshaft', fr: 'Un anneau à cames lève une soupape, sans arbre à cames', es: 'Un anillo de levas abre una válvula, sin árbol de levas'}, + 'cap:takeoff': {en: 'Throttle open: to 2,700 rpm in real time', fr: 'Plein gaz : jusqu’à 2 700 tr/min en temps réel', es: 'Gases a fondo: hasta 2700 rpm en tiempo real'}, + 'cap:faceFull': {en: 'Take-off rpm: 2,050 hp, 405 firings a second', fr: 'Régime décollage : 2 050 ch, 405 allumages par seconde', es: 'Régimen de despegue: 2050 CV, 405 encendidos por segundo'}, + 'cap:heroEnd': {en: 'Throttle back to idle', fr: 'Retour au ralenti', es: 'Vuelta al ralentí'}, + 'cap:live': {en: '', fr: '', es: ''}, + // ------------------------------------------------------------ callouts [name, sub] + cProp: {en: ['Propeller', '3 BLADES · 0.45 × CRANK SPEED'], fr: ['Hélice', '3 PALES · 0,45 × LE RÉGIME'], es: ['Hélice', '3 PALAS · 0,45 × EL RÉGIMEN']}, + cMagneto: {en: ['Magneto', '2 ON THE NOSE · ONE PLUG EACH'], fr: ['Magnéto', '2 SUR LE NEZ · UNE BOUGIE CHACUNE'], es: ['Magneto', '2 EN EL MORRO · UNA BUJÍA CADA UNO']}, + cHarness: {en: ['Ignition harness', 'BRAIDED · 36 LEADS'], fr: ['Faisceau d’allumage', 'TRESSÉ · 36 FILS'], es: ['Arnés de encendido', 'TRENZADO · 36 CABLES']}, + cHead: {en: ['Cylinder head', 'FORGED ALUMINIUM · 2 VALVES'], fr: ['Culasse', 'ALUMINIUM FORGÉ · 2 SOUPAPES'], es: ['Culata', 'ALUMINIO FORJADO · 2 VÁLVULAS']}, + cFins: {en: ['Barrel fins', 'ALUMINIUM MUFF ON STEEL'], fr: ['Ailettes du fût', 'MANCHON ALU SUR ACIER'], es: ['Aletas de la camisa', 'MANGUITO DE ALUMINIO SOBRE ACERO']}, + cPushrod: {en: ['Pushrod tubes', 'FROM THE CAM RING'], fr: ['Tubes de culbuteurs', 'DEPUIS L’ANNEAU À CAMES'], es: ['Tubos de varillas', 'DESDE EL ANILLO DE LEVAS']}, + cPipe: {en: ['Intake pipe', '18 FROM THE SUPERCHARGER'], fr: ['Pipe d’admission', '18 DEPUIS LE COMPRESSEUR'], es: ['Tubo de admisión', '18 DESDE EL COMPRESOR']}, + cStarFront: {en: ['Front row', 'EVEN NUMBERS · 9 CYLINDERS'], fr: ['Rangée avant', 'NUMÉROS PAIRS · 9 CYLINDRES'], es: ['Fila delantera', 'NÚMEROS PARES · 9 CILINDROS']}, + cStarRear: {en: ['Rear row', 'ODD NUMBERS · TURNED 20°'], fr: ['Rangée arrière', 'NUMÉROS IMPAIRS · DÉCALÉE DE 20°'], es: ['Fila trasera', 'NÚMEROS IMPARES · DESFASADA 20°']}, + cNose: {en: ['Nose case', 'REDUCTION GEAR INSIDE'], fr: ['Carter de nez', 'LE RÉDUCTEUR DEDANS'], es: ['Cárter del morro', 'LA REDUCTORA DENTRO']}, + cMaster: {en: ['Master rod', 'ONE PIECE · ON THE CRANKPIN'], fr: ['Bielle maîtresse', 'MONOBLOC · SUR LE MANETON'], es: ['Biela maestra', 'DE UNA PIEZA · EN LA MUÑEQUILLA']}, + cArt: {en: ['Articulated rod', '8 PER ROW · ON KNUCKLE PINS'], fr: ['Biellette', '8 PAR RANGÉE · SUR AXES'], es: ['Biela articulada', '8 POR FILA · EN BULONES']}, + cKnuckle: {en: ['Crankpin', 'r = 76.2 MM · HALF THE STROKE'], fr: ['Maneton', 'r = 76,2 MM · LA DEMI-COURSE'], es: ['Muñequilla', 'r = 76,2 MM · MEDIA CARRERA']}, + cPiston: {en: ['Piston', 'BORE 146 MM'], fr: ['Piston', 'ALÉSAGE 146 MM'], es: ['Pistón', 'DIÁMETRO 146 MM']}, + cPinRear: {en: ['Rear crankpin', 'ROW 1, 3, 5 …'], fr: ['Maneton arrière', 'RANGÉE 1, 3, 5 …'], es: ['Muñequilla trasera', 'FILA 1, 3, 5 …']}, + cPinFront: {en: ['Front crankpin', '180° AWAY'], fr: ['Maneton avant', 'À 180°'], es: ['Muñequilla delantera', 'A 180°']}, + cRows: {en: ['Two rows of nine', 'THE CRANK IS SPLIT AT THE PINS'], fr: ['Deux rangées de neuf', 'VILEBREQUIN EN PIÈCES AUX MANETONS'], es: ['Dos filas de nueve', 'CIGÜEÑAL PARTIDO EN LAS MUÑEQUILLAS']}, + cCam: {en: ['Cam ring', '4 LOBES · ⅛ CRANK SPEED, REVERSED'], fr: ['Anneau à cames', '4 LOBES · ⅛ DU RÉGIME, INVERSE'], es: ['Anillo de levas', '4 LÓBULOS · ⅛ DEL RÉGIMEN, INVERSO']}, + cTappet: {en: ['Tappet', 'RIDES THE LOBE'], fr: ['Poussoir', 'SUIT LE LOBE'], es: ['Taqué', 'SIGUE EL LÓBULO']}, + cRocker: {en: ['Rocker', 'IN ITS BOX ON THE HEAD'], fr: ['Culbuteur', 'DANS SA BOÎTE SUR LA CULASSE'], es: ['Balancín', 'EN SU CAJA SOBRE LA CULATA']}, + cValve: {en: ['Inlet valve', 'OPENS 20° BEFORE TOP CENTRE'], fr: ['Soupape d’admission', 'OUVRE 20° AVANT LE PMH'], es: ['Válvula de admisión', 'ABRE 20° ANTES DEL PMS']}, + cSuper: {en: ['Supercharger', '1 STAGE · 7.29 × CRANK'], fr: ['Compresseur', '1 ÉTAGE · 7,29 × LE RÉGIME'], es: ['Compresor', '1 ETAPA · 7,29 × EL RÉGIMEN']}, + cCarb: {en: ['Carburettor', 'PRESSURE TYPE'], fr: ['Carburateur', 'À INJECTION'], es: ['Carburador', 'DE PRESIÓN']}, + cGear: {en: ['Reduction gear', '0.45 : 1'], fr: ['Réducteur', '0,45 : 1'], es: ['Reductora', '0,45 : 1']}, + cStarter: {en: ['Starter', 'AT THE REAR'], fr: ['Démarreur', 'À L’ARRIÈRE'], es: ['Arranque', 'ATRÁS']}, + cOilPump: {en: ['Oil pump', 'DRY SUMP'], fr: ['Pompe à huile', 'CARTER SEC'], es: ['Bomba de aceite', 'CÁRTER SECO']}, + cBaffle: {en: ['Baffles', 'FORCE THE AIR THROUGH THE FINS'], fr: ['Déflecteurs', 'FORCENT L’AIR ENTRE LES AILETTES'], es: ['Deflectores', 'OBLIGAN AL AIRE A PASAR']}, + cCowl: {en: ['Cowling', 'NACA RING'], fr: ['Capot', 'ANNEAU NACA'], es: ['Capó', 'ANILLO NACA']}, + // ------------------------------------------------------------ the live page + tourOn: {en: 'AUTO TOUR · CLICK TO TAKE OVER', fr: 'VISITE AUTO · CLIQUER POUR PRENDRE LA MAIN', es: 'VISITA AUTOMÁTICA · CLIC PARA TOMAR EL CONTROL'}, + tourOff: {en: '▶ RESUME THE TOUR', fr: '▶ REPRENDRE LA VISITE', es: '▶ REANUDAR LA VISITA'}, + turnPhone: {en: 'Turn your phone sideways for the full console', fr: 'Tournez le téléphone pour la console complète', es: 'Gira el teléfono para ver la consola completa'}, + slowmo: {en: 'SLOW MOTION', fr: 'RALENTI', es: 'CÁMARA LENTA'}, + docTitle: {en: 'Radial · the R-2800 Double Wasp, taken apart', fr: 'Radial · le R-2800 Double Wasp, démonté', es: 'Radial · el R-2800 Double Wasp, desmontado'}, + footCredit: { + en: 'A C-series R-2800 after public sources, not affiliated with Pratt & Whitney', + fr: 'Un R-2800 de série C d’après les sources publiques, sans lien avec Pratt & Whitney', + es: 'Un R-2800 de la serie C según fuentes públicas, sin relación con Pratt & Whitney', + }, +}; + +/** the string for key in the page's language; extra arguments fill a templated one */ +export const T = makeT(S); +export const KEYS = Object.keys(S); +export const DICT = S; diff --git a/machines/radial/r2800-shared/live.js b/machines/radial/r2800-shared/live.js new file mode 100644 index 0000000..d659de6 --- /dev/null +++ b/machines/radial/r2800-shared/live.js @@ -0,0 +1,510 @@ +// Radial as a page you drive: the film's engine and overlay, run in real time. The starter, the magnetos and the +// throttle drive the one input (the crank angle, integrated from the engine speed each frame); slow motion, pause, +// the seven subsystems, the cutaways (glass, section, solid), four views, the cowling, orbit and zoom, H to hide the +// overlay. Left alone it plays the film's script as an auto tour with the operator's cursor, looped; a click, drag, +// wheel or key hands control to the visitor, with the engine as the tour left it; 25 s of quiet hands it back. +import {warmComposer} from 'teardown-kit/warm.js'; +import {CAMS, createConsole, CUTS, LAYERS, SUBS} from './console.js'; +import {CYL, FIRE, lift, ORDER, RATING, SPARK_ADV} from './engine.js'; +import {calloutsFor, CAM_CYL, camAt, CTX_OF, engineFrame, lookAtT, makeCursor, phaseOf, smoother, ss, SUB_OF, BTN_OF, VIEW_FN, blendLook, LOOK} from './film.js'; +import {loadFonts} from './fonts.js'; +import {airAt, camAtName, camSince, DURATION, lastSpark, rateAt, rpmAt, RUN, runAtTau, SCRIPT, starterAtTau, tauAt, thetaAt} from './schedule.js'; +import {createStage} from './stage.js'; +import {createChrome} from '../../../shared/chrome.js'; +import {LANG, T as tr} from './i18n.js'; + +const W = 1600; +const H = 900; +const IDLE = 25; +const D2R = Math.PI / 180; +const clamp = (x, a, b) => Math.min(b, Math.max(a, x)); +const wrap = (d) => ((((d + 180) % 360) + 360) % 360) - 180; +const RATES = [1, 1 / 4, 1 / 10, 1 / 25, 1 / 40]; +// what each subsystem button shows: its own parts solid, the case and the cylinders as ghosts, the rest hidden +const ALL = {case: 1, crank: 1, cyl: 1, valve: 1, ign: 1, air: 1, prop: 1, nose: 1, oil: 1, stand: 1, cowl: 0, baffle: 1}; +const ISO = { + crank: {case: 0.1, cyl: 0.12, valve: 0, ign: 0, air: 0, prop: 0.12, nose: 0.1, oil: 0, baffle: 0, stand: 0.5}, + cyl: {case: 0.5, crank: 0, valve: 0.35, ign: 0, air: 0.25, prop: 0.2, nose: 0.4, oil: 0, stand: 0.5}, + valve: {case: 0.12, cyl: 0.16, crank: 0, ign: 0, air: 0, prop: 0.1, nose: 0.1, oil: 0, baffle: 0, stand: 0.5}, + ign: {case: 0.5, cyl: 0.4, crank: 0, valve: 0.25, air: 0.15, prop: 0.25, nose: 0.5, oil: 0, baffle: 0, stand: 0.5}, + air: {case: 0.35, cyl: 0.35, crank: 0, valve: 0.15, ign: 0, air: 0.4, prop: 0.2, nose: 0.3, oil: 0, baffle: 0, stand: 0.5}, + prop: {case: 0.3, cyl: 0.3, crank: 0.4, valve: 0, ign: 0, air: 0.2, nose: 0.15, oil: 0, baffle: 0, stand: 0.5}, + oil: {case: 0.18, cyl: 0.12, crank: 0.4, valve: 0, ign: 0, air: 0.12, prop: 0.12, nose: 0.15, baffle: 0, stand: 0.5}, +}; +const CTX_SUB = {crank: 'law', cyl: 'cyl', valve: 'cam', ign: 'ign', air: 'air', prop: 'prop', oil: 'oil'}; +const PLANE = {face: 'rowcut', hero: 'profile', profile: 'profile', inside: 'inside'}; +const INSIDE_CYL = 2; + +const CSS = (top) => ` +html,body{margin:0;background:#e9eef1 linear-gradient(#e4ebf0,#edf0f0 55%,#f3ece1) fixed;overflow:hidden} +#app{position:absolute!important;inset:auto!important;left:0;top:0;width:${W}px;height:${H}px;transform-origin:0 0} +#gl{touch-action:none;cursor:grab} +#gl.drag{cursor:grabbing} +.tb{pointer-events:auto;cursor:pointer} +.tb:hover{filter:brightness(.93)} +.hit{position:absolute;pointer-events:auto;cursor:pointer} +.hit.ew{cursor:ew-resize} +.tourchip{position:absolute;left:800px;top:${30 + top}px;transform:translateX(-50%);display:flex;align-items:center;gap:8px;height:24px;padding:0 12px;border:1.5px solid #2b2f34;background:rgba(246,243,234,.96);color:#22262b;font:700 12px 'Barlow Condensed',sans-serif;letter-spacing:1.3px;white-space:nowrap;cursor:pointer;pointer-events:auto} +.tourchip i{display:block;width:7px;height:7px;border-radius:50%;background:#0a8fe0} +.tourchip.on i{animation:blink 1.2s steps(2) infinite} +@keyframes blink{50%{opacity:.15}} +.turn{position:fixed;left:0;right:0;bottom:18px;text-align:center;font:700 13px/1.4 'Barlow Condensed',sans-serif;letter-spacing:1px;color:#777b80;text-transform:uppercase;display:none} +@media (orientation:portrait) and (max-width:820px){.turn{display:block}} +`; + +export async function runLive() { + const style = document.createElement('style'); + style.textContent = CSS(0); + document.head.appendChild(style); + document.title = tr('docTitle'); + document.documentElement.lang = LANG; + await loadFonts(); + const app = document.getElementById('app'); + const canvas = document.createElement('canvas'); + canvas.id = 'gl'; + app.appendChild(canvas); + const st = createStage({canvas}); + const ui = createConsole(app, {live: true}); + const tourCursor = makeCursor(ui); + + // ------------------------------------------------------------ quality tiers + const TIERS = [ + {samples: 8, ao: true, shadow: 4096, pr: 2}, + {samples: 4, ao: false, shadow: 2048, pr: 1.5}, + {samples: 2, ao: false, shadow: 1024, pr: 1}, + ]; + const light = matchMedia('(pointer: coarse)').matches || Math.min(innerWidth, innerHeight) < 700; + let tier = light ? 2 : 0; + let scale = 1; + const chrome = createChrome({slug: 'radial', name: 'Radial', credit: tr('footCredit')}); + const fit = () => { + const {top, bottom} = chrome.heights(); + const h = innerHeight - top - bottom; + scale = Math.min(innerWidth / W, h / H); + app.style.transform = `translate(${(innerWidth - W * scale) / 2}px, ${top + (h - H * scale) / 2}px) scale(${scale})`; + st.resize(W, H, clamp((devicePixelRatio || 1) * scale, 0.75, TIERS[tier].pr)); + }; + const applyTier = () => { + const {pr, ...q} = TIERS[tier]; + void pr; + st.setQuality(q); + fit(); + }; + applyTier(); + addEventListener('resize', fit); + const toStage = (cx, cy) => { + const r = app.getBoundingClientRect(); + return [(cx - r.left) / scale, (cy - r.top) / scale]; + }; + const tourChip = document.createElement('div'); + tourChip.className = 'tourchip'; + ui.root.appendChild(tourChip); + const note = document.createElement('div'); + note.className = 'turn'; + note.textContent = tr('turnPhone'); + document.body.appendChild(note); + + // ------------------------------------------------------------ the engine, live: θ integrated from N each frame + const E = {th: 6, N: 0, target: RATING.idle, ign: false, starter: false, run: 0, air: 0, sparks: CYL.map(() => null), n: 0}; + const hash = (n) => { + const x = Math.sin(n * 127.1 + 311.7) * 43758.5453; + return x - Math.floor(x); + }; + const stepEngine = (dtau, T) => { + const running = E.ign && E.run > 0.55; + if (E.starter && E.run >= 1) E.starter = false; + let want = 0; + let tc = 1.2; + if (running) { + want = E.target; + tc = want > E.N ? 0.9 : 1.1; + } else if (E.starter) { + want = RATING.crank; + tc = 0.35; + } + E.N += (want - E.N) * (1 - Math.exp(-dtau / tc)); + if (!running && !E.starter && E.N < 25) E.N = Math.max(0, E.N - 40 * dtau); + if (E.ign && E.N > 80) E.run = Math.min(1, E.run + dtau / 1.0); + if (!E.ign) E.run = Math.max(0, E.run - dtau / 0.4); + const th0 = E.th; + E.th += E.N * 6 * dtau; + E.air += (E.N / 60) * dtau * 0.2; + // the sparks this step crossed: each lights its charge with the engine's chance of catching + if (E.ign) { + const pCatch = 0.12 + 0.88 * smoother(E.run / 0.8); + for (const c of ORDER) { + const base = FIRE[c] - SPARK_ADV; + let m = Math.ceil((th0 - base) / 720); + for (let k = 0; k < 4; k++, m++) { + const ths = base + 720 * m; + if (ths > E.th) break; + if (ths <= th0) continue; + const f = (ths - th0) / Math.max(1e-9, E.th - th0); + E.sparks[c - 1] = {t: T - (1 - f) * frameDt, th: ths, lit: hash(m * 18 + ORDER.indexOf(c) + 7 + E.n * 0.0) < pCatch}; + } + } + } + }; + let frameDt = 1 / 60; + + // ------------------------------------------------------------ state + let T = 0; + let rateI = 3; + let paused = false; + let view = 'hero'; + let viewAt = 0; + let cut = 'solid'; + let sub = ''; + const layers = {cowl: false, callouts: true}; + const off = {az: 0, el: 0, k: 1}; + const cam = {...VIEW_FN.hero(0)}; + let ring = {t: -9, x: 0, y: 0}; + let hidden = false; + const visNow = {...ALL}; + const pulse = (x, y) => (ring = {t: T, x, y}); + const pulseBtn = (k) => pulse(...ui.spots[k]); + + // ------------------------------------------------------------ the tour + const AP = {on: true, t0: 0, loop: 0}; + let lastInput = 0; + const startTour = () => { + AP.on = true; + AP.t0 = T; + AP.loop = 0; + paused = false; + cut = 'solid'; + sub = ''; + layers.cowl = false; + layers.callouts = true; + Object.assign(off, {az: 0, el: 0, k: 1}); + }; + const takeOver = () => { + lastInput = T; + if (!AP.on) return; + AP.on = false; + const cyc = (T - AP.t0) % DURATION; + const name = camAtName(cyc); + view = {face: 'face', faceFull: 'face', rowcut: 'face', apart: 'hero', cam: 'hero', takeoff: 'profile', heroEnd: 'hero'}[name] || 'hero'; + viewAt = T - 10; + sub = {rowcut: 'crank', cam: 'valve'}[name] || ''; + cut = name === 'rowcut' ? 'section' : 'solid'; + for (const g of Object.keys(ALL)) visNow[g] = sub ? (ISO[sub][g] ?? 1) : ALL[g]; + // the engine carries on where the tour left it + const tau = tauAt(cyc); + Object.assign(E, {th: thetaAt(cyc), N: rpmAt(cyc), ign: tau >= RUN.ign, starter: starterAtTau(tau) > 0, run: runAtTau(tau), air: airAt(cyc)}); + E.target = clamp(Math.round(E.N / 50) * 50, RATING.idle, RATING.takeoff.rpm); + rateI = RATES.reduce((b, r, i) => (Math.abs(Math.log(r / rateAt(cyc))) < Math.abs(Math.log(RATES[b] / rateAt(cyc))) ? i : b), 0); + for (const cy of CYL) { + const s = lastSpark(cy.c, cyc); + E.sparks[cy.c - 1] = {t: T - (cyc - s.t), th: s.th, lit: s.lit}; + } + }; + tourChip.addEventListener('pointerdown', (e) => { + e.stopPropagation(); + lastInput = T; + if (AP.on) takeOver(); + else startTour(); + }); + addEventListener('pointerdown', (e) => { + if (e.target !== tourChip) takeOver(); + }); + + // ------------------------------------------------------------ controls + const setView = (v) => { + view = v; + viewAt = T; + Object.assign(off, {az: 0, el: 0, k: 1}); + if (v === 'inside') cut = 'section'; + }; + const on = (k, fn) => + ui.btn[k].addEventListener('click', () => { + takeOver(); + pulseBtn(k); + fn(); + }); + for (const k of CAMS) on(k, () => setView(k)); + for (const k of CUTS) on(k, () => (cut = k)); + for (const k of SUBS) on(k, () => (sub = sub === k ? '' : k)); + for (const k of LAYERS) on(k, () => (layers[k] = !layers[k])); + on('pause', () => (paused = !paused)); + on('starter', () => { + if (E.run < 1) E.starter = !E.starter; + }); + on('ignition', () => (E.ign = !E.ign)); + on('slowmo', () => (rateI = (rateI + 1) % RATES.length)); + { + const {SL} = ui; + const d = document.createElement('div'); + d.className = 'hit ew'; + Object.assign(d.style, {left: `${SL.x - 8}px`, top: '840px', width: `${SL.w + 16}px`, height: '26px'}); + const apply = (e) => { + const [x] = toStage(e.clientX, e.clientY); + const k = clamp((x - SL.x) / SL.w, 0, 1); + E.target = Math.round((RATING.idle + k * (RATING.takeoff.rpm - RATING.idle)) / 50) * 50; + lastInput = T; + }; + d.addEventListener('pointerdown', (e) => { + takeOver(); + d.setPointerCapture(e.pointerId); + const up = () => { + removeEventListener('pointermove', apply); + removeEventListener('pointerup', up); + }; + addEventListener('pointermove', apply); + addEventListener('pointerup', up); + apply(e); + }); + ui.root.appendChild(d); + } + addEventListener('keydown', (e) => { + if (e.altKey || e.ctrlKey || e.metaKey) return; + const key = e.key.toLowerCase(); + const v = {1: 'face', 2: 'hero', 3: 'profile', 4: 'inside'}[key]; + takeOver(); + if (v) setView(v); + else if (key === ' ') paused = !paused; + else if (key === 'h') hidden = !hidden; + else if (key === 's') E.starter = E.run < 1 && !E.starter; + else if (key === 'm') E.ign = !E.ign; + else if (key === 'arrowleft') rateI = clamp(rateI + 1, 0, RATES.length - 1); + else if (key === 'arrowright') rateI = clamp(rateI - 1, 0, RATES.length - 1); + else if (key === 'arrowup') E.target = clamp(E.target + 100, RATING.idle, RATING.takeoff.rpm); + else if (key === 'arrowdown') E.target = clamp(E.target - 100, RATING.idle, RATING.takeoff.rpm); + else return; + e.preventDefault(); + }); + let drag = null; + canvas.addEventListener('pointerdown', (e) => { + drag = {x: e.clientX, y: e.clientY}; + canvas.setPointerCapture(e.pointerId); + canvas.classList.add('drag'); + }); + canvas.addEventListener('pointermove', (e) => { + if (!drag) return; + off.az += ((e.clientX - drag.x) / scale) * 0.3; + off.el = clamp(off.el + ((e.clientY - drag.y) / scale) * 0.2, -25, 60); + drag = {x: e.clientX, y: e.clientY}; + lastInput = T; + }); + const endDrag = () => { + drag = null; + canvas.classList.remove('drag'); + }; + canvas.addEventListener('pointerup', endDrag); + canvas.addEventListener('pointercancel', endDrag); + canvas.addEventListener( + 'wheel', + (e) => { + e.preventDefault(); + takeOver(); + off.k = clamp(off.k * Math.exp(e.deltaY * 0.0012), 0.35, 2.5); + }, + {passive: false}, + ); + + // ------------------------------------------------------------ the frame + startTour(); + let last = performance.now(); + const perf = {n: 0, sum: 0, slow: 0, age: 0}; + const frame = (now) => { + const dt = Math.min(0.1, Math.max(0, (now - last) / 1000)); + frameDt = dt; + last = now; + T += dt; + if (tier < TIERS.length - 1) { + perf.age += dt; + if (perf.age > 0.6) { + perf.sum += dt; + perf.n++; + if (perf.sum >= 0.5 && perf.n >= 6) { + perf.slow = perf.sum / perf.n > 0.022 ? perf.slow + 1 : 0; + perf.sum = 0; + perf.n = 0; + if (perf.slow >= (perf.age < 6 ? 1 : 2)) { + tier++; + applyTier(); + Object.assign(perf, {age: 0, slow: 0}); + } + } + } + } + + let th; + let N; + let run; + let rate; + let spark; + let tgt; + let cursor; + let fxLook; + let caption = ''; + let calloutView; + let since; + let phase; + let ctx; + let ctxArg; + let camBtn; + let camHi = null; + let starterOn; + let ignOn; + let air; + let thr; + if (AP.on) { + // the film, exactly: its run, its look, its camera + const c = T - AP.t0; + const loop = Math.floor(c / DURATION); + const cyc = c - loop * DURATION; + if (loop > AP.loop) AP.loop = loop; + th = thetaAt(cyc); + const tau = tauAt(cyc); + N = rpmAt(cyc); + run = runAtTau(tau); + rate = rateAt(cyc); + spark = (cc) => { + const s = lastSpark(cc, cyc); + return {t: T - (cyc - s.t), th: s.th, lit: s.lit}; + }; + const name = camAtName(cyc); + since = camSince(cyc); + fxLook = lookAtT(cyc); + tgt = camAt(cyc); + cursor = tourCursor(cyc); + if (AP.loop > 0 && cyc < 0.8) { + const end = tourCursor(DURATION - 0.01); + const k = ss(0, 0.8, cyc); + cursor = {...cursor, x: end.x + (cursor.x - end.x) * k, y: end.y + (cursor.y - end.y) * k}; + } + phase = phaseOf(tau); + caption = tr('cap:' + (name === 'hero' && phase !== 'stopped' ? phase : name)); + calloutView = name; + ctx = CTX_OF[name] || 'run'; + ctxArg = name === 'cam' ? CAM_CYL : name === 'rowcut' ? 'front' : undefined; + camBtn = BTN_OF[name]; + if (fxLook.focusK > 0.5) camHi = CYL.map((cy) => (cy.c === CAM_CYL ? {in: lift(cy.c, 'in', th), ex: lift(cy.c, 'ex', th)} : {in: 0, ex: 0})); + starterOn = starterAtTau(tau) > 0; + ignOn = tau >= RUN.ign; + air = airAt(cyc); + thr = N; + st.setCut(fxLook.cut ? 'section' : 'solid', fxLook.cut || 'profile'); + sub = SUB_OF[name] || ''; + if (name === 'hero' && cyc > 1.5) since = -1; + } else { + if (T - lastInput > IDLE) startTour(); + rate = paused ? 0 : RATES[rateI]; + stepEngine(dt * rate, T); + th = E.th; + N = E.N; + run = E.run; + spark = (cc) => E.sparks[cc - 1]; + since = T - viewAt; + // the look: the subsystem's, eased + const want = sub ? {...ALL, ...ISO[sub], [sub]: 1} : {...ALL}; + want.cowl = layers.cowl ? 1 : 0; + if (sub === 'prop') want.nose = 0.15; + const kk = 1 - Math.exp(-dt / 0.25); + for (const g of Object.keys(ALL)) visNow[g] += ((want[g] ?? 1) - visNow[g]) * kk; + fxLook = {vis: {...visNow}, apart: 0, hideRear: 0, focus: 0}; + tgt = VIEW_FN[view](since); + tgt.az += off.az; + tgt.el = clamp(tgt.el + off.el, -20, 85); + tgt.d *= off.k; + const rk = Math.max(0, 1 - (T - ring.t) / 0.55); + cursor = {x: -99, y: -99, press: false, ring: rk, ringX: ring.x, ringY: ring.y}; + phase = !E.ign && !E.starter && N < 1 ? 'stopped' : E.starter && E.run < 0.55 ? (E.ign ? 'ignition' : 'starter') : N > E.target + 60 ? 'back' : N < E.target - 60 ? 'climb' : N > 2500 ? 'takeoff' : 'idle'; + calloutView = view === 'hero' ? 'hero' : view === 'face' ? 'face' : ''; + ctx = sub ? CTX_SUB[sub] : N > 1500 ? 'takeoff' : 'run'; + ctxArg = sub === 'valve' ? INSIDE_CYL : sub === 'crank' ? 'front' : undefined; + camBtn = view; + if (sub === 'valve') camHi = CYL.map((cy) => ({in: lift(cy.c, 'in', th), ex: lift(cy.c, 'ex', th)})); + starterOn = E.starter; + ignOn = E.ign; + air = E.air; + thr = E.target; + if (cut === 'section') { + if (view === 'inside') { + const a = CYL[INSIDE_CYL - 1].angle * D2R; + st.planes.inside.normal.set(-Math.cos(a), -Math.sin(a), 0); + st.planes.inside.constant = 0; + } + st.setCut('section', PLANE[view] + (view === 'inside' ? '' : '')); + } else st.setCut('solid'); + } + const {s, lit, blur} = engineFrame({th, N, run, rate: Math.max(rate, 1e-4), spark, now: T}); + + // the camera eases toward its target + const k = 1 - Math.exp(-dt / (AP.on ? 0.1 : 0.35)); + cam.az += wrap(tgt.az - cam.az) * k; + for (const key of ['tx', 'ty', 'tz', 'el', 'sx', 'sy']) cam[key] += ((tgt[key] ?? 0) - (cam[key] ?? 0)) * k; + cam.fov = (cam.fov ?? 26) + ((tgt.fov ?? 26) - (cam.fov ?? 26)) * k; + cam.d = Math.exp(Math.log(cam.d) + (Math.log(tgt.d) - Math.log(cam.d)) * k); + const fx = { + th, + vis: fxLook.vis, + apart: fxLook.apart, + hideRear: fxLook.hideRear, + focus: fxLook.focus, + focusK: fxLook.focusK ?? 0, + glass: !AP.on && cut === 'glass', + glow: lit, + headGlow: lit.map((g) => g * 0.85 * (1 - (fxLook.focusK ?? 0))), + blur, + camHi, + air, + airK: !AP.on && sub === 'air' ? 1 : 0, + oil: th / 1440, + oilK: !AP.on && sub === 'oil' ? 1 : 0, + }; + st.frame(fx, {...cam, az: cam.az * D2R, el: cam.el * D2R}); + + ui.root.style.display = hidden ? 'none' : ''; + const callVis = layers.callouts && calloutView && since >= 0 ? ss(1.2, 2.0, since) : 0; + ui.update({ + ...s, + th, + lit, + rate: Math.max(rate, 1e-4), + phase, + starter: starterOn, + ignition: ignOn, + thrRpm: thr, + ctx, + ctxArg, + sub, + cut: AP.on ? (fxLook.cut ? 'section' : 'solid') : cut, + camBtn, + layers: {...layers}, + paused, + slowmo: rate < 0.98, + caption, + callouts: calloutView ? calloutsFor(calloutView, st, callVis) : [], + cursor, + }); + if (tourChip.classList.contains('on') !== AP.on || !tourChip.firstChild) { + tourChip.classList.toggle('on', AP.on); + tourChip.innerHTML = AP.on ? `${tr('tourOn')}` : tr('tourOff'); + } + if (!window.SIM_SHOWN) { + window.SIM_SHOWN = true; + dispatchEvent(new Event('simframe')); + } + requestAnimationFrame(frame); + }; + st.frame({th: 6, vis: ALL, glow: CYL.map(() => 0), headGlow: CYL.map(() => 0), blur: 0}, {...cam, az: cam.az * D2R, el: cam.el * D2R}); + warmComposer(st.renderer, st.composer, st.scene, st.camera).then(() => requestAnimationFrame(frame)); + window.LIVE = { + st, + cam, + E, + startTour, + takeOver, + get tier() { + return tier; + }, + get T() { + return T; + }, + }; + void blendLook; + void LOOK; + void SCRIPT; +} diff --git a/machines/radial/r2800-shared/make-timeline.mjs b/machines/radial/r2800-shared/make-timeline.mjs new file mode 100644 index 0000000..060702e --- /dev/null +++ b/machines/radial/r2800-shared/make-timeline.mjs @@ -0,0 +1,47 @@ +// Writes ../r2800-film/timeline.json (the beats, for review sheets and the score) and ../r2800-film/events.json +// (every spark of the film, lit or missed, and the engine's speed, slow motion, manifold pressure and firing rate on +// screen sampled at 100 Hz), all from the same schedule and model the film draws. +// node r2800-shared/make-timeline.mjs (from machines/radial) +import fs from 'node:fs'; +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; +import {stateAt} from './engine.js'; +import {BEATS, DURATION, rateAt, rpmAt, RUN, runAtTau, SCRIPT, sparkList, tauAt, thetaAt} from './schedule.js'; + +const HERE = path.dirname(fileURLToPath(import.meta.url)); +const r = (x) => +x.toFixed(3); +// film time of a physical time (τ is monotone in t) +const tOfTau = (tau) => { + let lo = 0; + let hi = DURATION; + for (let k = 0; k < 50; k++) { + const mid = (lo + hi) / 2; + if (tauAt(mid) < tau) lo = mid; + else hi = mid; + } + return r((lo + hi) / 2); +}; +const beats = { + views: BEATS, + presses: SCRIPT.filter((e) => e.press).map((e) => e.t), + starter: tOfTau(RUN.starter), + ignition: tOfTau(RUN.ign), + disengage: tOfTau(RUN.disengage), + climb: tOfTau(RUN.climb), + full: tOfTau(RUN.climb + RUN.climbLen), + back: tOfTau(RUN.back), + idleAgain: tOfTau(RUN.back + RUN.backLen), +}; +fs.writeFileSync(path.join(HERE, '../r2800-film/timeline.json'), JSON.stringify({duration: DURATION, beats})); +const samples = []; +for (let i = 0; i <= DURATION * 100; i++) { + const t = i / 100; + const N = rpmAt(t); + const tau = tauAt(t); + const s = stateAt(N, runAtTau(tau)); + const rate = rateAt(t); + samples.push([r(N), r(rate), r(s.map), r(s.fireHz * rate * runAtTau(tau)), r(thetaAt(t))]); +} +const sparks = sparkList(); +fs.writeFileSync(path.join(HERE, '../r2800-film/events.json'), JSON.stringify({rate: 100, fields: ['rpm', 'slow', 'map', 'fireHzScreen', 'theta'], samples, sparks})); +console.log(beats, sparks.length, 'sparks', sparks.filter((s) => s[2]).length, 'lit'); diff --git a/machines/radial/r2800-shared/model.js b/machines/radial/r2800-shared/model.js new file mode 100644 index 0000000..a31986b --- /dev/null +++ b/machines/radial/r2800-shared/model.js @@ -0,0 +1,928 @@ +// The R-2800 itself, built from code in metres from the numbers in engine.js and against the reference photographs +// (REFERENCES.md): a grey-blue forged crankcase in three sections, 18 steel barrels under black finned muffs, raw +// aluminium heads with deep fins and two rocker boxes each, chromed pushrod tubes from two cam rings, two plugs per +// head on a braided harness ring, two magnetos on the nose, black intake pipes from the supercharger's diffuser, a +// two-throw crankshaft with a master rod and eight articulated rods per row, a planetary reduction gear, a three-blade +// propeller, a cowling and the black inter-cylinder baffles. update(fx) poses everything from the crank angle. +// +// World: the engine's axis is z (the propeller at +z), y up, the axis at the origin. An angle a measured clockwise +// from the top seen from the rear (engine.js) is a rotation of +a about z. +import * as THREE from 'three'; +import {mergeGeometries} from 'three/addons/utils/BufferGeometryUtils.js'; +import {CAM, CAM_PHASE, CYL, E, GEAR, lift, lobeOffset, PROP_D, ROWS, rowPose, VALVE} from './engine.js'; + +export const ACCENT = '#0a8fe0'; +const V3 = THREE.Vector3; +const D2R = Math.PI / 180; +const mm = (x) => x / 1000; +export const FLOOR_Y = -2.2; +const PROP_OFF = 0; // the blades' angle at θ = 0, chosen so frame 0 shows the cylinders between them + +// ------------------------------------------------------------ geometry helpers (millimetres in, metres out) +/** a lathed part around Y: profile [[r, y], ...] in mm */ +const lathe = (pts, seg = 40) => new THREE.LatheGeometry(pts.map(([r, y]) => new THREE.Vector2(mm(r), mm(y))), seg); +/** a lathed part around the engine axis z: profile [[r, z], ...] in mm */ +const latheZ = (pts, seg = 64) => lathe(pts, seg).rotateX(Math.PI / 2); +/** the same, its profile smoothed by a centripetal spline through the points (no facets at the knees) */ +const latheZs = (pts, seg = 72, n = 4) => { + const c = new THREE.SplineCurve(pts.map(([r, z]) => new THREE.Vector2(r, z))); + const out = c.getSpacedPoints(Math.max(8, pts.length * n)).map((v) => [Math.max(0, v.x), v.y]); + out[0] = pts[0]; + out[out.length - 1] = pts[pts.length - 1]; + return latheZ(out, seg); +}; +/** an annular fin: outer wall plus two flat faces, between y and y + t, from rIn to rOut (mm) */ +function finGeo(rIn, rOut, y, t, seg) { + const side = new THREE.CylinderGeometry(mm(rOut), mm(rOut), mm(t), seg, 1, true).translate(0, mm(y + t / 2), 0); + const top = new THREE.RingGeometry(mm(rIn), mm(rOut), seg, 1).rotateX(-Math.PI / 2).translate(0, mm(y + t), 0); + const bot = new THREE.RingGeometry(mm(rIn), mm(rOut), seg, 1).rotateX(Math.PI / 2).translate(0, mm(y), 0); + return [side, top, bot]; +} +const tube = (r, y0, y1, seg = 32, open = true) => new THREE.CylinderGeometry(mm(r), mm(r), mm(y1 - y0), seg, 1, open).translate(0, mm((y0 + y1) / 2), 0); +const merge = (list) => { + const g = mergeGeometries(list.map((x) => (x.index ? x.toNonIndexed() : x))); + g.computeBoundingSphere(); + return g; +}; +/** a gear disc in the XY plane (extruded along z): teeth, pitch radius, width, all mm */ +function gearGeo(teeth, rp, width, hole = 0) { + const m = (2 * rp) / teeth; + const ro = rp + m; + const rr = rp - 1.2 * m; + const sh = new THREE.Shape(); + for (let i = 0; i < teeth; i++) { + const a0 = (i / teeth) * Math.PI * 2; + const da = (Math.PI * 2) / teeth; + const pts = [ + [rr, a0], + [rr, a0 + da * 0.2], + [ro, a0 + da * 0.36], + [ro, a0 + da * 0.6], + [rr, a0 + da * 0.76], + ]; + pts.forEach(([r, a], k) => (i === 0 && k === 0 ? sh.moveTo(mm(r * Math.cos(a)), mm(r * Math.sin(a))) : sh.lineTo(mm(r * Math.cos(a)), mm(r * Math.sin(a))))); + } + sh.closePath(); + if (hole) { + const h = new THREE.Path(); + h.absarc(0, 0, mm(hole), 0, Math.PI * 2, true); + sh.holes.push(h); + } + const g = new THREE.ExtrudeGeometry(sh, {depth: mm(width), bevelEnabled: false, curveSegments: 2}); + g.translate(0, 0, -mm(width) / 2); + return g; +} +/** an internal (ring) gear: teeth pointing in */ +function ringGearGeo(teeth, rp, rOut, width) { + const m = (2 * rp) / teeth; + const ri = rp - m; + const rr = rp + 1.2 * m; + const sh = new THREE.Shape(); + sh.absarc(0, 0, mm(rOut), 0, Math.PI * 2, false); + const h = new THREE.Path(); + for (let i = 0; i < teeth; i++) { + const a0 = (i / teeth) * Math.PI * 2; + const da = (Math.PI * 2) / teeth; + const pts = [ + [rr, a0], + [rr, a0 + da * 0.2], + [ri, a0 + da * 0.36], + [ri, a0 + da * 0.6], + [rr, a0 + da * 0.76], + ]; + pts.forEach(([r, a], k) => (i === 0 && k === 0 ? h.moveTo(mm(r * Math.cos(a)), mm(r * Math.sin(a))) : h.lineTo(mm(r * Math.cos(a)), mm(r * Math.sin(a))))); + } + h.closePath(); + sh.holes.push(h); + const g = new THREE.ExtrudeGeometry(sh, {depth: mm(width), bevelEnabled: false, curveSegments: 24}); + g.translate(0, 0, -mm(width) / 2); + return g; +} +/** a cam track: base circle plus 4 lobes at the given ring angles (degrees clockwise from the rear), in XY */ +function camTrackGeo(phase, half, base, rise, width) { + const sh = new THREE.Shape(); + const N = 360; + for (let i = 0; i <= N; i++) { + const b = (i / N) * 360; // ring angle, clockwise from the top seen from the rear + const x = (((b - phase) % 90) + 90 + 45) % 90 - 45; + const u = Math.abs(x) / half; + const r = base + (u >= 1 ? 0 : rise * (0.5 + 0.5 * Math.cos(Math.PI * u))); + const px = -Math.sin(b * D2R) * r; + const py = Math.cos(b * D2R) * r; + if (i === 0) sh.moveTo(mm(px), mm(py)); + else sh.lineTo(mm(px), mm(py)); + } + const h = new THREE.Path(); + h.absarc(0, 0, mm(base - 16), 0, Math.PI * 2, true); + sh.holes.push(h); + const g = new THREE.ExtrudeGeometry(sh, {depth: mm(width), bevelEnabled: false, curveSegments: 48}); + g.translate(0, 0, -mm(width) / 2); + return g; +} +const curveTube = (pts, r, seg = 48, rs = 10) => new THREE.TubeGeometry(new THREE.CatmullRomCurve3(pts.map((p) => new V3(mm(p[0]), mm(p[1]), mm(p[2])))), seg, mm(r), rs, false); +/** a point given by its engine angle (clockwise from the top seen from the rear), radius and z (mm) */ +const polar = (a, r, z) => [-Math.sin(a * D2R) * r, Math.cos(a * D2R) * r, z]; + +// ------------------------------------------------------------ textures from code +function braidTexture() { + const c = document.createElement('canvas'); + c.width = 64; + c.height = 16; + const g = c.getContext('2d'); + g.fillStyle = '#8f918c'; + g.fillRect(0, 0, 64, 16); + for (let x = -16; x < 80; x += 4) { + g.strokeStyle = x % 8 ? '#6c6e69' : '#b4b5b0'; + g.lineWidth = 1.6; + g.beginPath(); + g.moveTo(x, 0); + g.lineTo(x + 16, 16); + g.stroke(); + g.beginPath(); + g.moveTo(x + 16, 0); + g.lineTo(x, 16); + g.stroke(); + } + const t = new THREE.CanvasTexture(c); + t.wrapS = t.wrapT = THREE.RepeatWrapping; + t.repeat.set(40, 1); + t.colorSpace = THREE.SRGBColorSpace; + return t; +} +function blurTexture() { + const c = document.createElement('canvas'); + c.width = 256; + c.height = 4; + const g = c.getContext('2d'); + const gr = g.createLinearGradient(0, 0, 256, 0); + gr.addColorStop(0, 'rgba(24,24,24,0.0)'); + gr.addColorStop(0.08, 'rgba(24,24,24,0.55)'); + gr.addColorStop(0.5, 'rgba(26,26,26,0.42)'); + gr.addColorStop(0.9, 'rgba(30,30,30,0.3)'); + gr.addColorStop(0.94, 'rgba(214,170,40,0.55)'); + gr.addColorStop(1, 'rgba(214,170,40,0.0)'); + g.fillStyle = gr; + g.fillRect(0, 0, 256, 4); + const t = new THREE.CanvasTexture(c); + t.colorSpace = THREE.SRGBColorSpace; + return t; +} + +export function buildEngine() { + const root = new THREE.Group(); + const CLIP = [new THREE.Plane(new V3(0, 0, -1), 0)]; + const M = { + fins: new THREE.MeshStandardMaterial({color: '#18191b', roughness: 0.62, metalness: 0.35, side: THREE.DoubleSide}), + case: new THREE.MeshStandardMaterial({color: '#6b7884', roughness: 0.55, metalness: 0.35, side: THREE.DoubleSide}), + caseDark: new THREE.MeshStandardMaterial({color: '#56616b', roughness: 0.58, metalness: 0.35, side: THREE.DoubleSide}), + alu: new THREE.MeshStandardMaterial({color: '#a3a7ab', roughness: 0.5, metalness: 0.8, side: THREE.DoubleSide}), + chrome: new THREE.MeshStandardMaterial({color: '#aeb2b7', roughness: 0.42, metalness: 1, envMapIntensity: 0.55}), + steel: new THREE.MeshStandardMaterial({color: '#a7acb2', roughness: 0.42, metalness: 0.95, side: THREE.DoubleSide}), + steelDark: new THREE.MeshStandardMaterial({color: '#6e7277', roughness: 0.48, metalness: 0.9, side: THREE.DoubleSide}), + piston: new THREE.MeshStandardMaterial({color: '#c9ccd0', roughness: 0.45, metalness: 0.8, side: THREE.DoubleSide}), + black: new THREE.MeshStandardMaterial({color: '#1e2022', roughness: 0.62, metalness: 0.25, side: THREE.DoubleSide}), + exhaust: new THREE.MeshStandardMaterial({color: '#4a3f37', roughness: 0.75, metalness: 0.5}), + braid: new THREE.MeshStandardMaterial({color: '#9a9b96', roughness: 0.55, metalness: 0.7, map: braidTexture()}), + hub: new THREE.MeshStandardMaterial({color: '#3b3e42', roughness: 0.48, metalness: 0.7}), + plug: new THREE.MeshStandardMaterial({color: '#8c8f93', roughness: 0.45, metalness: 0.9}), + stand: new THREE.MeshStandardMaterial({color: '#55585b', roughness: 0.6, metalness: 0.5}), + cowl: new THREE.MeshStandardMaterial({color: '#959ba1', roughness: 0.5, metalness: 0.55, side: THREE.DoubleSide, envMapIntensity: 0.6}), + blade: new THREE.MeshStandardMaterial({color: '#ffffff', roughness: 0.62, metalness: 0.2, vertexColors: true, side: THREE.DoubleSide}), + oil: new THREE.MeshStandardMaterial({color: '#8a6a3a', roughness: 0.5, metalness: 0.6, emissive: '#c58a2a', emissiveIntensity: 0}), + glass: new THREE.MeshPhysicalMaterial({color: '#e9eef2', roughness: 0.1, metalness: 0, transparent: true, opacity: 0.13, depthWrite: false, side: THREE.DoubleSide}), + flame: new THREE.MeshBasicMaterial({color: ACCENT, transparent: true, opacity: 0, depthWrite: false, side: THREE.DoubleSide}), + accent: new THREE.MeshBasicMaterial({color: ACCENT}), + blur: new THREE.MeshBasicMaterial({color: '#2a2b2c', transparent: true, opacity: 0, depthWrite: false, side: THREE.DoubleSide}), + blurTip: new THREE.MeshBasicMaterial({color: '#c99a1e', transparent: true, opacity: 0, depthWrite: false, side: THREE.DoubleSide}), + }; + // every lit material can be cut by the section plane + for (const k of Object.keys(M)) M[k].clipShadows = true; + + // groups: what each subsystem button isolates + const GROUPS = ['case', 'crank', 'cyl', 'valve', 'ign', 'air', 'prop', 'nose', 'oil', 'stand', 'cowl', 'baffle']; + const parts = Object.fromEntries(GROUPS.map((g) => [g, []])); + const add = (parent, geo, mat, group, opts = {}) => { + const m = new THREE.Mesh(geo, mat); + m.castShadow = opts.cast ?? true; + m.receiveShadow = opts.receive ?? true; + m.userData = {group, mat, glassable: !!opts.glassable, nocut: !!opts.nocut}; + parent.add(m); + parts[group].push(m); + return m; + }; + + // per-row assemblies (they slide apart along the axis in the "rows apart" view) + const rowG = {rear: new THREE.Group(), front: new THREE.Group()}; + root.add(rowG.rear, rowG.front); + + // ------------------------------------------------------------ the power section crankcase + const caseGeo = latheZ([ + [0, -232], + [236, -232], + [252, -214], + [258, -150], + [262, -105], + [258, -60], + [250, 0], + [258, 60], + [262, 105], + [258, 150], + [252, 214], + [246, 250], + [0, 250], + ]); + add(root, caseGeo, M.case, 'case', {glassable: true}); + // the cylinder pads, one boss per cylinder + const padGeo = tube(112, 236, 262, 36, false); + for (const cy of CYL) { + const p = add(rowG[cy.row], padGeo, M.caseDark, 'case', {glassable: true}); + p.rotation.z = cy.angle * D2R; + p.position.z = mm(E.rowZ[cy.row]); + p.rotation.order = 'ZYX'; + } + + // ------------------------------------------------------------ cylinders + const barrelGeo = (() => { + const g = [tube(84, 262, 300), tube(73, 236, 470), tube(84, 438, 448)]; + g.push(...finGeo(84, 99, 254, 10, 40)); + for (let y = 302; y < 432; y += 5.6) g.push(...finGeo(84, 102, y, 1.8, 40)); + return merge(g); + })(); + const headGeo = (() => { + const g = [lathe([[86, 440], [88, 470], [86, 540], [70, 580], [40, 598], [0, 604]], 40)]; + for (let y = 452, i = 0; y < 570; y += 6.6, i++) { + const k = (y - 452) / 118; + g.push(...finGeo(84 - 22 * k * k, 112 - 26 * k * k, y, 2.4, 40)); + } + // the combustion chamber's roof, seen in section + g.push(lathe([[73, 470], [70, 478], [52, 492], [0, 500]], 36)); + return merge(g); + })(); + // rocker boxes: one over each valve, their covers at the top + const boxGeo = merge([new THREE.CapsuleGeometry(mm(24), mm(62), 6, 16).rotateX(Math.PI / 2), new THREE.CylinderGeometry(mm(29), mm(29), mm(8), 20).translate(0, mm(16), mm(-18))]); + const portGeo = new THREE.CylinderGeometry(mm(34), mm(38), mm(60), 20).rotateX(Math.PI / 2); + const exGeo = curveTube([[0, 512, 92], [0, 520, 128], [0, 540, 158]], 22, 12, 12); + const plugGeo = merge([new THREE.CylinderGeometry(mm(10), mm(10), mm(44), 12).rotateX(Math.PI / 2), new THREE.CylinderGeometry(mm(14), mm(14), mm(12), 6).rotateX(Math.PI / 2).translate(0, 0, mm(-14))]); + const flameGeo = lathe([[70, 436], [72, 468], [52, 490], [0, 498]], 32); + const cylinders = CYL.map((cy) => { + const g = new THREE.Group(); + g.rotation.z = cy.angle * D2R; + g.position.z = mm(E.rowZ[cy.row]); + rowG[cy.row].add(g); + add(g, barrelGeo, M.fins, 'cyl', {glassable: true}); + const headMat = M.alu.clone(); + headMat.clipShadows = true; + headMat.emissive = new THREE.Color(ACCENT); + headMat.emissiveIntensity = 0; + const head = add(g, headGeo, headMat, 'cyl', {glassable: true}); + head.userData.ownMat = true; + head.userData.mat = headMat; + const flame = add(g, flameGeo, M.flame.clone(), 'cyl', {cast: false, receive: false}); + flame.userData.isFlame = true; + flame.renderOrder = 2; + // the cam side: the front row's ring is in front of it, the rear row's behind + const side = cy.row === 'front' ? 1 : -1; + for (const s of [-1, 1]) { + const b = add(g, boxGeo, M.alu, 'cyl'); + b.position.set(0, mm(592), mm(60 * s)); + b.rotation.x = -0.32 * s; + } + add(g, portGeo, M.alu, 'cyl').position.set(0, mm(522), mm(-100)); + const ex = add(g, exGeo, M.exhaust, 'cyl'); + if (cy.row === 'rear') ex.scale.z = 0.55; + for (const s of [-1, 1]) { + const p = add(g, plugGeo, M.plug, 'ign'); + p.position.set(mm(s * 30), mm(476), mm(110 * s)); + p.rotation.y = s * 0.25; + } + return {cy, g, head, flame, side}; + }); + + // ------------------------------------------------------------ the valve train: two cam rings, tappets, pushrods, rockers, valves + const camRings = {}; + for (const row of ['rear', 'front']) { + const side = row === 'front' ? 1 : -1; + const z = E.rowZ[row] + side * 125; + const g = new THREE.Group(); + g.position.z = mm(z); + rowG[row].add(g); + const half = {in: (VALVE.in[1] - VALVE.in[0]) / 16, ex: (VALVE.ex[1] - VALVE.ex[0]) / 16}; + const tin = add(g, camTrackGeo(CAM_PHASE[row].in, half.in, 140, 12, 12), M.steel, 'valve'); + tin.position.z = mm(-8); + const tex = add(g, camTrackGeo(CAM_PHASE[row].ex, half.ex, 140, 12, 12), M.steel, 'valve'); + tex.position.z = mm(8); + add(g, tube(120, -14, 14, 48, false).rotateX(Math.PI / 2), M.steelDark, 'valve'); + camRings[row] = g; + } + const tappetGeo = merge([tube(9, 0, 96, 12, false), new THREE.CylinderGeometry(mm(12), mm(12), mm(10), 14).rotateZ(Math.PI / 2)]); + const rodGeo = (a, b) => curveTube([a, [(a[0] + b[0]) / 2, (a[1] + b[1]) / 2, (a[2] + b[2]) / 2], b], 7.5, 8, 10); + // the pushrod tubes: the near valve goes straight up the cam side, the far one around the barrel + const nearTube = curveTube([[18, 262, 125], [18, 420, 124], [18, 566, 116]], 7.5, 24, 10); + const farTube = curveTube([[-24, 262, 125], [-92, 340, 86], [-114, 440, 0], [-92, 528, -84], [-24, 566, -116]], 7.5, 48, 10); + const valveGeo = merge([tube(4.5, 470, 580, 10, false), lathe([[0, 462], [27, 462], [27, 466], [10, 474], [4.5, 486]], 24)]); + const rockerGeo = merge([new THREE.BoxGeometry(mm(12), mm(10), mm(96)).translate(0, 0, mm(10)), new THREE.CylinderGeometry(mm(9), mm(9), mm(22), 12).rotateZ(Math.PI / 2)]); + const train = cylinders.map((C) => { + const {g, side} = C; + const out = {}; + for (const ev of ['in', 'ex']) { + // the inlet valve is at the rear of the head, the exhaust at the front + const vs = ev === 'in' ? -1 : 1; + const near = vs === side; + const tz = side * 125 + (ev === 'in' ? -8 : 8); + const tp = add(g, tappetGeo, M.steel, 'valve'); + tp.position.set(mm(near ? 18 : -18), mm(152), mm(tz)); + const tb = add(g, near ? nearTube : farTube, M.chrome, 'valve', {glassable: true}); + if (side < 0) tb.scale.z = -1; + const v = add(g, valveGeo, M.steel, 'valve'); + v.position.z = mm(34 * vs); + v.rotation.x = 0; + const rk = add(g, rockerGeo, M.steel, 'valve'); + rk.position.set(0, mm(590), mm(70 * vs)); + rk.scale.z = vs; + out[ev] = {tp, tb, v, rk, near}; + } + return out; + }); + + // every part that belongs to one cylinder knows which (the cam view shows one cylinder's train); its tappet stays + for (const C of cylinders) C.g.traverse((o) => o.isMesh && (o.userData.cyl = C.cy.c)); + for (const tr of train) for (const ev of ['in', 'ex']) tr[ev].tp.userData.keep = true; + + // ------------------------------------------------------------ the crankshaft: two throws at 180°, two halves + const crank = {}; + const webGeo = (() => { + const sh = new THREE.Shape(); + const R = 128; + sh.moveTo(mm(-R * Math.sin(1.1)), mm(-R * Math.cos(1.1))); + sh.absarc(0, 0, mm(R), -Math.PI / 2 - 1.1, -Math.PI / 2 + 1.1, false); + sh.lineTo(mm(52), mm(20)); + sh.absarc(0, mm(E.r), mm(54), 0, Math.PI, false); + sh.lineTo(mm(-52), mm(20)); + sh.closePath(); + const g = new THREE.ExtrudeGeometry(sh, {depth: mm(26), bevelEnabled: true, bevelThickness: mm(2), bevelSize: mm(2), bevelSegments: 1, curveSegments: 20}); + g.translate(0, 0, -mm(13)); + return g; + })(); + for (const row of ['rear', 'front']) { + const g = new THREE.Group(); + g.position.z = mm(E.rowZ[row]); + rowG[row].add(g); + const sign = row === 'rear' ? 1 : -1; // the front pin is 180° from the rear one + const inner = row === 'rear' ? 1 : -1; // toward the centre of the engine + for (const dz of [-44, 44]) { + const w = add(g, webGeo, M.steel, 'crank'); + w.position.z = mm(dz); + if (sign < 0) w.rotation.z = Math.PI; + } + add(g, tube(46, -32, 32, 32, false).rotateX(Math.PI / 2).translate(0, mm(E.r * sign), 0), M.steel, 'crank'); + // main journals: outward to the end bearing, inward to the centre one + add(g, tube(50, 0, 160, 32, false).rotateX(Math.PI / 2).translate(0, 0, mm(-inner * 130)), M.steel, 'crank'); + add(g, tube(50, -inner * 60, -inner * 4, 32, false).rotateX(Math.PI / 2).translate(0, 0, mm(inner * 60 + (inner > 0 ? 0 : 0))), M.steel, 'crank'); + // the oil drilling, through the journal and out to the crankpin + add(g, curveTube([[0, 0, -inner * 150], [0, 0, -inner * 40], [0, E.r * sign * 0.5, 0], [0, E.r * sign, 0]], 7, 24, 8), M.oil, 'oil', {cast: false}); + crank[row] = g; + } + // the centre main bearing + add(root, tube(58, -16, 16, 36, false).rotateX(Math.PI / 2), M.steelDark, 'crank'); + + // ------------------------------------------------------------ rods and pistons + const pistonGeo = (() => { + const g = [tube(72.5, -50, 66, 40, false), new THREE.CircleGeometry(mm(72.5), 40).rotateX(-Math.PI / 2).translate(0, mm(66), 0)]; + for (const y of [40, 48, 56]) g.push(tube(73.2, y, y + 2.2, 40, false)); + return merge(g); + })(); + const pinGeo = new THREE.CylinderGeometry(mm(16), mm(16), mm(128), 16).rotateZ(Math.PI / 2); + const masterGeo = (() => { + const sh = new THREE.Shape(); + sh.absarc(0, 0, mm(88), 0, Math.PI * 2, false); + const h = new THREE.Path(); + h.absarc(0, 0, mm(47), 0, Math.PI * 2, true); + sh.holes.push(h); + const flange = new THREE.ExtrudeGeometry(sh, {depth: mm(52), bevelEnabled: false, curveSegments: 40}).translate(0, 0, -mm(26)); + const shank = new THREE.BoxGeometry(mm(34), mm(E.L - 110), mm(30)).translate(0, mm(80 + (E.L - 110) / 2 - 10), 0); + const eye = new THREE.CylinderGeometry(mm(26), mm(26), mm(34), 20).rotateX(Math.PI / 2).translate(0, mm(E.L), 0); + return merge([flange, shank, eye]); + })(); + const knuckleGeo = new THREE.CylinderGeometry(mm(11), mm(11), mm(60), 14).rotateX(Math.PI / 2); + const artGeo = merge([ + new THREE.BoxGeometry(mm(22), mm(E.l - 40), mm(18)).translate(0, mm(E.l / 2), 0), + new THREE.CylinderGeometry(mm(18), mm(18), mm(22), 16).rotateX(Math.PI / 2), + new THREE.CylinderGeometry(mm(22), mm(22), mm(26), 16).rotateX(Math.PI / 2).translate(0, mm(E.l), 0), + ]); + const rods = {}; + for (const row of ['rear', 'front']) { + const m = E.master[row]; + const mg = add(rowG[row], masterGeo, M.steel, 'crank'); + const knuckles = []; + for (const cy of ROWS[row]) { + if (cy.c === m) continue; + const k = add(mg, knuckleGeo, M.steelDark, 'crank'); + const d = (cy.angle - CYL[m - 1].angle) * D2R; + k.position.set(-Math.sin(d) * mm(E.rk), Math.cos(d) * mm(E.rk), 0); + knuckles.push(k); + } + const arts = {}; + for (const cy of ROWS[row]) if (cy.c !== m) arts[cy.c] = add(rowG[row], artGeo, M.steel, 'crank'); + rods[row] = {master: mg, arts}; + } + const pistons = CYL.map((cy) => { + const p = add(cylinders[cy.c - 1].g, pistonGeo, M.piston, 'crank'); + add(p, pinGeo, M.steelDark, 'crank'); + return p; + }); + + // ------------------------------------------------------------ the nose: reduction gear, magnetos, harness, propeller + add( + root, + latheZs([ + [246, 250], + [282, 282], + [300, 330], + [292, 400], + [252, 470], + [205, 540], + [165, 598], + [128, 640], + [0, 652], + ]), + M.case, + 'nose', + {glassable: true}, + ); + const gearG = new THREE.Group(); + gearG.position.z = mm(380); + root.add(gearG); + const RG = {sun: 72, ring: 88, module: 3.4}; // 72 / (72 + 88) = 0.45 [E: the layout] + const rpS = (RG.sun * RG.module) / 2; + const rpR = (RG.ring * RG.module) / 2; + const rpP = (rpR - rpS) / 2; + const sun = add(gearG, gearGeo(RG.sun, rpS, 34, 30), M.steel, 'prop'); + add(gearG, ringGearGeo(RG.ring, rpR, rpR + 16, 34), M.steelDark, 'prop'); + const carrier = new THREE.Group(); + gearG.add(carrier); + add(carrier, new THREE.CylinderGeometry(mm(rpR - 4), mm(rpR - 4), mm(10), 48).rotateX(Math.PI / 2).translate(0, 0, mm(26)), M.steelDark, 'prop'); + const planets = []; + for (let i = 0; i < 6; i++) { + const pg = add(carrier, gearGeo(8, rpP, 34, 0), M.steel, 'prop'); + const a = (i / 6) * Math.PI * 2; + pg.position.set(Math.cos(a) * mm(rpS + rpP), Math.sin(a) * mm(rpS + rpP), 0); + planets.push(pg); + } + // the propeller shaft (splined) and hub: they turn with the carrier + const propG = new THREE.Group(); + root.add(propG); + add(propG, tube(62, 600, 760, 32, false).rotateX(Math.PI / 2), M.steel, 'prop'); + add(propG, latheZs([[0, 720], [132, 722], [140, 760], [130, 830], [100, 880], [50, 905], [0, 910]], 48), M.hub, 'prop'); + const bladeGeo = (() => { + const R = PROP_D * 500; + const rows = 28; + const cols = 14; + const pos = []; + const col = []; + const idx = []; + const tipY = new THREE.Color('#d8a925'); + const blk = new THREE.Color('#1b1c1d'); + for (let i = 0; i <= rows; i++) { + const u = i / rows; + const r = 150 + (R - 150) * u; + const chord = u < 0.1 ? 120 + 1300 * u : 250 * (1 - 0.45 * Math.max(0, (u - 0.3) / 0.7) ** 1.4) + (u > 0.97 ? -1500 * (u - 0.97) : 0); + const thick = 60 * (1 - u) + 7; + const tw = (52 - 40 * u) * D2R; + const cc = (r > R - 120 ? tipY : blk).clone(); + for (let j = 0; j < cols; j++) { + const a = (j / cols) * Math.PI * 2; + const x = (Math.cos(a) * chord) / 2; + const z = (Math.sin(a) * thick) / 2; + pos.push(mm(x * Math.cos(tw) - z * Math.sin(tw)), mm(r), mm(x * Math.sin(tw) + z * Math.cos(tw))); + col.push(cc.r, cc.g, cc.b); + } + } + for (let i = 0; i < rows; i++) + for (let j = 0; j < cols; j++) { + const a = i * cols + j; + const b = i * cols + ((j + 1) % cols); + idx.push(a, b, a + cols, b, b + cols, a + cols); + } + const g = new THREE.BufferGeometry(); + g.setAttribute('position', new THREE.Float32BufferAttribute(pos, 3)); + g.setAttribute('color', new THREE.Float32BufferAttribute(col, 3)); + g.setIndex(idx); + g.computeVertexNormals(); + return g; + })(); + const blades = []; + for (let i = 0; i < 3; i++) { + const b = add(propG, bladeGeo, M.blade, 'prop'); + b.rotation.z = (i * 2 * Math.PI) / 3; + b.position.z = mm(790); + blades.push(b); + } + const blurDisc = add(root, new THREE.RingGeometry(mm(150), mm(PROP_D * 500 - 120), 96, 1), M.blur, 'prop', {cast: false, receive: false}); + const blurTip = add(blurDisc, new THREE.RingGeometry(mm(PROP_D * 500 - 120), mm(PROP_D * 500), 96, 1), M.blurTip, 'prop', {cast: false, receive: false}); + blurDisc.position.z = mm(790); + blurDisc.renderOrder = 3; + // two magnetos on the nose, their distributors turning at half crank speed + const magnetos = []; + for (const a of [-38, 38]) { + const g = new THREE.Group(); + const [x, y] = polar(a, 300, 0); + g.position.set(mm(x), mm(y), mm(360)); + g.rotation.z = a * D2R; + root.add(g); + add(g, new THREE.BoxGeometry(mm(92), mm(96), mm(128)).translate(0, mm(34), 0), M.caseDark, 'ign'); + const cap = add(g, new THREE.CylinderGeometry(mm(42), mm(46), mm(30), 24).translate(0, mm(96), 0), M.black, 'ign'); + const rotor = add(g, new THREE.BoxGeometry(mm(60), mm(6), mm(10)).translate(mm(16), mm(114), 0), M.steel, 'ign'); + void cap; + magnetos.push({g, rotor}); + } + // the harness ring and its 36 leads + add(root, new THREE.TorusGeometry(mm(302), mm(15), 12, 96), M.braid, 'ign').position.z = mm(268); + const plugAt = (cy, s) => { + // a plug's tip in world mm: s +1 front plug, -1 rear plug + const a = cy.angle; + const local = [30 * s, 476, 110 * s + 22 * s]; + const r = local[1]; + const t = (local[0] * Math.PI) / 180 / 4.76; // small tangential offset as an angle + void t; + const ang = a - (local[0] / r) * (180 / Math.PI); + return polar(ang, r, E.rowZ[cy.row] + local[2]); + }; + for (const cy of CYL) { + for (const s of [1, -1]) { + const p = plugAt(cy, s); + const a0 = cy.angle + (cy.row === 'front' ? 0 : 0); + const start = polar(a0, 302, 268); + let path; + if (cy.row === 'front' && s > 0) path = [start, polar(a0, 380, 262), polar(a0 - 3, 455, 245), p]; + else if (cy.row === 'front') path = [start, polar(a0 - 14, 360, 250), polar(a0 - 17, 440, 120), polar(a0 - 14, 470, 20), p]; + else if (s > 0) path = [start, polar(a0, 340, 240), polar(a0, 420, 130), polar(a0 - 3, 466, 30), p]; + else path = [start, polar(a0, 340, 240), polar(a0, 420, 130), polar(a0 - 13, 470, -60), polar(a0 - 9, 474, -180), p]; + add(root, curveTube(path, 5, 40, 6), M.braid, 'ign', {cast: false}); + } + } + + // ------------------------------------------------------------ the rear: supercharger, diffuser, 18 intake pipes, carburettor, accessories + add( + root, + latheZs([ + [0, -232], + [252, -232], + [318, -268], + [336, -300], + [330, -340], + [282, -400], + [272, -430], + [262, -520], + [248, -760], + [238, -1000], + [228, -1180], + [150, -1240], + [0, -1244], + ]), + M.case, + 'air', + {glassable: true}, + ); + const impG = new THREE.Group(); + impG.position.z = mm(-312); + root.add(impG); + add(impG, latheZ([[0, -26], [40, -26], [140, 10], [140, 16], [0, 16]], 40), M.alu, 'air'); + const vane = new THREE.BoxGeometry(mm(4), mm(98), mm(34)).translate(0, mm(90), 0); + for (let i = 0; i < 18; i++) { + const v = add(impG, vane, M.alu, 'air'); + v.rotation.z = (i / 18) * Math.PI * 2; + } + // the pipes: from the diffuser's outlets to each cylinder's inlet port + const pipeCurves = []; + for (const cy of CYL) { + const zr = E.rowZ[cy.row]; + const a = cy.angle; + const pts = [polar(a, 318, -300), polar(a, 400, -310), polar(a, 492, cy.row === 'front' ? -150 : zr - 175), polar(a, 522, zr - 128)]; + const c = new THREE.CatmullRomCurve3(pts.map((p) => new V3(mm(p[0]), mm(p[1]), mm(p[2])))); + pipeCurves.push(c); + add(root, new THREE.TubeGeometry(c, 40, mm(34), 14, false), M.black, 'air', {glassable: true}); + } + // carburettor on top of the rear case, the air scoop's throat + add(root, new THREE.BoxGeometry(mm(240), mm(150), mm(260)).translate(0, mm(330), mm(-560)), M.black, 'air'); + add(root, new THREE.BoxGeometry(mm(200), mm(60), mm(220)).translate(0, mm(430), mm(-560)), M.caseDark, 'air'); + // the starter at the very rear, a generator and pumps on their pads + add(root, latheZ([[0, -1244], [96, -1244], [100, -1300], [92, -1420], [60, -1450], [0, -1452]], 32), M.black, 'case'); + for (const [a, r, len] of [[120, 160, 230], [240, 160, 230], [180, 170, 180]]) { + const [x, y] = polar(a, r, 0); + add(root, new THREE.CylinderGeometry(mm(64), mm(64), mm(len), 24).rotateX(Math.PI / 2).translate(mm(x), mm(y), mm(-1240 - len / 2 + 30)), M.caseDark, 'case'); + } + // the oil system: pressure pump low at the rear, its line to the rear main bearing, the scavenge sump, the nose feed + add(root, new THREE.BoxGeometry(mm(150), mm(120), mm(170)).translate(0, mm(-250), mm(-760)), M.caseDark, 'oil'); + const oilLines = [ + [[0, -250, -680], [0, -238, -480], [0, -120, -300], [0, -40, -240]], + [[60, -262, -150], [50, -300, -400], [40, -300, -700], [40, -260, -760]], + [[-120, -230, 250], [-200, -250, 330], [-160, -230, 440], [-60, -120, 470]], + ]; + const oilCurves = oilLines.map((pts) => new THREE.CatmullRomCurve3(pts.map((p) => new V3(mm(p[0]), mm(p[1]), mm(p[2]))))); + for (const c of oilCurves) add(root, new THREE.TubeGeometry(c, 40, mm(11), 10, false), M.oil, 'oil'); + add(root, new THREE.BoxGeometry(mm(240), mm(60), mm(300)).translate(0, mm(-272), 0), M.caseDark, 'oil'); + + // ------------------------------------------------------------ baffles, cowling, the test stand + const baffleGeo = (() => { + const sh = new THREE.Shape(); + sh.moveTo(mm(-44), mm(420)); + sh.lineTo(mm(44), mm(420)); + sh.lineTo(mm(56), mm(560)); + sh.lineTo(mm(-56), mm(560)); + sh.closePath(); + return new THREE.ExtrudeGeometry(sh, {depth: mm(3), bevelEnabled: false}).translate(0, 0, -mm(1.5)).rotateY(Math.PI / 2); + })(); + for (const row of ['rear', 'front']) { + for (const cy of ROWS[row]) { + const b = add(rowG[row], baffleGeo, M.black, 'baffle'); + b.rotation.z = (cy.angle + 20) * D2R; + b.position.z = mm(E.rowZ[row]); + b.rotation.order = 'ZYX'; + b.scale.set(1, 1, 1); + } + } + const cowl = add( + root, + latheZ( + [ + [640, -300], + [668, -120], + [690, 120], + [700, 260], + [690, 330], + [655, 352], + [610, 340], + [612, 320], + [664, 300], + [672, 240], + [662, 120], + [636, -120], + [612, -298], + ], + 96, + ), + M.cowl, + 'cowl', + {glassable: true}, + ); + void cowl; + // the mount ring at the rear and a tubular run-up stand down to the concrete + add(root, new THREE.TorusGeometry(mm(352), mm(22), 12, 64).translate(0, 0, mm(-360)), M.stand, 'stand'); + const leg = (a, b) => { + const A = new V3(...a.map(mm)); + const B = new V3(...b.map(mm)); + const g = new THREE.CylinderGeometry(mm(24), mm(24), A.distanceTo(B), 12); + const m = add(root, g, M.stand, 'stand'); + m.position.copy(A).add(B).multiplyScalar(0.5); + m.quaternion.setFromUnitVectors(new V3(0, 1, 0), B.clone().sub(A).normalize()); + }; + const Fy = FLOOR_Y * 1000; + for (const s of [-1, 1]) { + leg([s * 300, -180, -360], [s * 700, Fy, -150]); + leg([s * 300, -180, -360], [s * 700, Fy, -1100]); + leg([s * 340, 60, -360], [s * 700, Fy + 900, -620]); + leg([s * 700, Fy, -150], [s * 700, Fy, -1100]); + } + leg([-700, Fy, -1100], [700, Fy, -1100]); + leg([-700, Fy, -150], [700, Fy, -150]); + + // ------------------------------------------------------------ the air and the oil, as particles along their paths + const dotGeo = new THREE.SphereGeometry(1, 10, 8); + const airDots = new THREE.InstancedMesh(dotGeo, new THREE.MeshBasicMaterial({color: ACCENT, transparent: true, opacity: 0.9, depthWrite: false}), 18 * 5 + 60); + airDots.frustumCulled = false; + airDots.renderOrder = 4; + root.add(airDots); + const oilDots = new THREE.InstancedMesh(dotGeo, new THREE.MeshBasicMaterial({color: '#d0902c', transparent: true, opacity: 0.95, depthWrite: false}), 3 * 10); + oilDots.frustumCulled = false; + oilDots.renderOrder = 4; + root.add(oilDots); + // the charge's path inside the rear case: the carburettor's throat down to the impeller's eye, out to the diffuser + const throat = new THREE.CatmullRomCurve3([new V3(0, 0.33, -0.56), new V3(0, 0.22, -0.48), new V3(0, 0.06, -0.4), new V3(0, 0.0, -0.33)]); + + // ------------------------------------------------------------ anchors for the callouts (world, metres) + const top = CYL[0]; + const front1 = CYL[1]; + const A = { + head: () => cylinders[0].g.localToWorld(new V3(0, mm(560), 0)), + fins: () => cylinders[0].g.localToWorld(new V3(mm(-100), mm(360), 0)), + headFront: () => cylinders[1].g.localToWorld(new V3(0, mm(540), mm(30))), + pushrod: () => cylinders[1].g.localToWorld(new V3(mm(18), mm(400), mm(124))), + harness: () => new V3(...polar(-60, 302, 268).map(mm)), + magneto: () => magnetos[1].g.localToWorld(new V3(0, mm(60), 0)), + nose: () => new V3(0, mm(250), mm(520)), + hub: () => new V3(0, 0, mm(900)), + blade: () => blades[0].localToWorld(new V3(0, 1.4, 0)), + pipe: () => pipeCurves[8].getPoint(0.55), + carb: () => new V3(0, mm(410), mm(-560)), + starter: () => new V3(0, 0, mm(-1440)), + impeller: () => impG.localToWorld(new V3(0, mm(120), 0)), + camRing: (row = 'front') => camRings[row].localToWorld(new V3(mm(-100), mm(-100), 0)), + master: (row = 'front') => rods[row].master.localToWorld(new V3(0, mm(150), 0)), + art: (row, c) => rods[row].arts[c].localToWorld(new V3(0, mm(E.l * 0.5), 0)), + pin: (row = 'front') => crank[row].localToWorld(new V3(0, mm(E.r * (row === 'rear' ? 1 : -1)), mm(-44))), + piston: (c) => pistons[c - 1].localToWorld(new V3(0, mm(66), 0)), + tappet: (c, ev) => train[c - 1][ev].tp.localToWorld(new V3(0, mm(40), 0)), + rocker: (c, ev) => train[c - 1][ev].rk.localToWorld(new V3(0, 0, mm(30))), + valve: (c, ev) => train[c - 1][ev].v.localToWorld(new V3(0, mm(470), 0)), + gear: () => gearG.localToWorld(new V3(mm(-90), mm(90), 0)), + oilPump: () => new V3(0, mm(-250), mm(-760)), + sump: () => new V3(mm(100), mm(-280), 0), + baffle: () => cylinders[4].g.localToWorld(new V3(mm(120), mm(520), 0)), + cowl: () => new V3(mm(-600), mm(330), mm(300)), + cylAt: (c, y = 520) => cylinders[c - 1].g.localToWorld(new V3(0, mm(y), 0)), + }; + void top; + void front1; + + // ------------------------------------------------------------ cutaways and visibility + const ghostOf = new Map(); + const ghost = (mat) => { + let g = ghostOf.get(mat); + if (!g) { + g = mat.clone(); + g.transparent = true; + g.depthWrite = false; + g.clipShadows = true; + ghostOf.set(mat, g); + } + return g; + }; + const cut = {mode: 'solid', glass: false}; + const all = Object.values(parts).flat(); + const allMats = new Set(); + for (const m of all) allMats.add(m.material); + for (const m of Object.values(M)) allMats.add(m); + const setCut = (mode, plane) => { + cut.mode = mode; + if (plane) CLIP[0].copy(plane); + const planes = mode === 'section' ? CLIP : null; + for (const mat of [...allMats, ...ghostOf.values()]) { + mat.clippingPlanes = planes; + mat.needsUpdate = true; + } + }; + + // ------------------------------------------------------------ pose everything from the crank angle + const tmp = new V3(); + const m4 = new THREE.Matrix4(); + const q = new THREE.Quaternion(); + const sc = new V3(); + const up = new V3(0, 1, 0); + /** + * fx: th (crank °), vis {group: 0..1 opacity}, glass (bool: case, barrels, heads, pipes as glass), apart (0..1), + * glow[18] (the flame in each chamber, 0..1), headGlow[18], camHi[18] ({in, ex} 0..1 accent on the tappet and tube), + * blur (propeller blur 0..1), air (phase), airK (0..1), oil (phase), oilK (0..1) + */ + const update = (fx) => { + const th = fx.th; + const vis = fx.vis || {}; + // groups' visibility: 1 is the part's own material, 0 is hidden, between is a ghost + for (const g of GROUPS) { + const v = vis[g] ?? 1; + for (const m of parts[g]) { + if (v <= 0.01) { + m.visible = false; + continue; + } + const vf = fx.focus && m.userData.cyl && m.userData.cyl !== fx.focus && !m.userData.keep ? v * (1 - (fx.focusK ?? 1)) : v; + if (vf <= 0.01) { + m.visible = false; + continue; + } + m.visible = true; + if (m.userData.isFlame) continue; + const base = m.userData.mat; + if (m.userData.glassable && fx.glass) m.material = M.glass; + else if (m.userData.ownMat) { + m.material = base; + base.transparent = vf < 0.99; + base.depthWrite = vf >= 0.99; + base.opacity = vf; + } else if (vf < 0.99) { + const gm = ghost(base); + gm.opacity = vf; + m.material = gm; + } else m.material = base; + } + } + const apart = fx.apart || 0; + rowG.front.position.z = apart * 0.2; + rowG.rear.position.z = -apart * 0.14; + rowG.rear.visible = (fx.hideRear || 0) < 0.5; + // crank + crank.rear.rotation.z = th * D2R; + crank.front.rotation.z = th * D2R; + // rods and pistons, from the exact geometry of the master and articulated rods + for (const row of ['rear', 'front']) { + const P = rowPose(row, th); + const z = mm(E.rowZ[row]); + const R = rods[row]; + R.master.position.set(mm(-P.C[0]), mm(P.C[1]), z); + R.master.rotation.z = Math.atan2(P.d[0], P.d[1]); + for (const cy of ROWS[row]) { + const x = P.cyl[cy.c]; + pistons[cy.c - 1].position.y = mm(x.s); + if (x.master) continue; + const art = R.arts[cy.c]; + const dx = x.P[0] - x.K[0]; + const dy = x.P[1] - x.K[1]; + art.position.set(mm(-x.K[0]), mm(x.K[1]), z); + art.rotation.z = Math.atan2(dx, dy); + } + } + // the cam rings turn against the crank at 1/8; tappets ride their lobes, rockers and valves follow + for (const row of ['rear', 'front']) camRings[row].rotation.z = th * CAM.ratio * D2R; + for (const C of cylinders) { + const c = C.cy.c; + for (const ev of ['in', 'ex']) { + const T = train[c - 1][ev]; + const L = lift(c, ev, th); + T.tp.position.y = mm(152 + 12 * L); + T.v.position.y = mm(-CAM.liftMm * L); + T.rk.rotation.x = L * 0.2 * (ev === 'in' ? -1 : 1); + const hi = fx.camHi ? fx.camHi[c - 1]?.[ev] || 0 : 0; + if (hi > 0.05) { + T.tp.material = M.accent; + T.v.material = M.accent; + } + } + const glow = fx.glow ? fx.glow[c - 1] : 0; + C.flame.material.opacity = Math.min(0.85, glow) * (vis.cyl ?? 1); + C.flame.visible = glow > 0.01 && (vis.cyl ?? 1) > 0.01 && (!fx.focus || fx.focus === c || (fx.focusK ?? 1) < 0.5); + const hg = fx.headGlow ? fx.headGlow[c - 1] : 0; + if (C.head.material !== M.glass) C.head.material.emissiveIntensity = 0.95 * hg; + } + // the reduction gear: the sun on the crank, the ring fixed, the carrier (and the propeller) at 0.45 + const prop = th * GEAR.prop; + sun.rotation.z = th * D2R; + carrier.rotation.z = prop * D2R; + // a pinion rolling on the fixed ring: its spin relative to the carrier is -(R/p) times the carrier's turn + for (const p of planets) p.rotation.z = (-(rpR / rpP) * prop) * D2R; + propG.rotation.z = (prop + (fx.propOff ?? PROP_OFF)) * D2R; + const blur = fx.blur || 0; + const bo = (1 - blur) * (vis.prop ?? 1); + for (const b of blades) { + b.visible = bo > 0.02; + if (b.visible) { + const gm = bo < 0.99 ? ghost(M.blade) : M.blade; + gm.opacity = bo; + b.material = gm; + } + } + blurDisc.visible = blur > 0.01 && (vis.prop ?? 1) > 0.01; + blurDisc.material.opacity = blur * 0.32 * (vis.prop ?? 1); + blurTip.visible = blurDisc.visible; + blurTip.material.opacity = blur * 0.45 * (vis.prop ?? 1); + blurDisc.rotation.z = prop * D2R; + impG.rotation.z = th * GEAR.impLow * D2R; + for (const mg of magnetos) mg.rotor.rotation.y = th * 0.5 * D2R; + // the charge: dots down the throat, through the impeller, out along every pipe + const airK = fx.airK || 0; + airDots.visible = airK > 0.01; + if (airDots.visible) { + let n = 0; + const ph = fx.air || 0; + const s = 0.011 * airK; + for (let i = 0; i < 18; i++) { + for (let j = 0; j < 5; j++) { + const u = (((j / 5 + ph + i * 0.137) % 1) + 1) % 1; + pipeCurves[i].getPoint(u, tmp); + m4.compose(tmp, q, sc.set(s, s, s)); + airDots.setMatrixAt(n++, m4); + } + } + for (let j = 0; j < 60; j++) { + const u = (((j / 60 + ph * 3) % 1) + 1) % 1; + if (u < 0.5) throat.getPoint(u * 2, tmp); + else { + const a = j * 2.4 + ph * 20; + const r = 0.04 + (u - 0.5) * 0.58; + tmp.set(Math.cos(a) * r, Math.sin(a) * r, -0.31); + } + m4.compose(tmp, q, sc.set(s, s, s)); + airDots.setMatrixAt(n++, m4); + } + airDots.instanceMatrix.needsUpdate = true; + airDots.material.opacity = 0.9 * airK; + } + const oilK = fx.oilK || 0; + oilDots.visible = oilK > 0.01; + M.oil.emissiveIntensity = 0.6 * oilK; + if (oilDots.visible) { + let n = 0; + for (let i = 0; i < 3; i++) + for (let j = 0; j < 10; j++) { + const u = (((j / 10 + (fx.oil || 0)) % 1) + 1) % 1; + oilCurves[i].getPoint(u, tmp); + m4.compose(tmp, q, sc.set(0.014, 0.014, 0.014)); + oilDots.setMatrixAt(n++, m4); + } + oilDots.instanceMatrix.needsUpdate = true; + oilDots.material.opacity = oilK; + } + void up; + void lobeOffset; + }; + + return {root, update, setCut, CLIP, A, parts, M, cylinders, rods, pistons, crank, camRings, blades, rowG, plugAt, cut, FLOOR_Y}; +} diff --git a/machines/radial/r2800-shared/schedule.js b/machines/radial/r2800-shared/schedule.js new file mode 100644 index 0000000..eb0fc8b --- /dev/null +++ b/machines/radial/r2800-shared/schedule.js @@ -0,0 +1,168 @@ +// The film's operator script and its one input. A run of the engine is planned once in physical time τ (s): the +// starter, the ignition, the first firings missed then caught, idle, the climb to take-off rpm, the throttle back. +// The film plays it through a slow-motion map τ(t). The crank angle θ is integrated from the rpm once, at load, and +// every pose, valve, spark, gauge and sound of the film is read from θ(t). No three.js: node imports it for the +// timeline and the score. +import {FIRE, ORDER, RATING, SPARK_ADV, stateAt} from './engine.js'; + +export const DURATION = 40; +export const FPS_TABLE = 1200; // table rate, samples per second of film + +// operator moves: views and the buttons the cursor presses +export const SCRIPT = [ + {t: 0, cam: 'hero'}, + {t: 1.6, press: 'starter'}, + {t: 3.3, press: 'ignition'}, + {t: 6.4, cam: 'face'}, + {t: 12.6, cam: 'rowcut'}, + {t: 18.6, cam: 'apart'}, + {t: 23.6, cam: 'cam'}, + {t: 28.4, cam: 'takeoff', press: 'throttle'}, + {t: 32.6, cam: 'faceFull'}, + {t: 35.4, cam: 'heroEnd', press: 'throttleBack'}, +]; +export const BEATS = SCRIPT.filter((e) => e.t > 0).map((e) => e.t); +export const camAtName = (t) => SCRIPT.filter((e) => e.cam && e.t <= t).pop().cam; +export const camSince = (t) => t - SCRIPT.filter((e) => e.cam && e.t <= t).pop().t; + +const smoother = (x) => { + const u = Math.min(1, Math.max(0, x)); + return u * u * u * (u * (u * 6 - 15) + 10); +}; +// slow motion: τ seconds per film second, eased between keys in log space +const RATE = [ + [0, 1], + [6.4, 1], + [7.6, 1 / 25], + [12.6, 1 / 25], + [13.4, 1 / 40], + [23.6, 1 / 40], + [24.4, 1 / 14], + [28.4, 1 / 14], + [29.6, 1], + [DURATION, 1], +]; +export const rateAt = (t) => { + let i = 0; + while (i < RATE.length - 2 && t >= RATE[i + 1][0]) i++; + const [t0, a] = RATE[i]; + const [t1, b] = RATE[i + 1]; + const k = smoother((t - t0) / (t1 - t0)); + return Math.exp(Math.log(a) + (Math.log(b) - Math.log(a)) * k); +}; + +// ------------------------------------------------------------ the tables: τ(t), then N(τ), θ, the air +const NT = Math.ceil(DURATION * FPS_TABLE) + 2; +const TAU = new Float64Array(NT); +for (let i = 1; i < NT; i++) { + const t = (i - 0.5) / FPS_TABLE; + TAU[i] = TAU[i - 1] + rateAt(t) / FPS_TABLE; +} +const lerpT = (arr, t) => { + const x = Math.min(NT - 1.001, Math.max(0, t * FPS_TABLE)); + const i = Math.floor(x); + return arr[i] + (arr[i + 1] - arr[i]) * (x - i); +}; +export const tauAt = (t) => lerpT(TAU, t); + +// the run, in physical seconds, keyed to the film's beats +export const RUN = (() => { + const s = tauAt(1.6); + const ign = tauAt(3.3); + return { + starter: s, // the starter engages + ign, // magnetos on + catch0: ign + 0.25, // the first firings, mostly missed + catch1: ign + 1.05, // every cylinder firing + disengage: ign + 1.3, // the starter lets go + climb: tauAt(29.7), // the throttle opens + climbLen: 3.0, + back: tauAt(35.6), // the throttle closes + backLen: 3.0, + }; +})(); +const {idle, crank} = RATING; +const TO = RATING.takeoff.rpm; +/** the planned engine speed (rpm) at physical time τ */ +export const rpmAtTau = (tau) => { + const R = RUN; + let N = crank * smoother((tau - R.starter) / 1.0); + // caught: a flare to ~1,050 rpm, then idle + const up = smoother((tau - (R.ign + 0.85)) / 1.0); + const settle = smoother((tau - (R.ign + 1.85)) / 1.15); + N += up * (1050 - crank) - settle * (1050 - idle); + N += smoother((tau - R.climb) / R.climbLen) * (TO - idle); + N -= smoother((tau - R.back) / R.backLen) * (TO - idle); + return Math.max(0, N); +}; +/** 0 on the starter, 1 when every cylinder fires and the engine carries itself */ +export const runAtTau = (tau) => smoother((tau - (RUN.ign + 0.6)) / 1.0); +/** the chance that a spark lights its charge, while the engine catches */ +export const catchAtTau = (tau) => (tau < RUN.ign ? 0 : 0.12 + 0.88 * smoother((tau - RUN.catch0) / (RUN.catch1 - RUN.catch0))); +export const starterAtTau = (tau) => (tau >= RUN.starter && tau < RUN.disengage ? 1 : 0); + +const TH = new Float64Array(NT); // crank angle, degrees +const AIR = new Float64Array(NT); // the charge carried down the pipes, in turns of a pipe (for the particles) +const THETA0 = 6; +TH[0] = THETA0; +for (let i = 1; i < NT; i++) { + const tau = (TAU[i] + TAU[i - 1]) / 2; + const dtau = TAU[i] - TAU[i - 1]; + const N = rpmAtTau(tau); + TH[i] = TH[i - 1] + N * 6 * dtau; + const st = stateAt(N, runAtTau(tau)); + AIR[i] = AIR[i - 1] + (N / 60) * (st.map / 29.92) * dtau * 0.2; +} +export const thetaAt = (t) => lerpT(TH, t); +export const airAt = (t) => lerpT(AIR, t); +export const rpmAt = (t) => rpmAtTau(tauAt(t)); +/** film time at which the crank reaches th (θ is monotone) */ +export const tAtTheta = (th) => { + if (th <= TH[0]) return 0; + let lo = 0; + let hi = NT - 1; + if (th >= TH[hi]) return DURATION; + while (hi - lo > 1) { + const mid = (lo + hi) >> 1; + if (TH[mid] < th) lo = mid; + else hi = mid; + } + const f = (th - TH[lo]) / Math.max(1e-9, TH[hi] - TH[lo]); + return (lo + f) / FPS_TABLE; +}; + +// ------------------------------------------------------------ the sparks +const hash = (n) => { + const x = Math.sin(n * 127.1 + 311.7) * 43758.5453; + return x - Math.floor(x); +}; +const IDX = Object.fromEntries(ORDER.map((c, i) => [c, i])); +/** spark number m of cylinder c (m-th cycle): its crank angle */ +const sparkTheta = (c, m) => FIRE[c] - SPARK_ADV + 720 * m; +/** does spark (c, m) light its charge? the ignition must be on and the engine catching */ +export const firesAt = (c, m, tau) => hash(m * 18 + IDX[c] + 7) < catchAtTau(tau); +/** the last spark of cylinder c at film time t: when it was (film s), whether it lit, its crank angle */ +export function lastSpark(c, t) { + const th = thetaAt(t); + const m = Math.floor((th - (FIRE[c] - SPARK_ADV)) / 720); + const ths = sparkTheta(c, m); + const ts = tAtTheta(ths); + const tau = tauAt(ts); + return {t: ts, th: ths, lit: tau >= RUN.ign && firesAt(c, m, tau), m}; +} +/** every spark of the film after the ignition, for the score: [t, cylinder, lit] */ +export function sparkList() { + const out = []; + const th1 = TH[NT - 1]; + for (const c of ORDER) { + for (let m = -1; sparkTheta(c, m) < th1; m++) { + const ths = sparkTheta(c, m); + if (ths < TH[0]) continue; + const t = tAtTheta(ths); + const tau = tauAt(t); + if (tau < RUN.ign) continue; + out.push([+t.toFixed(4), c, firesAt(c, m, tau) ? 1 : 0]); + } + } + return out.sort((a, b) => a[0] - b[0]); +} diff --git a/machines/radial/r2800-shared/score.py b/machines/radial/r2800-shared/score.py new file mode 100644 index 0000000..6990726 --- /dev/null +++ b/machines/radial/r2800-shared/score.py @@ -0,0 +1,129 @@ +"""Score for Radial (an R-2800 Double Wasp after public sources), every sound on the film's own timeline. + +The starter whines up and settles on A4 (the one key, D minor, that every tonal sound keeps: the starter, the low +drone, the click); the first sparks after the magnetos come on are coughs, the missed ones silent (events.json lists +every spark, lit or not, from the same schedule the film draws). Once the engine runs, each firing is a dull thud +while they come slower than ~12 a second on screen (the slow-motion stretches); faster, they merge into a growl +whose pulse is the firing rate on screen, 9 a turn, with the half- and first-order beats under it. The propeller's +wash rises with its speed. A quiet click on each button the tour's cursor presses. + + node r2800-shared/make-timeline.mjs && python3 "$SKILL_DIR/run_sfx.py" r2800-shared/score.py +""" + +import json +import math +import os +import random + +from sfx.dsp import svf, zeros +from sfx.score_kit import airy, bang, hz, thud +from sfx.synth import SR, bandnoise, click + +TIMELINE = "../r2800-film/timeline.json" +OUT = os.path.join(os.environ.get("TEARDOWN_OUT", "teardown-out"), "radial-score.wav") +TARGET_LUFS = -14.0 +SEED = 2800 +HERE = os.path.dirname(os.path.abspath(__file__)) + + +def smooth(a, b, x): + u = min(1.0, max(0.0, (x - a) / (b - a))) + return u * u * (3 - 2 * u) + + +def score(mix, tl): + dur = tl["duration"] + b = tl["beats"] + with open(os.path.join(HERE, "../r2800-film/events.json"), encoding="utf8") as f: + ev = json.load(f) + rate = ev["rate"] + S = ev["samples"] # rpm, slow, map, fireHzScreen, theta + n = int(dur * SR) + + def at(t, i): + x = min(len(S) - 1.001, max(0.0, t * rate)) + k = int(x) + return S[k][i] + (S[k + 1][i] - S[k][i]) * (x - k) + + # ---------------------------------------------------------------- the low drone: D, very quiet, the whole way + drone = zeros(n) + f0 = hz("D2") + for k in range(n): + t = k / SR + env = min(1.0, t / 2.0, (dur - t) / 2.5) + drone[k] = env * (math.sin(2 * math.pi * f0 * t) + 0.5 * math.sin(2 * math.pi * f0 * 1.5 * t + 0.4 * math.sin(0.3 * t)) + 0.3 * math.sin(2 * math.pi * f0 * 2 * t)) + drone = svf(drone, 500, 0.6, "lp") + mix.put(0, drone, 0.05) + + # ---------------------------------------------------------------- the starter: a whine up to A4, then it lets go + t0 = b["starter"] + t1 = b["disengage"] + m = int((t1 - t0 + 0.6) * SR) + whine = [] + ph = 0.0 + for k in range(m): + t = t0 + k / SR + spin = smooth(t0, t0 + 1.0, t) if t < t1 else max(0.0, 1 - (t - t1) / 0.6) + f = hz("A4") * (0.25 + 0.75 * spin) + ph += 2 * math.pi * f / SR + g = spin * (1 if t < t1 else 0.8) + whine.append(g * (math.sin(ph) * 0.6 + 0.25 * math.sin(2 * ph) + 0.12 * math.sin(3 * ph))) + mix.put(t0, svf(whine, 2400, 0.7, "lp"), 0.06) + mix.put(t0, airy(t1 - t0 + 0.4, 300, 900, 0.5), 0.02) + + # ---------------------------------------------------------------- sparks: coughs while it catches, thuds in slow motion + rnd = random.Random(SEED) + catch_end = b["disengage"] + 0.6 + for t, c, lit in ev["sparks"]: + if t >= dur - 0.05: + continue + fire = at(t, 3) + if t < catch_end: + if lit: + mix.put(t, bang(0.5 + 0.5 * rnd.random(), seed=int(t * 1000)), 0.11 * (0.6 + 0.4 * rnd.random()), rnd.uniform(-0.25, 0.25)) + continue + g = 1 - smooth(8, 18, fire) + if g > 0.01: + mix.put(t, thud(54 + 6 * (c % 3), 0.07, 0.32), 0.16 * g, 0.12 if c % 2 else -0.12) + + # ---------------------------------------------------------------- the growl: the firings merged, pulse = their rate on screen + growl = zeros(n) + ph = 0.0 + phc = 0.0 + for k in range(n): + t = k / SR + fire = at(t, 3) + level = smooth(10, 30, fire) + if fire <= 0.5: + continue + ph += 2 * math.pi * fire / SR + phc += 2 * math.pi * fire / 9 / SR + # a pulse train at the firing rate, the first and half orders under it (rows and rods not quite alike) + p = math.sin(ph) + 0.5 * math.sin(2 * ph) + 0.25 * math.sin(3 * ph) + p *= 0.75 + 0.25 * math.sin(phc) + 0.12 * math.sin(phc / 2) + sub = math.sin(phc) * 0.6 + math.sin(phc / 2) * 0.35 + growl[k] = level * (math.tanh(1.4 * p) * 0.7 + sub) + growl = svf(growl, 900, 0.7, "lp") + mix.put(0, growl, 0.11) + # the exhaust's grit over it: band noise opening with the rpm + grit = bandnoise(n, lambda k: 300 + 1.1 * at(k / SR, 0) * at(k / SR, 1), q=0.6) + for k in range(n): + t = k / SR + grit[k] *= smooth(10, 30, at(t, 3)) * (0.3 + 0.7 * min(1.0, at(t, 0) / 2700)) + mix.put(0, grit, 0.05) + + # ---------------------------------------------------------------- the propeller's wash: air, rising with its speed, blade-pass beat + wash = bandnoise(n, lambda k: 700 + 500 * min(1.0, at(k / SR, 0) / 2700), q=0.5) + php = 0.0 + for k in range(n): + t = k / SR + N = at(t, 0) * at(t, 1) + bpf = 3 * N * 0.45 / 60 + php += 2 * math.pi * bpf / SR + lvl = (min(1.0, N / 2700)) ** 2 + wash[k] *= lvl * (0.8 + 0.2 * math.sin(php)) + mix.put(0, wash, 0.09) + + # ---------------------------------------------------------------- the cursor's clicks + for t in b["views"]: + mix.put(t, click(2200, 0.03), 0.05) diff --git a/machines/radial/r2800-shared/stage.js b/machines/radial/r2800-shared/stage.js new file mode 100644 index 0000000..f3d77c2 --- /dev/null +++ b/machines/radial/r2800-shared/stage.js @@ -0,0 +1,218 @@ +// Radial's stage: a 1940s airfield under a white overcast. A sky dome pale at the zenith (#e4ebf0) down to a warm, +// light horizon; a light concrete apron in 5 m slabs fading into the haze; a hard outdoor sun from the upper left +// with a crisp shadow on the concrete; a pale sky fill. frame(fx, cam) poses the engine and draws one frame. +import * as THREE from 'three'; +import {EffectComposer} from 'three/addons/postprocessing/EffectComposer.js'; +import {GTAOPass} from 'three/addons/postprocessing/GTAOPass.js'; +import {OutputPass} from 'three/addons/postprocessing/OutputPass.js'; +import {Pass} from 'three/addons/postprocessing/Pass.js'; +import {RenderPass} from 'three/addons/postprocessing/RenderPass.js'; +import {buildEngine, FLOOR_Y} from './model.js'; + +const V3 = THREE.Vector3; +export const SKY = {zenith: '#e4ebf0', mid: '#edf0f0', horizon: '#f3ece1', ground: '#e6dfd3'}; + +function skyDome() { + const mat = new THREE.ShaderMaterial({ + side: THREE.BackSide, + depthWrite: false, + fog: false, + uniforms: { + zen: {value: new THREE.Color(SKY.zenith)}, + mid: {value: new THREE.Color(SKY.mid)}, + hor: {value: new THREE.Color(SKY.horizon)}, + gnd: {value: new THREE.Color(SKY.ground)}, + }, + vertexShader: 'varying vec3 vD; void main(){ vD = normalize(position); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); gl_Position.z = gl_Position.w; }', + fragmentShader: + 'uniform vec3 zen; uniform vec3 mid; uniform vec3 hor; uniform vec3 gnd; varying vec3 vD;' + + 'void main(){ float y = vD.y; vec3 c;' + + ' if (y > 0.0) { float a = clamp(y / 0.18, 0.0, 1.0); float b = clamp((y - 0.18) / 0.6, 0.0, 1.0); c = mix(mix(hor, mid, a), zen, b); }' + + ' else { c = mix(hor, gnd, clamp(-y / 0.08, 0.0, 1.0)); }' + + ' gl_FragColor = vec4(c, 1.0); }', + }); + const m = new THREE.Mesh(new THREE.SphereGeometry(80, 32, 16), mat); + m.frustumCulled = false; + m.renderOrder = -10; + return m; +} +function concreteTexture() { + const c = document.createElement('canvas'); + c.width = c.height = 512; + const g = c.getContext('2d'); + g.fillStyle = '#d9d3c8'; + g.fillRect(0, 0, 512, 512); + // a fixed speckle (a seeded generator: the texture is the same every load) + let s = 7; + const r = () => ((s = (s * 16807) % 2147483647) / 2147483647); + for (let i = 0; i < 9000; i++) { + const v = 190 + Math.floor(r() * 40); + g.fillStyle = `rgba(${v},${v - 4},${v - 12},${0.25 + r() * 0.3})`; + g.fillRect(r() * 512, r() * 512, 1 + r() * 2, 1 + r() * 2); + } + for (let i = 0; i < 14; i++) { + g.fillStyle = `rgba(150,140,125,${0.04 + r() * 0.05})`; + g.beginPath(); + g.ellipse(r() * 512, r() * 512, 20 + r() * 70, 10 + r() * 40, r() * 3, 0, Math.PI * 2); + g.fill(); + } + // the joints of a slab + g.strokeStyle = 'rgba(140,132,120,0.3)'; + g.lineWidth = 2.5; + g.strokeRect(1.5, 1.5, 509, 509); + const t = new THREE.CanvasTexture(c); + t.wrapS = t.wrapT = THREE.RepeatWrapping; + t.repeat.set(16, 16); + t.anisotropy = 8; + t.colorSpace = THREE.SRGBColorSpace; + return t; +} + +export function createStage({canvas}) { + const renderer = new THREE.WebGLRenderer({canvas, antialias: false, preserveDrawingBuffer: true, powerPreference: 'high-performance'}); + renderer.toneMapping = THREE.NeutralToneMapping; + renderer.outputColorSpace = THREE.SRGBColorSpace; + renderer.shadowMap.enabled = true; + renderer.shadowMap.type = THREE.PCFShadowMap; + renderer.localClippingEnabled = true; + const scene = new THREE.Scene(); + scene.background = new THREE.Color(SKY.horizon); + scene.fog = new THREE.Fog(SKY.horizon, 14, 46); + const sky = skyDome(); + scene.add(sky); + const camera = new THREE.PerspectiveCamera(26, 16 / 9, 0.02, 120); + const composer = new EffectComposer(renderer, new THREE.WebGLRenderTarget(4, 4, {type: THREE.HalfFloatType, samples: 8})); + composer.addPass(new RenderPass(scene, camera)); + const gtao = new GTAOPass(scene, camera, 4, 4); + gtao.output = GTAOPass.OUTPUT.Default; + gtao.blendIntensity = 0.65; + gtao.updateGtaoMaterial({radius: 0.07, distanceExponent: 1.4, thickness: 0.6, scale: 1.0, samples: 16, distanceFallOff: 1.0, screenSpaceRadius: false}); + gtao.updatePdMaterial({lumaPhi: 10, depthPhi: 2, normalPhi: 3, radius: 6, rings: 2, samples: 16}); + class Toggle extends Pass { + constructor(fn) { + super(); + this.needsSwap = false; + this.fn = fn; + } + render() { + this.fn(); + } + } + const aoSkip = (on) => { + sky.visible = on; + floor.visible = on; + }; + composer.addPass(new Toggle(() => aoSkip(false))); + composer.addPass(gtao); + composer.addPass(new Toggle(() => aoSkip(true))); + composer.addPass(new OutputPass()); + + // an overcast sky for the metal to reflect: bright above, the warm apron below, a brighter patch toward the sun + { + const env = new THREE.Scene(); + env.background = new THREE.Color('#d6dbde'); + const box = (w, h, pos, color, k) => { + const m = new THREE.Mesh(new THREE.PlaneGeometry(w, h), new THREE.MeshBasicMaterial({color: new THREE.Color(color).multiplyScalar(k), side: THREE.DoubleSide})); + m.position.copy(pos); + m.lookAt(0, 0, 0); + env.add(m); + }; + box(30, 30, new V3(0, 16, 0), '#eef2f5', 2.2); + box(10, 8, new V3(-12, 9, 6), '#ffffff', 3.0); + box(30, 4, new V3(0, 1, -16), '#f2ece2', 1.3); + box(30, 4, new V3(0, 1, 16), '#f2ece2', 1.3); + const g = new THREE.Mesh(new THREE.CircleGeometry(40, 32), new THREE.MeshBasicMaterial({color: '#bdb6aa', side: THREE.DoubleSide})); + g.rotation.x = -Math.PI / 2; + g.position.y = -3; + env.add(g); + const pm = new THREE.PMREMGenerator(renderer); + scene.environment = pm.fromScene(env, 0.03).texture; + scene.environmentIntensity = 0.75; + pm.dispose(); + } + const sun = new THREE.DirectionalLight('#fffaf0', 3.0); + sun.position.set(-4.2, 7.5, 3.4); + sun.target.position.set(0, -0.6, -0.2); + sun.castShadow = true; + Object.assign(sun.shadow.camera, {left: -3.2, right: 3.2, top: 3.2, bottom: -3.2, near: 2, far: 20}); + sun.shadow.mapSize.set(4096, 4096); + sun.shadow.bias = -0.0003; + sun.shadow.normalBias = 0.012; + scene.add(sun, sun.target); + scene.add(new THREE.HemisphereLight('#eaf0f4', '#cbbfae', 0.9)); + + const floor = new THREE.Mesh(new THREE.PlaneGeometry(120, 120), new THREE.MeshStandardMaterial({color: '#ffffff', map: concreteTexture(), roughness: 0.92, metalness: 0})); + floor.rotation.x = -Math.PI / 2; + floor.position.y = FLOOR_Y; + floor.receiveShadow = true; + floor.material.map.repeat.set(24, 24); + scene.add(floor); + + const eng = buildEngine(); + scene.add(eng.root); + + const size = {w: 1600, h: 900, pr: 1}; + const resize = (w, h, pr) => { + size.w = w; + size.h = h; + size.pr = pr; + renderer.setPixelRatio(pr); + renderer.setSize(w, h, false); + composer.setPixelRatio(pr); + composer.setSize(w, h); + camera.aspect = w / h; + camera.updateProjectionMatrix(); + }; + let aoWanted = true; + // cam: target (tx, ty, tz), azimuth from +z toward +x, elevation, distance (radians, metres), sx/sy screen shift + const frame = (fx, cam) => { + const {tx, ty, tz, az, el, d} = cam; + camera.position.set(tx + d * Math.cos(el) * Math.sin(az), ty + d * Math.sin(el), tz + d * Math.cos(el) * Math.cos(az)); + camera.lookAt(tx, ty, tz); + camera.fov = cam.fov ?? 26; + camera.near = Math.max(0.01, d * 0.03); + camera.updateProjectionMatrix(); + camera.setViewOffset(size.w, size.h, -(cam.sx ?? 0), -(cam.sy ?? 0), size.w, size.h); + camera.updateMatrixWorld(); + sky.position.copy(camera.position); + gtao.enabled = aoWanted && eng.cut.mode !== 'section' && !fx.glass; + eng.update(fx); + composer.render(); + }; + const pv = new V3(); + const project = (p) => { + if (!p) return null; + pv.copy(p).project(camera); + if (pv.z > 1) return null; + return [(pv.x * 0.5 + 0.5) * size.w, (-pv.y * 0.5 + 0.5) * size.h]; + }; + const setQuality = ({samples, ao, shadow}) => { + if (samples !== undefined) { + for (const t of [composer.renderTarget1, composer.renderTarget2]) { + t.samples = samples; + t.dispose(); + } + } + if (ao !== undefined) aoWanted = ao; + if (shadow !== undefined) { + sun.shadow.mapSize.set(shadow, shadow); + sun.shadow.map?.dispose(); + sun.shadow.map = null; + } + }; + // the section plane: n·x + c ≥ 0 is kept + const planes = { + rowcut: new THREE.Plane(new V3(0, 0, -1), 0.105), + profile: new THREE.Plane(new V3(-1, 0, 0), 0), + inside: new THREE.Plane(new V3(-1, 0, 0), 0), + }; + let cutKey = ''; + const setCut = (mode, planeKey = 'profile') => { + const key = mode + ':' + planeKey; + if (key === cutKey) return; + cutKey = key; + eng.setCut(mode, planes[planeKey]); + }; + setCut('solid'); + return {renderer, scene, camera, eng, composer, gtao, sun, resize, frame, project, size, setQuality, setCut, planes}; +} diff --git a/package-lock.json b/package-lock.json index b4c6f1b..17297ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,8 +10,10 @@ "license": "MIT", "dependencies": { "@fontsource-variable/inter": "5.3.0", + "@fontsource/barlow-condensed": "5.3.0", "@fontsource/instrument-serif": "^5.3.0", "@fontsource/jetbrains-mono": "5.3.0", + "@fontsource/saira-stencil-one": "5.3.0", "esbuild": "0.28.1", "three": "0.186.1" } @@ -441,6 +443,15 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "node_modules/@fontsource/barlow-condensed": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@fontsource/barlow-condensed/-/barlow-condensed-5.3.0.tgz", + "integrity": "sha512-RA7MmIx0v3eQ6Gcf74qLVLOwLB0GpPOzx+eU9iG/AmCnSJGcIWYeU8y6CEMGZ210MGwGg5CZhzLkkvyZdTTk1g==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/@fontsource/instrument-serif": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/@fontsource/instrument-serif/-/instrument-serif-5.3.0.tgz", @@ -459,6 +470,15 @@ "url": "https://github.com/sponsors/ayuhito" } }, + "node_modules/@fontsource/saira-stencil-one": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@fontsource/saira-stencil-one/-/saira-stencil-one-5.3.0.tgz", + "integrity": "sha512-b7ILM7KrAWTIUSWKuzV29lTQZV5QOGhlmXXEt3Dsg/rJ4lo1kjUjuo6dBG9Iq+pR7wRZCVXftinVHDof+i9nSA==", + "license": "OFL-1.1", + "funding": { + "url": "https://github.com/sponsors/ayuhito" + } + }, "node_modules/esbuild": { "version": "0.28.1", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", diff --git a/package.json b/package.json index 12c5ea9..52b3aba 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,16 @@ "description": "Exploded: real machines, built from code with their real numbers, that you can take apart in the browser.", "license": "MIT", "scripts": { - "check": "node machines/spindl/check.mjs && node machines/quantum/check.mjs && node scripts/test-root-lang.mjs", + "check": "node machines/spindl/check.mjs && node machines/quantum/check.mjs && node machines/radial/check.mjs && node scripts/test-root-lang.mjs", "build": "node scripts/build.mjs", "test": "npm run check && npm run build" }, "dependencies": { "@fontsource-variable/inter": "5.3.0", + "@fontsource/barlow-condensed": "5.3.0", "@fontsource/instrument-serif": "^5.3.0", "@fontsource/jetbrains-mono": "5.3.0", + "@fontsource/saira-stencil-one": "5.3.0", "esbuild": "0.28.1", "three": "0.186.1" } diff --git a/scripts/build.mjs b/scripts/build.mjs index 0e186a3..63eb0b4 100644 --- a/scripts/build.mjs +++ b/scripts/build.mjs @@ -57,6 +57,8 @@ const bundle = async (entry) => { write: false, target: 'es2022', legalComments: 'none', + // a machine may inline its own type (Radial's fonts.js) + loader: {'.woff2': 'base64'}, logLevel: 'warning', }); return res.outputFiles[0].text.replace(/<\/script/g, '<\\/script'); diff --git a/scripts/machines.mjs b/scripts/machines.mjs index a73ce2c..c693300 100644 --- a/scripts/machines.mjs +++ b/scripts/machines.mjs @@ -1,6 +1,35 @@ // The collection: one entry per machine, newest first (the gallery's order). Each machine lives in machines//, // its live page's entry point is `entry`, its share card `og` (1200 x 630, also the gallery's thumbnail). export const MACHINES = [ + { + slug: 'radial', + name: 'Radial', + entry: 'machines/radial/r2800-live/main.js', + og: 'machines/radial/og.png', + meta: { + en: { + title: 'Radial · the R-2800 Double Wasp, taken apart', + line: 'An 18-cylinder twin-row radial: the starter, the firing order round the star, a master rod and its eight articulated rods, the cam rings, take-off rpm.', + description: + 'The Pratt & Whitney R-2800 Double Wasp you can take apart in the browser: 18 cylinders in two rows, a master rod and eight articulated rods per row, cam rings instead of a camshaft, the run from the starter to 2,700 rpm. A C-series R-2800 after public sources; not affiliated with Pratt & Whitney.', + locale: 'en_US', + }, + fr: { + title: 'Radial · le R-2800 Double Wasp, démonté', + line: 'Un moteur en étoile à 18 cylindres sur deux rangées : le démarreur, l’ordre d’allumage autour de l’étoile, une bielle maîtresse et ses huit biellettes, les anneaux à cames, le régime de décollage.', + description: + 'Le Pratt & Whitney R-2800 Double Wasp à démonter dans le navigateur : 18 cylindres sur deux rangées, une bielle maîtresse et huit biellettes par rangée, des anneaux à cames au lieu d’un arbre à cames, la marche du démarreur à 2 700 tr/min. Un R-2800 de série C d’après les sources publiques ; sans lien avec Pratt & Whitney.', + locale: 'fr_FR', + }, + es: { + title: 'Radial · el R-2800 Double Wasp, desmontado', + line: 'Un motor radial de 18 cilindros en dos filas: el arranque, el orden de encendido alrededor de la estrella, una biela maestra y sus ocho articuladas, los anillos de levas, el régimen de despegue.', + description: + 'El Pratt & Whitney R-2800 Double Wasp para desmontar en el navegador: 18 cilindros en dos filas, una biela maestra y ocho articuladas por fila, anillos de levas en lugar de árbol de levas, la marcha del arranque a 2700 rpm. Un R-2800 de la serie C según fuentes públicas; sin relación con Pratt & Whitney.', + locale: 'es_ES', + }, + }, + }, { slug: 'quantum', name: 'Quantum', @@ -67,7 +96,7 @@ export const GALLERY = { lead: 'Real machines, built from code with their real numbers, that you can take apart in the browser.', sub: 'Every gauge reads the same model that moves the parts. Left alone, each one plays a guided tour; any click hands control over.', open: 'Open', - description: 'Real machines, built from code with their real numbers, that you can take apart in the browser: a hard drive, a photonic quantum computer.', + description: 'Real machines, built from code with their real numbers, that you can take apart in the browser: an 18-cylinder radial engine, a hard drive, a photonic quantum computer.', locale: 'en_US', }, fr: { @@ -75,7 +104,7 @@ export const GALLERY = { lead: 'De vraies machines, construites en code avec leurs vrais chiffres, à démonter dans le navigateur.', sub: 'Chaque jauge lit le modèle qui fait bouger les pièces. Laissée seule, chacune joue une visite guidée ; un clic suffit pour prendre la main.', open: 'Ouvrir', - description: 'De vraies machines, construites en code avec leurs vrais chiffres, à démonter dans le navigateur : un disque dur, un ordinateur quantique photonique.', + description: 'De vraies machines, construites en code avec leurs vrais chiffres, à démonter dans le navigateur : un moteur en étoile à 18 cylindres, un disque dur, un ordinateur quantique photonique.', locale: 'fr_FR', }, es: { @@ -83,7 +112,7 @@ export const GALLERY = { lead: 'Máquinas reales, construidas en código con sus cifras reales, para desmontar en el navegador.', sub: 'Cada indicador lee el mismo modelo que mueve las piezas. Si la dejas sola, cada una hace una visita guiada; cualquier clic te da el control.', open: 'Abrir', - description: 'Máquinas reales, construidas en código con sus cifras reales, para desmontar en el navegador: un disco duro, un ordenador cuántico fotónico.', + description: 'Máquinas reales, construidas en código con sus cifras reales, para desmontar en el navegador: un motor radial de 18 cilindros, un disco duro, un ordenador cuántico fotónico.', locale: 'es_ES', }, };