【发布时间】:2014-03-19 02:30:36
【问题描述】:
假设我有一组用于绘制折线的点。当我点击折线时,我想在点击发生的线上添加一个新点。我需要弄清楚在数组中插入新点的位置,以便正确绘制线。一条线可以向任何方向走:上、下、左、右、上和左、下和右等,所以我最初的想法是弄清楚线的方向和斜率,然后从那里进行比较。考虑到这一点,我想出了这个代码:
/**
* Determines direction line is traveling in
* @param {Object} point1 - starting point
* @param {Object} point2 - ending point
* @param {Object} offset - position offset
* @return {Number} direction traveling (0 - straight up, 1 - up & right, 2 - straight right, 3 - down & right, etc.)
*/
getLineDirection: function(point1, point2, offset){
var rise, run, abs1, abs2, dirX, dirY,
slope, direction, ceil = {}, floor = {};
//get normalized positions
abs1 = this.getPointPosition(null,offset,point1);
abs2 = this.getPointPosition(null,offset,point2);
dirX = abs1.x > abs2.x ? -1 : 1;
dirY = abs1.y > abs2.y ? 1 : -1;
ceil.x = abs2.x > abs1.x ? abs2.x : abs1.x;
ceil.y = abs2.y > abs1.y ? abs2.y : abs1.y;
floor.x = abs2.x > abs1.x ? abs1.x : abs2.x;
floor.y = abs2.y > abs1.y ? abs1.y : abs2.y;
run = ceil.x - floor.x;
rise = ceil.y - floor.y
if(abs2.y > abs1.y){
rise = -rise;
}
if(abs2.x < abs1.x){
run = -run;
}
if(rise !== 0){
slope = rise/run;
if(slope === 0){
//horizontal
direction = dirX > 0 ? 2 : 6;
} else {
//angle
if(dirX === 1){
direction = dirY === 1 ? 1 : 3;
} else {
direction = dirY === -1 ? 5 : 7;
}
}
} else {
//vertical
direction = dirY > 0 ? 0 : 4;
}
return direction;
}
有了这个,我想我可以遍历构成线的点,然后确定是否应该在相应的点之前插入新点。这几乎可以正常工作,但是有些问题。
findInsertionIndex : function(x,y){
var count = this.points.length-1;
var p1 = this.points[0];
var p2 = { x : p1.x, y : p1.y };
var offset = this.offset();
var direction, pos;
for(i = 1; i < count;i++){
p2.x += this.points[i].x;
p2.y += this.points[i].y;
direction = this.getLineDirection(p1,p2,offset);
pos = this.getPointPosition(null,offset,p2);
//TODO: handle vertical lines
if(direction > 0 && direction < 4){
if(x < pos.x){
break;
}
} else if (direction > 4){
if(x > pos.x){
break;
}
}
p1 = p2;
}
return i;
}
我数学很烂,但这似乎是一种合乎逻辑的方法。我在想可能有更好的方法来做到这一点。如果有人能指出我正确的方向,我将不胜感激。
好的,不要再廉价双关语了:)
编辑
感谢@MvG,这里是完整的 findInsertionIndex 块供参考:
findInsertionIndex : function(x,y){
var count = this.points.length;
var offset = this.offset();
var p1 = this.getPointPosition(0,offset), p2;
var direction, pos, ox, oy, dx, dy, t, ex, ey, errSq,best,bestIndex = count-1;
for(var i = 1; i < count;i++){
p2 = this.getPointPosition(i,offset);
ox = x - p1.x;
oy = y - p1.y;
dx = p2.x - p1.x;
dy = p2.y - p1.y;
t = (ox*dx + oy*dy)/(dx*dx + dy*dy);
if (t < 0) t = 0;
if (t > 1) t = 1;
ex = t*dx - ox;
ey = t*dy - oy;
errSq = ex*ex + ey*ey;
if (!best || errSq < best) {
best = errSq;
bestIndex = i;
}
p1 = p2;
}
return bestIndex;
}
【问题讨论】:
标签: vector geometry 2d lines polyline