Last active
June 25, 2021 18:41
-
-
Save Gro-Tsen/556f407eb74abd26aeb524c97d9c500f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> | |
<head> | |
<meta charset="utf-8" /> | |
<title>Rampe parking</title> | |
</head> | |
<body> | |
<h1>Rampe parking</h1> | |
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" | |
viewBox="0 0 494 569" width="494" height="569" | |
style="stroke-linecap: round; stroke-linejoin: round" id="svg"> | |
<g transform="scale(30,30) translate(0.3,0.3)"> | |
<g style="stroke: rgb(0,0,0); stroke-width: 0.05; fill: none; stroke-dasharray: 0.25 0.25"> | |
<path d="M 0.945 1.375" id="trail" /> | |
</g> | |
<g style="stroke: rgb(0,0,0); stroke-width: 0.3; fill: none"> | |
<path d="M 0.00 0.00 L 9.37 0.00 A 6.50 6.50 0 0 1 15.87 6.50 L 15.87 18.38" /> | |
<path d="M 0.00 2.75 L 7.62 2.75 A 5.50 5.50 0 0 1 13.12 8.25 L 13.12 18.38" /> | |
</g> | |
<g style="fill: none"> | |
<path d="M -0.15 0.15 L 9.37 0.15 A 6.35 6.35 0 0 1 15.72 6.50 L 15.72 18.53 | |
L 13.27 18.53 L 13.27 8.25 A 5.65 5.65 0 0 0 7.62 2.60 L -0.15 2.60" | |
id="permitted-region" /> | |
<!-- (Shave 2.5cm off) | |
<path d="M -0.15 0.125 L 9.37 0.125 A 6.375 6.375 0 0 1 15.745 6.50 L 15.745 18.53 | |
L 13.245 18.53 L 13.245 8.25 A 5.625 5.625 0 0 0 7.62 2.625 L -0.15 2.625" | |
id="permitted-region" /> | |
--> | |
<!-- (Easier: shave 5cm off) | |
<path d="M -0.15 0.10 L 9.37 0.10 A 6.40 6.40 0 0 1 15.77 6.50 L 15.77 18.53 | |
L 13.22 18.53 L 13.22 8.25 A 5.60 5.60 0 0 0 7.62 2.65 L -0.15 2.65" | |
id="permitted-region" /> | |
--> | |
</g> | |
<g transform="translate(0.945,1.375) rotate(0)" id="car"> | |
<g transform="translate(-0.945,-0.925)" style="fill: rgb(192,192,192)"> | |
<rect width="4.69" height="1.85" /> <!-- Car body --> | |
</g> | |
<g transform="translate(0,-0.825)" style="fill: rgb(64,64,64)"> | |
<rect x="-0.25" y="-0.10" width="0.50" height="0.20" /> <!-- Rear left wheel --> | |
</g> | |
<g transform="translate(0,0.825)" style="fill: rgb(64,64,64)"> | |
<rect x="-0.25" y="-0.10" width="0.50" height="0.20" /> <!-- Rear right wheel --> | |
</g> | |
<g transform="translate(2.83,-0.825)" style="fill: rgb(64,64,64)"> | |
<g transform="rotate(0)" id="front-left"> | |
<rect x="-0.25" y="-0.10" width="0.50" height="0.20" /> <!-- Front left wheel --> | |
</g> | |
</g> | |
<g transform="translate(2.83,0.825)" style="fill: rgb(64,64,64)"> | |
<g transform="rotate(0)" id="front-right"> | |
<rect x="-0.25" y="-0.10" width="0.50" height="0.20" /> <!-- Front right wheel --> | |
</g> | |
</g> | |
</g> | |
</g> | |
</svg> | |
<script type="text/javascript"> | |
// <![CDATA[ | |
"use strict"; | |
const axldist = 2.83; | |
const axlbrea = 1.85 - 0.20; | |
const carlength = 4.69; | |
const carwidth = 1.85; | |
const carrear = 0.945; | |
var posx = 0.945; | |
var posy = 1.375; | |
var angl = 0; | |
var whee = 0; | |
const max_whee = 35; | |
var trail_path = "M " + posx + " " + posy; | |
var last_path_seg = ""; | |
var last_path_seg_whee; | |
var last_path_seg_sign_dst; | |
var last_path_seg_tot_dst = 0; | |
var svg = document.getElementById("svg"); | |
var car = document.getElementById("car"); | |
var front_left = document.getElementById("front-left"); | |
var front_right = document.getElementById("front-right"); | |
var permitted_region = document.getElementById("permitted-region"); | |
var trail = document.getElementById("trail"); | |
function draw_car() { | |
"use strict"; | |
car.transform.baseVal.getItem(0).setTranslate(posx,posy); | |
car.transform.baseVal.getItem(1).setRotate(angl,0,0); | |
var whee_left, whee_right; | |
if ( whee == 0 ) { | |
whee_left = 0; whee_right = 0; | |
} else { | |
var steer_rad = axldist / Math.tan(whee/180*Math.PI); | |
whee_left = Math.atan(axldist/(steer_rad+axlbrea/2))/Math.PI*180; | |
whee_right = Math.atan(axldist/(steer_rad-axlbrea/2))/Math.PI*180; | |
} | |
front_left.transform.baseVal.getItem(0).setRotate(whee_left,0,0); | |
front_right.transform.baseVal.getItem(0).setRotate(whee_right,0,0); | |
} | |
function advance_car(dst, check) { | |
"use strict"; | |
var dispu, dispv, dispa, dispx, dispy; | |
if ( whee == 0 ) { | |
dispu = dst; | |
dispv = 0; | |
dispa = 0; | |
} else { | |
var steer_rad = axldist / Math.tan(whee/180*Math.PI); | |
var eps = dst / steer_rad; | |
dispu = steer_rad * Math.sin(eps); | |
dispv = steer_rad * (1 - Math.cos(eps)); | |
dispa = eps/Math.PI*180; | |
} | |
dispx = dispu * Math.cos(angl/180*Math.PI) - dispv * Math.sin(angl/180*Math.PI); | |
dispy = dispu * Math.sin(angl/180*Math.PI) + dispv * Math.cos(angl/180*Math.PI); | |
var new_posx = posx + dispx; | |
var new_posy = posy + dispy; | |
var new_angl = angl + dispa; | |
var check_ok = true; | |
if ( check ) { | |
var new_cos = Math.cos(new_angl/180*Math.PI); | |
var new_sin = Math.sin(new_angl/180*Math.PI); | |
var check_points = [ | |
[ 0, 0 ], | |
[ axldist, 0 ], | |
[ 0, carwidth/2 ], | |
[ 0, -carwidth/2 ], | |
[ axldist/4, carwidth/2 ], | |
[ axldist/4, -carwidth/2 ], | |
[ axldist/2, carwidth/2 ], | |
[ axldist/2, -carwidth/2 ], | |
[ 3*axldist/4, carwidth/2 ], | |
[ 3*axldist/4, -carwidth/2 ], | |
[ axldist, carwidth/2 ], | |
[ axldist, -carwidth/2 ], | |
[ -carrear, carwidth/2 ], | |
[ -carrear, 0 ], | |
[ -carrear, -carwidth/2 ], | |
[ carlength-carrear, carwidth/2 ], | |
[ carlength-carrear, 0 ], | |
[ carlength-carrear, -carwidth/2 ] | |
]; | |
for ( var pt of check_points ) { | |
var test_x = new_posx + new_cos*pt[0] - new_sin*pt[1]; | |
var test_y = new_posy + new_cos*pt[1] + new_sin*pt[0]; | |
// New API is to use `new DOMPointInit(test_x, test_y)` | |
// but this does not work in Chrome. Use SVGPoint instead: | |
var test_pt = svg.createSVGPoint(); | |
test_pt.x = test_x; | |
test_pt.y = test_y; | |
if ( ! permitted_region.isPointInFill(test_pt) ) | |
check_ok = false; | |
} | |
} | |
if ( check_ok ) { | |
// Using Bezier curves: | |
/* | |
var ctrlx = posx + (dst/3) * Math.cos(angl/180*Math.PI); | |
var ctrly = posy + (dst/3) * Math.sin(angl/180*Math.PI); | |
var new_ctrlx = new_posx - (dst/3) * Math.cos(new_angl/180*Math.PI); | |
var new_ctrly = new_posy - (dst/3) * Math.sin(new_angl/180*Math.PI); | |
var new_pathseg = " C " + ctrlx + " " + ctrly + " " + new_ctrlx + " " + new_ctrly + " " + new_posx + " " + new_posy; | |
trail_path += new_pathseg; | |
*/ | |
// Using arcs: | |
/* */ | |
var new_pathseg; | |
if ( whee == 0 ) { | |
new_pathseg = " L " + new_posx + " " + new_posy; | |
} else { | |
new_pathseg = " A " + Math.abs(steer_rad) | |
+ " " + Math.abs(steer_rad) | |
+ " 0 0 " + (steer_rad>0 ? "1" : "0") | |
+ " " + new_posx + " " + new_posy; | |
} | |
if ( whee != last_path_seg_whee | |
|| Math.sign(dst) != last_path_seg_sign_dst | |
|| last_path_seg_tot_dst + Math.abs(dst) > 1 ) { | |
trail_path += last_path_seg; | |
// console.log("new path segment after length " + last_path_seg_tot_dst); | |
last_path_seg = new_pathseg; | |
last_path_seg_whee = whee; | |
last_path_seg_sign_dst = Math.sign(dst); | |
last_path_seg_tot_dst = 0; | |
} else { | |
last_path_seg = new_pathseg; | |
last_path_seg_tot_dst += Math.abs(dst); | |
} | |
/* */ | |
posx = new_posx; | |
posy = new_posy; | |
angl = new_angl; | |
trail.setAttribute("d", trail_path + last_path_seg); | |
} | |
} | |
function keyListener(evt) { | |
"use strict"; | |
if ( evt.key == "ArrowUp" ) { | |
advance_car(0.05, true); draw_car(); | |
evt.preventDefault(); | |
} else if ( evt.key == "ArrowDown" ) { | |
advance_car(-0.05, true); draw_car(); | |
evt.preventDefault(); | |
} else if ( evt.key == "ArrowLeft" ) { | |
whee -= 1; if ( whee < -max_whee ) whee = -max_whee; draw_car(); | |
evt.preventDefault(); | |
} else if ( evt.key == "ArrowRight" ) { | |
whee += 1; if ( whee > max_whee ) whee = max_whee; draw_car(); | |
evt.preventDefault(); | |
} | |
} | |
document.addEventListener("keydown", keyListener); | |
// ]]> | |
</script> | |
<p>Utiliser les flêches ← et → pour tourner les roues avant, et ↑ pour | |
avancer, ↓ pour reculer (marche arrière). Le but est de faire | |
parvenir la voiture à l'autre extrémité de la rampe, si possible sans | |
marche arrière.</p> | |
<p>(La ligne en pointillés montre la trajectoire du milieu des roues | |
arrière.)</p> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment