我最近一直在做一些图像处理,我正在寻找一个javascript解决方案来确定完全在非常规形状内的最长线段。总而言之,线段应该是接触形状的最长线段,而不是重叠或移动到形状之外。
以下是我遵循的步骤
第1步:
第2步:
第3步:
如步骤3中所示蓝线表示最大长度。 它完美地确定了常规形状的长度,但是在形状不规则的情况下它不起作用(也是在3点的情况下)。
要首先计算长度,我已经取得了点数(这是画布向下事件中的鼠标坐标。
以下是Canvas的片段:
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(我现在正在做什么)
预期输出
任何帮助都将不胜感激。
提前致谢!
答案 0 :(得分:2)
当您从凸多边形切换到凹多边形时,问题的复杂性会发生变化:您需要检查交叉点并“增长”候选区段。
使用凸多边形,您有一个候选集,由所有段定义(p 1 ,p 2 ),(p 1 ,p 3 ),...,(p 2 ,p 3 ),...,(p n-1 ,p n ),其中最长的候选者是结果:
此示例共有10个候选人。您只需选择最长的一个。
如果包含凹面多边形,则必须修改候选线段以拉伸到多边形的边缘,并排除与多边形相交的任何线段。
红色部分被排除在外。绿色部分是经过修改的部分。还有更复杂的案例没有被描述。
注意:过去我必须使用这个数学运算,并将链接到我构建的旧JavaScript库的函数。点表示为
{ x: number, y: number}
,多边形表示为点数组。
可以排除细分,原因有两个:
任一端点都以离开多边形的线段开始。您可以通过获取global angle of the candidate segment(来自所述端点)和两个相邻多边形边的全局角度并检查if the candidate segment's angle falls between those two来进行测试。
The candidate segment intersects any of the edges (inclusive of edge endpoints).
细分的扩展有点复杂:
查找所有段,其中任一端点是多边形的凹顶点。如果两个端点都是凹的,则包括两次。
对于所述(段,端点)对,通过polar projection将段穿过端点拉长距离(如10000000)。
使用多边形检测细长线段的所有intersection points。
找到未修改端点nearest的交叉点。此交叉点和未修改的端点是新的候选段。
结果是剩余的最长候选区段。
提示:我可能建议使用GeoGebra进行图表制作(我绝不是附属的)?