// Quad-edge manipulation primitives EdgePointer CDelaunay::makeEdge(SitePointer origin, SitePointer destination) { EdgePointer temp, ans; temp = allocEdge(); ans = temp; onext(temp) = ans; orig(temp) = origin; onext(++temp) = (EdgePointer) (ans + 3); onext(++temp) = (EdgePointer) (ans + 2); orig(temp) = destination; onext(++temp) = (EdgePointer) (ans + 1); return(ans); }
void SMwriter_smc_old::write_triangle(const int* t_idx, const bool* t_final) { if (v_count + f_count == 0) write_header(); int i,j; my_vertex_hash::iterator hash_elements[3]; SMvertex* vertices[3]; SMedge* edges[3]; // get vertices from hash for (i = 0; i < 3; i++) { hash_elements[i] = vertex_hash->find(t_idx[i]); if (hash_elements[i] == vertex_hash->end()) { fprintf(stderr,"ERROR: vertex %d not in hash\n",t_idx[i]); exit(0); } else { vertices[i] = (*hash_elements[i]).second; } } // are vertices already visited int v_visited[3]; int num_v_visited = 0; int last_v_visited = -1; int last_v_unvisited = -1; for (i = 0; i < 3; i++) { if (vertices[i]->use_count) { v_visited[i] = 1; last_v_visited = i; num_v_visited++; } else { v_visited[i] = 0; last_v_unvisited = i; } } // are edges already visited int e_visited[3]; int num_e_visited = 0; int last_e_visited = -1; int last_e_unvisited = -1; for (i = 0; i < 3; i++) { e_visited[i] = 0; if (v_visited[i] && v_visited[(i+1)%3]) { for (j = 0; j < vertices[i]->list_size; j++) { if (vertices[i]->list[j]->origin == vertices[(i+1)%3]) { e_visited[i] = 1; last_e_visited = i; edges[i] = vertices[i]->list[j]; break; } else if (vertices[i]->list[j]->target == vertices[(i+1)%3]) // not-oriented case { e_visited[i] = 1; last_e_visited = i; edges[i] = vertices[i]->list[j]; break; } } if (last_e_visited != i) { last_e_unvisited = i; } else { num_e_visited++; } } } // compress the triangle based in its operation: start, add/join, or fill/end int dv_index; int lc_pos; int candidate; int candidate_count; int degree_one; int use_count; int rot = 0; SMvertex* v0; SMvertex* v1; SMvertex* v2; if (num_e_visited == 0) // start { op_start++; if (edge_buffer_size) { re_conn_op->encode(rmSAJFE[last_SAJFE], SMC_START); } else { re_conn_op->encode(rmDone, 0); // more to come } last_SAJFE = SMC_START; PRINT_DEBUG_OUTPUT(stderr, "%d ", SMC_START); // rotate triangle if necessary if (num_v_visited == 1) { rot = last_v_visited; } else if (num_v_visited == 2) { rot = (last_v_unvisited + 1) % 3; } // encode the (rotated) start configuration v0 = vertices[rot]; v1 = vertices[(rot+1)%3]; v2 = vertices[(rot+2)%3]; // encode vertex v0 if (v0->use_count) { // an old vertex re_conn->encode(rmS_0Old, 1); // encode its index among all active vertices dv_index = dv->getRelativeIndex(v0); re_conn_index->encode(dv->size(),dv_index); start_non_manifold++; PRINT_DEBUG_OUTPUT(stderr, "SNM0 "); } else { // a new vertex re_conn->encode(rmS_0Old, 0); // encode its position compressVertexPosition(v0->v); // insert it into the indexable data structure dv->addElement(v0); } // encode vertex v1 if (v1->use_count) { // an old vertex re_conn->encode(rmS_1Old, 1); // encode its index among all active vertices dv_index = dv->getRelativeIndex(v1); re_conn_index->encode(dv->size(),dv_index); start_non_manifold++; PRINT_DEBUG_OUTPUT(stderr, "SNM1 "); } else { // a new vertex re_conn->encode(rmS_1Old, 0); // encode its position compressVertexPosition(v0->v, v1->v); // insert it into the indexable data structure dv->addElement(v1); } // encode vertex v2 if (v2->use_count) { // an old vertex re_conn->encode(rmS_2Old, 1); // encode its index among all active vertices dv_index = dv->getRelativeIndex(v2); re_conn_index->encode(dv->size(),dv_index); start_non_manifold++; PRINT_DEBUG_OUTPUT(stderr, "SNM2 "); } else { // a new vertex re_conn->encode(rmS_2Old, 0); // encode its position compressVertexPosition(v0->v, v2->v); // insert it into the indexable data structure dv->addElement(v2); } } else if (num_e_visited == 1) // add (or join) { op_add_join++; re_conn_op->encode(rmSAJFE[last_SAJFE], SMC_ADD_JOIN); last_SAJFE = SMC_ADD_JOIN; PRINT_DEBUG_OUTPUT(stderr, "%d ", SMC_ADD_JOIN); // rotate triangle if necessary rot = last_e_visited; // encode the (rotated) add (or join) configuration v0 = vertices[rot]; v1 = vertices[(rot+1)%3]; v2 = vertices[(rot+2)%3]; SMedge* e0 = edges[rot]; // encode the index of v0 (-> improve with cache of with prediction) lc_pos = lc->pos(v0->index); if (lc_pos == -1) { add_miss++; if (lc->pos(v1->index) != -1) { add_miss_hit_possible++; } re_conn_cache->encode(rmAJ_CacheHit,0); dv_index = dv->getRelativeIndex(v0); re_conn_index->encode(dv->size(),dv_index); PRINT_DEBUG_OUTPUT(stderr, "m%d ", dv_index); } else { add_hit++; add_pos[lc_pos]++; re_conn_cache->encode(rmAJ_CacheHit,1); re_conn_cache->encode(rmAJ_CachePos,lc_pos); PRINT_DEBUG_OUTPUT(stderr, "h%d ", lc_pos); } // encode which of the edges incident to v0 is e0 candidate = -1; candidate_count = 0; if (e0->degree == 1) // is this edge only used by one other triangle? { re_conn->encode(rmAJ_Manifold,0); // is attached in a manifold way if (e0->target == v0) // the target vertex of this edge is v0 { re_conn->encode(rmAJ_ManifoldOriented,0); // is attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "mo "); // how many oriented degree-one edges are around that vertex? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->target == v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmAJ_ManifoldOriented,1); // is attached in an not-oriented way PRINT_DEBUG_OUTPUT(stderr, "mno "); // how many not-oriented degree-one edges are around that vertex? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->target != v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } } else { re_conn->encode(rmAJ_Manifold,1); // is attached in non-manifold way if (e0->target == v0) // the target vertex of this edge is v0 { re_conn->encode(rmAJ_NonManifoldOriented,0); // is attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "nmo "); // how many oriented higher-degree edges are around that vertex? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->target == v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmAJ_NonManifoldOriented,1); // is attached in an not-oriented way PRINT_DEBUG_OUTPUT(stderr, "nmno "); // how many not-oriented higher-degree edges are around that vertex? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->target != v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } } if (candidate_count != 1) { re_conn->encode(candidate_count,candidate); PRINT_DEBUG_OUTPUT(stderr, "c%d:%d ",candidate_count,candidate); } // encode v2 if (v2->use_count) { // an old vertex re_conn->encode(rmAJ_Old, 1); // encode its index among all active vertices dv_index = dv->getRelativeIndex(v2); re_conn_index->encode(dv->size(),dv_index); add_non_manifold++; PRINT_DEBUG_OUTPUT(stderr, "AJNM %d ",dv_index); } else { // a new vertex re_conn->encode(rmAJ_Old, 0); // encode its position compressVertexPosition(v0->v, e0->across, v1->v, v2->v); // insert it into the indexable data structure dv->addElement(v2); } } else // fill or end { op_fill_end++; re_conn_op->encode(rmSAJFE[last_SAJFE], SMC_FILL_END); last_SAJFE = SMC_FILL_END; PRINT_DEBUG_OUTPUT(stderr, "%d ", SMC_FILL_END); // rotate triangle if necessary if (num_e_visited == 2) { rot = (last_e_unvisited + 2) % 3; } else { for (i = 0; i < 3; i++) { if (lc->pos(vertices[i]->index) != -1) { rot = i; break; } } } // encode the (rotated) fill (or end) configuration v0 = vertices[rot]; v1 = vertices[(rot+1)%3]; v2 = vertices[(rot+2)%3]; SMedge* e0 = edges[rot]; // SMedge* e1 = edges[(rot+1)%3]; SMedge* e2 = edges[(rot+2)%3]; // encode the index of v0 lc_pos = lc->pos(v0->index); if (lc_pos == -1) { fill_miss++; if (lc->pos(v1->index) != -1) { fill_miss_hit_possible_v1++; } else if (lc->pos(v2->index) != -1) { fill_miss_hit_possible_v2++; } re_conn_cache->encode(rmFE_CacheHit,0); dv_index = dv->getRelativeIndex(v0); re_conn_index->encode(dv->size(),dv_index); PRINT_DEBUG_OUTPUT(stderr, "m%d ", dv_index); } else { fill_hit++; fill_pos[lc_pos]++; re_conn_cache->encode(rmFE_CacheHit,1); re_conn_cache->encode(rmFE_CachePos,lc_pos); PRINT_DEBUG_OUTPUT(stderr, "h%d ", lc_pos); } // encode edge e0 (e.g. the edge from v0 to v1) candidate = -1; candidate_count = 0; if (e0->degree == 1) { re_conn->encode(rmFE_0Manifold,0); // along e0 attached in a manifold way if (e0->target == v0) { re_conn->encode(rmFE_0ManifoldOriented,0); // along e0 attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "mo "); // how many oriented manifold edges are around v0 that could potentially be e0? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->target == v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmFE_0ManifoldOriented,1); // along e0 *not* attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "mno "); // how many not-oriented manifold edges are around v0 that could potentially be e0? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->target != v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } } else { re_conn->encode(rmFE_0Manifold,1); // along e0 *not* attached in a manifold way if (e0->target == v0) { re_conn->encode(rmFE_0NonManifoldOriented,0); // along e0 attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "nmo "); // how many oriented non-manifold edges are around v0 that could potentially be e0? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->target == v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmFE_0NonManifoldOriented,1); // along e0 *not* attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "nmno "); // how many not-oriented non-manifold edges are around v0 that could potentially be e0? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->target != v0) { if (v0->list[i] == e0) candidate = candidate_count; candidate_count++; } } } } if (candidate_count != 1) { re_conn->encode(candidate_count,candidate); PRINT_DEBUG_OUTPUT(stderr, "c%d:%d ",candidate_count,candidate); } // encode edge e2 (e.g. the edge from v2 to v0) candidate = -1; candidate_count = 0; if (e2->degree == 1) { re_conn->encode(rmFE_2Manifold,0); // along e2 attached in a manifold way if (e2->origin == v0) { re_conn->encode(rmFE_2ManifoldOriented,0); // along e2 attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "mo "); // how many oriented manifold edges are around v0 that could potentially be e2? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->origin == v0) { if (v0->list[i] == e2) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmFE_2ManifoldOriented,1); // along e2 *not* attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "mno "); // how many not-oriented manifold edges are around v0 that could potentially be e2? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree == 1 && v0->list[i]->origin != v0) { if (v0->list[i] == e2) candidate = candidate_count; candidate_count++; } } } } else { re_conn->encode(rmFE_2Manifold,1); // along e2 *not* attached in a manifold way if (e2->origin == v0) { re_conn->encode(rmFE_2NonManifoldOriented,0); // along e2 attached in an oriented way PRINT_DEBUG_OUTPUT(stderr, "nmo "); // how many oriented non-manifold edges are around v0 that could potentially be e2? for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->origin == v0) { if (v0->list[i] == e2) candidate = candidate_count; candidate_count++; } } } else { re_conn->encode(rmFE_2NonManifoldOriented,1); // along e2 *not* attached in an oriented way // how many not-oriented non-manifold edges are around v0 that could potentially be e2? PRINT_DEBUG_OUTPUT(stderr, "nmno "); for (i = 0; i < v0->list_size; i++) { if (v0->list[i]->degree > 1 && v0->list[i]->origin != v0) { if (v0->list[i] == e2) candidate = candidate_count; candidate_count++; } } } } if (candidate_count != 1) { re_conn->encode(candidate_count,candidate); PRINT_DEBUG_OUTPUT(stderr, "c%d:%d ",candidate_count,candidate); } } // update cache #if defined(USE_CACHE) lc->put(v0->index, v1->index, v2->index, v0, v1, v2); #endif if (rot != 0) { // printf("WARNING "); } // increment vertex use_counts, create edges, and update edge degrees for (j = 0; j < 3; j++) { i = (j+rot)%3; vertices[i]->use_count++; if (e_visited[i] == 0) { edges[i] = allocEdge(vertices[(i+2)%3]->v); edges[i]->origin = vertices[i]; edges[i]->target = vertices[(i+1)%3]; addEdgeToVertex(edges[i],vertices[i]); addEdgeToVertex(edges[i],vertices[(i+1)%3]); } else { if (edges[i]->degree == 1) { edges[i]->origin->degree_one--; edges[i]->target->degree_one--; } edges[i]->degree++; } } // write finalization info and finalize vertices for (j = 0; j < 3; j++) { i = (j+rot)%3; degree_one = vertices[i]->degree_one; if (degree_one >= MAX_DEGREE_ONE) { degree_one = MAX_DEGREE_ONE-1; } use_count = vertices[i]->use_count; if (use_count >= MAX_USE_COUNT) { use_count = MAX_USE_COUNT-1; } re_conn_final->encode(rmFinalized[degree_one][use_count],t_final[i]); // PRINT_DEBUG_OUTPUT(stderr, "f%d:%d:%d ",degree_one,use_count,t_final[i]); if (t_final[i]) { SMvertex* vertex = vertices[i]; vertex_hash->erase(hash_elements[i]); dv->removeElement(vertex); for (int k = 0; k < vertex->list_size; k++) { SMedge* edge = vertex->list[k]; if (vertex == edge->origin) { removeEdgeFromVertex(edge, edge->target); } else { removeEdgeFromVertex(edge, edge->origin); } deallocEdge(edge); } deallocVertex(vertex); } } f_count++; }