PageRenderTime 50ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/source/polygontriangulation.h

https://bitbucket.org/val_haris/asc-ai
C++ Header | 382 lines | 274 code | 71 blank | 37 comment | 80 complexity | 1d578fedb21bb507a4e0c6536a435008 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-2.0
  1. /*! \file polygontriangulation.h
  2. \brief Interface to the polygon triangulation library
  3. */
  4. // $Id: polygontriangulation.h,v 1.6 2009-04-18 13:48:38 mbickel Exp $
  5. /*
  6. This file is part of Advanced Strategic Command; http://www.asc-hq.de
  7. Copyright (C) 1994-2010 Martin Bickel and Marc Schellenberger
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; see the file COPYING. If not, write to the
  18. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  19. Boston, MA 02111-1307 USA
  20. */
  21. #ifndef polygontriangulationH
  22. #define polygontriangulationH
  23. #include <math.h>
  24. #include <sys/types.h>
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. namespace PolygonTriangulationLibrary {
  28. #include "libs/triangul/interfac.h"
  29. #include "libs/triangul/triangul.h"
  30. };
  31. template <class Poly>
  32. class PolygonPainter {
  33. public:
  34. bool paintPolygon ( const Poly& poly );
  35. protected:
  36. virtual void sortpolygon ( Poly& a );
  37. virtual void painttriangle ( typename Poly::Point p[] );
  38. virtual void painthorizline ( int x1, int x2, int y );
  39. virtual void paintline ( int x1, int y1, int x2, int y2 );
  40. virtual void setpoint ( int x, int y ) = 0;
  41. virtual int getpolydir ( const Poly& a);
  42. virtual double getsegmentdir ( int dx, int dy );
  43. //! returns true if polygon correct
  44. virtual bool checkpolygon ( const Poly& poly );
  45. //! returns true if lines a-b and c-d don't intersect
  46. virtual bool checkline ( typename Poly::Point a, typename Poly::Point b, typename Poly::Point d, typename Poly::Point e );
  47. virtual ~PolygonPainter() {};
  48. };
  49. template <class Poly>
  50. bool PolygonPainter<Poly>::paintPolygon ( const Poly& poly )
  51. {
  52. if ( !poly.vertex.size() )
  53. return true;
  54. // displayLogMessage ( 10, "pp1 ");
  55. if (checkpolygon ( poly )) {
  56. if ( poly.vertex.size() == 1 ) {
  57. setpoint ( poly.vertex[0].x, poly.vertex[0].y );
  58. return true;
  59. }
  60. if ( poly.vertex.size() == 2 ) {
  61. paintline ( poly.vertex[0].x, poly.vertex[0].y, poly.vertex[1].x, poly.vertex[1].y );
  62. return true;
  63. }
  64. // displayLogMessage ( 10, "pp2 ");
  65. Poly pol2 = poly;
  66. sortpolygon ( pol2 );
  67. typedef double double2[2];
  68. double2* floatpoints = new double2 [ pol2.vertex.size()+1 ];
  69. for ( int i=0; i<pol2.vertex.size() ; i++ ) {
  70. floatpoints[i+1][0] = (double) pol2.vertex[i].x;
  71. floatpoints[i+1][1] = (double) pol2.vertex[i].y;
  72. } /* endfor */
  73. typedef int int3[3];
  74. int3* triangles = new int3 [ pol2.vertex.size() ];
  75. int contours = pol2.vertex.size();
  76. // displayLogMessage ( 10, "pp3 ");
  77. PolygonTriangulationLibrary::triangulate_polygon ( 1, &contours, floatpoints, triangles );
  78. // displayLogMessage ( 10, "pp4 ");
  79. for ( int i=0; i<pol2.vertex.size()-2 ;i++ ) {
  80. typename Poly::Point tripos[3];
  81. tripos[0] = pol2.vertex[triangles[i][0]-1];
  82. tripos[1] = pol2.vertex[triangles[i][1]-1];
  83. tripos[2] = pol2.vertex[triangles[i][2]-1];
  84. painttriangle ( tripos );
  85. } /* endfor */
  86. delete[] triangles;
  87. delete[] floatpoints;
  88. return true;
  89. } else
  90. return false;
  91. }
  92. static const double pi = 3.141592654;
  93. template <class Poly>
  94. bool PolygonPainter<Poly>::checkline( typename Poly::Point a, typename Poly::Point b, typename Poly::Point d, typename Poly::Point e )
  95. {
  96. double r,s,t;
  97. b.x -= a.x;
  98. b.y -= a.y;
  99. e.x -= d.x;
  100. e.y -= d.y;
  101. /*
  102. if ( b.y != 0 && e.y != 0 ) {
  103. if ( abs( b.x / b.y - e.x / e.y ) < 1e-6 )
  104. return false;
  105. } else
  106. if ( b.y == 0 && e.y == 0 )
  107. return false;
  108. */
  109. t = b.x * e.y - b.y * e.x;
  110. if (t != 0) {
  111. double m = ( a.x * b.y - a.y * b.x + d.y * b.x - d.x * b.y );
  112. r = m / -t;
  113. double n = ( a.y * e.x - a.x * e.y + d.x * e.y - d.y * e.x );
  114. s = n / t;
  115. if ( s>=0 && s <= 1 && r>=0 && r <= 1)
  116. return false;
  117. } /* endif */
  118. return true;
  119. }
  120. template <class Poly>
  121. bool PolygonPainter<Poly>::checkpolygon ( const Poly& poly )
  122. {
  123. if ( poly.vertex.size() > 1 && poly.vertex.size() < 3 )
  124. return true;
  125. else {
  126. size_t i,j,k;
  127. for ( i = 0; i < poly.vertex.size(); i++ )
  128. for ( j = 0; j < poly.vertex.size(); j++ )
  129. if ( i != j )
  130. if ( poly.vertex[i].x == poly.vertex[j].x &&
  131. poly.vertex[i].y == poly.vertex[j].y )
  132. return false;
  133. k = poly.vertex.size() -1;
  134. for (i=0; i < k ; i++) {
  135. for (j = i +2; j < k ; j++)
  136. if (checkline ( poly.vertex[i], poly.vertex[i+1], poly.vertex[j], poly.vertex[j+1] ) == false)
  137. return false;
  138. if (i > 0 && j == k)
  139. if (checkline ( poly.vertex[i], poly.vertex[i+1], poly.vertex[j], poly.vertex[0] ) == false)
  140. return false;
  141. } /* endfor */
  142. return true;
  143. }
  144. }
  145. template <class Poly>
  146. double PolygonPainter<Poly>::getsegmentdir ( int dx, int dy )
  147. {
  148. double alpha;
  149. if (dx) {
  150. alpha = atan ( (double) dy / (double) dx );
  151. if ( dy < 0 ) {
  152. if ( dx < 0)
  153. alpha = -pi + alpha;
  154. } else
  155. if ( dx < 0)
  156. alpha = pi - alpha;
  157. } else {
  158. if (dy > 0)
  159. alpha = pi/2;
  160. else
  161. alpha = -pi/2;
  162. } /* endif */
  163. return alpha;
  164. }
  165. template <class Poly>
  166. int PolygonPainter<Poly>::getpolydir ( const Poly& a)
  167. {
  168. int p ;
  169. double alpha, beta, gamma;
  170. int r = 0;
  171. for (p=0; p< a.vertex.size(); p++) {
  172. if (p == 0)
  173. alpha = getsegmentdir( a.vertex[p].x - a.vertex[a.vertex.size()-1].x , a.vertex[p].y - a.vertex[a.vertex.size()-1].y );
  174. else
  175. alpha = getsegmentdir( a.vertex[p].x - a.vertex[p-1].x, a.vertex[p].y - a.vertex[p-1].y );
  176. if (p+1 >= a.vertex.size())
  177. beta = getsegmentdir( a.vertex[0].x - a.vertex[p].x , a.vertex[0].y - a.vertex[p].y );
  178. else
  179. beta = getsegmentdir( a.vertex[p+1].x - a.vertex[p].x, a.vertex[p+1].y - a.vertex[p].y );
  180. gamma = beta - alpha ;
  181. if (gamma > pi)
  182. gamma = pi - gamma;
  183. if (gamma < -pi)
  184. gamma = -pi - gamma;
  185. r+= (int) ( gamma * 1000 );
  186. }
  187. return r;
  188. }
  189. template <class Poly>
  190. void PolygonPainter<Poly>::sortpolygon ( Poly& a )
  191. {
  192. if ( a.vertex.size() >= 3 )
  193. if ( getpolydir(a) < 0 ) {
  194. for ( int i=0;i< a.vertex.size()/2 ;i++ ) {
  195. typename Poly::Point p = a.vertex[i];
  196. a.vertex[i] = a.vertex[a.vertex.size()-i-1];
  197. a.vertex[a.vertex.size()-i-1] = p;
  198. } /* endfor */
  199. }
  200. }
  201. template <class Poly>
  202. void PolygonPainter<Poly>::painttriangle ( typename Poly::Point p[] )
  203. {
  204. int x,y,dx1,dx2,dy1,dy2;
  205. for ( int i=0; i<2 ; ) {
  206. if ( p[i+1].y < p[i].y || ( p[i+1].y == p[i].y && p[i+1].x < p[i].x )) {
  207. x = p[i].x;
  208. p[i].x = p[i+1].x;
  209. p[i+1].x = x;
  210. y = p[i].y;
  211. p[i].y = p[i+1].y;
  212. p[i+1].y = y;
  213. i = 0;
  214. } else
  215. i++;
  216. } /* endfor */
  217. if ( p[0].y < p[1].y ) {
  218. dx1 = p[1].x - p[0].x;
  219. dx2 = p[2].x - p[0].x;
  220. dy1 = p[1].y - p[0].y;
  221. dy2 = p[2].y - p[0].y;
  222. for (y=p[0].y; y<=p[1].y ; y++)
  223. painthorizline ( p[0].x + dx1 * (y - p[0].y) / dy1 , p[0].x + dx2 * (y - p[0].y) / dy2, y );
  224. if (p[1].y < p[2].y) {
  225. dx1 = p[2].x - p[1].x;
  226. dy1 = p[2].y - p[1].y;
  227. for ( ; y<=p[2].y ; y++)
  228. painthorizline ( p[1].x + dx1 * (y - p[1].y) / dy1 , p[0].x + dx2 * (y - p[0].y) / dy2, y );
  229. }
  230. } else {
  231. if ( p[1].y < p[2].y ) {
  232. dx1 = p[2].x - p[1].x;
  233. dx2 = p[2].x - p[0].x;
  234. dy1 = p[2].y - p[0].y;
  235. for (y=p[0].y; y<=p[2].y ; y++)
  236. painthorizline ( p[1].x + dx1 * (y - p[0].y) / dy1 , p[0].x + dx2 * (y - p[0].y) / dy1, y );
  237. } else
  238. painthorizline ( p[0].x, p[2].x, p[0].y );
  239. }
  240. }
  241. template <class Poly>
  242. void PolygonPainter<Poly>::painthorizline ( int x1, int x2, int y )
  243. {
  244. int dx;
  245. if (x1 > x2)
  246. dx = -1;
  247. else
  248. if (x1 < x2)
  249. dx = 1;
  250. else {
  251. setpoint ( x2, y );
  252. return;
  253. }
  254. int x= x1;
  255. do {
  256. setpoint ( x, y );
  257. x += dx;
  258. } while ( x != x2 ); /* enddo */
  259. setpoint ( x, y );
  260. }
  261. template <class Poly>
  262. void PolygonPainter<Poly>::paintline ( int x1, int y1, int x2, int y2 )
  263. {
  264. float m, b;
  265. int w;
  266. float yy1, yy2, xx1, xx2;
  267. if ( x1 == x2) {
  268. for (w=y1;w<=y2 ;w++ )
  269. setpoint ( x1, w );
  270. } else {
  271. if ( y1 == y2) {
  272. for (w=x1;w<=x2 ;w++ )
  273. setpoint( w, y1 );
  274. } else {
  275. yy1 = y1;
  276. yy2 = y2;
  277. xx1 = x1;
  278. xx2 = x2;
  279. m = (yy2 - yy1) / (xx2 - xx1);
  280. b = y1 - m * x1;
  281. if ((m <= 1) && (m >= -1)) {
  282. if (x2 < x1) {
  283. w = x2;
  284. x2 = x1;
  285. x1 = w;
  286. w = y2;
  287. y2 = y1;
  288. y1 = w;
  289. }
  290. for (w = x1; w <= x2; w++)
  291. setpoint(w, (int) (m * w + b) );
  292. } else {
  293. if (y2 < y1) {
  294. w = x2;
  295. x2 = x1;
  296. x1 = w;
  297. w = y2;
  298. y2 = y1;
  299. y1 = w;
  300. }
  301. for (w = y1; w <= y2; w++) {
  302. setpoint( (int) ((w - b) / m), w );
  303. }
  304. }
  305. } /* endif */
  306. }
  307. }
  308. #endif