block by bycoffe 5575904

Point-in-polygon

Full Screen

index.html

<!doctype html>
<meta charset="utf-8">
<html>
  <head>
    <style type="text/css">
      #canvas {
        width: 800px;
        height: 400px;
        border: 1px solid #666;
      }
      path {
        fill: none;
        stroke-width: 1px;
        stroke: #666;
      }
      circle {
        fill: steelblue;
      }
      circle.selected {
        fill: #ff0000;
      }
    </style>
  </head>

  <body>

    <div id="canvas"></div>

    <span id="clear">[clear]</span>

    <script src="//d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="main.js"></script>

  </body>
</html>

main.js

;(function() {

  var copy,
      coords = [],
      width = 800,
      height = 400,
      margin = 50,

      line = d3.svg.line(),
      dragStart = function() {
        coords = [];
        g.selectAll("path").remove();
      },

      drawPath = function(terminator) {
        g.append("path").attr({
          d: line(coords)
        });
        if (terminator) {
          g.select("#terminator").remove();
          g.append("path").attr({
            id: "terminator",
            d: line([coords[0], coords[coords.length-1]])
          });
        }
      },

      dragMove = function() {
        dot.classed("selected", false);
        coords.push(d3.mouse(this));
        dot.each(function(d, i) {
          point = [d3.select(this).attr("cx"), d3.select(this).attr("cy")];
          if (pointInPolygon(point, coords)) {
            d3.select(this).classed("selected", true)
          }
        });
        drawPath();
      },

      dragEnd = function() {
        drawPath(true);
      }

      drag = d3.behavior.drag()
                .on("dragstart", dragStart)
                .on("drag", dragMove)
                .on("dragend", dragEnd),

      // from https://github.com/substack/point-in-polygon
      pointInPolygon = function (point, vs) {
        // ray-casting algorithm based on
        // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
        var xi, xj, i, intersect,
            x = point[0],
            y = point[1],
            inside = false;
        for (var i = 0, j = vs.length - 1; i < vs.length; j = i++) {
          xi = vs[i][0],
          yi = vs[i][1],
          xj = vs[j][0],
          yj = vs[j][1],
          intersect = ((yi > y) != (yj > y))
              && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
          if (intersect) inside = !inside;
        }
        return inside;
      },

      svg = d3.select("#canvas").append("svg").attr({
                width: width,
                height: height
              }).call(drag),

      g = svg.append("g"),

      randPoint = function(min, max) {
        return Math.floor(Math.random() * (max-min)) + min;
      },

      points = function(numPoints) {
        var data = [];
        for (i=0; i < numPoints; i++) {
          data.push({x: randPoint(margin, width-margin), y: randPoint(margin, height-margin)});
        }
        return data;
      },

      dot = g.selectAll("circle")
                .data(points(1000))
              .enter().append("circle")
                .attr({
                  cx: function(d, i) {
                    return d.x;
                  },
                  cy: function(d, i) {
                    return d.y;
                  },
                  r: 3
                });

  d3.select("#clear").on("click", function() {
    dot.classed("selected", false);
    dragStart();
  })

}());