【问题标题】:Find max height-width of irregular shape drawn on HTML 5 canvas查找在 HTML 5 画布上绘制的不规则形状的最大高度宽度
【发布时间】:2018-05-01 04:00:40
【问题描述】:

我最近一直在做一些图像处理,并且正在寻找一种 javascript 解决方案来确定完全在非常规形状内的最长线段。综上所述,线段应该是与形状接触的最长的线段,且不重叠或移出形状。

这是我遵循的步骤

第一步:

第二步:

第三步:

如第三步所示蓝线表示最大长度。 它可以完美地确定规则形状的长度,但在不规则形状的情况下它不起作用(在 3 点的情况下也是如此)。

首先要计算长度,我已经取了点(这是画布向下事件上的鼠标坐标。

这是 Canvas down 的 sn-p :

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(我现在得到的)

预期输出

任何帮助将不胜感激。

提前致谢!

【问题讨论】:

  • @Piglet,我已经尝试过上面的解决方案,但在我的情况下它不起作用,上面的解决方案也适用于computational-geometry,我的问题是 javascript
  • 您说您正在寻找专门接触形状端点的最长线。那应该是什么意思?你如何定义端点?
  • @Piglet 通过端点,这里我的意思是用户通过点击在画布上创建的鼠标坐标。另外,我在这里担心的是最长的应该包含在形状内,而不是与形状线重叠。正如您在最后一张图片中看到的那样,绿线是预期的结果,但我得到的是蓝线。另外,我已经编辑了我的问题,使其更清楚。
  • 你的实际问题是什么?您不是在寻找仅与多边形相交两次的最长线吗?我假设您只对多边形顶点之间的线感兴趣?
  • 我正在寻找一种解决方案,它可以提供与多边形相交的最长线,但不应与任何线重叠。你可以看到最后一张图片,我想要绿色的线条而不是蓝色的线条。蓝色与其他线条重叠,因此我们将选择绿色,因为它不会与其他线条重叠。

标签: javascript image-processing html5-canvas


【解决方案1】:

当您从凸多边形切换到凹多边形时,问题的复杂性会发生变化:您需要检查交叉点并“增长”候选线段。

对于凸多边形,您有一个候选集,由所有线段定义 (p1, p2), (p1 , p3), ..., (p2, p3), ..., (pn-1 , pn),其中最长的候选是结果:

此示例共有 10 个候选者。您只需选择最长的。


当您包含凹多边形时,您必须修改候选线段以拉伸到多边形的边缘并排除与多边形相交的任何线段。

红色部分被排除在外。绿色部分是修改后的部分。还有一些更复杂的情况也没有描述。

注意:过去我不得不在这个数学上玩很多,并且将链接到我构建的旧 JavaScript 库的函数。点表示为{ x: number, y: number},多边形表示为点数组。

可以排除段有两个原因:

  1. 任一端点都从离开多边形的线段开始。您可以通过获取global angle of the candidate segment(来自所述端点)和两个相邻多边形边缘的全局角度并检查if the candidate segment's angle falls between those two来测试这一点。

  2. The candidate segment intersects any of the edges (inclusive of edge endpoints).

段的扩展有些复杂:

  1. 查找其中任一端点是多边形的凹顶点的所有线段。如果两个端点都是凹的,则包含两次。

  2. 对于所述(段,端点)对,通过polar projection 将段通过端点拉伸很长一段距离(如 10000000)。

    1. 用多边形检测所有intersection points

    2. 找到未修改端点nearest的交点。这个交点和未修改的端点就是新的候选线段。

结果是剩余最长的候选片段。

提示:我可以推荐使用GeoGebra 来绘制图表吗(我没有任何附属关系)?

【讨论】:

  • 你能不能用一些更简单的方式解释一下。
猜你喜欢
  • 2020-12-30
  • 2017-02-28
  • 2015-05-10
  • 1970-01-01
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 2012-05-08
相关资源
最近更新 更多