utility.cpp
上传用户:chinasdcnc
上传日期:2022-07-02
资源大小:2702k
文件大小:6k
源码类别:

分形几何

开发平台:

Visual C++

  1. //
  2. // Delaunay Triangulation
  3. //
  4. // Homework of CG lesson (Fall 2009) in Tsinghua University.
  5. // All rights reserved.
  6. //
  7. // temp include, delete later if necessary
  8. #include "stdafx.h"
  9. #include "utility.h"
  10. // C++headers
  11. #include <cmath>
  12. // User headers
  13. #include "dcel.h"
  14. #include "base.h"
  15. #include "line2d.h"
  16. Edge* makeEdge(void)
  17. {
  18.     DCEL* dcel = new DCEL();
  19.     return dcel->e;
  20. }
  21. void splice(Edge* a, Edge* b)
  22. {
  23.     a->prev()->eNext = b;
  24.     b->prev()->eNext = a;
  25.     Edge* t1 = a->prev();
  26.     Edge* t2 = b->prev();
  27.     a->ePrev = t2;
  28.     b->ePrev = t1;
  29. }
  30. void deleteEdge(Edge* e)
  31. {
  32.     if (e != NULL)
  33.     {
  34.         splice(e, e->oPrev());
  35.         splice(e->sym(), e->sym()->oPrev());
  36.         delete e->qEdge();
  37.         e = NULL;
  38.     }
  39. }
  40. Edge* connect(Edge* a, Edge* b)
  41. {
  42.     Edge* e = makeEdge();
  43.     splice(e, a->lNext());
  44.     splice(e->sym(), b);
  45.     e->endPoints(a->dest(), b->org());
  46.     return e;
  47. }
  48. void swap(Edge* e)
  49. {
  50.     Edge* a = e->oPrev();
  51.     Edge* b = e->sym()->oPrev();
  52.     splice(e, a);
  53.     splice(e->sym(), b);
  54.     splice(e, a->lNext());
  55.     splice(e->sym(), b->lNext());
  56.     e->endPoints(a->dest(), b->dest());
  57. }
  58. double triarea(const Point2d& a, const Point2d& b, const Point2d& c)
  59. {
  60.     return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
  61. }
  62. bool inCircle(const Point2d& a, const Point2d& b,
  63.               const Point2d& c, const Point2d& d)
  64. {
  65.     if (&d == &a || &d == &b || &d == &c)
  66.         return false;
  67.     return (a.x*a.x + a.y*a.y) * triarea(b, c, d) -
  68.            (b.x*b.x + b.y*b.y) * triarea(a, c, d) +
  69.            (c.x*c.x + c.y*c.y) * triarea(a, b, d) -
  70.            (d.x*d.x + d.y*d.y) * triarea(a, b, c) > 0;
  71. }
  72. bool ccw(const Point2d& a, const Point2d& b, const Point2d& c)
  73. {
  74.     return (triarea(a, b, c) > 0);
  75. }
  76. bool rightOf(const Point2d& x, Edge* e)
  77. {
  78.     return ccw(x, e->dest2d(), e->org2d());
  79. }
  80. bool leftOf(const Point2d& x, Edge* e)
  81. {
  82.     return ccw(x, e->org2d(), e->dest2d());
  83. }
  84. bool onEdge(const Point2d& x, Edge* e)
  85. {
  86.     double t1, t2, t3;
  87.     t1 = (x - e->org2d()).squareNorm();
  88.     t2 = (x - e->dest2d()).squareNorm();
  89.     if (t1 < TOLERANCE || t2 < TOLERANCE)
  90.         return true;
  91.     t3 = (e->org2d() - e->dest2d()).squareNorm();
  92.     if (t1 > t3 || t2 > t3)
  93.         return false;
  94.     Line2d line(e->org2d(), e->dest2d());
  95.     return (fabs(line.eval(x)) < TOLERANCE);
  96. }
  97. bool valid(Edge* e, Edge* basel)
  98. {
  99. return rightOf(*(e->dest()), basel);
  100. }
  101. bool testInside(const Point2d &x, Edge* startEdge)
  102. {
  103. Edge* e = startEdge->twin();
  104. do {
  105. if (leftOf(x, e))
  106. return false;
  107. e = e->lNext();
  108. } while (e != startEdge->twin());
  109. return true;
  110. }
  111. Edge* locate(const Point2d& x, Edge* startEdge)
  112. {
  113. if (!testInside(x, startEdge))
  114. return NULL;
  115.     Edge* e = startEdge;
  116. int lastState = 0;
  117.     while (true) 
  118. {
  119.         if (&x == e->org() || &x == e->dest())
  120.             return e;
  121. else if (onEdge(x, e))
  122.     return e;
  123.         else if (!rightOf(x, e->oNext()))
  124. {
  125. if (lastState != 1)
  126. {
  127. lastState = 1;
  128. startEdge = e;
  129. }
  130.             e = e->oNext();
  131. if (e == startEdge)
  132. return NULL;
  133. }
  134.         else if (!rightOf(x, e->dPrev()))
  135. {
  136. if (lastState != 2)
  137. {
  138. lastState = 2;
  139. startEdge = e;
  140. }
  141.             e = e->dPrev();
  142. if (e == startEdge)
  143. return NULL;
  144. }
  145.         else
  146.             return e;
  147.     }
  148. }
  149. bool lineIntersected(const Point2d& p1, const Point2d& p2,
  150.                      const Point2d& p3, const Point2d& p4)
  151. {
  152.     if((ccw(p3, p4, p1) != ccw(p3, p4, p2)) &&
  153. ccw(p1, p2, p3) != ccw(p1, p2, p4))
  154.     return true;
  155. else
  156. return false;
  157. }
  158. Edge* searchIntersectedEdge(Point2d& p1, Point2d& p2, Edge* startEdge)
  159. {
  160. Edge *e = startEdge->twin()->lNext();
  161. bool isIntersect = false;
  162. while (e != startEdge->twin())
  163. {
  164. if (lineIntersected(p1, p2, e->org2d(), e->dest2d()) && leftOf(p1, e))
  165. {
  166. isIntersect = true;
  167. return e->twin();
  168. }
  169. e = e->lNext();
  170. }
  171. if (lineIntersected(p1, p2, e->org2d(), e->dest2d()) && leftOf(p1, e))
  172. return e->twin();
  173. else
  174. return NULL;
  175. }
  176. void intersectedTris(Point2d& p1, Point2d& p2,
  177.                      vector<Edge *>& edges, Edge* startEdge)
  178. {
  179.     // find the first intersected triangle
  180. Edge *initEdge = locate(p1, startEdge);
  181. bool outerCase1 = false;
  182. bool outerCase2 = false;
  183. if (initEdge == NULL)
  184. {
  185. outerCase1 = true;
  186. initEdge = searchIntersectedEdge(p1, p2, startEdge);  // search outer intersect edge.
  187. if (initEdge == NULL)  // no intersection.
  188. return;
  189. }
  190. if (locate(p2, startEdge) == NULL)
  191. outerCase2 = true;
  192. Edge *iterEdge;
  193. Edge *firstEdge = initEdge;
  194. bool isIntersected = false;
  195. bool isFirst = false;
  196. // decide whether p1 is on the initEdge
  197. if(!onEdge(p1, initEdge))
  198. {
  199. while(1)
  200. {
  201. isIntersected = false;
  202. iterEdge = initEdge->lNext();
  203. while(iterEdge != initEdge)
  204. {
  205. if (iterEdge == firstEdge || iterEdge == firstEdge->twin())
  206. return; //break
  207. if(lineIntersected(p1, p2, iterEdge->org2d(), iterEdge->dest2d()))
  208. {
  209. isIntersected = true;
  210. break;
  211. }
  212. iterEdge = iterEdge->lNext();
  213. }
  214. if(!isFirst && !isIntersected && !outerCase1)
  215. {
  216.     if(lineIntersected(p1, p2, iterEdge->org2d(), iterEdge->dest2d()))
  217. {
  218. isIntersected = true;
  219. }
  220. }
  221. // p1, p2 is not surrounded by tri define by initEdge
  222. if(isIntersected)
  223. {
  224. if (!isFirst)
  225. isFirst = true;
  226. edges.push_back(iterEdge);
  227. initEdge = iterEdge->twin();
  228. }
  229. else
  230. {
  231. if(!isFirst)
  232. {
  233. edges.push_back(initEdge);
  234. return;
  235. }
  236. else if (isFirst && !outerCase2)
  237. {
  238. if (!outerCase2)
  239. edges.push_back(initEdge);
  240. return;
  241. }
  242. else
  243. {
  244. return;
  245. }
  246. }
  247. }
  248. }
  249. else
  250. {
  251. }
  252. }
  253. void circumCircle(const Point2d& p1, const Point2d& p2, const Point2d& p3,
  254.                   Point2d* pCenter, double* radius)
  255. {
  256. double u1 = 0.5 * (pow(p2.x, 2.0) - pow(p1.x, 2.0) + pow(p2.y, 2.0) - pow(p1.y, 2.0));
  257. double u2 = 0.5 * (pow(p3.x, 2.0) - pow(p1.x, 2.0) + pow(p3.y, 2.0) - pow(p1.y, 2.0));
  258. double d11 = p2.x - p1.x;
  259. double d12 = p2.y - p1.y;
  260. double d21 = p3.x - p1.x;
  261. double d22 = p3.y - p1.y;
  262. pCenter->x = (u1 * d22 - u2 * d12) / (d11 * d22 - d21 * d12);
  263. pCenter->y = (u2 * d11 - u1 * d21) / (d11 * d22 - d21 * d12);
  264. *radius = sqrt((pCenter->x - p1.x) * (pCenter->x - p1.x)
  265.         + (pCenter->y - p1.y) * (pCenter->y - p1.y));
  266. }