Graphviz  2.29.20120523.0446
lib/neatogen/edges.c
Go to the documentation of this file.
00001 /* $Id$ $Revision$ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /*************************************************************************
00005  * Copyright (c) 2011 AT&T Intellectual Property 
00006  * All rights reserved. This program and the accompanying materials
00007  * are made available under the terms of the Eclipse Public License v1.0
00008  * which accompanies this distribution, and is available at
00009  * http://www.eclipse.org/legal/epl-v10.html
00010  *
00011  * Contributors: See CVS logs. Details at http://www.graphviz.org/
00012  *************************************************************************/
00013 
00014 #include "neato.h"
00015 #include "mem.h"
00016 #include "info.h"
00017 #include "edges.h"
00018 #include <math.h>
00019 
00020 
00021 double pxmin, pxmax, pymin, pymax;      /* clipping window */
00022 
00023 static int nedges;
00024 static Freelist efl;
00025 
00026 void edgeinit()
00027 {
00028     freeinit(&efl, sizeof(Edge));
00029     nedges = 0;
00030 }
00031 
00032 Edge *bisect(Site * s1, Site * s2)
00033 {
00034     double dx, dy, adx, ady;
00035     Edge *newedge;
00036 
00037     newedge = (Edge *) getfree(&efl);
00038 
00039     newedge->reg[0] = s1;
00040     newedge->reg[1] = s2;
00041     ref(s1);
00042     ref(s2);
00043     newedge->ep[0] = (Site *) NULL;
00044     newedge->ep[1] = (Site *) NULL;
00045 
00046     dx = s2->coord.x - s1->coord.x;
00047     dy = s2->coord.y - s1->coord.y;
00048     adx = dx > 0 ? dx : -dx;
00049     ady = dy > 0 ? dy : -dy;
00050     newedge->c =
00051         s1->coord.x * dx + s1->coord.y * dy + (dx * dx + dy * dy) * 0.5;
00052     if (adx > ady) {
00053         newedge->a = 1.0;
00054         newedge->b = dy / dx;
00055         newedge->c /= dx;
00056     } else {
00057         newedge->b = 1.0;
00058         newedge->a = dx / dy;
00059         newedge->c /= dy;
00060     };
00061 
00062     newedge->edgenbr = nedges;
00063 #ifdef STANDALONE
00064     out_bisector(newedge);
00065 #endif
00066     nedges += 1;
00067     return (newedge);
00068 }
00069 
00070 
00071 static void doSeg(Edge * e, double x1, double y1, double x2, double y2)
00072 {
00073     addVertex(e->reg[0], x1, y1);
00074     addVertex(e->reg[0], x2, y2);
00075     addVertex(e->reg[1], x1, y1);
00076     addVertex(e->reg[1], x2, y2);
00077 }
00078 
00079 void clip_line(Edge * e)
00080 {
00081     Site *s1, *s2;
00082     double x1, x2, y1, y2;
00083 
00084     if (e->a == 1.0 && e->b >= 0.0) {
00085         s1 = e->ep[1];
00086         s2 = e->ep[0];
00087     } else {
00088         s1 = e->ep[0];
00089         s2 = e->ep[1];
00090     }
00091 
00092     if (e->a == 1.0) {
00093         if (s1 != (Site *) NULL) {
00094             y1 = s1->coord.y;
00095             if (y1 > pymax)
00096                 return;
00097             else if (y1 >= pymin)
00098                 x1 = s1->coord.x;
00099             else {
00100                 y1 = pymin;
00101                 x1 = e->c - e->b * y1;
00102             }
00103         } else {
00104             y1 = pymin;
00105             x1 = e->c - e->b * y1;
00106         }
00107 
00108         if (s2 != (Site *) NULL) {
00109             y2 = s2->coord.y;
00110             if (y2 < pymin)
00111                 return;
00112             else if (y2 <= pymax)
00113                 x2 = s2->coord.x;
00114             else {
00115                 y2 = pymax;
00116                 x2 = e->c - e->b * y2;
00117             }
00118         } else {
00119             y2 = pymax;
00120             x2 = e->c - e->b * y2;
00121         }
00122 
00123         if (((x1 > pxmax) & (x2 > pxmax)) | ((x1 < pxmin) & (x2 < pxmin)))
00124             return;
00125         if (x1 > pxmax) {
00126             x1 = pxmax;
00127             y1 = (e->c - x1) / e->b;
00128         };
00129         if (x1 < pxmin) {
00130             x1 = pxmin;
00131             y1 = (e->c - x1) / e->b;
00132         };
00133         if (x2 > pxmax) {
00134             x2 = pxmax;
00135             y2 = (e->c - x2) / e->b;
00136         };
00137         if (x2 < pxmin) {
00138             x2 = pxmin;
00139             y2 = (e->c - x2) / e->b;
00140         };
00141     } else {
00142         if (s1 != (Site *) NULL) {
00143             x1 = s1->coord.x;
00144             if (x1 > pxmax)
00145                 return;
00146             else if (x1 >= pxmin)
00147                 y1 = s1->coord.y;
00148             else {
00149                 x1 = pxmin;
00150                 y1 = e->c - e->a * x1;
00151             }
00152         } else {
00153             x1 = pxmin;
00154             y1 = e->c - e->a * x1;
00155         }
00156 
00157         if (s2 != (Site *) NULL) {
00158             x2 = s2->coord.x;
00159             if (x2 < pxmin)
00160                 return;
00161             else if (x2 <= pxmax)
00162                 y2 = s2->coord.y;
00163             else {
00164                 x2 = pxmax;
00165                 y2 = e->c - e->a * x2;
00166             }
00167         } else {
00168             x2 = pxmax;
00169             y2 = e->c - e->a * x2;
00170         }
00171 
00172         if (((y1 > pymax) & (y2 > pymax)) | ((y1 < pymin) & (y2 < pymin)))
00173             return;
00174         if (y1 > pymax) {
00175             y1 = pymax;
00176             x1 = (e->c - y1) / e->a;
00177         };
00178         if (y1 < pymin) {
00179             y1 = pymin;
00180             x1 = (e->c - y1) / e->a;
00181         };
00182         if (y2 > pymax) {
00183             y2 = pymax;
00184             x2 = (e->c - y2) / e->a;
00185         };
00186         if (y2 < pymin) {
00187             y2 = pymin;
00188             x2 = (e->c - y2) / e->a;
00189         };
00190     }
00191 
00192     doSeg(e, x1, y1, x2, y2);
00193 #ifdef STANDALONE
00194     if (doPS)
00195         line(x1, y1, x2, y2);
00196 #endif
00197 }
00198 
00199 void endpoint(Edge * e, int lr, Site * s)
00200 {
00201     e->ep[lr] = s;
00202     ref(s);
00203     if (e->ep[re - lr] == (Site *) NULL)
00204         return;
00205     clip_line(e);
00206 #ifdef STANDALONE
00207     out_ep(e);
00208 #endif
00209     deref(e->reg[le]);
00210     deref(e->reg[re]);
00211     makefree(e, &efl);
00212 }