static void map_path(node_t * from, node_t * to, edge_t * orig, edge_t * ve, int type) { int r; node_t *u, *v; edge_t *e; assert(ND_rank(from) < ND_rank(to)); if ((agtail(ve) == from) && (aghead(ve) == to)) return; if (ED_count(ve) > 1) { ED_to_virt(orig) = NULL; if (ND_rank(to) - ND_rank(from) == 1) { if ((e = find_fast_edge(from, to)) && (ports_eq(orig, e))) { merge_oneway(orig, e); if ((ND_node_type(from) == NORMAL) && (ND_node_type(to) == NORMAL)) other_edge(orig); return; } } u = from; for (r = ND_rank(from); r < ND_rank(to); r++) { if (r < ND_rank(to) - 1) v = clone_vn(agraphof(from), aghead(ve)); else v = to; e = virtual_edge(u, v, orig); ED_edge_type(e) = type; u = v; ED_count(ve)--; ve = ND_out(aghead(ve)).list[0]; } } else { if (ND_rank(to) - ND_rank(from) == 1) { if ((ve = find_fast_edge(from, to)) && (ports_eq(orig, ve))) { /*ED_to_orig(ve) = orig; */ ED_to_virt(orig) = ve; ED_edge_type(ve) = type; ED_count(ve)++; if ((ND_node_type(from) == NORMAL) && (ND_node_type(to) == NORMAL)) other_edge(orig); } else { ED_to_virt(orig) = NULL; ve = virtual_edge(from, to, orig); ED_edge_type(ve) = type; } } if (ND_rank(to) - ND_rank(from) > 1) { e = ve; if (agtail(ve) != from) { ED_to_virt(orig) = NULL; e = ED_to_virt(orig) = virtual_edge(from, aghead(ve), orig); delete_fast_edge(ve); } else e = ve; while (ND_rank(aghead(e)) != ND_rank(to)) e = ND_out(aghead(e)).list[0]; if (aghead(e) != to) { ve = e; e = virtual_edge(agtail(e), to, orig); ED_edge_type(e) = type; delete_fast_edge(ve); } } } }
void class2(graph_t* g) { int c; node_t *n,*t,*h; edge_t *e,*prev,*opp; g->u.nlist = NULL; g->u.n_nodes = 0; /* new */ mark_clusters(g); for (c = 1; c <= g->u.n_cluster; c++) build_skeleton(g,g->u.clust[c]); for (n = agfstnode(g); n; n = agnxtnode(g,n)) for (e = agfstout(g,n); e; e = agnxtout(g,e)) { if (e->head->u.weight_class <= 2) e->head->u.weight_class++; if (e->tail->u.weight_class <= 2) e->tail->u.weight_class++; } for (n = agfstnode(g); n; n = agnxtnode(g,n)) { if ((n->u.clust == NULL) && (n == UF_find(n))) {fast_node(g,n); g->u.n_nodes++;} prev = NULL; for (e = agfstout(g,n); e; e = agnxtout(g,e)) { /* already processed */ if (e->u.to_virt) continue; /* edges involving sub-clusters of g */ if (is_cluster_edge(e)) { /* following is new cluster multi-edge code */ if (mergeable(prev,e)) { if (prev->u.to_virt) { merge_chain(g,e,prev->u.to_virt,FALSE); other_edge(e); } else if (e->tail->u.rank == e->head->u.rank) { merge_oneway(e,prev); other_edge(e); } /* else is an intra-cluster edge */ continue; } interclrep(g,e); prev = e; continue; } /* merge multi-edges */ if (prev && (e->tail == prev->tail) && (e->head == prev->head)) { if (e->tail->u.rank == e->head->u.rank) { merge_oneway(e,prev); other_edge(e); continue; } if ((e->u.label == NULL) && (prev->u.label == NULL) && ports_eq(e,prev)) { if (Concentrate) e->u.edge_type = IGNORED; else{ merge_chain(g,e,prev->u.to_virt,TRUE); other_edge(e); } continue; } /* parallel edges with different labels fall through here */ } /* self edges */ if (e->tail == e->head) { other_edge(e); prev = e; continue; } t = UF_find(e->tail); h = UF_find(e->head); /* non-leader leaf nodes */ if ((e->tail != t) || (e->head != h)) { /* ### need to merge stuff */ continue; } /* flat edges */ if (e->tail->u.rank == e->head->u.rank) { flat_edge(g,e); prev = e; continue; } /* forward edges */ if (e->head->u.rank > e->tail->u.rank) { make_chain(g,e->tail,e->head,e); prev = e; continue; } /* backward edges */ else { /*other_edge(e);*/ if ((opp = agfindedge(g,e->head,e->tail))) { /* shadows a forward edge */ if (opp->u.to_virt == NULL) make_chain(g,opp->tail,opp->head,opp); if ((e->u.label == NULL) && (opp->u.label == NULL) && ports_eq(e,opp)) { if (Concentrate) { e->u.edge_type = IGNORED; opp->u.conc_opp_flag = TRUE; } else{ /* see above. this is getting out of hand */ other_edge(e); merge_chain(g,e,opp->u.to_virt,TRUE); } continue; } } make_chain(g,e->head,e->tail,e); prev = e; } } } /* since decompose() is not called on subgraphs */ if (g != g->root) { g->u.comp.list = ALLOC(1,g->u.comp.list,node_t*); g->u.comp.list[0] = g->u.nlist; }
void map_path(node_t *from, node_t *to, edge_t *orig, edge_t *ve, int type) { int r; node_t *u,*v; edge_t *e; assert(from->u.rank < to->u.rank); if ((ve->tail == from) && (ve->head == to)) return; if (ve->u.count > 1) { orig->u.to_virt = NULL; if (to->u.rank - from->u.rank == 1) { if ((e = find_fast_edge(from,to)) && (ports_eq(orig,e))) { merge_oneway(orig,e); if ((from->u.node_type == NORMAL) && (to->u.node_type == NORMAL)) other_edge(orig); return; } } u = from; for (r = from->u.rank; r < to->u.rank; r++) { if (r < to->u.rank - 1) v = clone_vn(from->graph,ve->head); else v = to; e = virtual_edge(u,v,orig); e->u.edge_type = type; u = v; ve->u.count--; ve = ve->head->u.out.list[0]; } } else { if (to->u.rank - from->u.rank == 1) { if ((ve = find_fast_edge(from,to)) && (ports_eq(orig,ve))) { /*ve->u.to_orig = orig;*/ orig->u.to_virt = ve; ve->u.edge_type = type; ve->u.count++; if ((from->u.node_type == NORMAL) && (to->u.node_type == NORMAL)) other_edge(orig); } else { orig->u.to_virt = NULL; ve = virtual_edge(from,to,orig); ve->u.edge_type = type; } } if (to->u.rank - from->u.rank > 1) { e = ve; if (ve->tail != from) { orig->u.to_virt = NULL; e = orig->u.to_virt = virtual_edge(from,ve->head,orig); delete_fast_edge(ve); } else e = ve; while (e->head->u.rank != to->u.rank) e = e->head->u.out.list[0]; if (e->head != to) { ve = e; e = virtual_edge(e->tail,to,orig); e->u.edge_type = type; delete_fast_edge(ve); } } } }
/* finds another sharp edge which uses vert, by traversing faces around the * vert until it does one of the following: * - hits a loose edge (the edge is returned) * - hits a sharp edge (the edge is returned) * - returns to the start edge (NULL is returned) */ static SmoothEdge *find_other_sharp_edge(SmoothVert *vert, SmoothEdge *edge, LinkNode **visited_faces) { SmoothFace *face = NULL; SmoothEdge *edge2 = NULL; /* holds the edges we've seen so we can avoid looping indefinitely */ LinkNode *visited_edges = NULL; #ifdef EDGESPLIT_DEBUG_1 printf("=== START === find_other_sharp_edge(edge = %4d, vert = %4d)\n", edge->newIndex, vert->newIndex); #endif /* get a face on which to start */ if(edge->faces) face = edge->faces->link; else return NULL; /* record this edge as visited */ BLI_linklist_prepend(&visited_edges, edge); /* get the next edge */ edge2 = other_edge(face, vert, edge); /* record this face as visited */ if(visited_faces) BLI_linklist_prepend(visited_faces, face); /* search until we hit a loose edge or a sharp edge or an edge we've * seen before */ while(face && !edge_is_sharp(edge2) && !linklist_contains(visited_edges, edge2)) { #ifdef EDGESPLIT_DEBUG_3 printf("current face %4d; current edge %4d\n", face->newIndex, edge2->newIndex); #endif /* get the next face */ face = other_face(edge2, face); /* if face == NULL, edge2 is a loose edge */ if(face) { /* record this face as visited */ if(visited_faces) BLI_linklist_prepend(visited_faces, face); /* record this edge as visited */ BLI_linklist_prepend(&visited_edges, edge2); /* get the next edge */ edge2 = other_edge(face, vert, edge2); #ifdef EDGESPLIT_DEBUG_3 printf("next face %4d; next edge %4d\n", face->newIndex, edge2->newIndex); } else { printf("loose edge: %4d\n", edge2->newIndex); #endif } } /* either we came back to the start edge or we found a sharp/loose edge */ if(linklist_contains(visited_edges, edge2)) /* we came back to the start edge */ edge2 = NULL; BLI_linklist_free(visited_edges, NULL); #ifdef EDGESPLIT_DEBUG_1 printf("=== END === find_other_sharp_edge(edge = %4d, vert = %4d), " "returning edge %d\n", edge->newIndex, vert->newIndex, edge2 ? edge2->newIndex : -1); #endif return edge2; }