In the last post, we found pairs of subtriangles of our curved triangle which intersect. The subtriangles were linear approximations, which means that the intersection points we found are also only approximate. This might be good enough for our purposes, but in the interest of getting training data that’s as accurate as possible, we will refine these intersections by projecting them onto the exact curved triangle.
To be precise, we are looking for two distinct parameter pairs 
This is a classic root-finding problem, and we’ll use the Gauss-Newton method to solve it. That same method is also used for non-linear regression, but we use it for a completely non-statistical purpose here!
The optimization problem
We want to find a vector of parameters 
Unlike in a classical application of Newton’s method, here the input is four-dimensional, but the output is only three-dimensional. In other words, we have four unknowns, but only three equations—our problem is underdetermined. In geometric terms, this simply means that in general the intersection is not a point, but a curve! That’s fine for us, though—for now we are only interested in finding any point that lies exactly on that intersection curve.
A standard approach for underdetermined problems is to treat it as a least-squares problem, i.e., minimize the squared residual 
The Gauss-Newton iteration
Let 
where the update step 
(This is the only difference to the standard Newton’s method—it would solve 
The Jacobian matrix 
Computing CurvedTriangle class:
    Eigen::Matrix<double, 3, 2> jacobian(double u, double v) const {
        Eigen::Vector3d a = P200 + P002 - 2 * P101;
        Eigen::Vector3d b = P020 + P002 - 2 * P011;
        Eigen::Vector3d c = 2 * P110 + 2 * P002 - 2 * P101 - 2 * P011;
        Eigen::Vector3d d = -2 * P002 + 2 * P101;
        Eigen::Vector3d e = -2 * P002 + 2 * P011;
        // Compute partial derivatives
        Eigen::Vector3d dTdu = 2 * a * u + c * v + d;
        Eigen::Vector3d dTdv = 2 * b * v + c * u + e;
        Eigen::Matrix<double, 3, 2> J;
        J.col(0) = dTdu;
        J.col(1) = dTdv;
        return J;
    }
Putting it together
Now we have all the pieces in place and can implement the Gauss-Newton method to compute precise intersection points. A few more details we have to take into account:
- Initial guess: For each pair of intersecting subtriangles, we use their centroids in (u,v)-parameter space as the initial guess for - Solving the linear system: Directly inverting - Parameter domain constraints: The parameters - Distinctness: If the two parameter points of our initial guess are too close together, it could happen that after convergence we end up with - Spurious intersections: Since the subtriangles we started with were only linear approximations, in rare cases it can happen that they intersect, but the real surface 
Bonus: tracing out the intersection curve
Remember that the self-intersection usually takes the form of a curve. Until now we found one point
The answer lies, again, in the Jacobian 
 A self-intersection curve (in red) plotted out in 3D space. Intersecting subtriangles are shown in yellow.
A self-intersection curve (in red) plotted out in 3D space. Intersecting subtriangles are shown in yellow.
This class of algorithms is known as predictor-corrector methods, or numerical continuation. Working out all the details is beyond the scope of this article, but the method is implemented in the code repository which I’ll put online soon.
Summary
By formulating the self-intersection condition