docs: @Pure
  	public static double getTriangleSegmentIntersectionFactorWithJimenezAlgorithm(
  			double tx1, double ty1, double tz1,
  			double tx2, double ty2, double tz2,
  			double tx3, double ty3, double tz3,
  			double sx1, double sy1, double sz1,
  			double sx2, double sy2, double sz2) {
  		// Input: Triangle (V1, V2, V3); Segment(Q1, Q2)
  
  		// A = Q1 - V3
  		double Ax = sx1 - tx3;
  		double Ay = sy1 - ty3;
  		double Az = sz1 - tz3;
  		// B = V1 - V3
  		double Bx = tx1 - tx3;
  		double By = ty1 - ty3;
  		double Bz = tz1 - tz3;
  		// C = V2 - V3
  		double Cx = tx2 - tx3;
  		double Cy = ty2 - ty3;
  		double Cz = tz2 - tz3;
  		// W1 = B x C
  		Vector3f W1 = new Vector3f();
  		FunctionalVector3D.crossProduct(Bx, By, Bz, Cx, Cy, Cz, W1);
  		// w = A . W1
  		double w = FunctionalVector3D.dotProduct(Ax, Ay, Az, W1.getX(), W1.getY(), W1.getZ());
  		// D = Q2 - Q1
  		double Dx = sx2 - sx1;
  		double Dy = sy2 - sy1;
  		double Dz = sz2 - sz1;
  		// s = D . W1
  		double t, u;
  		double s = FunctionalVector3D.dotProduct(Dx, Dy, Dz, W1.getX(), W1.getY(), W1.getZ());
  
  		int cmp = MathUtil.compareEpsilon(w, 0.);
  		if (cmp > 0) {
  			// Case: if (w > epsilon)
  			//
  			// if (s > epsilon) rejection 2
  			if (!MathUtil.isEpsilonZero(s)) {
  				return Double.NaN;
  			}
  			// W2 = A x D
  			Vector3f W2 = new Vector3f();
  			FunctionalVector3D.crossProduct(Ax, Ay, Az, Dx, Dy, Dz, W2);
  			// t = W2 . C
  			t = FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Cx, Cy, Cz);
  			// if (t < -epsilon) rejection 3
  			if ( t < -MathConstants.EPSILON) {
  				return Double.NaN;
  			}
  			// u = - W2 . B
  			u = - FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Bx, By, Bz);
  			// if ( u < -epsilon) rejection 4
  			if (u < -MathConstants.EPSILON) {
  				return Double.NaN;
  			}
  			// if (w < s + t + u) rejection 5
  			if (w < (s + t + u)) {
  				return Double.NaN;
  			}
  		} else if (cmp < 0) {
  			// Case: if (w < -epsilon)
  			//
  			// if (s < -epsilon) rejection 2
  			if (s < -MathConstants.EPSILON) {
  				return Double.NaN;
  			}
  			// W2 = A x D
  			Vector3f W2 = new Vector3f();
  			FunctionalVector3D.crossProduct(Ax, Ay, Az, Dx, Dy, Dz, W2);
  			// t = W2 . C
  			t = FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Cx, Cy, Cz);
  			// if (t > epsilon) rejection 3
  			if ( t > MathConstants.EPSILON) {
  				return Double.NaN;
  			}
  			// u = - W2 . B
  			u = - FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Bx, By, Bz);
  			// if ( u > epsilon) rejection 4
  			if (u > MathConstants.EPSILON) {
  				return Double.NaN;
  			}
  			// if (w > s + t + u) rejection 5
  			if (w > (s + t + u)) {
  				return Double.NaN;
  			}
  		} else {
  			// Case: if (-epsilon <= w <= epsilon)
  			// Swap Q1, Q2
  			if (s > MathConstants.EPSILON) {
  				// if (s > epsilon)
  				//
  				// W2 = D x A
  				Vector3f W2 = new Vector3f();
  				FunctionalVector3D.crossProduct(Dx, Dy, Dz, Ax, Ay, Az, W2);
  				// t = W2 . C
  				t = FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Cx, Cy, Cz);
  				// if (t < -epsilon) rejection 3
  				if (t < -MathConstants.EPSILON) {
  					return Double.NaN;
  				}
  				// u = - W2 . B
  				u = - FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Bx, By, Bz);
  				// if ( u < -epsilon) rejection 4
  				if (u < -MathConstants.EPSILON) {
  					return Double.NaN;
  				}
  				// if (-s < t + u) rejection 5
  				if (-s < (t + u)) {
  					return Double.NaN;
  				}
  			} else if (s < -MathConstants.EPSILON) {
  				// if (s < -epsilon)
  				//
  				// W2 = D x A
  				Vector3f W2 = new Vector3f();
  				FunctionalVector3D.crossProduct(Dx, Dy, Dz, Ax, Ay, Az, W2);
  				// t = W2 . C
  				t = FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Cx, Cy, Cz);
  				// if (t > epsilon) rejection 3
  				if (t > MathConstants.EPSILON) {
  					return Double.NaN;
  				}
  				// u = - W2 . B
  				u = - FunctionalVector3D.dotProduct(W2.getX(), W2.getY(), W2.getZ(), Bx, By, Bz);
  				// if ( u > epsilon) rejection 4
  				if (u > MathConstants.EPSILON) {
  					return Double.NaN;
  				}
  				// if (-s > t + u) rejection 5
  				if (-s > (t + u)) {
  					return Double.NaN;
  				}
  			} else {
  				// rejection 1
  				return Double.NaN;
  			}
  		}
  		//		double tt = 1. / (s-w);
  		double t_param = w / (s-w);
  		//		double alpha = tt * t;
  		//		double beta = tt * u;
  		return t_param;
  	}