9
3

envelope_on_spheroid.cpp 93 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2015-2018, Oracle and/or its affiliates.
  4. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  5. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Licensed under the Boost Software License version 1.0.
  8. // http://www.boost.org/users/license.html
  9. #ifndef BOOST_TEST_MODULE
  10. #define BOOST_TEST_MODULE test_envelope_on_sphere_or_spheroid
  11. #endif
  12. #include <boost/test/included/unit_test.hpp>
  13. #include <cstddef>
  14. #include <limits>
  15. #include <iostream>
  16. #include <string>
  17. #include <geometry_test_common.hpp>
  18. #include <from_wkt.hpp>
  19. #include <boost/numeric/conversion/bounds.hpp>
  20. #include <boost/type_traits/is_same.hpp>
  21. #include <boost/geometry/core/coordinate_dimension.hpp>
  22. #include <boost/geometry/core/tag.hpp>
  23. #include <boost/geometry/core/tags.hpp>
  24. #include <boost/geometry/geometries/geometries.hpp>
  25. #include <boost/geometry/util/condition.hpp>
  26. #include <boost/geometry/io/dsv/write.hpp>
  27. #include <boost/geometry/io/wkt/wkt.hpp>
  28. #include <boost/geometry/algorithms/convert.hpp>
  29. #include <boost/geometry/algorithms/envelope.hpp>
  30. #include <boost/geometry/algorithms/reverse.hpp>
  31. #include <boost/geometry/index/detail/algorithms/is_valid.hpp>
  32. #include "test_envelope_expand_on_spheroid.hpp"
  33. template <typename FormulaPolicy, typename CS_Tag>
  34. struct test_envelope
  35. {
  36. template <typename Geometry, typename Box>
  37. static inline void apply(Geometry& geometry, Box& detected)
  38. {
  39. bg::envelope(geometry, detected);
  40. }
  41. };
  42. template <typename FormulaPolicy>
  43. struct test_envelope<FormulaPolicy, bg::geographic_tag>
  44. {
  45. template <typename Geometry, typename Box>
  46. static inline void apply(Geometry& geometry,
  47. Box& detected)
  48. {
  49. typedef bg::strategy::envelope::spherical_point point_strategy_t;
  50. typedef bg::strategy::envelope::spherical_multipoint multi_point_strategy_t;
  51. typedef bg::strategy::envelope::spherical_box box_strategy_t;
  52. typedef bg::strategy::envelope::geographic<FormulaPolicy, bg::srs::spheroid<double>, double> strategy_t;
  53. typename boost::mpl::if_c
  54. <
  55. boost::is_same<typename bg::tag<Geometry>::type, bg::point_tag>::value,
  56. point_strategy_t,
  57. typename boost::mpl::if_c
  58. <
  59. boost::is_same<typename bg::tag<Geometry>::type, bg::multi_point_tag>::value,
  60. multi_point_strategy_t,
  61. typename boost::mpl::if_c
  62. <
  63. boost::is_same<typename bg::tag<Geometry>::type, bg::box_tag>::value,
  64. box_strategy_t,
  65. strategy_t
  66. >::type
  67. >::type
  68. >::type strategy;
  69. bg::envelope(geometry, detected, strategy);
  70. }
  71. };
  72. template <typename MBR, typename FormulaPolicy = bg::strategy::thomas>
  73. class envelope_on_spheroid_basic_tester
  74. {
  75. private:
  76. template
  77. <
  78. typename Geometry,
  79. typename Tag = typename bg::tag<Geometry>::type
  80. >
  81. struct write_geometry
  82. {
  83. template <typename OutputStream>
  84. static inline OutputStream& apply(OutputStream& os,
  85. Geometry const& geometry)
  86. {
  87. os << bg::wkt(geometry);
  88. return os;
  89. }
  90. };
  91. template <typename Segment>
  92. struct write_geometry<Segment, bg::segment_tag>
  93. {
  94. template <typename OutputStream>
  95. static inline OutputStream& apply(OutputStream& os,
  96. Segment const& segment)
  97. {
  98. os << "SEGMENT" << bg::dsv(segment);
  99. return os;
  100. }
  101. };
  102. template <typename Box>
  103. struct write_geometry<Box, bg::box_tag>
  104. {
  105. template <typename OutputStream>
  106. static inline OutputStream& apply(OutputStream& os,
  107. Box const& box)
  108. {
  109. os << "BOX" << bg::dsv(box);
  110. return os;
  111. }
  112. };
  113. template <typename Geometry, typename Box>
  114. static inline void check_message(bool same_boxes,
  115. std::string const& case_id,
  116. std::string const& units_str,
  117. Geometry const& geometry,
  118. Box const& expected,
  119. Box const& detected)
  120. {
  121. std::ostringstream stream;
  122. stream << "case ID: " << case_id << ", "
  123. << "MBR units: " << units_str << "; "
  124. << "geometry: ";
  125. write_geometry<Geometry>::apply(stream, geometry);
  126. stream << std::setprecision(17);
  127. stream << "; " << "expected: " << bg::dsv(expected)
  128. << ", " << "detected: " << bg::dsv(detected);
  129. BOOST_CHECK_MESSAGE(same_boxes, stream.str());
  130. }
  131. template
  132. <
  133. typename Geometry, typename Box,
  134. typename T1, typename T2, typename T3, typename T4
  135. >
  136. static inline void check_message(bool same_boxes,
  137. std::string const& case_id,
  138. std::string const& units_str,
  139. Geometry const& geometry,
  140. T1 const& lon_min, T2 const& lat_min, double height_min,
  141. T3 const& lon_max, T4 const& lat_max, double height_max,
  142. Box const& detected)
  143. {
  144. std::ostringstream stream;
  145. stream << "case ID: " << case_id << ", "
  146. << "MBR units: " << units_str << "; "
  147. << "geometry: ";
  148. write_geometry<Geometry>::apply(stream, geometry);
  149. stream << std::setprecision(17);
  150. stream << "; " << "expected: ";
  151. if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
  152. {
  153. stream << "(" << lon_min << " " << lat_min
  154. << ", " << lon_max << " " << lat_max << ")";
  155. }
  156. else
  157. {
  158. stream << "(" << lon_min << " " << lat_min << " " << height_min
  159. << ", " << lon_max << " " << lat_max << " " << height_max << ")";
  160. }
  161. stream << ", " << "detected: " << bg::dsv(detected);
  162. BOOST_CHECK_MESSAGE(same_boxes, stream.str());
  163. }
  164. template
  165. <
  166. typename Box, typename Geometry,
  167. typename T1, typename T2, typename T3, typename T4
  168. >
  169. static inline void base_test(std::string const& case_id,
  170. Geometry const& geometry,
  171. T1 const& lon_min, T2 const& lat_min, double height_min,
  172. T3 const& lon_max, T4 const& lat_max, double height_max,
  173. double tolerance)
  174. {
  175. typedef typename bg::coordinate_system<Box>::type::units box_units_type;
  176. std::string const units_str = units2string<box_units_type>();
  177. Box detected;
  178. test_envelope<FormulaPolicy, typename bg::cs_tag<Geometry>::type>
  179. ::apply(geometry, detected);
  180. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  181. std::cout << "geometry: ";
  182. write_geometry<Geometry>::apply(std::cout, geometry);
  183. std::cout << std::endl
  184. << "MBR units: " << units_str
  185. << std::endl;
  186. std::cout << "expected: ";
  187. if (BOOST_GEOMETRY_CONDITION(bg::dimension<Box>::value == 2))
  188. {
  189. std::cout << "(" << lon_min << " " << lat_min
  190. << ", " << lon_max << " " << lat_max << ")";
  191. }
  192. else
  193. {
  194. std::cout << "(" << lon_min << " " << lat_min << " " << height_min
  195. << ", " << lon_max << " " << lat_max << " " << height_max << ")";
  196. }
  197. std::cout << std::endl
  198. << "detected: " << bg::dsv(detected)
  199. << std::endl << std::endl;
  200. #endif
  201. bool check = box_check_equals<Box>::apply(detected,
  202. lon_min, lat_min, height_min,
  203. lon_max, lat_max, height_max,
  204. tolerance);
  205. check_message(check,
  206. case_id, units_str,
  207. geometry,
  208. lon_min, lat_min, height_min,
  209. lon_max, lat_max, height_max,
  210. detected);
  211. // if valid box is expected, check the validity
  212. if (lon_min <= lon_max && lat_min <= lat_max && height_min <= height_max)
  213. {
  214. BOOST_CHECK_MESSAGE(bg::index::detail::is_valid(detected),
  215. "Case ID: " << case_id << ", "
  216. << "MBR units: " << units_str << "; "
  217. << "Invalid Box: " << bg::dsv(detected));
  218. }
  219. }
  220. public:
  221. template
  222. <
  223. typename Geometry,
  224. typename T1, typename T2, typename T3, typename T4
  225. >
  226. static inline void apply(std::string const& case_id,
  227. Geometry const& geometry,
  228. T1 const& lon_min, T2 const& lat_min, double height_min,
  229. T3 const& lon_max, T4 const& lat_max, double height_max,
  230. double tolerance)
  231. {
  232. typedef other_system_info
  233. <
  234. typename bg::coordinate_system<MBR>::type
  235. > other;
  236. typedef bg::model::box
  237. <
  238. bg::model::point
  239. <
  240. typename bg::coordinate_type<MBR>::type,
  241. bg::dimension<MBR>::value,
  242. typename other::type
  243. >
  244. > other_mbr_type;
  245. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  246. std::cout << std::endl << std::endl;
  247. std::cout << "case ID: " << case_id << std::endl << std::endl;
  248. #endif
  249. base_test<MBR>(case_id, geometry,
  250. lon_min, lat_min, height_min,
  251. lon_max, lat_max, height_max,
  252. tolerance);
  253. if (lon_max < lon_min)
  254. {
  255. // we are in the case were a special MBR is returned;
  256. // makes no sense to change units
  257. base_test<other_mbr_type>(case_id, geometry,
  258. lon_min, lat_min, height_min,
  259. lon_max, lat_max, height_max,
  260. tolerance);
  261. }
  262. else
  263. {
  264. base_test<other_mbr_type>(case_id, geometry,
  265. other::convert(lon_min),
  266. other::convert(lat_min),
  267. height_min,
  268. other::convert(lon_max),
  269. other::convert(lat_max),
  270. height_max,
  271. tolerance);
  272. }
  273. }
  274. };
  275. // test the reverse of a geometry if it is either linear or ring
  276. template <typename Geometry, typename Tag = typename bg::tag<Geometry>::type>
  277. struct test_reverse_geometry
  278. {
  279. static bool const is_linear =
  280. boost::is_same<Tag, bg::segment_tag>::value
  281. || boost::is_same<Tag, bg::linestring_tag>::value
  282. || boost::is_same<Tag, bg::multi_linestring_tag>::value;
  283. // currently disable rings
  284. static bool const is_ring = false;
  285. // static bool const is_ring = boost::is_same<Tag, bg::ring_tag>::value;
  286. typedef typename boost::mpl::if_c
  287. <
  288. is_linear || is_ring,
  289. boost::true_type,
  290. boost::false_type
  291. >::type type;
  292. static bool const value = type::value;
  293. };
  294. template
  295. <
  296. typename Geometry,
  297. typename MBR,
  298. typename Tag = typename bg::tag<Geometry>::type,
  299. bool TestReverse = test_reverse_geometry<Geometry>::value,
  300. typename FormulaPolicy = bg::strategy::thomas
  301. >
  302. struct test_envelope_on_sphere_or_spheroid
  303. {
  304. template <typename T1, typename T2, typename T3, typename T4,
  305. typename T5, typename T6, typename T7, typename T8>
  306. static inline void apply(std::string const& case_id,
  307. Geometry const& geometry,
  308. T1 const& lon_min1, T2 const& lat_min1, double height_min1,
  309. T3 const& lon_max1, T4 const& lat_max1, double height_max1,
  310. T5 const& lon_min2, T6 const& lat_min2, double height_min2,
  311. T7 const& lon_max2, T8 const& lat_max2, double height_max2,
  312. double tolerance = std::numeric_limits<double>::epsilon())
  313. {
  314. envelope_on_spheroid_basic_tester
  315. <
  316. MBR, FormulaPolicy
  317. >::apply(case_id, geometry,
  318. lon_min1, lat_min1, height_min1,
  319. lon_max1, lat_max1, height_max1,
  320. tolerance);
  321. if (BOOST_GEOMETRY_CONDITION(TestReverse))
  322. {
  323. std::string reversed_case_id = case_id + "-reverse";
  324. Geometry reversed_geometry = geometry;
  325. bg::reverse(reversed_geometry);
  326. envelope_on_spheroid_basic_tester
  327. <
  328. MBR, FormulaPolicy
  329. >::apply(reversed_case_id, reversed_geometry,
  330. lon_min2, lat_min2, height_min2,
  331. lon_max2, lat_max2, height_max2,
  332. tolerance);
  333. }
  334. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  335. std::cout << "=================="
  336. << std::endl << std::endl;
  337. #endif
  338. }
  339. template <typename T1, typename T2, typename T3, typename T4,
  340. typename T5, typename T6, typename T7, typename T8>
  341. static inline void apply(std::string const& case_id,
  342. Geometry const& geometry,
  343. T1 const& lon_min1, T2 const& lat_min1,
  344. T3 const& lon_max1, T4 const& lat_max1,
  345. T5 const& lon_min2, T6 const& lat_min2,
  346. T7 const& lon_max2, T8 const& lat_max2,
  347. double tolerance = std::numeric_limits<double>::epsilon())
  348. {
  349. apply(case_id, geometry,
  350. lon_min1, lat_min1, 0, lon_max1, lat_max1, 0,
  351. lon_min2, lat_min2, 0, lon_max2, lat_max2, 0,
  352. tolerance);
  353. }
  354. template <typename T1, typename T2, typename T3, typename T4>
  355. static inline void apply(std::string const& case_id,
  356. Geometry const& geometry,
  357. T1 const& lon_min, T2 const& lat_min, double height_min,
  358. T3 const& lon_max, T4 const& lat_max, double height_max,
  359. double tolerance = std::numeric_limits<double>::epsilon())
  360. {
  361. apply(case_id, geometry,
  362. lon_min, lat_min, height_min,
  363. lon_max, lat_max, height_max,
  364. lon_min, lat_min, height_min,
  365. lon_max, lat_max, height_max,
  366. tolerance);
  367. }
  368. template <typename T1, typename T2, typename T3, typename T4>
  369. static inline void apply(std::string const& case_id,
  370. Geometry const& geometry,
  371. T1 const& lon_min, T2 const& lat_min,
  372. T3 const& lon_max, T4 const& lat_max,
  373. double tolerance = std::numeric_limits<double>::epsilon())
  374. {
  375. apply(case_id, geometry,
  376. lon_min, lat_min, 0, lon_max, lat_max, 0,
  377. tolerance);
  378. }
  379. };
  380. // special tester for rings
  381. template <typename Geometry, typename MBR, bool TestReverse>
  382. struct test_envelope_on_sphere_or_spheroid<Geometry, MBR, bg::ring_tag, TestReverse>
  383. {
  384. template <typename T1, typename T2, typename T3, typename T4,
  385. typename T5, typename T6, typename T7, typename T8>
  386. static inline void apply(std::string const& case_id,
  387. Geometry const& geometry,
  388. T1 const& lon_min1, T2 const& lat_min1,
  389. T3 const& lon_max1, T4 const& lat_max1,
  390. T5 const& lon_min2, T6 const& lat_min2,
  391. T7 const& lon_max2, T8 const& lat_max2,
  392. double const& tolerance = std::numeric_limits<double>::epsilon())
  393. {
  394. envelope_on_spheroid_basic_tester
  395. <
  396. MBR
  397. >::apply(case_id, geometry,
  398. lon_min1, lat_min1, 0,
  399. lon_max1, lat_max1, 0,
  400. tolerance);
  401. std::string ccw_case_id = case_id + "-2ccw";
  402. bg::model::ring
  403. <
  404. typename bg::point_type<Geometry>::type, false
  405. > ccw_ring;
  406. bg::convert(geometry, ccw_ring);
  407. envelope_on_spheroid_basic_tester
  408. <
  409. MBR
  410. >::apply(ccw_case_id, ccw_ring,
  411. lon_min2, lat_min2, 0,
  412. lon_max2, lat_max2, 0,
  413. tolerance);
  414. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  415. std::cout << "=================="
  416. << std::endl << std::endl;
  417. #endif
  418. }
  419. template <typename T1, typename T2, typename T3, typename T4>
  420. static inline void apply(std::string const& case_id,
  421. Geometry const& geometry,
  422. T1 const& lon_min, T2 const& lat_min,
  423. T3 const& lon_max, T4 const& lat_max,
  424. double tolerance = std::numeric_limits<double>::epsilon())
  425. {
  426. apply(case_id, geometry,
  427. lon_min, lat_min, lon_max, lat_max,
  428. lon_min, lat_min, lon_max, lat_max,
  429. tolerance);
  430. }
  431. };
  432. template <typename CoordinateSystem, typename Geometry>
  433. void test_empty_geometry(std::string const& case_id, std::string const& wkt)
  434. {
  435. std::size_t const dim = bg::dimension<Geometry>::value;
  436. typedef bg::model::point<double, dim, CoordinateSystem> point_type;
  437. typedef bg::model::box<point_type> B;
  438. typedef test_envelope_on_sphere_or_spheroid<Geometry, B> tester;
  439. typedef typename bg::coordinate_type<Geometry>::type ct;
  440. ct high_val = boost::numeric::bounds<ct>::highest();
  441. ct low_val = boost::numeric::bounds<ct>::lowest();
  442. if (BOOST_GEOMETRY_CONDITION(dim == 2))
  443. {
  444. tester::apply(case_id,
  445. from_wkt<Geometry>(wkt),
  446. high_val, high_val, low_val, low_val);
  447. }
  448. else
  449. {
  450. tester::apply(case_id,
  451. from_wkt<Geometry>(wkt),
  452. high_val, high_val, high_val, low_val, low_val, low_val);
  453. }
  454. }
  455. template <typename CoordinateSystem>
  456. void test_envelope_point()
  457. {
  458. typedef bg::model::point<double, 2, CoordinateSystem> point_type;
  459. typedef point_type G;
  460. typedef bg::model::box<point_type> B;
  461. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  462. tester::apply("p01",
  463. from_wkt<G>("POINT(10 10)"),
  464. 10, 10, 10, 10);
  465. tester::apply("p02",
  466. from_wkt<G>("POINT(370 10)"),
  467. 10, 10, 10, 10);
  468. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  469. tester::apply("p03",
  470. from_wkt<G>("POINT(370 -350)"),
  471. 10, 10, 10, 10);
  472. #endif
  473. // north and south poles
  474. tester::apply("p04",
  475. from_wkt<G>("POINT(0 90)"),
  476. 0, 90, 0, 90);
  477. tester::apply("p04a",
  478. from_wkt<G>("POINT(10 90)"),
  479. 0, 90, 0, 90);
  480. tester::apply("p04b",
  481. from_wkt<G>("POINT(270 90)"),
  482. 0, 90, 0, 90);
  483. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  484. tester::apply("p04c",
  485. from_wkt<G>("POINT(270 450)"),
  486. 0, 90, 0, 90);
  487. #endif
  488. tester::apply("p04d",
  489. from_wkt<G>("POINT(190 90)"),
  490. 0, 90, 0, 90);
  491. tester::apply("p04e",
  492. from_wkt<G>("POINT(-100 90)"),
  493. 0, 90, 0, 90);
  494. tester::apply("p05",
  495. from_wkt<G>("POINT(0 -90)"),
  496. 0, -90, 0, -90);
  497. tester::apply("p05a",
  498. from_wkt<G>("POINT(10 -90)"),
  499. 0, -90, 0, -90);
  500. tester::apply("p05b",
  501. from_wkt<G>("POINT(270 -90)"),
  502. 0, -90, 0, -90);
  503. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  504. tester::apply("p05c",
  505. from_wkt<G>("POINT(270 -450)"),
  506. 0, -90, 0, -90);
  507. #endif
  508. tester::apply("p05d",
  509. from_wkt<G>("POINT(190 -90)"),
  510. 0, -90, 0, -90);
  511. tester::apply("p05e",
  512. from_wkt<G>("POINT(-100 -90)"),
  513. 0, -90, 0, -90);
  514. tester::apply("p05f",
  515. from_wkt<G>("POINT(-100 -90)"),
  516. 0, -90, 0, -90);
  517. }
  518. BOOST_AUTO_TEST_CASE( envelope_point )
  519. {
  520. test_envelope_point<bg::cs::spherical_equatorial<bg::degree> >();
  521. test_envelope_point<bg::cs::geographic<bg::degree> >();
  522. }
  523. template <typename CoordinateSystem>
  524. void test_envelope_point_with_height()
  525. {
  526. typedef bg::model::point<double, 3, CoordinateSystem> point_type;
  527. typedef point_type G;
  528. typedef bg::model::box<point_type> B;
  529. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  530. tester::apply("ph01",
  531. from_wkt<G>("POINT(10 10 1256)"),
  532. 10, 10, 1256, 10, 10, 1256);
  533. }
  534. BOOST_AUTO_TEST_CASE( envelope_point_with_height )
  535. {
  536. test_envelope_point_with_height
  537. <
  538. bg::cs::spherical_equatorial<bg::degree>
  539. >();
  540. test_envelope_point_with_height<bg::cs::geographic<bg::degree> >();
  541. }
  542. BOOST_AUTO_TEST_CASE( envelope_segment_sphere )
  543. {
  544. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  545. typedef bg::model::point<double, 2, coordinate_system_type> P;
  546. typedef bg::model::segment<P> G;
  547. typedef bg::model::box<P> B;
  548. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  549. double const eps = std::numeric_limits<double>::epsilon();
  550. tester::apply("s01",
  551. from_wkt<G>("SEGMENT(10 10,40 40)"),
  552. 10, 10, 40, 40);
  553. tester::apply("s02",
  554. from_wkt<G>("SEGMENT(10 10,40 10)"),
  555. 10, 10, 40, 10.345270046149988);
  556. /*
  557. tester::apply("s02",
  558. from_wkt<G>("SEGMENT(1 2,70 1)"),
  559. 1, 1, 70, 2.01);
  560. */
  561. tester::apply("s02a",
  562. from_wkt<G>("SEGMENT(40 10,10 10)"),
  563. 10, 10, 40, 10.34527004614999);
  564. tester::apply("s03",
  565. from_wkt<G>("SEGMENT(160 10,-170 10)"),
  566. 160, 10, 190, 10.34527004614999);
  567. tester::apply("s03a",
  568. from_wkt<G>("SEGMENT(-170 10,160 10)"),
  569. 160, 10, 190, 10.34527004614999);
  570. tester::apply("s03b",
  571. from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
  572. 160, -10.34527004614999, 190, -10);
  573. tester::apply("s04",
  574. from_wkt<G>("SEGMENT(-40 45,140 60)"),
  575. -40, 45, 140, 90);
  576. tester::apply("s04a",
  577. from_wkt<G>("SEGMENT(-40 45,140 25)"),
  578. -40, 25, 140, 90);
  579. // segment ending at the north pole
  580. tester::apply("s05",
  581. from_wkt<G>("SEGMENT(40 45,80 90)"),
  582. 40, 45, 40, 90);
  583. // segment starting at the north pole
  584. tester::apply("s05a",
  585. from_wkt<G>("SEGMENT(80 90,40 45)"),
  586. 40, 45, 40, 90);
  587. // segment ending at the north pole
  588. tester::apply("s06",
  589. from_wkt<G>("SEGMENT(-40 45,80 90)"),
  590. -40, 45, -40, 90);
  591. // segment starting at the north pole
  592. tester::apply("s06a",
  593. from_wkt<G>("SEGMENT(70 90,-40 45)"),
  594. -40, 45, -40, 90);
  595. // segment ending at the north pole
  596. tester::apply("s07",
  597. from_wkt<G>("SEGMENT(40 -45,80 90)"),
  598. 40, -45, 40, 90);
  599. // segment passing through the south pole
  600. tester::apply("s08",
  601. from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
  602. -170, -90, 10, -30);
  603. tester::apply("s09",
  604. from_wkt<G>("SEGMENT(1 -45,179 30)"),
  605. 1, -85.28884376852969, 179, 30,
  606. 3 * eps);
  607. tester::apply("s09a",
  608. from_wkt<G>("SEGMENT(2 -45,181 30)"),
  609. 2, -87.63659983704832, 181, 30);
  610. // very long segment
  611. tester::apply("s10",
  612. from_wkt<G>("SEGMENT(0 -45,181 30)"),
  613. -179, -87.636599837048323, 0, 30,
  614. 2.0 * eps);
  615. tester::apply("s11",
  616. from_wkt<G>("SEGMENT(260 30,20 45)"),
  617. -100, 30, 20, 57.93195594009233);
  618. tester::apply("s11a",
  619. from_wkt<G>("SEGMENT(260 45,20 30)"),
  620. -100, 30, 20, 57.931955940092337);
  621. // segment degenerating to the north pole
  622. tester::apply("s12",
  623. from_wkt<G>("SEGMENT(10 90,20 90)"),
  624. 0, 90, 0, 90);
  625. // segment degenerating to the south pole
  626. tester::apply("s13",
  627. from_wkt<G>("SEGMENT(10 -90,20 -90)"),
  628. 0, -90, 0, -90);
  629. tester::apply("s14",
  630. from_wkt<G>("SEGMENT(20 20,10 30)"),
  631. 10, 20, 20, 30);//48.87458730907602);
  632. tester::apply("s15",
  633. from_wkt<G>("SEGMENT(50 45,185 45)"),
  634. 50, 45, 185, 69.05897952775615);
  635. // segment that lies on the equator
  636. tester::apply("s16",
  637. from_wkt<G>("SEGMENT(0 0,50 0)"),
  638. 0, 0, 50, 0);
  639. // segment that lies on the equator
  640. tester::apply("s16a",
  641. from_wkt<G>("SEGMENT(-50 0,50 0)"),
  642. -50, 0, 50, 0);
  643. // segment that lies on the equator and touches antimeridian
  644. tester::apply("s16b",
  645. from_wkt<G>("SEGMENT(50 0,180 0)"),
  646. 50, 0, 180, 0);
  647. // segment that lies on the equator and crosses antimeridian
  648. tester::apply("s16c",
  649. from_wkt<G>("SEGMENT(-170 0,160 0)"),
  650. 160, 0, 190, 0);
  651. tester::apply("s17",
  652. from_wkt<G>("SEGMENT(140 10, -140 80)"),
  653. 140, 10, 220, 80);
  654. tester::apply("s17-r",
  655. from_wkt<G>("SEGMENT(-140 80, 140 10)"),
  656. 140, 10, 220, 80);
  657. tester::apply("s18",
  658. from_wkt<G>("SEGMENT(20 10, 100 80)"),
  659. 20, 10, 100, 80);
  660. tester::apply("s18-r",
  661. from_wkt<G>("SEGMENT(100 80, 20 10)"),
  662. 20, 10, 100, 80);
  663. // segment connecting the north and south pole
  664. //
  665. // this should be forbidden actually, as it is not well-defined
  666. // with this test we demonstrate that the algorithm still returns
  667. // something meaningful
  668. tester::apply("s99",
  669. from_wkt<G>("SEGMENT(10 90,20 -90)"),
  670. 0, -90, 0, 90);
  671. // https://svn.boost.org/trac/boost/ticket/12106
  672. tester::apply("s100_ticket_12106",
  673. G(P(11.488323611111111, 53.687086666666673), P(11.488324166666667, 53.687086666666673)),
  674. 11.488323611111111, 53.687086666666673, 11.488324166666667, 53.687086666666673);
  675. double const heps = eps / 2;
  676. tester::apply("s101",
  677. G(P(1, 1), P(1-heps, 1-heps)),
  678. 1-heps, 1-heps, 1, 1);
  679. tester::apply("s102",
  680. G(P(1, 1), P(1, 1-heps)),
  681. 1, 1-heps, 1, 1);
  682. tester::apply("s103",
  683. G(P(1, 1), P(1-heps, 1)),
  684. 1-heps, 1, 1, 1);
  685. tester::apply("s104",
  686. G(P(2, 1), P(1, 1-heps)),
  687. 1, 1-heps, 2, 1.000038070652770505);
  688. tester::apply("s105",
  689. G(P(1, 2), P(1-heps, 1)),
  690. 1-heps, 1, 1, 2);
  691. }
  692. BOOST_AUTO_TEST_CASE( envelope_segment_spherical_polar )
  693. {
  694. typedef bg::cs::spherical<bg::degree> coordinate_system_type;
  695. typedef bg::model::point<double, 2, coordinate_system_type> P;
  696. typedef bg::model::segment<P> G;
  697. typedef bg::model::box<P> B;
  698. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  699. tester::apply("s01",
  700. from_wkt<G>("SEGMENT(10 10,40 40)"),
  701. 10, 10, 40, 40);
  702. tester::apply("s02",
  703. from_wkt<G>("SEGMENT(10 80,40 80)"),
  704. 10, 90 - 10.345270046149988, 40, 80);
  705. tester::apply("s03",
  706. from_wkt<G>("SEGMENT(160 80,-170 80)"),
  707. 160, 90 - 10.34527004614999, 190, 80);
  708. // segment ending at the north pole
  709. tester::apply("s05",
  710. from_wkt<G>("SEGMENT(40 45,80 0)"),
  711. 40, 0, 40, 45);
  712. }
  713. BOOST_AUTO_TEST_CASE( envelope_segment_spheroid )
  714. {
  715. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  716. typedef bg::model::point<double, 2, coordinate_system_type> P;
  717. typedef bg::model::segment<P> G;
  718. typedef bg::model::box<P> B;
  719. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  720. double const eps = std::numeric_limits<double>::epsilon();
  721. tester::apply("s01",
  722. from_wkt<G>("SEGMENT(10 10,40 40)"),
  723. 10, 10, 40, 40);
  724. tester::apply("s02",
  725. from_wkt<G>("SEGMENT(10 10,40 10)"),
  726. 10, 10, 40, 10.347587605817942);
  727. tester::apply("s02a",
  728. from_wkt<G>("SEGMENT(40 10,10 10)"),
  729. 10, 10, 40, 10.347587605817942);
  730. tester::apply("s03",
  731. from_wkt<G>("SEGMENT(160 10,-170 10)"),
  732. 160, 10, 190, 10.347587605817942);
  733. tester::apply("s03a",
  734. from_wkt<G>("SEGMENT(-170 10,160 10)"),
  735. 160, 10, 190, 10.347587605817942);
  736. tester::apply("s03b",
  737. from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
  738. 160, -10.347587605817942, 190, -10);
  739. tester::apply("s04",
  740. from_wkt<G>("SEGMENT(-40 45,140 60)"),
  741. -40, 45, 140, 90);
  742. tester::apply("s04a",
  743. from_wkt<G>("SEGMENT(-40 45,140 25)"),
  744. -40, 25, 140, 90);
  745. // segment ending at the north pole
  746. tester::apply("s05",
  747. from_wkt<G>("SEGMENT(40 45,80 90)"),
  748. 40, 45, 40, 90);
  749. // segment starting at the north pole
  750. tester::apply("s05a",
  751. from_wkt<G>("SEGMENT(80 90,40 45)"),
  752. 40, 45, 40, 90);
  753. // segment ending at the north pole
  754. tester::apply("s06",
  755. from_wkt<G>("SEGMENT(-40 45,80 90)"),
  756. -40, 45, -40, 90);
  757. // segment starting at the north pole
  758. tester::apply("s06a",
  759. from_wkt<G>("SEGMENT(70 90,-40 45)"),
  760. -40, 45, -40, 90);
  761. // segment ending at the north pole
  762. tester::apply("s07",
  763. from_wkt<G>("SEGMENT(40 -45,80 90)"),
  764. 40, -45, 40, 90);
  765. // segment passing through the south pole
  766. tester::apply("s08",
  767. from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
  768. -170, -90, 10, -30);
  769. tester::apply("s09",
  770. from_wkt<G>("SEGMENT(1 -45,179 30)"),
  771. 1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
  772. tester::apply("s09a",
  773. from_wkt<G>("SEGMENT(2 -45,181 30)"),
  774. 2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
  775. // very long segment
  776. tester::apply("s10",
  777. from_wkt<G>("SEGMENT(0 -45,181 30)"),
  778. -179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
  779. tester::apply("s11",
  780. from_wkt<G>("SEGMENT(260 30,20 45)"),
  781. -100, 30, 20, rng(57.990810958016482, 57.990810958016965));
  782. tester::apply("s11a",
  783. from_wkt<G>("SEGMENT(260 45,20 30)"),
  784. -100, 30, 20, rng(57.990810958016453, 57.990810958016965));
  785. // segment degenerating to the north pole
  786. tester::apply("s12",
  787. from_wkt<G>("SEGMENT(10 90,20 90)"),
  788. 0, 90, 0, 90);
  789. // segment degenerating to the south pole
  790. tester::apply("s13",
  791. from_wkt<G>("SEGMENT(10 -90,20 -90)"),
  792. 0, -90, 0, -90);
  793. tester::apply("s14",
  794. from_wkt<G>("SEGMENT(20 20,10 30)"),
  795. 10, 20, 20, 30);//48.87458730907602);
  796. tester::apply("s15",
  797. from_wkt<G>("SEGMENT(50 45,185 45)"),
  798. 50, 45, 185, rng(69.098479073902851, 69.098479073903178));
  799. // segment that lies on the equator
  800. tester::apply("s16",
  801. from_wkt<G>("SEGMENT(0 0,50 0)"),
  802. 0, 0, 50, 0);
  803. // segment that lies on the equator
  804. tester::apply("s16a",
  805. from_wkt<G>("SEGMENT(-50 0,50 0)"),
  806. -50, 0, 50, 0);
  807. // segment that lies on the equator and touches antimeridian
  808. tester::apply("s16b",
  809. from_wkt<G>("SEGMENT(50 0,180 0)"),
  810. 50, 0, 180, 0);
  811. // segment that lies on the equator and crosses antimeridian
  812. tester::apply("s16c",
  813. from_wkt<G>("SEGMENT(-170 0,160 0)"),
  814. 160, 0, 190, 0);
  815. tester::apply("s17",
  816. from_wkt<G>("SEGMENT(140 10, -140 80)"),
  817. 140, 10, 220, 80);
  818. tester::apply("s17-r",
  819. from_wkt<G>("SEGMENT(-140 80, 140 10)"),
  820. 140, 10, 220, 80);
  821. tester::apply("s18",
  822. from_wkt<G>("SEGMENT(20 10, 100 80)"),
  823. 20, 10, 100, 80);
  824. tester::apply("s18-r",
  825. from_wkt<G>("SEGMENT(100 80, 20 10)"),
  826. 20, 10, 100, 80);
  827. // segment connecting the north and south pole
  828. //
  829. // this should be forbidden actually, as it is not well-defined
  830. // with this test we demonstrate that the algorithm still returns
  831. // something meaningful
  832. tester::apply("s99",
  833. from_wkt<G>("SEGMENT(10 90,20 -90)"),
  834. 0, -90, 0, 90);
  835. // https://svn.boost.org/trac/boost/ticket/12106
  836. tester::apply("s100_ticket_12106",
  837. G(P(11.488323611111111, 53.687086666666673), P(11.488324166666667, 53.687086666666673)),
  838. 11.488323611111111, 53.687086666666673, 11.488324166666667, 53.687086666666673);
  839. double const heps = eps / 2;
  840. tester::apply("s101",
  841. G(P(1, 1), P(1-heps, 1-heps)),
  842. 1-heps, 1-heps, 1, 1);
  843. tester::apply("s102",
  844. G(P(1, 1), P(1, 1-heps)),
  845. 1, 1-heps, 1, 1);
  846. tester::apply("s103",
  847. G(P(1, 1), P(1-heps, 1)),
  848. 1-heps, 1, 1, 1);
  849. tester::apply("s104",
  850. G(P(2, 1), P(1, 1-heps)),
  851. 1, 1-heps, 2, rng(1.0000383271568751, 1.0000383271569036));
  852. tester::apply("s105",
  853. G(P(1, 2), P(1-heps, 1)),
  854. 1-heps, 1, 1, 2);
  855. }
  856. BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_thomas )
  857. {
  858. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  859. typedef bg::model::point<double, 2, coordinate_system_type> P;
  860. typedef bg::model::segment<P> G;
  861. typedef bg::model::box<P> B;
  862. typedef test_envelope_on_sphere_or_spheroid
  863. <
  864. G, B,
  865. bg::tag<G>::type,
  866. test_reverse_geometry<G>::value,
  867. bg::strategy::thomas
  868. > tester;
  869. tester::apply("s01",
  870. from_wkt<G>("SEGMENT(10 10,40 40)"),
  871. 10, 10, 40, 40);
  872. tester::apply("s02",
  873. from_wkt<G>("SEGMENT(10 10,40 10)"),
  874. 10, 10, 40, 10.347587605817942);
  875. tester::apply("s02a",
  876. from_wkt<G>("SEGMENT(40 10,10 10)"),
  877. 10, 10, 40, 10.347587605817942);
  878. tester::apply("s03",
  879. from_wkt<G>("SEGMENT(160 10,-170 10)"),
  880. 160, 10, 190, 10.347587605817942);
  881. tester::apply("s03a",
  882. from_wkt<G>("SEGMENT(-170 10,160 10)"),
  883. 160, 10, 190, 10.347587605817942);
  884. tester::apply("s03b",
  885. from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
  886. 160, -10.347587605817942, 190, -10);
  887. tester::apply("s04",
  888. from_wkt<G>("SEGMENT(-40 45,140 60)"),
  889. -40, 45, 140, 90);
  890. tester::apply("s04a",
  891. from_wkt<G>("SEGMENT(-40 45,140 25)"),
  892. -40, 25, 140, 90);
  893. // segment ending at the north pole
  894. tester::apply("s05",
  895. from_wkt<G>("SEGMENT(40 45,80 90)"),
  896. 40, 45, 40, 90);
  897. // segment starting at the north pole
  898. tester::apply("s05a",
  899. from_wkt<G>("SEGMENT(80 90,40 45)"),
  900. 40, 45, 40, 90);
  901. // segment ending at the north pole
  902. tester::apply("s06",
  903. from_wkt<G>("SEGMENT(-40 45,80 90)"),
  904. -40, 45, -40, 90);
  905. // segment starting at the north pole
  906. tester::apply("s06a",
  907. from_wkt<G>("SEGMENT(70 90,-40 45)"),
  908. -40, 45, -40, 90);
  909. // segment ending at the north pole
  910. tester::apply("s07",
  911. from_wkt<G>("SEGMENT(40 -45,80 90)"),
  912. 40, -45, 40, 90);
  913. // segment passing through the south pole
  914. tester::apply("s08",
  915. from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
  916. -170, -90, 10, -30);
  917. tester::apply("s09",
  918. from_wkt<G>("SEGMENT(1 -45,179 30)"),
  919. 1, rng(-85.392785243526134, -85.392785243525253), 179, 30);
  920. tester::apply("s09a",
  921. from_wkt<G>("SEGMENT(2 -45,181 30)"),
  922. 2, rng(-87.689300911353811, -87.689300911353371), 181, 30);
  923. // very long segment
  924. tester::apply("s10",
  925. from_wkt<G>("SEGMENT(0 -45,181 30)"),
  926. -179, rng(-87.689300911353797, -87.689300911353385), 0, 30);
  927. tester::apply("s11",
  928. from_wkt<G>("SEGMENT(260 30,20 45)"),
  929. -100, 30, 20, rng(57.990810958016482, 57.990810958016965));
  930. tester::apply("s11a",
  931. from_wkt<G>("SEGMENT(260 45,20 30)"),
  932. -100, 30, 20, rng(57.990810958016453, 57.990810958016965));
  933. // segment degenerating to the north pole
  934. tester::apply("s12",
  935. from_wkt<G>("SEGMENT(10 90,20 90)"),
  936. 0, 90, 0, 90);
  937. // segment degenerating to the south pole
  938. tester::apply("s13",
  939. from_wkt<G>("SEGMENT(10 -90,20 -90)"),
  940. 0, -90, 0, -90);
  941. tester::apply("s14",
  942. from_wkt<G>("SEGMENT(20 20,10 30)"),
  943. 10, 20, 20, 30);//48.87458730907602);
  944. tester::apply("s15",
  945. from_wkt<G>("SEGMENT(50 45,185 45)"),
  946. 50, 45, 185, rng(69.098479073902851, 69.098479073903178));
  947. // segment that lies on the equator
  948. tester::apply("s16",
  949. from_wkt<G>("SEGMENT(0 0,50 0)"),
  950. 0, 0, 50, 0);
  951. // segment that lies on the equator
  952. tester::apply("s16a",
  953. from_wkt<G>("SEGMENT(-50 0,50 0)"),
  954. -50, 0, 50, 0);
  955. // segment that lies on the equator and touches antimeridian
  956. tester::apply("s16b",
  957. from_wkt<G>("SEGMENT(50 0,180 0)"),
  958. 50, 0, 180, 0);
  959. // segment that lies on the equator and crosses antimeridian
  960. tester::apply("s16c",
  961. from_wkt<G>("SEGMENT(-170 0,160 0)"),
  962. 160, 0, 190, 0);
  963. tester::apply("s17",
  964. from_wkt<G>("SEGMENT(140 10, -140 80)"),
  965. 140, 10, 220, 80);
  966. tester::apply("s17-r",
  967. from_wkt<G>("SEGMENT(-140 80, 140 10)"),
  968. 140, 10, 220, 80);
  969. tester::apply("s18",
  970. from_wkt<G>("SEGMENT(20 10, 100 80)"),
  971. 20, 10, 100, 80);
  972. tester::apply("s18-r",
  973. from_wkt<G>("SEGMENT(100 80, 20 10)"),
  974. 20, 10, 100, 80);
  975. }
  976. BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_andoyer )
  977. {
  978. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  979. typedef bg::model::point<double, 2, coordinate_system_type> P;
  980. typedef bg::model::segment<P> G;
  981. typedef bg::model::box<P> B;
  982. typedef test_envelope_on_sphere_or_spheroid
  983. <
  984. G, B,
  985. bg::tag<G>::type,
  986. test_reverse_geometry<G>::value,
  987. bg::strategy::andoyer
  988. > tester;
  989. tester::apply("s01",
  990. from_wkt<G>("SEGMENT(10 10,40 40)"),
  991. 10, 10, 40, 40);
  992. tester::apply("s02",
  993. from_wkt<G>("SEGMENT(10 10,40 10)"),
  994. 10, 10, 40, 10.34758709960203);
  995. tester::apply("s02a",
  996. from_wkt<G>("SEGMENT(40 10,10 10)"),
  997. 10, 10, 40, 10.34758709960203);
  998. tester::apply("s03",
  999. from_wkt<G>("SEGMENT(160 10,-170 10)"),
  1000. 160, 10, 190, 10.34758709960203);
  1001. tester::apply("s03a",
  1002. from_wkt<G>("SEGMENT(-170 10,160 10)"),
  1003. 160, 10, 190, 10.34758709960203);
  1004. tester::apply("s03b",
  1005. from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
  1006. 160, -10.34758709960203, 190, -10);
  1007. tester::apply("s04",
  1008. from_wkt<G>("SEGMENT(-40 45,140 60)"),
  1009. -40, 45, 140, 90);
  1010. tester::apply("s04a",
  1011. from_wkt<G>("SEGMENT(-40 45,140 25)"),
  1012. -40, 25, 140, 90);
  1013. // segment ending at the north pole
  1014. tester::apply("s05",
  1015. from_wkt<G>("SEGMENT(40 45,80 90)"),
  1016. 40, 45, 40, 90);
  1017. // segment starting at the north pole
  1018. tester::apply("s05a",
  1019. from_wkt<G>("SEGMENT(80 90,40 45)"),
  1020. 40, 45, 40, 90);
  1021. // segment ending at the north pole
  1022. tester::apply("s06",
  1023. from_wkt<G>("SEGMENT(-40 45,80 90)"),
  1024. -40, 45, -40, 90);
  1025. // segment starting at the north pole
  1026. tester::apply("s06a",
  1027. from_wkt<G>("SEGMENT(70 90,-40 45)"),
  1028. -40, 45, -40, 90);
  1029. // segment ending at the north pole
  1030. tester::apply("s07",
  1031. from_wkt<G>("SEGMENT(40 -45,80 90)"),
  1032. 40, -45, 40, 90);
  1033. // segment passing through the south pole
  1034. tester::apply("s08",
  1035. from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
  1036. -170, -90, 10, -30);
  1037. tester::apply("s09",
  1038. from_wkt<G>("SEGMENT(1 -45,179 30)"),
  1039. 1, rng(-85.394745211091248, -85.394745211090353), 179, 30);
  1040. tester::apply("s09a",
  1041. from_wkt<G>("SEGMENT(2 -45,181 30)"),
  1042. 2, rng(-87.690317839849726, -87.690317839849271), 181, 30);
  1043. // very long segment
  1044. tester::apply("s10",
  1045. from_wkt<G>("SEGMENT(0 -45,181 30)"),
  1046. -179, rng(-87.69031783984974, -87.690317839849271), 0, 30);
  1047. tester::apply("s11",
  1048. from_wkt<G>("SEGMENT(260 30,20 45)"),
  1049. -100, 30, 20, rng(57.990742552279649, 57.990742552280153));
  1050. tester::apply("s11a",
  1051. from_wkt<G>("SEGMENT(260 45,20 30)"),
  1052. -100, 30, 20, rng(57.99074255227962, 57.990742552280118));
  1053. // segment degenerating to the north pole
  1054. tester::apply("s12",
  1055. from_wkt<G>("SEGMENT(10 90,20 90)"),
  1056. 0, 90, 0, 90);
  1057. // segment degenerating to the south pole
  1058. tester::apply("s13",
  1059. from_wkt<G>("SEGMENT(10 -90,20 -90)"),
  1060. 0, -90, 0, -90);
  1061. tester::apply("s14",
  1062. from_wkt<G>("SEGMENT(20 20,10 30)"),
  1063. 10, 20, 20, 30);//48.87458730907602);
  1064. tester::apply("s15",
  1065. from_wkt<G>("SEGMENT(50 45,185 45)"),
  1066. 50, 45, 185, rng(69.098446893408124, 69.09844689340845));
  1067. // segment that lies on the equator
  1068. tester::apply("s16",
  1069. from_wkt<G>("SEGMENT(0 0,50 0)"),
  1070. 0, 0, 50, 0);
  1071. // segment that lies on the equator
  1072. tester::apply("s16a",
  1073. from_wkt<G>("SEGMENT(-50 0,50 0)"),
  1074. -50, 0, 50, 0);
  1075. // segment that lies on the equator and touches antimeridian
  1076. tester::apply("s16b",
  1077. from_wkt<G>("SEGMENT(50 0,180 0)"),
  1078. 50, 0, 180, 0);
  1079. // segment that lies on the equator and crosses antimeridian
  1080. tester::apply("s16c",
  1081. from_wkt<G>("SEGMENT(-170 0,160 0)"),
  1082. 160, 0, 190, 0);
  1083. tester::apply("s17",
  1084. from_wkt<G>("SEGMENT(140 10, -140 80)"),
  1085. 140, 10, 220, 80);
  1086. tester::apply("s17-r",
  1087. from_wkt<G>("SEGMENT(-140 80, 140 10)"),
  1088. 140, 10, 220, 80);
  1089. tester::apply("s18",
  1090. from_wkt<G>("SEGMENT(20 10, 100 80)"),
  1091. 20, 10, 100, 80);
  1092. tester::apply("s18-r",
  1093. from_wkt<G>("SEGMENT(100 80, 20 10)"),
  1094. 20, 10, 100, 80);
  1095. // segments intersecting pole
  1096. tester::apply("s19",
  1097. from_wkt<G>("SEGMENT(0 0, 180 0)"),
  1098. 0, 0, 180, 90);
  1099. tester::apply("s20",
  1100. from_wkt<G>("SEGMENT(0 0, -180 0)"),
  1101. 0, 0, 180, 90);
  1102. tester::apply("s21",
  1103. from_wkt<G>("SEGMENT(0 1, 180 1)"),
  1104. 0, 1, 180, 90,
  1105. std::numeric_limits<double>::epsilon() * 10);
  1106. tester::apply("s22",
  1107. from_wkt<G>("SEGMENT(0 -1, 180 -1)"),
  1108. 0, -90, 180, -1,
  1109. std::numeric_limits<double>::epsilon() * 10);
  1110. }
  1111. BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_strategy_vincenty )
  1112. {
  1113. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1114. typedef bg::model::point<double, 2, coordinate_system_type> P;
  1115. typedef bg::model::segment<P> G;
  1116. typedef bg::model::box<P> B;
  1117. typedef test_envelope_on_sphere_or_spheroid
  1118. <
  1119. G, B,
  1120. bg::tag<G>::type,
  1121. test_reverse_geometry<G>::value,
  1122. bg::strategy::vincenty
  1123. > tester;
  1124. tester::apply("s01",
  1125. from_wkt<G>("SEGMENT(10 10,40 40)"),
  1126. 10, 10, 40, 40);
  1127. tester::apply("s02",
  1128. from_wkt<G>("SEGMENT(10 10,40 10)"),
  1129. 10, 10, 40, rng(10.347587628821937, 10.347587628821941));
  1130. tester::apply("s02a",
  1131. from_wkt<G>("SEGMENT(40 10,10 10)"),
  1132. 10, 10, 40, rng(10.347587628821937, 10.347587628821941));
  1133. tester::apply("s03",
  1134. from_wkt<G>("SEGMENT(160 10,-170 10)"),
  1135. 160, 10, 190, rng(10.347587628821937, 10.347587628821941));
  1136. tester::apply("s03a",
  1137. from_wkt<G>("SEGMENT(-170 10,160 10)"),
  1138. 160, 10, 190, rng(10.347587628821937, 10.347587628821941));
  1139. tester::apply("s03b",
  1140. from_wkt<G>("SEGMENT(-170 -10,160 -10)"),
  1141. 160, rng(-10.347587628821941, -10.347587628821937), 190, -10);
  1142. tester::apply("s04",
  1143. from_wkt<G>("SEGMENT(-40 45,140 60)"),
  1144. -40, 45, 140, 90);
  1145. tester::apply("s04a",
  1146. from_wkt<G>("SEGMENT(-40 45,140 25)"),
  1147. -40, 25, 140, 90);
  1148. // segment ending at the north pole
  1149. tester::apply("s05",
  1150. from_wkt<G>("SEGMENT(40 45,80 90)"),
  1151. 40, 45, 40, 90);
  1152. // segment starting at the north pole
  1153. tester::apply("s05a",
  1154. from_wkt<G>("SEGMENT(80 90,40 45)"),
  1155. 40, 45, 40, 90);
  1156. // segment ending at the north pole
  1157. tester::apply("s06",
  1158. from_wkt<G>("SEGMENT(-40 45,80 90)"),
  1159. -40, 45, -40, 90);
  1160. // segment starting at the north pole
  1161. tester::apply("s06a",
  1162. from_wkt<G>("SEGMENT(70 90,-40 45)"),
  1163. -40, 45, -40, 90);
  1164. // segment ending at the north pole
  1165. tester::apply("s07",
  1166. from_wkt<G>("SEGMENT(40 -45,80 90)"),
  1167. 40, -45, 40, 90);
  1168. // segment passing through the south pole
  1169. tester::apply("s08",
  1170. from_wkt<G>("SEGMENT(-170 -45,10 -30)"),
  1171. -170, -90, 10, -30);
  1172. tester::apply("s09",
  1173. from_wkt<G>("SEGMENT(1 -45,179 30)"),
  1174. 1, rng(-85.392840929577218, -85.392840929576352), 179, 30);
  1175. tester::apply("s09a",
  1176. from_wkt<G>("SEGMENT(2 -45,181 30)"),
  1177. 2, rng(-87.689330275867817, -87.689330275867405), 181, 30);
  1178. // very long segment
  1179. tester::apply("s10",
  1180. from_wkt<G>("SEGMENT(0 -45,181 30)"),
  1181. -179, rng(-87.689330275867832, -87.689330275867405), 0, 30);
  1182. tester::apply("s11",
  1183. from_wkt<G>("SEGMENT(260 30,20 45)"),
  1184. -100, 30, 20, rng(57.990810647056549, 57.990810647057032));
  1185. tester::apply("s11a",
  1186. from_wkt<G>("SEGMENT(260 45,20 30)"),
  1187. -100, 30, 20, rng(57.990810647056541, 57.990810647057032));
  1188. // segment degenerating to the north pole
  1189. tester::apply("s12",
  1190. from_wkt<G>("SEGMENT(10 90,20 90)"),
  1191. 0, 90, 0, 90);
  1192. // segment degenerating to the south pole
  1193. tester::apply("s13",
  1194. from_wkt<G>("SEGMENT(10 -90,20 -90)"),
  1195. 0, -90, 0, -90);
  1196. tester::apply("s14",
  1197. from_wkt<G>("SEGMENT(20 20,10 30)"),
  1198. 10, 20, 20, 30);//48.87458730907602);
  1199. tester::apply("s15",
  1200. from_wkt<G>("SEGMENT(50 45,185 45)"),
  1201. 50, 45, 185, rng(69.098479136978156, 69.098479136978497));
  1202. // segment that lies on the equator
  1203. tester::apply("s16",
  1204. from_wkt<G>("SEGMENT(0 0,50 0)"),
  1205. 0, 0, 50, 0);
  1206. // segment that lies on the equator
  1207. tester::apply("s16a",
  1208. from_wkt<G>("SEGMENT(-50 0,50 0)"),
  1209. -50, 0, 50, 0);
  1210. // segment that lies on the equator and touches antimeridian
  1211. tester::apply("s16b",
  1212. from_wkt<G>("SEGMENT(50 0,180 0)"),
  1213. 50, 0, 180, 0);
  1214. // segment that lies on the equator and crosses antimeridian
  1215. tester::apply("s16c",
  1216. from_wkt<G>("SEGMENT(-170 0,160 0)"),
  1217. 160, 0, 190, 0);
  1218. tester::apply("s17",
  1219. from_wkt<G>("SEGMENT(140 10, -140 80)"),
  1220. 140, 10, 220, 80);
  1221. tester::apply("s17-r",
  1222. from_wkt<G>("SEGMENT(-140 80, 140 10)"),
  1223. 140, 10, 220, 80);
  1224. tester::apply("s18",
  1225. from_wkt<G>("SEGMENT(20 10, 100 80)"),
  1226. 20, 10, 100, 80);
  1227. tester::apply("s18-r",
  1228. from_wkt<G>("SEGMENT(100 80, 20 10)"),
  1229. 20, 10, 100, 80);
  1230. }
  1231. BOOST_AUTO_TEST_CASE( envelope_segment_sphere_with_height )
  1232. {
  1233. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1234. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1235. typedef bg::model::segment<point_type> G;
  1236. typedef bg::model::box<point_type> B;
  1237. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1238. tester::apply("sh01",
  1239. from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
  1240. 10, 10, 567, 40, 40, 1356);
  1241. tester::apply("sh02",
  1242. from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
  1243. 10, 10, 567, 40, 40, 1356);
  1244. }
  1245. BOOST_AUTO_TEST_CASE( envelope_segment_spheroid_with_height )
  1246. {
  1247. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1248. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1249. typedef bg::model::segment<point_type> G;
  1250. typedef bg::model::box<point_type> B;
  1251. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1252. tester::apply("sh01",
  1253. from_wkt<G>("SEGMENT(10 10 567,40 40 1356)"),
  1254. 10, 10, 567, 40, 40, 1356);
  1255. tester::apply("sh02",
  1256. from_wkt<G>("SEGMENT(10 10 1356,40 40 567)"),
  1257. 10, 10, 567, 40, 40, 1356);
  1258. }
  1259. template <typename CoordinateSystem>
  1260. void test_envelope_multipoint()
  1261. {
  1262. typedef bg::model::point<double, 2, CoordinateSystem> P;
  1263. typedef bg::model::multi_point<P> G;
  1264. typedef bg::model::box<P> B;
  1265. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1266. // empty multipoint
  1267. test_empty_geometry<CoordinateSystem, G>("mp00", "MULTIPOINT()");
  1268. tester::apply("mp01",
  1269. from_wkt<G>("MULTIPOINT(0 0,10 10)"),
  1270. 0, 0, 10, 10);
  1271. tester::apply("mp02",
  1272. from_wkt<G>("MULTIPOINT(0 10,10 0)"),
  1273. 0, 0, 10, 10);
  1274. tester::apply("mp03",
  1275. from_wkt<G>("MULTIPOINT(-10 20,0 10,10 0)"),
  1276. -10, 0, 10, 20);
  1277. tester::apply("mp04",
  1278. from_wkt<G>("MULTIPOINT(-10 20,0 10,10 -15)"),
  1279. -10, -15, 10, 20);
  1280. tester::apply("mp05",
  1281. from_wkt<G>("MULTIPOINT(-85 10,85 -20)"),
  1282. -85, -20, 85, 10);
  1283. tester::apply("mp06",
  1284. from_wkt<G>("MULTIPOINT(-95 10,85 -20)"),
  1285. -95, -20, 85, 10);
  1286. tester::apply("mp07",
  1287. from_wkt<G>("MULTIPOINT(-96 10,85 -20)"),
  1288. 85, -20, -96+360, 10);
  1289. tester::apply("mp08",
  1290. from_wkt<G>("MULTIPOINT(175 15,-175 -20)"),
  1291. 175, -20, -175+360, 15);
  1292. tester::apply("mp09",
  1293. from_wkt<G>("MULTIPOINT(170 15,170 20,-175 10,-90 10,10 10)"),
  1294. 170, 10, 10+360, 20);
  1295. // this should fail
  1296. tester::apply("mp09a",
  1297. from_wkt<G>("MULTIPOINT(10 10,170 15,170 20,-175 10,-90 10)"),
  1298. 170, 10, 10+360, 20);
  1299. tester::apply("mp10",
  1300. from_wkt<G>("MULTIPOINT(10 10,20 90,30 -90)"),
  1301. 10, -90, 10, 90);
  1302. // this should fail
  1303. tester::apply("mp11",
  1304. from_wkt<G>("MULTIPOINT(179 90,-179 -90,10 10)"),
  1305. 10, -90, 10, 90);
  1306. tester::apply("mp11a",
  1307. from_wkt<G>("MULTIPOINT(10 10,179 90,-179 -90)"),
  1308. 10, -90, 10, 90);
  1309. // this should fail
  1310. tester::apply("mp11b",
  1311. from_wkt<G>("MULTIPOINT(179 90,-179 -90,-90 0)"),
  1312. -90, -90, -90, 90);
  1313. tester::apply("mp11c",
  1314. from_wkt<G>("MULTIPOINT(-90 0,179 90,-179 -90,-90 0)"),
  1315. -90, -90, -90, 90);
  1316. tester::apply("mp12",
  1317. from_wkt<G>("MULTIPOINT(170 -30,175 60,-178 10)"),
  1318. 170, -30, -178+360, 60);
  1319. tester::apply("mp13",
  1320. from_wkt<G>("MULTIPOINT(-170 -30,-175 40,178 50)"),
  1321. 178, -30, -170+360, 50);
  1322. tester::apply("mp13a",
  1323. from_wkt<G>("MULTIPOINT(-170 -30,178 50)"),
  1324. 178, -30, -170+360, 50);
  1325. tester::apply("mp13b",
  1326. from_wkt<G>("MULTIPOINT(-170 -30,178 50,-175 40)"),
  1327. 178, -30, -170+360, 50);
  1328. tester::apply("mp15",
  1329. from_wkt<G>("MULTIPOINT(10 -20)"),
  1330. 10, -20, 10, -20);
  1331. tester::apply("mp16",
  1332. from_wkt<G>("MULTIPOINT(0 90,10 90)"),
  1333. 0, 90, 0, 90);
  1334. tester::apply("mp17",
  1335. from_wkt<G>("MULTIPOINT(179 80,-179 -80,10 10)"),
  1336. 10, -80, -179+360, 80);
  1337. tester::apply("mp17a",
  1338. from_wkt<G>("MULTIPOINT(10 10,179 80,-179 -80)"),
  1339. 10, -80, -179+360, 80);
  1340. tester::apply("mp17b",
  1341. from_wkt<G>("MULTIPOINT(179 80,-179 -80,-90 0)"),
  1342. 179, -80, -90+360, 80);
  1343. tester::apply("mp17c",
  1344. from_wkt<G>("MULTIPOINT(-90 0,179 80,-179 -80,-90 0)"),
  1345. 179, -80, -90+360, 80);
  1346. tester::apply("mp18",
  1347. from_wkt<G>("MULTIPOINT(-170 45,20 25,40 40)"),
  1348. 20, 25, 190, 45);
  1349. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  1350. tester::apply("mp18a",
  1351. from_wkt<G>("MULTIPOINT(10 135,20 25,40 40)"),
  1352. 20, 25, 190, 45);
  1353. #endif
  1354. tester::apply("mp19",
  1355. from_wkt<G>("MULTIPOINT(350 45,20 25,40 40)"),
  1356. -10, 25, 40, 45);
  1357. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  1358. tester::apply("mp19a",
  1359. from_wkt<G>("MULTIPOINT(170 135,20 25,40 40)"),
  1360. -10, 25, 40, 45);
  1361. #endif
  1362. double eps = std::numeric_limits<double>::epsilon();
  1363. double heps = eps / 2;
  1364. {
  1365. G mp;
  1366. mp.push_back(P(1, 1));
  1367. mp.push_back(P(1-heps, 1-heps));
  1368. tester::apply("mp20", mp, 1-heps, 1-heps, 1, 1);
  1369. }
  1370. }
  1371. BOOST_AUTO_TEST_CASE( envelope_multipoint )
  1372. {
  1373. test_envelope_multipoint<bg::cs::spherical_equatorial<bg::degree> >();
  1374. test_envelope_multipoint<bg::cs::geographic<bg::degree> >();
  1375. }
  1376. template <typename CoordinateSystem>
  1377. void test_envelope_multipoint_with_height()
  1378. {
  1379. typedef bg::model::point<double, 3, CoordinateSystem> point_type;
  1380. typedef bg::model::multi_point<point_type> G;
  1381. typedef bg::model::box<point_type> B;
  1382. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1383. // empty multipoint
  1384. test_empty_geometry<CoordinateSystem, G>("mph00", "MULTIPOINT()");
  1385. tester::apply("mph01",
  1386. from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456)"),
  1387. 0, 0, 567, 10, 10, 1456);
  1388. tester::apply("mph02",
  1389. from_wkt<G>("MULTIPOINT(0 0 567,10 10 1456,20 90 967)"),
  1390. 0, 0, 567, 10, 90, 1456);
  1391. }
  1392. BOOST_AUTO_TEST_CASE( envelope_multipoint_with_height )
  1393. {
  1394. test_envelope_multipoint_with_height
  1395. <
  1396. bg::cs::spherical_equatorial<bg::degree>
  1397. >();
  1398. test_envelope_multipoint_with_height<bg::cs::geographic<bg::degree> >();
  1399. }
  1400. template <typename CoordinateSystem>
  1401. void test_envelope_box()
  1402. {
  1403. typedef bg::model::point<double, 2, CoordinateSystem> P;
  1404. typedef bg::model::box<P> G;
  1405. typedef bg::model::box<P> B;
  1406. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1407. tester::apply("b01",
  1408. from_wkt<G>("BOX(10 10,20 20)"),
  1409. 10, 10, 20, 20);
  1410. #ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
  1411. tester::apply("b02",
  1412. from_wkt<G>("BOX(10 370,20 20)"),
  1413. 10, 10, 20, 20);
  1414. #endif
  1415. // box crosses anti-meridian
  1416. tester::apply("b02a",
  1417. from_wkt<G>("BOX(170 10,-170 20)"),
  1418. 170, 10, 190, 20);
  1419. tester::apply("b03",
  1420. from_wkt<G>("BOX(-170 10,170 20)"),
  1421. -170, 10, 170, 20);
  1422. tester::apply("b04",
  1423. from_wkt<G>("BOX(10 10,350 20)"),
  1424. 10, 10, 350, 20);
  1425. tester::apply("b04a",
  1426. from_wkt<G>("BOX(10 10,-10 20)"),
  1427. 10, 10, 350, 20);
  1428. // box is a band
  1429. tester::apply("b05",
  1430. from_wkt<G>("BOX(0 10,360 20)"),
  1431. -180, 10, 180, 20);
  1432. tester::apply("b05a",
  1433. from_wkt<G>("BOX(0 10,0 20)"),
  1434. 0, 10, 0, 20);
  1435. // box is almost a band
  1436. tester::apply("b06",
  1437. from_wkt<G>("BOX(10 10,5 20)"),
  1438. 10, 10, 365, 20);
  1439. // initial box is a band that crosses itself
  1440. tester::apply("b07",
  1441. from_wkt<G>("BOX(0 10,540 20)"),
  1442. -180, 10, 180, 20);
  1443. // initial box is a band that crosses itself
  1444. tester::apply("b08",
  1445. from_wkt<G>("BOX(0 10,720 20)"),
  1446. -180, 10, 180, 20);
  1447. tester::apply("b09",
  1448. from_wkt<G>("BOX(10 10,10 10)"),
  1449. 10, 10, 10, 10);
  1450. tester::apply("b09a",
  1451. from_wkt<G>("BOX(370 10,370 10)"),
  1452. 10, 10, 10, 10);
  1453. // box contains north and south pole
  1454. tester::apply("b10",
  1455. from_wkt<G>("BOX(0 -90,0 90)"),
  1456. 0, -90, 0, 90);
  1457. // box contains north and south pole
  1458. tester::apply("b10a",
  1459. from_wkt<G>("BOX(10 -90,10 90)"),
  1460. 10, -90, 10, 90);
  1461. // box contains north and south pole
  1462. tester::apply("b10b",
  1463. from_wkt<G>("BOX(0 -90,10 90)"),
  1464. 0, -90, 10, 90);
  1465. // box contains north and south pole
  1466. tester::apply("b11",
  1467. from_wkt<G>("BOX(0 -90,180 90)"),
  1468. 0, -90, 180, 90);
  1469. // box contains north and south pole
  1470. tester::apply("b11a",
  1471. from_wkt<G>("BOX(10 -90,190 90)"),
  1472. 10, -90, 190, 90);
  1473. // box contains north and south pole
  1474. tester::apply("b11b",
  1475. from_wkt<G>("BOX(10 -90,110 90)"),
  1476. 10, -90, 110, 90);
  1477. // box contains north and south pole and is a band
  1478. // (box covers the entire spheroid)
  1479. tester::apply("b12",
  1480. from_wkt<G>("BOX(0 -90,360 90)"),
  1481. -180, -90, 180, 90);
  1482. // box contains north and south pole and is a band
  1483. // (box covers the entire spheroid)
  1484. tester::apply("b12a",
  1485. from_wkt<G>("BOX(10 -90,370 90)"),
  1486. -180, -90, 180, 90);
  1487. // box contains north and south pole and is a band
  1488. // (box covers the entire spheroid)
  1489. tester::apply("b12b",
  1490. from_wkt<G>("BOX(-175 -90,185 90)"),
  1491. -180, -90, 180, 90);
  1492. // box contains north and south pole and is a band
  1493. // (box covers the entire spheroid)
  1494. tester::apply("b12c",
  1495. from_wkt<G>("BOX(-175 -90,185 90)"),
  1496. -180, -90, 180, 90);
  1497. // box contains north and south pole and is a band and is self-intersecting
  1498. // (box covers the entire spheroid)
  1499. tester::apply("b12d",
  1500. from_wkt<G>("BOX(-175 -90,186 90)"),
  1501. -180, -90, 180, 90);
  1502. // box contains north and south pole and is a band and is self-intersecting
  1503. // (box covers the entire spheroid)
  1504. tester::apply("b12e",
  1505. from_wkt<G>("BOX(0 -90,540 90)"),
  1506. -180, -90, 180, 90);
  1507. // box contains north and south pole and is a band and is self-intersecting
  1508. // (box covers the entire spheroid)
  1509. tester::apply("b12f",
  1510. from_wkt<G>("BOX(10 -90,540 90)"),
  1511. -180, -90, 180, 90);
  1512. // box is a band
  1513. tester::apply("b13",
  1514. from_wkt<G>("BOX(180 -10,-180 10)"),
  1515. -180, -10, 180, 10);
  1516. // box contains north and south pole and is a band
  1517. // (box covers the entire spheroid)
  1518. tester::apply("b13a",
  1519. from_wkt<G>("BOX(180 -90,-180 90)"),
  1520. -180, -90, 180, 90);
  1521. tester::apply("b14",
  1522. from_wkt<G>("BOX(0 10,30 90)"),
  1523. 0, 10, 30, 90);
  1524. tester::apply("b15",
  1525. from_wkt<G>("BOX(179 10,178 70)"),
  1526. 179, 10, 538, 70);
  1527. // box contains north pole
  1528. tester::apply("b16",
  1529. from_wkt<G>("BOX(10 40,20 90)"),
  1530. 10, 40, 20, 90);
  1531. tester::apply("b16a",
  1532. from_wkt<G>("BOX(170 40,-170 90)"),
  1533. 170, 40, 190, 90);
  1534. // box contains south pole
  1535. tester::apply("b17",
  1536. from_wkt<G>("BOX(10 -90,20 40)"),
  1537. 10, -90, 20, 40);
  1538. tester::apply("b17a",
  1539. from_wkt<G>("BOX(150 -90,-150 40)"),
  1540. 150, -90, 210, 40);
  1541. // box degenerates to the north pole
  1542. tester::apply("b98",
  1543. from_wkt<G>("BOX(10 90,20 90)"),
  1544. 0, 90, 0, 90);
  1545. // box degenerates to the south pole
  1546. tester::apply("b99",
  1547. from_wkt<G>("BOX(10 -90,20 -90)"),
  1548. 0, -90, 0, -90);
  1549. double eps = std::numeric_limits<double>::epsilon();
  1550. double heps = eps / 2;
  1551. tester::apply("b100", G(P(1-heps, 1-heps), P(1, 1)), 1-heps, 1-heps, 1, 1);
  1552. }
  1553. template <typename CoordinateSystem>
  1554. void test_envelope_box_polar()
  1555. {
  1556. typedef bg::model::point<double, 2, CoordinateSystem> P;
  1557. typedef bg::model::box<P> G;
  1558. typedef bg::model::box<P> B;
  1559. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1560. tester::apply("b01",
  1561. from_wkt<G>("BOX(10 10,20 20)"),
  1562. 10, 10, 20, 20);
  1563. tester::apply("b02a",
  1564. from_wkt<G>("BOX(170 10,-170 20)"),
  1565. 170, 10, 190, 20);
  1566. tester::apply("b10b",
  1567. from_wkt<G>("BOX(0 0,10 180)"),
  1568. 0, 0, 10, 180);
  1569. tester::apply("b16a",
  1570. from_wkt<G>("BOX(170 40,-170 180)"),
  1571. 170, 40, 190, 180);
  1572. }
  1573. BOOST_AUTO_TEST_CASE( envelope_box )
  1574. {
  1575. test_envelope_box<bg::cs::spherical_equatorial<bg::degree> >();
  1576. test_envelope_box<bg::cs::geographic<bg::degree> >();
  1577. test_envelope_box_polar<bg::cs::spherical<bg::degree> >();
  1578. }
  1579. template <typename CoordinateSystem>
  1580. void test_envelope_box_with_height()
  1581. {
  1582. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1583. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1584. typedef bg::model::box<point_type> G;
  1585. typedef bg::model::box<point_type> B;
  1586. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1587. tester::apply("bh01",
  1588. from_wkt<G>("BOX(10 10 567,20 20 2834)"),
  1589. 10, 10, 567, 20, 20, 2834);
  1590. tester::apply("bh02",
  1591. from_wkt<G>("BOX(10 10 567,20 20 567)"),
  1592. 10, 10, 567, 20, 20, 567);
  1593. tester::apply("bh03",
  1594. from_wkt<G>("BOX(0 10 567,170 90 1567)"),
  1595. 0, 10, 567, 170, 90, 1567);
  1596. }
  1597. BOOST_AUTO_TEST_CASE( envelope_box_with_height )
  1598. {
  1599. test_envelope_box_with_height<bg::cs::spherical_equatorial<bg::degree> >();
  1600. test_envelope_box_with_height<bg::cs::geographic<bg::degree> >();
  1601. }
  1602. BOOST_AUTO_TEST_CASE( envelope_sphere_linestring )
  1603. {
  1604. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1605. typedef bg::model::point<double, 2, coordinate_system_type> P;
  1606. typedef bg::model::linestring<P> G;
  1607. typedef bg::model::box<P> B;
  1608. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1609. // empty linestring
  1610. test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
  1611. tester::apply("l01",
  1612. from_wkt<G>("LINESTRING(10 15)"),
  1613. 10, 15, 10, 15);
  1614. tester::apply("l01a",
  1615. from_wkt<G>("LINESTRING(370 15)"),
  1616. 10, 15, 10, 15);
  1617. tester::apply("l01b",
  1618. from_wkt<G>("LINESTRING(370 90)"),
  1619. 0, 90, 0, 90);
  1620. tester::apply("l02",
  1621. from_wkt<G>("LINESTRING(10 10,20 20,10 30)"),
  1622. 10, 10, 20, 30);
  1623. // linestring that circles the entire globe
  1624. tester::apply("l03",
  1625. from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
  1626. -180, 0, 180, 33.587539971516854,
  1627. 4.0 * std::numeric_limits<double>::epsilon());
  1628. // linestring that crosses the antimeridian but staying close to it
  1629. tester::apply("l04",
  1630. from_wkt<G>("LINESTRING(-170 10,170 45,160 5,-160 25)"),
  1631. 160, 5, 200, 45);
  1632. // linestring that goes through the north pole (twice)
  1633. tester::apply("l05",
  1634. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30)"),
  1635. -170, 30, 20, 90);
  1636. // linestring that goes through the north pole (three times)
  1637. tester::apply("l05a",
  1638. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70)"),
  1639. -170, 30, 30, 90);
  1640. // linestring that goes through the north pole (four times)
  1641. tester::apply("l05b",
  1642. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25)"),
  1643. -170, 25, 40, 90);
  1644. // linestring that goes through the north pole (five times)
  1645. tester::apply("l05c",
  1646. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45)"),
  1647. -170, 25, 50, 90);
  1648. // linestring that goes through the north pole (five times)
  1649. tester::apply("l05d",
  1650. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45,185 45)"),
  1651. -170, 25, 185, 90);
  1652. // linestring that crosses the antimeridian
  1653. tester::apply("l06",
  1654. from_wkt<G>("LINESTRING(-160 85,-170 80,170 40,160 80)"),
  1655. 160, 40, 200, 85);
  1656. // linestring that crosses the antimeridian
  1657. tester::apply("l06a",
  1658. from_wkt<G>("LINESTRING(-130 85,-170 84,170 40,160 80)"),
  1659. 160, 40, 230, 85.02629680862029);
  1660. // linestring that goes through the north pole
  1661. tester::apply("l07",
  1662. from_wkt<G>("LINESTRING(-160 40,-170 90,-140 40,-50 30)"),
  1663. -160, 30, -50, 90);
  1664. // linestring that degenerates to the north pole
  1665. tester::apply("l08",
  1666. from_wkt<G>("LINESTRING(-40 90,-30 90,-140 90,10 90)"),
  1667. 0, 90, 0, 90);
  1668. // linestring with duplicate points
  1669. tester::apply("l09",
  1670. from_wkt<G>("LINESTRING(-40 20,-40 20,-140 85,-10 5,-10 5)"),
  1671. -140, 5, -10, 86.184540574427757);
  1672. // linestring with duplicate points
  1673. tester::apply("l09a",
  1674. from_wkt<G>("LINESTRING(-40 20,320 20,-140 85,-10 5,350 5)"),
  1675. -140, 5, -10, 86.184540574427757);
  1676. // linestring that lies on the equator
  1677. tester::apply("l10",
  1678. from_wkt<G>("LINESTRING(0 0,50 0)"),
  1679. 0, 0, 50, 0);
  1680. // linestring that lies on the equator
  1681. tester::apply("l10a",
  1682. from_wkt<G>("LINESTRING(-50 0,50 0)"),
  1683. -50, 0, 50, 0);
  1684. // linestring that lies on the equator and touches antimeridian
  1685. tester::apply("l10b",
  1686. from_wkt<G>("LINESTRING(50 0,180 0)"),
  1687. 50, 0, 180, 0);
  1688. // linestring that lies on the equator and crosses antimeridian
  1689. tester::apply("l10c",
  1690. from_wkt<G>("LINESTRING(-170 0,160 0)"),
  1691. 160, 0, 190, 0);
  1692. double eps = std::numeric_limits<double>::epsilon();
  1693. double heps = eps / 2;
  1694. {
  1695. G l;
  1696. l.push_back(P(1, 1));
  1697. l.push_back(P(1-heps, 1-heps));
  1698. tester::apply("l11", l, 1-heps, 1-heps, 1, 1);
  1699. }
  1700. {
  1701. G l;
  1702. l.push_back(P(0, 0));
  1703. l.push_back(P(1-heps, 1-heps));
  1704. l.push_back(P(0, 0));
  1705. l.push_back(P(1, 1));
  1706. tester::apply("l12", l, 0, 0, 1, 1);
  1707. }
  1708. }
  1709. BOOST_AUTO_TEST_CASE( envelope_spheroid_linestring )
  1710. {
  1711. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1712. typedef bg::model::point<double, 2, coordinate_system_type> P;
  1713. typedef bg::model::linestring<P> G;
  1714. typedef bg::model::box<P> B;
  1715. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1716. // empty linestring
  1717. test_empty_geometry<coordinate_system_type, G>("l00", "LINESTRING()");
  1718. tester::apply("l01",
  1719. from_wkt<G>("LINESTRING(10 15)"),
  1720. 10, 15, 10, 15);
  1721. tester::apply("l01a",
  1722. from_wkt<G>("LINESTRING(370 15)"),
  1723. 10, 15, 10, 15);
  1724. tester::apply("l01b",
  1725. from_wkt<G>("LINESTRING(370 90)"),
  1726. 0, 90, 0, 90);
  1727. tester::apply("l02",
  1728. from_wkt<G>("LINESTRING(10 10,20 20,10 30)"),
  1729. 10, 10, 20, 30);
  1730. // linestring that circles the entire globe
  1731. tester::apply("l03",
  1732. from_wkt<G>("LINESTRING(-185 0,-170 25,-50 10,10 10,20 20,100 5,180 15)"),
  1733. -180, 0, 180, rng(33.702476580412359, 33.702476580413318));
  1734. // linestring that crosses the antimeridian but staying close to it
  1735. tester::apply("l04",
  1736. from_wkt<G>("LINESTRING(-170 10,170 45,160 5,-160 25)"),
  1737. 160, 5, 200, 45);
  1738. // linestring that goes through the north pole (twice)
  1739. tester::apply("l05",
  1740. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30)"),
  1741. -170, 30, 20, 90);
  1742. // linestring that goes through the north pole (three times)
  1743. tester::apply("l05a",
  1744. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70)"),
  1745. -170, 30, 30, 90);
  1746. // linestring that goes through the north pole (four times)
  1747. tester::apply("l05b",
  1748. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25)"),
  1749. -170, 25, 40, 90);
  1750. // linestring that goes through the north pole (five times)
  1751. tester::apply("l05c",
  1752. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45)"),
  1753. -170, 25, 50, 90);
  1754. // linestring that goes through the north pole (five times)
  1755. tester::apply("l05d",
  1756. from_wkt<G>("LINESTRING(-170 80,10 60,20 80,-160 30,-150 30,30 70,40 85,-140 25,-130 25,50 45,185 45)"),
  1757. -170, 25, 185, 90);
  1758. // linestring that crosses the antimeridian
  1759. tester::apply("l06",
  1760. from_wkt<G>("LINESTRING(-160 85,-170 80,170 40,160 80)"),
  1761. 160, 40, 200, 85);
  1762. // linestring that crosses the antimeridian
  1763. tester::apply("l06a",
  1764. from_wkt<G>("LINESTRING(-130 85,-170 84,170 40,160 80)"),
  1765. 160, 40, 230, 85.02630556315151);
  1766. // linestring that goes through the north pole
  1767. tester::apply("l07",
  1768. from_wkt<G>("LINESTRING(-160 40,-170 90,-140 40,-50 30)"),
  1769. -160, 30, -50, 90);
  1770. // linestring that degenerates to the north pole
  1771. tester::apply("l08",
  1772. from_wkt<G>("LINESTRING(-40 90,-30 90,-140 90,10 90)"),
  1773. 0, 90, 0, 90);
  1774. // linestring with duplicate points
  1775. tester::apply("l09",
  1776. from_wkt<G>("LINESTRING(-40 20,-40 20,-140 85,-10 5,-10 5)"),
  1777. -140, 5, -10, 86.18564770636192);
  1778. // linestring with duplicate points
  1779. tester::apply("l09a",
  1780. from_wkt<G>("LINESTRING(-40 20,320 20,-140 85,-10 5,350 5)"),
  1781. -140, 5, -10, 86.18564770636192);
  1782. // linestring that lies on the equator
  1783. tester::apply("l10",
  1784. from_wkt<G>("LINESTRING(0 0,50 0)"),
  1785. 0, 0, 50, 0);
  1786. // linestring that lies on the equator
  1787. tester::apply("l10a",
  1788. from_wkt<G>("LINESTRING(-50 0,50 0)"),
  1789. -50, 0, 50, 0);
  1790. // linestring that lies on the equator and touches antimeridian
  1791. tester::apply("l10b",
  1792. from_wkt<G>("LINESTRING(50 0,180 0)"),
  1793. 50, 0, 180, 0);
  1794. // linestring that lies on the equator and crosses antimeridian
  1795. tester::apply("l10c",
  1796. from_wkt<G>("LINESTRING(-170 0,160 0)"),
  1797. 160, 0, 190, 0);
  1798. double eps = std::numeric_limits<double>::epsilon();
  1799. double heps = eps / 2;
  1800. {
  1801. G l;
  1802. l.push_back(P(1, 1));
  1803. l.push_back(P(1-heps, 1-heps));
  1804. tester::apply("l11", l, 1-heps, 1-heps, 1, 1);
  1805. }
  1806. {
  1807. G l;
  1808. l.push_back(P(0, 0));
  1809. l.push_back(P(1-heps, 1-heps));
  1810. l.push_back(P(0, 0));
  1811. l.push_back(P(1, 1));
  1812. tester::apply("l12", l, 0, 0, 1, 1);
  1813. }
  1814. }
  1815. BOOST_AUTO_TEST_CASE( envelope_linestring_sphere_with_height )
  1816. {
  1817. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1818. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1819. typedef bg::model::linestring<point_type> G;
  1820. typedef bg::model::box<point_type> B;
  1821. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1822. // empty linestring
  1823. test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
  1824. tester::apply("lh01",
  1825. from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
  1826. 10, 15, 30, 30, 35, 434);
  1827. }
  1828. BOOST_AUTO_TEST_CASE( envelope_linestring_spheroid_with_height )
  1829. {
  1830. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1831. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1832. typedef bg::model::linestring<point_type> G;
  1833. typedef bg::model::box<point_type> B;
  1834. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1835. // empty linestring
  1836. test_empty_geometry<coordinate_system_type, G>("lh00", "LINESTRING()");
  1837. tester::apply("lh01",
  1838. from_wkt<G>("LINESTRING(10 15 30,20 25 434,30 35 186)"),
  1839. 10, 15, 30, 30, 35, 434);
  1840. }
  1841. BOOST_AUTO_TEST_CASE( envelope_sphere_multilinestring )
  1842. {
  1843. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1844. typedef bg::model::point<double, 2, coordinate_system_type> point_type;
  1845. typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
  1846. typedef bg::model::box<point_type> B;
  1847. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1848. // empty multilinestring
  1849. test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
  1850. // invalid multilinestring
  1851. test_empty_geometry<coordinate_system_type, G>("ml00a",
  1852. "MULTILINESTRING(())");
  1853. // invalid multilinestring
  1854. test_empty_geometry<coordinate_system_type, G>("ml00b",
  1855. "MULTILINESTRING((),())");
  1856. // invalid multilinestring
  1857. tester::apply("ml00c",
  1858. from_wkt<G>("MULTILINESTRING((10 15),(),())"),
  1859. 10, 15, 10, 15);
  1860. // invalid multilinestring
  1861. tester::apply("ml00d",
  1862. from_wkt<G>("MULTILINESTRING((),(10 15),())"),
  1863. 10, 15, 10, 15);
  1864. tester::apply("ml01",
  1865. from_wkt<G>("MULTILINESTRING((10 15))"),
  1866. 10, 15, 10, 15);
  1867. #ifdef BOOST_GEOMETRY_TEST_FAILURES
  1868. tester::apply("ml01a",
  1869. from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
  1870. 10, 15, 10, 15);
  1871. #endif
  1872. tester::apply("ml02",
  1873. from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
  1874. -180, 25, 180, 81.113793608034072);
  1875. tester::apply("ml03",
  1876. from_wkt<G>("MULTILINESTRING((-150 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
  1877. -150, 25, 200, 81.113793608034072);
  1878. tester::apply("ml04",
  1879. from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
  1880. -150, 35, 100, 80.07385383411011);
  1881. tester::apply("ml04a",
  1882. from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
  1883. 10, 25, 260, 80.07385383411011);
  1884. tester::apply("ml05",
  1885. from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
  1886. -140, 35, 100, 80.07385383411011);
  1887. tester::apply("ml05a",
  1888. from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
  1889. 10, 25, 260, 80.07385383411011);
  1890. }
  1891. BOOST_AUTO_TEST_CASE( envelope_spheroid_multilinestring )
  1892. {
  1893. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1894. typedef bg::model::point<double, 2, coordinate_system_type> point_type;
  1895. typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
  1896. typedef bg::model::box<point_type> B;
  1897. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1898. // empty multilinestring
  1899. test_empty_geometry<coordinate_system_type, G>("ml00", "MULTILINESTRING()");
  1900. // invalid multilinestring
  1901. test_empty_geometry<coordinate_system_type, G>("ml00a",
  1902. "MULTILINESTRING(())");
  1903. // invalid multilinestring
  1904. test_empty_geometry<coordinate_system_type, G>("ml00b",
  1905. "MULTILINESTRING((),())");
  1906. // invalid multilinestring
  1907. tester::apply("ml00c",
  1908. from_wkt<G>("MULTILINESTRING((10 15),(),())"),
  1909. 10, 15, 10, 15);
  1910. // invalid multilinestring
  1911. tester::apply("ml00d",
  1912. from_wkt<G>("MULTILINESTRING((),(10 15),())"),
  1913. 10, 15, 10, 15);
  1914. tester::apply("ml01",
  1915. from_wkt<G>("MULTILINESTRING((10 15))"),
  1916. 10, 15, 10, 15);
  1917. #ifdef BOOST_GEOMETRY_TEST_FAILURES
  1918. tester::apply("ml01a",
  1919. from_wkt<G>("MULTILINESTRING((),(),(10 15),())"),
  1920. 10, 15, 10, 15);
  1921. #endif
  1922. tester::apply("ml02",
  1923. from_wkt<G>("MULTILINESTRING((-170 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
  1924. -180, 25, 180, 81.115885076701147);
  1925. tester::apply("ml03",
  1926. from_wkt<G>("MULTILINESTRING((-150 40,-100 80,10 40),(-10 25,10 35,100 45),(50 30,150 45,-160 30))"),
  1927. -150, 25, 200, 81.115885076701147);
  1928. tester::apply("ml04",
  1929. from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80))"),
  1930. -150, 35, 100, rng(80.07385383411011, 80.082544902477267));
  1931. tester::apply("ml04a",
  1932. from_wkt<G>("MULTILINESTRING((-150 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
  1933. 10, 25, 260, rng(80.07385383411011, 80.082544902477267));
  1934. tester::apply("ml05",
  1935. from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80))"),
  1936. -140, 35, 100, rng(80.07385383411011, 80.082544902477267));
  1937. tester::apply("ml05a",
  1938. from_wkt<G>("MULTILINESTRING((-140 40,-100 80),(10 35,100 80),(170 25,-160 80))"),
  1939. 10, 25, 260, rng(80.07385383411011, 80.082544902477267));
  1940. }
  1941. BOOST_AUTO_TEST_CASE( envelope_multilinestring_sphere_with_height )
  1942. {
  1943. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1944. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1945. typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
  1946. typedef bg::model::box<point_type> B;
  1947. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1948. tester::apply("mlh01",
  1949. from_wkt<G>("MULTILINESTRING((10 15 1000))"),
  1950. 10, 15, 1000, 10, 15, 1000);
  1951. #ifdef BOOST_GEOMETRY_TEST_FAILURES
  1952. tester::apply("mlh01a",
  1953. from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
  1954. 10, 15, 1000, 10, 15, 1000);
  1955. #endif
  1956. tester::apply("mlh02",
  1957. from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
  1958. -10, 25, 300, 260, 80, 700);
  1959. }
  1960. BOOST_AUTO_TEST_CASE( envelope_multilinestring_spheroid_with_height )
  1961. {
  1962. typedef bg::cs::geographic<bg::degree> coordinate_system_type;
  1963. typedef bg::model::point<double, 3, coordinate_system_type> point_type;
  1964. typedef bg::model::multi_linestring<bg::model::linestring<point_type> > G;
  1965. typedef bg::model::box<point_type> B;
  1966. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1967. tester::apply("mlh01",
  1968. from_wkt<G>("MULTILINESTRING((10 15 1000))"),
  1969. 10, 15, 1000, 10, 15, 1000);
  1970. #ifdef BOOST_GEOMETRY_TEST_FAILURES
  1971. tester::apply("mlh01a",
  1972. from_wkt<G>("MULTILINESTRING((),(),(10 15 1000),())"),
  1973. 10, 15, 1000, 10, 15, 1000);
  1974. #endif
  1975. tester::apply("mlh02",
  1976. from_wkt<G>("MULTILINESTRING((-170 40 400,-100 80 300),(-10 25 600,10 35 700,120 45 450))"),
  1977. -10, 25, 300, 260, 80, 700);
  1978. }
  1979. //Test spherical polygons and rings (geographic should be similar)
  1980. BOOST_AUTO_TEST_CASE( envelope_polygon )
  1981. {
  1982. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  1983. typedef bg::model::point<double, 2, coordinate_system_type> point_type;
  1984. typedef bg::model::polygon<point_type> G;
  1985. typedef bg::model::box<point_type> B;
  1986. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  1987. typedef bg::model::ring<point_type> R;
  1988. typedef test_envelope_on_sphere_or_spheroid<R, B> testerR;
  1989. R ring1;
  1990. bg::append(ring1, point_type(0.0, 0.0));
  1991. bg::append(ring1, point_type(0.0, 5.0));
  1992. bg::append(ring1, point_type(5.0, 5.0));
  1993. bg::append(ring1, point_type(5.0, 0.0));
  1994. bg::append(ring1, point_type(0.0, 0.0));
  1995. testerR::apply("r01",
  1996. ring1,
  1997. 0, 0, 5, 5.0047392446083938);
  1998. tester::apply("p01",
  1999. from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0))"),
  2000. 0, 0, 1, 1.0000380706527705);
  2001. tester::apply("p02",
  2002. from_wkt<G>("POLYGON((0 0,1 0,1 1,0 1,0 0),(0.5 0.5,0.7 0.5,0.7 0.7,0.5 0.5))"),
  2003. 0, 0, 1, 1.0000380706527705);
  2004. tester::apply("p03",
  2005. from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5))"),
  2006. 0.5, 0.5, 0.7, 0.70000106605644807);
  2007. tester::apply("p04",
  2008. from_wkt<G>("POLYGON((),(0.5 0.5,0.5 0.7,0.7 0.7,0.5 0.5),\
  2009. (0.7 0.5,0.9 0.5,0.9 0.7,0.7 0.5))"),
  2010. 0.5, 0.5, 0.9, 0.70000106605644807);
  2011. // https://github.com/boostorg/geometry/issues/466
  2012. tester::apply("p5-issue466",
  2013. from_wkt<G>("POLYGON((2.4 48.9021,2.4 48.89,2.3 48.89,2.3 48.9021,2.4 48.9021))"),
  2014. 2.3, 48.89, 2.4, 48.902110807274966);
  2015. tester::apply("p6-issue466",
  2016. from_wkt<G>("POLYGON((2.4 48.90215,2.4 48.89,2.3 48.89,2.3 48.90215,2.4 48.90215))"),
  2017. 2.3, 48.89, 2.4, 48.902160807272381);
  2018. tester::apply("p7-issue466",
  2019. from_wkt<G>("POLYGON((2.4 48.9022,2.4 48.89,2.3 48.89,2.3 48.9022,2.4 48.9022))"),
  2020. 2.3, 48.89, 2.4, 48.902210807269796);
  2021. }
  2022. // unit test for rings de-activated for now (current implementation
  2023. // for area on the spherical equatorial coordinate system is not complete)
  2024. // TODO: re-activate once implementation is done
  2025. // right now implementation does not distinguish between ccw and cw rings
  2026. BOOST_AUTO_TEST_CASE( envelope_cw_ring )
  2027. {
  2028. typedef bg::cs::spherical_equatorial<bg::degree> coordinate_system_type;
  2029. typedef bg::model::point<double, 2, coordinate_system_type> point_type;
  2030. typedef bg::model::polygon<point_type> G;
  2031. typedef bg::model::box<point_type> B;
  2032. typedef test_envelope_on_sphere_or_spheroid<G, B> tester;
  2033. //double const eps = std::numeric_limits<double>::epsilon();
  2034. tester::apply("r01cw",
  2035. from_wkt<G>("POLYGON((0 10,0 45,50 10,0 10))"),
  2036. 0, 10, 50, 45);
  2037. #if 0
  2038. // ring that contains both the north and south poles in its interior
  2039. tester::apply("r01cw-r",
  2040. from_wkt<G>("POLYGON((0 10,50 10,0 45,0 10))"),
  2041. -180, -90, 180, 90);
  2042. // ring that contains the north pole in its interior
  2043. tester::apply("r02cw",
  2044. from_wkt<G>("POLYGON((0 0,-50 0,-170 0,180 0,100 0,0 0))"),
  2045. -180, 0, 180, 90);
  2046. // -180, -90, 180, 0);
  2047. // ring that contains the south pole in its interior
  2048. tester::apply("r02cw-r",
  2049. from_wkt<G>("POLYGON((0 0,100 0,180 0,-170 0,-50 0,0 0))"),
  2050. -180, -90, 180, 0);
  2051. // -180, 0, 180, 90);
  2052. // ring that contains the north pole in its interior
  2053. tester::apply("r03cw",
  2054. from_wkt<G>("POLYGON((0 -10,-50 -10,-170 -10,180 -10,100 -10,0 -10))"),
  2055. -180, -19.42540014068282, 180, 90);
  2056. // -180, -90, 180, -10);
  2057. // ring that contains both the south and north poles in its interior
  2058. tester::apply("r03cw-r",
  2059. from_wkt<G>("POLYGON((0 -10,100 -10,180 -10,-170 -10,-50 -10,0 -10))"),
  2060. -180, -90, 180, -10);
  2061. // -180, -19.42540014068282, 180, 90);
  2062. // ring that has the north pole as vertex and contains the south pole
  2063. tester::apply("r04cw",
  2064. from_wkt<G>("POLYGON((0 0,-50 90,-50 0,0 0))"),
  2065. -180, -90, 180, 90);
  2066. // ring that has the north pole as vertex
  2067. tester::apply("r04cw-r",
  2068. from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
  2069. -50, 0, 0, 90);
  2070. // ring that crosses antimeridian but does not contain any pole
  2071. tester::apply("r05cw",
  2072. from_wkt<G>("POLYGON((-140 0,140 10,-140 80,-140 0))"),
  2073. 140, 0, 220, 80);
  2074. // ring that crosses antimeridian multiple times but does not
  2075. // contain any pole
  2076. tester::apply("r06cw",
  2077. from_wkt<G>("POLYGON((-140 10,140 10,140 80,-140 80,-140 10))"),
  2078. 140, 10, 220, 82.30737118075496,
  2079. 2 * eps);
  2080. // ring that crosses antimeridian multiple times but does not
  2081. // contain any pole
  2082. tester::apply("r07cw",
  2083. from_wkt<G>("POLYGON((-140 10,140 10,180 80,-140 10))"),
  2084. 140, 10, 220, 80);
  2085. // ring that goes through the north pole
  2086. tester::apply("r08cw",
  2087. from_wkt<G>("POLYGON((0 0,-50 0,-50 90,0 0))"),
  2088. -50, 0, 0, 90);
  2089. // ring that goes through the south pole and contains the north pole
  2090. tester::apply("r09cw",
  2091. from_wkt<G>("POLYGON((0 0,0 -90,50 0,0 0))"),
  2092. -180, -90, 180, 90);
  2093. // ring that goes through the south pole
  2094. tester::apply("r09cw-r",
  2095. from_wkt<G>("POLYGON((0 0,50 0,50 -90,0 0))"),
  2096. 0, -90, 50, 0);
  2097. // ring that goes through both south and north pole
  2098. tester::apply("r10cw",
  2099. from_wkt<G>("POLYGON((50 0,50 -90,40 0,40 90,50 0))"),
  2100. 40, -90, 50, 90);
  2101. // ring that goes through both south and north pole and crosses antimeridian
  2102. tester::apply("r11cw",
  2103. from_wkt<G>("POLYGON((-170 0,-170 -90,160 0,160 90,-170 0))"),
  2104. 160, -90, 190, 90);
  2105. // ring with edge that goes through the north pole and contains
  2106. // south pole (the bounding box is the entire globe)
  2107. tester::apply("r12cw",
  2108. from_wkt<G>("POLYGON((-50 40,130 10,170 80,-50 40))"),
  2109. -180, -90, 180, 90);
  2110. // -180, 10, 180, 90);
  2111. // ring with edge that goes through the north pole
  2112. tester::apply("r12cw-r",
  2113. from_wkt<G>("POLYGON((-50 40,170 80,130 10,-50 40))"),
  2114. -180, 10, 180, 90);
  2115. // -180, -90, 180, 90);
  2116. // ring that represents a spherical cap near the north pole
  2117. tester::apply("r13cw",
  2118. from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 90,100 45))"),
  2119. -100, 45, 100, 90);
  2120. // ring that represents the complement of a spherical cap
  2121. // near the north pole
  2122. tester::apply("r13cw-r",
  2123. from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 90,-100 45))"),
  2124. -180, -90, 180, 90);
  2125. // ring that represents the complement of a spherical cap
  2126. // that touches the south pole
  2127. tester::apply("r14cw",
  2128. from_wkt<G>("POLYGON((-100 45,0 45,100 45,100 -90,-100 45))"),
  2129. -100, -90, 100, 57.26759279038765);
  2130. // ring that represents a spherical cap that touches the south pole
  2131. tester::apply("r14cw-r",
  2132. from_wkt<G>("POLYGON((100 45,0 45,-100 45,-100 -90,100 45))"),
  2133. -180, -90, 180, 90);
  2134. // ring with edge that goes through the south pole
  2135. tester::apply("r15cw",
  2136. from_wkt<G>("POLYGON((-50 -40,130 -10,170 -80,-50 -40))"),
  2137. -180, -90, 180, -10);
  2138. // ring with edge that goes through the south pole and contains
  2139. // north pole (the bounding box is the entire globe)
  2140. tester::apply("r15cw-r",
  2141. from_wkt<G>("POLYGON((-50 -40,170 -80,130 -10,-50 -40))"),
  2142. -180, -90, 180, 90);
  2143. // ring that does not contain any pole and lies in the lower hemisphere
  2144. tester::apply("r16",
  2145. from_wkt<G>("POLYGON((-50 -80,-50 -40,-30 -40,-30 -80,-50 -80))"),
  2146. -50, -80.14892388341609, -30, -40);
  2147. // ring that lies in the lower hemisphere and contains both poles
  2148. tester::apply("r16-r",
  2149. from_wkt<G>("POLYGON((-50 -80,-30 -80,-30 -40,-50 -40,-50 -80))"),
  2150. -180, -90, 180, 90);
  2151. // ring that goes through the south pole and contains the north pole
  2152. tester::apply("r17cw",
  2153. from_wkt<G>("POLYGON((50 0,50 -90,100 0,50 0))"),
  2154. -180, -90, 180, 90);
  2155. // ring that goes through the south pole
  2156. tester::apply("r17cw-r",
  2157. from_wkt<G>("POLYGON((50 0,100 0,100 -90,50 0))"),
  2158. 50, -90, 100, 0);
  2159. // ring that goes through the south pole and contains the north pole
  2160. tester::apply("r18cw",
  2161. from_wkt<G>("POLYGON((50 0,50 -90,460 0,50 0))"),
  2162. -180, -90, 180, 90);
  2163. // ring that goes through the south pole
  2164. tester::apply("r18cw-r",
  2165. from_wkt<G>("POLYGON((50 0,460 0,100 -90,50 0))"),
  2166. 50, -90, 100, 0);
  2167. // ring that goes through the south pole and contains the north pole
  2168. tester::apply("r19cw",
  2169. from_wkt<G>("POLYGON((50 0,50 -90,-260 0,50 0))"),
  2170. -180, -90, 180, 90);
  2171. // ring that goes through the south pole
  2172. tester::apply("r19cw-r",
  2173. from_wkt<G>("POLYGON((50 0,-260 0,100 -90,50 0))"),
  2174. 50, -90, 100, 0);
  2175. // ring that goes through both poles
  2176. tester::apply("r20cw",
  2177. from_wkt<G>("POLYGON((10 0,10 90,20 0,20 -90,10 0))"),
  2178. 10, -90, 20, 90); // SUCCEEDS FOR WRONG REASON
  2179. // ring that goes through both poles
  2180. tester::apply("r20cw-r",
  2181. from_wkt<G>("POLYGON((10 0,10 -90,20 0,20 90,10 0))"),
  2182. -180, -90, 180, 90); // FAILS NOW
  2183. // ring that goes through both poles and its boundary forms
  2184. // a great circle
  2185. tester::apply("r21cw",
  2186. from_wkt<G>("POLYGON((-10 0,-10 90,170 0,170 -90,-10 0))"),
  2187. -10, -90, 170, 90); // SUCCEEDS FOR WRONG REASON
  2188. // ring that goes through both poles and its boundary forms
  2189. // a great circle
  2190. tester::apply("r21cw-r",
  2191. from_wkt<G>("POLYGON((-10 0,-10 -90,170 0,170 90,-10 0))"),
  2192. 170, -90, 350, 90); // FAILS NOW
  2193. #endif
  2194. }