<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>VisIdeal2D</title>
       <!-- <script type="text/javascript" src="js/d3.v3.js"></script>-->
        <link href="css/bootstrap.min.css" rel="stylesheet">
    <link href="css/BootSideMenu.css" rel="stylesheet">
    <link href="css/nouislider.min.css" rel="stylesheet">
        <style>
           #svgMain {margin-left:auto; margin-right: auto; display:block}
            .axis path,
            .axis line {
                fill: none;
                stroke: black;
                stroke-width: 2;
                shape-rendering: crispEdges;
            }

            .axis text {
                font-family: sans-serif;
                font-size: 11px;
            }




      .noselect {
        -webkit-touch-callout: none;
        -webkit-user-select: none;
        -khtml-user-select: none;
        -moz-user-select: none;
        -ms-user-select: none;
        user-select: none;
      }

      a { cursor: pointer; cursor: hand; }

      #canvasElement2d {
        background-color: #FFF;
        cursor: default;
        display:inline;
        z-index:2;
        padding-bottom: 10px;
      }

      #canvasElement2d:not(.active):not(.shift) {
        cursor: crosshair;
      }

      /* CSS for sliders */
      #charge-slider{
         margin: 10px;
         display: inline-block;
         height: 10px;
         width: 120px;
      }
    
      #linkdist-slider{
         margin: 10px;
         display: inline-block;
         height: 10px;
         width: 120px;
      }
    
      .noUi-horizontal .noUi-handle {
         width: 24px;
         height: 18px;
         left: -17px;
         top: -6px;
      }
    
      .noUi-horizontal {
         height: 14px;
      }

      /* Vertical lines on the handles */
      .noUi-handle:before,
      .noUi-handle:after {
         content: "";
         display: block;
         position: absolute;
         height: 10px;
         width: 1px;
         background: #E8E7E6;
         left: 10px;
         top: 3px;
      }
      .noUi-handle:after {
         left: 12px;
      }
        
      .noUi-horizontal.noUi-extended {
         padding-right: 20px;
      }
      .noUi-horizontal.noUi-extended .noUi-handle {
         left: -2px;
      }
      .noUi-horizontal.noUi-extended .noUi-origin  {
         right: -32px;
      }
        
      path.link {
        fill: none;
        stroke: #B6B6B6;
        stroke-width: 2px;
        cursor: default;
      }

      #canvasElement2d:not(.active):not(.shift) path.link {
        cursor: pointer;
      }

      path.link.selected {
        stroke-dasharray: 10,2;
      }
        
      path.link.highlighted {
        fill: none;
        /* stroke: #B6B6B6; */
        stroke: #FF0000;
        stroke-width: 4px;
        cursor: default;
      }

      path.link.dragline {
        pointer-events: none;
      }

      path.link.hidden {
        stroke-width: 0;
      }

      circle.node {
        stroke-width: 0px;
        cursor: pointer;
      }

      circle.node.reflexive {
        stroke: #000 !important;
        stroke-width: 2.5px;
      }
     
      circle.node.highlighted {
        stroke: #000 !important;    
        stroke-width: 2.5px;
      }

      text {
        font: 12px sans-serif;
        pointer-events: none;
      }

      text.id {
        text-anchor: middle;
        font-weight: bold;
      }

      #canvasElement3d {
        background-color: #FFF;
        cursor: default;
        display:none;
        z-index: 0;
        padding-bottom: 10px;
      }

      #constructorString {
        -o-user-select: text;
        -moz-user-select: text;
        -webkit-user-select: text;
        user-select: text;
        z-index: 100;
        padding-bottom: 5px;
      }

      #incString {
        -o-user-select: text;
        -moz-user-select: text;
        -webkit-user-select: text;
        user-select: text;
        z-index: 100;
        padding-bottom: 5px;
      }
      #adjString {
        -o-user-select: text;
        -moz-user-select: text;
        -webkit-user-select: text;
        user-select: text;
        z-index: 100;
        padding-bottom: 5px;
      }
        </style>
        <script type="text/javascript">
      //global variables
      curConvex = true;
      h = window.innerHeight-10;//600;
      w = window.innerWidth-10;//900;
      dataset = visArray;
    </script>
    </head>
    <body>


    <div id="side">
          <h2>&#8202;&#8202;Menu</h2>
          <div class="list-group" id="menuList">
            </div>
            <a id="convexToggle" href="#" class="list-group-item">Convex Hull: off</a>
            <a id="idealGens" href="#" class="list-group-item">Ideal Generators</a>
            <!-- we can put these options in later
            <a id="exportTikz" href="#" class="list-group-item">Generate TikZ code</a>
            <a id="endSession" href="#" class="list-group-item">End session</a>            
            -->
          </div>
        </div>
  

    <div class="container">
    <div id="canvasElement2d"></div>
  </div>

  <script src="js/jquery-1.11.3.min.js"></script>
  <script src="js/BootSideMenu.js"></script>
  <script src="js/d3.v3.min.js"></script>
  <script src="js/bootstrap.min.js"></script>
<!--  <script src="js/clipboard.min.js"></script>
  <script src="js/nouislider.min.js"></script>
-->


    <script type="text/javascript">

    $('#side').BootSideMenu({side:"right", closeOnClick: false, width: "230px"});

    $(document).ready(function(){

    // display convex hull when clicked
    $("#convexToggle").on("click", function(){
        if(curConvex) {
          $(this).html("Convex Hull: on");
          curConvex = !curConvex;
            hull.attr("opacity",1);
        } else {
          $(this).html("Convex Hull: off");
          curConvex = !curConvex;
            hull.attr("opacity",0);
        }
      });

    // show the ideal generators when clicked
    $("#idealGens").on("click", function(){
          $(this).html("Ideal Generators: "  + labels);
      });
    });
     
        dataset.sort(function(a,b) {return a[0]-b[0]});

        svg = d3.select("body")
                        .append("svg")
                        .attr("height", h)
                        .attr("width", w)
                        .attr("id", "svgMain");

        // find largest x and y exponents
        xMax = 0;
        yMax = 0;
        for (i = 0; i < dataset.length; i++) {
                if (dataset[i][0] > xMax) {
                        xMax = dataset[i][0];
                }
                if (dataset[i][1] > yMax) {
                        yMax = dataset[i][1];
                }
        }

        // make the lattice go one unit beyond max x and y values
        // looks like chart is an array of arrays of 1's
        chart = [];
        for (i = 0; i < yMax+1; i++) {
                chart.push([]);
                for (j = 0; j < xMax+1; j++) {
                        chart[i].push(1);
                }
        }

        // determine the size of each unit square
        sq = Math.ceil(Math.min(h/(yMax+2), w/(xMax+2)));

        // datum will be a coordinate in the plane and blankout will 
        // put a 0 in every lattice point above and to the right
        var blankOut = function(datum, chart) {
                for (i = 0; i < chart.length; i++) {
                        if (i >= datum[1]) {
                                for (j = 0; j < chart[0].length; j++) {
                                        if (j >= datum[0]) {
                                                chart[i][j] = 0;
                                        }
                                }
                        }
                }
                return chart;
        }

        // put 0 in coordinates for elements of ideal
        for (k = 0; k < dataset.length; k++) {
                chart = blankOut(dataset[k], chart);
                }


        // the lattice points not in the ideal
        var makeDatFromChart = function(chart) {
                dat = [];
                for (i = 0; i < chart.length; i++) {
                        for (j = 0; j < chart[0].length; j++) {
                                if (chart[i][j] === 1) {
                                        dat.push([i, j]);
                                }
                        }
                }
                return dat;
        }

        // the coordinates of the points not in the ideal
        dat = makeDatFromChart(chart);


        
        // i'm not sure but i think the lines we get when switching
        // between convex hull are coming from the scale
        var xScale = d3.scale.linear();
        xScale.domain([0,xMax+1]);
        xScale.range([sq/2, (xMax+1.5)*sq]);

        var yScale = d3.scale.linear();
        yScale.domain([0, yMax+1]);
        yScale.range([h-1.5*sq, h-(yMax+2.5)*sq]);




        // list of triangles from generator to another generator to
        // the point with (x max, y max)
        tri = [];

        for (i = 0; i < dataset.length-1; i++) {
                for(j = i+1; j < dataset.length; j++) {
                        tri.push(xScale(dataset[i][0]+.01).toString() + "," +
                        yScale(dataset[i][1]-1).toString() + " " +
                        xScale(dataset[j][0]+.01).toString() + "," +
                        yScale(dataset[j][1]-1).toString() + " " +
                        xScale(Math.max(dataset[i][0]+.01,
                        dataset[j][0]+.01)).toString() + "," +
                        yScale(Math.max(dataset[i][1],
                        dataset[j][1])-1).toString());
                }
        }



        console.log(tri);

        var xAxis = d3.svg.axis()
                        .scale(xScale)
                        .ticks(xMax)
                        .orient("bottom");

        var yAxis = d3.svg.axis()
                        .scale(yScale) 
                        .ticks(yMax)
                        .orient("left");

        var latticePoints= [];
        for (i = 0; i <= yMax; i++) {
                for (j = 1; j <= xMax+1; j++) {
                        latticePoints.push([i,j]);
                }
        }


        // shades all the squares not in the ideal
        ideal = svg.selectAll("rect")
                        .data(dat)
                        .enter()
                        .append("rect")
                        .attr("x", function(d) { return Math.ceil(xScale(d[1])); })
                        .attr("y", function(d) { return Math.ceil(yScale(d[0])); })
                        .attr("width", sq)
                        .attr("height", sq) 
                        .attr("fill", "#f5deb3");

        // shades all the triangles. default is transparent
        hull = svg.selectAll("polygon")
                        .data(tri)
                        .enter()
                        .append("polygon")
                        .attr("points", function(d) { return d; })
                        .attr("fill", "#FFFFFF")
                        .attr("opacity", 0);

        // shades all the lattice points
        lattice = svg.selectAll("circle.lattice")
                        .data(latticePoints)
                        .enter()
                        .append("circle")
                        .attr("cx", function(d) { return Math.floor(xScale(d[1])); })
                        .attr("cy", function(d) { return Math.floor(yScale(d[0])); })
                        .attr("r", 4) 
                        .attr("fill", "#b3caf5");


        svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(0," + (h-sq/2) + ")")
                .call(xAxis);

        svg.append("g")
                .attr("class", "axis")
                .attr("transform", "translate(" + sq/2 + "," + sq + ")")
                .call(yAxis);


        var makeXYstring = function(x,y) {
                if (x === 0) { xstr = ""; }
                else if (x === 1) { xstr = "x"; }
                else { xstr = "x<sup>" + x.toString() + "</sup>"; }
                if (y === 0) { ystr = ""; }
                else if (y === 1) { ystr = "y"; }
                else { ystr = "y<sup>" + y.toString() + "</sup>"; }
                xystr = xstr + ystr;
                return xystr;
        }

        var labels = []
        for (i = 0; i < dataset.length; i++) {
                labels.push(makeXYstring(dataset[i][0],dataset[i][1]));
        }


        var pointsBelow = function (point1, point2, extX, extY) {
                if (point1[0] < point2[0]) {
                        first = point1;
                        second = point2;
                }
                else { first = point2; second = point1; }
                xMin = first[0];
                xMax = second[0];
                yMin = 0;
                yMax = Math.max(point1[1], point2[1]);
                points = []
                for (x = xMin; x <= xMax; x++) {
                        for (y = yMin; y <= yMax; y++) {
                                t = (x - xMin)/(xMax - xMin);
                                l = first[1]*(1-t) + second[1]*(t);
                                if (y < l) { points.push([x,y]); }
                        }
                }
                for (x = 0; x < xMin; x++) {
                        for (y = 0; y <= extY; y++) {
                                points.push([x,y]);
                        }
                }
                for (x = xMax+1; x <= extX; x++) {
                        for (y = 0; y <= extY; y++) {
                                points.push([x,y]);
                        }
                }
                return points;
        }

        var comparePoints = function(point1, point2) {
                if (point1[0] === point2[0] && point1[1] === point2[1]) { return true; }
                else { return false; }
        }

        extX = 0
        extY = 0
        for (i = 0; i < dataset.length; i++) {
                if (dataset[i][0] > extX) { extX = dataset[i][0]; }
                if (dataset[i][1] > extY) { extY = dataset[i][1]; }
        }

        pointList = []
        for (i = 0; i <= extX; i++) {
                for (j = 0; j <= extY; j++) {
                        pointList.push([i,j])
                }
        }

        for (i = 0; i < dataset.length-1; i++) {
                for (j = i+1; j < dataset.length; j++) {
                        pointsUnder = pointsBelow(dataset[i], dataset[j], extX, extY);
                        newPointList = []
                        for (a = 0; a < pointsUnder.length; a++) {
                                for (b = 0; b < pointList.length; b++) {
                                        if (comparePoints(pointsUnder[a], pointList[b])) { newPointList.push(pointsUnder[a]); }
                                }
                        }
                        pointList = newPointList;
                }
        }

        innerLattice = svg.selectAll("circle.inner")
                        .data(pointList)
                        .enter()
                        .append("circle")
                        .attr("cx", function(d) { return Math.floor(xScale(d[0])); })
                        .attr("cy", function(d) { return Math.floor(yScale(d[1]-1)); })
                        .attr("r", 2) 
                        .attr("fill", "#FFFFFF");


        </script>


</body>
</html>