Numerical precision of implementation for convex quadrilateral area
Debugging floating-point precision issues is, as @Bobby mentioned, off-topic for this site, so this is going to be just a code review :)

The first thing that strikes me, is the cryptic two-letter identifiers.

Let's start with the signature for GetTriangleArea. You're taking 9 parameters, this is bad. In reality you really need 3 groups of 3 numbers. Your code has failed to make this abstraction, and this is why you end up with a1-a2-a3 -style identifiers.

What if GetTriangleArea had a signature like this?

internal static double GetTriangleArea(Point3D pointA, Point3D pointB, Point3D pointC)


Given a Point3D struct with members X, Y and Z, the rest of the code would be much less cryptic.

The same applies to GetConvexQuadrilateralArea, which could look much less crowded like this:

internal static double GetConvexQuadrilateralArea(Point3D pointA, Point3D pointB, Point3D pointC, Point3D pointD)


Lastly, I'm not sure, but I think GetConvexQuadrilateralArea is lying - the method isn't actively verifying the convex-ness of the points it's given, which may or may not be problematic.