class GeographicUtilities {

    public static Map<List<LatLonAlt>, Collection<List<LatLonAlt>>> decomposePositionsToPolygons(List<LatLonAlt> rings)
    {
        Map<List<LatLonAlt>, Collection<List<LatLonAlt>>> polygons = New.map();

        LatLonAlt startPoint = null;
        List<LatLonAlt> curPoly = New.list();
        Collection<List<LatLonAlt>> holes = null;
        // Some shapefiles have duplicate successive points, so we remove them for the following logic work
        List<LatLonAlt> deduped = removeDuplicates(rings);
        for (LatLonAlt lla : deduped)
        {
            curPoly.add(lla);

            if (startPoint == null)
            {
                startPoint = lla;
                continue;
            }

            if (startPoint.equals(lla))
            {
                if (curPoly.size() > 2)
                {
                    /* Exterior rings are defined in clockwise order and inner rings are defined in counter-clockwise order. Make
                     * an exception to allow a counter-clockwise polygon if it's the only one in the list. */
                    PolygonWinding winding = getNaturalWinding(curPoly);
                    if (winding == PolygonWinding.CLOCKWISE || deduped.size() == curPoly.size())
                    {
                        holes = New.collection();
                        polygons.put(curPoly, holes);
                    }
                    else
                    {
                        if (holes != null)
                        {
                            holes.add(curPoly);
                        }
                        else
                        {
                            LOGGER.error("Polygon hole listed before polygon or incorrect winding for polygon.");
                        }
                    }
                }
                curPoly = New.list();
                startPoint = null;
            }
        }

        if (!curPoly.isEmpty())
        {
            LOGGER.warn("Encountered unclosed polygon while reading shapefile.");
        }

        return polygons;
    }

    private  GeographicUtilities();

}