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