edges.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*************************************************************************
  2. * Copyright (c) 2011 AT&T Intellectual Property
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * https://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: Details at https://graphviz.org
  9. *************************************************************************/
  10. #include <neatogen/neato.h>
  11. #include <neatogen/mem.h>
  12. #include <neatogen/info.h>
  13. #include <neatogen/edges.h>
  14. #include <math.h>
  15. double pxmin, pxmax, pymin, pymax; /* clipping window */
  16. static Freelist efl;
  17. void edgeinit(void)
  18. {
  19. freeinit(&efl, sizeof(Edge));
  20. }
  21. Edge *gvbisect(Site * s1, Site * s2)
  22. {
  23. double dx, dy, adx, ady;
  24. Edge *newedge;
  25. newedge = getfree(&efl);
  26. newedge->reg[0] = s1;
  27. newedge->reg[1] = s2;
  28. ref(s1);
  29. ref(s2);
  30. newedge->ep[0] = NULL;
  31. newedge->ep[1] = NULL;
  32. dx = s2->coord.x - s1->coord.x;
  33. dy = s2->coord.y - s1->coord.y;
  34. adx = fabs(dx);
  35. ady = fabs(dy);
  36. newedge->c =
  37. s1->coord.x * dx + s1->coord.y * dy + (dx * dx + dy * dy) * 0.5;
  38. if (adx > ady) {
  39. newedge->a = 1.0;
  40. newedge->b = dy / dx;
  41. newedge->c /= dx;
  42. } else {
  43. newedge->b = 1.0;
  44. newedge->a = dx / dy;
  45. newedge->c /= dy;
  46. };
  47. return (newedge);
  48. }
  49. static void doSeg(Edge * e, double x1, double y1, double x2, double y2)
  50. {
  51. addVertex(e->reg[0], x1, y1);
  52. addVertex(e->reg[0], x2, y2);
  53. addVertex(e->reg[1], x1, y1);
  54. addVertex(e->reg[1], x2, y2);
  55. }
  56. void clip_line(Edge * e)
  57. {
  58. Site *s1, *s2;
  59. double x1, x2, y1, y2;
  60. if (e->a == 1.0 && e->b >= 0.0) {
  61. s1 = e->ep[1];
  62. s2 = e->ep[0];
  63. } else {
  64. s1 = e->ep[0];
  65. s2 = e->ep[1];
  66. }
  67. if (e->a == 1.0) {
  68. if (s1 != NULL) {
  69. y1 = s1->coord.y;
  70. if (y1 > pymax)
  71. return;
  72. else if (y1 >= pymin)
  73. x1 = s1->coord.x;
  74. else {
  75. y1 = pymin;
  76. x1 = e->c - e->b * y1;
  77. }
  78. } else {
  79. y1 = pymin;
  80. x1 = e->c - e->b * y1;
  81. }
  82. if (s2 != NULL) {
  83. y2 = s2->coord.y;
  84. if (y2 < pymin)
  85. return;
  86. else if (y2 <= pymax)
  87. x2 = s2->coord.x;
  88. else {
  89. y2 = pymax;
  90. x2 = e->c - e->b * y2;
  91. }
  92. } else {
  93. y2 = pymax;
  94. x2 = e->c - e->b * y2;
  95. }
  96. if ((x1 > pxmax && x2 > pxmax) || (x1 < pxmin && x2 < pxmin))
  97. return;
  98. if (x1 > pxmax) {
  99. x1 = pxmax;
  100. y1 = (e->c - x1) / e->b;
  101. };
  102. if (x1 < pxmin) {
  103. x1 = pxmin;
  104. y1 = (e->c - x1) / e->b;
  105. };
  106. if (x2 > pxmax) {
  107. x2 = pxmax;
  108. y2 = (e->c - x2) / e->b;
  109. };
  110. if (x2 < pxmin) {
  111. x2 = pxmin;
  112. y2 = (e->c - x2) / e->b;
  113. };
  114. } else {
  115. if (s1 != NULL) {
  116. x1 = s1->coord.x;
  117. if (x1 > pxmax)
  118. return;
  119. else if (x1 >= pxmin)
  120. y1 = s1->coord.y;
  121. else {
  122. x1 = pxmin;
  123. y1 = e->c - e->a * x1;
  124. }
  125. } else {
  126. x1 = pxmin;
  127. y1 = e->c - e->a * x1;
  128. }
  129. if (s2 != NULL) {
  130. x2 = s2->coord.x;
  131. if (x2 < pxmin)
  132. return;
  133. else if (x2 <= pxmax)
  134. y2 = s2->coord.y;
  135. else {
  136. x2 = pxmax;
  137. y2 = e->c - e->a * x2;
  138. }
  139. } else {
  140. x2 = pxmax;
  141. y2 = e->c - e->a * x2;
  142. }
  143. if ((y1 > pymax && y2 > pymax) || (y1 < pymin && y2 < pymin))
  144. return;
  145. if (y1 > pymax) {
  146. y1 = pymax;
  147. x1 = (e->c - y1) / e->a;
  148. };
  149. if (y1 < pymin) {
  150. y1 = pymin;
  151. x1 = (e->c - y1) / e->a;
  152. };
  153. if (y2 > pymax) {
  154. y2 = pymax;
  155. x2 = (e->c - y2) / e->a;
  156. };
  157. if (y2 < pymin) {
  158. y2 = pymin;
  159. x2 = (e->c - y2) / e->a;
  160. };
  161. }
  162. doSeg(e, x1, y1, x2, y2);
  163. }
  164. void endpoint(Edge * e, int lr, Site * s)
  165. {
  166. e->ep[lr] = s;
  167. ref(s);
  168. if (e->ep[re - lr] == NULL)
  169. return;
  170. clip_line(e);
  171. deref(e->reg[le]);
  172. deref(e->reg[re]);
  173. makefree(e, &efl);
  174. }