/misc/src/release/graphviz-2.18-1/src/graphviz-2.18/lib/neatogen/intersect.c

Go to the documentation of this file.
00001 /* $Id: intersect.c,v 1.2 2005/02/24 00:57:33 ellson Exp $ $Revision: 1.2 $ */
00002 /* vim:set shiftwidth=4 ts=8: */
00003 
00004 /**********************************************************
00005 *      This software is part of the graphviz package      *
00006 *                http://www.graphviz.org/                 *
00007 *                                                         *
00008 *            Copyright (c) 1994-2004 AT&T Corp.           *
00009 *                and is licensed under the                *
00010 *            Common Public License, Version 1.0           *
00011 *                      by AT&T Corp.                      *
00012 *                                                         *
00013 *        Information and Software Systems Research        *
00014 *              AT&T Research, Florham Park NJ             *
00015 **********************************************************/
00016 
00017 #include "neato.h"
00018 #include "simple.h"
00019 
00020 /* find the sign of the area of each of the triangles
00021     formed by adding a vertex of m to l  
00022     also find the sign of their product  */
00023 static void sgnarea(struct vertex *l, struct vertex *m, int i[])
00024 {
00025     double a, b, c, d, e, f, g, h, t;
00026     a = l->pos.x;
00027     b = l->pos.y;
00028     c = after(l)->pos.x - a;
00029     d = after(l)->pos.y - b;
00030     e = m->pos.x - a;
00031     f = m->pos.y - b;
00032     g = after(m)->pos.x - a;
00033     h = after(m)->pos.y - b;
00034     t = (c * f) - (d * e);
00035     i[0] = ((t == 0) ? 0 : (t > 0 ? 1 : -1));
00036     t = (c * h) - (d * g);
00037     i[1] = ((t == 0) ? 0 : (t > 0 ? 1 : -1));
00038     i[2] = i[0] * i[1];
00039 }
00040 
00041 /* determine if g lies between f and h      */
00042 static int between(double f, double g, double h)
00043 {
00044     if ((f == g) || (g == h))
00045         return (0);
00046     return ((f < g) ? (g < h ? 1 : -1) : (h < g ? 1 : -1));
00047 }
00048 
00049 /* determine if vertex i of line m is on line l     */
00050 static int online(struct vertex *l, struct vertex *m, int i)
00051 {
00052     struct position a, b, c;
00053     a = l->pos;
00054     b = after(l)->pos;
00055     c = (i == 0) ? m->pos : after(m)->pos;
00056     return ((a.x == b.x) ? ((a.x == c.x)
00057                             && (-1 !=
00058                                 between(a.y, c.y, b.y))) : between(a.x,
00059                                                                    c.x,
00060                                                                    b.x));
00061 }
00062 
00063 /* determine point of detected intersections  */
00064 static int intpoint(struct vertex *l, struct vertex *m, double *x, double *y, int cond)
00065 {
00066     struct position ls, le, ms, me, pt1, pt2;
00067     double m1, m2, c1, c2;
00068 
00069     if (cond <= 0)
00070         return (0);
00071     ls = l->pos;
00072     le = after(l)->pos;
00073     ms = m->pos;
00074     me = after(m)->pos;
00075 
00076     switch (cond) {
00077 
00078     case 3:                     /* a simple intersection        */
00079         if (ls.x == le.x) {
00080             *x = ls.x;
00081             *y = me.y + SLOPE(ms, me) * (*x - me.x);
00082         } else if (ms.x == me.x) {
00083             *x = ms.x;
00084             *y = le.y + SLOPE(ls, le) * (*x - le.x);
00085         } else {
00086             m1 = SLOPE(ms, me);
00087             m2 = SLOPE(ls, le);
00088             c1 = ms.y - (m1 * ms.x);
00089             c2 = ls.y - (m2 * ls.x);
00090             *x = (c2 - c1) / (m1 - m2);
00091             *y = ((m1 * c2) - (c1 * m2)) / (m1 - m2);
00092         }
00093         break;
00094 
00095     case 2:                     /*     the two lines  have a common segment  */
00096         if (online(l, m, 0) == -1) {    /* ms between ls and le */
00097             pt1 = ms;
00098             pt2 =
00099                 (online(m, l, 1) ==
00100                  -1) ? ((online(m, l, 0) == -1) ? le : ls) : me;
00101         } else if (online(l, m, 1) == -1) {     /* me between ls and le */
00102             pt1 = me;
00103             pt2 =
00104                 (online(l, m, 0) ==
00105                  -1) ? ((online(m, l, 0) == -1) ? le : ls) : ms;
00106         } else {
00107             /* may be degenerate? */
00108             if (online(m, l, 0) != -1)
00109                 return 0;
00110             pt1 = ls;
00111             pt2 = le;
00112         }
00113 
00114         *x = (pt1.x + pt2.x) / 2;
00115         *y = (pt1.y + pt2.y) / 2;
00116         break;
00117 
00118     case 1:                     /* a vertex of line m is on line l */
00119         if ((ls.x - le.x) * (ms.y - ls.y) == (ls.y - le.y) * (ms.x - ls.x)) {
00120             *x = ms.x;
00121             *y = ms.y;
00122         } else {
00123             *x = me.x;
00124             *y = me.y;
00125         }
00126     }                           /* end switch  */
00127     return (1);
00128 }
00129 
00130 /*detect whether lines l and m intersect      */
00131 void find_intersection(struct vertex *l,
00132                   struct vertex *m,
00133                   struct intersection ilist[], struct data *input)
00134 {
00135     double x, y;
00136     int i[3];
00137     sgnarea(l, m, i);
00138 
00139     if (i[2] > 0)
00140         return;
00141 
00142     if (i[2] < 0) {
00143         sgnarea(m, l, i);
00144         if (i[2] > 0)
00145             return;
00146         if (!intpoint
00147             (l, m, &x, &y, (i[2] < 0) ? 3 : online(m, l, ABS(i[0]))))
00148             return;
00149     }
00150 
00151     else if (!intpoint(l, m, &x, &y, (i[0] == i[1]) ?
00152                        2 * MAX(online(l, m, 0),
00153                                online(l, m, 1)) : online(l, m, ABS(i[0]))))
00154         return;
00155 
00156     if (input->ninters >= MAXINTS) {
00157         agerr(AGERR, "using too many intersections\n");
00158         exit(1);
00159     }
00160 
00161     ilist[input->ninters].firstv = l;
00162     ilist[input->ninters].secondv = m;
00163     ilist[input->ninters].firstp = l->poly;
00164     ilist[input->ninters].secondp = m->poly;
00165     ilist[input->ninters].x = x;
00166     ilist[input->ninters].y = y;
00167     input->ninters++;
00168 }

Generated on Mon Mar 31 19:03:27 2008 for Graphviz by  doxygen 1.5.1