Ejemplo n.º 1
0
   // Given an edge, the constructor for EdgeRecord finds the
   // optimal point associated with the edge's current quadric,
   // and assigns this edge a cost based on how much quadric
   // error is observed at this optimal point.
   EdgeRecord::EdgeRecord( EdgeIter& _edge )
   : edge( _edge )
   {
      // TODO Compute the combined quadric from the edge endpoints.
			Matrix4x4 q = _edge->halfedge()->vertex()->quadric +
										_edge->halfedge()->twin()->vertex()->quadric;
		 
      // TODO Build the 3x3 linear system whose solution minimizes
      // the quadric error associated with these two endpoints.
			Matrix3x3 quadratic;
			quadratic(0,0) =  q(0,0); quadratic(0,1) =  q(0,1); quadratic(0,2) =  q(0,2);
			quadratic(1,0) =  q(1,0); quadratic(1,1) =  q(1,1); quadratic(1,2) =  q(1,2);
			quadratic(2,0) =  q(2,0); quadratic(2,1) =  q(2,1); quadratic(2,2) =  q(2,2);
			Vector3D linear(q(3,0), q(3,1), q(3,2));
		 
      // TODO Use this system to solve for the optimal position, and
      // TODO store it in EdgeRecord::optimalPoint.
			optimalPoint = - quadratic.inv() * linear;
		 
      // TODO Also store the cost associated with collapsing this edge
      // TODO in EdgeRecord::Cost.
			Vector4D optH(optimalPoint);
			optH.w = 1.0;
			score = dot(optH, q * optH);
   }
const HalfedgeMesh& HalfedgeMesh::operator=(const HalfedgeMesh& mesh)
// The assignment operator does a "deep" copy of the halfedge mesh data
// structure; in other words, it makes new instances of each mesh element, and
// ensures that pointers in the copy point to the newly allocated elements
// rather than elements in the original mesh.  This behavior is especially
// important for making assignments, since the mesh on the right-hand side of an
// assignment may be temporary (hence any pointers to elements in this mesh will
// become invalid as soon as it is released.)
{
  // Clear any existing elements.
  halfedges.clear();
  vertices.clear();
  edges.clear();
  faces.clear();
  boundaries.clear();

  // These maps will be used to identify elements of the old mesh
  // with elements of the new mesh.  (Note that we can use a single
  // map for both interior and boundary faces, because the map
  // doesn't care which list of faces these iterators come from.)
  map<HalfedgeCIter, HalfedgeIter> halfedgeOldToNew;
  map<VertexCIter, VertexIter> vertexOldToNew;
  map<EdgeCIter, EdgeIter> edgeOldToNew;
  map<FaceCIter, FaceIter> faceOldToNew;

  // Copy geometry from the original mesh and create a map from
  // pointers in the original mesh to those in the new mesh.
  for (HalfedgeCIter h = mesh.halfedgesBegin(); h != mesh.halfedgesEnd(); h++)
    halfedgeOldToNew[h] = halfedges.insert(halfedges.end(), *h);
  for (VertexCIter v = mesh.verticesBegin(); v != mesh.verticesEnd(); v++)
    vertexOldToNew[v] = vertices.insert(vertices.end(), *v);
  for (EdgeCIter e = mesh.edgesBegin(); e != mesh.edgesEnd(); e++)
    edgeOldToNew[e] = edges.insert(edges.end(), *e);
  for (FaceCIter f = mesh.facesBegin(); f != mesh.facesEnd(); f++)
    faceOldToNew[f] = faces.insert(faces.end(), *f);
  for (FaceCIter b = mesh.boundariesBegin(); b != mesh.boundariesEnd(); b++)
    faceOldToNew[b] = boundaries.insert(boundaries.end(), *b);

  // "Search and replace" old pointers with new ones.
  for (HalfedgeIter he = halfedgesBegin(); he != halfedgesEnd(); he++) {
    he->next() = halfedgeOldToNew[he->next()];
    he->twin() = halfedgeOldToNew[he->twin()];
    he->vertex() = vertexOldToNew[he->vertex()];
    he->edge() = edgeOldToNew[he->edge()];
    he->face() = faceOldToNew[he->face()];
  }
  for (VertexIter v = verticesBegin(); v != verticesEnd(); v++)
    v->halfedge() = halfedgeOldToNew[v->halfedge()];
  for (EdgeIter e = edgesBegin(); e != edgesEnd(); e++)
    e->halfedge() = halfedgeOldToNew[e->halfedge()];
  for (FaceIter f = facesBegin(); f != facesEnd(); f++)
    f->halfedge() = halfedgeOldToNew[f->halfedge()];
  for (FaceIter b = boundariesBegin(); b != boundariesEnd(); b++)
    b->halfedge() = halfedgeOldToNew[b->halfedge()];

  // Return a reference to the new mesh.
  return *this;
}
Ejemplo n.º 3
0
 static std::string getEdgeAttributes(const void *Node, EdgeIter EI) {
   SDValue Op = EI.getNode()->getOperand(EI.getOperand());
   EVT VT = Op.getValueType();
   if (VT == MVT::Flag)
     return "color=red,style=bold";
   else if (VT == MVT::Other)
     return "color=blue,style=dashed";
   return "";
 }
Ejemplo n.º 4
0
 static std::string getEdgeAttributes(PAGNode *node, EdgeIter EI, PAG *pag) {
     const PAGEdge* edge = *(EI.getCurrent());
     assert(edge && "No edge found!!");
     if (isa<AddrPE>(edge)) {
         return "color=green";
     } else if (isa<CopyPE>(edge)) {
         return "color=black";
     } else if (isa<GepPE>(edge)) {
         return "color=purple";
     } else if (isa<StorePE>(edge)) {
         return "color=blue";
     } else if (isa<LoadPE>(edge)) {
         return "color=red";
     } else if (isa<TDForkPE>(edge)) {
         return "color=Turquoise";
     } else if (isa<TDJoinPE>(edge)) {
         return "color=Turquoise";
     } else if (isa<CallPE>(edge)) {
         return "color=black,style=dashed";
     } else if (isa<RetPE>(edge)) {
         return "color=black,style=dotted";
     }
     else {
         assert(0 && "No such kind edge!!");
     }
 }
Ejemplo n.º 5
0
//-----------------------------------------
void LegacyWriter::writeEdgesNode(xmlTextWriterPtr writer) {
//-----------------------------------------
    /* Start an element named "edges" as child of graph. */
    int rc = xmlTextWriterStartElement(writer, BAD_CAST "edges");
    if (rc < 0) {
        throw FileWriterException("Error at xmlTextWriterStartElement");
    }

    /* Iterate on each edge */
    EdgeIter* it = _gexf->getUndirectedGraph().getEdges();
    unsigned int cpt = 0;
    while(it->hasNext()) {
        const t_id edge_id = it->next();
        const t_id source_id = it->currentSource();
        const t_id target_id = it->currentTarget();

        const unsigned int new_id = cpt++;
        unsigned int new_source = _nodes.find(source_id)->second;
        unsigned int new_target = _nodes.find(target_id)->second;

        const unsigned int card = (unsigned int)it->currentProperty(EDGE_WEIGHT);
        const t_edge_type type = (t_edge_type)it->currentProperty(EDGE_TYPE);
        this->writeEdgeNode(writer, Conv::idToStr(edge_id), Conv::unsignedIntToStr(new_id), Conv::unsignedIntToStr(new_source), Conv::unsignedIntToStr(new_target), Conv::unsignedIntToStr(card), Conv::edgeTypeToStr(type));
    }

    /* Close the element named edges. */
    rc = xmlTextWriterEndElement(writer);
    if (rc < 0) {
        throw FileWriterException("Error at xmlTextWriterEndElement");
    }
}
Ejemplo n.º 6
0
	 bool willFlipEdgeImprove(EdgeIter e0)
	 {
		 
		 //1. collect elements
		 
		 //Halfedges
		 HalfedgeIter h0 = e0->halfedge();
		 HalfedgeIter h3 = h0->twin();
		 
		 //Faces
		 FaceIter f0 = h0->face();
		 FaceIter f1 = h3->face();
		 
		 //Early Exit #1: Ignore requests to flip boundary edges
		 if(f0->isBoundary() || f1->isBoundary())
			 return false;
		 
		 HalfedgeIter h1 = h0->next();
		 HalfedgeIter h2 = h1->next();
		 
		 
		 HalfedgeIter h4 = h3->next();
		 HalfedgeIter h5 = h4->next();
		 
		 //Vertices
		 VertexIter v0 = h0->vertex();
		 VertexIter v1 = h3->vertex();
		 VertexIter v2 = h2->vertex();
		 VertexIter v3 = h5->vertex();
		 
		 //Early Exit #2: Does the flipped edge already exist?
		 HalfedgeIter h = v2->halfedge();
		 do
		 {
			 h = h->twin();
			 if(h->vertex() == v3)
				 return false;
			 h = h->next();
		 }
		 while(h != v2->halfedge());
		 
		 int oldDev =
		 std::abs((int)v0->degree() - 6) +
		 std::abs((int)v1->degree() - 6) +
		 std::abs((int)v2->degree() - 6) +
		 std::abs((int)v3->degree() - 6);
		 
		 int newDev =
		 std::abs((int)v0->degree() - 7) +
		 std::abs((int)v1->degree() - 7) +
		 std::abs((int)v2->degree() - 5) +
		 std::abs((int)v3->degree() - 5);
		 
		 if( newDev < oldDev)
			 return true;
		 else return false;
	 }
Ejemplo n.º 7
0
 static std::string getEdgeSourceLabel(PAGNode *node, EdgeIter EI) {
     const PAGEdge* edge = *(EI.getCurrent());
     assert(edge && "No edge found!!");
     if(const CallPE* calledge = dyn_cast<CallPE>(edge)) {
         const llvm::Instruction* callInst= calledge->getCallInst();
         return analysisUtil::getSourceLoc(callInst);
     }
     else if(const RetPE* retedge = dyn_cast<RetPE>(edge)) {
         const llvm::Instruction* callInst= retedge->getCallInst();
         return analysisUtil::getSourceLoc(callInst);
     }
     return "";
 }
Ejemplo n.º 8
0
    static std::string getEdgeAttributes(PTACallGraphNode *node, EdgeIter EI, PTACallGraph *PTACallGraph) {

        //TODO: mark indirect call of Fork with different color
        PTACallGraphEdge* edge = *(EI.getCurrent());
        assert(edge && "No edge found!!");

        std::string color;

        if (edge->getEdgeKind() == PTACallGraphEdge::TDJoinEdge) {
            color = "color=green";
        } else if (edge->getEdgeKind() == PTACallGraphEdge::TDForkEdge) {
            color = "color=blue";
        } else {
            color = "color=black";
        }
        if (0 != edge->getIndirectCalls().size()) {
            color = "color=red";
        }
        return color;
    }
Ejemplo n.º 9
0
 static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) {
   SDNode *TargetNode = *I;
   SDNodeIterator NI = SDNodeIterator::begin(TargetNode);
   std::advance(NI, I.getNode()->getOperand(I.getOperand()).getResNo());
   return NI;
 }
Ejemplo n.º 10
0
   void MeshResampler::resample( HalfedgeMesh& mesh )
   {
      // TODO Compute the mean edge length.
			double mean2 = 0;
			for(auto edge = mesh.edgesBegin(); edge != mesh.edgesEnd(); ++edge)
			{
				Vector3D v0 = edge->halfedge()->vertex()->position;
				Vector3D v1 = edge->halfedge()->twin()->vertex()->position;
				mean2 += (v0 - v1).norm();
			}
			mean2 /= (double)mesh.nEdges();
			mean2 *= mean2;
		 
      // TODO Repeat the four main steps for 5 or 6 iterations
			const int ITER_TIMES = 5;
			const int SMOOTH_TIMES = 20;
			const double WEIGHT_FACTOR = 0.2;
			const double LONG_EDGE_2 = 1.7777777778;
			const double SHORT_EDGE_2 = 0.64;
			std::unordered_set<EdgeIter> edgeSet;
			edgeSet.reserve(mesh.nEdges());
			
			for(int i = 0; i < ITER_TIMES; ++i)
			{
				// TODO Split edges much longer than the target length (being careful about how the loop is written!)
				EdgeIter old_end = mesh.edgesEnd();
				--old_end;
				for(auto edge = mesh.edgesBegin(); edge != mesh.edgesEnd(); ++edge)
				{
					Vector3D v0 = edge->halfedge()->vertex()->position;
					Vector3D v1 = edge->halfedge()->twin()->vertex()->position;
					if((v0 - v1).norm2() > LONG_EDGE_2 * mean2)
					{
						mesh.splitEdge(edge);
					}
					if(edge == old_end)
						break;
				}
				
				// TODO Collapse edges much shorter than the target length.  Here we need to be EXTRA careful about
				// TODO advancing the loop, because many edges may have been destroyed by a collapse (which ones?)
				edgeSet.clear();
				for(auto edge = mesh.edgesBegin(); edge != mesh.edgesEnd(); ++edge)
				{
					edgeSet.insert(edge);
				}
				while(edgeSet.size() > 0)
				{
					EdgeIter curr = *(edgeSet.begin());
					edgeSet.erase(edgeSet.begin());
					
					VertexIter v0 = curr->halfedge()->vertex();
					VertexIter v1 = curr->halfedge()->twin()->vertex();
					
					if((v0->position - v1->position).norm2() >= SHORT_EDGE_2 * mean2)
						continue;
					
					HalfedgeIter h = v0->halfedge();
					do
					{
						if(edgeSet.find(h->edge()) != edgeSet.end())
							edgeSet.erase(h->edge());
						h = h->twin()->next();
					}
					while(h != v0->halfedge());
					
					h = v1->halfedge();
					do
					{
						if(edgeSet.find(h->edge()) != edgeSet.end())
							edgeSet.erase(h->edge());
						h = h->twin()->next();
					}
					while(h != v1->halfedge());
					
					VertexIter v_new = mesh.collapseEdge(curr);
					if(v_new != mesh.verticesEnd())
					{
						h = v_new->halfedge();
						do
						{
							edgeSet.insert(h->edge());
							h = h->twin()->next();
						}
						while(h != v_new->halfedge());
					}
				}
				
				// TODO Now flip each edge if it improves vertex degree
				for(auto edge = mesh.edgesBegin(); edge != mesh.edgesEnd(); ++edge)
				{
					if(willFlipEdgeImprove(edge))
						mesh.flipEdge(edge);
				}

//				 TODO Finally, apply some tangential smoothing to the vertex positions

				for(int j = 0; j < SMOOTH_TIMES; ++j)
				{
					for(auto vertex = mesh.verticesBegin(); vertex != mesh.verticesEnd(); ++vertex)
					{
						if(vertex->isBoundary())
							continue;
						vertex->computeCentroid();
					}
					
					for(auto vertex = mesh.verticesBegin(); vertex != mesh.verticesEnd(); ++vertex)
					{
						if(vertex->isBoundary())
							continue;
						Vector3D dir = vertex->centroid - vertex->position;
						Vector3D nrm = vertex->normal();
						dir -= (dot(nrm, dir) * nrm);
						vertex->position = vertex->position + WEIGHT_FACTOR * dir;
					}
				}

			}

   }
Ejemplo n.º 11
0
   void MeshResampler::upsample( HalfedgeMesh& mesh )
   // This routine should increase the number of triangles in the mesh using Loop subdivision.
   {
      // Each vertex and edge of the original surface can be associated with a vertex in the new (subdivided) surface.
      // Therefore, our strategy for computing the subdivided vertex locations is to *first* compute the new positions
      // using the connectity of the original (coarse) mesh; navigating this mesh will be much easier than navigating
      // the new subdivided (fine) mesh, which has more elements to traverse.  We will then assign vertex positions in
      // the new mesh based on the values we computed for the original mesh.


      // TODO Compute new positions for all the vertices in the input mesh, using the Loop subdivision rule,
      // TODO and store them in Vertex::newPosition. At this point, we also want to mark each vertex as being
      // TODO a vertex of the original mesh.
			for(VertexIter v = mesh.verticesBegin(); v != mesh.verticesEnd(); ++v )
			{
				v->isNew = false;
				if(!v->isBoundary())
				{
					//By convention, Vertex::degree() returns the face degree,
					//not the edge degree. The edge degree can be computed by finding the face
					//degree, and adding 1 if the vertex is a boundary vertex.
					int degree = v->degree();
					
					double u = degree == 3 ? 0.1875 : (3.0 / (8.0 * degree)); //0.1875 = 3/16
					v->newPosition = v->position * (1.0 - u * degree);
					HalfedgeIter h = v->halfedge();
					do
					{
						h = h->twin();
						v->newPosition += (h->vertex()->position * u);
						h = h->next();
					}
					while(h != v->halfedge());
					}
				else
				{
					HalfedgeIter h0_b = v->halfedge();
					while(!h0_b->isBoundary())
						h0_b = h0_b->twin()->next();
					VertexIter v0_b = h0_b->twin()->vertex();
					
					HalfedgeIter h1_b = v->halfedge();
					do
					{
						h1_b = h1_b->twin();
						if(h1_b->isBoundary())
							break;
						h1_b = h1_b->next();
					}
					while(h1_b != v->halfedge());
					VertexIter v1_b = h1_b->vertex();
					v->newPosition = 0.75 * v->position + 0.125 * (v0_b->position + v1_b->position);
				}
			}

      // TODO Next, compute the updated vertex positions associated with edges, and store it in Edge::newPosition.
			for(EdgeIter e = mesh.edgesBegin(); e != mesh.edgesEnd(); ++e)
			{
				e->isNew = false;
				FaceIter f0 = e->halfedge()->face();
				FaceIter f1 = e->halfedge()->twin()->face();
				if(f0->isBoundary() || f1->isBoundary())
				{
					VertexIter v0_b = e->halfedge()->vertex();
					VertexIter v1_b = e->halfedge()->twin()->vertex();
					e->newPosition = 0.5 * (v0_b->position + v1_b->position);
				}
				else
				{
					Vector3D v0,v1; //this diagonal
					v0 = e->halfedge()->vertex()->position;
					v1 = e->halfedge()->twin()->vertex()->position;
					e->newPosition = 0.375 * (v0 + v1);
					Vector3D v2,v3; //opposite diagonal
					v2 = e->halfedge()->next()->next()->vertex()->position;
					v3 = e->halfedge()->twin()->next()->next()->vertex()->position;
					e->newPosition += 0.125 * (v2 + v3);
				}
			}

      // TODO Next, we're going to split every edge in the mesh, in any order.  For future
      // TODO reference, we're also going to store some information about which subdivided
      // TODO edges come from splitting an edge in the original mesh, and which edges are new,
      // TODO by setting the flat Edge::isNew.  Note that in this loop, we only want to iterate
      // TODO over edges of the original mesh---otherwise, we'll end up splitting edges that we
      // TODO just split (and the loop will never end!)
			EdgeIter e = mesh.edgesBegin();
			while(e != mesh.edgesEnd())
			{
				EdgeIter next = e;
				++next;
				if(!e->isNew &&
					 !e->halfedge()->vertex()->isNew &&
					 !e->halfedge()->twin()->vertex()->isNew)
				{
					VertexIter e_v0 = e->halfedge()->vertex();
					VertexIter e_v1 = e->halfedge()->twin()->vertex();
					VertexIter v_new = mesh.splitEdge(e);
					v_new->isNew = true;
					v_new->position = e->newPosition;
					
					HalfedgeIter h = v_new->halfedge();
					do
					{
						h = h->twin();
						VertexIter v = h->vertex();
						h->edge()->isNew = (v != e_v0 && v != e_v1);
						h = h->next();
					}
					while(h != v_new->halfedge());
				}
				
				e = next;
			}

      // TODO Now flip any new edge that connects an old and new vertex.
			for(EdgeIter e = mesh.edgesBegin(); e!= mesh.edgesEnd(); ++e)
			{
				VertexIter v0 = e->halfedge()->vertex();
				VertexIter v1 = e->halfedge()->twin()->vertex();
				bool v_old_new = (v0->isNew && !v1->isNew) || (!v0->isNew && v1->isNew);
				if(v_old_new && e->isNew)
					mesh.flipEdge(e);
			}

      // TODO Finally, copy the new vertex positions into final Vertex::position.
		 for(VertexIter v = mesh.verticesBegin(); v != mesh.verticesEnd(); ++v)
		 {
			 if(!v->isNew)
				 v->position = v->newPosition;
		 }
   }
Ejemplo n.º 12
0
   EdgeIter HalfedgeMesh::flipEdge( EdgeIter e0 )
   {
      // TODO This method should flip the given edge and return an iterator to the flipped edge.
		
		 //1. collect elements
		 
		 //Halfedges
		 HalfedgeIter h0 = e0->halfedge();
		 HalfedgeIter h3 = h0->twin();
		 
		 //Faces
		 FaceIter f0 = h0->face();
		 FaceIter f1 = h3->face();
		 
		 //Early Exit #1: Ignore requests to flip boundary edges
		 if(f0->isBoundary() || f1->isBoundary())
			 return edgesEnd();
		 
		 HalfedgeIter h1 = h0->next();
		 HalfedgeIter h2 = h1->next();
		 
	
		 HalfedgeIter h4 = h3->next();
		 HalfedgeIter h5 = h4->next();
		 
		 //Vertices
		 VertexIter v0 = h0->vertex();
		 VertexIter v1 = h3->vertex();
		 VertexIter v2 = h2->vertex();
		 VertexIter v3 = h5->vertex();
		 
		 //Early Exit #2: Does the flipped edge already exist?
		 HalfedgeIter h = v2->halfedge();
		 do
		 {
			 h = h->twin();
			 if(h->vertex() == v3)
				 return edgesEnd();
			 h = h->next();
		 }
		 while(h != v2->halfedge());
		 
		 //Edges
		 //e0 is given

		 //2. reassign elements
		 
		 //HalfEdges
		 h0->next() = h5; h0->vertex() = v2;
		 h5->next() = h1; h5->face() = f0;
		 h1->next() = h0;
		 h3->next() = h2; h3->vertex() = v3;
		 h2->next() = h4; h2->face() = f1;
		 h4->next() = h3;
		
		 //Vertices
		 v0->halfedge() = h4;
		 v1->halfedge() = h1;
		 v2->halfedge() = h0;
		 v3->halfedge() = h3;
		 
		 //Faces
		 f0->halfedge() = h0;
		 f1->halfedge() = h3;
		 
		 return e0;
   }
Ejemplo n.º 13
0
   VertexIter HalfedgeMesh::splitEdge( EdgeIter e0 )
   {
      // TODO This method should split the given edge and return an iterator to the newly inserted vertex.
      // TODO The halfedge of this vertex should point along the edge that was split, rather than the new edges.
		 
		 //1. collect elements
		 //Halfedges
		 HalfedgeIter h0 = e0->halfedge();
		 HalfedgeIter h3 = h0->twin();
		 
		 //Faces
		 FaceIter f0 = h0->face();
		 FaceIter f1 = h3->face();
		 
		 //Ignore requests to split boundary edges
		 if(f0->isBoundary() && f1->isBoundary())
			 return verticesEnd();
		 else if(f0->isBoundary())
		 {
			 //1. collent elements (continue)
			 HalfedgeIter h1 = h0->next();
			 
			 HalfedgeIter h4 = h3->next();
			 HalfedgeIter h5 = h4->next();

			 //Vertices
			 VertexIter v0 = h0->vertex();
			 VertexIter v1 = h3->vertex();
			 VertexIter v3 = h5->vertex();
			 
			 //Edges
			 //e0 is given
			 
			 //2. allocate new elements
			 HalfedgeIter h11 = newHalfedge();
			 HalfedgeIter h13 = newHalfedge();
			 HalfedgeIter h14 = newHalfedge();
			 HalfedgeIter h15 = newHalfedge();
			 
			 FaceIter f3 = newFace();
			 
			 EdgeIter e6 = newEdge();
			 EdgeIter e7 = newEdge();
			 
			 VertexIter v4 = newVertex();
			 v4->position = 0.5f * (v0->position + v1->position);
			 
			 //3. reassign elements
			 
				//Halfedges
			 h0->next() = h11;
			 h11->setNeighbors(h1, h14, v4, e7, f0);
			 h3->vertex() = v4;
			 h4->next() = h13;
			 h13->setNeighbors(h3, h15, v3, e6, f1);
			 h14->setNeighbors(h15, h11, v1, e7, f3);
			 h15->setNeighbors(h5, h13, v4, e6, f3);
			 h5->next() = h14; h5->face() = f3;
			 
			 //Vertices
			 v0->halfedge() = h0;
			 v1->halfedge() = h14;
			 v3->halfedge() = h13;
			 v4->halfedge() = h3;
			 
			 //Edges
			 e6->halfedge() = h13;
			 e7->halfedge() = h14;
			 
			 //Faces
			 f1->halfedge() = h3;
			 f3->halfedge() = h14;
			 return v4;
			 
		 }
		 else if(f1->isBoundary())
		 {
			 //1. collent elements (continue)
			 HalfedgeIter h1 = h0->next();
			 HalfedgeIter h2 = h1->next();
			 
			 
			 //HalfedgeIter h4 = h3->next();
			 HalfedgeIter h5 = h3;
			 do
				 h5 = h5->next();
			 while(h5->next() != h3);
			 
			 //Vertices
			 VertexIter v0 = h0->vertex();
			 VertexIter v1 = h3->vertex();
			 VertexIter v2 = h2->vertex();
			 
			 //Edges
			 //e0 is given

			 //2. allocate new elements
			 HalfedgeIter h10 = newHalfedge();
			 HalfedgeIter h11 = newHalfedge();
			 HalfedgeIter h12 = newHalfedge();
			 HalfedgeIter h14 = newHalfedge();
			 
			 FaceIter f2 = newFace();
			 
			 EdgeIter e5 = newEdge();
			 EdgeIter e7 = newEdge();
			 
			 VertexIter v4 = newVertex();
			 v4->position = 0.5f * (v0->position + v1->position);
			 
			 //3. reassign elements
			 
			 //Halfedges
			 h0->next() = h10;
			 h10->setNeighbors(h2, h12, v4, e5, f0);
			 h11->setNeighbors(h1, h14, v4, e7, f2);
			 h1->next() = h12; h1->face() = f2;
			 h12->setNeighbors(h11, h10, v2, e5, f2);
			 h3->vertex() = v4;
			 h5->next() = h14;
			 
			 h14->setNeighbors(h3, h11, v1, e7, f1);
			 
			 //Vertices
			 v0->halfedge() = h0;
			 v1->halfedge() = h14;
			 v2->halfedge() = h12;
			 v4->halfedge() = h3;
			 
			 //Edges
			 e7->halfedge() = h11;
			 e5->halfedge() = h10;
			 
			 //Faces
			 f0->halfedge() = h0;
			 f1->halfedge() = h3;
			 f2->halfedge() = h1;
			 
			 return v4;
			 
		 }
		 else
		 {
			 //1. collent elements (continue)
			 HalfedgeIter h1 = h0->next();
			 HalfedgeIter h2 = h1->next();
			 
			 
			 HalfedgeIter h4 = h3->next();
			 HalfedgeIter h5 = h4->next();
			 
//			 HalfedgeIter h6 = h1->twin();
//			 HalfedgeIter h7 = h2->twin();
//			 HalfedgeIter h8 = h4->twin();
//			 HalfedgeIter h9 = h5->twin();
			 
			 //Vertices
			 VertexIter v0 = h0->vertex();
			 VertexIter v1 = h3->vertex();
			 VertexIter v2 = h2->vertex();
			 VertexIter v3 = h5->vertex();
			 
			 //Edges
			 //e0 is given
			 EdgeIter e1 = h1->edge();
			 EdgeIter e2 = h2->edge();
			 EdgeIter e3 = h4->edge();
			 EdgeIter e4 = h5->edge();
			 
			 //2. allocate new elements
			 HalfedgeIter h10 = newHalfedge();
			 HalfedgeIter h11 = newHalfedge();
			 HalfedgeIter h12 = newHalfedge();
			 HalfedgeIter h13 = newHalfedge();
			 HalfedgeIter h14 = newHalfedge();
			 HalfedgeIter h15 = newHalfedge();
			 
			 FaceIter f2 = newFace();
			 FaceIter f3 = newFace();
			 
			 EdgeIter e5 = newEdge();
			 EdgeIter e6 = newEdge();
			 EdgeIter e7 = newEdge();
		 
			 VertexIter v4 = newVertex();
			 v4->position = 0.5f * (v0->position + v1->position);

			 //3. reassign elements
		 
			 //Halfedges
			 h0->next() = h10; h0->twin() = h3; h0->vertex() = v0; h0->edge() = e0; h0->face() = f0;
			 
			 h1->next() = h12; /*h1->twin() = h6;*/ h1->vertex() = v1; h1->edge() = e1; h1->face() = f2;
			 
			 h2->next() = h0; /*h2->twin() = h7;*/ h2->vertex() = v2; h2->edge() = e2; h2->face() = f0;
		 
			 h3->next() = h4; h3->twin() = h0; h3->vertex() = v4; h3->edge() = e0; h3->face() = f1;
		 
			 h4->next() = h13; /*h4->twin() = h8;*/ h4->vertex() = v0; h4->edge() = e3; h4->face() = f1;
		 
			 h5->next() = h14; /*h5->twin() = h9;*/ h5->vertex() = v3; h5->edge() = e4; h5->face() = f3;
		 
//			 h6->twin() = h1; h6->vertex() = v2; h6->edge() = e1;
		 
//			 h7->twin() = h2; h7->vertex() = v0; h7->edge() = e2;
		 
//			 h8->twin() = h4; h8->vertex() = v3; h8->edge() = e3;
		 
//			 h9->twin() = h5; h9->vertex() = v1; h9->edge() = e4;
		 
			 h10->next() = h2; h10->twin() = h12; h10->vertex() = v4; h10->edge() = e5; h10->face() = f0;
		 
			 h11->next() = h1; h11->twin() = h14; h11->vertex() = v4; h11->edge() = e7; h11->face() = f2;
		 
			 h12->next() = h11; h12->twin() = h10; h12->vertex() = v2; h12->edge() = e5; h12->face() = f2;
		 
			 h13->next() = h3; h13->twin() = h15; h13->vertex() = v3; h13->edge() = e6; h13->face() = f1;
			 
			 h14->next() = h15; h14->twin() = h11; h14->vertex() = v1; h14->edge() = e7; h14->face() = f3;
		 
			 h15->next() = h5; h15->twin() = h13; h15->vertex() = v4; h15->edge() = e6; h15->face() = f3;
		 
			 //Vertices
			 v0->halfedge() = h0;
			 v1->halfedge() = h1;
			 v2->halfedge() = h2;
			 v3->halfedge() = h5;
			 v4->halfedge() = h3;
			 
			 //Edges
			 e0->halfedge() = h0;
			 e1->halfedge() = h1;
			 e2->halfedge() = h2;
			 e3->halfedge() = h4;
			 e4->halfedge() = h5;
			 e5->halfedge() = h10;
			 e6->halfedge() = h13;
			 e7->halfedge() = h11;
			 
			 //Faces
			 f0->halfedge() = h0;
			 f1->halfedge() = h3;
			 f2->halfedge() = h1;
			 f3->halfedge() = h5;
		 
			 return v4;
		 }
	 }
void HalfedgeMesh::build(const vector<vector<Index> >& polygons,
                         const vector<Vector3D>& vertexPositions)
// This method initializes the halfedge data structure from a raw list of
// polygons, where each input polygon is specified as a list of vertex indices.
// The input must describe a manifold, oriented surface, where the orientation
// of a polygon is determined by the order of vertices in the list. Polygons
// must have at least three vertices.  Note that there are no special conditions
// on the vertex indices, i.e., they do not have to start at 0 or 1, nor does
// the collection of indices have to be contiguous.  Overall, this initializer
// is designed to be robust but perhaps not incredibly fast (though of course
// this does not affect the performance of the resulting data structure).  One
// could also implement faster initializers that handle important special cases
// (e.g., all triangles, or data that is known to be manifold). Since there are
// no strong conditions on the indices of polygons, we assume that the list of
// vertex positions is given in lexicographic order (i.e., that the lowest index
// appearing in any polygon corresponds to the first entry of the list of
// positions and so on).
{
  // define some types, to improve readability
  typedef vector<Index> IndexList;
  typedef IndexList::const_iterator IndexListCIter;
  typedef vector<IndexList> PolygonList;
  typedef PolygonList::const_iterator PolygonListCIter;
  typedef pair<Index, Index> IndexPair;  // ordered pair of vertex indices,
                                         // corresponding to an edge of an
                                         // oriented polygon

  // Clear any existing elements.
  halfedges.clear();
  vertices.clear();
  edges.clear();
  faces.clear();
  boundaries.clear();

  // Since the vertices in our halfedge mesh are stored in a linked list,
  // we will temporarily need to keep track of the correspondence between
  // indices of vertices in our input and pointers to vertices in the new
  // mesh (which otherwise can't be accessed by index).  Note that since
  // we're using a general-purpose map (rather than, say, a vector), we can
  // be a bit more flexible about the indexing scheme: input vertex indices
  // aren't required to be 0-based or 1-based; in fact, the set of indices
  // doesn't even have to be contiguous.  Taking advantage of this fact makes
  // our conversion a bit more robust to different types of input, including
  // data that comes from a subset of a full mesh.

  // maps a vertex index to the corresponding vertex
  map<Index, VertexIter> indexToVertex;

  // Also store the vertex degree, i.e., the number of polygons that use each
  // vertex; this information will be used to check that the mesh is manifold.
  map<VertexIter, Size> vertexDegree;

  // First, we do some basic sanity checks on the input.
  for (PolygonListCIter p = polygons.begin(); p != polygons.end(); p++) {
    if (p->size() < 3) {
      // Refuse to build the mesh if any of the polygons have fewer than three
      // vertices.(Note that if we omit this check the code will still
      // constructsomething fairlymeaningful for 1- and 2-point polygons, but
      // enforcing this stricterrequirementon the input will help simplify code
      // further downstream, since it canbe certainit doesn't have to check for
      // these rather degenerate cases.)
      cerr << "Error converting polygons to halfedge mesh: each polygon must "
              "have at least three vertices." << endl;
      exit(1);
    }

    // We want to count the number of distinct vertex indices in this
    // polygon, to make sure it's the same as the number of vertices
    // in the polygon---if they disagree, then the polygon is not valid
    // (or at least, for simplicity we don't handle polygons of this type!).
    set<Index> polygonIndices;

    // loop over polygon vertices
    for (IndexListCIter i = p->begin(); i != p->end(); i++) {
      polygonIndices.insert(*i);

      // allocate one vertex for each new index we encounter
      if (indexToVertex.find(*i) == indexToVertex.end()) {
        VertexIter v = newVertex();
        v->halfedge() =
            halfedges.end();  // this vertex doesn't yet point to any halfedge
        indexToVertex[*i] = v;
        vertexDegree[v] = 1;  // we've now seen this vertex only once
      } else {
        // keep track of the number of times we've seen this vertex
        vertexDegree[indexToVertex[*i]]++;
      }

    }  // end loop over polygon vertices

    // check that all vertices of the current polygon are distinct
    Size degree = p->size();  // number of vertices in this polygon
    if (polygonIndices.size() < degree) {
      cerr << "Error converting polygons to halfedge mesh: one of the input "
              "polygons does not have distinct vertices!" << endl;
      cerr << "(vertex indices:";
      for (IndexListCIter i = p->begin(); i != p->end(); i++) {
        cerr << " " << *i;
      }
      cerr << ")" << endl;
      exit(1);
    }  // end check that polygon vertices are distinct

  }  // end basic sanity checks on input

  // The number of vertices in the mesh is the
  // number of unique indices seen in the input.
  Size nVertices = indexToVertex.size();

  // The number of faces is just the number of polygons in the input.
  Size nFaces = polygons.size();
  faces.resize(nFaces);  // allocate storage for faces in our new mesh

  // We will store a map from ordered pairs of vertex indices to
  // the corresponding halfedge object in our new (halfedge) mesh;
  // this map gets constructed during the next loop over polygons.
  map<IndexPair, HalfedgeIter> pairToHalfedge;

  // Next, we actually build the halfedge connectivity by again looping over
  // polygons
  PolygonListCIter p;
  FaceIter f;
  for (p = polygons.begin(), f = faces.begin(); p != polygons.end(); p++, f++) {
    vector<HalfedgeIter> faceHalfedges;  // cyclically ordered list of the half
                                         // edges of this face
    Size degree = p->size();             // number of vertices in this polygon

    // loop over the halfedges of this face (equivalently, the ordered pairs of
    // consecutive vertices)
    for (Index i = 0; i < degree; i++) {
      Index a = (*p)[i];                 // current index
      Index b = (*p)[(i + 1) % degree];  // next index, in cyclic order
      IndexPair ab(a, b);
      HalfedgeIter hab;

      // check if this halfedge already exists; if so, we have a problem!
      if (pairToHalfedge.find(ab) != pairToHalfedge.end()) {
        cerr << "Error converting polygons to halfedge mesh: found multiple "
                "oriented edges with indices (" << a << ", " << b << ")."
             << endl;
        cerr << "This means that either (i) more than two faces contain this "
                "edge (hence the surface is nonmanifold), or" << endl;
        cerr << "(ii) there are exactly two faces containing this edge, but "
                "they have the same orientation (hence the surface is" << endl;
        cerr << "not consistently oriented." << endl;
        exit(1);
      } else  // otherwise, the halfedge hasn't been allocated yet
      {
        // so, we point this vertex pair to a new halfedge
        hab = newHalfedge();
        pairToHalfedge[ab] = hab;

        // link the new halfedge to its face
        hab->face() = f;
        hab->face()->halfedge() = hab;

        // also link it to its starting vertex
        hab->vertex() = indexToVertex[a];
        hab->vertex()->halfedge() = hab;

        // keep a list of halfedges in this face, so that we can later
        // link them together in a loop (via their "next" pointers)
        faceHalfedges.push_back(hab);
      }

      // Also, check if the twin of this halfedge has already been constructed
      // (during construction of a different face).  If so, link the twins
      // together and allocate their shared halfedge.  By the end of this pass
      // over polygons, the only halfedges that will not have a twin will hence
      // be those that sit along the domain boundary.
      IndexPair ba(b, a);
      map<IndexPair, HalfedgeIter>::iterator iba = pairToHalfedge.find(ba);
      if (iba != pairToHalfedge.end()) {
        HalfedgeIter hba = iba->second;

        // link the twins
        hab->twin() = hba;
        hba->twin() = hab;

        // allocate and link their edge
        EdgeIter e = newEdge();
        hab->edge() = e;
        hba->edge() = e;
        e->halfedge() = hab;
      } else { // If we didn't find a twin...
        // ...mark this halfedge as being twinless by pointing
        // it to the end of the list of halfedges. If it remains
        // twinless by the end of the current loop over polygons,
        // it will be linked to a boundary face in the next pass.
        hab->twin() = halfedges.end();
      }

    }  // end loop over the current polygon's halfedges

    // Now that all the halfedges of this face have been allocated,
    // we can link them together via their "next" pointers.
    for (Index i = 0; i < degree; i++) {
      Index j =
          (i + 1) % degree;  // index of the next halfedge, in cyclic order
      faceHalfedges[i]->next() = faceHalfedges[j];
    }

  }  // done building basic halfedge connectivity

  // For each vertex on the boundary, advance its halfedge pointer to one that
  // is also on the boundary.
  for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) {
    // loop over halfedges around vertex
    HalfedgeIter h = v->halfedge();
    do {
      if (h->twin() == halfedges.end()) {
        v->halfedge() = h;
        break;
      }

      h = h->twin()->next();
    } while (h != v->halfedge());  // end loop over halfedges around vertex

  }  // done advancing halfedge pointers for boundary vertices

  // Next we construct new faces for each boundary component.
  for (HalfedgeIter h = halfedgesBegin(); h != halfedgesEnd();
       h++)  // loop over all halfedges
  {
    // Any halfedge that does not yet have a twin is on the boundary of the
    // domain. If we follow the boundary around long enough we will of course
    // eventually make a closed loop; we can represent this boundary loop by a
    // new face. To make clear the distinction between faces and boundary loops,
    // the boundary face will (i) have a flag indicating that it is a boundary
    // loop, and (ii) be stored in a list of boundaries, rather than the usual
    // list of faces.  The reason we need the both the flag *and* the separate
    // list is that faces are often accessed in two fundamentally different
    // ways: either by (i) local traversal of the neighborhood of some mesh
    // element using the halfedge structure, or (ii) global traversal of all
    // faces (or boundary loops).
    if (h->twin() == halfedges.end()) {
      FaceIter b = newBoundary();
      vector<HalfedgeIter> boundaryHalfedges;  // keep a list of halfedges along
                                               // the boundary, so we can link
                                               // them together

      // We now need to walk around the boundary, creating new
      // halfedges and edges along the boundary loop as we go.
      HalfedgeIter i = h;
      do {
        // create a twin, which becomes a halfedge of the boundary loop
        HalfedgeIter t = newHalfedge();
        boundaryHalfedges.push_back(
            t);  // keep a list of all boundary halfedges, in cyclic order
        i->twin() = t;
        t->twin() = i;
        t->face() = b;
        t->vertex() = i->next()->vertex();

        // create the shared edge
        EdgeIter e = newEdge();
        e->halfedge() = i;
        i->edge() = e;
        t->edge() = e;

        // Advance i to the next halfedge along the current boundary loop
        // by walking around its target vertex and stopping as soon as we
        // find a halfedge that does not yet have a twin defined.
        i = i->next();
        while (i != h &&  // we're done if we end up back at the beginning of
                          // the loop
               i->twin() != halfedges.end())  // otherwise, we're looking for
                                              // the next twinless halfedge
                                              // along the loop
        {
          i = i->twin();
          i = i->next();
        }
      } while (i != h);

      // The only pointers that still need to be set are the "next" pointers of
      // the twins; these we can set from the list of boundary halfedges, but we
      // must use the opposite order from the order in the list, since the
      // orientation of the boundary loop is opposite the orientation of the
      // halfedges "inside" the domain boundary.
      Size degree = boundaryHalfedges.size();
      for (Index p = 0; p < degree; p++) {
        Index q = (p - 1 + degree) % degree;
        boundaryHalfedges[p]->next() = boundaryHalfedges[q];
      }

    }  // end construction of one of the boundary loops

    // Note that even though we are looping over all halfedges, we will still
    // construct the appropriate number of boundary loops (and not, say, one
    // loop per boundary halfedge).  The reason is that as we continue to
    // iterate through halfedges, we check whether their twin has been assigned,
    // and since new twins may have been assigned earlier in this loop, we will
    // end up skipping many subsequent halfedges.

  }  // done adding "virtual" faces corresponding to boundary loops

  // To make later traversal of the mesh easier, we will now advance the
  // halfedge
  // associated with each vertex such that it refers to the *first* non-boundary
  // halfedge, rather than the last one.
  for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) {
    v->halfedge() = v->halfedge()->twin()->next();
  }

  // Finally, we check that all vertices are manifold.
  for (VertexIter v = vertices.begin(); v != vertices.end(); v++) {
    // First check that this vertex is not a "floating" vertex;
    // if it is then we do not have a valid 2-manifold surface.
    if (v->halfedge() == halfedges.end()) {
      cerr << "Error converting polygons to halfedge mesh: some vertices are "
              "not referenced by any polygon." << endl;
      exit(1);
    }

    // Next, check that the number of halfedges emanating from this vertex in
    // our half edge data structure equals the number of polygons containing
    // this vertex, which we counted during our first pass over the mesh.  If
    // not, then our vertex is not a "fan" of polygons, but instead has some
    // other (nonmanifold) structure.
    Size count = 0;
    HalfedgeIter h = v->halfedge();
    do {
      if (!h->face()->isBoundary()) {
        count++;
      }
      h = h->twin()->next();
    } while (h != v->halfedge());

    if (count != vertexDegree[v]) {
      cerr << "Error converting polygons to halfedge mesh: at least one of the "
              "vertices is nonmanifold." << endl;
      exit(1);
    }
  }  // end loop over vertices

  // Now that we have the connectivity, we copy the list of vertex
  // positions into member variables of the individual vertices.
  if (vertexPositions.size() != vertices.size()) {
    cerr << "Error converting polygons to halfedge mesh: number of vertex "
            "positions is different from the number of distinct vertices!"
         << endl;
    cerr << "(number of positions in input: " << vertexPositions.size() << ")"
         << endl;
    cerr << "(  number of vertices in mesh: " << vertices.size() << ")" << endl;
    exit(1);
  }
  // Since an STL map internally sorts its keys, we can iterate over the map
  // from vertex indices to vertex iterators to visit our (input) vertices in
  // lexicographic order
  int i = 0;
  for (map<Index, VertexIter>::const_iterator e = indexToVertex.begin();
       e != indexToVertex.end(); e++) {
    // grab a pointer to the vertex associated with the current key (i.e., the
    // current index)
    VertexIter v = e->second;

    // set the att of this vertex to the corresponding
    // position in the input
    v->position = vertexPositions[i];
    i++;
  }

  // compute initial normals
  for (VertexIter v = verticesBegin(); v != verticesEnd(); v++) {
    v->computeNormal();
  }

}  // end HalfedgeMesh::build()