Graphviz 13.1.1~dev.20250718.1235
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 // vertical line
72 if (((p.y >= b.LL.y) ^ (q.y >= b.LL.y)) && BETWEEN(b.LL.x, p.x, b.UR.x)) {
73 return 0;
74 }
75 } else if (p.y == q.y) {
76 // horizontal line
77 if (((p.x >= b.LL.x) ^ (q.x >= b.LL.x)) && BETWEEN(b.LL.y, p.y, b.UR.y)) {
78 return 0;
79 }
80 } else {
81 double m, x, y;
82
83 /*
84 * Diagonal line. Compute slope of line and use
85 * for intersection checks against each of the
86 * sides of the rectangle: left, right, bottom, top.
87 */
88
89 m = (q.y - p.y)/(q.x - p.x);
90 double low = fmin(p.x, q.x);
91 double high = fmax(p.x, q.x);
92
93 // left edge
94 y = p.y + (b.LL.x - p.x)*m;
95 if (BETWEEN(low, b.LL.x, high) && BETWEEN(b.LL.y, y, b.UR.y)) {
96 return 0;
97 }
98
99 // right edge
100 y += (b.UR.x - b.LL.x)*m;
101 if (BETWEEN(b.LL.y, y, b.UR.y) && BETWEEN(low, b.UR.x, high)) {
102 return 0;
103 }
104
105 // bottom edge
106 low = fmin(p.y, q.y);
107 high = fmax(p.y, q.y);
108 x = p.x + (b.LL.y - p.y)/m;
109 if (BETWEEN(b.LL.x, x, b.UR.x) && BETWEEN(low, b.LL.y, high)) {
110 return 0;
111 }
112
113 // top edge
114 x += (b.UR.y - b.LL.y)/m;
115 if (BETWEEN(b.LL.x, x, b.UR.x) && BETWEEN(low, b.UR.y, high)) {
116 return 0;
117 }
118 }
119 return -1;
120}
121
123{
124 p[3].x = p[2].x = p[1].x;
125 p[2].y = p[1].y;
126 p[3].y = p[0].y;
127 p[1].x = p[0].x;
128}
129
131{
132 assert(cwrot == 0 || cwrot == 90 || cwrot == 180 || cwrot == 270);
133 switch (cwrot) {
134 case 0:
135 break;
136 case 90:
137 return (pointf){.x = p.y, .y = -p.x};
138 case 180:
139 return (pointf){.x = p.x, .y = -p.y};
140 case 270:
141 return exch_xyf(p);
142 default:
143 UNREACHABLE();
144 }
145 return p;
146}
147
149{
150 assert(ccwrot == 0 || ccwrot == 90 || ccwrot == 180 || ccwrot == 270);
151 switch (ccwrot) {
152 case 0:
153 break;
154 case 90:
155 return perp(p);
156 case 180:
157 return (pointf){.x = p.x, .y = -p.y};
158 case 270:
159 return exch_xyf(p);
160 default:
161 UNREACHABLE();
162 }
163 return p;
164}
165
167{
168 /* flip box */
169 boxf r = {.LL = exch_xyf(b.LL), .UR = exch_xyf(b.UR)};
170 /* move box */
171 r.LL = add_pointf(r.LL, p);
172 r.UR = add_pointf(r.UR, p);
173 return r;
174}
175
176#define SMALL 0.0000000001
177
178/* ptToLine2:
179 * Return distance from point p to line a-b squared.
180 */
182{
183 double dx = b.x-a.x;
184 double dy = b.y-a.y;
185 double a2 = (p.y-a.y)*dx - (p.x-a.x)*dy;
186 a2 *= a2; /* square - ensures that it is positive */
187 if (a2 < SMALL) return 0.; /* avoid 0/0 problems */
188 return a2 / (dx*dx + dy*dy);
189}
190
191#define dot(v,w) (v.x*w.x+v.y*w.y)
192
193/* line_intersect:
194 * Computes intersection of lines a-b and c-d, returning intersection
195 * point in *p.
196 * Returns 0 if no intersection (lines parallel), 1 otherwise.
197 */
199{
200
201 pointf mv = sub_pointf(b,a);
202 pointf lv = sub_pointf(d,c);
203 pointf ln = perp (lv);
204 double lc = -dot(ln,c);
205 double dt = dot(ln,mv);
206
207 if (fabs(dt) < SMALL) return 0;
208
209 *p = sub_pointf(a,scale((dot(ln,a)+lc)/dt,mv));
210 return 1;
211}
212
#define BETWEEN(a, b, c)
Definition arith.h:38
static float dy
Definition draw.c:39
static float dx
Definition draw.c:38
int lineToBox(pointf p, pointf q, boxf b)
Definition geom.c:47
#define SMALL
Definition geom.c:176
boxf flip_rec_boxf(boxf b, pointf p)
Definition geom.c:166
void rect2poly(pointf *p)
Definition geom.c:122
#define dot(v, w)
Definition geom.c:191
pointf ccwrotatepf(pointf p, int ccwrot)
Definition geom.c:148
double ptToLine2(pointf a, pointf b, pointf p)
Definition geom.c:181
pointf cwrotatepf(pointf p, int cwrot)
Definition geom.c:130
int line_intersect(pointf a, pointf b, pointf c, pointf d, pointf *p)
Definition geom.c:198
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 add_pointf(pointf p, pointf q)
Definition geomprocs.h:88
static pointf sub_pointf(pointf p, pointf q)
Definition geomprocs.h:97
static pointf scale(double c, pointf p)
Definition geomprocs.h:155
static pointf exch_xyf(pointf p)
Definition geomprocs.h:133
static pointf perp(pointf p)
Definition geomprocs.h:146
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