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 стороны, отслеживая попадания во все стенки
Далее отсеиваем всё, что вне зоны
Получается, что так же стреляет в каждую стенку,
где и стенка, как бесконечный луч и луч тоже бесконечный
а потом отсеивает все попадания вне прямоугольника
Да, оптимальнее увеличивать линию, и смотреть пересечение каждой стенки
*/