Graphviz 14.0.5~dev.20251126.0104
Loading...
Searching...
No Matches
edge_distinct_coloring.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 <sparse/general.h>
12#include <math.h>
13#include <stdbool.h>
14#include <string.h>
15#include <time.h>
16#include <sparse/SparseMatrix.h>
19#include <sparse/DotIO.h>
21#include <sparse/QuadTree.h>
22#include <util/list.h>
23
24static int splines_intersect(size_t dim,
25 double cos_critical, int check_edges_with_same_endpoint,
26 char *xsplines1, char *xsplines2){
27 /* cos_critical: cos of critical angle
28 check_edges_with_same_endpoint: whether need to treat two splines from
29 . the same end point specially in ignoring splines that exit/enter the same end point at around 180
30 xsplines1,xsplines2: the first and second splines corresponding to two edges
31
32 */
33 int iter1 = 0, iter2 = 0;
34 double cos_a;
35 bool endp1 = false;
36 bool endp2 = false;
37
38 double tmp[2] = {0};
39 LIST(double) x1 = {0};
40 LIST(double) x2 = {0};
41
42 assert(dim == 2);
43
44 /* splines could be a list of
45 1. 3n points
46 2. of the form "e,x,y" followed by 3n points, where x,y is really padded to the end of the 3n points
47 3. of the form "s,x,y" followed by 3n points, where x,y is padded to the start of the 3n points
48 */
49 if (xsplines1){
50 if(strstr(xsplines1, "e,")){
51 endp1 = true;
52 xsplines1 = strstr(xsplines1, "e,") + 2;
53 } else if (strstr(xsplines1, "s,")){
54 xsplines1 = strstr(xsplines1, "s,") + 2;
55 }
56 }
57 for (double x, y; xsplines1 && sscanf(xsplines1,"%lf,%lf", &x, &y) == 2; ) {
58 if (endp1 && iter1 == 0){
59 tmp[0] = x;
60 tmp[1] = y;
61 } else {
62 LIST_APPEND(&x1, x);
63 LIST_APPEND(&x1, y);
64 }
65 iter1++;
66 xsplines1 = strchr(xsplines1, ' ');
67 if (!xsplines1) break;
68 xsplines1++;
69 }
70 if (endp1){/* pad the end point at the last position */
71 LIST_APPEND(&x1, tmp[0]);
72 LIST_APPEND(&x1, tmp[1]);
73 }
74
75
76 /* splines could be a list of
77 1. 3n points
78 2. of the form "e,x,y" followed by 3n points, where x,y is really padded to the end of the 3n points
79 3. of the form "s,x,y" followed by 3n points, where x,y is padded to the start of the 3n points
80 */
81 if (xsplines2){
82 if(strstr(xsplines2, "e,")){
83 endp2 = true;
84 xsplines2 = strstr(xsplines2, "e,") + 2;
85 } else if (strstr(xsplines2, "s,")){
86 xsplines2 = strstr(xsplines2, "s,") + 2;
87 }
88 }
89 for (double x, y; xsplines2 && sscanf(xsplines2,"%lf,%lf", &x, &y) == 2; ) {
90 if (endp2 && iter2 == 0){
91 tmp[0] = x;
92 tmp[1] = y;
93 } else {
94 LIST_APPEND(&x2, x);
95 LIST_APPEND(&x2, y);
96 }
97 iter2++;
98 xsplines2 = strchr(xsplines2, ' ');
99 if (!xsplines2) break;
100 xsplines2++;
101 }
102 if (endp2){/* pad the end point at the last position */
103 LIST_APPEND(&x2, tmp[0]);
104 LIST_APPEND(&x2, tmp[1]);
105 }
106
107 assert(LIST_SIZE(&x1) % dim == 0);
108 for (size_t i = 0; i < LIST_SIZE(&x1) / 2 - 1; i++) {
109 assert(LIST_SIZE(&x2) % dim == 0);
110 for (size_t j = 0; j < LIST_SIZE(&x2) / 2 - 1; j++) {
111 cos_a = intersection_angle(LIST_AT(&x1, dim * i),
112 LIST_AT(&x1, dim * (i + 1)),
113 LIST_AT(&x2, dim * j),
114 LIST_AT(&x2, dim * (j + 1)));
115 if (!check_edges_with_same_endpoint && cos_a >= -1) cos_a = fabs(cos_a);
116 if (cos_a > cos_critical) {
117 LIST_FREE(&x1);
118 LIST_FREE(&x2);
119 return 1;
120 }
121
122 }
123 }
124
125 LIST_FREE(&x1);
126 LIST_FREE(&x2);
127 return 0;
128}
129
130Agraph_t *edge_distinct_coloring(const char *color_scheme, int *lightness,
131 Agraph_t *g, double angle, double accuracy,
132 int check_edges_with_same_endpoint, int seed) {
133 double *x = NULL;
134 int dim = 2;
135 SparseMatrix A, B, C;
136 int *irn, *jcn, nz, nz2 = 0;
137 double cos_critical = cos(angle/180*3.14159), cos_a;
138 int u1, v1, u2, v2, i, j;
139 double *colors = NULL;
140 int flag, ne;
141 char **xsplines = NULL;
142 int cdim;
143
145 if (!x){
146 fprintf(stderr,"The gv file contains no or improper 2D coordinates\n");
147 return NULL;
148 }
149
150
151 irn = A->ia; jcn = A->ja;
152 nz = A->nz;
153
154 /* get rid of self edges */
155 for (i = 0; i < nz; i++){
156 if (irn[i] != jcn[i]){
157 irn[nz2] = irn[i];
158 jcn[nz2++] = jcn[i];
159 }
160 }
161
162 if (Verbose)
163 fprintf(stderr,"cos = %f, nz2 = %d\n", cos_critical, nz2);
164 /* now find edge collision */
166
167 if (Import_dot_splines(g, &ne, &xsplines)){
168#ifdef TIME
169 clock_t start = clock();
170#endif
171 assert(ne == nz2);
172 cos_a = 1.;/* for splines we exit conflict check as soon as we find an conflict, so the angle may not be representative, hence set to constant */
173 for (i = 0; i < nz2; i++){
174 for (j = i+1; j < nz2; j++){
175 if (splines_intersect((size_t)dim, cos_critical,
176 check_edges_with_same_endpoint, xsplines[i],
177 xsplines[j])) {
179 }
180 }
181 }
182#ifdef TIME
183 fprintf(stderr, "cpu for dual graph =%10.3f", ((double) (clock() - start))/CLOCKS_PER_SEC);
184#endif
185
186 } else {
187 /* no splines, just simple edges */
188#ifdef TIME
189 clock_t start = clock();
190#endif
191
192
193 for (i = 0; i < nz2; i++){
194 u1 = irn[i]; v1 = jcn[i];
195 for (j = i+1; j < nz2; j++){
196 u2 = irn[j]; v2 = jcn[j];
197 cos_a = intersection_angle(&(x[dim*u1]), &(x[dim*v1]), &(x[dim*u2]), &(x[dim*v2]));
198 if (!check_edges_with_same_endpoint && cos_a >= -1) cos_a = fabs(cos_a);
199 if (cos_a > cos_critical) {
201 }
202 }
203 }
204#ifdef TIME
205 fprintf(stderr, "cpu for dual graph (splines) =%10.3f\n", ((double) (clock() - start))/CLOCKS_PER_SEC);
206#endif
207 }
209 if (B != C) SparseMatrix_delete(B);
210
211 {
212#ifdef TIME
213 clock_t start = clock();
214#endif
215 const bool weightedQ = false;
216 flag = node_distinct_coloring(color_scheme, lightness, weightedQ, C,
217 accuracy, seed, &cdim, &colors);
218 if (flag) goto RETURN;
219#ifdef TIME
220 fprintf(stderr, "cpu for color assignment =%10.3f\n", ((double) (clock() - start))/CLOCKS_PER_SEC);
221#endif
222 }
223
224 if (Verbose)
225 fprintf(stderr,"The edge conflict graph has %d nodes and %d edges\n", C->m, C->nz);
226
227 attach_edge_colors(g, cdim, colors);
228
229 RETURN:
232 free(colors);
233 free(x);
234 if (xsplines){
235 for (i = 0; i < ne; i++){
236 free(xsplines[i]);
237 }
238 free(xsplines);
239 }
240 return g;
241}
SparseMatrix SparseMatrix_import_dot(Agraph_t *g, int dim, double **x, int format)
Definition DotIO.c:81
void attach_edge_colors(Agraph_t *g, int dim, double *colors)
Definition DotIO.c:51
int Import_dot_splines(Agraph_t *g, int *ne, char ***xsplines)
Definition DotIO.c:218
SparseMatrix SparseMatrix_from_coordinate_format(SparseMatrix A)
SparseMatrix SparseMatrix_coordinate_form_add_entry(SparseMatrix A, int irn, int jcn, const void *val)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format)
@ MATRIX_TYPE_REAL
@ FORMAT_COORD
Agraph_t * edge_distinct_coloring(const char *color_scheme, int *lightness, Agraph_t *g, double angle, double accuracy, int check_edges_with_same_endpoint, int seed)
static int splines_intersect(size_t dim, double cos_critical, int check_edges_with_same_endpoint, char *xsplines1, char *xsplines2)
static long seed
Definition exeval.c:1005
#define A(n, t)
Definition expr.h:76
static bool Verbose
Definition gml2gv.c:24
void free(void *)
node NULL
Definition grammar.y:181
#define B
Definition hierarchy.c:118
double intersection_angle(double *p1, double *p2, double *q1, double *q2)
type-generic dynamically expanding list
#define LIST_AT(list, index)
Definition list.h:168
#define LIST(type)
Definition list.h:55
#define LIST_SIZE(list)
Definition list.h:80
#define LIST_APPEND(list, item)
Definition list.h:120
#define LIST_FREE(list)
Definition list.h:370
static const int dim
int node_distinct_coloring(const char *color_scheme, int *lightness, bool weightedQ, SparseMatrix A0, double accuracy, int seed, int *cdim0, double **colors)
#define C
Definition pack.c:30
#define RETURN(v)
Definition strmatch.c:144
graph or subgraph
Definition cgraph.h:424