js продление прямой до границ прямоугольника

// ТЗ { // Напишите функцию на JavaScript, которая принимает на вход координаты начальной и конечной точек отрезка, //который находится в прямоугольнике, на плоскости. Функция должна продлить этот отрезок до границ прямоугольника //(превратить в двунаправленный луч) и вернуть координаты 2х точек, в которых лучи отрезка пересекают границу //прямоугольника. Если пересекает в углу, то всё равно должно вернуть только 2х точек. } // Теоретическое решение { //Уравнение прямой, проходящей через две точки: (y — y1)/(y2 — y1) = (x — x1)/(x2 — x1), где (x1, y1) и (x2, y2) – координаты заданных точек. //Если точка лежит на прямой, её координаты при подстановке в это уравнение будут давать верное равенство //Если 2 прямые пересекаются, то точка их пересечения будет решением системы уравнений этих прямых //...\.|.................................... //....\|R2.................................. //.....|\................................... //.....|.\.................................. //....A|__\R1_________B..................... //.....|...\..........|..................... //.....|....\.........|..................... //.....|.....\R.......|..................... //.....|......\.......|..................... //.....|.......\Q.....|..................... //.....|........\.....|..................... //....D|_________\____|C.................... //..............Q1\...|..................... //.................\..|..................... //..................\.|..................... //...................\|Q2................... //....................|\.................... // На рисунке пример условия. Точки R1 и Q1 необходимо найти, а точки R2 и Q2 необходимо будет исключить из ответа // т.к. они также являются пересечением двунаправленого луча с прямыми, содержащими стороны, но не внутри прямоугольника // Если пересечение будет в углу, то R1 и R2, и/или Q1 и Q2 будут совпадать //Итого, суть задачи: найти пересечение прямой, содержащей отрезок, со всеми сторонами прямоугольника, //из полученых 4х точек убрать повторы (если есть), и убрать точки, у которых координаты находятся снаружи прямоугольника } // Практическая часть { //Зададим начальные данные: function rInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // Прямоугольник ABCD задаетс точками A и C. p - point function setABCD(){ let pA = { x:0, //rInt(0,500), y:0 //rInt(0,500) } let pC = { x:500,//rInt(pA.x + 1,500), y:500,//rInt(pA.y + 1,500) } //Достроим прямоугольник let pB = { x:pC.x, y:pA.y } let pD = { x:pA.x, y:pC.y } let abcd = { a:pA, b:pB, c:pC, d:pD } console.log(abcd); return abcd; } // Отрезок PQ задается точками R и Q function setRQ(abcd){ let pR = { x:rInt(abcd.a.x,abcd.c.x), y:rInt(abcd.a.y,abcd.c.y) } let pQ = { x:rInt(abcd.a.x,abcd.c.x), y:rInt(abcd.a.y,abcd.c.y) } let rq = { r:pR, q:pQ } console.log(rq); return rq; } //Получить из 2х точек уравнение прямой в виде y = kx + b // k - подобие наклона // b - смещение function getLine(p1, p2){ let res = {} if(p1.x === p2.x){ res.isVertical = true; // обработка случая с вертикальной прямой res.x = p1.x; console.log('x=',res.x); }else{ res.k = (p2.y - p1.y) / (p2.x - p1.x); // делить на 0 нельзя! Тут рассчёт наклона res.b = - (p2.y - p1.y) / (p2.x - p1.x) * p1.x + p1.y; console.log('y=',res.k,'*x+',res.b); } return res; } //Решить систему уравнение вида // y = k1*x + b1; // y = k2*x + b2 // Он ищет все точки пересечения, если бы все были лучами function solveSystem(l1, l2){ console.log(l1,l2); let res = { x:0, y:0 } if(l1.isVertical && !l2.isVertical){ console.log('Вертикальная прямая', l1); res.x = l1.x; res.y = l2.k * res.x + l2.b; }else if(l2.isVertical && !l1.isVertical){ console.log('Вертикальная прямая', l2); res.x = l2.x; res.y = l1.k * res.x + l1.b; } // l2.k - l1.k === 0 Это наклон, когда он одинаковый else if(l2.k - l1.k === 0 || l1.isVertical && l2.isVertical){ // прямые параллельны res.x = undefined; res.y = undefined; }else{ res.x = (l2.b - l1.b) / (l1.k - l2.k); res.y = l1.k * res.x + l1.b; //подставляем найденный x в уравнение любой из прямых } return res; } //Решение function solution(abcd,rq){ //Находим точки пересечения отрезка со сторонами прямоугольника // Тут у всего получение наклона и смещение console.log('RQ'); let lineRQ = getLine(rq.r, rq.q); console.log('AB'); let lineAB = getLine(abcd.a, abcd.b); console.log('BC'); let lineBC = getLine(abcd.b, abcd.c); console.log('CD'); let lineCD = getLine(abcd.c, abcd.d); console.log('AD'); let lineAD = getLine(abcd.a, abcd.d); // Тыкает луч в каждую стенку, которая тоже является лучём let preRresult = [ solveSystem(lineRQ,lineAB), solveSystem(lineRQ,lineBC), solveSystem(lineRQ,lineCD), solveSystem(lineRQ,lineAD), ] console.log(preRresult); let result = []; // Проверяем, что точки существуют и находятся в пределах прямоугольника // Сбор полученных результатов preRresult.forEach(el => { if( // Не являются параллельными el.x !== undefined && el.y !== undefined && // Находятся внутри прямоугольника el.x >= abcd.a.x && el.x <= abcd.c.x && el.y >= abcd.a.y && el.y <= abcd.c.y){ result.push(el); } }); // Выкидываем дубли, которых и так не должно быть return [... new Set(result)]; //убираем повторы } let abcd = setABCD(); let rq = setRQ(abcd); console.log(solution(abcd,rq)); } /* Кратко: Ограничила с права и лев И пуляем луч во все 4 стороны, отслеживая попадания во все стенки Далее отсеиваем всё, что вне зоны Получается, что так же стреляет в каждую стенку, где и стенка, как бесконечный луч и луч тоже бесконечный а потом отсеивает все попадания вне прямоугольника Да, оптимальнее увеличивать линию, и смотреть пересечение каждой стенки */