Найти максимальную ширину высоты неправильной формы на холсте HTML 5
Недавно я занимался обработкой изображений, и я ищу решение javascript для определения самого длинного сегмента линии, который полностью находится в нерегулярной форме. Чтобы подвести итог, сегмент линии должен быть самым длинным сегментом линии, который касается формы, а не перекрывается или перемещается за пределы формы.
Вот шаги, которые я выполнил
шаг 1:
![введите описание изображения здесь]()
Шаг 2:
![введите описание изображения здесь]()
Шаг 3:
![введите описание изображения здесь]()
как показано на шаге 3 Синяя линия указывает максимальную длину.
Он отлично работает, чтобы определить длину регулярных фигур, но в случае нерегулярных фигур он не работает (также в случае 3 точек).
Для вычисления длины сначала я взял точки (которые являются координатами мыши на событии canvas down.
Вот фрагмент для Canvas down:
function getXY(e) {
var el = document.getElementById('canvas');
var rect = el.getBoundingClientRect();
/* console.log("widht "+$("#canvas").width());
console.log("heihgt "+$("#canvas").height());
console.log("X "+Math.round(e.clientX - rect.left));
console.log("y "+Math.round(e.clientY - rect.top));*/
return {
x: Math.round(e.clientX - rect.left),
y: Math.round(e.clientY - rect.top)
}
}
$('#canvas').mousedown(function(e) {
var can = document.getElementById("canvas");
var ctx = can.getContext('2d');
if (condition == 1) {
if (e.which == 1) {
//store the points on mousedown
var poss = getXY(e);
i = i + 1;
if (firstX == poss.x && firstY == poss.y) {
console.log(" inside if poss.x===" + poss.x + " poss.y===" + poss.y);
//$('#crop').click();
} else {
console.log(" inside else poss.x===" + poss.x + " poss.y===" + poss.y);
points.push(Math.round(poss.x), Math.round(poss.y));
pointsforline.push({ "x": Math.round(poss.x), "y": Math.round(poss.y) });
xarray.push(poss.x);
yarray.push(poss.y);
sendpoints.push(Math.round(poss.x), Math.round(poss.y));
if(points.length >= 6){
$('#fixMarkingBtn').show();
}
}
// Type 1 using array
if(points.length == 6 && sendpoints.length ==6 ){
$('#fixMarkingBtn').show();
}
// Type 2 using counter
/* if (i == 3) {
$('#fixMarkingBtn').show();
}*/
if (i == 1) {
$('#undoMarkingBtn').show();
$('#resetMarkingBtn').show();
firstX = poss.x;
firstY = poss.y;
//change is here
Xmax = poss.x;
Ymax = poss.y;
Xmin = poss.x;
Ymin = poss.y;
minX1 = poss.x;
maxY1 = poss.y;
minX1 = poss.x;
minY1 = poss.y;
}
if (poss.x < Xmin) {
Xmin = poss.x;
minY1 = poss.y;
}
if (poss.x > Xmax) {
Xmax = poss.x;
maxY1 = poss.y;
}
if (poss.y < Ymin) {
Ymin = poss.y;
minX1 = poss.x;
}
if (poss.y > Ymax) {
Ymax = poss.y;
maxX1 = poss.x;
}
ctx.globalCompositeOperation = 'source-over';
var oldposx = $('#oldposx').html();
var oldposy = $('#oldposy').html();
var posx = $('#posx').html();
var posy = $('#posy').html();
ctx.beginPath();
ctx.lineWidth = 13;
ctx.moveTo(oldposx, oldposy);
if (oldposx != '') {
ctx.lineTo(posx, posy);
ctx.stroke();
}
$('#oldposx').html(poss.x);
$('#oldposy').html(poss.y);
}
ctx.fillStyle = 'red';
ctx.strokeStyle = 'red';
ctx.fillRect(posx, posy, 10, 10);
$('#posx').html(posx);
$('#posy').html(posy);
} //condition
});
вот код, который я использовал (точка проблемы):
function calMaxMin() {
for (var i = 0; i < points.length; i += 2) {
if (i == 0) {
Xmax = points[i];
Ymax = points[i + 1];
Xmin = points[i];
Ymin = points[i + 1];
minX1 = points[i];
maxY1 = points[i + 1];
minX1 = points[i];
minY1 = points[i + 1];
}
if (points[i] < Xmin) {
Xmin = points[i];
minY1 = points[i + 1];
}
if (points[i] > Xmax) {
Xmax = points[i];
maxY1 = points[i + 1];
}
if (points[i + 1] < Ymin) {
Ymin = points[i + 1];
minX1 = points[i];
}
if (points[i + 1] > Ymax) {
Ymax = points[i + 1];
maxX1 = points[i];
}
}
}
Изображение проблемы 1
![введите описание изображения здесь]()
Изображение проблемы 2 (что я получаю сейчас)
![введите описание изображения здесь]()
Ожидаемый результат
![введите описание изображения здесь]()
Любая помощь будет оценена.
Спасибо заранее!
Ответы
Ответ 1
Сложность проблемы изменяется при переключении с выпуклого многоугольника на вогнутый многоугольник: вам нужно проверить пересечения и "вырастить" сегменты-кандидаты.
С выпуклым многоугольником у вас есть один набор кандидатов, определенный всеми сегментами (p 1, p 2), (p 1, p 3),..., (p 2, p 3),..., (p n-1, p n), в котором самый длинный из этих кандидатов является результатом:
![nrR00.png]()
В этом примере представлено всего 10 кандидатов. Вы просто выбираете самый длинный.
Когда вы включаете вогнутые многоугольники, вы должны изменить сегменты-кандидаты, чтобы растянуть их до краев многоугольника и исключить любые сегменты, которые пересекают многоугольник.
![BDLcb.png]()
Красные сегменты исключены. Зеленые сегменты являются модифицированными. Есть и более сложные случаи, которые не изображены.
ПРИМЕЧАНИЕ. Мне пришлось немного поиграть с этой математикой в прошлом, и я буду ссылаться на функции старой библиотеки JavaScript, которую я создал. Точки представлены как { x: number, y: number}
и полигоны как массивы точек.
Сегменты могут быть исключены по двум причинам:
Расширение сегментов несколько сложно:
-
Найдите все сегменты, в которых либо конечная точка является вогнутой вершиной многоугольника. Включите его дважды, если обе конечные точки являются вогнутыми.
-
Для упомянутых (сегментных, конечных) пар растяните сегмент через конечную точку на большое расстояние (например, 10000000) через полярная проекция.
-
Обнаружить все точки пересечения удлиненного сегмента с полигоном.
-
Найдите точку пересечения, которая ближайшая неизмененная конечная точка. Эта точка пересечения и немодифицированная конечная точка являются новым сегментом-кандидатом.
Результат - самый длинный оставшийся сегмент-кандидат.
СОВЕТ: Могу ли я рекомендовать использовать GeoGebra для диаграмм (я никоим образом не аффилирован)?