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