diff --git a/src/half_edge.c b/src/half_edge.c index 8e3eae9..09ad110 100644 --- a/src/half_edge.c +++ b/src/half_edge.c @@ -99,7 +99,7 @@ static bool get_all_emanating_edges(HE_vert const * const vert, rc++; } - } while (edge != vert->edge); + } while (edge && edge != vert->edge); /* set out-pointers */ *edge_array_out = edge_array; @@ -370,7 +370,8 @@ HE_obj *parse_obj(char const * const obj_string) faces = (HE_face*) malloc(sizeof(HE_face) * fc); CHECK_PTR_VAL(faces); - edges = (HE_edge*) malloc(sizeof(HE_edge) * ec); + /* hold enough space for possible dummy edges */ + edges = (HE_edge*) malloc(sizeof(HE_edge) * ec * 2); CHECK_PTR_VAL(edges); ec = 0; @@ -429,6 +430,7 @@ HE_obj *parse_obj(char const * const obj_string) /* find pairs */ for (uint32_t i = 0; i < ec; i++) { /* for all edges */ uint32_t eac = edges[i].vert->eac; + bool pair_found = false; for (uint32_t j = 0; j < eac; j++) { /* for all potential pairs */ if (edges[i].vert->edge_array[j] && @@ -436,11 +438,36 @@ HE_obj *parse_obj(char const * const obj_string) edges[i].vert->edge_array[j]->vert)) { edges[i].pair = edges[i].vert->edge_array[j]; edges[i].vert->edge_array[j] = NULL; + + /* this is a trick to make sure the + * edge member of HE_vert is never + * a border-edge (unless there are only + * border edges), otherwise + * get_all_emanating_edges() would break + * for vertices that are at the edge + * of an open object */ + edges[i].vert->edge = &(edges[i]); + + pair_found = true; break; } } + + if (!pair_found) { /* we have a border edge */ + /* add dummy edge, so get_all_emanating_edges() + * does not break */ + edges[ec + i].face = NULL; + edges[ec + i].next = NULL; + edges[ec + i].pair = &(edges[i]); + edges[ec + i].vert = edges[i].next->vert; + edges[i].pair = &(edges[ec + i]); + } } + /* don't need the edge array anymore */ + for (uint32_t i = 0; i < vc; i++) + free(vertices[i].edge_array); + obj = (HE_obj*) malloc(sizeof(HE_obj)); CHECK_PTR_VAL(obj); @@ -472,7 +499,6 @@ void delete_object(HE_obj *obj) for (uint32_t i = 0; i < obj->vc; i++) { free(obj->vertices[i].vec); free(obj->vertices[i].col); - free(obj->vertices[i].edge_array); } free(obj->edges); free(obj->vertices); diff --git a/src/half_edge.h b/src/half_edge.h index 3fd2328..b5e2921 100644 --- a/src/half_edge.h +++ b/src/half_edge.h @@ -118,6 +118,8 @@ struct HE_edge { HE_vert *vert; /** * Oppositely oriented adjacent half-edge. + * Border edges have a dummy pair which have "face" + * and "next" set to NULL. */ HE_edge *pair; /** @@ -143,14 +145,19 @@ struct HE_vert { /** * One of the half-edges emanating from the vertex. + * It is made sure that this is never a border edge, + * unless there are only border edges. */ HE_edge *edge; /** - * Acceleration structure which saves all - * edges that point TO this vertex. It is used + * Acceleration structure which saves all potential + * pair edges that point TO this vertex. It is used * for finding the pairs when assembling - * the HE_edge struct. + * the HE_edge struct. Note that this does not reliably + * save all border edges (which is a non-issue for the + * specific purpose of this struct since border-edges + * don't qualify for pairs anyway). */ HE_edge **edge_array;