16#include "../tools/openFile.h"
42 fprintf(stderr,
"Usage: %s <options> gv file with 2D coordinates.\n",
cmd);
43 fprintf(stderr,
"Find a color assignment of the edges, such that edges that cross at small angle have as different as possible.\n");
44 fprintf(stderr,
"Options are: \n");
45 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");
46 fprintf(stderr,
" --angle=a : if edge crossing is less than that angle a, then make the edge colors different. Default 15.\n");
47 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");
48 fprintf(stderr,
" --color_scheme=c : palette used. The string c should be \"rgb\", \"gray\", \"lab\" (default); or\n");
49 fprintf(stderr,
" a comma-separated list of RGB colors in hex (e.g., \"#ff0000,#aabbed,#eeffaa\"); or\n");
50 fprintf(stderr,
" a string specifying a Brewer color scheme (e.g., \"accent7\"; see https://graphviz.org/doc/info/colors.html#brewer).\n");
51 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");
52 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");
53 fprintf(stderr,
" parallel but is on the opposite ends of the shared point (around 180 degree).\n");
54 fprintf(stderr,
" -v : verbose\n");
55 fprintf(stderr,
" -o fname : write output to file fname (stdout)\n");
73 if ((h =
aghead(e)) == n)
return 1;
74 if (h == prevh)
return 1;
82static void init(
int argc,
char *argv[],
double *angle,
double *accuracy,
83 int *check_edges_with_same_endpoint,
int *
seed,
84 const char **color_scheme,
int *lightness) {
92 *check_edges_with_same_endpoint = 0;
94 *color_scheme =
"lab";
104 OPT_COLOR_SCHEME = 130,
105 OPT_RANDOM_SEED = 131,
107 OPT_SHARE_ENDPOINT = 133,
110 static const struct option
opts[] = {
112 {
"accuracy", required_argument, 0, OPT_ACCURACY},
113 {
"angle", required_argument, 0, OPT_ANGLE},
114 {
"color_scheme", required_argument, 0, OPT_COLOR_SCHEME},
115 {
"random_seed", required_argument, 0, OPT_RANDOM_SEED},
116 {
"lightness", required_argument, 0, OPT_LIGHTNESS},
117 {
"share_endpoint", no_argument, 0, OPT_SHARE_ENDPOINT},
122 int option_index = 0;
123 int c = getopt_long(argc, argv,
"a:c:r:l:o:s:v?",
opts, &option_index);
129 const char *arg = optarg;
132 if (c ==
'a' &&
startswith(arg,
"ccuracy=")) {
134 arg += strlen(
"ccuracy=");
135 }
else if (c ==
'a' &&
startswith(arg,
"ngle=")) {
137 arg += strlen(
"ngle=");
138 }
else if (c ==
'c' &&
startswith(arg,
"olor_scheme=")) {
139 c = OPT_COLOR_SCHEME;
140 arg += strlen(
"olor_scheme=");
141 }
else if (c ==
'r' &&
startswith(arg,
"andom_seed=")) {
143 arg += strlen(
"andom_seed=");
144 }
else if (c ==
'l' &&
startswith(arg,
"ightness=")) {
146 arg += strlen(
"ightness=");
147 }
else if (c ==
's' &&
startswith(arg,
"hare_endpoint")) {
148 c = OPT_SHARE_ENDPOINT;
158 fprintf(stderr,
"option -%c unrecognized.\n", c);
163 if (optopt ==
'\0' || optopt ==
'?') {
166 fprintf(stderr,
"option -%c unrecognized.\n", optopt);
182 if (sscanf(arg,
"%lf", accuracy) != 1 || *accuracy <= 0) {
183 fprintf(stderr,
"--accuracy option must be a positive real number.\n");
189 if (sscanf(arg,
"%lf", angle) != 1 || *angle <= 0 || *angle >= 90) {
190 fprintf(stderr,
"--angle option must be a positive real number "
191 "between 0 and 90.\n");
196 case OPT_COLOR_SCHEME:
199 "--color_scheme option must be a known color scheme.\n");
205 case OPT_LIGHTNESS: {
208 if (sscanf(arg,
"%d,%d", &l1, &l2) != 2 || l1 < 0 || l2 > 100 ||
210 fprintf(stderr,
"invalid --lightness=%s option.\n", arg);
218 case OPT_RANDOM_SEED:
219 if (sscanf(arg,
"%d",
seed) != 1) {
220 fprintf(stderr,
"--random_seed option must be an integer.\n");
225 case OPT_SHARE_ENDPOINT:
226 *check_edges_with_same_endpoint = 1;
235 Files = argv + optind;
244 int check_edges_with_same_endpoint,
int seed,
245 const char *color_scheme,
int *lightness) {
260int main(
int argc,
char *argv[])
264 int check_edges_with_same_endpoint,
seed;
265 const char *color_scheme =
NULL;
266 int lightness[] = {0, 70};
270 int rv = EXIT_SUCCESS;
272 init(argc, argv, &angle, &accuracy, &check_edges_with_same_endpoint, &
seed, &color_scheme, lightness);
281 fprintf(stderr,
"Process graph %s in file %s\n",
agnameof(g),
283 if (
clarify(g, angle, accuracy, check_edges_with_same_endpoint,
seed,
284 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)
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?