function calcSurfacePoint( p, q, U, V, P, u, v, target ) {

	const uspan = findSpan( p, u, U );
	const vspan = findSpan( q, v, V );
	const Nu = calcBasisFunctions( uspan, u, p, U );
	const Nv = calcBasisFunctions( vspan, v, q, V );
	const temp = [];

	for ( let l = 0; l <= q; ++ l ) {

		temp[ l ] = new Vector4( 0, 0, 0, 0 );
		for ( let k = 0; k <= p; ++ k ) {

			const point = P[ uspan - p + k ][ vspan - q + l ].clone();
			const w = point.w;
			point.x *= w;
			point.y *= w;
			point.z *= w;
			temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );

		}

	}

	const Sw = new Vector4( 0, 0, 0, 0 );
	for ( let l = 0; l <= q; ++ l ) {

		Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );

	}

	Sw.divideScalar( Sw.w );
	target.set( Sw.x, Sw.y, Sw.z );

}
Calculates a rational B-Spline surface point. See The NURBS Book, page 134, algorithm A4.3.

@param {number} p - The first degree of B-Spline surface.
@param {number} q - The second degree of B-Spline surface.
@param {Array<number>} U - The first knot vector.
@param {Array<number>} V - The second knot vector.
@param {Array<Array<Vector4>>} P - The control points in homogeneous space.
@param {number} u - The first parametric point.
@param {number} v - The second parametric point.
@param {Vector3} target - The target vector.