Graphviz 14.1.2~dev.20260119.0928
Loading...
Searching...
No Matches
edges.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 <assert.h>
14#include <neatogen/neato.h>
15#include <neatogen/info.h>
16#include <neatogen/edges.h>
17#include <math.h>
18#include <stddef.h>
19#include <util/arena.h>
20
21double pxmin, pxmax, pymin, pymax; /* clipping window */
22
23Edge *gvbisect(Site *s1, Site *s2, arena_t *allocator) {
24 assert(allocator != NULL);
25 double dx, dy, adx, ady;
26 Edge *newedge = ARENA_NEW(allocator, Edge);
27
28 newedge->reg[0] = s1;
29 newedge->reg[1] = s2;
30 newedge->ep[0] = NULL;
31 newedge->ep[1] = NULL;
32
33 dx = s2->coord.x - s1->coord.x;
34 dy = s2->coord.y - s1->coord.y;
35 adx = fabs(dx);
36 ady = fabs(dy);
37 newedge->c =
38 s1->coord.x * dx + s1->coord.y * dy + (dx * dx + dy * dy) * 0.5;
39 if (adx > ady) {
40 newedge->a = 1.0;
41 newedge->b = dy / dx;
42 newedge->c /= dx;
43 } else {
44 newedge->b = 1.0;
45 newedge->a = dx / dy;
46 newedge->c /= dy;
47 }
48
49 return newedge;
50}
51
52
53static void doSeg(Edge * e, double x1, double y1, double x2, double y2)
54{
55 addVertex(e->reg[0], x1, y1);
56 addVertex(e->reg[0], x2, y2);
57 addVertex(e->reg[1], x1, y1);
58 addVertex(e->reg[1], x2, y2);
59}
60
61void clip_line(Edge * e)
62{
63 Site *s1, *s2;
64 double x1, x2, y1, y2;
65
66 if (e->a == 1.0 && e->b >= 0.0) {
67 s1 = e->ep[1];
68 s2 = e->ep[0];
69 } else {
70 s1 = e->ep[0];
71 s2 = e->ep[1];
72 }
73
74 if (e->a == 1.0) {
75 if (s1 != NULL) {
76 y1 = s1->coord.y;
77 if (y1 > pymax)
78 return;
79 else if (y1 >= pymin)
80 x1 = s1->coord.x;
81 else {
82 y1 = pymin;
83 x1 = e->c - e->b * y1;
84 }
85 } else {
86 y1 = pymin;
87 x1 = e->c - e->b * y1;
88 }
89
90 if (s2 != NULL) {
91 y2 = s2->coord.y;
92 if (y2 < pymin)
93 return;
94 else if (y2 <= pymax)
95 x2 = s2->coord.x;
96 else {
97 y2 = pymax;
98 x2 = e->c - e->b * y2;
99 }
100 } else {
101 y2 = pymax;
102 x2 = e->c - e->b * y2;
103 }
104
105 if ((x1 > pxmax && x2 > pxmax) || (x1 < pxmin && x2 < pxmin))
106 return;
107 if (x1 > pxmax) {
108 x1 = pxmax;
109 y1 = (e->c - x1) / e->b;
110 }
111 if (x1 < pxmin) {
112 x1 = pxmin;
113 y1 = (e->c - x1) / e->b;
114 }
115 if (x2 > pxmax) {
116 x2 = pxmax;
117 y2 = (e->c - x2) / e->b;
118 }
119 if (x2 < pxmin) {
120 x2 = pxmin;
121 y2 = (e->c - x2) / e->b;
122 }
123 } else {
124 if (s1 != NULL) {
125 x1 = s1->coord.x;
126 if (x1 > pxmax)
127 return;
128 else if (x1 >= pxmin)
129 y1 = s1->coord.y;
130 else {
131 x1 = pxmin;
132 y1 = e->c - e->a * x1;
133 }
134 } else {
135 x1 = pxmin;
136 y1 = e->c - e->a * x1;
137 }
138
139 if (s2 != NULL) {
140 x2 = s2->coord.x;
141 if (x2 < pxmin)
142 return;
143 else if (x2 <= pxmax)
144 y2 = s2->coord.y;
145 else {
146 x2 = pxmax;
147 y2 = e->c - e->a * x2;
148 }
149 } else {
150 x2 = pxmax;
151 y2 = e->c - e->a * x2;
152 }
153
154 if ((y1 > pymax && y2 > pymax) || (y1 < pymin && y2 < pymin))
155 return;
156 if (y1 > pymax) {
157 y1 = pymax;
158 x1 = (e->c - y1) / e->a;
159 }
160 if (y1 < pymin) {
161 y1 = pymin;
162 x1 = (e->c - y1) / e->a;
163 }
164 if (y2 > pymax) {
165 y2 = pymax;
166 x2 = (e->c - y2) / e->a;
167 }
168 if (y2 < pymin) {
169 y2 = pymin;
170 x2 = (e->c - y2) / e->a;
171 }
172 }
173
174 doSeg(e, x1, y1, x2, y2);
175}
176
177void endpoint(Edge *e, int lr, Site *s, arena_t *allocator) {
178 assert(allocator != NULL);
179 e->ep[lr] = s;
180 if (e->ep[re - lr] == NULL)
181 return;
182 clip_line(e);
183 gv_arena_free(allocator, e, sizeof(*e));
184}
void gv_arena_free(arena_t *arena, void *ptr, size_t size)
Definition arena.c:151
Region-based memory allocator.
#define ARENA_NEW(arena, type)
Definition arena.h:55
static float dy
Definition draw.c:43
static float dx
Definition draw.c:42
static Agedge_t * newedge(Agraph_t *g, Agnode_t *t, Agnode_t *h, IDTYPE id)
Definition edge.c:194
double pymin
Definition edges.c:21
static void doSeg(Edge *e, double x1, double y1, double x2, double y2)
Definition edges.c:53
double pymax
Definition edges.c:21
double pxmin
Definition edges.c:21
void clip_line(Edge *e)
Definition edges.c:61
void endpoint(Edge *e, int lr, Site *s, arena_t *allocator)
Definition edges.c:177
Edge * gvbisect(Site *s1, Site *s2, arena_t *allocator)
Definition edges.c:23
double pxmax
Definition edges.c:21
#define re
Definition edges.h:30
node NULL
Definition grammar.y:181
void addVertex(Site *s, double x, double y)
insert vertex into sorted list
Definition info.c:102
NEATOPROCS_API void s1(graph_t *, node_t *)
Definition stuff.c:651
Definition edges.h:23
Site * ep[2]
Definition edges.h:25
double b
Definition edges.h:24
double c
Definition edges.h:24
Site * reg[2]
Definition edges.h:26
double a
Definition edges.h:24
double x
Definition geometry.h:24
double y
Definition geometry.h:24
Definition site.h:23
Point coord
Definition site.h:24
Definition grammar.c:90