16#include "../tools/openFile.h"
43 fprintf(stderr,
"Usage: %s <options> gv file with 2D coordinates.\n",
cmd);
44 fprintf(stderr,
"Find a color assignment of the edges, such that edges that cross at small angle have as different as possible.\n");
45 fprintf(stderr,
"Options are: \n");
46 fprintf(stderr,
" --accuracy=e : accuracy with which to find the maximally different coloring for each node with regard to its neighbors. Default 0.01.\n");
47 fprintf(stderr,
" --angle=a : if edge crossing is less than that angle a, then make the edge colors different. Default 15.\n");
48 fprintf(stderr,
" --random_seed=s : random seed to use. s must be an integer. If s is negative, we do -s iterations with different seeds and pick the best.\n");
49 fprintf(stderr,
" --color_scheme=c : palette used. The string c should be \"rgb\", \"gray\", \"lab\" (default); or\n");
50 fprintf(stderr,
" a comma-separated list of RGB colors in hex (e.g., \"#ff0000,#aabbed,#eeffaa\"); or\n");
51 fprintf(stderr,
" a string specifying a Brewer color scheme (e.g., \"accent7\"; see https://graphviz.org/doc/info/colors.html#brewer).\n");
52 fprintf(stderr,
" --lightness=l1,l2 : only applied for LAB color scheme: l1 must be integer >=0, l2 integer <=100, and l1 <=l2. By default we use 0,70\n");
53 fprintf(stderr,
" --share_endpoint : if this option is specified, edges that shares an end point are not considered in conflict if they are close to\n");
54 fprintf(stderr,
" parallel but is on the opposite ends of the shared point (around 180 degree).\n");
55 fprintf(stderr,
" -v : verbose\n");
56 fprintf(stderr,
" -o fname : write output to file fname (stdout)\n");
74 if ((h =
aghead(e)) == n)
return 1;
75 if (h == prevh)
return 1;
83static void init(
int argc,
char *argv[],
double *angle,
double *accuracy,
84 int *check_edges_with_same_endpoint,
int *
seed,
85 const char **color_scheme,
int *lightness) {
93 *check_edges_with_same_endpoint = 0;
95 *color_scheme =
"lab";
105 OPT_COLOR_SCHEME = 130,
106 OPT_RANDOM_SEED = 131,
108 OPT_SHARE_ENDPOINT = 133,
111 static const struct option
opts[] = {
113 {
"accuracy", required_argument, 0, OPT_ACCURACY},
114 {
"angle", required_argument, 0, OPT_ANGLE},
115 {
"color_scheme", required_argument, 0, OPT_COLOR_SCHEME},
116 {
"random_seed", required_argument, 0, OPT_RANDOM_SEED},
117 {
"lightness", required_argument, 0, OPT_LIGHTNESS},
118 {
"share_endpoint", no_argument, 0, OPT_SHARE_ENDPOINT},
123 int option_index = 0;
124 int c = getopt_long(argc, argv,
"a:c:r:l:o:s:v?",
opts, &option_index);
130 const char *arg = optarg;
133 if (c ==
'a' &&
startswith(arg,
"ccuracy=")) {
135 arg += strlen(
"ccuracy=");
136 }
else if (c ==
'a' &&
startswith(arg,
"ngle=")) {
138 arg += strlen(
"ngle=");
139 }
else if (c ==
'c' &&
startswith(arg,
"olor_scheme=")) {
140 c = OPT_COLOR_SCHEME;
141 arg += strlen(
"olor_scheme=");
142 }
else if (c ==
'r' &&
startswith(arg,
"andom_seed=")) {
144 arg += strlen(
"andom_seed=");
145 }
else if (c ==
'l' &&
startswith(arg,
"ightness=")) {
147 arg += strlen(
"ightness=");
148 }
else if (c ==
's' &&
startswith(arg,
"hare_endpoint")) {
149 c = OPT_SHARE_ENDPOINT;
159 fprintf(stderr,
"option -%c unrecognized.\n", c);
164 if (optopt ==
'\0' || optopt ==
'?') {
167 fprintf(stderr,
"option -%c unrecognized.\n", optopt);
183 if (sscanf(arg,
"%lf", accuracy) != 1 || *accuracy <= 0) {
184 fprintf(stderr,
"--accuracy option must be a positive real number.\n");
190 if (sscanf(arg,
"%lf", angle) != 1 || *angle <= 0 || *angle >= 90) {
191 fprintf(stderr,
"--angle option must be a positive real number "
192 "between 0 and 90.\n");
197 case OPT_COLOR_SCHEME:
200 "--color_scheme option must be a known color scheme.\n");
206 case OPT_LIGHTNESS: {
209 if (sscanf(arg,
"%d,%d", &l1, &l2) != 2 || l1 < 0 || l2 > 100 ||
211 fprintf(stderr,
"invalid --lightness=%s option.\n", arg);
219 case OPT_RANDOM_SEED:
220 if (sscanf(arg,
"%d",
seed) != 1) {
221 fprintf(stderr,
"--random_seed option must be an integer.\n");
226 case OPT_SHARE_ENDPOINT:
227 *check_edges_with_same_endpoint = 1;
236 Files = argv + optind;
245 int check_edges_with_same_endpoint,
int seed,
246 const char *color_scheme,
int *lightness) {
261int main(
int argc,
char *argv[])
265 int check_edges_with_same_endpoint,
seed;
266 const char *color_scheme =
NULL;
267 int lightness[] = {0, 70};
271 int rv = EXIT_SUCCESS;
273 init(argc, argv, &angle, &accuracy, &check_edges_with_same_endpoint, &
seed, &color_scheme, lightness);
282 if (
clarify(g, angle, accuracy, check_edges_with_same_endpoint,
seed,
283 color_scheme, lightness) != 0) {
void initDotIO(Agraph_t *g)
Memory allocation wrappers that exit on failure.
abstract graph C library, Cgraph API
bool knownColorScheme(const char *name)
helpers for verbose/debug printing
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 clarify(Agraph_t *g, double angle, double accuracy, int check_edges_with_same_endpoint, int seed, const char *color_scheme, int *lightness)
static void init(int argc, char *argv[], double *angle, double *accuracy, int *check_edges_with_same_endpoint, int *seed, const char **color_scheme, int *lightness)
static int checkG(Agraph_t *g)
static NORETURN void graphviz_exit(int status)
static int eval(Agraph_t *g, int root)
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
void agerrorf(const char *fmt,...)
int agclose(Agraph_t *g)
deletes a graph, freeing its associated storage
int agwrite(Agraph_t *g, void *chan)
Return 0 on success, EOF on failure.
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Agnode_t * agfstnode(Agraph_t *g)
char * agnameof(void *)
returns a string descriptor for the object.
static const char * usage
char * fileName(ingraph_state *sp)
Return name of current file being processed.
Agraph_t * nextGraph(ingraph_state *sp)
ingraph_state * newIngraph(ingraph_state *sp, char **files)
supports user-supplied data
static FILE * openFile(const char *argv0, const char *name, const char *mode)
point containers PointSet and PointMap
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?