Graphviz 14.1.2~dev.20260118.1035
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 "config.h"
12
13#include <math.h>
14#include "simple.h"
15#include <stdlib.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
157void find_intersection(struct vertex *l, struct vertex *m,
158 intersections_t *ilist) {
159 double x, y;
160 int i[3];
161 sgnarea(l, m, i);
162
163 if (i[2] > 0)
164 return;
165
166 if (i[2] < 0) {
167 sgnarea(m, l, i);
168 if (i[2] > 0)
169 return;
170 if (!intpoint(l, m, &x, &y, i[2] < 0 ? 3 : online(m, l, abs(i[0]))))
171 return;
172 }
173
174 else if (!intpoint(l, m, &x, &y, i[0] == i[1] ? 2 * MAX(online(l, m, 0),
175 online(l, m, 1)) : online(l, m, abs(i[0]))))
176 return;
177
178 struct intersection inter = {
179 .firstv = l,
180 .secondv = m,
181 .firstp = l->poly,
182 .secondp = m->poly,
183 .x = x,
184 .y = y
185 };
186 LIST_APPEND(ilist, inter);
187}
#define MAX(a, b)
Definition arith.h:33
#define le
Definition edges.h:29
static int between(double f, double g, double h)
Definition intersect.c:58
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
void find_intersection(struct vertex *l, struct vertex *m, intersections_t *ilist)
detect whether lines l and m intersect
Definition intersect.c:157
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:29
#define SLOPE(p, q)
Definition legal.c:25
#define LIST_APPEND(list, item)
Definition list.h:120
struct vertex * firstv
Definition simple.h:36
double y
Definition simple.h:38
double x
Definition simple.h:38
double x
Definition geom.h:29
double y
Definition geom.h:29
double x
Definition simple.h:21
double y
Definition simple.h:21
Definition legal.c:34
pointf pos
Definition legal.c:35
polygon * poly
Definition legal.c:36
#define UNREACHABLE()
Definition unreachable.h:30