Найти максимальную ширину высоты неправильной формы на холсте 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 кандидатов. Вы просто выбираете самый длинный.


Когда вы включаете вогнутые многоугольники, вы должны изменить сегменты-кандидаты, чтобы растянуть их до краев многоугольника и исключить любые сегменты, которые пересекают многоугольник.

JVczA.png BDLcb.png

Красные сегменты исключены. Зеленые сегменты являются модифицированными. Есть и более сложные случаи, которые не изображены.

ПРИМЕЧАНИЕ. Мне пришлось немного поиграть с этой математикой в ​​прошлом, и я буду ссылаться на функции старой библиотеки JavaScript, которую я создал. Точки представлены как { x: number, y: number} и полигоны как массивы точек.

Сегменты могут быть исключены по двум причинам:

Расширение сегментов несколько сложно:

  • Найдите все сегменты, в которых либо конечная точка является вогнутой вершиной многоугольника. Включите его дважды, если обе конечные точки являются вогнутыми.

  • Для упомянутых (сегментных, конечных) пар растяните сегмент через конечную точку на большое расстояние (например, 10000000) через полярная проекция.

    • Обнаружить все точки пересечения удлиненного сегмента с полигоном.

    • Найдите точку пересечения, которая ближайшая неизмененная конечная точка. Эта точка пересечения и немодифицированная конечная точка являются новым сегментом-кандидатом.

Результат - самый длинный оставшийся сегмент-кандидат.

СОВЕТ: Могу ли я рекомендовать использовать GeoGebra для диаграмм (я никоим образом не аффилирован)?