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