polygon_traits.hpp 72 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862
  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