static void processOneEdge(const V2 &edge,
                                 const carve::csg::detail::LoopEdges &a_edge_map,
                                 const carve::csg::detail::LoopEdges &b_edge_map,
                                 Classification &a_classification,
                                 Classification &b_classification,
								 double EPSILON) {
        GrpEdgeSurfMap a_edge_surfaces;
        GrpEdgeSurfMap b_edge_surfaces;

        carve::geom3d::Vector edge_vector = (edge.second->v - edge.first->v).normalized();
        carve::geom3d::Vector base_vector = perpendicular(edge_vector);

        carve::csg::detail::LoopEdges::const_iterator ae_f = a_edge_map.find(edge);
        carve::csg::detail::LoopEdges::const_iterator ae_r = a_edge_map.find(flip(edge));
        CARVE_ASSERT(ae_f != a_edge_map.end() || ae_r != a_edge_map.end());

        carve::csg::detail::LoopEdges::const_iterator be_f = b_edge_map.find(edge);
        carve::csg::detail::LoopEdges::const_iterator be_r = b_edge_map.find(flip(edge));
        CARVE_ASSERT(be_f != b_edge_map.end() || be_r != b_edge_map.end());

        if (ae_f != a_edge_map.end() && !processForwardEdgeSurfaces(a_edge_surfaces, (*ae_f).second, edge_vector, base_vector,EPSILON)) return;
        if (ae_r != a_edge_map.end() && !processReverseEdgeSurfaces(a_edge_surfaces, (*ae_r).second, edge_vector, base_vector,EPSILON)) return;
        if (be_f != b_edge_map.end() && !processForwardEdgeSurfaces(b_edge_surfaces, (*be_f).second, edge_vector, base_vector,EPSILON)) return;
        if (be_r != b_edge_map.end() && !processReverseEdgeSurfaces(b_edge_surfaces, (*be_r).second, edge_vector, base_vector,EPSILON)) return;

        classifyAB(a_edge_surfaces, b_edge_surfaces, b_classification);
        classifyAB(b_edge_surfaces, a_edge_surfaces, a_classification);
      }
void carve::csg::CSG::groupFaceLoops(carve::mesh::MeshSet<3> *src,
                                     carve::csg::FaceLoopList &face_loops,
                                     const carve::csg::detail::LoopEdges &loop_edges,
                                     const carve::csg::V2Set &no_cross,
                                     carve::csg::FLGroupList &out_loops) {
  // Find all the groups of face loops that are connected by edges
  // that are not part of no_cross.
  // this could potentially be done with a disjoint set data-structure.
#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
  static int call_num = 0;
  call_num++;
#endif

  static carve::TimingName GROUP_FACE_LOOPS("groupFaceLoops()");

  carve::TimingBlock block(GROUP_FACE_LOOPS);

  int tag_num = 0;
  while (face_loops.size()) {
    out_loops.push_back(FaceLoopGroup(src));
    carve::csg::FaceLoopGroup &group = (out_loops.back());
    carve::csg::FaceLoopList &curr = (group.face_loops);
    carve::csg::V2Set &perim = (group.perimeter);

    carve::csg::FaceLoop *expand = face_loops.head;

    expand->group = &group;
    face_loops.remove(expand);
    curr.append(expand);

    while (expand) {
      std::vector<carve::mesh::MeshSet<3>::vertex_t *> &loop = (expand->vertices);
      carve::mesh::MeshSet<3>::vertex_t *v1, *v2;

      v1 = loop.back();
      for (size_t i = 0; i < loop.size(); ++i) {
        v2 = loop[i];

        carve::csg::V2Set::const_iterator nc = no_cross.find(std::make_pair(v1, v2));
        if (nc == no_cross.end()) {
          carve::csg::detail::LoopEdges::const_iterator j;

          j = loop_edges.find(std::make_pair(v1, v2));
          if (j != loop_edges.end()) {
            for (std::list<carve::csg::FaceLoop *>::const_iterator
                   k = (*j).second.begin(), ke = (*j).second.end();
                 k != ke; ++k) {
              if ((*k)->group != NULL ||
                  (*k)->orig_face->mesh != expand->orig_face->mesh) continue;
              face_loops.remove((*k));
              curr.append((*k));
              (*k)->group = &group;
            }
          }

          j = loop_edges.find(std::make_pair(v2, v1));
          if (j != loop_edges.end()) {
            for (std::list<carve::csg::FaceLoop *>::const_iterator
                   k = (*j).second.begin(), ke = (*j).second.end();
                 k != ke; ++k) {
              if ((*k)->group != NULL ||
                  (*k)->orig_face->mesh != expand->orig_face->mesh) continue;
              face_loops.remove((*k));
              curr.append((*k));
              (*k)->group = &group;
            }
          }
        } else {
          perim.insert(std::make_pair(v1, v2));
        }
        v1 = v2;
      }
      expand = expand->next;
    }
    tag_num++;

#if defined(CARVE_DEBUG_WRITE_PLY_DATA)
    {
      carve::mesh::MeshSet<3> *poly = groupToPolyhedron(group);
      char buf[128];
      sprintf(buf, "/tmp/group-%d-%p.ply", call_num, &curr);
      std::string out(buf);
      ::writePLY(out, poly, false);
      delete poly;
    }
#endif
  }
}