_computeHorizon( eyePoint, crossEdge, face, horizon ) {

		// moves face's vertices to the 'unassigned' vertex list

		this._deleteFaceVertices( face );

		face.mark = Deleted;

		let 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 {

			const twinEdge = edge.twin;
			const 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;

	}
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'.

@private
@param {Vector3} eyePoint - The 3D-coordinates of a point.
@param {HalfEdge} crossEdge - The edge used to jump to the current face.
@param {Face} face - The current face being tested.
@param {Array<HalfEdge>} horizon - The edges that form part of the horizon in CCW order.
@return {ConvexHull} A reference to this convex hull.