Статья по теме:
Демо JavaScript:
var ctx, canvas, h, w, m, xs = [], ys = [], xt = [], yt = [], min = [], ans, xcen, ycen, k; window.onload = function(){ canvas = document.getElementById("paint"); w = canvas.width; h = canvas.height; ctx = canvas.getContext("2d"); ctx.fillStyle = "white"; }; function Init(){ // Инициализация переменных var xa, xb, ya, yb, xc, xd, yc, yd; // точки концов отрезков // массивы, содержащие информацию о точках и длинах всех рассматриваемых отрезков xs = []; ys = []; xt = []; yt = []; min = []; //счётчик для переходу по элементам вышеуказанных массивов k = 0; // ввод всех концов отрезков и масштаба xa = parseInt(document.getElementById("xa").value); xb = parseInt(document.getElementById("xb").value); xc = parseInt(document.getElementById("xc").value); xd = parseInt(document.getElementById("xd").value); ya = parseInt(document.getElementById("ya").value); yb = parseInt(document.getElementById("yb").value); yc = parseInt(document.getElementById("yc").value); yd = parseInt(document.getElementById("yd").value); m = parseInt(document.getElementById("m").value); // центры по x и y xcen = w / 2; ycen = h / 2; //alert(xa + " " + ya + " " + xb + " " + yb + " " + xc + " " + yc + " " + xd + " " + yd); //запуск функции вычисления execute(xa, ya, xb, yb, xc, yc, xd, yd); } //функция, которая отрисовывает координатную ось function draw_back(){ ctx.fillRect(0, 0, w, h); ctx.strokeStyle = "black"; ctx.beginPath(); ctx.moveTo(xcen, 0); ctx.lineTo(xcen, h); ctx.moveTo(0, ycen); ctx.lineTo(w, ycen); ctx.closePath(); ctx.stroke(); } //функция, которая отрисовывает отрезки function draw_sections(xa, ya, xb, yb, xc, yc, xd, yd){ ctx.strokeStyle = "red"; ctx.beginPath(); ctx.moveTo(xcen + (xa * m), (h - ya * m) - ycen); ctx.lineTo(xcen + (xb * m), (h - yb * m) - ycen); ctx.moveTo(xcen + (xc * m), (h - yc * m) - ycen); ctx.lineTo(xcen + (xd * m), (h - yd * m) - ycen); ctx.closePath(); ctx.stroke(); } //функция, которая отрисовывает отрезок, длина которого и является кратчайшим расстоянием между двумя отрезками function draw_distance(){ minv = 801; j = 0; for (i = 0; i < k; i++){ if (minv > min[i]){ j = i; minv = min[i]; } } ctx.strokeStyle = "green"; ctx.beginPath(); ctx.moveTo(xcen + (xs[j] * m), (h - ys[j] * m) - ycen); ctx.lineTo(xcen + (xt[j] * m), (h - yt[j] * m) - ycen); ctx.closePath(); ctx.stroke(); } //функция, которая опускает высоту function ras(x1, y1, x2, y2, x3, y3){ var k1, d; //коэффициенты для уравнения прямой var ok = 0; // переменная, дающая понять меняли ли мы в дальнейшем координаты каждой точки if(x1 == x2){ //Если отрезок вертикальный - меняем местами координаты каждой точки. ok = 1; var tmp = x1; x1 = y1; y1 = tmp; tmp = x2 x2 = y2; y2 = tmp; tmp = x3; x3 = y3; y3 = tmp; } k1 = (y1 - y2) / (x1 - x2); //Ищем коэффициенты уравнения прямой, которому принадлежит данный отрезок. d = y1 - k1 * x1; var xz = (x3 * x2 - x3 * x1 + y2 * y3 - y1 * y3 + y1 * d - y2 * d) / (k1 * y2 - k1 * y1 + x2 - x1); var dl = -1; if((xz <= x2 && xz >= x1) || (xz <= x1 && xz >= x2)){//Проверим лежит ли основание высоты на отрезке. dl = Math.sqrt((x3 - xz) * (x3 - xz) + (y3 - xz * k1 - d) * (y3 - xz * k1 - d)); //вычисляем длину высоты var yz = k1 * xz + d; if (ok == 1){ // если мы ранее меняли местами координаты, то произведём обратное изменение, чтоб всё отрисовалась правильно var tmp = xz; xz = yz; yz = tmp; tmp = x3; x3 = y3; y3 = tmp; } xs[k] = xz; ys[k] = yz; xt[k] = x3; yt[k] = y3; min[k] = dl; k++; } return dl; } //функция вычисления function execute(xa, ya, xb, yb, xc, yc, xd, yd) { draw_back(); draw_sections(xa, ya, xb, yb, xc, yc, xd, yd); var dl, dl1, dl2, dl3, dl4, minv = -1, o, o1, o2, t = -2, s = -2; o = (xb - xa) * (-yd + yc) - (yb - ya) * (-xd + xc); // Вычисляем определители o1 = (xb - xa) * (yc - ya) - (yb - ya) * (xc - xa); o2 = (-yd + yc) * (xc - xa) - (-xd + xc) * (yc - ya); if(o != 0){ t = o1 / o; s = o2 / o; } if((t >= 0 && s >= 0) && (t <=1 && s <= 1)) {//Проверим пересекаются ли отрезки. minv = 0; } else { //Найдём наименьшую высоту опущенную из конца одного отрезка на другой. dl1 = ras(xa, ya, xb, yb, xc, yc); minv = dl1; dl2 = ras(xa, ya, xb, yb, xd, yd); if((dl2 < minv && dl2 != -1) || minv == -1) { minv=dl2; } dl3 = ras(xc, yc, xd, yd, xa, ya); if((dl3 < minv && dl3 != -1) || minv == -1){ minv = dl3; } dl4 = ras(xc, yc, xd, yd, xb, yb); if((dl4 < minv && dl4 != -1) || minv == -1){ minv = dl4; } if(minv == -1){ //В случае, если невозможно опустить высоту найдём минимальное расстояние между точками. dl1 = Math.sqrt((xa - xc) * (xa - xc) + (ya - yc) * (ya - yc)); minv = dl1; xs[k] = xa; ys[k] = ya; xt[k] = xc; yt[k] = yc; min[k] = minv; k++; dl2 = Math.sqrt((xb - xd) * (xb - xd) + (yb - yd) * (yb - yd)); if(dl2 < minv){ minv = dl2; xs[k] = xb; ys[k] = yb; xt[k] = xd; yt[k] = yd; min[k] = minv; k++; } dl3 = Math.sqrt((xb - xc) * (xb - xc) + (yb - yc) * (yb - yc)); if(dl3 < minv){ minv = dl3; xs[k] = xb; ys[k] = yb; xt[k] = xc; yt[k] = yc; min[k] = minv; k++; } dl4 = Math.sqrt((xa - xd) * (xa - xd) + (ya - yd) * (ya - yd)); if(dl4 < minv){ minv = dl4; xs[k] = xa; ys[k] = ya; xt[k] = xd; yt[k] = yd; min[k] = minv; k++; } } } if (minv > 0){ // Если расстояние не нулевое, то отобразим отрезок, соединяющий два изначальных draw_distance(); } document.getElementById("answer").innerHTML = "Ответ: " + minv + "."; // выведем на экран минимальное расстояние }