circle.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558
  1. //*****************************************************************************
  2. //
  3. // circle.c - Routines for drawing circles.
  4. //
  5. // Copyright (c) 2007-2010 Texas Instruments Incorporated. All rights reserved.
  6. // Software License Agreement
  7. //
  8. // Texas Instruments (TI) is supplying this software for use solely and
  9. // exclusively on TI's microcontroller products. The software is owned by
  10. // TI and/or its suppliers, and is protected under applicable copyright
  11. // laws. You may not combine this software with "viral" open-source
  12. // software in order to form a larger program.
  13. //
  14. // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS.
  15. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT
  16. // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  17. // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY
  18. // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
  19. // DAMAGES, FOR ANY REASON WHATSOEVER.
  20. //
  21. // This is part of revision 6288 of the Stellaris Graphics Library.
  22. //
  23. //*****************************************************************************
  24. #include "debug.h"
  25. #include "grlib.h"
  26. //*****************************************************************************
  27. //
  28. //! \addtogroup primitives_api
  29. //! @{
  30. //
  31. //*****************************************************************************
  32. //*****************************************************************************
  33. //
  34. //! Draws a circle.
  35. //!
  36. //! \param pContext is a pointer to the drawing context to use.
  37. //! \param lX is the X coordinate of the center of the circle.
  38. //! \param lY is the Y coordinate of the center of the circle.
  39. //! \param lRadius is the radius of the circle.
  40. //!
  41. //! This function draws a circle, utilizing the Bresenham circle drawing
  42. //! algorithm. The extent of the circle is from \e lX - \e lRadius to \e lX +
  43. //! \e lRadius and \e lY - \e lRadius to \e lY + \e lRadius, inclusive.
  44. //!
  45. //! \return None.
  46. //
  47. //*****************************************************************************
  48. void
  49. GrCircleDraw(const tContext *pContext, int lX, int lY, int lRadius)
  50. {
  51. int lA, lB, lD, lX1, lY1;
  52. //
  53. // Check the arguments.
  54. //
  55. ASSERT(pContext);
  56. //
  57. // Initialize the variables that control the Bresenham circle drawing
  58. // algorithm.
  59. //
  60. lA = 0;
  61. lB = lRadius;
  62. lD = 3 - (2 * lRadius);
  63. //
  64. // Loop until the A delta is greater than the B delta, meaning that the
  65. // entire circle has been drawn.
  66. //
  67. while(lA <= lB)
  68. {
  69. //
  70. // Determine the row when subtracting the A delta.
  71. //
  72. lY1 = lY - lA;
  73. //
  74. // See if this row is within the clipping region.
  75. //
  76. if((lY1 >= pContext->sClipRegion.sYMin) &&
  77. (lY1 <= pContext->sClipRegion.sYMax))
  78. {
  79. //
  80. // Determine the column when subtracting the B delta.
  81. //
  82. lX1 = lX - lB;
  83. //
  84. // If this column is within the clipping region, then draw a pixel
  85. // at that position.
  86. //
  87. if((lX1 >= pContext->sClipRegion.sXMin) &&
  88. (lX1 <= pContext->sClipRegion.sXMax))
  89. {
  90. GrPixelDraw(pContext, lX1, lY1);
  91. }
  92. //
  93. // Determine the column when adding the B delta.
  94. //
  95. lX1 = lX + lB;
  96. //
  97. // If this column is within the clipping region, then draw a pixel
  98. // at that position.
  99. //
  100. if((lX1 >= pContext->sClipRegion.sXMin) &&
  101. (lX1 <= pContext->sClipRegion.sXMax))
  102. {
  103. GrPixelDraw(pContext, lX1, lY1);
  104. }
  105. }
  106. //
  107. // Determine the row when adding the A delta.
  108. //
  109. lY1 = lY + lA;
  110. //
  111. // See if this row is within the clipping region, and the A delta is
  112. // not zero (otherwise, it will be the same row as when the A delta was
  113. // subtracted).
  114. //
  115. if((lY1 >= pContext->sClipRegion.sYMin) &&
  116. (lY1 <= pContext->sClipRegion.sYMax) &&
  117. (lA != 0))
  118. {
  119. //
  120. // Determine the column when subtracting the B delta.
  121. //
  122. lX1 = lX - lB;
  123. //
  124. // If this column is within the clipping region, then draw a pixel
  125. // at that position.
  126. //
  127. if((lX1 >= pContext->sClipRegion.sXMin) &&
  128. (lX1 <= pContext->sClipRegion.sXMax))
  129. {
  130. GrPixelDraw(pContext, lX1, lY1);
  131. }
  132. //
  133. // Determine the column when adding the B delta.
  134. //
  135. lX1 = lX + lB;
  136. //
  137. // If this column is within the clipping region, then draw a pixel
  138. // at that position.
  139. //
  140. if((lX1 >= pContext->sClipRegion.sXMin) &&
  141. (lX1 <= pContext->sClipRegion.sXMax))
  142. {
  143. GrPixelDraw(pContext, lX1, lY1);
  144. }
  145. }
  146. //
  147. // Only draw the complementary pixels if the A and B deltas are
  148. // different (otherwise, they describe the same set of pixels).
  149. //
  150. if(lA != lB)
  151. {
  152. //
  153. // Determine the row when subtracting the B delta.
  154. //
  155. lY1 = lY - lB;
  156. //
  157. // See if this row is within the clipping region.
  158. //
  159. if((lY1 >= pContext->sClipRegion.sYMin) &&
  160. (lY1 <= pContext->sClipRegion.sYMax))
  161. {
  162. //
  163. // Determine the column when subtracting the a delta.
  164. //
  165. lX1 = lX - lA;
  166. //
  167. // If this column is within the clipping region, then draw a
  168. // pixel at that position.
  169. //
  170. if((lX1 >= pContext->sClipRegion.sXMin) &&
  171. (lX1 <= pContext->sClipRegion.sXMax))
  172. {
  173. GrPixelDraw(pContext, lX1, lY1);
  174. }
  175. //
  176. // Only draw the mirrored pixel if the A delta is non-zero
  177. // (otherwise, it will be the same pixel).
  178. //
  179. if(lA != 0)
  180. {
  181. //
  182. // Determine the column when adding the A delta.
  183. //
  184. lX1 = lX + lA;
  185. //
  186. // If this column is within the clipping region, then draw
  187. // a pixel at that position.
  188. //
  189. if((lX1 >= pContext->sClipRegion.sXMin) &&
  190. (lX1 <= pContext->sClipRegion.sXMax))
  191. {
  192. GrPixelDraw(pContext, lX1, lY1);
  193. }
  194. }
  195. }
  196. //
  197. // Determine the row when adding the B delta.
  198. //
  199. lY1 = lY + lB;
  200. //
  201. // See if this row is within the clipping region.
  202. //
  203. if((lY1 >= pContext->sClipRegion.sYMin) &&
  204. (lY1 <= pContext->sClipRegion.sYMax))
  205. {
  206. //
  207. // Determine the column when subtracting the A delta.
  208. //
  209. lX1 = lX - lA;
  210. //
  211. // If this column is within the clipping region, then draw a
  212. // pixel at that position.
  213. //
  214. if((lX1 >= pContext->sClipRegion.sXMin) &&
  215. (lX1 <= pContext->sClipRegion.sXMax))
  216. {
  217. GrPixelDraw(pContext, lX1, lY1);
  218. }
  219. //
  220. // Only draw the mirrored pixel if the A delta is non-zero
  221. // (otherwise, it will be the same pixel).
  222. //
  223. if(lA != 0)
  224. {
  225. //
  226. // Determine the column when adding the A delta.
  227. //
  228. lX1 = lX + lA;
  229. //
  230. // If this column is within the clipping region, then draw
  231. // a pixel at that position.
  232. //
  233. if((lX1 >= pContext->sClipRegion.sXMin) &&
  234. (lX1 <= pContext->sClipRegion.sXMax))
  235. {
  236. GrPixelDraw(pContext, lX1, lY1);
  237. }
  238. }
  239. }
  240. }
  241. //
  242. // See if the error term is negative.
  243. //
  244. if(lD < 0)
  245. {
  246. //
  247. // Since the error term is negative, adjust it based on a move in
  248. // only the A delta.
  249. //
  250. lD += (4 * lA) + 6;
  251. }
  252. else
  253. {
  254. //
  255. // Since the error term is non-negative, adjust it based on a move
  256. // in both the A and B deltas.
  257. //
  258. lD += (4 * (lA - lB)) + 10;
  259. //
  260. // Decrement the B delta.
  261. //
  262. lB -= 1;
  263. }
  264. //
  265. // Increment the A delta.
  266. //
  267. lA++;
  268. }
  269. }
  270. //*****************************************************************************
  271. //
  272. //! Draws a filled circle.
  273. //!
  274. //! \param pContext is a pointer to the drawing context to use.
  275. //! \param lX is the X coordinate of the center of the circle.
  276. //! \param lY is the Y coordinate of the center of the circle.
  277. //! \param lRadius is the radius of the circle.
  278. //!
  279. //! This function draws a filled circle, utilizing the Bresenham circle drawing
  280. //! algorithm. The extent of the circle is from \e lX - \e lRadius to \e lX +
  281. //! \e lRadius and \e lY - \e lRadius to \e lY + \e lRadius, inclusive.
  282. //!
  283. //! \return None.
  284. //
  285. //*****************************************************************************
  286. void
  287. GrCircleFill(const tContext *pContext, int lX, int lY, int lRadius)
  288. {
  289. int lA, lB, lD, lX1, lX2, lY1;
  290. //
  291. // Check the arguments.
  292. //
  293. ASSERT(pContext);
  294. //
  295. // Initialize the variables that control the Bresenham circle drawing
  296. // algorithm.
  297. //
  298. lA = 0;
  299. lB = lRadius;
  300. lD = 3 - (2 * lRadius);
  301. //
  302. // Loop until the A delta is greater than the B delta, meaning that the
  303. // entire circle has been filled.
  304. //
  305. while(lA <= lB)
  306. {
  307. //
  308. // Determine the row when subtracting the A delta.
  309. //
  310. lY1 = lY - lA;
  311. //
  312. // See if this row is within the clipping region.
  313. //
  314. if((lY1 >= pContext->sClipRegion.sYMin) &&
  315. (lY1 <= pContext->sClipRegion.sYMax))
  316. {
  317. //
  318. // Determine the column when subtracting the B delta, and move it
  319. // to the left edge of the clipping region if it is to the left of
  320. // the clipping region.
  321. //
  322. lX1 = lX - lB;
  323. if(lX1 < pContext->sClipRegion.sXMin)
  324. {
  325. lX1 = pContext->sClipRegion.sXMin;
  326. }
  327. //
  328. // Determine the column when adding the B delta, and move it to the
  329. // right edge of the clipping region if it is to the right of the
  330. // clipping region.
  331. //
  332. lX2 = lX + lB;
  333. if(lX2 > pContext->sClipRegion.sXMax)
  334. {
  335. lX2 = pContext->sClipRegion.sXMax;
  336. }
  337. //
  338. // Draw a horizontal line if this portion of the circle is within
  339. // the clipping region.
  340. //
  341. if(lX1 <= lX2)
  342. {
  343. GrLineDrawH(pContext, lX1, lX2, lY1);
  344. }
  345. }
  346. //
  347. // Determine the row when adding the A delta.
  348. //
  349. lY1 = lY + lA;
  350. //
  351. // See if this row is within the clipping region, and the A delta is
  352. // not zero (otherwise, this describes the same row of the circle).
  353. //
  354. if((lY1 >= pContext->sClipRegion.sYMin) &&
  355. (lY1 <= pContext->sClipRegion.sYMax) &&
  356. (lA != 0))
  357. {
  358. //
  359. // Determine the column when subtracting the B delta, and move it
  360. // to the left edge of the clipping region if it is to the left of
  361. // the clipping region.
  362. //
  363. lX1 = lX - lB;
  364. if(lX1 < pContext->sClipRegion.sXMin)
  365. {
  366. lX1 = pContext->sClipRegion.sXMin;
  367. }
  368. //
  369. // Determine the column when adding the B delta, and move it to the
  370. // right edge of the clipping region if it is to the right of the
  371. // clipping region.
  372. //
  373. lX2 = lX + lB;
  374. if(lX2 > pContext->sClipRegion.sXMax)
  375. {
  376. lX2 = pContext->sClipRegion.sXMax;
  377. }
  378. //
  379. // Draw a horizontal line if this portion of the circle is within
  380. // the clipping region.
  381. //
  382. if(lX1 <= lX2)
  383. {
  384. GrLineDrawH(pContext, lX1, lX2, lY1);
  385. }
  386. }
  387. //
  388. // Only draw the complementary lines if the B delta is about to change
  389. // and the A and B delta are different (otherwise, they describe the
  390. // same set of pixels).
  391. //
  392. if((lD >= 0) && (lA != lB))
  393. {
  394. //
  395. // Determine the row when subtracting the B delta.
  396. //
  397. lY1 = lY - lB;
  398. //
  399. // See if this row is within the clipping region.
  400. //
  401. if((lY1 >= pContext->sClipRegion.sYMin) &&
  402. (lY1 <= pContext->sClipRegion.sYMax))
  403. {
  404. //
  405. // Determine the column when subtracting the A delta, and move
  406. // it to the left edge of the clipping regino if it is to the
  407. // left of the clipping region.
  408. //
  409. lX1 = lX - lA;
  410. if(lX1 < pContext->sClipRegion.sXMin)
  411. {
  412. lX1 = pContext->sClipRegion.sXMin;
  413. }
  414. //
  415. // Determine the column when adding the A delta, and move it to
  416. // the right edge of the clipping region if it is to the right
  417. // of the clipping region.
  418. //
  419. lX2 = lX + lA;
  420. if(lX2 > pContext->sClipRegion.sXMax)
  421. {
  422. lX2 = pContext->sClipRegion.sXMax;
  423. }
  424. //
  425. // Draw a horizontal line if this portion of the circle is
  426. // within the clipping region.
  427. //
  428. if(lX1 <= lX2)
  429. {
  430. GrLineDrawH(pContext, lX1, lX2, lY1);
  431. }
  432. }
  433. //
  434. // Determine the row when adding the B delta.
  435. //
  436. lY1 = lY + lB;
  437. //
  438. // See if this row is within the clipping region.
  439. //
  440. if((lY1 >= pContext->sClipRegion.sYMin) &&
  441. (lY1 <= pContext->sClipRegion.sYMax))
  442. {
  443. //
  444. // Determine the column when subtracting the A delta, and move
  445. // it to the left edge of the clipping region if it is to the
  446. // left of the clipping region.
  447. //
  448. lX1 = lX - lA;
  449. if(lX1 < pContext->sClipRegion.sXMin)
  450. {
  451. lX1 = pContext->sClipRegion.sXMin;
  452. }
  453. //
  454. // Determine the column when adding the A delta, and move it to
  455. // the right edge of the clipping region if it is to the right
  456. // of the clipping region.
  457. //
  458. lX2 = lX + lA;
  459. if(lX2 > pContext->sClipRegion.sXMax)
  460. {
  461. lX2 = pContext->sClipRegion.sXMax;
  462. }
  463. //
  464. // Draw a horizontal line if this portion of the circle is
  465. // within the clipping region.
  466. //
  467. if(lX1 <= lX2)
  468. {
  469. GrLineDrawH(pContext, lX1, lX2, lY1);
  470. }
  471. }
  472. }
  473. //
  474. // See if the error term is negative.
  475. //
  476. if(lD < 0)
  477. {
  478. //
  479. // Since the error term is negative, adjust it based on a move in
  480. // only the A delta.
  481. //
  482. lD += (4 * lA) + 6;
  483. }
  484. else
  485. {
  486. //
  487. // Since the error term is non-negative, adjust it based on a move
  488. // in both the A and B deltas.
  489. //
  490. lD += (4 * (lA - lB)) + 10;
  491. //
  492. // Decrement the B delta.
  493. //
  494. lB -= 1;
  495. }
  496. //
  497. // Increment the A delta.
  498. //
  499. lA++;
  500. }
  501. }
  502. //*****************************************************************************
  503. //
  504. // Close the Doxygen group.
  505. //! @}
  506. //
  507. //*****************************************************************************