class AbstractGeographicProjection extends AbstractProjection {

    @Override
    public Ellipsoid getBoundingEllipsoid(BoundingBox<GeographicPosition> bbox, Vector3d modelCenter, boolean forceGenerate)
    {
        Ellipsoid ellipsoid = null;
        if (!forceGenerate)
        {
            ellipsoid = getEllipsoidFromCache(bbox);
        }
        if (ellipsoid == null)
        {
            // TODO It would be nice if this could be modified to get the
            // minimum bounding ellipsoid.
            GeographicBoundingBox geoBox = (GeographicBoundingBox)bbox;
            Vector3d[] modelCorners = new Vector3d[4];
            modelCorners[0] = convertToModel(geoBox.getLowerLeft(), modelCenter);
            modelCorners[1] = convertToModel(geoBox.getLowerRight(), modelCenter);
            modelCorners[2] = convertToModel(geoBox.getUpperRight(), modelCenter);
            modelCorners[3] = convertToModel(geoBox.getUpperLeft(), modelCenter);

            double xsum = 0;
            double ysum = 0;
            double zsum = 0;
            for (Vector3d corner : modelCorners)
            {
                xsum += corner.getX();
                ysum += corner.getY();
                zsum += corner.getZ();
            }
            double quarter = 1. / modelCorners.length;
            double x = xsum * quarter;
            double y = ysum * quarter;
            double z = zsum * quarter;

            Vector3d center = new Vector3d(x, y, z);
            double radius = 0;
            for (Vector3d corner : modelCorners)
            {
                radius = Math.max(radius, center.distance(corner));
            }

            Vector3d geoCenterModel = convertToModel(geoBox.getCenter(), modelCenter);

            Vector3d xAxis;
            Vector3d yAxis;
            if (modelCorners[1].equals(modelCorners[2]))
            {
                xAxis = modelCorners[0].subtract(center).getNormalized();
                yAxis = modelCorners[1].subtract(center).getNormalized();
            }
            else
            {
                xAxis = modelCorners[1].subtract(center).getNormalized();
                yAxis = modelCorners[2].subtract(center).getNormalized();
            }
            Vector3d zAxis = xAxis.cross(yAxis).getNormalized();
            // make the y axis perpendicular to both other axes.
            yAxis = zAxis.cross(xAxis);

            xAxis = xAxis.multiply(radius);
            yAxis = yAxis.multiply(radius);
            final double maximumFlattening = .05;
            zAxis = zAxis.multiply(Math.max(radius * maximumFlattening, geoCenterModel.subtract(center).getLength()));

            ellipsoid = new DefaultEllipsoid(center, xAxis, yAxis, zAxis);
            // if this is a force generated ellipsoid, then do not cache it.
            if (!forceGenerate)
            {
                cacheEllipsoid(bbox, ellipsoid);
            }
        }
        return ellipsoid;
    }

}