selectionfuncs.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  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 <limits.h>
  11. #include <stddef.h>
  12. #include <util/alloc.h>
  13. #include "selectionfuncs.h"
  14. #include "topviewfuncs.h"
  15. #include "smyrna_utils.h"
  16. static void select_node(Agraph_t* g,Agnode_t* obj,int reverse)
  17. {
  18. Agsym_t* sel_attr = GN_selected(g);
  19. if(!sel_attr)
  20. sel_attr = GN_selected(g) = agattr(g, AGNODE,"selected","0");
  21. if(!reverse)
  22. {
  23. agxset(obj,sel_attr,"1");
  24. ND_selected(obj) = 1;
  25. }
  26. else
  27. {
  28. if(ND_selected(obj)==1)
  29. {
  30. agxset(obj,sel_attr,"0");
  31. ND_selected(obj) = 0;
  32. ND_printLabel(obj) = 0;
  33. }
  34. else
  35. {
  36. agxset(obj,sel_attr,"1");
  37. ND_selected(obj) = 1;
  38. }
  39. }
  40. }
  41. static void select_edge(Agraph_t* g,Agedge_t* obj,int reverse)
  42. {
  43. Agsym_t* sel_attr = GE_selected(g);
  44. if (!sel_attr)
  45. sel_attr = GE_selected(g) = agattr(g, AGEDGE,"selected","0");
  46. if (!reverse)
  47. {
  48. agxset(obj,sel_attr,"1");
  49. ED_selected(obj) = 1;
  50. }
  51. else
  52. {
  53. if (ED_selected(obj) == 1)
  54. {
  55. agxset(obj,sel_attr,"0");
  56. ED_selected(obj) = 0;
  57. }
  58. else
  59. {
  60. agxset(obj,sel_attr,"1");
  61. ED_selected(obj) = 1;
  62. }
  63. }
  64. }
  65. static void pick_objects_in_rect(Agraph_t *g, float x1, float y1, float x2,
  66. float y2) {
  67. Agnode_t *v;
  68. Agedge_t *e;
  69. glCompPoint posT;
  70. glCompPoint posH;
  71. glCompPoint posN;
  72. for (v = agfstnode(g); v; v = agnxtnode(g, v))
  73. {
  74. if (view->Topview->sel.selectNodes) {
  75. posN = ND_A(v);
  76. if(!ND_visible(v))
  77. continue;
  78. if(is_point_in_rectangle(posN.x,posN.y,x1,y1,x2-x1,y2-y1) )
  79. select_node(g,v,0);
  80. }
  81. if (view->Topview->sel.selectEdges) {
  82. for (e = agfstout(g, v); e; e = agnxtout(g, e))
  83. {
  84. posT = ED_posTail(e);
  85. posH = ED_posHead(e);
  86. if(is_point_in_rectangle(posT.x,posT.y,x1,y1,x2-x1,y2-y1))
  87. if(is_point_in_rectangle(posH.x,posH.y,x1,y1,x2-x1,y2-y1))
  88. select_edge(g,e,0);
  89. }
  90. }
  91. }
  92. }
  93. static void* pick_object(Agraph_t* g,glCompPoint p)
  94. {
  95. Agnode_t *v;
  96. Agedge_t *e;
  97. glCompPoint posT;
  98. glCompPoint posH;
  99. glCompPoint posN;
  100. int defaultNodeShape;
  101. float dist = FLT_MAX;
  102. float nd; // node distance to point
  103. float ed; // edge distance to point
  104. float nodeSize=0;
  105. void *rv = NULL;
  106. defaultNodeShape=getAttrBool(g,g,"defaultnodeshape",0);
  107. if(defaultNodeShape==0)
  108. nodeSize=GetOGLDistance(view->nodeScale*view->Topview->fitin_zoom/view->zoom);
  109. for (v = agfstnode(g); v; v = agnxtnode(g, v))
  110. {
  111. if(!ND_visible(v))
  112. continue;
  113. posN = ND_A(v);
  114. if(defaultNodeShape==1)
  115. {
  116. nodeSize = ND_size(v);
  117. }
  118. nd=distBetweenPts(posN,p,nodeSize);
  119. if( nd < dist )
  120. {
  121. rv=v;dist=nd;
  122. }
  123. for (e = agfstout(g, v); e; e = agnxtout(g, e))
  124. {
  125. posT = ED_posTail(e);
  126. posH = ED_posHead(e);
  127. ed=point_to_lineseg_dist(p, posT,posH);
  128. if( ed < dist ) {rv=e;dist=ed;}
  129. }
  130. }
  131. return rv;
  132. }
  133. void pick_object_xyz(Agraph_t *g, topview *t, float x, float y, float z) {
  134. glCompPoint p;
  135. void* a;
  136. p.x=x;p.y=y;p.z=z;
  137. a=pick_object(g,p);
  138. if (!a)
  139. return;
  140. if(agobjkind(a)==AGNODE)
  141. {
  142. select_node(g,a,1);
  143. ND_printLabel((Agnode_t*)a) = 1;
  144. cacheSelectedNodes(g,t);
  145. }
  146. if(agobjkind(a)==AGEDGE)
  147. {
  148. select_edge(g,a,1);
  149. cacheSelectedEdges(g,t);
  150. }
  151. }
  152. void pick_objects_rect(Agraph_t* g)
  153. {
  154. float x1;
  155. float y1;
  156. float x2;
  157. float y2;
  158. if(view->mouse.GLfinalPos.x > view->mouse.GLinitPos.x)
  159. {
  160. x1=view->mouse.GLinitPos.x;
  161. x2=view->mouse.GLfinalPos.x;
  162. }
  163. else
  164. {
  165. x2=view->mouse.GLinitPos.x;
  166. x1=view->mouse.GLfinalPos.x;
  167. }
  168. if(view->mouse.GLfinalPos.y > view->mouse.GLinitPos.y)
  169. {
  170. y1=view->mouse.GLinitPos.y;
  171. y2=view->mouse.GLfinalPos.y;
  172. }
  173. else
  174. {
  175. y2=view->mouse.GLinitPos.y;
  176. y1=view->mouse.GLfinalPos.y;
  177. }
  178. pick_objects_in_rect(g,x1,y1,x2,y2);
  179. cacheSelectedNodes(g,view->Topview);
  180. cacheSelectedEdges(g,view->Topview);
  181. }
  182. void deselect_all(Agraph_t* g)
  183. {
  184. Agnode_t *v;
  185. Agedge_t *e;
  186. Agsym_t* nsel_attr = GN_selected(g);
  187. Agsym_t* esel_attr = GE_selected(g);
  188. if(!nsel_attr)
  189. nsel_attr = GN_selected(g) = agattr(g, AGNODE,"selected","0");
  190. if(!esel_attr)
  191. esel_attr = GE_selected(g) = agattr(g, AGEDGE,"selected","0");
  192. for (v = agfstnode(g); v; v = agnxtnode(g, v))
  193. {
  194. agxset(v,nsel_attr,"0");
  195. ND_selected(v) = 0;
  196. ND_printLabel(v) = 0;
  197. for (e = agfstout(g, v); e; e = agnxtout(g, e))
  198. {
  199. agxset(e,esel_attr,"0");
  200. ED_selected(e) = 0;
  201. }
  202. }
  203. cacheSelectedNodes(g,view->Topview);
  204. cacheSelectedEdges(g,view->Topview);
  205. }
  206. static int close_poly(glCompPoly_t *selPoly, glCompPoint pt) {
  207. /* int i=0; */
  208. const float EPS = GetOGLDistance(3.0f);
  209. if (glCompPoly_size(selPoly) < 2)
  210. return 0;
  211. if (glCompPoly_front(selPoly)->x - pt.x < EPS &&
  212. glCompPoly_front(selPoly)->y - pt.y < EPS)
  213. return 1;
  214. return 0;
  215. }
  216. static void select_polygon(Agraph_t *g, glCompPoly_t *selPoly) {
  217. Agnode_t *v;
  218. glCompPoint posN;
  219. for (v = agfstnode(g); v; v = agnxtnode(g, v))
  220. {
  221. posN = ND_A(v);
  222. if(point_in_polygon(selPoly,posN))
  223. select_node(g,v,0);
  224. }
  225. cacheSelectedNodes(g,view->Topview);
  226. }
  227. void add_selpoly(Agraph_t *g, glCompPoly_t *selPoly, glCompPoint pt) {
  228. if(!close_poly(selPoly,pt))
  229. {
  230. glCompPoly_append(selPoly, (glCompPoint){.x = pt.x, .y = pt.y});
  231. }
  232. else
  233. {
  234. select_polygon (g,selPoly);
  235. glCompPoly_free(selPoly);
  236. }
  237. }