最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Connecting dots without crossing lines - Stack Overflow

programmeradmin1浏览0评论

I am trying to create a Javascript web application where a user clicks on a canvas to drop an infinite amount of dots. There is solve button, that when clicked draws lines between the dots so that all dots are connected by exactly 2 other dots, and no lines can cross. With my code so far, there are certain instances where the lines still cross, and I can't programmatically figure out logic that will connect all the dots without any lines ever crossing.

So far, I collect all the points (X-Y coordinates) and put them in a JavaScript array of objects. I then need to sort the array so that it is in the correct order to be drawn. Everything works at this point except the order does not always satisfy the requirements.

My Question: Does anyone have any ideas on a set of rules that will order these points (X-Y coordinates) so that they all connect but never cross, that will work in every scenario?

Thanks for your help.

    var centroid = get_polygon_centroid($points);

    $points = _.sortBy($points, function(p){
        var dx = p.coords.x-centroid.x;
        var dy = p.coords.y-centroid.y;
        return dx*dx + dy*dy;
    });

    $points = _.sortBy($points, function(p){
        var dx = p.coords.x-centroid.x;
        var dy = p.coords.y-centroid.y;
        return Math.atan2(dy, dx);
    });

    $points.push($points[0]);

I am trying to create a Javascript web application where a user clicks on a canvas to drop an infinite amount of dots. There is solve button, that when clicked draws lines between the dots so that all dots are connected by exactly 2 other dots, and no lines can cross. With my code so far, there are certain instances where the lines still cross, and I can't programmatically figure out logic that will connect all the dots without any lines ever crossing.

So far, I collect all the points (X-Y coordinates) and put them in a JavaScript array of objects. I then need to sort the array so that it is in the correct order to be drawn. Everything works at this point except the order does not always satisfy the requirements.

My Question: Does anyone have any ideas on a set of rules that will order these points (X-Y coordinates) so that they all connect but never cross, that will work in every scenario?

Thanks for your help.

    var centroid = get_polygon_centroid($points);

    $points = _.sortBy($points, function(p){
        var dx = p.coords.x-centroid.x;
        var dy = p.coords.y-centroid.y;
        return dx*dx + dy*dy;
    });

    $points = _.sortBy($points, function(p){
        var dx = p.coords.x-centroid.x;
        var dy = p.coords.y-centroid.y;
        return Math.atan2(dy, dx);
    });

    $points.push($points[0]);
Share Improve this question edited Jun 19, 2013 at 12:13 pmandell asked Jun 15, 2013 at 17:34 pmandellpmandell 4,31819 silver badges21 bronze badges 0
Add a ment  | 

1 Answer 1

Reset to default 9

Here's an algorithm:

  • Find the center of mass ( O(n) time, where n is the number of points)
  • For each point, pute the angle from the center to that point ( O(n) time). This can be done with Math.atan2(p.y-c.y, p.x-c.x) in JS where p is the current point and c is the center.
  • Sort by angle ( O(n log n) time). For any angles that are exactly the same, sort by radius next, smallest to largest.
  • Connect pairs of points ai to ai+1 for every i from 0 to n-1 and also an-1 to a0

This should result in a connected graph where no two lines intersect in O(n log n) time.


Update:

This code should work.

//iterate through all points and calculate the center, c
var c = {x:0, y:0}, p;
for (p : points) {
    c.x+=p.coords.x;
    c.y+=p.coords.y;
}

c.x/=points.length;
c.y/=points.length;


points.sort(function(p1, p2){
    var dx1 = p1.coords.x-c.x;
    var dy1 = p1.coords.y-c.y;
    var a1 = Math.atan2(dy1, dx1);

    var dx2 = p2.coords.x-c.x;
    var dy2 = p2.coords.y-c.y;
    var a2 = Math.atan2(dy2, dx2);

    //If angles are the same, sort by length
    if (a1===a2){
        var d1 = dx1*dx1 + dy1*dy1;
        var d2 = dx2*dx2 + dy2*dy2;

        return d1-d2;
    }

    //otherwise sort by angle
    return a1-a2;
}

//Iterate through all Points and draw lines between them
var i;
for (i=0;i<n;i++){
    //This is not real code \/
    line(p[i], p[(i+1)%n]);
}
发布评论

评论列表(0)

  1. 暂无评论