uint8_t _update_avg_graph( graph_t *gin, graph_t *gavg, array_t *nodemap, edge_weight_t edgeweight, uint16_t ninputs) { uint64_t i; uint64_t j; uint32_t ginnodes; uint32_t *nbrs; uint32_t nnbrs; uint32_t outi; uint32_t outj; float inwt; float outwt; ginnodes = graph_num_nodes(gin); for (i = 0; i < ginnodes; i++) { outi = *(uint32_t *)array_getd(nodemap, i); nnbrs = graph_num_neighbours(gin, i); nbrs = graph_get_neighbours(gin, i); for (j = 0; j < nnbrs; j++) { if (i >= nbrs[j]) continue; outj = *(uint32_t *)array_getd(nodemap, nbrs[j]); /*will have no effect if edge already exists*/ graph_add_edge(gavg, outi, outj, 0.0); inwt = graph_get_weight(gin, i, nbrs[j]); outwt = graph_get_weight(gavg, outi, outj); switch (edgeweight) { case SUM_WEIGHTS: outwt = outwt + inwt; break; case COUNT_EDGES: outwt = outwt + 1; break; case AVG_WEIGHTS: outwt = outwt + (inwt/ninputs); break; default: goto fail; } if (graph_set_weight(gavg, outi, outj, outwt)) goto fail; } } return 0; fail: return 1; }
static int path_decimate(gstack_t** path, double* Dmin) { size_t n = gstack_size(*path); double xmin = pow(*Dmin, 2); corner_t cns[n]; /* empty the stack into a corners array - we do this in reverse order so the gstack_push below gives us a gstack_t in the same order (needed due to an assumed orientation of the boundaries) */ for (int i = 0 ; i < n ; i++) { if (gstack_pop(*path, (void*)(cns+(n-1-i))) != 0) return -1; } /* cache metric tensor and ellipse centres */ vector_t e[n]; m2_t mt[n]; for (int i = 0 ; i < n ; i++) { ellipse_t E; arrow_ellipse(&(cns[i].A), &E); mt[i] = ellipse_mt(E); e[i] = E.centre; } /* create ellipse intersection graph */ graph_t G; if (graph_init(n,&G) != 0) return -1; size_t err = 0; for (int i = 0 ; i < n-1 ; i++) { for (int j = i+1 ; j < n ; j++) { double x = contact_mt(vsub(e[j], e[i]), mt[i], mt[j]); /* failed contact() results in edge not being included in the graph so possible intesection survives - save the number for a warning (below) */ if (x<0) { err++; continue; } /* weight of each node is the maximum of the contact-distances of the incoming edges */ if (x < xmin) { double w1 = graph_get_weight(G, i), w2 = graph_get_weight(G, j); graph_set_weight(G, i, MAX(w1, x)); graph_set_weight(G, j, MAX(w2, x)); if (graph_add_edge(G, i, j) != 0) return -1; } } } if (err) fprintf(stderr,"failed contact distance for %i pairs\n", (int)err); /* greedy node deletion to obtain non-intersecting subset */ size_t maxi; while (graph_maxedge(G, &maxi) > 0) if (graph_del_node(G, maxi) != 0) return -1; /* dump back into gstack */ for (int i = 0 ; i < n ; i++) if ( !graph_node_flag(G, i, NODE_STALE) ) gstack_push(*path, (void*)(cns+i)); graph_clean(&G); return 1; }