ortho.c 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556
  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. /* TODO:
  11. * In dot, prefer bottom or top routing
  12. * In general, prefer closest side to closest side routing.
  13. * Edge labels
  14. * Ports/compass points
  15. * ordering attribute
  16. * Weights on edges in nodes
  17. * Edge concentrators?
  18. */
  19. #include "config.h"
  20. #define DEBUG
  21. #include <assert.h>
  22. #include <float.h>
  23. #include <math.h>
  24. #include <stdbool.h>
  25. #include <stddef.h>
  26. #include <ortho/maze.h>
  27. #include <ortho/fPQ.h>
  28. #include <ortho/ortho.h>
  29. #include <common/geomprocs.h>
  30. #include <common/globals.h>
  31. #include <common/render.h>
  32. #include <common/pointset.h>
  33. #include <util/alloc.h>
  34. #include <util/exit.h>
  35. #include <util/unused.h>
  36. typedef struct {
  37. int d;
  38. Agedge_t* e;
  39. } epair_t;
  40. #ifdef DEBUG
  41. #define DEBUG_FN /* nothing */
  42. #else
  43. #define DEBUG_FN UNUSED
  44. #endif
  45. static DEBUG_FN void emitSearchGraph(FILE *fp, sgraph *sg);
  46. static DEBUG_FN void emitGraph(FILE *fp, maze *mp, size_t n_edges,
  47. route *route_list, epair_t[]);
  48. #ifdef DEBUG
  49. int odb_flags;
  50. #endif
  51. #define CELL(n) ((cell*)ND_alg(n))
  52. #define MID(a,b) (((a)+(b))/2.0)
  53. #define SC 1
  54. /* cellOf:
  55. * Given 2 snodes sharing a cell, return the cell.
  56. */
  57. static cell*
  58. cellOf (snode* p, snode* q)
  59. {
  60. cell* cp = p->cells[0];
  61. if (cp == q->cells[0] || cp == q->cells[1]) return cp;
  62. else return p->cells[1];
  63. }
  64. static pointf
  65. midPt (cell* cp)
  66. {
  67. pointf p;
  68. p.x = MID(cp->bb.LL.x,cp->bb.UR.x);
  69. p.y = MID(cp->bb.LL.y,cp->bb.UR.y);
  70. return p;
  71. }
  72. /* sidePt:
  73. * Given a cell and an snode on one of its sides, return the
  74. * midpoint of the side.
  75. */
  76. static pointf
  77. sidePt (snode* ptr, cell* cp)
  78. {
  79. pointf pt;
  80. if (cp == ptr->cells[1]) {
  81. if (ptr->isVert) {
  82. pt.x = cp->bb.LL.x;
  83. pt.y = MID(cp->bb.LL.y,cp->bb.UR.y);
  84. }
  85. else {
  86. pt.x = MID(cp->bb.LL.x,cp->bb.UR.x);
  87. pt.y = cp->bb.LL.y;
  88. }
  89. }
  90. else {
  91. if (ptr->isVert) {
  92. pt.x = cp->bb.UR.x;
  93. pt.y = MID(cp->bb.LL.y,cp->bb.UR.y);
  94. }
  95. else {
  96. pt.x = MID(cp->bb.LL.x,cp->bb.UR.x);
  97. pt.y = cp->bb.UR.y;
  98. }
  99. }
  100. return pt;
  101. }
  102. /* setSet:
  103. * Initialize and normalize segments.
  104. * p1 stores smaller value
  105. * Assume b1 != b2
  106. */
  107. static void
  108. setSeg (segment* sp, bool dir, double fix, double b1, double b2, int l1, int l2)
  109. {
  110. sp->isVert = dir;
  111. sp->comm_coord = fix;
  112. if (b1 < b2) {
  113. sp->p.p1 = b1;
  114. sp->p.p2 = b2;
  115. sp->l1 = l1;
  116. sp->l2 = l2;
  117. }
  118. else {
  119. sp->p.p2 = b1;
  120. sp->p.p1 = b2;
  121. sp->l2 = l1;
  122. sp->l1 = l2;
  123. }
  124. }
  125. /* Convert route in shortest path graph to route
  126. * of segments. This records the first and last cells,
  127. * plus cells where the path bends.
  128. * Note that the shortest path will always have at least 4 nodes:
  129. * the two dummy nodes representing the center of the two real nodes,
  130. * and the two nodes on the boundary of the two real nodes.
  131. */
  132. static route
  133. convertSPtoRoute (sgraph* g, snode* fst, snode* lst)
  134. {
  135. route rte;
  136. snode* ptr;
  137. snode* next;
  138. snode* prev; /* node in shortest path just previous to next */
  139. size_t sz = 0;
  140. cell* cp;
  141. cell* ncp;
  142. segment seg;
  143. double fix, b1, b2;
  144. int l1, l2;
  145. pointf bp1, bp2, prevbp = {0.0,0.0}; /* bend points */
  146. /* count no. of nodes in shortest path */
  147. for (ptr = fst; ptr; ptr = N_DAD(ptr)) sz++;
  148. rte.n = 0;
  149. assert(sz >= 2);
  150. rte.segs = gv_calloc(sz - 2, sizeof(segment)); /* at most sz-2 segments */
  151. seg.prev = seg.next = 0;
  152. ptr = prev = N_DAD(fst);
  153. next = N_DAD(ptr);
  154. if (IsNode(ptr->cells[0]))
  155. cp = ptr->cells[1];
  156. else
  157. cp = ptr->cells[0];
  158. bp1 = sidePt (ptr, cp);
  159. while (N_DAD(next)!=NULL) {
  160. ncp = cellOf (prev, next);
  161. updateWts (g, ncp, N_EDGE(ptr));
  162. /* add seg if path bends or at end */
  163. if (ptr->isVert != next->isVert || N_DAD(next) == lst) {
  164. if (ptr->isVert != next->isVert)
  165. bp2 = midPt (ncp);
  166. else
  167. bp2 = sidePt(next, ncp);
  168. if (ptr->isVert) { /* horizontal segment */
  169. if (ptr == N_DAD(fst)) l1 = B_NODE;
  170. else if (prevbp.y > bp1.y) l1 = B_UP;
  171. else l1 = B_DOWN;
  172. if (ptr->isVert != next->isVert) {
  173. if (next->cells[0] == ncp) l2 = B_UP;
  174. else l2 = B_DOWN;
  175. }
  176. else l2 = B_NODE;
  177. fix = cp->bb.LL.y;
  178. b1 = cp->bb.LL.x;
  179. b2 = ncp->bb.LL.x;
  180. }
  181. else { /* vertical segment */
  182. if (ptr == N_DAD(fst)) l1 = B_NODE;
  183. else if (prevbp.x > bp1.x) l1 = B_RIGHT;
  184. else l1 = B_LEFT;
  185. if (ptr->isVert != next->isVert) {
  186. if (next->cells[0] == ncp) l2 = B_RIGHT;
  187. else l2 = B_LEFT;
  188. }
  189. else l2 = B_NODE;
  190. fix = cp->bb.LL.x;
  191. b1 = cp->bb.LL.y;
  192. b2 = ncp->bb.LL.y;
  193. }
  194. setSeg (&seg, !ptr->isVert, fix, b1, b2, l1, l2);
  195. rte.segs[rte.n++] = seg;
  196. cp = ncp;
  197. prevbp = bp1;
  198. bp1 = bp2;
  199. if (ptr->isVert != next->isVert && N_DAD(next) == lst) {
  200. bp2 = sidePt(next, ncp);
  201. l2 = B_NODE;
  202. if (next->isVert) { /* horizontal segment */
  203. if (prevbp.y > bp1.y) l1 = B_UP;
  204. else l1 = B_DOWN;
  205. fix = cp->bb.LL.y;
  206. b1 = cp->bb.LL.x;
  207. b2 = ncp->bb.LL.x;
  208. }
  209. else {
  210. if (prevbp.x > bp1.x) l1 = B_RIGHT;
  211. else l1 = B_LEFT;
  212. fix = cp->bb.LL.x;
  213. b1 = cp->bb.LL.y;
  214. b2 = ncp->bb.LL.y;
  215. }
  216. setSeg (&seg, !next->isVert, fix, b1, b2, l1, l2);
  217. rte.segs[rte.n++] = seg;
  218. }
  219. ptr = next;
  220. }
  221. prev = next;
  222. next = N_DAD(next);
  223. }
  224. rte.segs = gv_recalloc(rte.segs, sz - 2, rte.n, sizeof(segment));
  225. for (size_t i=0; i<rte.n; i++) {
  226. if (i > 0)
  227. rte.segs[i].prev = rte.segs + (i-1);
  228. if (i < rte.n-1)
  229. rte.segs[i].next = rte.segs + (i+1);
  230. }
  231. return rte;
  232. }
  233. typedef struct {
  234. Dtlink_t link;
  235. double v;
  236. Dt_t* chans;
  237. } chanItem;
  238. static void freeChannel(void *chan) {
  239. channel *cp = chan;
  240. free_graph (cp->G);
  241. seg_list_free(&cp->seg_list);
  242. free (cp);
  243. }
  244. static void freeChanItem(void *item) {
  245. chanItem *cp = item;
  246. dtclose (cp->chans);
  247. free (cp);
  248. }
  249. /* chancmpid:
  250. * Compare intervals. Two intervals are equal if one contains
  251. * the other. Otherwise, the one with the smaller p1 value is
  252. * less.
  253. * This combines two separate functions into one. Channels are
  254. * disjoint, so we really only need to key on p1.
  255. * When searching for a channel containing a segment, we rely on
  256. * interval containment to return the correct channel.
  257. */
  258. static int chancmpid(void *k1, void *k2) {
  259. const paird *key1 = k1;
  260. const paird *key2 = k2;
  261. if (key1->p1 > key2->p1) {
  262. if (key1->p2 <= key2->p2) return 0;
  263. else return 1;
  264. }
  265. else if (key1->p1 < key2->p1) {
  266. if (key1->p2 >= key2->p2) return 0;
  267. else return -1;
  268. }
  269. else return 0;
  270. }
  271. static int dcmpid(void *k1, void *k2) {
  272. const double *key1 = k1;
  273. const double *key2 = k2;
  274. if (*key1 > *key2) return 1;
  275. else if (*key1 < *key2) return -1;
  276. else return 0;
  277. }
  278. static Dtdisc_t chanDisc = {
  279. offsetof(channel,p),
  280. sizeof(paird),
  281. offsetof(channel,link),
  282. 0,
  283. freeChannel,
  284. chancmpid,
  285. };
  286. static Dtdisc_t chanItemDisc = {
  287. offsetof(chanItem,v),
  288. sizeof(double),
  289. offsetof(chanItem,link),
  290. 0,
  291. freeChanItem,
  292. dcmpid,
  293. };
  294. static void
  295. addChan (Dt_t* chdict, channel* cp, double j)
  296. {
  297. chanItem* subd = dtmatch (chdict, &j);
  298. if (!subd) {
  299. subd = gv_alloc(sizeof(chanItem));
  300. subd->v = j;
  301. subd->chans = dtopen (&chanDisc, Dtoset);
  302. dtinsert (chdict, subd);
  303. }
  304. dtinsert (subd->chans, cp);
  305. }
  306. static Dt_t*
  307. extractHChans (maze* mp)
  308. {
  309. int i;
  310. snode* np;
  311. Dt_t* hchans = dtopen (&chanItemDisc, Dtoset);
  312. for (i = 0; i < mp->ncells; i++) {
  313. channel* chp;
  314. cell* cp = mp->cells+i;
  315. cell* nextcp;
  316. if (IsHScan(cp)) continue;
  317. /* move left */
  318. while ((np = cp->sides[M_LEFT]) && (nextcp = np->cells[0]) &&
  319. !IsNode(nextcp)) {
  320. cp = nextcp;
  321. }
  322. chp = gv_alloc(sizeof(channel));
  323. chp->cp = cp;
  324. chp->p.p1 = cp->bb.LL.x;
  325. /* move right */
  326. cp->flags |= MZ_HSCAN;
  327. while ((np = cp->sides[M_RIGHT]) && (nextcp = np->cells[1]) &&
  328. !IsNode(nextcp)) {
  329. cp = nextcp;
  330. cp->flags |= MZ_HSCAN;
  331. }
  332. chp->p.p2 = cp->bb.UR.x;
  333. addChan (hchans, chp, chp->cp->bb.LL.y);
  334. }
  335. return hchans;
  336. }
  337. static Dt_t*
  338. extractVChans (maze* mp)
  339. {
  340. int i;
  341. snode* np;
  342. Dt_t* vchans = dtopen (&chanItemDisc, Dtoset);
  343. for (i = 0; i < mp->ncells; i++) {
  344. channel* chp;
  345. cell* cp = mp->cells+i;
  346. cell* nextcp;
  347. if (IsVScan(cp)) continue;
  348. /* move down */
  349. while ((np = cp->sides[M_BOTTOM]) && (nextcp = np->cells[0]) &&
  350. !IsNode(nextcp)) {
  351. cp = nextcp;
  352. }
  353. chp = gv_alloc(sizeof(channel));
  354. chp->cp = cp;
  355. chp->p.p1 = cp->bb.LL.y;
  356. /* move up */
  357. cp->flags |= MZ_VSCAN;
  358. while ((np = cp->sides[M_TOP]) && (nextcp = np->cells[1]) &&
  359. !IsNode(nextcp)) {
  360. cp = nextcp;
  361. cp->flags |= MZ_VSCAN;
  362. }
  363. chp->p.p2 = cp->bb.UR.y;
  364. addChan (vchans, chp, chp->cp->bb.LL.x);
  365. }
  366. return vchans;
  367. }
  368. static void
  369. insertChan (channel* chan, segment* seg)
  370. {
  371. seg->ind_no = seg_list_size(&chan->seg_list);
  372. seg_list_append(&chan->seg_list, seg);
  373. }
  374. static channel*
  375. chanSearch (Dt_t* chans, segment* seg)
  376. {
  377. channel* cp;
  378. chanItem* chani = dtmatch (chans, &seg->comm_coord);
  379. assert (chani);
  380. cp = dtmatch (chani->chans, &seg->p);
  381. assert (cp);
  382. return cp;
  383. }
  384. static void
  385. assignSegs (size_t nrtes, route* route_list, maze* mp)
  386. {
  387. channel* chan;
  388. for (size_t i=0;i<nrtes;i++) {
  389. route rte = route_list[i];
  390. for (size_t j=0;j<rte.n;j++) {
  391. segment* seg = rte.segs+j;
  392. if (seg->isVert)
  393. chan = chanSearch(mp->vchans, seg);
  394. else
  395. chan = chanSearch(mp->hchans, seg);
  396. insertChan (chan, seg);
  397. }
  398. }
  399. }
  400. /* addLoop:
  401. * Add two temporary nodes to sgraph corresponding to two ends of a loop at cell cp, i
  402. * represented by dp and sp.
  403. */
  404. static void
  405. addLoop (sgraph* sg, cell* cp, snode* dp, snode* sp)
  406. {
  407. int i;
  408. int onTop;
  409. for (i = 0; i < cp->nsides; i++) {
  410. snode* onp = cp->sides[i];
  411. if (onp->isVert) continue;
  412. if (onp->cells[0] == cp) {
  413. onTop = 1;
  414. }
  415. else {
  416. onTop = 0;
  417. }
  418. if (onTop)
  419. createSEdge (sg, sp, onp, 0); /* FIX weight */
  420. else
  421. createSEdge (sg, dp, onp, 0); /* FIX weight */
  422. }
  423. sg->nnodes += 2;
  424. }
  425. /* addNodeEdges:
  426. * Add temporary node to sgraph corresponding to cell cp, represented
  427. * by np.
  428. */
  429. static void
  430. addNodeEdges (sgraph* sg, cell* cp, snode* np)
  431. {
  432. int i;
  433. for (i = 0; i < cp->nsides; i++) {
  434. snode* onp = cp->sides[i];
  435. createSEdge (sg, np, onp, 0); /* FIX weight */
  436. }
  437. sg->nnodes++;
  438. #ifdef DEBUG
  439. np->cells[0] = np->cells[1] = cp;
  440. #endif
  441. }
  442. static char* bendToStr (bend b)
  443. {
  444. char* s = NULL;
  445. switch (b) {
  446. case B_NODE :
  447. s = "B_NODE";
  448. break;
  449. case B_UP :
  450. s = "B_UP";
  451. break;
  452. case B_LEFT :
  453. s = "B_LEFT";
  454. break;
  455. case B_DOWN :
  456. s = "B_DOWN";
  457. break;
  458. default:
  459. assert(b == B_RIGHT);
  460. s = "B_RIGHT";
  461. break;
  462. }
  463. return s;
  464. }
  465. static void putSeg (FILE* fp, segment* seg)
  466. {
  467. if (seg->isVert)
  468. fprintf (fp, "((%f,%f),(%f,%f)) %s %s", seg->comm_coord, seg->p.p1,
  469. seg->comm_coord, seg->p.p2, bendToStr (seg->l1), bendToStr (seg->l2));
  470. else
  471. fprintf (fp, "((%f,%f),(%f,%f)) %s %s", seg->p.p1,seg->comm_coord,
  472. seg->p.p2, seg->comm_coord, bendToStr (seg->l1), bendToStr (seg->l2));
  473. }
  474. static DEBUG_FN void dumpChanG(channel *cp, double v) {
  475. if (seg_list_size(&cp->seg_list) < 2) return;
  476. fprintf (stderr, "channel %.0f (%f,%f)\n", v, cp->p.p1, cp->p.p2);
  477. for (size_t k = 0; k < seg_list_size(&cp->seg_list); ++k) {
  478. const adj_list_t adj = cp->G->vertices[k].adj_list;
  479. if (adj_list_is_empty(&adj)) continue;
  480. putSeg(stderr, seg_list_get(&cp->seg_list, k));
  481. fputs (" ->\n", stderr);
  482. for (size_t i = 0; i < adj_list_size(&adj); ++i) {
  483. fputs (" ", stderr);
  484. putSeg(stderr, seg_list_get(&cp->seg_list, adj_list_get(&adj, i)));
  485. fputs ("\n", stderr);
  486. }
  487. }
  488. }
  489. static void
  490. assignTrackNo (Dt_t* chans)
  491. {
  492. Dt_t* lp;
  493. Dtlink_t* l1;
  494. Dtlink_t* l2;
  495. channel* cp;
  496. for (l1 = dtflatten (chans); l1; l1 = dtlink(chans,l1)) {
  497. lp = ((chanItem*)l1)->chans;
  498. for (l2 = dtflatten (lp); l2; l2 = dtlink(lp,l2)) {
  499. cp = (channel*)l2;
  500. if (!seg_list_is_empty(&cp->seg_list)) {
  501. #ifdef DEBUG
  502. if (odb_flags & ODB_CHANG) dumpChanG (cp, ((chanItem*)l1)->v);
  503. #endif
  504. top_sort (cp->G);
  505. for (size_t k = 0; k < seg_list_size(&cp->seg_list); ++k)
  506. seg_list_get(&cp->seg_list, k)->track_no = cp->G->vertices[k].topsort_order+1;
  507. }
  508. }
  509. }
  510. }
  511. static void
  512. create_graphs(Dt_t* chans)
  513. {
  514. Dt_t* lp;
  515. Dtlink_t* l1;
  516. Dtlink_t* l2;
  517. channel* cp;
  518. for (l1 = dtflatten (chans); l1; l1 = dtlink(chans,l1)) {
  519. lp = ((chanItem*)l1)->chans;
  520. for (l2 = dtflatten (lp); l2; l2 = dtlink(lp,l2)) {
  521. cp = (channel*)l2;
  522. cp->G = make_graph(seg_list_size(&cp->seg_list));
  523. }
  524. }
  525. }
  526. static int
  527. eqEndSeg (bend S1l2, bend S2l2, bend T1, bend T2)
  528. {
  529. if ((S1l2==T2 && S2l2!=T2) || (S1l2==B_NODE && S2l2==T1))
  530. return 0;
  531. else
  532. return -1;
  533. }
  534. static int
  535. overlapSeg (segment* S1, segment* S2, bend T1, bend T2)
  536. {
  537. if(S1->p.p2<S2->p.p2) {
  538. if(S1->l2==T1&&S2->l1==T2) return(-1);
  539. else if(S1->l2==T2&&S2->l1==T1) return(1);
  540. else return(0);
  541. }
  542. if (S1->p.p2 > S2->p.p2) {
  543. if(S2->l1==T2&&S2->l2==T2) return(-1);
  544. else if (S2->l1==T1&&S2->l2==T1) return(1);
  545. else return(0);
  546. }
  547. if (S2->l1 == T2) return eqEndSeg (S1->l2, S2->l2, T1, T2);
  548. return -1 * eqEndSeg(S2->l2, S1->l2, T1, T2);
  549. }
  550. static int
  551. ellSeg (bend S1l1, bend S1l2, bend T)
  552. {
  553. if (S1l1 == T) {
  554. if (S1l2== T) return -1;
  555. else return 0;
  556. }
  557. else return 1;
  558. }
  559. static int
  560. segCmp (segment* S1, segment* S2, bend T1, bend T2)
  561. {
  562. /* no overlap */
  563. if (S1->p.p2 < S2->p.p1 || S1->p.p1 > S2->p.p2) return 0;
  564. /* left endpoint of S2 inside S1 */
  565. if(S1->p.p1<S2->p.p1&&S2->p.p1<S1->p.p2)
  566. return overlapSeg (S1, S2, T1, T2);
  567. /* left endpoint of S1 inside S2 */
  568. if (S2->p.p1 < S1->p.p1 && S1->p.p1 < S2->p.p2)
  569. return -1*overlapSeg (S2, S1, T1, T2);
  570. if (S1->p.p1 == S2->p.p1) {
  571. if(S1->p.p2==S2->p.p2) {
  572. if (S1->l1 == S2->l1 && S1->l2 == S2->l2)
  573. return 0;
  574. if (S2->l1 == S2->l2) {
  575. if (S2->l1 == T1) return 1;
  576. if (S2->l1 == T2) return -1;
  577. if (S1->l1 != T1 && S1->l2 != T1) return 1;
  578. if (S1->l1 != T2 && S1->l2 != T2) return -1;
  579. return 0;
  580. }
  581. if (S2->l1 == T1 && S2->l2 == T2) {
  582. if (S1->l1 != T1 && S1->l2 == T2) return 1;
  583. if (S1->l1 == T1 && S1->l2 != T2) return -1;
  584. return 0;
  585. }
  586. if (S2->l2 == T1 && S2->l1 == T2) {
  587. if (S1->l2 != T1 && S1->l1 == T2) return 1;
  588. if (S1->l2 == T1 && S1->l1 != T2) return -1;
  589. return 0;
  590. }
  591. if (S2->l1 == B_NODE && S2->l2 == T1) {
  592. return ellSeg (S1->l1, S1->l2, T1);
  593. }
  594. if (S2->l1 == B_NODE && S2->l2 == T2) {
  595. return -1*ellSeg (S1->l1, S1->l2, T2);
  596. }
  597. if (S2->l1 == T1 && S2->l2 == B_NODE) {
  598. return ellSeg (S1->l2, S1->l1, T1);
  599. }
  600. /* ((S2->l1==T2)&&(S2->l2==B_NODE)) */
  601. return -1 * ellSeg(S1->l2, S1->l1, T2);
  602. }
  603. if (S1->p.p2 < S2->p.p2) {
  604. if(S1->l2==T1)
  605. return eqEndSeg (S2->l1, S1->l1, T1, T2);
  606. return -1 * eqEndSeg(S2->l1, S1->l1, T1, T2);
  607. }
  608. /* S1->p.p2>S2->p.p2 */
  609. if (S2->l2 == T2)
  610. return eqEndSeg(S1->l1, S2->l1, T1, T2);
  611. return -1 * eqEndSeg(S1->l1, S2->l1, T1, T2);
  612. }
  613. if (S1->p.p2 == S2->p.p1) {
  614. if (S1->l2 == S2->l1) return 0;
  615. if (S1->l2 == T2) return 1;
  616. return -1;
  617. }
  618. /* S1->p.p1==S2->p.p2 */
  619. if (S1->l1 == S2->l2) return 0;
  620. if (S1->l1 == T2) return 1;
  621. return -1;
  622. }
  623. /* Function seg_cmp returns
  624. * -1 if S1 HAS TO BE to the right/below S2 to avoid a crossing,
  625. * 0 if a crossing is unavoidable or there is no crossing at all or
  626. * the segments are parallel,
  627. * 1 if S1 HAS TO BE to the left/above S2 to avoid a crossing
  628. * -2 if S1 and S2 are incomparable
  629. *
  630. * Note: This definition means horizontal segments have track numbers
  631. * increasing as y decreases, while vertical segments have track numbers
  632. * increasing as x increases. It would be good to make this consistent,
  633. * with horizontal track numbers increasing with y. This can be done by
  634. * switching B_DOWN and B_UP in the first call to segCmp. At present,
  635. * though, I'm not sure what assumptions are made in handling parallel
  636. * segments, so we leave the code alone for the time being.
  637. */
  638. static int
  639. seg_cmp(segment* S1, segment* S2)
  640. {
  641. if(S1->isVert!=S2->isVert||S1->comm_coord!=S2->comm_coord) {
  642. agerrorf("incomparable segments !! -- Aborting\n");
  643. return -2;
  644. }
  645. if(S1->isVert)
  646. return segCmp (S1, S2, B_RIGHT, B_LEFT);
  647. else
  648. return segCmp (S1, S2, B_DOWN, B_UP);
  649. }
  650. static int
  651. add_edges_in_G(channel* cp)
  652. {
  653. seg_list_t *seg_list = &cp->seg_list;
  654. const size_t size = seg_list_size(&cp->seg_list);
  655. rawgraph* G = cp->G;
  656. for (size_t x = 0; x + 1 < size; ++x) {
  657. for (size_t y = x + 1; y < size; ++y) {
  658. const int cmp = seg_cmp(seg_list_get(seg_list, x),
  659. seg_list_get(seg_list, y));
  660. if (cmp == -2) {
  661. return -1;
  662. } else if (cmp > 0) {
  663. insert_edge(G,x,y);
  664. } else if (cmp == -1) {
  665. insert_edge(G,y,x);
  666. }
  667. }
  668. }
  669. return 0;
  670. }
  671. static int
  672. add_np_edges (Dt_t* chans)
  673. {
  674. Dt_t* lp;
  675. Dtlink_t* l1;
  676. Dtlink_t* l2;
  677. channel* cp;
  678. for (l1 = dtflatten (chans); l1; l1 = dtlink(chans,l1)) {
  679. lp = ((chanItem*)l1)->chans;
  680. for (l2 = dtflatten (lp); l2; l2 = dtlink(lp,l2)) {
  681. cp = (channel*)l2;
  682. if (!seg_list_is_empty(&cp->seg_list))
  683. if (add_edges_in_G(cp)) {
  684. return -1;
  685. }
  686. }
  687. }
  688. return 0;
  689. }
  690. static segment*
  691. next_seg(segment* seg, int dir)
  692. {
  693. assert(seg);
  694. if (!dir)
  695. return seg->prev;
  696. else
  697. return seg->next;
  698. }
  699. /* propagate_prec propagates the precedence relationship along
  700. * a series of parallel segments on 2 edges
  701. */
  702. static int
  703. propagate_prec(segment* seg, int prec, int hops, int dir)
  704. {
  705. int x;
  706. int ans=prec;
  707. segment* next;
  708. segment* current;
  709. current = seg;
  710. for(x=1;x<=hops;x++) {
  711. next = next_seg(current, dir);
  712. if(!current->isVert) {
  713. if(next->comm_coord==current->p.p1) {
  714. if(current->l1==B_UP) ans *= -1;
  715. }
  716. else {
  717. if(current->l2==B_DOWN) ans *= -1;
  718. }
  719. }
  720. else {
  721. if(next->comm_coord==current->p.p1) {
  722. if(current->l1==B_RIGHT) ans *= -1;
  723. }
  724. else {
  725. if(current->l2==B_LEFT) ans *= -1;
  726. }
  727. }
  728. current = next;
  729. }
  730. return ans;
  731. }
  732. static bool
  733. is_parallel(segment* s1, segment* s2)
  734. {
  735. assert (s1->comm_coord==s2->comm_coord);
  736. return s1->p.p1 == s2->p.p1 &&
  737. s1->p.p2 == s2->p.p2 &&
  738. s1->l1 == s2->l1 &&
  739. s1->l2 == s2->l2;
  740. }
  741. /* decide_point returns (through ret) the number of hops needed in the given
  742. * directions along the 2 edges to get to a deciding point (or NODES) and also
  743. * puts into prec the appropriate dependency (follows same convention as
  744. * seg_cmp)
  745. */
  746. static int
  747. decide_point(pair *ret, segment* si, segment* sj, int dir1, int dir2)
  748. {
  749. int prec = 0, ans = 0, temp;
  750. segment* np1;
  751. segment *np2 = NULL;
  752. while ((np1 = next_seg(si,dir1)) && (np2 = next_seg(sj,dir2)) &&
  753. is_parallel(np1, np2)) {
  754. ans++;
  755. si = np1;
  756. sj = np2;
  757. }
  758. if (!np1)
  759. prec = 0;
  760. else if (!np2)
  761. assert(0); /* FIXME */
  762. else {
  763. temp = seg_cmp(np1, np2);
  764. if (temp == -2) {
  765. return -1;
  766. }
  767. prec = propagate_prec(np1, temp, ans+1, 1-dir1);
  768. }
  769. ret->a = ans;
  770. ret->b = prec;
  771. return 0;
  772. }
  773. /* sets the edges for a series of parallel segments along two edges starting
  774. * from segment i, segment j. It is assumed that the edge should be from
  775. * segment i to segment j - the dependency is appropriately propagated
  776. */
  777. static void
  778. set_parallel_edges (segment* seg1, segment* seg2, int dir1, int dir2, int hops,
  779. maze* mp)
  780. {
  781. int x;
  782. channel* chan;
  783. channel* nchan;
  784. segment* prev1;
  785. segment* prev2;
  786. if (seg1->isVert)
  787. chan = chanSearch(mp->vchans, seg1);
  788. else
  789. chan = chanSearch(mp->hchans, seg1);
  790. insert_edge(chan->G, seg1->ind_no, seg2->ind_no);
  791. for (x=1;x<=hops;x++) {
  792. prev1 = next_seg(seg1, dir1);
  793. prev2 = next_seg(seg2, dir2);
  794. if(!seg1->isVert) {
  795. nchan = chanSearch(mp->vchans, prev1);
  796. if(prev1->comm_coord==seg1->p.p1) {
  797. if(seg1->l1==B_UP) {
  798. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  799. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  800. else
  801. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  802. }
  803. else {
  804. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  805. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  806. else
  807. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  808. }
  809. }
  810. else {
  811. if(seg1->l2==B_UP) {
  812. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  813. insert_edge(nchan->G,prev1->ind_no, prev2->ind_no);
  814. else
  815. insert_edge(nchan->G,prev2->ind_no, prev1->ind_no);
  816. }
  817. else {
  818. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  819. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  820. else
  821. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  822. }
  823. }
  824. }
  825. else {
  826. nchan = chanSearch(mp->hchans, prev1);
  827. if(prev1->comm_coord==seg1->p.p1) {
  828. if(seg1->l1==B_LEFT) {
  829. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  830. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  831. else
  832. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  833. }
  834. else {
  835. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  836. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  837. else
  838. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  839. }
  840. }
  841. else {
  842. if(seg1->l2==B_LEFT) {
  843. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  844. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  845. else
  846. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  847. }
  848. else {
  849. if(edge_exists(chan->G, seg1->ind_no, seg2->ind_no))
  850. insert_edge(nchan->G, prev1->ind_no, prev2->ind_no);
  851. else
  852. insert_edge(nchan->G, prev2->ind_no, prev1->ind_no);
  853. }
  854. }
  855. }
  856. chan = nchan;
  857. seg1 = prev1;
  858. seg2 = prev2;
  859. }
  860. }
  861. /* removes the edge between segments after the resolution of a conflict
  862. */
  863. static void
  864. removeEdge(segment* seg1, segment* seg2, int dir, maze* mp)
  865. {
  866. segment* ptr1;
  867. segment* ptr2;
  868. channel* chan;
  869. ptr1 = seg1;
  870. ptr2 = seg2;
  871. while(is_parallel(ptr1, ptr2)) {
  872. ptr1 = next_seg(ptr1, 1);
  873. ptr2 = next_seg(ptr2, dir);
  874. }
  875. if(ptr1->isVert)
  876. chan = chanSearch(mp->vchans, ptr1);
  877. else
  878. chan = chanSearch(mp->hchans, ptr1);
  879. remove_redge (chan->G, ptr1->ind_no, ptr2->ind_no);
  880. }
  881. static int
  882. addPEdges (channel* cp, maze* mp)
  883. {
  884. /* dir[1,2] are used to figure out whether we should use prev
  885. * pointers or next pointers -- 0 : decrease, 1 : increase
  886. */
  887. int dir;
  888. /* number of hops along the route to get to the deciding points */
  889. pair hops;
  890. /* precedences of the deciding points : same convention as
  891. * seg_cmp function
  892. */
  893. int prec1, prec2;
  894. pair p;
  895. rawgraph* G = cp->G;
  896. seg_list_t *segs = &cp->seg_list;
  897. for(size_t i = 0; i + 1 < seg_list_size(&cp->seg_list); ++i) {
  898. for(size_t j = i + 1; j < seg_list_size(&cp->seg_list); ++j) {
  899. if (!edge_exists(G,i,j) && !edge_exists(G,j,i)) {
  900. if (is_parallel(seg_list_get(segs, i), seg_list_get(segs, j))) {
  901. /* get_directions */
  902. if (seg_list_get(segs, i)->prev == 0) {
  903. if (seg_list_get(segs, j)->prev == 0)
  904. dir = 0;
  905. else
  906. dir = 1;
  907. }
  908. else if (seg_list_get(segs, j)->prev == 0) {
  909. dir = 1;
  910. }
  911. else {
  912. if (seg_list_get(segs, i)->prev->comm_coord ==
  913. seg_list_get(segs, j)->prev->comm_coord)
  914. dir = 0;
  915. else
  916. dir = 1;
  917. }
  918. if (decide_point(&p, seg_list_get(segs, i), seg_list_get(segs, j), 0, dir)
  919. != 0) {
  920. return -1;
  921. }
  922. hops.a = p.a;
  923. prec1 = p.b;
  924. if (decide_point(&p, seg_list_get(segs, i), seg_list_get(segs, j), 1,
  925. 1 - dir) != 0) {
  926. return -1;
  927. }
  928. hops.b = p.a;
  929. prec2 = p.b;
  930. if (prec1 == -1) {
  931. set_parallel_edges(seg_list_get(segs, j), seg_list_get(segs, i), dir, 0,
  932. hops.a, mp);
  933. set_parallel_edges(seg_list_get(segs, j), seg_list_get(segs, i), 1 - dir, 1,
  934. hops.b, mp);
  935. if(prec2==1)
  936. removeEdge(seg_list_get(segs, i), seg_list_get(segs, j), 1 - dir, mp);
  937. } else if (prec1 == 0) {
  938. if (prec2 == -1) {
  939. set_parallel_edges(seg_list_get(segs, j), seg_list_get(segs, i), dir, 0,
  940. hops.a, mp);
  941. set_parallel_edges(seg_list_get(segs, j), seg_list_get(segs, i), 1 - dir,
  942. 1, hops.b, mp);
  943. } else if (prec2 == 0) {
  944. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 0, dir,
  945. hops.a, mp);
  946. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 1,
  947. 1 - dir, hops.b, mp);
  948. } else if (prec2 == 1) {
  949. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 0, dir,
  950. hops.a, mp);
  951. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 1,
  952. 1 - dir, hops.b, mp);
  953. }
  954. } else if (prec1 == 1) {
  955. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 0, dir,
  956. hops.a, mp);
  957. set_parallel_edges(seg_list_get(segs, i), seg_list_get(segs, j), 1, 1 - dir,
  958. hops.b, mp);
  959. if(prec2==-1)
  960. removeEdge(seg_list_get(segs, i), seg_list_get(segs, j), 1 - dir, mp);
  961. }
  962. }
  963. }
  964. }
  965. }
  966. return 0;
  967. }
  968. static int
  969. add_p_edges (Dt_t* chans, maze* mp)
  970. {
  971. Dt_t* lp;
  972. Dtlink_t* l1;
  973. Dtlink_t* l2;
  974. for (l1 = dtflatten (chans); l1; l1 = dtlink(chans,l1)) {
  975. lp = ((chanItem*)l1)->chans;
  976. for (l2 = dtflatten (lp); l2; l2 = dtlink(lp,l2)) {
  977. if (addPEdges((channel*)l2, mp) != 0) {
  978. return -1;
  979. }
  980. }
  981. }
  982. return 0;
  983. }
  984. static int
  985. assignTracks (maze* mp)
  986. {
  987. /* Create the graphs for each channel */
  988. create_graphs(mp->hchans);
  989. create_graphs(mp->vchans);
  990. /* add edges between non-parallel segments */
  991. if (add_np_edges(mp->hchans) != 0) {
  992. return -1;
  993. }
  994. if (add_np_edges(mp->vchans) != 0) {
  995. return -1;
  996. }
  997. /* add edges between parallel segments + remove appropriate edges */
  998. if (add_p_edges(mp->hchans, mp) != 0) {
  999. return -1;
  1000. }
  1001. if (add_p_edges(mp->vchans, mp) != 0) {
  1002. return -1;
  1003. }
  1004. /* Assign the tracks after a top sort */
  1005. assignTrackNo (mp->hchans);
  1006. assignTrackNo (mp->vchans);
  1007. return 0;
  1008. }
  1009. static double
  1010. vtrack (segment* seg, maze* m)
  1011. {
  1012. channel* chp = chanSearch(m->vchans, seg);
  1013. const double f = (double)seg->track_no / ((double)seg_list_size(&chp->seg_list) + 1);
  1014. double left = chp->cp->bb.LL.x;
  1015. double right = chp->cp->bb.UR.x;
  1016. return left + f*(right-left);
  1017. }
  1018. static double htrack(segment *seg, maze *m) {
  1019. channel* chp = chanSearch(m->hchans, seg);
  1020. double f = 1.0 - (double)seg->track_no / ((double)seg_list_size(&chp->seg_list) + 1);
  1021. double lo = chp->cp->bb.LL.y;
  1022. double hi = chp->cp->bb.UR.y;
  1023. return round(lo + f * (hi - lo));
  1024. }
  1025. static pointf
  1026. addPoints(pointf p0, pointf p1)
  1027. {
  1028. p0.x += p1.x;
  1029. p0.y += p1.y;
  1030. return p0;
  1031. }
  1032. static void attachOrthoEdges(maze *mp, size_t n_edges, route* route_list,
  1033. splineInfo *sinfo, epair_t es[], bool doLbls) {
  1034. int ipt;
  1035. pointf* ispline = 0;
  1036. size_t splsz = 0;
  1037. pointf p, p1, q1;
  1038. route rte;
  1039. segment* seg;
  1040. Agedge_t* e;
  1041. textlabel_t* lbl;
  1042. for (size_t irte = 0; irte < n_edges; irte++) {
  1043. e = es[irte].e;
  1044. p1 = addPoints(ND_coord(agtail(e)), ED_tail_port(e).p);
  1045. q1 = addPoints(ND_coord(aghead(e)), ED_head_port(e).p);
  1046. rte = route_list[irte];
  1047. size_t npts = 1 + 3*rte.n;
  1048. if (npts > splsz) {
  1049. free (ispline);
  1050. ispline = gv_calloc(npts, sizeof(pointf));
  1051. splsz = npts;
  1052. }
  1053. seg = rte.segs;
  1054. if (seg->isVert) {
  1055. p.x = vtrack(seg, mp);
  1056. p.y = p1.y;
  1057. }
  1058. else {
  1059. p.y = htrack(seg, mp);
  1060. p.x = p1.x;
  1061. }
  1062. ispline[0] = ispline[1] = p;
  1063. ipt = 2;
  1064. for (size_t i = 1;i<rte.n;i++) {
  1065. seg = rte.segs+i;
  1066. if (seg->isVert)
  1067. p.x = vtrack(seg, mp);
  1068. else
  1069. p.y = htrack(seg, mp);
  1070. ispline[ipt+2] = ispline[ipt+1] = ispline[ipt] = p;
  1071. ipt += 3;
  1072. }
  1073. if (seg->isVert) {
  1074. p.x = vtrack(seg, mp);
  1075. p.y = q1.y;
  1076. }
  1077. else {
  1078. p.y = htrack(seg, mp);
  1079. p.x = q1.x;
  1080. }
  1081. ispline[ipt] = ispline[ipt+1] = p;
  1082. if (Verbose > 1)
  1083. fprintf(stderr, "ortho %s %s\n", agnameof(agtail(e)),agnameof(aghead(e)));
  1084. clip_and_install(e, aghead(e), ispline, npts, sinfo);
  1085. if (doLbls && (lbl = ED_label(e)) && !lbl->set)
  1086. addEdgeLabels(e);
  1087. }
  1088. free(ispline);
  1089. }
  1090. static int
  1091. edgeLen (Agedge_t* e)
  1092. {
  1093. pointf p = ND_coord(agtail(e));
  1094. pointf q = ND_coord(aghead(e));
  1095. return (int)DIST2(p,q);
  1096. }
  1097. static int edgecmp(const void *x, const void *y) {
  1098. const epair_t *e0 = x;
  1099. const epair_t *e1 = y;
  1100. if (e0->d > e1->d) {
  1101. return 1;
  1102. }
  1103. if (e0->d < e1->d) {
  1104. return -1;
  1105. }
  1106. return 0;
  1107. }
  1108. static bool spline_merge(node_t * n)
  1109. {
  1110. (void)n;
  1111. return false;
  1112. }
  1113. static bool swap_ends_p(edge_t * e)
  1114. {
  1115. (void)e;
  1116. return false;
  1117. }
  1118. static splineInfo sinfo = { swap_ends_p, spline_merge, true, true };
  1119. /* orthoEdges:
  1120. * For edges without position information, construct an orthogonal routing.
  1121. * If useLbls is true, use edge label info when available to guide routing,
  1122. * and set label pos for those edges for which this info is not available.
  1123. */
  1124. void orthoEdges(Agraph_t *g, bool useLbls) {
  1125. sgraph* sg;
  1126. maze* mp;
  1127. route* route_list;
  1128. int gstart;
  1129. Agnode_t* n;
  1130. Agedge_t* e;
  1131. snode* sn;
  1132. snode* dn;
  1133. epair_t* es = gv_calloc(agnedges(g), sizeof(epair_t));
  1134. cell* start;
  1135. cell* dest;
  1136. PointSet* ps = NULL;
  1137. textlabel_t* lbl;
  1138. if (Concentrate)
  1139. ps = newPS();
  1140. #ifdef DEBUG
  1141. {
  1142. char* s = agget(g, "odb");
  1143. char c;
  1144. odb_flags = 0;
  1145. if (s && *s != '\0') {
  1146. while ((c = *s++)) {
  1147. switch (c) {
  1148. case 'c' :
  1149. odb_flags |= ODB_CHANG; // emit channel graph
  1150. break;
  1151. case 'i' :
  1152. odb_flags |= (ODB_SGRAPH|ODB_IGRAPH); // emit search graphs
  1153. break;
  1154. case 'm' :
  1155. odb_flags |= ODB_MAZE; // emit maze
  1156. break;
  1157. case 'r' :
  1158. odb_flags |= ODB_ROUTE; // emit routes in maze
  1159. break;
  1160. case 's' :
  1161. odb_flags |= ODB_SGRAPH; // emit search graph
  1162. break;
  1163. default:
  1164. break;
  1165. }
  1166. }
  1167. }
  1168. }
  1169. #endif
  1170. if (useLbls) {
  1171. agwarningf("Orthogonal edges do not currently handle edge labels. Try using xlabels.\n");
  1172. useLbls = false;
  1173. }
  1174. mp = mkMaze(g);
  1175. sg = mp->sg;
  1176. #ifdef DEBUG
  1177. if (odb_flags & ODB_SGRAPH) emitSearchGraph (stderr, sg);
  1178. #endif
  1179. /* store edges to be routed in es, along with their lengths */
  1180. size_t n_edges = 0;
  1181. for (n = agfstnode (g); n; n = agnxtnode(g, n)) {
  1182. for (e = agfstout(g, n); e; e = agnxtout(g,e)) {
  1183. if (Nop == 2 && ED_spl(e)) continue;
  1184. if (Concentrate) {
  1185. int ti = AGSEQ(agtail(e));
  1186. int hi = AGSEQ(aghead(e));
  1187. if (ti <= hi) {
  1188. if (isInPS (ps,ti,hi)) continue;
  1189. else addPS (ps,ti,hi);
  1190. }
  1191. else {
  1192. if (isInPS (ps,hi,ti)) continue;
  1193. else addPS (ps,hi,ti);
  1194. }
  1195. }
  1196. es[n_edges].e = e;
  1197. es[n_edges].d = edgeLen (e);
  1198. n_edges++;
  1199. }
  1200. }
  1201. route_list = gv_calloc(n_edges, sizeof(route));
  1202. qsort(es, n_edges, sizeof(epair_t), edgecmp);
  1203. gstart = sg->nnodes;
  1204. PQgen (sg->nnodes+2);
  1205. sn = &sg->nodes[gstart];
  1206. dn = &sg->nodes[gstart+1];
  1207. for (size_t i = 0; i < n_edges; i++) {
  1208. #ifdef DEBUG
  1209. if (i > 0 && (odb_flags & ODB_IGRAPH)) emitSearchGraph (stderr, sg);
  1210. #endif
  1211. e = es[i].e;
  1212. start = CELL(agtail(e));
  1213. dest = CELL(aghead(e));
  1214. if (useLbls && (lbl = ED_label(e)) && lbl->set) {
  1215. }
  1216. else {
  1217. if (start == dest)
  1218. addLoop (sg, start, dn, sn);
  1219. else {
  1220. addNodeEdges (sg, dest, dn);
  1221. addNodeEdges (sg, start, sn);
  1222. }
  1223. if (shortPath (sg, dn, sn)) goto orthofinish;
  1224. }
  1225. route_list[i] = convertSPtoRoute(sg, sn, dn);
  1226. reset (sg);
  1227. }
  1228. PQfree ();
  1229. mp->hchans = extractHChans (mp);
  1230. mp->vchans = extractVChans (mp);
  1231. assignSegs (n_edges, route_list, mp);
  1232. if (assignTracks(mp) != 0)
  1233. goto orthofinish;
  1234. #ifdef DEBUG
  1235. if (odb_flags & ODB_ROUTE) emitGraph (stderr, mp, n_edges, route_list, es);
  1236. #endif
  1237. attachOrthoEdges(mp, n_edges, route_list, &sinfo, es, useLbls);
  1238. orthofinish:
  1239. if (Concentrate)
  1240. freePS (ps);
  1241. for (size_t i=0; i < n_edges; i++)
  1242. free (route_list[i].segs);
  1243. free (route_list);
  1244. freeMaze (mp);
  1245. free (es);
  1246. }
  1247. #include <common/arith.h>
  1248. #define TRANS 10
  1249. static char* prolog2 =
  1250. "%%!PS-Adobe-2.0\n\
  1251. %%%%BoundingBox: (atend)\n\
  1252. /point {\n\
  1253. /Y exch def\n\
  1254. /X exch def\n\
  1255. newpath\n\
  1256. X Y 3 0 360 arc fill\n\
  1257. } def\n\
  1258. /cell {\n\
  1259. /Y exch def\n\
  1260. /X exch def\n\
  1261. /y exch def\n\
  1262. /x exch def\n\
  1263. newpath\n\
  1264. x y moveto\n\
  1265. x Y lineto\n\
  1266. X Y lineto\n\
  1267. X y lineto\n\
  1268. closepath stroke\n\
  1269. } def\n\
  1270. /node {\n\
  1271. /u exch def\n\
  1272. /r exch def\n\
  1273. /d exch def\n\
  1274. /l exch def\n\
  1275. newpath l d moveto\n\
  1276. r d lineto r u lineto l u lineto\n\
  1277. closepath fill\n\
  1278. } def\n\
  1279. \n";
  1280. static char* epilog2 =
  1281. "showpage\n\
  1282. %%%%Trailer\n\
  1283. %%%%BoundingBox: %.f %.f %.f %.f\n";
  1284. static pointf coordOf(cell *cp, snode *np) {
  1285. pointf p;
  1286. if (cp->sides[M_TOP] == np) {
  1287. p.x = (cp->bb.LL.x + cp->bb.UR.x)/2;
  1288. p.y = cp->bb.UR.y;
  1289. }
  1290. else if (cp->sides[M_BOTTOM] == np) {
  1291. p.x = (cp->bb.LL.x + cp->bb.UR.x)/2;
  1292. p.y = cp->bb.LL.y;
  1293. }
  1294. else if (cp->sides[M_LEFT] == np) {
  1295. p.y = (cp->bb.LL.y + cp->bb.UR.y)/2;
  1296. p.x = cp->bb.LL.x;
  1297. }
  1298. else if (cp->sides[M_RIGHT] == np) {
  1299. p.y = (cp->bb.LL.y + cp->bb.UR.y)/2;
  1300. p.x = cp->bb.UR.x;
  1301. }
  1302. else {
  1303. agerrorf("Node not adjacent to cell -- Aborting\n");
  1304. graphviz_exit(EXIT_FAILURE);
  1305. }
  1306. return p;
  1307. }
  1308. static boxf
  1309. emitEdge (FILE* fp, Agedge_t* e, route rte, maze* m, boxf bb)
  1310. {
  1311. double x, y;
  1312. boxf n = CELL(agtail(e))->bb;
  1313. segment* seg = rte.segs;
  1314. if (seg->isVert) {
  1315. x = vtrack(seg, m);
  1316. y = (n.UR.y + n.LL.y)/2;
  1317. }
  1318. else {
  1319. y = htrack(seg, m);
  1320. x = (n.UR.x + n.LL.x)/2;
  1321. }
  1322. bb.LL.x = fmin(bb.LL.x, SC * x);
  1323. bb.LL.y = fmin(bb.LL.y, SC * y);
  1324. bb.UR.x = fmax(bb.UR.x, SC * x);
  1325. bb.UR.y = fmax(bb.UR.y, SC * y);
  1326. fprintf(fp, "newpath %.0f %.0f moveto\n", SC * x, SC * y);
  1327. for (size_t i = 1;i<rte.n;i++) {
  1328. seg = rte.segs+i;
  1329. if (seg->isVert) {
  1330. x = vtrack(seg, m);
  1331. }
  1332. else {
  1333. y = htrack(seg, m);
  1334. }
  1335. bb.LL.x = fmin(bb.LL.x, SC * x);
  1336. bb.LL.y = fmin(bb.LL.y, SC * y);
  1337. bb.UR.x = fmax(bb.UR.x, SC * x);
  1338. bb.UR.y = fmax(bb.UR.y, SC * y);
  1339. fprintf(fp, "%.0f %.0f lineto\n", SC * x, SC * y);
  1340. }
  1341. n = CELL(aghead(e))->bb;
  1342. if (seg->isVert) {
  1343. x = vtrack(seg, m);
  1344. y = (n.UR.y + n.LL.y)/2;
  1345. }
  1346. else {
  1347. y = htrack(seg, m);
  1348. x = (n.LL.x + n.UR.x)/2;
  1349. }
  1350. bb.LL.x = fmin(bb.LL.x, SC * x);
  1351. bb.LL.y = fmin(bb.LL.y, SC * y);
  1352. bb.UR.x = fmax(bb.UR.x, SC * x);
  1353. bb.UR.y = fmax(bb.UR.y, SC * y);
  1354. fprintf(fp, "%.0f %.0f lineto stroke\n", SC * x, SC * y);
  1355. return bb;
  1356. }
  1357. /**
  1358. * @brief dumps in dot format @ref snode::cells and @ref edges of
  1359. * @ref sgraph for debugging
  1360. *
  1361. * The routine uses coordinates of @ref cells calculated
  1362. * from @ref gcells.
  1363. * Coordinates of @ref gcellg are calculated by original
  1364. * specified graph layout engine.
  1365. */
  1366. static DEBUG_FN void emitSearchGraph(FILE *fp, sgraph *sg) {
  1367. cell* cp;
  1368. snode* np;
  1369. sedge* ep;
  1370. pointf p;
  1371. int i;
  1372. fputs ("graph G {\n", fp);
  1373. fputs (" node[shape=point]\n", fp);
  1374. fputs (" layout=neato\n", fp);
  1375. for (i = 0; i < sg->nnodes; i++) {
  1376. np = sg->nodes+i;
  1377. cp = np->cells[0];
  1378. if (cp == np->cells[1]) {
  1379. p = midPt(cp);
  1380. }
  1381. else {
  1382. if (IsNode(cp)) cp = np->cells[1];
  1383. p = coordOf (cp, np);
  1384. }
  1385. fprintf (fp, " %d [pos=\"%.0f,%.0f!\"]\n", i, p.x, p.y);
  1386. }
  1387. for (i = 0; i < sg->nedges; i++) {
  1388. ep = sg->edges+i;
  1389. fprintf (fp, " %d -- %d[label=\"%f\"]\n", ep->v1, ep->v2, ep->weight);
  1390. }
  1391. fputs ("}\n", fp);
  1392. }
  1393. static DEBUG_FN void emitGraph(FILE *fp, maze *mp, size_t n_edges,
  1394. route *route_list, epair_t es[]) {
  1395. boxf absbb = {.LL = {.x = DBL_MAX, .y = DBL_MAX},
  1396. .UR = {.x = -DBL_MAX, .y = -DBL_MAX}};
  1397. fprintf (fp, "%s", prolog2);
  1398. fprintf (fp, "%d %d translate\n", TRANS, TRANS);
  1399. fputs ("0 0 1 setrgbcolor\n", fp);
  1400. for (int i = 0; i < mp->ngcells; i++) {
  1401. const boxf bb = mp->gcells[i].bb;
  1402. fprintf (fp, "%f %f %f %f node\n", bb.LL.x, bb.LL.y, bb.UR.x, bb.UR.y);
  1403. }
  1404. for (size_t i = 0; i < n_edges; i++) {
  1405. absbb = emitEdge (fp, es[i].e, route_list[i], mp, absbb);
  1406. }
  1407. fputs ("0.8 0.8 0.8 setrgbcolor\n", fp);
  1408. for (int i = 0; i < mp->ncells; i++) {
  1409. const boxf bb = mp->cells[i].bb;
  1410. fprintf (fp, "%f %f %f %f cell\n", bb.LL.x, bb.LL.y, bb.UR.x, bb.UR.y);
  1411. absbb.LL.x = fmin(absbb.LL.x, bb.LL.x);
  1412. absbb.LL.y = fmin(absbb.LL.y, bb.LL.y);
  1413. absbb.UR.x = fmax(absbb.UR.x, bb.UR.x);
  1414. absbb.UR.y = fmax(absbb.UR.y, bb.UR.y);
  1415. }
  1416. const boxf bbox = {
  1417. .LL = {.x = absbb.LL.x + TRANS,
  1418. .y = absbb.LL.y + TRANS},
  1419. .UR = {.x = absbb.UR.x + TRANS,
  1420. .y = absbb.UR.y + TRANS}};
  1421. fprintf (fp, epilog2, bbox.LL.x, bbox.LL.y, bbox.UR.x, bbox.UR.y);
  1422. }