Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
<!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