code: function(eyePoint, crossEdge, face, horizon) {
        // moves face's vertices to the 'unassigned' vertex list
  
        this.deleteFaceVertices(face);
  
        face.mark = Deleted;
  
        var edge;
  
        if (crossEdge === null) {
          edge = crossEdge = face.getEdge(0);
        } else {
          // start from the next edge since 'crossEdge' was already analyzed
          // (actually 'crossEdge.twin' was the edge who called this method recursively)
  
          edge = crossEdge.next;
        }
  
        do {
          var twinEdge = edge.twin;
          var oppositeFace = twinEdge.face;
  
          if (oppositeFace.mark === Visible) {
            if (oppositeFace.distanceToPoint(eyePoint) > this.tolerance) {
              // the opposite face can see the vertex, so proceed with next edge
  
              this.computeHorizon(eyePoint, twinEdge, oppositeFace, horizon);
            } else {
              // the opposite face can't see the vertex, so this edge is part of the horizon
  
              horizon.push(edge);
            }
          }
  
          edge = edge.next;
        } while (edge !== crossEdge);
  
        return this;
      }
docs: Computes a chain of half edges in CCW order called the 'horizon'. For an edge to be part of the horizon it must join a face that can see 'eyePoint' and a face that cannot see 'eyePoint'.