Graphviz 13.1.3~dev.20250815.1023
Loading...
Searching...
No Matches
intersect.c
Go to the documentation of this file.
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
11#include <math.h>
12#include <stdio.h>
13#include "simple.h"
14#include <stdlib.h>
15#include <util/exit.h>
16#include <util/unreachable.h>
17
18static int sign(double v) {
19 if (v < 0)
20 return -1;
21 if (v > 0)
22 return 1;
23 return 0;
24}
25
26/* find the sign of the area of each of the triangles
27 formed by adding a vertex of m to l
28 also find the sign of their product */
29static void sgnarea(struct vertex *l, struct vertex *m, int i[])
30{
31 const double a = l->pos.x;
32 const double b = l->pos.y;
33 const double c = after(l)->pos.x - a;
34 const double d = after(l)->pos.y - b;
35 const double e = m->pos.x - a;
36 const double f = m->pos.y - b;
37 const double g = after(m)->pos.x - a;
38 const double h = after(m)->pos.y - b;
39 double t = c * f - d * e;
40 i[0] = sign(t);
41 t = c * h - d * g;
42 i[1] = sign(t);
43 i[2] = i[0] * i[1];
44}
45
58static int between(double f, double g, double h) {
59 if (f < g) {
60 if (g < h) {
61 return 1;
62 }
63 if (g > h) {
64 return -1;
65 }
66 return 0;
67 }
68 if (f > g) {
69 if (g > h) {
70 return 1;
71 }
72 if (g < h) {
73 return -1;
74 }
75 return 0;
76 }
77 return 0;
78}
79
80/* determine if vertex i of line m is on line l */
81static int online(struct vertex *l, struct vertex *m, int i)
82{
83 struct position a, b, c;
84 a = l->pos;
85 b = after(l)->pos;
86 c = i == 0 ? m->pos : after(m)->pos;
87 return a.x == b.x ? (a.x == c.x && -1 != between(a.y, c.y, b.y))
88 : between(a.x, c.x, b.x);
89}
90
91/* determine point of detected intersections */
92static int intpoint(struct vertex *l, struct vertex *m, double *x, double *y,
93 int cond) {
94 struct position ls, le, ms, me, pt1, pt2;
95
96 if (cond <= 0)
97 return (0);
98 ls = l->pos;
99 le = after(l)->pos;
100 ms = m->pos;
101 me = after(m)->pos;
102
103 switch (cond) {
104
105 case 3: /* a simple intersection */
106 if (ls.x == le.x) {
107 *x = ls.x;
108 *y = me.y + SLOPE(ms, me) * (*x - me.x);
109 } else if (ms.x == me.x) {
110 *x = ms.x;
111 *y = le.y + SLOPE(ls, le) * (*x - le.x);
112 } else {
113 const double m1 = SLOPE(ms, me);
114 const double m2 = SLOPE(ls, le);
115 const double c1 = ms.y - m1 * ms.x;
116 const double c2 = ls.y - m2 * ls.x;
117 *x = (c2 - c1) / (m1 - m2);
118 *y = (m1 * c2 - c1 * m2) / (m1 - m2);
119 }
120 break;
121
122 case 2: /* the two lines have a common segment */
123 if (online(l, m, 0) == -1) { /* ms between ls and le */
124 pt1 = ms;
125 pt2 = online(m, l, 1) == -1 ? (online(m, l, 0 == -1) ? le : ls) : me;
126 } else if (online(l, m, 1) == -1) { /* me between ls and le */
127 pt1 = me;
128 pt2 = online(l, m, 0) == -1 ? (online(m, l, 0) == -1 ? le : ls) : ms;
129 } else {
130 /* may be degenerate? */
131 if (online(m, l, 0) != -1)
132 return 0;
133 pt1 = ls;
134 pt2 = le;
135 }
136
137 *x = (pt1.x + pt2.x) / 2;
138 *y = (pt1.y + pt2.y) / 2;
139 break;
140
141 case 1: /* a vertex of line m is on line l */
142 if ((ls.x - le.x) * (ms.y - ls.y) == (ls.y - le.y) * (ms.x - ls.x)) {
143 *x = ms.x;
144 *y = ms.y;
145 } else {
146 *x = me.x;
147 *y = me.y;
148 }
149 break;
150
151 default:
152 UNREACHABLE();
153 } /* end switch */
154 return 1;
155}
156
158 struct vertex *m,
159 struct intersection ilist[], struct data *input)
160{
161 double x, y;
162 int i[3];
163 sgnarea(l, m, i);
164
165 if (i[2] > 0)
166 return;
167
168 if (i[2] < 0) {
169 sgnarea(m, l, i);
170 if (i[2] > 0)
171 return;
172 if (!intpoint(l, m, &x, &y, i[2] < 0 ? 3 : online(m, l, abs(i[0]))))
173 return;
174 }
175
176 else if (!intpoint(l, m, &x, &y, i[0] == i[1] ? 2 * MAX(online(l, m, 0),
177 online(l, m, 1)) : online(l, m, abs(i[0]))))
178 return;
179
180 if (input->ninters >= MAXINTS) {
181 fprintf(stderr, "\n**ERROR**\n using too many intersections\n");
182 graphviz_exit(1);
183 }
184
185 ilist[input->ninters].firstv = l;
186 ilist[input->ninters].secondv = m;
187 ilist[input->ninters].firstp = l->poly;
188 ilist[input->ninters].secondp = m->poly;
189 ilist[input->ninters].x = x;
190 ilist[input->ninters].y = y;
191 input->ninters++;
192}
#define le
Definition edges.h:31
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
static int between(double f, double g, double h)
Definition intersect.c:58
void find_intersection(struct vertex *l, struct vertex *m, struct intersection ilist[], struct data *input)
detect whether lines l and m intersect
Definition intersect.c:157
static void sgnarea(struct vertex *l, struct vertex *m, int i[])
Definition intersect.c:29
static int online(struct vertex *l, struct vertex *m, int i)
Definition intersect.c:81
static int sign(double v)
Definition intersect.c:18
static int intpoint(struct vertex *l, struct vertex *m, double *x, double *y, int cond)
Definition intersect.c:92
#define after(v)
Definition legal.c:25
#define SLOPE(p, q)
Definition legal.c:21
#define MAXINTS
Definition simple.h:13
Definition legal.c:50
int ninters
Definition legal.c:51
struct vertex * firstv
Definition simple.h:37
double y
Definition simple.h:39
struct polygon * firstp
Definition simple.h:38
struct vertex * secondv
Definition simple.h:37
double x
Definition simple.h:39
struct polygon * secondp
Definition simple.h:38
double x
Definition geom.h:29
double y
Definition geom.h:29
double x
Definition simple.h:22
double y
Definition simple.h:22
Definition legal.c:31
pointf pos
Definition legal.c:32
polygon * poly
Definition legal.c:33
#define UNREACHABLE()
Definition unreachable.h:30
#define MAX(a, b)
Definition write.c:32