Ticket #9066: Mats-Taraldsvik-AddMultiLineStringMultiPolygonSupport.patch

File Mats-Taraldsvik-AddMultiLineStringMultiPolygonSupport.patch, 27.1 KB (added by mats.taraldsvik@…, 9 years ago)

Add support for MultiLinestring and MultiPolygon

  • extensions/test/gis/io/wkb/read_wkb.cpp

     
    1010#include <iterator>
    1111#include <string>
    1212#include <vector>
     13#include <iostream>
    1314
    1415#include <boost/test/included/test_exec_monitor.hpp>
    1516#include <boost/test/included/unit_test.hpp>
     
    1718#include <boost/cstdint.hpp>
    1819
    1920#include <boost/geometry/algorithms/equals.hpp>
     21#include <boost/geometry/strategies/strategies.hpp>
    2022#include <boost/geometry/geometries/geometries.hpp>
    2123#include <boost/geometry/io/wkt/read.hpp>
    2224#include <boost/geometry/extensions/gis/io/wkb/read_wkb.hpp>
     
    2426
    2527#include <boost/geometry/multi/algorithms/equals.hpp>
    2628#include <boost/geometry/multi/geometries/multi_geometries.hpp>
    27 #include <boost/geometry/multi/io/wkt/read.hpp>
     29#include <boost/geometry/multi/io/wkt/wkt.hpp>
    2830
    2931#include <boost/geometry/extensions/multi/gis/io/wkb/read_wkb.hpp>
    3032
    void test_geometry_wrong_wkb(std::string const& wkbhex, std::string const& wkt)  
    4345    std::cout << bg::read_wkb(wkb.begin(), wkb.end(), g_wkb) << std::endl;
    4446}
    4547
     48template <typename Geometry>
     49void test_geometry_parse_failure(std::string const& wkbhex, std::string const& wkt)
     50{
     51    byte_vector wkb;
     52    BOOST_CHECK( bg::hex2wkb(wkbhex, std::back_inserter(wkb)) );
     53    Geometry g_wkb;
     54    BOOST_CHECK( bg::read_wkb(wkb.begin(), wkb.end(), g_wkb) == false );
     55}
     56
    4657template <typename Geometry, bool IsEqual>
    4758void test_geometry_equals(std::string const& wkbhex, std::string const& wkt)
    4859{
    void test_geometry_equals(std::string const& wkbhex, std::string const& wkt)  
    5364
    5465    Geometry g_expected;
    5566    bg::read_wkt(wkt, g_expected);
     67   
     68    bool eq = bg::equals(g_wkb, g_expected);
     69   
     70    if(eq != IsEqual)
     71    {
     72        std::cout << "WKT EXPECTED:"<< bg::wkt(g_expected) << std::endl;
     73        std::cout << "WKT ACTUAL:"<< bg::wkt(g_wkb) << std::endl;
     74    }
     75   
     76    BOOST_CHECK( eq == IsEqual );
     77}
     78
     79template <typename Geometry, bool IsEqual>
     80void test_geometry_print(std::string const& wkbhex, std::string const& wkt)
     81{
     82    byte_vector wkb;
     83    BOOST_CHECK( bg::hex2wkb(wkbhex, std::back_inserter(wkb)) );
     84    Geometry g_wkb;
     85    BOOST_CHECK( bg::read_wkb(wkb.begin(), wkb.end(), g_wkb) );
     86
     87    Geometry g_expected;
     88    bg::read_wkt(wkt, g_expected);
     89   
     90    std::cout << "WKT OUT:"<< bg::wkt(g_wkb) << std::endl;
     91   
    5692    BOOST_CHECK( bg::equals(g_wkb, g_expected) == IsEqual );
    5793}
    5894
    int test_main(int, char* [])  
    72108{
    73109    typedef bg::model::point<double, 2, bg::cs::cartesian> point_type;
    74110    typedef bg::model::linestring<point_type> linestring_type;
     111    typedef bg::model::polygon<point_type> polygon_type;
     112   
     113    typedef bg::model::point<double, 3, bg::cs::cartesian> point_3d_type;
     114    typedef bg::model::linestring<point_3d_type> linestring_3d_type;
     115    typedef bg::model::polygon<point_3d_type> polygon_3d_type;
    75116
    76117    //
    77118    // POINT
    int test_main(int, char* [])  
    110151        "01010000E0E61000005839B4C876BEF33F83C0CAA145B616400000000000002E400000000000C05340",
    111152        "POINT (1.234 5.678)");
    112153   
     154//    //// 3D - needs to implement geometry_type handling
     155//   
     156//    // POINT(1.234 5.678 99)
     157//    test_geometry_equals<point_3d_type, true>(
     158//        "01e90300005839b4c876bef33f83c0caa145b616400000000000c05840", "POINT Z (1.234 5.678 99)");
     159   
    113160    //
    114161    // LineString
    115162    //
    116163   
    117     //test_geometry_equals<linestring_type, true>(
    118     //  "0102000000030000005839B4C876BEF33F83C0CAA145B616404F401361C333224062A1D634EF3824409CC420B072482A40EB73B515FB2B3040",
    119     //  "LINESTRING (1.234 5.678, 9.1011 10.1112, 13.1415 16.1718)");
     164    test_geometry_equals<linestring_type, true>(
     165      "0102000000030000005839B4C876BEF33F83C0CAA145B616404F401361C333224062A1D634EF3824409CC420B072482A40EB73B515FB2B3040",
     166      "LINESTRING (1.234 5.678, 9.1011 10.1112, 13.1415 16.1718)");
    120167   
     168    // LINESTRING (1.234 5.678 99, 9.1011 10.1112 99, 13.1415 16.1718 99) - Z coordinate in a two-dimensional linestring
     169    // Result is LINESTRING (1.234 5.678, 99 9.1011, 10.1112 99)
     170    test_geometry_equals<linestring_type, false>(
     171"0102000080030000005839B4C876BEF33F83C0CAA145B616400000000000C058404F401361C333224062A1D634EF3824400000000000C058409CC420B072482A40EB73B515FB2B30400000000000C05840",
     172      "LINESTRING (1.234 5.678, 9.1011 10.1112, 13.1415 16.1718)");
    121173   
    122174    //
    123     // MultiPoint
     175    // Polygon
     176    //
     177   
     178    test_geometry_equals<polygon_type, true>(
     179"010300000001000000050000000000000000005940000000000000694000000000000069400000000000006940000000000000694000000000000079400000000000005940000000000000794000000000000059400000000000006940",
     180    "POLYGON((100 200, 200 200, 200 400, 100 400, 100 200))"
     181    );
     182   
     183    // POLYGON((100 200 99, 200 200 99, 200 400 99, 100 400 99, 100 200 99)) - Z coordinate in a two-dimensional polygon
     184    // Result is POLYGON((100 200,99 200,200 99,200 400,99 100))
     185    test_geometry_equals<polygon_type, false>(
     186"01030000800100000005000000000000000000594000000000000069400000000000C05840000000000000694000000000000069400000000000C05840000000000000694000000000000079400000000000C05840000000000000594000000000000079400000000000C05840000000000000594000000000000069400000000000C05840",
     187    "POLYGON((100 200, 200 200, 200 400, 100 400, 100 200))"
     188    );
     189   
     190    test_geometry_equals<polygon_type, true>(
     191"0103000000020000000500000000000000008041400000000000002440000000000000244000000000000034400000000000002E40000000000000444000000000008046400000000000804640000000000080414000000000000024400400000000000000000034400000000000003E40000000000080414000000000008041400000000000003E40000000000000344000000000000034400000000000003E40",
     192    "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"
     193    );
     194   
     195    // POLYGON ((35 10 99, 10 20 99, 15 40 99, 45 45 99, 35 10 99),(20 30 99, 35 35 99, 30 20 99, 20 30 99)) - Z coordinate in a two-dimensional polygon
     196    // Result is POLYGON((35 10,99 10,20 99,15 40,99 45),())
     197    test_geometry_equals<polygon_type, false>(
     198"01030000800200000005000000000000000080414000000000000024400000000000C05840000000000000244000000000000034400000000000C058400000000000002E4000000000000044400000000000C05840000000000080464000000000008046400000000000C05840000000000080414000000000000024400000000000C058400400000000000000000034400000000000003E400000000000C05840000000000080414000000000008041400000000000C058400000000000003E4000000000000034400000000000C0584000000000000034400000000000003E400000000000C05840",
     199    "POLYGON ((35 10, 10 20, 15 40, 45 45, 35 10),(20 30, 35 35, 30 20, 20 30))"
     200    );
     201   
     202   
     203    //
     204    // Multi Geometries
    124205    //
    125206   
    126207    typedef bg::model::multi_point<point_type> multipoint_type;
     208    typedef bg::model::multi_linestring<linestring_type> multilinestring_type;
     209    typedef bg::model::multi_polygon<polygon_type> multipolygon_type;
     210   
     211    //
     212    // MultiPoint
     213    //
    127214   
    128215    test_geometry_equals<multipoint_type, true>(
    129     "0104000000020000000101000000000000000000F03F0000000000000040010100000000000000000008400000000000001040",       "MULTIPOINT (1 2, 3 4)");
     216    "01040000000100000001010000005839b4c876bef33f83c0caa145b61640",
     217    "MULTIPOINT (1.234 5.678)"
     218    );
    130219   
    131220    test_geometry_equals<multipoint_type, true>(
    132     "01040000000200000001010000005839B4C876BEF33F83C0CAA145B61640010100000062A1D634EF3824409CC420B072482A40",       "MULTIPOINT (1.234 5.678, 10.1112 13.1415)");
     221    "01040000000200000001010000005839B4C876BEF33F83C0CAA145B61640010100000062A1D634EF3824409CC420B072482A40",
     222    "MULTIPOINT (1.234 5.678, 10.1112 13.1415)"
     223    );
     224   
     225    //
     226    // MultiLineString
     227    //
     228   
     229    test_geometry_equals<multilinestring_type, true>(
     230      "0105000000010000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b3040",
     231      "MULTILINESTRING((1.234 5.678,9.1011 10.1112,13.1415 16.1718))");
     232    test_geometry_equals<multilinestring_type, true>(
     233      "0105000000020000000102000000030000005839b4c876bef33f83c0caa145b616404f401361c333224062a1d634ef3824409cc420b072482a40eb73b515fb2b30400102000000020000003333333333333340b81e85eb513835403d0ad7a3703d3740c3f5285c8f423940",
     234      "MULTILINESTRING((1.234 5.678,9.1011 10.1112,13.1415 16.1718),(19.2 21.22,23.24 25.26))");
     235
     236   
     237    //
     238    // MultiPolygon
     239    //
     240   
     241    test_geometry_equals<multipolygon_type, true>(
     242"010600000001000000010300000001000000050000000000000000005940000000000000694000000000000069400000000000006940000000000000694000000000000079400000000000005940000000000000794000000000000059400000000000006940",
     243    "MULTIPOLYGON(((100 200,200 200,200 400,100 400,100 200)))"
     244    );
     245   
     246    test_geometry_equals<multipolygon_type, true>(
     247"0106000000010000000103000000020000000500000000000000008041400000000000002440000000000000244000000000000034400000000000002e40000000000000444000000000008046400000000000804640000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40",
     248    "MULTIPOLYGON(((35 10,10 20,15 40,45 45,35 10),(20 30,35 35,30 20,20 30)))"
     249    );
    133250   
    134251    return 0;
    135252}
  • include/boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp

    struct geometry_type  
    6969        point      = 1,
    7070        linestring = 2,
    7171        polygon    = 3,
    72        
    73         // TODO: Not implemented
    7472        multipoint = 4,
    75         //multilinestring = 5,
    76         //multipolygon = 6,
     73        multilinestring = 5,
     74        multipolygon = 6,
    7775        //collection = 7
    7876    };
    7977};
  • include/boost/geometry/extensions/gis/io/wkb/detail/parser.hpp

    struct geometry_type_parser  
    107107        byte_order_type::enum_t order)
    108108    {
    109109        boost::uint32_t value;
    110         if (value_parser<boost::uint32_t>::parse(it, end, value, order))
     110        if (!value_parser<boost::uint32_t>::parse(it, end, value, order))
    111111        {
    112             // TODO: Refine the test when multi* geometries are supported
     112            return false;
     113        }
    113114           
    114             boost::uint32_t id = value & 0xff;
     115        boost::uint32_t id = value & 0xff;
     116        type = geometry_type::enum_t(id);
    115117           
    116             if (geometry_type::multipoint >= id)
    117             {
    118                 type = geometry_type::enum_t(id);
    119                 return true;
    120             }
    121         }
    122         return false;
     118        return true;
    123119    }
    124120};
    125121
    struct parsing_assigner<P, N, N>  
    164160    }
    165161};
    166162
    167 template <typename P>
     163template <typename Point>
    168164struct point_parser
    169165{
    170166    template <typename Iterator>
    171     static bool parse(Iterator& it, Iterator end, P& point, byte_order_type::enum_t order)
     167    static bool parse(Iterator& it, Iterator end, Point& point, byte_order_type::enum_t order)
    172168    {
    173         // TODO: mloskot - Add assert on point dimension, 2d only
    174 
    175169        geometry_type::enum_t type;
    176         if (geometry_type_parser::parse(it, end, type, order))
     170       
     171        if (!geometry_type_parser::parse(it, end, type, order))
    177172        {
    178             if (geometry_type::point == type && it != end)
    179             {
    180                 parsing_assigner<P, 0, dimension<P>::value>::run(it, end, point, order);
    181             }
    182             return true;
     173            return false;
    183174        }
    184         return false;
     175       
     176        if (geometry_type::point != type)
     177        {
     178            return false;
     179        }
     180       
     181        // Check that the number of double values in the stream is equal
     182        // or greater than the number of expected values in the point
     183       
     184        typedef typename std::iterator_traits<Iterator>::difference_type size_type;
     185       
     186        size_type const container_byte_size = dimension<Point>::value * sizeof(double);
     187        size_type const stream_byte_size = std::distance(it,end);
     188       
     189        assert(stream_byte_size >= container_byte_size);
     190       
     191        parsing_assigner<Point, 0, dimension<Point>::value>::run(it, end, point, order);
     192       
     193        return true;
    185194    }
    186195};
    187196
    template <typename C>  
    189198struct point_container_parser
    190199{
    191200    template <typename Iterator>
    192     static bool parse(Iterator& it, Iterator end, C& container, byte_order_type::enum_t order)
     201    static bool parse(Iterator& it, Iterator end, C& container, byte_order_type::enum_t order, boost::uint32_t num_points)
    193202    {
    194203        typedef typename point_type<C>::type point_type;
    195204
    196         boost::uint32_t num_points(0);
    197         if (!value_parser<boost::uint32_t>::parse(it, end, num_points, order))
    198         {
    199             return false;
    200         }
    201 
    202205        typedef typename std::iterator_traits<Iterator>::difference_type size_type;
    203206        assert(num_points <= boost::uint32_t( (std::numeric_limits<size_type>::max)() ) );
    204207
    205208        size_type const container_size = static_cast<size_type>(num_points);
    206         size_type const point_size = dimension<point_type>::value * sizeof(double);
    207209
    208         if (std::distance(it, end) >= (container_size * point_size))
    209         {
    210             point_type point_buffer;
    211             std::back_insert_iterator<C> output(std::back_inserter(container));
    212 
    213             // Read coordinates into point and append point to line (ring)
    214             size_type points_parsed = 0;
    215             while (points_parsed < container_size && it != end)
    216             {
    217                 parsing_assigner<point_type, 0, dimension<point_type>::value>::run(it, end, point_buffer, order);
    218                 output = point_buffer;
    219                 ++output;
    220                 ++points_parsed;
    221             }
     210        point_type point_buffer;
     211        std::back_insert_iterator<C> output(std::back_inserter(container));
    222212
    223             if (container_size != points_parsed)
    224             {
    225                 return false;
    226             }
     213        // Read coordinates into point and append point to container
     214        size_type points_parsed = 0;
     215        while (points_parsed < container_size && it != end)
     216        {
     217            parsing_assigner<point_type, 0, dimension<point_type>::value>::run(it, end, point_buffer, order);
     218            output = point_buffer;
     219            ++output;
     220            ++points_parsed;
    227221        }
    228222
    229223        return true;
    struct linestring_parser  
    249243            return false;
    250244        }
    251245
    252         assert(it != end);
    253         return point_container_parser<L>::parse(it, end, linestring, order);
     246        boost::uint32_t num_points(0);
     247        if (!value_parser<boost::uint32_t>::parse(it, end, num_points, order))
     248        {
     249            return false;
     250        }
     251       
     252        // Check that the number of double values in the stream is equal
     253        // or greater than the number of expected values in the linestring
     254       
     255        typedef typename std::iterator_traits<Iterator>::difference_type size_type;
     256       
     257        size_type const container_byte_size = dimension<point_type>::value * num_points * sizeof(double);
     258        size_type const stream_byte_size = std::distance(it,end);
     259       
     260        assert(stream_byte_size >= container_byte_size);
     261       
     262        return point_container_parser<L>::parse(it, end, linestring, order, num_points);
    254263    }
    255264};
    256265
    struct polygon_parser  
    276285        typedef typename ring_type<Polygon>::type ring_type;
    277286
    278287        std::size_t rings_parsed = 0;
    279         while (rings_parsed < num_rings && it != end) //while (rings_parsed < num_rings && it != end)
     288       
     289        while (rings_parsed < num_rings && it != end)
    280290        {
     291           
     292            boost::uint32_t num_points(0);
     293            if (!value_parser<boost::uint32_t>::parse(it, end, num_points, order))
     294            {
     295                return false;
     296            }
     297           
    281298            if (0 == rings_parsed)
    282299            {
    283300                ring_type& ring0 = exterior_ring(polygon);
    284                 if (!point_container_parser<ring_type>::parse(it, end, ring0, order))
     301               
     302                if (!point_container_parser<ring_type>::parse(it, end, ring0, order, num_points))
    285303                {
    286304                    return false;
    287305                }
    struct polygon_parser  
    290308            {
    291309                interior_rings(polygon).resize(rings_parsed);
    292310                ring_type& ringN = interior_rings(polygon).back();
    293                 if (!point_container_parser<ring_type>::parse(it, end, ringN, order))
     311               
     312                if (!point_container_parser<ring_type>::parse(it, end, ringN, order, num_points))
    294313                {
    295314                    return false;
    296315                }
    297316            }
    298             ++rings_parsed;
    299         }
    300317
    301         if (num_rings != rings_parsed)
    302         {
    303             return false;
     318            ++rings_parsed;
    304319        }
    305320
    306321        return true;
  • include/boost/geometry/extensions/multi/gis/io/wkb/detail/parser.hpp

     
    1919#include <boost/geometry/extensions/gis/io/wkb/detail/ogc.hpp>
    2020
    2121#include <boost/geometry/multi/core/point_type.hpp>
     22#include <boost/geometry/multi/core/ring_type.hpp>
     23
     24#include <boost/geometry/multi/core/interior_rings.hpp>
    2225
    2326namespace boost { namespace geometry
    2427{
    struct multipoint_parser  
    5255            return false;
    5356        }
    5457       
     58        // Check that the number of double values in the stream is equal
     59        // or greater than the number of expected values in the multipoint
     60       
     61        typedef typename std::iterator_traits<Iterator>::difference_type size_type;
     62       
     63        size_type const container_byte_size = dimension<point_type>::value * num_points * sizeof(double)
     64                                            + num_points * sizeof(boost::uint8_t)
     65                                            + num_points * sizeof(boost::uint32_t);
     66       
     67        size_type const stream_byte_size = std::distance(it,end);
     68       
     69        assert(stream_byte_size >= container_byte_size);
     70       
    5571        point_type point_buffer;
    5672        std::back_insert_iterator<MultiPoint> output(std::back_inserter(multipoint));
    5773       
    struct multipoint_parser  
    6783                return false;
    6884            }
    6985           
    70             point_parser<point_type>::parse(it, end, point_buffer, point_byte_order);
     86            geometry_type::enum_t point_type_type;
     87            if (!geometry_type_parser::parse(it, end, point_type_type, point_byte_order))
     88            {
     89                return false;
     90            }
     91           
     92            parsing_assigner<point_type, 0, dimension<point_type>::value>::run(it, end, point_buffer, point_byte_order);
    7193           
    7294            output = point_buffer;
    7395           
    struct multipoint_parser  
    78100    }
    79101};
    80102
     103template <typename MultiLinestring>
     104struct multilinestring_parser
     105{
     106    template <typename Iterator>
     107    static bool parse(Iterator& it, Iterator end, MultiLinestring& multilinestring, byte_order_type::enum_t order)
     108    {
     109        typedef typename MultiLinestring::value_type linestring_type;
     110        typedef typename point_type<MultiLinestring>::type point_type;
     111       
     112        geometry_type::enum_t type;
     113        if (!geometry_type_parser::parse(it, end, type, order))
     114        {
     115            return false;
     116        }
     117       
     118        if (geometry_type::multilinestring != type)
     119        {
     120            return false;
     121        }
     122       
     123        boost::uint32_t num_linestrings(0);
     124        if (!value_parser<boost::uint32_t>::parse(it, end, num_linestrings, order))
     125        {
     126            return false;
     127        }
     128       
     129        linestring_type linestring_buffer;
     130        std::back_insert_iterator<MultiLinestring> output(std::back_inserter(multilinestring));
     131       
     132        typedef typename std::iterator_traits<Iterator>::difference_type size_type;
     133        assert(num_linestrings <= boost::uint32_t( (std::numeric_limits<size_type>::max)() ) );
     134       
     135        size_type linestrings_parsed = 0;
     136        while (linestrings_parsed < num_linestrings && it != end)
     137        {
     138            detail::wkb::byte_order_type::enum_t linestring_byte_order;
     139            if (!detail::wkb::byte_order_parser::parse(it, end, linestring_byte_order))
     140            {
     141                return false;
     142            }
     143           
     144            geometry_type::enum_t type;
     145            if (!geometry_type_parser::parse(it, end, type, linestring_byte_order))
     146            {
     147                return false;
     148            }
     149           
     150            if (geometry_type::linestring != type)
     151            {
     152                return false;
     153            }
     154           
     155            boost::uint32_t num_points(0);
     156            if (!value_parser<boost::uint32_t>::parse(it, end, num_points, linestring_byte_order))
     157            {
     158                return false;
     159            }
     160           
     161            // Check that the number of double values in the stream is equal
     162            // or greater than the number of expected values in the linestring
     163           
     164            typedef typename std::iterator_traits<Iterator>::difference_type size_type;
     165           
     166            size_type const container_byte_size = dimension<point_type>::value * num_points * sizeof(double);
     167            size_type const stream_byte_size = std::distance(it,end);
     168           
     169            assert(stream_byte_size >= container_byte_size);
     170           
     171            return point_container_parser<linestring_type>::parse(it, end, linestring_buffer, linestring_byte_order, num_points);
     172           
     173            output = linestring_buffer;
     174           
     175            ++output;
     176            ++linestrings_parsed;
     177        }
     178        return true;
     179    }
     180};
     181
     182template <typename MultiPolygon>
     183struct multipolygon_parser
     184{
     185    template <typename Iterator>
     186    static bool parse(Iterator& it, Iterator end, MultiPolygon& multipolygon, byte_order_type::enum_t order)
     187    {
     188        typedef typename MultiPolygon::value_type polygon_type;
     189        typedef typename ring_type<MultiPolygon>::type ring_type;
     190       
     191        geometry_type::enum_t multipolygontype;
     192        if (!geometry_type_parser::parse(it, end, multipolygontype, order))
     193        {
     194            return false;
     195        }
     196       
     197        if (geometry_type::multipolygon != multipolygontype)
     198        {
     199            return false;
     200        }
     201       
     202        boost::uint32_t num_polygons(0);
     203        if (!value_parser<boost::uint32_t>::parse(it, end, num_polygons, order))
     204        {
     205            return false;
     206        }
     207       
     208        polygon_type polygon_buffer;
     209        std::back_insert_iterator<MultiPolygon> output(std::back_inserter(multipolygon));
     210       
     211        std::size_t polygons_parsed = 0;
     212        while(polygons_parsed < num_polygons && it != end)
     213        {
     214            detail::wkb::byte_order_type::enum_t polygon_byte_order;
     215            if (!detail::wkb::byte_order_parser::parse(it, end, polygon_byte_order))
     216            {
     217                return false;
     218            }
     219           
     220            geometry_type::enum_t type;
     221            if (!geometry_type_parser::parse(it, end, type, polygon_byte_order))
     222            {
     223                return false;
     224            }
     225           
     226            if (geometry_type::polygon != type)
     227            {
     228                return false;
     229            }
     230
     231            boost::uint32_t num_rings(0);
     232            if (geometry_type::polygon != type ||
     233                !value_parser<boost::uint32_t>::parse(it, end, num_rings, polygon_byte_order))
     234            {
     235                return false;
     236            }
     237           
     238            std::size_t rings_parsed = 0;
     239           
     240            while (rings_parsed < num_rings && it != end)
     241            {
     242                boost::uint32_t num_points(0);
     243                if (!value_parser<boost::uint32_t>::parse(it, end, num_points, polygon_byte_order))
     244                {
     245                    return false;
     246                }
     247               
     248                if (0 == rings_parsed)
     249                {
     250                    ring_type& ring0 = exterior_ring(polygon_buffer);
     251                   
     252                    if (!point_container_parser<ring_type>::parse(it, end, ring0, polygon_byte_order, num_points))
     253                    {
     254                        return false;
     255                    }
     256                }
     257                else
     258                {
     259                    interior_rings(polygon_buffer).resize(rings_parsed);
     260                    ring_type& ringN = interior_rings(polygon_buffer).back();
     261                   
     262                    if (!point_container_parser<ring_type>::parse(it, end, ringN, polygon_byte_order, num_points))
     263                    {
     264                        return false;
     265                    }
     266                }
     267                ++rings_parsed;
     268            }
     269            output = polygon_buffer;
     270            ++output;
     271        }
     272       
     273        return true;
     274    }
     275};
     276
    81277}} // namespace detail::wkb
    82278#endif // DOXYGEN_NO_IMPL
    83279
  • include/boost/geometry/extensions/multi/gis/io/wkb/read_wkb.hpp

    struct read_wkb<multi_point_tag, Geometry>  
    3232    }
    3333};
    3434
     35template <typename Geometry>
     36struct read_wkb<multi_linestring_tag, Geometry>
     37{
     38    template <typename Iterator>
     39    static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
     40        detail::wkb::byte_order_type::enum_t order)
     41    {
     42        return detail::wkb::multilinestring_parser<Geometry>::parse(it, end, geometry, order);
     43    }
     44};
     45
     46template <typename Geometry>
     47struct read_wkb<multi_polygon_tag, Geometry>
     48{
     49    template <typename Iterator>
     50    static inline bool parse(Iterator& it, Iterator end, Geometry& geometry,
     51        detail::wkb::byte_order_type::enum_t order)
     52    {
     53        return detail::wkb::multipolygon_parser<Geometry>::parse(it, end, geometry, order);
     54    }
     55};
     56
    3557} // namespace dispatch
    3658#endif // DOXYGEN_NO_DISPATCH
    3759
  • include/boost/geometry/multi/algorithms/equals.hpp

    struct equals  
    4141    : detail::equals::equals_by_collection<detail::equals::num_points_check>
    4242{};
    4343
     44template <typename MultiLinestring1, typename MultiLinestring2, bool Reverse>
     45struct equals
     46    <
     47        MultiLinestring1, MultiLinestring2,
     48        multi_linestring_tag, multi_linestring_tag,
     49        2,
     50        Reverse
     51    >
     52    : detail::equals::equals_by_collection<detail::equals::length_check>
     53{};
     54
    4455template <typename MultiPolygon1, typename MultiPolygon2, bool Reverse>
    4556struct equals
    4657    <