draco/docs/spec/edgebreaker.traversal.prediction.degree.md
2017-10-27 11:44:48 -07:00

3.1 KiB

EdgeBreaker Traversal Prediction Degree

AddCornerToTraversalStack()

void AddCornerToTraversalStack(ci, priority) {
  traversal_stacks_[priority].push_back(ci);
  if (priority < best_priority_)
    best_priority_ = priority;
}

{:.draco-syntax }

ComputePriority()

int ComputePriority(corner_id) {
  CornerToVerts(curr_att_dec, corner_id, &v_tip, &next_vert, &prev_vert);
  priority = 0;
  if (!is_vertex_visited_[v_tip]) {
    degree = ++prediction_degree_[v_tip];
    priority = (degree > 1 ? 1 : 2);
  }
  if (priority >= kMaxPriority)
    priority = kMaxPriority - 1;
  return priority;
}

{:.draco-syntax }

PopNextCornerToTraverse()

int PopNextCornerToTraverse() {
  for (i = best_priority_; i < kMaxPriority; ++i) {
    if (!traversal_stacks_[i].empty()) {
      ret = traversal_stacks_[i].pop_back();
      best_priority_ = i;
      return ret;
    }
  }
  return kInvalidCornerIndex;
}

{:.draco-syntax }

PredictionDegree_TraverseFromCorner()

void PredictionDegree_TraverseFromCorner(corner_id) {
  traversal_stacks_[0].push_back(corner_id);
  best_priority_ = 0;
  CornerToVerts(curr_att_dec, corner_id, &tip_vertex, &next_vert, &prev_vert);
  if (!is_vertex_visited_[next_vert]) {
    is_vertex_visited_[next_vert] = true;
    next_c = Next(corner_id);
    OnNewVertexVisited(next_vert, next_c);
  }
  if (!is_vertex_visited_[prev_vert]) {
    is_vertex_visited_[prev_vert] = true;
    prev_c = Previous(corner_id);
    OnNewVertexVisited(prev_vert, prev_c);
  }
  if (!is_vertex_visited_[tip_vertex]) {
    is_vertex_visited_[tip_vertex] = true;
    OnNewVertexVisited(tip_vertex, corner_id);
  }
  while ((corner_id = PopNextCornerToTraverse()) >= 0) {
    face_id = corner_id / 3;
    if (IsFaceVisited(face_id)) {
      continue;
    }
    while (true) {
      face_id = corner_id / 3;
      is_face_visited_[face_id] = true;
      CornerToVerts(curr_att_dec, corner_id, &vert_id, &next_vert, &prev_vert);
      if (!is_vertex_visited_[vert_id]) {
        is_vertex_visited_[vert_id] = true;
        OnNewVertexVisited(vert_id, corner_id);
      }
      right_corner_id = GetRightCorner(corner_id);
      left_corner_id = GetLeftCorner(corner_id);
      right_face_id = right_corner_id < 0 ? -1 : right_corner_id / 3;
      left_face_id = left_corner_id < 0 ? -1 : left_corner_id / 3;
      is_right_face_visited = IsFaceVisited(right_face_id);
      is_left_face_visited = IsFaceVisited(left_face_id);
      if (!is_left_face_visited) {
        priority = ComputePriority(left_corner_id);
        if (is_right_face_visited && priority <= best_priority_) {
          corner_id = left_corner_id;
          continue;
        } else {
          AddCornerToTraversalStack(left_corner_id, priority);
        }
      }
      if (!is_right_face_visited) {
        priority = ComputePriority(right_corner_id);
        if (priority <= best_priority_) {
          corner_id = right_corner_id;
          continue;
        } else {
          AddCornerToTraversalStack(right_corner_id, priority);
        }
      }
      break;
    }
  }
}

{:.draco-syntax }