My goal is to recognize all the shapes present in an image. The idea is:
Changing cv::CHAIN_APPROX_SIMPLE to cv::CHAIN_APPROX_NONE
in the call to cv::findContours() gives me much more reasonable results.
It makes sense that we would get a better ellipse approximation with more points included in the contour but I am still not sure why the results are so off with the simple chain approximation. See opencv docs for explanation of the difference
It appears that when using cv::CHAIN_APPROX_SIMPLE, the relatively horizontal edges of the triangles are almost completely removed from the contour.

As to your classification of best fit, as others have pointed out, using only the area will give you the results you observe as positioning is not taken into account at all.