Graphviz 13.0.0~dev.20241220.2304
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/alloc.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 pont at around 180
30 xsplines1,xsplines2: the first and second splines corresponding to two edges
31
32 */
33 size_t len1 = 100, len2 = 100;
34 size_t ns1 = 0, ns2 = 0;
35 int iter1 = 0, iter2 = 0;
36 double cos_a, tmp[2];
37 int endp1 = 0, endp2 = 0;
38
39 tmp[0] = tmp[1] = 0;
40 double *x1 = gv_calloc(len1, sizeof(double));
41 double *x2 = gv_calloc(len2, sizeof(double));
42
43 assert(dim <= 3);
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 = 1;
53 xsplines1 = strstr(xsplines1, "e,") + 2;
54 } else if (strstr(xsplines1, "s,")){
55 xsplines1 = strstr(xsplines1, "s,") + 2;
56 }
57 }
58 while (xsplines1 && sscanf(xsplines1,"%lf,%lf", &(x1[ns1*dim]), &x1[ns1*dim + 1]) == 2){
59 if (endp1 && iter1 == 0){
60 tmp[0] = x1[ns1*dim]; tmp[1] = x1[ns1*dim + 1];
61 } else {
62 ns1++;
63 }
64 iter1++;
65 xsplines1 = strchr(xsplines1, ' ');
66 if (!xsplines1) break;
67 xsplines1++;
68 if (ns1*dim >= len1){
69 size_t new_len1 = ns1 * dim + MAX(10u, ns1 * dim / 5);
70 x1 = gv_recalloc(x1, len1, new_len1, sizeof(double));
71 len1 = new_len1;
72 }
73 }
74 if (endp1){/* pad the end point at the last position */
75 ns1++;
76 if (ns1*dim >= len1){
77 size_t new_len1 = ns1 * dim + MAX(10u, ns1 * dim / 5);
78 x1 = gv_recalloc(x1, len1, new_len1, sizeof(double));
79 len1 = new_len1;
80 }
81 x1[(ns1-1)*dim] = tmp[0]; x1[(ns1-1)*dim + 1] = tmp[1];
82 }
83
84
85 /* splines could be a list of
86 1. 3n points
87 2. of the form "e,x,y" followed by 3n points, where x,y is really padded to the end of the 3n points
88 3. of the form "s,x,y" followed by 3n points, where x,y is padded to the start of the 3n points
89 */
90 if (xsplines2){
91 if(strstr(xsplines2, "e,")){
92 endp2 = 1;
93 xsplines2 = strstr(xsplines2, "e,") + 2;
94 } else if (strstr(xsplines2, "s,")){
95 xsplines2 = strstr(xsplines2, "s,") + 2;
96 }
97 }
98 while (xsplines2 && sscanf(xsplines2,"%lf,%lf", &(x2[ns2*dim]), &x2[ns2*dim + 1]) == 2){
99 if (endp2 && iter2 == 0){
100 tmp[0] = x2[ns2*dim]; tmp[1] = x2[ns2*dim + 1];
101 } else {
102 ns2++;
103 }
104 iter2++;
105 xsplines2 = strchr(xsplines2, ' ');
106 if (!xsplines2) break;
107 xsplines2++;
108 if (ns2*dim >= len2){
109 size_t new_len2 = ns2 * dim + MAX(10u, ns2 * dim / 5);
110 x2 = gv_recalloc(x2, len2, new_len2, sizeof(double));
111 len2 = new_len2;
112 }
113 }
114 if (endp2){/* pad the end point at the last position */
115 ns2++;
116 if (ns2*dim >= len2){
117 size_t new_len2 = ns2 * dim + MAX(10u, ns2 * dim / 5);
118 x2 = gv_recalloc(x2, len2, new_len2, sizeof(double));
119 len2 = new_len2;
120 }
121 x2[(ns2-1)*dim] = tmp[0]; x2[(ns2-1)*dim + 1] = tmp[1];
122 }
123
124 for (size_t i = 0; i < ns1 - 1; i++) {
125 for (size_t j = 0; j < ns2 - 1; j++) {
126 cos_a = intersection_angle(&(x1[dim*i]), &(x1[dim*(i + 1)]), &(x2[dim*j]), &(x2[dim*(j+1)]));
127 if (!check_edges_with_same_endpoint && cos_a >= -1) cos_a = fabs(cos_a);
128 if (cos_a > cos_critical) {
129 free(x1);
130 free(x2);
131 return 1;
132 }
133
134 }
135 }
136
137 free(x1);
138 free(x2);
139 return 0;
140}
141
142Agraph_t *edge_distinct_coloring(const char *color_scheme, int *lightness,
143 Agraph_t *g, double angle, double accuracy,
144 int check_edges_with_same_endpoint, int seed) {
145 double *x = NULL;
146 int dim = 2;
147 SparseMatrix A, B, C;
148 int *irn, *jcn, nz, nz2 = 0;
149 double cos_critical = cos(angle/180*3.14159), cos_a;
150 int u1, v1, u2, v2, i, j;
151 double *colors = NULL;
152 int flag, ne;
153 char **xsplines = NULL;
154 int cdim;
155
157 if (!x){
158 fprintf(stderr,"The gv file contains no or improper 2D coordinates\n");
159 return NULL;
160 }
161
162
163 irn = A->ia; jcn = A->ja;
164 nz = A->nz;
165
166 /* get rid of self edges */
167 for (i = 0; i < nz; i++){
168 if (irn[i] != jcn[i]){
169 irn[nz2] = irn[i];
170 jcn[nz2++] = jcn[i];
171 }
172 }
173
174 if (Verbose)
175 fprintf(stderr,"cos = %f, nz2 = %d\n", cos_critical, nz2);
176 /* now find edge collision */
178
179 if (Import_dot_splines(g, &ne, &xsplines)){
180#ifdef TIME
181 clock_t start = clock();
182#endif
183 assert(ne == nz2);
184 cos_a = 1.;/* for splines we exit conflict check as soon as we find an conflict, so the anle may not be representitive, hence set to constant */
185 for (i = 0; i < nz2; i++){
186 for (j = i+1; j < nz2; j++){
187 if (splines_intersect((size_t)dim, cos_critical,
188 check_edges_with_same_endpoint, xsplines[i],
189 xsplines[j])) {
191 }
192 }
193 }
194#ifdef TIME
195 fprintf(stderr, "cpu for dual graph =%10.3f", ((double) (clock() - start))/CLOCKS_PER_SEC);
196#endif
197
198 } else {
199 /* no splines, justsimple edges */
200#ifdef TIME
201 clock_t start = clock();
202#endif
203
204
205 for (i = 0; i < nz2; i++){
206 u1 = irn[i]; v1 = jcn[i];
207 for (j = i+1; j < nz2; j++){
208 u2 = irn[j]; v2 = jcn[j];
209 cos_a = intersection_angle(&(x[dim*u1]), &(x[dim*v1]), &(x[dim*u2]), &(x[dim*v2]));
210 if (!check_edges_with_same_endpoint && cos_a >= -1) cos_a = fabs(cos_a);
211 if (cos_a > cos_critical) {
213 }
214 }
215 }
216#ifdef TIME
217 fprintf(stderr, "cpu for dual graph (splines) =%10.3f\n", ((double) (clock() - start))/CLOCKS_PER_SEC);
218#endif
219 }
221 if (B != C) SparseMatrix_delete(B);
222
223 {
224#ifdef TIME
225 clock_t start = clock();
226#endif
227 const bool weightedQ = false;
228 flag = node_distinct_coloring(color_scheme, lightness, weightedQ, C,
229 accuracy, seed, &cdim, &colors);
230 if (flag) goto RETURN;
231#ifdef TIME
232 fprintf(stderr, "cpu for color assignmment =%10.3f\n", ((double) (clock() - start))/CLOCKS_PER_SEC);
233#endif
234 }
235
236 if (Verbose)
237 fprintf(stderr,"The edge conflict graph has %d nodes and %d edges\n", C->m, C->nz);
238
239 attach_edge_colors(g, cdim, colors);
240
241 RETURN:
244 free(colors);
245 free(x);
246 if (xsplines){
247 for (i = 0; i < ne; i++){
248 free(xsplines[i]);
249 }
250 free(xsplines);
251 }
252 return g;
253}
SparseMatrix SparseMatrix_import_dot(Agraph_t *g, int dim, double **x, int format)
Definition DotIO.c:80
void attach_edge_colors(Agraph_t *g, int dim, double *colors)
Definition DotIO.c:50
int Import_dot_splines(Agraph_t *g, int *ne, char ***xsplines)
Definition DotIO.c:217
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
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
Definition alloc.h:73
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
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:1035
#define A(n, t)
Definition expr.h:76
static bool Verbose
Definition gml2gv.c:23
void free(void *)
node NULL
Definition grammar.y:163
#define B
Definition hierarchy.c:117
double intersection_angle(double *p1, double *p2, double *q1, double *q2)
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:29
#define RETURN(v)
Definition strmatch.c:144
graph or subgraph
Definition cgraph.h:425
#define MAX(a, b)
Definition write.c:31