Graphviz 13.0.0~dev.20241220.2304
Loading...
Searching...
No Matches
geom.c
Go to the documentation of this file.
1
4/*************************************************************************
5 * Copyright (c) 2011 AT&T Intellectual Property
6 * All rights reserved. This program and the accompanying materials
7 * are made available under the terms of the Eclipse Public License v1.0
8 * which accompanies this distribution, and is available at
9 * https://www.eclipse.org/legal/epl-v10.html
10 *
11 * Contributors: Details at https://graphviz.org
12 *************************************************************************/
13
14/* geometric functions (e.g. on points and boxes) with application to, but
15 * no specific dependence on graphs */
16
17#include "config.h"
18#include <assert.h>
19#include <common/geom.h>
20#include <common/geomprocs.h>
21#include <math.h>
22#include <stdbool.h>
23#include <util/unreachable.h>
24
25/*
26 *--------------------------------------------------------------
27 *
28 * lineToBox --
29 *
30 * Determine whether a line lies entirely inside, entirely
31 * outside, or overlapping a given rectangular area.
32 *
33 * Results:
34 * -1 is returned if the line given by p and q
35 * is entirely outside the rectangle given by b.
36 * 0 is returned if the polygon overlaps the rectangle, and
37 * 1 is returned if the polygon is entirely inside the rectangle.
38 *
39 * Side effects:
40 * None.
41 *
42 *--------------------------------------------------------------
43 */
44
45/* This code steals liberally from algorithms in tk/generic/tkTrig.c -- jce */
46
48{
49 /*
50 * First check the two points individually to see whether they
51 * are inside the rectangle or not.
52 */
53
54 bool inside1 = INSIDE(p, b);
55 bool inside2 = INSIDE(q, b);
56 if (inside1 != inside2) {
57 return 0;
58 }
59 if (inside1 && inside2) {
60 return 1;
61 }
62
63 /*
64 * Both points are outside the rectangle, but still need to check
65 * for intersections between the line and the rectangle. Horizontal
66 * and vertical lines are particularly easy, so handle them
67 * separately.
68 */
69
70 if (p.x == q.x) {
71 /*
72 * Vertical line.
73 */
74
75 if (((p.y >= b.LL.y) ^ (q.y >= b.LL.y)) && BETWEEN(b.LL.x, p.x, b.UR.x)) {
76 return 0;
77 }
78 } else if (p.y == q.y) {
79 /*
80 * Horizontal line.
81 */
82 if (((p.x >= b.LL.x) ^ (q.x >= b.LL.x)) && BETWEEN(b.LL.y, p.y, b.UR.y)) {
83 return 0;
84 }
85 } else {
86 double m, x, y;
87
88 /*
89 * Diagonal line. Compute slope of line and use
90 * for intersection checks against each of the
91 * sides of the rectangle: left, right, bottom, top.
92 */
93
94 m = (q.y - p.y)/(q.x - p.x);
95 double low = fmin(p.x, q.x);
96 double high = fmax(p.x, q.x);
97
98 /*
99 * Left edge.
100 */
101
102 y = p.y + (b.LL.x - p.x)*m;
103 if (BETWEEN(low, b.LL.x, high) && BETWEEN(b.LL.y, y, b.UR.y)) {
104 return 0;
105 }
106
107 /*
108 * Right edge.
109 */
110
111 y += (b.UR.x - b.LL.x)*m;
112 if (BETWEEN(b.LL.y, y, b.UR.y) && BETWEEN(low, b.UR.x, high)) {
113 return 0;
114 }
115
116 /*
117 * Bottom edge.
118 */
119
120 low = fmin(p.y, q.y);
121 high = fmax(p.y, q.y);
122 x = p.x + (b.LL.y - p.y)/m;
123 if (BETWEEN(b.LL.x, x, b.UR.x) && BETWEEN(low, b.LL.y, high)) {
124 return 0;
125 }
126
127 /*
128 * Top edge.
129 */
130
131 x += (b.UR.y - b.LL.y)/m;
132 if (BETWEEN(b.LL.x, x, b.UR.x) && BETWEEN(low, b.UR.y, high)) {
133 return 0;
134 }
135 }
136 return -1;
137}
138
140{
141 p[3].x = p[2].x = p[1].x;
142 p[2].y = p[1].y;
143 p[3].y = p[0].y;
144 p[1].x = p[0].x;
145}
146
148{
149 assert(cwrot == 0 || cwrot == 90 || cwrot == 180 || cwrot == 270);
150 double x = p.x, y = p.y;
151 switch (cwrot) {
152 case 0:
153 break;
154 case 90:
155 p.x = y;
156 p.y = -x;
157 break;
158 case 180:
159 p.x = x;
160 p.y = -y;
161 break;
162 case 270:
163 p.x = y;
164 p.y = x;
165 break;
166 default:
167 UNREACHABLE();
168 }
169 return p;
170}
171
173{
174 assert(ccwrot == 0 || ccwrot == 90 || ccwrot == 180 || ccwrot == 270);
175 double x = p.x, y = p.y;
176 switch (ccwrot) {
177 case 0:
178 break;
179 case 90:
180 p.x = -y;
181 p.y = x;
182 break;
183 case 180:
184 p.x = x;
185 p.y = -y;
186 break;
187 case 270:
188 p.x = y;
189 p.y = x;
190 break;
191 default:
192 UNREACHABLE();
193 }
194 return p;
195}
196
198{
199 boxf r;
200 /* flip box */
201 r.UR.x = b.UR.y;
202 r.UR.y = b.UR.x;
203 r.LL.x = b.LL.y;
204 r.LL.y = b.LL.x;
205 /* move box */
206 r.LL.x += p.x;
207 r.LL.y += p.y;
208 r.UR.x += p.x;
209 r.UR.y += p.y;
210 return r;
211}
212
213#define SMALL 0.0000000001
214
215/* ptToLine2:
216 * Return distance from point p to line a-b squared.
217 */
219{
220 double dx = b.x-a.x;
221 double dy = b.y-a.y;
222 double a2 = (p.y-a.y)*dx - (p.x-a.x)*dy;
223 a2 *= a2; /* square - ensures that it is positive */
224 if (a2 < SMALL) return 0.; /* avoid 0/0 problems */
225 return a2 / (dx*dx + dy*dy);
226}
227
228#define dot(v,w) (v.x*w.x+v.y*w.y)
229
230/* line_intersect:
231 * Computes intersection of lines a-b and c-d, returning intersection
232 * point in *p.
233 * Returns 0 if no intersection (lines parallel), 1 otherwise.
234 */
236{
237
238 pointf mv = sub_pointf(b,a);
239 pointf lv = sub_pointf(d,c);
240 pointf ln = perp (lv);
241 double lc = -dot(ln,c);
242 double dt = dot(ln,mv);
243
244 if (fabs(dt) < SMALL) return 0;
245
246 *p = sub_pointf(a,scale((dot(ln,a)+lc)/dt,mv));
247 return 1;
248}
249
#define BETWEEN(a, b, c)
Definition arith.h:38
static float dy
Definition draw.c:38
static float dx
Definition draw.c:37
int lineToBox(pointf p, pointf q, boxf b)
Definition geom.c:47
#define SMALL
Definition geom.c:213
boxf flip_rec_boxf(boxf b, pointf p)
Definition geom.c:197
void rect2poly(pointf *p)
Definition geom.c:139
#define dot(v, w)
Definition geom.c:228
pointf ccwrotatepf(pointf p, int ccwrot)
Definition geom.c:172
double ptToLine2(pointf a, pointf b, pointf p)
Definition geom.c:218
pointf cwrotatepf(pointf p, int cwrot)
Definition geom.c:147
int line_intersect(pointf a, pointf b, pointf c, pointf d, pointf *p)
Definition geom.c:235
geometric types and macros (e.g. points and boxes)
#define INSIDE(p, b)
Definition geom.h:45
geometric functions (e.g. on points and boxes)
static pointf sub_pointf(pointf p, pointf q)
Definition geomprocs.h:72
static pointf scale(double c, pointf p)
Definition geomprocs.h:130
static pointf perp(pointf p)
Definition geomprocs.h:121
Definition geom.h:41
pointf UR
Definition geom.h:41
pointf LL
Definition geom.h:41
double x
Definition geom.h:29
double y
Definition geom.h:29
#define UNREACHABLE()
Definition unreachable.h:30