polygon_traits.hpp 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861
  1. /*
  2. Copyright 2008 Intel Corporation
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. */
  7. #ifndef BOOST_POLYGON_POLYGON_TRAITS_HPP
  8. #define BOOST_POLYGON_POLYGON_TRAITS_HPP
  9. namespace boost { namespace polygon{
  10. template <typename T, typename enable = gtl_yes>
  11. struct polygon_90_traits {
  12. typedef typename T::coordinate_type coordinate_type;
  13. typedef typename T::compact_iterator_type compact_iterator_type;
  14. // Get the begin iterator
  15. static inline compact_iterator_type begin_compact(const T& t) {
  16. return t.begin_compact();
  17. }
  18. // Get the end iterator
  19. static inline compact_iterator_type end_compact(const T& t) {
  20. return t.end_compact();
  21. }
  22. // Get the number of sides of the polygon
  23. static inline std::size_t size(const T& t) {
  24. return t.size();
  25. }
  26. // Get the winding direction of the polygon
  27. static inline winding_direction winding(const T&) {
  28. return unknown_winding;
  29. }
  30. };
  31. template <typename T>
  32. struct polygon_traits_general {
  33. typedef typename T::coordinate_type coordinate_type;
  34. typedef typename T::iterator_type iterator_type;
  35. typedef typename T::point_type point_type;
  36. // Get the begin iterator
  37. static inline iterator_type begin_points(const T& t) {
  38. return t.begin();
  39. }
  40. // Get the end iterator
  41. static inline iterator_type end_points(const T& t) {
  42. return t.end();
  43. }
  44. // Get the number of sides of the polygon
  45. static inline std::size_t size(const T& t) {
  46. return t.size();
  47. }
  48. // Get the winding direction of the polygon
  49. static inline winding_direction winding(const T&) {
  50. return unknown_winding;
  51. }
  52. };
  53. template <typename T>
  54. struct polygon_traits_90 {
  55. typedef typename polygon_90_traits<T>::coordinate_type coordinate_type;
  56. typedef iterator_compact_to_points<typename polygon_90_traits<T>::compact_iterator_type, point_data<coordinate_type> > iterator_type;
  57. typedef point_data<coordinate_type> point_type;
  58. // Get the begin iterator
  59. static inline iterator_type begin_points(const T& t) {
  60. return iterator_type(polygon_90_traits<T>::begin_compact(t),
  61. polygon_90_traits<T>::end_compact(t));
  62. }
  63. // Get the end iterator
  64. static inline iterator_type end_points(const T& t) {
  65. return iterator_type(polygon_90_traits<T>::end_compact(t),
  66. polygon_90_traits<T>::end_compact(t));
  67. }
  68. // Get the number of sides of the polygon
  69. static inline std::size_t size(const T& t) {
  70. return polygon_90_traits<T>::size(t);
  71. }
  72. // Get the winding direction of the polygon
  73. static inline winding_direction winding(const T& t) {
  74. return polygon_90_traits<T>::winding(t);
  75. }
  76. };
  77. #ifndef BOOST_VERY_LITTLE_SFINAE
  78. template <typename T, typename enable = gtl_yes>
  79. struct polygon_traits {};
  80. template <typename T>
  81. struct polygon_traits<T,
  82. typename gtl_or_4<
  83. typename gtl_same_type<typename geometry_concept<T>::type, polygon_concept>::type,
  84. typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_concept>::type,
  85. typename gtl_same_type<typename geometry_concept<T>::type, polygon_with_holes_concept>::type,
  86. typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_with_holes_concept>::type
  87. >::type> : public polygon_traits_general<T> {};
  88. template <typename T>
  89. struct polygon_traits< T,
  90. typename gtl_or<
  91. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type,
  92. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type
  93. >::type > : public polygon_traits_90<T> {};
  94. #else
  95. template <typename T, typename T_IF, typename T_ELSE>
  96. struct gtl_ifelse {};
  97. template <typename T_IF, typename T_ELSE>
  98. struct gtl_ifelse<gtl_no, T_IF, T_ELSE> {
  99. typedef T_ELSE type;
  100. };
  101. template <typename T_IF, typename T_ELSE>
  102. struct gtl_ifelse<gtl_yes, T_IF, T_ELSE> {
  103. typedef T_IF type;
  104. };
  105. template <typename T, typename enable = gtl_yes>
  106. struct polygon_traits {};
  107. template <typename T>
  108. struct polygon_traits<T, typename gtl_or<typename gtl_or_4<
  109. typename gtl_same_type<typename geometry_concept<T>::type, polygon_concept>::type,
  110. typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_concept>::type,
  111. typename gtl_same_type<typename geometry_concept<T>::type, polygon_with_holes_concept>::type,
  112. typename gtl_same_type<typename geometry_concept<T>::type, polygon_45_with_holes_concept>::type
  113. >::type, typename gtl_or<
  114. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type,
  115. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type
  116. >::type>::type > : public gtl_ifelse<typename gtl_or<
  117. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_concept>::type,
  118. typename gtl_same_type<typename geometry_concept<T>::type, polygon_90_with_holes_concept>::type >::type,
  119. polygon_traits_90<T>,
  120. polygon_traits_general<T> >::type {
  121. };
  122. #endif
  123. template <typename T, typename enable = void>
  124. struct polygon_with_holes_traits {
  125. typedef typename T::iterator_holes_type iterator_holes_type;
  126. typedef typename T::hole_type hole_type;
  127. // Get the begin iterator
  128. static inline iterator_holes_type begin_holes(const T& t) {
  129. return t.begin_holes();
  130. }
  131. // Get the end iterator
  132. static inline iterator_holes_type end_holes(const T& t) {
  133. return t.end_holes();
  134. }
  135. // Get the number of holes
  136. static inline std::size_t size_holes(const T& t) {
  137. return t.size_holes();
  138. }
  139. };
  140. template <typename T, typename enable = void>
  141. struct polygon_90_mutable_traits {
  142. // Set the data of a polygon with the unique coordinates in an iterator, starting with an x
  143. template <typename iT>
  144. static inline T& set_compact(T& t, iT input_begin, iT input_end) {
  145. t.set_compact(input_begin, input_end);
  146. return t;
  147. }
  148. };
  149. template <typename T, typename enable = void>
  150. struct polygon_mutable_traits {
  151. // Set the data of a polygon with the unique coordinates in an iterator, starting with an x
  152. template <typename iT>
  153. static inline T& set_points(T& t, iT input_begin, iT input_end) {
  154. t.set(input_begin, input_end);
  155. return t;
  156. }
  157. };
  158. template <typename T, typename enable = void>
  159. struct polygon_with_holes_mutable_traits {
  160. // Set the data of a polygon with the unique coordinates in an iterator, starting with an x
  161. template <typename iT>
  162. static inline T& set_holes(T& t, iT inputBegin, iT inputEnd) {
  163. t.set_holes(inputBegin, inputEnd);
  164. return t;
  165. }
  166. };
  167. }
  168. }
  169. #include "isotropy.hpp"
  170. //point
  171. #include "point_data.hpp"
  172. #include "point_traits.hpp"
  173. #include "point_concept.hpp"
  174. //interval
  175. #include "interval_data.hpp"
  176. #include "interval_traits.hpp"
  177. #include "interval_concept.hpp"
  178. //rectangle
  179. #include "rectangle_data.hpp"
  180. #include "rectangle_traits.hpp"
  181. #include "rectangle_concept.hpp"
  182. //algorithms needed by polygon types
  183. #include "detail/iterator_points_to_compact.hpp"
  184. #include "detail/iterator_compact_to_points.hpp"
  185. //polygons
  186. #include "polygon_45_data.hpp"
  187. #include "polygon_data.hpp"
  188. #include "polygon_90_data.hpp"
  189. #include "polygon_90_with_holes_data.hpp"
  190. #include "polygon_45_with_holes_data.hpp"
  191. #include "polygon_with_holes_data.hpp"
  192. namespace boost { namespace polygon{
  193. struct polygon_concept {};
  194. struct polygon_with_holes_concept {};
  195. struct polygon_45_concept {};
  196. struct polygon_45_with_holes_concept {};
  197. struct polygon_90_concept {};
  198. struct polygon_90_with_holes_concept {};
  199. template <typename T>
  200. struct is_polygon_90_type {
  201. typedef typename geometry_concept<T>::type GC;
  202. typedef typename gtl_same_type<polygon_90_concept, GC>::type type;
  203. };
  204. template <typename T>
  205. struct is_polygon_45_type {
  206. typedef typename geometry_concept<T>::type GC;
  207. typedef typename gtl_or<typename is_polygon_90_type<T>::type,
  208. typename gtl_same_type<polygon_45_concept, GC>::type>::type type;
  209. };
  210. template <typename T>
  211. struct is_polygon_type {
  212. typedef typename geometry_concept<T>::type GC;
  213. typedef typename gtl_or<typename is_polygon_45_type<T>::type,
  214. typename gtl_same_type<polygon_concept, GC>::type>::type type;
  215. };
  216. template <typename T>
  217. struct is_polygon_90_with_holes_type {
  218. typedef typename geometry_concept<T>::type GC;
  219. typedef typename gtl_or<typename is_polygon_90_type<T>::type,
  220. typename gtl_same_type<polygon_90_with_holes_concept, GC>::type>::type type;
  221. };
  222. template <typename T>
  223. struct is_polygon_45_with_holes_type {
  224. typedef typename geometry_concept<T>::type GC;
  225. typedef typename gtl_or_3<typename is_polygon_90_with_holes_type<T>::type,
  226. typename is_polygon_45_type<T>::type,
  227. typename gtl_same_type<polygon_45_with_holes_concept, GC>::type>::type type;
  228. };
  229. template <typename T>
  230. struct is_polygon_with_holes_type {
  231. typedef typename geometry_concept<T>::type GC;
  232. typedef typename gtl_or_3<typename is_polygon_45_with_holes_type<T>::type,
  233. typename is_polygon_type<T>::type,
  234. typename gtl_same_type<polygon_with_holes_concept, GC>::type>::type type;
  235. };
  236. template <typename T>
  237. struct is_mutable_polygon_90_type {
  238. typedef typename geometry_concept<T>::type GC;
  239. typedef typename gtl_same_type<polygon_90_concept, GC>::type type;
  240. };
  241. template <typename T>
  242. struct is_mutable_polygon_45_type {
  243. typedef typename geometry_concept<T>::type GC;
  244. typedef typename gtl_same_type<polygon_45_concept, GC>::type type;
  245. };
  246. template <typename T>
  247. struct is_mutable_polygon_type {
  248. typedef typename geometry_concept<T>::type GC;
  249. typedef typename gtl_same_type<polygon_concept, GC>::type type;
  250. };
  251. template <typename T>
  252. struct is_mutable_polygon_90_with_holes_type {
  253. typedef typename geometry_concept<T>::type GC;
  254. typedef typename gtl_same_type<polygon_90_with_holes_concept, GC>::type type;
  255. };
  256. template <typename T>
  257. struct is_mutable_polygon_45_with_holes_type {
  258. typedef typename geometry_concept<T>::type GC;
  259. typedef typename gtl_same_type<polygon_45_with_holes_concept, GC>::type type;
  260. };
  261. template <typename T>
  262. struct is_mutable_polygon_with_holes_type {
  263. typedef typename geometry_concept<T>::type GC;
  264. typedef typename gtl_same_type<polygon_with_holes_concept, GC>::type type;
  265. };
  266. template <typename T>
  267. struct is_any_mutable_polygon_with_holes_type {
  268. typedef typename gtl_or_3<typename is_mutable_polygon_90_with_holes_type<T>::type,
  269. typename is_mutable_polygon_45_with_holes_type<T>::type,
  270. typename is_mutable_polygon_with_holes_type<T>::type>::type type;
  271. };
  272. template <typename T>
  273. struct is_any_mutable_polygon_without_holes_type {
  274. typedef typename gtl_or_3<
  275. typename is_mutable_polygon_90_type<T>::type,
  276. typename is_mutable_polygon_45_type<T>::type,
  277. typename is_mutable_polygon_type<T>::type>::type type; };
  278. template <typename T>
  279. struct is_any_mutable_polygon_type {
  280. typedef typename gtl_or<typename is_any_mutable_polygon_with_holes_type<T>::type,
  281. typename is_any_mutable_polygon_without_holes_type<T>::type>::type type;
  282. };
  283. template <typename T>
  284. struct polygon_from_polygon_with_holes_type {};
  285. template <>
  286. struct polygon_from_polygon_with_holes_type<polygon_with_holes_concept> { typedef polygon_concept type; };
  287. template <>
  288. struct polygon_from_polygon_with_holes_type<polygon_45_with_holes_concept> { typedef polygon_45_concept type; };
  289. template <>
  290. struct polygon_from_polygon_with_holes_type<polygon_90_with_holes_concept> { typedef polygon_90_concept type; };
  291. template <>
  292. struct geometry_domain<polygon_45_concept> { typedef forty_five_domain type; };
  293. template <>
  294. struct geometry_domain<polygon_45_with_holes_concept> { typedef forty_five_domain type; };
  295. template <>
  296. struct geometry_domain<polygon_90_concept> { typedef manhattan_domain type; };
  297. template <>
  298. struct geometry_domain<polygon_90_with_holes_concept> { typedef manhattan_domain type; };
  299. template <typename domain_type, typename coordinate_type>
  300. struct distance_type_by_domain { typedef typename coordinate_traits<coordinate_type>::coordinate_distance type; };
  301. template <typename coordinate_type>
  302. struct distance_type_by_domain<manhattan_domain, coordinate_type> {
  303. typedef typename coordinate_traits<coordinate_type>::coordinate_difference type; };
  304. // \brief Sets the boundary of the polygon to the points in the iterator range
  305. // \tparam T A type that models polygon_concept
  306. // \tparam iT Iterator type over objects that model point_concept
  307. // \param t The polygon to set
  308. // \param begin_points The start of the range of points
  309. // \param end_points The end of the range of points
  310. /// \relatesalso polygon_concept
  311. template <typename T, typename iT>
  312. typename enable_if <typename is_any_mutable_polygon_type<T>::type, T>::type &
  313. set_points(T& t, iT begin_points, iT end_points) {
  314. polygon_mutable_traits<T>::set_points(t, begin_points, end_points);
  315. return t;
  316. }
  317. // \brief Sets the boundary of the polygon to the non-redundant coordinates in the iterator range
  318. // \tparam T A type that models polygon_90_concept
  319. // \tparam iT Iterator type over objects that model coordinate_concept
  320. // \param t The polygon to set
  321. // \param begin_compact_coordinates The start of the range of coordinates
  322. // \param end_compact_coordinates The end of the range of coordinates
  323. /// \relatesalso polygon_90_concept
  324. template <typename T, typename iT>
  325. typename enable_if <typename gtl_or<
  326. typename is_mutable_polygon_90_type<T>::type,
  327. typename is_mutable_polygon_90_with_holes_type<T>::type>::type, T>::type &
  328. set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) {
  329. polygon_90_mutable_traits<T>::set_compact(t, begin_compact_coordinates, end_compact_coordinates);
  330. return t;
  331. }
  332. /// \relatesalso polygon_with_holes_concept
  333. template <typename T, typename iT>
  334. typename enable_if< typename gtl_and <
  335. typename is_any_mutable_polygon_with_holes_type<T>::type,
  336. typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type,
  337. manhattan_domain>::type>::type,
  338. T>::type &
  339. set_compact(T& t, iT begin_compact_coordinates, iT end_compact_coordinates) {
  340. iterator_compact_to_points<iT, point_data<typename polygon_traits<T>::coordinate_type> >
  341. itrb(begin_compact_coordinates, end_compact_coordinates),
  342. itre(end_compact_coordinates, end_compact_coordinates);
  343. return set_points(t, itrb, itre);
  344. }
  345. /// \relatesalso polygon_with_holes_concept
  346. template <typename T, typename iT>
  347. typename enable_if <typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type &
  348. set_holes(T& t, iT begin_holes, iT end_holes) {
  349. polygon_with_holes_mutable_traits<T>::set_holes(t, begin_holes, end_holes);
  350. return t;
  351. }
  352. /// \relatesalso polygon_90_concept
  353. template <typename T>
  354. typename polygon_90_traits<T>::compact_iterator_type
  355. begin_compact(const T& polygon,
  356. typename enable_if<
  357. typename gtl_and <typename is_polygon_with_holes_type<T>::type,
  358. typename gtl_same_type<typename geometry_domain<typename geometry_concept<T>::type>::type,
  359. manhattan_domain>::type>::type>::type * = 0
  360. ) {
  361. return polygon_90_traits<T>::begin_compact(polygon);
  362. }
  363. /// \relatesalso polygon_90_concept
  364. template <typename T>
  365. typename polygon_90_traits<T>::compact_iterator_type
  366. end_compact(const T& polygon,
  367. typename enable_if<
  368. typename gtl_and <typename is_polygon_with_holes_type<T>::type,
  369. typename gtl_same_type<typename geometry_domain<typename geometry_concept<T>::type>::type,
  370. manhattan_domain>::type>::type>::type * = 0
  371. ) {
  372. return polygon_90_traits<T>::end_compact(polygon);
  373. }
  374. /// \relatesalso polygon_concept
  375. template <typename T>
  376. typename enable_if < typename gtl_if<
  377. typename is_polygon_with_holes_type<T>::type>::type,
  378. typename polygon_traits<T>::iterator_type>::type
  379. begin_points(const T& polygon) {
  380. return polygon_traits<T>::begin_points(polygon);
  381. }
  382. /// \relatesalso polygon_concept
  383. template <typename T>
  384. typename enable_if < typename gtl_if<
  385. typename is_polygon_with_holes_type<T>::type>::type,
  386. typename polygon_traits<T>::iterator_type>::type
  387. end_points(const T& polygon) {
  388. return polygon_traits<T>::end_points(polygon);
  389. }
  390. /// \relatesalso polygon_concept
  391. template <typename T>
  392. typename enable_if <typename is_polygon_with_holes_type<T>::type,
  393. std::size_t>::type
  394. size(const T& polygon) {
  395. return polygon_traits<T>::size(polygon);
  396. }
  397. /// \relatesalso polygon_with_holes_concept
  398. template <typename T>
  399. typename enable_if < typename gtl_if<
  400. typename is_polygon_with_holes_type<T>::type>::type,
  401. typename polygon_with_holes_traits<T>::iterator_holes_type>::type
  402. begin_holes(const T& polygon) {
  403. return polygon_with_holes_traits<T>::begin_holes(polygon);
  404. }
  405. /// \relatesalso polygon_with_holes_concept
  406. template <typename T>
  407. typename enable_if < typename gtl_if<
  408. typename is_polygon_with_holes_type<T>::type>::type,
  409. typename polygon_with_holes_traits<T>::iterator_holes_type>::type
  410. end_holes(const T& polygon) {
  411. return polygon_with_holes_traits<T>::end_holes(polygon);
  412. }
  413. /// \relatesalso polygon_with_holes_concept
  414. template <typename T>
  415. typename enable_if <typename is_polygon_with_holes_type<T>::type,
  416. std::size_t>::type
  417. size_holes(const T& polygon) {
  418. return polygon_with_holes_traits<T>::size_holes(polygon);
  419. }
  420. // \relatesalso polygon_concept
  421. template <typename T1, typename T2>
  422. typename enable_if<
  423. typename gtl_and< typename is_mutable_polygon_type<T1>::type,
  424. typename is_polygon_type<T2>::type>::type, T1>::type &
  425. assign(T1& lvalue, const T2& rvalue) {
  426. polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue),
  427. polygon_traits<T2>::end_points(rvalue));
  428. return lvalue;
  429. }
  430. // \relatesalso polygon_with_holes_concept
  431. template <typename T1, typename T2>
  432. typename enable_if<
  433. typename gtl_and< typename is_mutable_polygon_with_holes_type<T1>::type,
  434. typename is_polygon_with_holes_type<T2>::type>::type, T1>::type &
  435. assign(T1& lvalue, const T2& rvalue) {
  436. polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue),
  437. polygon_traits<T2>::end_points(rvalue));
  438. polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue),
  439. polygon_with_holes_traits<T2>::end_holes(rvalue));
  440. return lvalue;
  441. }
  442. // \relatesalso polygon_45_concept
  443. template <typename T1, typename T2>
  444. typename enable_if< typename gtl_and< typename is_mutable_polygon_45_type<T1>::type, typename is_polygon_45_type<T2>::type>::type, T1>::type &
  445. assign(T1& lvalue, const T2& rvalue) {
  446. polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue),
  447. polygon_traits<T2>::end_points(rvalue));
  448. return lvalue;
  449. }
  450. // \relatesalso polygon_45_with_holes_concept
  451. template <typename T1, typename T2>
  452. typename enable_if<
  453. typename gtl_and< typename is_mutable_polygon_45_with_holes_type<T1>::type,
  454. typename is_polygon_45_with_holes_type<T2>::type>::type, T1>::type &
  455. assign(T1& lvalue, const T2& rvalue) {
  456. polygon_mutable_traits<T1>::set_points(lvalue, polygon_traits<T2>::begin_points(rvalue),
  457. polygon_traits<T2>::end_points(rvalue));
  458. polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue),
  459. polygon_with_holes_traits<T2>::end_holes(rvalue));
  460. return lvalue;
  461. }
  462. // \relatesalso polygon_90_concept
  463. template <typename T1, typename T2>
  464. typename enable_if<
  465. typename gtl_and< typename is_mutable_polygon_90_type<T1>::type,
  466. typename is_polygon_90_type<T2>::type>::type, T1>::type &
  467. assign(T1& lvalue, const T2& rvalue) {
  468. polygon_90_mutable_traits<T1>::set_compact(lvalue, polygon_90_traits<T2>::begin_compact(rvalue),
  469. polygon_90_traits<T2>::end_compact(rvalue));
  470. return lvalue;
  471. }
  472. // \relatesalso polygon_90_with_holes_concept
  473. template <typename T1, typename T2>
  474. typename enable_if<
  475. typename gtl_and< typename is_mutable_polygon_90_with_holes_type<T1>::type,
  476. typename is_polygon_90_with_holes_type<T2>::type>::type, T1>::type &
  477. assign(T1& lvalue, const T2& rvalue) {
  478. polygon_90_mutable_traits<T1>::set_compact(lvalue, polygon_90_traits<T2>::begin_compact(rvalue),
  479. polygon_90_traits<T2>::end_compact(rvalue));
  480. polygon_with_holes_mutable_traits<T1>::set_holes(lvalue, polygon_with_holes_traits<T2>::begin_holes(rvalue),
  481. polygon_with_holes_traits<T2>::end_holes(rvalue));
  482. return lvalue;
  483. }
  484. // \relatesalso polygon_90_concept
  485. template <typename T1, typename T2>
  486. typename enable_if<
  487. typename gtl_and< typename is_any_mutable_polygon_type<T1>::type,
  488. typename is_rectangle_concept<typename geometry_concept<T2>::type>::type>::type, T1>::type &
  489. assign(T1& polygon, const T2& rect) {
  490. typedef point_data<typename polygon_traits<T1>::coordinate_type> PT;
  491. PT points[4] = {PT(xl(rect), yl(rect)), PT(xh(rect), yl(rect)), PT(xh(rect), yh(rect)), PT(xl(rect), yh(rect))};
  492. set_points(polygon, points, points+4);
  493. return polygon;
  494. }
  495. /// \relatesalso polygon_90_concept
  496. template <typename polygon_type, typename point_type>
  497. typename enable_if< typename gtl_and< typename is_mutable_polygon_90_type<polygon_type>::type,
  498. typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
  499. polygon_type>::type &
  500. convolve(polygon_type& polygon, const point_type& point) {
  501. std::vector<typename polygon_90_traits<polygon_type>::coordinate_type> coords;
  502. coords.reserve(::boost::polygon::size(polygon));
  503. bool pingpong = true;
  504. for(typename polygon_90_traits<polygon_type>::compact_iterator_type iter = begin_compact(polygon);
  505. iter != end_compact(polygon); ++iter) {
  506. coords.push_back((*iter) + (pingpong ? x(point) : y(point)));
  507. pingpong = !pingpong;
  508. }
  509. polygon_90_mutable_traits<polygon_type>::set_compact(polygon, coords.begin(), coords.end());
  510. return polygon;
  511. }
  512. /// \relatesalso polygon_concept
  513. template <typename polygon_type, typename point_type>
  514. typename enable_if< typename gtl_and< typename gtl_or<
  515. typename is_mutable_polygon_45_type<polygon_type>::type,
  516. typename is_mutable_polygon_type<polygon_type>::type>::type,
  517. typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
  518. polygon_type>::type &
  519. convolve(polygon_type& polygon, const point_type& point) {
  520. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  521. points.reserve(::boost::polygon::size(polygon));
  522. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  523. iter != end_points(polygon); ++iter) {
  524. points.push_back(*iter);
  525. convolve(points.back(), point);
  526. }
  527. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  528. return polygon;
  529. }
  530. /// \relatesalso polygon_with_holes_concept
  531. template <typename polygon_type, typename point_type>
  532. typename enable_if<
  533. typename gtl_and< typename is_any_mutable_polygon_with_holes_type<polygon_type>::type,
  534. typename is_point_concept<typename geometry_concept<point_type>::type>::type>::type,
  535. polygon_type>::type &
  536. convolve(polygon_type& polygon, const point_type& point) {
  537. typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type;
  538. hole_type h;
  539. set_points(h, begin_points(polygon), end_points(polygon));
  540. convolve(h, point);
  541. std::vector<hole_type> holes;
  542. holes.reserve(size_holes(polygon));
  543. for(typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itr = begin_holes(polygon);
  544. itr != end_holes(polygon); ++itr) {
  545. holes.push_back(*itr);
  546. convolve(holes.back(), point);
  547. }
  548. assign(polygon, h);
  549. set_holes(polygon, holes.begin(), holes.end());
  550. return polygon;
  551. }
  552. /// \relatesalso polygon_concept
  553. template <typename T>
  554. typename enable_if< typename is_any_mutable_polygon_type<T>::type, T>::type &
  555. move(T& polygon, orientation_2d orient, typename polygon_traits<T>::coordinate_type displacement) {
  556. typedef typename polygon_traits<T>::coordinate_type Unit;
  557. if(orient == HORIZONTAL) return convolve(polygon, point_data<Unit>(displacement, Unit(0)));
  558. return convolve(polygon, point_data<Unit>(Unit(0), displacement));
  559. }
  560. /// \relatesalso polygon_concept
  561. /// \brief Applies a transformation to the polygon.
  562. /// \tparam polygon_type A type that models polygon_concept
  563. /// \tparam transform_type A type that may be either axis_transformation or transformation or that overloads point_concept::transform
  564. /// \param polygon The polygon to transform
  565. /// \param tr The transformation to apply
  566. template <typename polygon_type, typename transform_type>
  567. typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type &
  568. transform(polygon_type& polygon, const transform_type& tr) {
  569. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  570. points.reserve(::boost::polygon::size(polygon));
  571. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  572. iter != end_points(polygon); ++iter) {
  573. points.push_back(*iter);
  574. transform(points.back(), tr);
  575. }
  576. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  577. return polygon;
  578. }
  579. /// \relatesalso polygon_with_holes_concept
  580. template <typename T, typename transform_type>
  581. typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type &
  582. transform(T& polygon, const transform_type& tr) {
  583. typedef typename polygon_with_holes_traits<T>::hole_type hole_type;
  584. hole_type h;
  585. set_points(h, begin_points(polygon), end_points(polygon));
  586. transform(h, tr);
  587. std::vector<hole_type> holes;
  588. holes.reserve(size_holes(polygon));
  589. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon);
  590. itr != end_holes(polygon); ++itr) {
  591. holes.push_back(*itr);
  592. transform(holes.back(), tr);
  593. }
  594. assign(polygon, h);
  595. set_holes(polygon, holes.begin(), holes.end());
  596. return polygon;
  597. }
  598. template <typename polygon_type>
  599. typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type &
  600. scale_up(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) {
  601. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  602. points.reserve(::boost::polygon::size(polygon));
  603. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  604. iter != end_points(polygon); ++iter) {
  605. points.push_back(*iter);
  606. scale_up(points.back(), factor);
  607. }
  608. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  609. return polygon;
  610. }
  611. template <typename T>
  612. typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type &
  613. scale_up(T& polygon, typename coordinate_traits<typename polygon_traits<T>::coordinate_type>::unsigned_area_type factor) {
  614. typedef typename polygon_with_holes_traits<T>::hole_type hole_type;
  615. hole_type h;
  616. set_points(h, begin_points(polygon), end_points(polygon));
  617. scale_up(h, factor);
  618. std::vector<hole_type> holes;
  619. holes.reserve(size_holes(polygon));
  620. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon);
  621. itr != end_holes(polygon); ++itr) {
  622. holes.push_back(*itr);
  623. scale_up(holes.back(), factor);
  624. }
  625. assign(polygon, h);
  626. set_holes(polygon, holes.begin(), holes.end());
  627. return polygon;
  628. }
  629. //scale non-45 down
  630. template <typename polygon_type>
  631. typename enable_if<
  632. typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type,
  633. typename gtl_not<typename gtl_same_type
  634. < forty_five_domain,
  635. typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type,
  636. polygon_type>::type &
  637. scale_down(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) {
  638. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  639. points.reserve(::boost::polygon::size(polygon));
  640. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  641. iter != end_points(polygon); ++iter) {
  642. points.push_back(*iter);
  643. scale_down(points.back(), factor);
  644. }
  645. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  646. return polygon;
  647. }
  648. template <typename Unit>
  649. Unit local_abs(Unit value) { return value < 0 ? (Unit)-value : value; }
  650. template <typename Unit>
  651. void snap_point_vector_to_45(std::vector<point_data<Unit> >& pts) {
  652. typedef point_data<Unit> Point;
  653. if(pts.size() < 3) { pts.clear(); return; }
  654. typename std::vector<point_data<Unit> >::iterator endLocation = std::unique(pts.begin(), pts.end());
  655. if(endLocation != pts.end()){
  656. pts.resize(endLocation - pts.begin());
  657. }
  658. if(pts.back() == pts[0]) pts.pop_back();
  659. //iterate over point triplets
  660. int numPts = pts.size();
  661. bool wrap_around = false;
  662. for(int i = 0; i < numPts; ++i) {
  663. Point& pt1 = pts[i];
  664. Point& pt2 = pts[(i + 1) % numPts];
  665. Point& pt3 = pts[(i + 2) % numPts];
  666. //check if non-45 edge
  667. Unit deltax = x(pt2) - x(pt1);
  668. Unit deltay = y(pt2) - y(pt1);
  669. if(deltax && deltay &&
  670. local_abs(deltax) != local_abs(deltay)) {
  671. //adjust the middle point
  672. Unit ndx = x(pt3) - x(pt2);
  673. Unit ndy = y(pt3) - y(pt2);
  674. if(ndx && ndy) {
  675. Unit diff = local_abs(local_abs(deltax) - local_abs(deltay));
  676. Unit halfdiff = diff/2;
  677. if((deltax > 0 && deltay > 0) ||
  678. (deltax < 0 && deltay < 0)) {
  679. //previous edge is rising slope
  680. if(local_abs(deltax + halfdiff + (diff % 2)) ==
  681. local_abs(deltay - halfdiff)) {
  682. x(pt2, x(pt2) + halfdiff + (diff % 2));
  683. y(pt2, y(pt2) - halfdiff);
  684. } else if(local_abs(deltax - halfdiff - (diff % 2)) ==
  685. local_abs(deltay + halfdiff)) {
  686. x(pt2, x(pt2) - halfdiff - (diff % 2));
  687. y(pt2, y(pt2) + halfdiff);
  688. } else{
  689. //std::cout << "fail1\n";
  690. }
  691. } else {
  692. //previous edge is falling slope
  693. if(local_abs(deltax + halfdiff + (diff % 2)) ==
  694. local_abs(deltay + halfdiff)) {
  695. x(pt2, x(pt2) + halfdiff + (diff % 2));
  696. y(pt2, y(pt2) + halfdiff);
  697. } else if(local_abs(deltax - halfdiff - (diff % 2)) ==
  698. local_abs(deltay - halfdiff)) {
  699. x(pt2, x(pt2) - halfdiff - (diff % 2));
  700. y(pt2, y(pt2) - halfdiff);
  701. } else {
  702. //std::cout << "fail2\n";
  703. }
  704. }
  705. if(i == numPts - 1 && (diff % 2)) {
  706. //we have a wrap around effect
  707. if(!wrap_around) {
  708. wrap_around = true;
  709. i = -1;
  710. }
  711. }
  712. } else if(ndx) {
  713. //next edge is horizontal
  714. //find the x value for pt1 that would make the abs(deltax) == abs(deltay)
  715. Unit newDeltaX = local_abs(deltay);
  716. if(deltax < 0) newDeltaX *= -1;
  717. x(pt2, x(pt1) + newDeltaX);
  718. } else { //ndy
  719. //next edge is vertical
  720. //find the y value for pt1 that would make the abs(deltax) == abs(deltay)
  721. Unit newDeltaY = local_abs(deltax);
  722. if(deltay < 0) newDeltaY *= -1;
  723. y(pt2, y(pt1) + newDeltaY);
  724. }
  725. }
  726. }
  727. }
  728. template <typename polygon_type>
  729. typename enable_if< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type, polygon_type>::type &
  730. snap_to_45(polygon_type& polygon) {
  731. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  732. points.reserve(::boost::polygon::size(polygon));
  733. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  734. iter != end_points(polygon); ++iter) {
  735. points.push_back(*iter);
  736. }
  737. snap_point_vector_to_45(points);
  738. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  739. return polygon;
  740. }
  741. template <typename polygon_type>
  742. typename enable_if< typename is_any_mutable_polygon_with_holes_type<polygon_type>::type, polygon_type>::type &
  743. snap_to_45(polygon_type& polygon) {
  744. typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type;
  745. hole_type h;
  746. set_points(h, begin_points(polygon), end_points(polygon));
  747. snap_to_45(h);
  748. std::vector<hole_type> holes;
  749. holes.reserve(size_holes(polygon));
  750. for(typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itr = begin_holes(polygon);
  751. itr != end_holes(polygon); ++itr) {
  752. holes.push_back(*itr);
  753. snap_to_45(holes.back());
  754. }
  755. assign(polygon, h);
  756. set_holes(polygon, holes.begin(), holes.end());
  757. return polygon;
  758. }
  759. //scale specifically 45 down
  760. template <typename polygon_type>
  761. typename enable_if<
  762. typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type,
  763. typename gtl_same_type
  764. < forty_five_domain,
  765. typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type,
  766. polygon_type>::type &
  767. scale_down(polygon_type& polygon, typename coordinate_traits<typename polygon_traits<polygon_type>::coordinate_type>::unsigned_area_type factor) {
  768. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  769. points.reserve(::boost::polygon::size(polygon));
  770. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  771. iter != end_points(polygon); ++iter) {
  772. points.push_back(*iter);
  773. scale_down(points.back(), factor);
  774. }
  775. snap_point_vector_to_45(points);
  776. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  777. return polygon;
  778. }
  779. template <typename T>
  780. typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type, T>::type &
  781. scale_down(T& polygon, typename coordinate_traits<typename polygon_traits<T>::coordinate_type>::unsigned_area_type factor) {
  782. typedef typename polygon_with_holes_traits<T>::hole_type hole_type;
  783. hole_type h;
  784. set_points(h, begin_points(polygon), end_points(polygon));
  785. scale_down(h, factor);
  786. std::vector<hole_type> holes;
  787. holes.reserve(size_holes(polygon));
  788. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon);
  789. itr != end_holes(polygon); ++itr) {
  790. holes.push_back(*itr);
  791. scale_down(holes.back(), factor);
  792. }
  793. assign(polygon, h);
  794. set_holes(polygon, holes.begin(), holes.end());
  795. return polygon;
  796. }
  797. //scale non-45
  798. template <typename polygon_type>
  799. typename enable_if<
  800. typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type,
  801. typename gtl_not<typename gtl_same_type
  802. < forty_five_domain,
  803. typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type,
  804. polygon_type>::type &
  805. scale(polygon_type& polygon, double factor) {
  806. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  807. points.reserve(::boost::polygon::size(polygon));
  808. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  809. iter != end_points(polygon); ++iter) {
  810. points.push_back(*iter);
  811. scale(points.back(), anisotropic_scale_factor<double>(factor, factor));
  812. }
  813. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  814. return polygon;
  815. }
  816. //scale specifically 45
  817. template <typename polygon_type>
  818. polygon_type&
  819. scale(polygon_type& polygon, double factor,
  820. typename enable_if<
  821. typename gtl_and< typename is_any_mutable_polygon_without_holes_type<polygon_type>::type,
  822. typename gtl_same_type
  823. < forty_five_domain,
  824. typename geometry_domain<typename geometry_concept<polygon_type>::type>::type>::type>::type>::type * = 0
  825. ) {
  826. std::vector<typename std::iterator_traits<typename polygon_traits<polygon_type>::iterator_type>::value_type> points;
  827. points.reserve(::boost::polygon::size(polygon));
  828. for(typename polygon_traits<polygon_type>::iterator_type iter = begin_points(polygon);
  829. iter != end_points(polygon); ++iter) {
  830. points.push_back(*iter);
  831. scale(points.back(), anisotropic_scale_factor<double>(factor, factor));
  832. }
  833. snap_point_vector_to_45(points);
  834. polygon_mutable_traits<polygon_type>::set_points(polygon, points.begin(), points.end());
  835. return polygon;
  836. }
  837. template <typename T>
  838. T&
  839. scale(T& polygon, double factor,
  840. typename enable_if< typename is_any_mutable_polygon_with_holes_type<T>::type>::type * = 0
  841. ) {
  842. typedef typename polygon_with_holes_traits<T>::hole_type hole_type;
  843. hole_type h;
  844. set_points(h, begin_points(polygon), end_points(polygon));
  845. scale(h, factor);
  846. std::vector<hole_type> holes;
  847. holes.reserve(size_holes(polygon));
  848. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr = begin_holes(polygon);
  849. itr != end_holes(polygon); ++itr) {
  850. holes.push_back(*itr);
  851. scale(holes.back(), factor);
  852. }
  853. assign(polygon, h);
  854. set_holes(polygon, holes.begin(), holes.end());
  855. return polygon;
  856. }
  857. template <typename iterator_type, typename area_type>
  858. static area_type
  859. point_sequence_area(iterator_type begin_range, iterator_type end_range) {
  860. typedef typename std::iterator_traits<iterator_type>::value_type point_type;
  861. if(begin_range == end_range) return area_type(0);
  862. point_type first = *begin_range;
  863. point_type previous = first;
  864. ++begin_range;
  865. // Initialize trapezoid base line
  866. area_type y_base = (area_type)y(first);
  867. // Initialize area accumulator
  868. area_type area(0);
  869. while (begin_range != end_range) {
  870. area_type x1 = (area_type)x(previous);
  871. area_type x2 = (area_type)x(*begin_range);
  872. #ifdef BOOST_POLYGON_ICC
  873. #pragma warning (push)
  874. #pragma warning (disable:1572)
  875. #endif
  876. if(x1 != x2) {
  877. #ifdef BOOST_POLYGON_ICC
  878. #pragma warning (pop)
  879. #endif
  880. // do trapezoid area accumulation
  881. area += (x2 - x1) * (((area_type)y(*begin_range) - y_base) +
  882. ((area_type)y(previous) - y_base)) / 2;
  883. }
  884. previous = *begin_range;
  885. // go to next point
  886. ++begin_range;
  887. }
  888. //wrap around to evaluate the edge between first and last if not closed
  889. if(!equivalence(first, previous)) {
  890. area_type x1 = (area_type)x(previous);
  891. area_type x2 = (area_type)x(first);
  892. area += (x2 - x1) * (((area_type)y(first) - y_base) +
  893. ((area_type)y(previous) - y_base)) / 2;
  894. }
  895. return area;
  896. }
  897. template <typename T>
  898. typename enable_if<
  899. typename is_polygon_with_holes_type<T>::type,
  900. typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type,
  901. typename polygon_traits<T>::coordinate_type>::type>::type
  902. area(const T& polygon) {
  903. typedef typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type,
  904. typename polygon_traits<T>::coordinate_type>::type area_type;
  905. area_type retval = point_sequence_area<typename polygon_traits<T>::iterator_type, area_type>
  906. (begin_points(polygon), end_points(polygon));
  907. if(retval < 0) retval *= -1;
  908. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr =
  909. polygon_with_holes_traits<T>::begin_holes(polygon);
  910. itr != polygon_with_holes_traits<T>::end_holes(polygon); ++itr) {
  911. area_type tmp_area = point_sequence_area
  912. <typename polygon_traits<typename polygon_with_holes_traits<T>::hole_type>::iterator_type, area_type>
  913. (begin_points(*itr), end_points(*itr));
  914. if(tmp_area < 0) tmp_area *= -1;
  915. retval -= tmp_area;
  916. }
  917. return retval;
  918. }
  919. template <typename iT>
  920. bool point_sequence_is_45(iT itr, iT itr_end) {
  921. typedef typename std::iterator_traits<iT>::value_type Point;
  922. typedef typename point_traits<Point>::coordinate_type Unit;
  923. if(itr == itr_end) return true;
  924. Point firstPt = *itr;
  925. Point prevPt = firstPt;
  926. ++itr;
  927. while(itr != itr_end) {
  928. Point pt = *itr;
  929. Unit deltax = x(pt) - x(prevPt);
  930. Unit deltay = y(pt) - y(prevPt);
  931. if(deltax && deltay &&
  932. local_abs(deltax) != local_abs(deltay))
  933. return false;
  934. prevPt = pt;
  935. ++itr;
  936. }
  937. Unit deltax = x(firstPt) - x(prevPt);
  938. Unit deltay = y(firstPt) - y(prevPt);
  939. if(deltax && deltay &&
  940. local_abs(deltax) != local_abs(deltay))
  941. return false;
  942. return true;
  943. }
  944. template <typename polygon_type>
  945. typename enable_if< typename is_polygon_with_holes_type<polygon_type>::type, bool>::type
  946. is_45(const polygon_type& polygon) {
  947. typename polygon_traits<polygon_type>::iterator_type itr = begin_points(polygon), itr_end = end_points(polygon);
  948. if(!point_sequence_is_45(itr, itr_end)) return false;
  949. typename polygon_with_holes_traits<polygon_type>::iterator_holes_type itrh = begin_holes(polygon), itrh_end = end_holes(polygon);
  950. typedef typename polygon_with_holes_traits<polygon_type>::hole_type hole_type;
  951. for(; itrh != itrh_end; ++ itrh) {
  952. typename polygon_traits<hole_type>::iterator_type itr1 = begin_points(polygon), itr1_end = end_points(polygon);
  953. if(!point_sequence_is_45(itr1, itr1_end)) return false;
  954. }
  955. return true;
  956. }
  957. template <typename distance_type, typename iterator_type>
  958. distance_type point_sequence_distance(iterator_type itr, iterator_type itr_end) {
  959. typedef distance_type Unit;
  960. typedef iterator_type iterator;
  961. typedef typename std::iterator_traits<iterator>::value_type point_type;
  962. Unit return_value = Unit(0);
  963. point_type previous_point, first_point;
  964. if(itr == itr_end) return return_value;
  965. previous_point = first_point = *itr;
  966. ++itr;
  967. for( ; itr != itr_end; ++itr) {
  968. point_type current_point = *itr;
  969. return_value += (Unit)euclidean_distance(current_point, previous_point);
  970. previous_point = current_point;
  971. }
  972. return_value += (Unit)euclidean_distance(previous_point, first_point);
  973. return return_value;
  974. }
  975. template <typename T>
  976. typename distance_type_by_domain
  977. <typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type
  978. perimeter(const T& polygon,
  979. typename enable_if<
  980. typename is_polygon_with_holes_type<T>::type>::type * = 0
  981. ) {
  982. typedef typename distance_type_by_domain
  983. <typename geometry_domain<typename geometry_concept<T>::type>::type, typename polygon_traits<T>::coordinate_type>::type Unit;
  984. typedef typename polygon_traits<T>::iterator_type iterator;
  985. iterator itr = begin_points(polygon);
  986. iterator itr_end = end_points(polygon);
  987. Unit return_value = point_sequence_distance<Unit, iterator>(itr, itr_end);
  988. for(typename polygon_with_holes_traits<T>::iterator_holes_type itr_holes = begin_holes(polygon);
  989. itr_holes != end_holes(polygon); ++itr_holes) {
  990. typedef typename polygon_traits<typename polygon_with_holes_traits<T>::hole_type>::iterator_type hitertype;
  991. return_value += point_sequence_distance<Unit, hitertype>(begin_points(*itr_holes), end_points(*itr_holes));
  992. }
  993. return return_value;
  994. }
  995. template <typename T>
  996. typename enable_if <typename is_polygon_with_holes_type<T>::type,
  997. direction_1d>::type
  998. winding(const T& polygon) {
  999. winding_direction wd = polygon_traits<T>::winding(polygon);
  1000. if(wd != unknown_winding) {
  1001. return wd == clockwise_winding ? CLOCKWISE: COUNTERCLOCKWISE;
  1002. }
  1003. typedef typename area_type_by_domain< typename geometry_domain<typename geometry_concept<T>::type>::type,
  1004. typename polygon_traits<T>::coordinate_type>::type area_type;
  1005. return point_sequence_area<typename polygon_traits<T>::iterator_type, area_type>(begin_points(polygon), end_points(polygon)) < 0 ?
  1006. COUNTERCLOCKWISE : CLOCKWISE;
  1007. }
  1008. template <typename T, typename input_point_type>
  1009. typename enable_if<
  1010. typename gtl_and<
  1011. typename is_polygon_90_type<T>::type,
  1012. typename gtl_same_type<
  1013. typename geometry_concept<input_point_type>::type,
  1014. point_concept
  1015. >::type
  1016. >::type,
  1017. bool
  1018. >::type contains(
  1019. const T& polygon,
  1020. const input_point_type& point,
  1021. bool consider_touch = true) {
  1022. typedef T polygon_type;
  1023. typedef typename polygon_traits<polygon_type>::coordinate_type coordinate_type;
  1024. typedef typename polygon_traits<polygon_type>::iterator_type iterator;
  1025. typedef typename std::iterator_traits<iterator>::value_type point_type;
  1026. coordinate_type point_x = x(point);
  1027. coordinate_type point_y = y(point);
  1028. // Check how many intersections has the ray extended from the given
  1029. // point in the x-axis negative direction with the polygon edges.
  1030. // If the number is odd the point is within the polygon, otherwise not.
  1031. // We can safely ignore horizontal edges, however intersections with
  1032. // end points of the vertical edges require special handling. We should
  1033. // add one intersection in case horizontal edges that extend vertical edge
  1034. // point in the same direction.
  1035. int num_full_intersections = 0;
  1036. int num_half_intersections = 0;
  1037. for (iterator iter = begin_points(polygon); iter != end_points(polygon);) {
  1038. point_type curr_point = *iter;
  1039. ++iter;
  1040. point_type next_point = (iter == end_points(polygon)) ? *begin_points(polygon) : *iter;
  1041. if (x(curr_point) == x(next_point)) {
  1042. if (x(curr_point) > point_x) {
  1043. continue;
  1044. }
  1045. coordinate_type min_y = (std::min)(y(curr_point), y(next_point));
  1046. coordinate_type max_y = (std::max)(y(curr_point), y(next_point));
  1047. if (point_y > min_y && point_y < max_y) {
  1048. if (x(curr_point) == point_x) {
  1049. return consider_touch;
  1050. }
  1051. ++num_full_intersections;
  1052. }
  1053. if (point_y == min_y || point_y == max_y) {
  1054. num_half_intersections += (y(curr_point) < y(next_point) ? 1 : -1);
  1055. }
  1056. } else {
  1057. coordinate_type min_x = (std::min)(x(curr_point), x(next_point));
  1058. coordinate_type max_x = (std::max)(x(curr_point), x(next_point));
  1059. if (point_x >= min_x && point_x <= max_x) {
  1060. if (y(curr_point) == point_y) {
  1061. return consider_touch;
  1062. }
  1063. }
  1064. }
  1065. }
  1066. int total_intersections = num_full_intersections + (num_half_intersections >> 1);
  1067. return total_intersections & 1;
  1068. }
  1069. //TODO: refactor to expose as user APIs
  1070. template <typename Unit>
  1071. struct edge_utils {
  1072. typedef point_data<Unit> Point;
  1073. typedef std::pair<Point, Point> half_edge;
  1074. class less_point {
  1075. public:
  1076. typedef Point first_argument_type;
  1077. typedef Point second_argument_type;
  1078. typedef bool result_type;
  1079. inline less_point() {}
  1080. inline bool operator () (const Point& pt1, const Point& pt2) const {
  1081. if(pt1.get(HORIZONTAL) < pt2.get(HORIZONTAL)) return true;
  1082. if(pt1.get(HORIZONTAL) == pt2.get(HORIZONTAL)) {
  1083. if(pt1.get(VERTICAL) < pt2.get(VERTICAL)) return true;
  1084. }
  1085. return false;
  1086. }
  1087. };
  1088. static inline bool between(Point pt, Point pt1, Point pt2) {
  1089. less_point lp;
  1090. if(lp(pt1, pt2))
  1091. return lp(pt, pt2) && lp(pt1, pt);
  1092. return lp(pt, pt1) && lp(pt2, pt);
  1093. }
  1094. template <typename area_type>
  1095. static inline bool equal_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) {
  1096. typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type;
  1097. unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1);
  1098. unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2);
  1099. int dx1_sign = dx1 < 0 ? -1 : 1;
  1100. int dx2_sign = dx2 < 0 ? -1 : 1;
  1101. int dy1_sign = dy1 < 0 ? -1 : 1;
  1102. int dy2_sign = dy2 < 0 ? -1 : 1;
  1103. int cross_1_sign = dx2_sign * dy1_sign;
  1104. int cross_2_sign = dx1_sign * dy2_sign;
  1105. return cross_1 == cross_2 && (cross_1_sign == cross_2_sign || cross_1 == 0);
  1106. }
  1107. static inline bool equal_slope(const Unit& x, const Unit& y,
  1108. const Point& pt1, const Point& pt2) {
  1109. const Point* pts[2] = {&pt1, &pt2};
  1110. typedef typename coordinate_traits<Unit>::manhattan_area_type at;
  1111. at dy2 = (at)pts[1]->get(VERTICAL) - (at)y;
  1112. at dy1 = (at)pts[0]->get(VERTICAL) - (at)y;
  1113. at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x;
  1114. at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x;
  1115. return equal_slope(dx1, dy1, dx2, dy2);
  1116. }
  1117. template <typename area_type>
  1118. static inline bool less_slope(area_type dx1, area_type dy1, area_type dx2, area_type dy2) {
  1119. //reflext x and y slopes to right hand side half plane
  1120. if(dx1 < 0) {
  1121. dy1 *= -1;
  1122. dx1 *= -1;
  1123. } else if(dx1 == 0) {
  1124. //if the first slope is vertical the first cannot be less
  1125. return false;
  1126. }
  1127. if(dx2 < 0) {
  1128. dy2 *= -1;
  1129. dx2 *= -1;
  1130. } else if(dx2 == 0) {
  1131. //if the second slope is vertical the first is always less unless it is also vertical, in which case they are equal
  1132. return dx1 != 0;
  1133. }
  1134. typedef typename coordinate_traits<Unit>::unsigned_area_type unsigned_product_type;
  1135. unsigned_product_type cross_1 = (unsigned_product_type)(dx2 < 0 ? -dx2 :dx2) * (unsigned_product_type)(dy1 < 0 ? -dy1 : dy1);
  1136. unsigned_product_type cross_2 = (unsigned_product_type)(dx1 < 0 ? -dx1 :dx1) * (unsigned_product_type)(dy2 < 0 ? -dy2 : dy2);
  1137. int dx1_sign = dx1 < 0 ? -1 : 1;
  1138. int dx2_sign = dx2 < 0 ? -1 : 1;
  1139. int dy1_sign = dy1 < 0 ? -1 : 1;
  1140. int dy2_sign = dy2 < 0 ? -1 : 1;
  1141. int cross_1_sign = dx2_sign * dy1_sign;
  1142. int cross_2_sign = dx1_sign * dy2_sign;
  1143. if(cross_1_sign < cross_2_sign) return true;
  1144. if(cross_2_sign < cross_1_sign) return false;
  1145. if(cross_1_sign == -1) return cross_2 < cross_1;
  1146. return cross_1 < cross_2;
  1147. }
  1148. static inline bool less_slope(const Unit& x, const Unit& y,
  1149. const Point& pt1, const Point& pt2) {
  1150. const Point* pts[2] = {&pt1, &pt2};
  1151. //compute y value on edge from pt_ to pts[1] at the x value of pts[0]
  1152. typedef typename coordinate_traits<Unit>::manhattan_area_type at;
  1153. at dy2 = (at)pts[1]->get(VERTICAL) - (at)y;
  1154. at dy1 = (at)pts[0]->get(VERTICAL) - (at)y;
  1155. at dx2 = (at)pts[1]->get(HORIZONTAL) - (at)x;
  1156. at dx1 = (at)pts[0]->get(HORIZONTAL) - (at)x;
  1157. return less_slope(dx1, dy1, dx2, dy2);
  1158. }
  1159. //return -1 below, 0 on and 1 above line
  1160. //assumes point is on x interval of segment
  1161. static inline int on_above_or_below(Point pt, const half_edge& he) {
  1162. if(pt == he.first || pt == he.second) return 0;
  1163. if(equal_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second)) return 0;
  1164. bool less_result = less_slope(pt.get(HORIZONTAL), pt.get(VERTICAL), he.first, he.second);
  1165. int retval = less_result ? -1 : 1;
  1166. less_point lp;
  1167. if(lp(he.second, he.first)) retval *= -1;
  1168. if(!between(pt, he.first, he.second)) retval *= -1;
  1169. return retval;
  1170. }
  1171. };
  1172. template <typename T, typename input_point_type>
  1173. typename enable_if<
  1174. typename gtl_and< typename is_any_mutable_polygon_with_holes_type<T>::type,
  1175. typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type,
  1176. bool>::type
  1177. contains(const T& polygon, const input_point_type& point, bool consider_touch = true) {
  1178. typedef typename polygon_with_holes_traits<T>::iterator_holes_type holes_iterator;
  1179. bool isInside = contains( view_as< typename polygon_from_polygon_with_holes_type<
  1180. typename geometry_concept<T>::type>::type>( polygon ), point, consider_touch );
  1181. if(!isInside) return false; //no need to check holes
  1182. holes_iterator itH = begin_holes( polygon );
  1183. while( itH != end_holes( polygon ) ) {
  1184. if( contains( *itH, point, !consider_touch ) ) {
  1185. isInside = false;
  1186. break;
  1187. }
  1188. ++itH;
  1189. }
  1190. return isInside;
  1191. }
  1192. template <typename T, typename input_point_type>
  1193. typename enable_if<
  1194. typename gtl_and_3<
  1195. typename is_polygon_type<T>::type,
  1196. typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type,
  1197. typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type,
  1198. bool>::type
  1199. contains(const T& polygon, const input_point_type& point, bool consider_touch = true) {
  1200. typedef typename point_traits<input_point_type>::coordinate_type Unit;
  1201. typedef point_data<Unit> Point;
  1202. typedef std::pair<Point, Point> half_edge;
  1203. typedef typename polygon_traits<T>::iterator_type iterator;
  1204. iterator itr = begin_points(polygon);
  1205. iterator itrEnd = end_points(polygon);
  1206. half_edge he;
  1207. if(itr == itrEnd) return false;
  1208. assign(he.first, *itr);
  1209. Point firstPt;
  1210. assign(firstPt, *itr);
  1211. ++itr;
  1212. if(itr == itrEnd) return false;
  1213. bool done = false;
  1214. int above = 0;
  1215. while(!done) {
  1216. Point currentPt;
  1217. if(itr == itrEnd) {
  1218. done = true;
  1219. currentPt = firstPt;
  1220. } else {
  1221. assign(currentPt, *itr);
  1222. ++itr;
  1223. }
  1224. if(currentPt == he.first) {
  1225. continue;
  1226. } else {
  1227. he.second = currentPt;
  1228. if(equivalence(point, currentPt)) return consider_touch;
  1229. Unit xmin = (std::min)(x(he.first), x(he.second));
  1230. Unit xmax = (std::max)(x(he.first), x(he.second));
  1231. if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax
  1232. Point tmppt;
  1233. assign(tmppt, point);
  1234. int oabedge = edge_utils<Unit>::on_above_or_below(tmppt, he);
  1235. if(oabedge == 0) return consider_touch;
  1236. if(oabedge == 1) ++above;
  1237. } else if(x(point) == xmax) {
  1238. if(x(point) == xmin) {
  1239. Unit ymin = (std::min)(y(he.first), y(he.second));
  1240. Unit ymax = (std::max)(y(he.first), y(he.second));
  1241. Unit ypt = y(point);
  1242. if(ypt <= ymax && ypt >= ymin)
  1243. return consider_touch;
  1244. } else {
  1245. Point tmppt;
  1246. assign(tmppt, point);
  1247. if( edge_utils<Unit>::on_above_or_below(tmppt, he) == 0 ) {
  1248. return consider_touch;
  1249. }
  1250. }
  1251. }
  1252. }
  1253. he.first = he.second;
  1254. }
  1255. return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon
  1256. }
  1257. /*
  1258. template <typename T, typename input_point_type>
  1259. typename enable_if<
  1260. typename gtl_and_3<
  1261. typename is_polygon_with_holes_type<T>::type,
  1262. typename gtl_different_type<typename geometry_domain<typename geometry_concept<T>::type>::type, manhattan_domain>::type,
  1263. typename gtl_same_type<typename geometry_concept<input_point_type>::type, point_concept>::type>::type,
  1264. bool>::type
  1265. contains(const T& polygon, const input_point_type& point, bool consider_touch = true) {
  1266. typedef typename point_traits<input_point_type>::coordinate_type Unit;
  1267. typedef point_data<Unit> Point;
  1268. typedef std::pair<Point, Point> half_edge;
  1269. typedef typename polygon_traits<T>::iterator_type iterator;
  1270. iterator itr = begin_points(polygon);
  1271. iterator itrEnd = end_points(polygon);
  1272. half_edge he;
  1273. if(itr == itrEnd) return false;
  1274. assign(he.first, *itr);
  1275. Point firstPt;
  1276. assign(firstPt, *itr);
  1277. ++itr;
  1278. if(itr == itrEnd) return false;
  1279. bool done = false;
  1280. int above = 0;
  1281. while(!done) {
  1282. Point currentPt;
  1283. if(itr == itrEnd) {
  1284. done = true;
  1285. currentPt = firstPt;
  1286. } else {
  1287. assign(currentPt, *itr);
  1288. ++itr;
  1289. }
  1290. if(currentPt == he.first) {
  1291. continue;
  1292. } else {
  1293. he.second = currentPt;
  1294. if(equivalence(point, currentPt)) return consider_touch;
  1295. Unit xmin = (std::min)(x(he.first), x(he.second));
  1296. Unit xmax = (std::max)(x(he.first), x(he.second));
  1297. if(x(point) >= xmin && x(point) < xmax) { //double counts if <= xmax
  1298. Point tmppt;
  1299. assign(tmppt, point);
  1300. int oabedge = edge_utils<Unit>::on_above_or_below(tmppt, he);
  1301. if(oabedge == 0) return consider_touch;
  1302. if(oabedge == 1) ++above;
  1303. }
  1304. }
  1305. he.first = he.second;
  1306. }
  1307. return above % 2 != 0; //if the point is above an odd number of edges is must be inside polygon
  1308. }
  1309. */
  1310. template <typename T1, typename T2>
  1311. typename enable_if<
  1312. typename gtl_and< typename is_mutable_rectangle_concept<typename geometry_concept<T1>::type>::type,
  1313. typename is_polygon_with_holes_type<T2>::type>::type,
  1314. bool>::type
  1315. extents(T1& bounding_box, const T2& polygon) {
  1316. typedef typename polygon_traits<T2>::iterator_type iterator;
  1317. bool first_iteration = true;
  1318. iterator itr_end = end_points(polygon);
  1319. for(iterator itr = begin_points(polygon); itr != itr_end; ++itr) {
  1320. if(first_iteration) {
  1321. set_points(bounding_box, *itr, *itr);
  1322. first_iteration = false;
  1323. } else {
  1324. encompass(bounding_box, *itr);
  1325. }
  1326. }
  1327. if(first_iteration) return false;
  1328. return true;
  1329. }
  1330. template <typename T1, typename T2>
  1331. typename enable_if<
  1332. typename gtl_and< typename is_mutable_point_concept<typename geometry_concept<T1>::type>::type,
  1333. typename is_polygon_with_holes_type<T2>::type>::type,
  1334. bool>::type
  1335. center(T1& center_point, const T2& polygon) {
  1336. typedef typename polygon_traits<T2>::coordinate_type coordinate_type;
  1337. rectangle_data<coordinate_type> bbox;
  1338. extents(bbox, polygon);
  1339. return center(center_point, bbox);
  1340. }
  1341. template <class T>
  1342. template <class T2>
  1343. polygon_90_data<T>& polygon_90_data<T>::operator=(const T2& rvalue) {
  1344. assign(*this, rvalue);
  1345. return *this;
  1346. }
  1347. template <class T>
  1348. template <class T2>
  1349. polygon_45_data<T>& polygon_45_data<T>::operator=(const T2& rvalue) {
  1350. assign(*this, rvalue);
  1351. return *this;
  1352. }
  1353. template <class T>
  1354. template <class T2>
  1355. polygon_data<T>& polygon_data<T>::operator=(const T2& rvalue) {
  1356. assign(*this, rvalue);
  1357. return *this;
  1358. }
  1359. template <class T>
  1360. template <class T2>
  1361. polygon_90_with_holes_data<T>& polygon_90_with_holes_data<T>::operator=(const T2& rvalue) {
  1362. assign(*this, rvalue);
  1363. return *this;
  1364. }
  1365. template <class T>
  1366. template <class T2>
  1367. polygon_45_with_holes_data<T>& polygon_45_with_holes_data<T>::operator=(const T2& rvalue) {
  1368. assign(*this, rvalue);
  1369. return *this;
  1370. }
  1371. template <class T>
  1372. template <class T2>
  1373. polygon_with_holes_data<T>& polygon_with_holes_data<T>::operator=(const T2& rvalue) {
  1374. assign(*this, rvalue);
  1375. return *this;
  1376. }
  1377. template <typename T>
  1378. struct geometry_concept<polygon_data<T> > {
  1379. typedef polygon_concept type;
  1380. };
  1381. template <typename T>
  1382. struct geometry_concept<polygon_45_data<T> > {
  1383. typedef polygon_45_concept type;
  1384. };
  1385. template <typename T>
  1386. struct geometry_concept<polygon_90_data<T> > {
  1387. typedef polygon_90_concept type;
  1388. };
  1389. template <typename T>
  1390. struct geometry_concept<polygon_with_holes_data<T> > {
  1391. typedef polygon_with_holes_concept type;
  1392. };
  1393. template <typename T>
  1394. struct geometry_concept<polygon_45_with_holes_data<T> > {
  1395. typedef polygon_45_with_holes_concept type;
  1396. };
  1397. template <typename T>
  1398. struct geometry_concept<polygon_90_with_holes_data<T> > {
  1399. typedef polygon_90_with_holes_concept type;
  1400. };
  1401. // template <typename T> struct polygon_with_holes_traits<polygon_90_data<T> > {
  1402. // typedef polygon_90_data<T> hole_type;
  1403. // typedef const hole_type* iterator_holes_type;
  1404. // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; }
  1405. // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; }
  1406. // static inline std::size_t size_holes(const hole_type& t) { return 0; }
  1407. // };
  1408. // template <typename T> struct polygon_with_holes_traits<polygon_45_data<T> > {
  1409. // typedef polygon_45_data<T> hole_type;
  1410. // typedef const hole_type* iterator_holes_type;
  1411. // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; }
  1412. // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; }
  1413. // static inline std::size_t size_holes(const hole_type& t) { return 0; }
  1414. // };
  1415. // template <typename T> struct polygon_with_holes_traits<polygon_data<T> > {
  1416. // typedef polygon_data<T> hole_type;
  1417. // typedef const hole_type* iterator_holes_type;
  1418. // static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; }
  1419. // static inline iterator_holes_type end_holes(const hole_type& t) { return &t; }
  1420. // static inline std::size_t size_holes(const hole_type& t) { return 0; }
  1421. // };
  1422. template <typename T> struct get_void {};
  1423. template <> struct get_void<gtl_yes> { typedef void type; };
  1424. template <typename T> struct polygon_with_holes_traits<
  1425. T, typename get_void<typename is_any_mutable_polygon_without_holes_type<T>::type>::type > {
  1426. typedef T hole_type;
  1427. typedef const hole_type* iterator_holes_type;
  1428. static inline iterator_holes_type begin_holes(const hole_type& t) { return &t; }
  1429. static inline iterator_holes_type end_holes(const hole_type& t) { return &t; }
  1430. };
  1431. template <typename T>
  1432. struct view_of<rectangle_concept, T> {
  1433. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1434. typedef interval_data<coordinate_type> interval_type;
  1435. rectangle_data<coordinate_type> rect;
  1436. view_of(const T& obj) : rect() {
  1437. point_data<coordinate_type> pts[2];
  1438. typename polygon_traits<T>::iterator_type itr =
  1439. begin_points(obj), itre = end_points(obj);
  1440. if(itr == itre) return;
  1441. assign(pts[0], *itr);
  1442. ++itr;
  1443. if(itr == itre) return;
  1444. ++itr;
  1445. if(itr == itre) return;
  1446. assign(pts[1], *itr);
  1447. set_points(rect, pts[0], pts[1]);
  1448. }
  1449. inline interval_type get(orientation_2d orient) const {
  1450. return rect.get(orient); }
  1451. };
  1452. template <typename T>
  1453. struct geometry_concept<view_of<rectangle_concept, T> > {
  1454. typedef rectangle_concept type;
  1455. };
  1456. template <typename T>
  1457. struct view_of<polygon_45_concept, T> {
  1458. const T* t;
  1459. view_of(const T& obj) : t(&obj) {}
  1460. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1461. typedef typename polygon_traits<T>::iterator_type iterator_type;
  1462. typedef typename polygon_traits<T>::point_type point_type;
  1463. /// Get the begin iterator
  1464. inline iterator_type begin() const {
  1465. return polygon_traits<T>::begin_points(*t);
  1466. }
  1467. /// Get the end iterator
  1468. inline iterator_type end() const {
  1469. return polygon_traits<T>::end_points(*t);
  1470. }
  1471. /// Get the number of sides of the polygon
  1472. inline std::size_t size() const {
  1473. return polygon_traits<T>::size(*t);
  1474. }
  1475. /// Get the winding direction of the polygon
  1476. inline winding_direction winding() const {
  1477. return polygon_traits<T>::winding(*t);
  1478. }
  1479. };
  1480. template <typename T>
  1481. struct geometry_concept<view_of<polygon_45_concept, T> > {
  1482. typedef polygon_45_concept type;
  1483. };
  1484. template <typename T>
  1485. struct view_of<polygon_90_concept, T> {
  1486. const T* t;
  1487. view_of(const T& obj) : t(&obj) {}
  1488. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1489. typedef typename polygon_traits<T>::iterator_type iterator_type;
  1490. typedef typename polygon_traits<T>::point_type point_type;
  1491. typedef iterator_points_to_compact<iterator_type, point_type> compact_iterator_type;
  1492. /// Get the begin iterator
  1493. inline compact_iterator_type begin_compact() const {
  1494. return compact_iterator_type(polygon_traits<T>::begin_points(*t),
  1495. polygon_traits<T>::end_points(*t));
  1496. }
  1497. /// Get the end iterator
  1498. inline compact_iterator_type end_compact() const {
  1499. return compact_iterator_type(polygon_traits<T>::end_points(*t),
  1500. polygon_traits<T>::end_points(*t));
  1501. }
  1502. /// Get the number of sides of the polygon
  1503. inline std::size_t size() const {
  1504. return polygon_traits<T>::size(*t);
  1505. }
  1506. /// Get the winding direction of the polygon
  1507. inline winding_direction winding() const {
  1508. return polygon_traits<T>::winding(*t);
  1509. }
  1510. };
  1511. template <typename T>
  1512. struct geometry_concept<view_of<polygon_90_concept, T> > {
  1513. typedef polygon_90_concept type;
  1514. };
  1515. template <typename T>
  1516. struct view_of<polygon_45_with_holes_concept, T> {
  1517. const T* t;
  1518. view_of(const T& obj) : t(&obj) {}
  1519. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1520. typedef typename polygon_traits<T>::iterator_type iterator_type;
  1521. typedef typename polygon_traits<T>::point_type point_type;
  1522. typedef view_of<polygon_45_concept, typename polygon_with_holes_traits<T>::hole_type> hole_type;
  1523. struct iterator_holes_type {
  1524. typedef std::forward_iterator_tag iterator_category;
  1525. typedef hole_type value_type;
  1526. typedef std::ptrdiff_t difference_type;
  1527. typedef const hole_type* pointer; //immutable
  1528. typedef const hole_type& reference; //immutable
  1529. typedef typename polygon_with_holes_traits<T>::iterator_holes_type iht;
  1530. iht internal_itr;
  1531. iterator_holes_type() : internal_itr() {}
  1532. iterator_holes_type(iht iht_in) : internal_itr(iht_in) {}
  1533. inline iterator_holes_type& operator++() {
  1534. ++internal_itr;
  1535. return *this;
  1536. }
  1537. inline const iterator_holes_type operator++(int) {
  1538. iterator_holes_type tmp(*this);
  1539. ++(*this);
  1540. return tmp;
  1541. }
  1542. inline bool operator==(const iterator_holes_type& that) const {
  1543. return (internal_itr == that.internal_itr);
  1544. }
  1545. inline bool operator!=(const iterator_holes_type& that) const {
  1546. return (internal_itr != that.internal_itr);
  1547. }
  1548. inline value_type operator*() const {
  1549. return view_as<polygon_45_concept>(*internal_itr);
  1550. }
  1551. };
  1552. /// Get the begin iterator
  1553. inline iterator_type begin() const {
  1554. return polygon_traits<T>::begin_points(*t);
  1555. }
  1556. /// Get the end iterator
  1557. inline iterator_type end() const {
  1558. return polygon_traits<T>::end_points(*t);
  1559. }
  1560. /// Get the number of sides of the polygon
  1561. inline std::size_t size() const {
  1562. return polygon_traits<T>::size(*t);
  1563. }
  1564. /// Get the winding direction of the polygon
  1565. inline winding_direction winding() const {
  1566. return polygon_traits<T>::winding(*t);
  1567. }
  1568. /// Get the begin iterator
  1569. inline iterator_holes_type begin_holes() const {
  1570. return polygon_with_holes_traits<T>::begin_holes(*t);
  1571. }
  1572. /// Get the end iterator
  1573. inline iterator_holes_type end_holes() const {
  1574. return polygon_with_holes_traits<T>::end_holes(*t);
  1575. }
  1576. /// Get the number of sides of the polygon
  1577. inline std::size_t size_holes() const {
  1578. return polygon_with_holes_traits<T>::size_holes(*t);
  1579. }
  1580. };
  1581. template <typename T>
  1582. struct geometry_concept<view_of<polygon_45_with_holes_concept, T> > {
  1583. typedef polygon_45_with_holes_concept type;
  1584. };
  1585. template <typename T>
  1586. struct view_of<polygon_90_with_holes_concept, T> {
  1587. const T* t;
  1588. view_of(const T& obj) : t(&obj) {}
  1589. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1590. typedef typename polygon_traits<T>::iterator_type iterator_type;
  1591. typedef typename polygon_traits<T>::point_type point_type;
  1592. typedef iterator_points_to_compact<iterator_type, point_type> compact_iterator_type;
  1593. typedef view_of<polygon_90_concept, typename polygon_with_holes_traits<T>::hole_type> hole_type;
  1594. struct iterator_holes_type {
  1595. typedef std::forward_iterator_tag iterator_category;
  1596. typedef hole_type value_type;
  1597. typedef std::ptrdiff_t difference_type;
  1598. typedef const hole_type* pointer; //immutable
  1599. typedef const hole_type& reference; //immutable
  1600. typedef typename polygon_with_holes_traits<T>::iterator_holes_type iht;
  1601. iht internal_itr;
  1602. iterator_holes_type() : internal_itr() {}
  1603. iterator_holes_type(iht iht_in) : internal_itr(iht_in) {}
  1604. inline iterator_holes_type& operator++() {
  1605. ++internal_itr;
  1606. return *this;
  1607. }
  1608. inline const iterator_holes_type operator++(int) {
  1609. iterator_holes_type tmp(*this);
  1610. ++(*this);
  1611. return tmp;
  1612. }
  1613. inline bool operator==(const iterator_holes_type& that) const {
  1614. return (internal_itr == that.internal_itr);
  1615. }
  1616. inline bool operator!=(const iterator_holes_type& that) const {
  1617. return (internal_itr != that.internal_itr);
  1618. }
  1619. inline value_type operator*() const {
  1620. return view_as<polygon_90_concept>(*internal_itr);
  1621. }
  1622. };
  1623. /// Get the begin iterator
  1624. inline compact_iterator_type begin_compact() const {
  1625. return compact_iterator_type(polygon_traits<T>::begin_points(*t),
  1626. polygon_traits<T>::end_points(*t));
  1627. }
  1628. /// Get the end iterator
  1629. inline compact_iterator_type end_compact() const {
  1630. return compact_iterator_type(polygon_traits<T>::end_points(*t),
  1631. polygon_traits<T>::end_points(*t));
  1632. }
  1633. /// Get the number of sides of the polygon
  1634. inline std::size_t size() const {
  1635. return polygon_traits<T>::size(*t);
  1636. }
  1637. /// Get the winding direction of the polygon
  1638. inline winding_direction winding() const {
  1639. return polygon_traits<T>::winding(*t);
  1640. }
  1641. /// Get the begin iterator
  1642. inline iterator_holes_type begin_holes() const {
  1643. return polygon_with_holes_traits<T>::begin_holes(*t);
  1644. }
  1645. /// Get the end iterator
  1646. inline iterator_holes_type end_holes() const {
  1647. return polygon_with_holes_traits<T>::end_holes(*t);
  1648. }
  1649. /// Get the number of sides of the polygon
  1650. inline std::size_t size_holes() const {
  1651. return polygon_with_holes_traits<T>::size_holes(*t);
  1652. }
  1653. };
  1654. template <typename T>
  1655. struct geometry_concept<view_of<polygon_90_with_holes_concept, T> > {
  1656. typedef polygon_90_with_holes_concept type;
  1657. };
  1658. template <typename T>
  1659. struct view_of<polygon_concept, T> {
  1660. const T* t;
  1661. view_of(const T& obj) : t(&obj) {}
  1662. typedef typename polygon_traits<T>::coordinate_type coordinate_type;
  1663. typedef typename polygon_traits<T>::iterator_type iterator_type;
  1664. typedef typename polygon_traits<T>::point_type point_type;
  1665. /// Get the begin iterator
  1666. inline iterator_type begin() const {
  1667. return polygon_traits<T>::begin_points(*t);
  1668. }
  1669. /// Get the end iterator
  1670. inline iterator_type end() const {
  1671. return polygon_traits<T>::end_points(*t);
  1672. }
  1673. /// Get the number of sides of the polygon
  1674. inline std::size_t size() const {
  1675. return polygon_traits<T>::size(*t);
  1676. }
  1677. /// Get the winding direction of the polygon
  1678. inline winding_direction winding() const {
  1679. return polygon_traits<T>::winding(*t);
  1680. }
  1681. };
  1682. template <typename T>
  1683. struct geometry_concept<view_of<polygon_concept, T> > {
  1684. typedef polygon_concept type;
  1685. };
  1686. }
  1687. }
  1688. #endif