// 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);
}
예제 #2
0
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++;
}