/**
  * Set the partition bit to true for segments on the border and where the direction is 0
  *
  * @param sl
  */
 private void setPartitionBitForCertainSegments(ArrayList<Seg> sl) {
   for (int i = 0; i != sl.size(); i++) {
     Seg se = sl.get(i);
     if (((se.x == 0 || se.x == width) && se.dx == 0)
         || ((se.y == 0 || se.y == height) && se.dy == 0)) se.partition = true;
   }
 }
 /**
  * It generates the nodes. In every node, it has two section, left and right. It chooses the
  * segment which has the minimum grade value and then split this node into two nodes through this
  * segment. If all the segments in one node are partitioned, it will stop to split.
  *
  * @param sl
  * @return root node for BSP tree
  */
 private BSPNode genNodes(ArrayList<Seg> sl) {
   // if there is no segment with a partition bit set to false, there is nothing else to do and we
   // are at a leaf node
   if (countNonPartitions(sl) == 0) return new BSPLeaf(sl);
   // from the ones that have a partition bit set to false, pick a candidate with a low grade
   Seg pe = findPartitionCandidate(sl);
   // work on segment pe
   // mark pe as partitioned
   pe.partition = true;
   final int x = pe.x;
   final int y = pe.y;
   final int dx = pe.dx;
   final int dy = pe.dy;
   final ArrayList<Seg> lsl = new ArrayList<Seg>();
   final ArrayList<Seg> rsl = new ArrayList<Seg>();
   for (int i = 0; i != sl.size(); i++) {
     Seg se = (Seg) sl.get(i);
     int df1x = se.x - x;
     int df1y = se.y - y;
     int sendx = se.x + se.dx;
     int sendy = se.y + se.dy;
     int df2x = sendx - x;
     int df2y = sendy - y;
     int nx = dy;
     int ny = -dx;
     int dot1 = df1x * nx + df1y * ny;
     int dot2 = df2x * nx + df2y * ny;
     if (getSign(dot1) != getSign(dot2)) {
       if (dot1 == 0) dot1 = dot2;
       else if (dot2 != 0) {
         // we need to split this
         int spx = se.x;
         int spy = se.y;
         if (dx == 0) spx = x;
         else spy = y;
         Seg sps1 = new Seg(se.x, se.y, spx - se.x, spy - se.y, se.dist, colchange);
         Seg sps2 = new Seg(spx, spy, sendx - spx, sendy - spy, se.dist, colchange);
         if (dot1 > 0) {
           rsl.add(sps1);
           lsl.add(sps2);
         } else {
           rsl.add(sps2);
           lsl.add(sps1);
         }
         sps1.partition = sps2.partition = se.partition;
         continue;
       }
     }
     if (dot1 > 0 || (dot1 == 0 && se.getDir() == pe.getDir())) {
       rsl.add(se);
       if (dot1 == 0) se.partition = true;
     } else if (dot1 < 0 || (dot1 == 0 && se.getDir() == -pe.getDir())) {
       lsl.add(se);
       if (dot1 == 0) se.partition = true;
     } else {
       dbg("error xx 1 " + dot1);
     }
   }
   if (lsl.size() == 0) return new BSPLeaf(rsl);
   if (rsl.size() == 0) return new BSPLeaf(lsl);
   return new BSPBranch(x, y, dx, dy, genNodes(lsl), genNodes(rsl)); // recursion on both branches
 }