半边数据结构

核心数据结构采用半边数据结构实现,具体的实现功能是:

通过绘制一个基本的面,然后通过该面通过指定的向量和距离就可以扫成为一个体。

具体的核心代码如下:

CSolid* CEulerDoc::mvfs(GLdouble *point)
{
 CSolid *newSolid;
 CFace *newFace;
 CLoop *newLoop;
 CVertex *newVert;
 newSolid = new CSolid;
 newFace = new CFace;
 newLoop = new CLoop;
 newVert = new CVertex;

 // Set the coordinate of the new vertex
 newVert->SetCoord(point);

 // Add the new face to the new solid
 newSolid->AddFace(newFace);

 // Add the new vertex to the new solid
 newSolid->AddVertex(newVert);

 // Add the new loop to the new face
 newFace->AddLoop(newLoop);
 
 return newSolid;
}

CHalfEdge* CEulerDoc::mev(GLdouble *point1, GLdouble *point2, CLoop* lp)
{
 CSolid  *pSolid = lp->host_f->host_s;
 CVertex  *v1, *newVert;
 CEdge  *newEdge;
 CHalfEdge *he1, *he2;
 newVert = new CVertex;
 newEdge = new CEdge;
 he1 = new CHalfEdge;
 he2 = new CHalfEdge;

 // Find the start vertex of the edge
 v1 = pSolid->FindVertex(point1);
 if(!v1)
 {
  AfxMessageBox("Can't find the point1!");
  return NULL;
 }

 // Set the coordinate of the new vertex
 newVert->SetCoord(point2);

 // Set v1 as the start vertex of halfedge1
 he1->SetVertex(v1);

 // Set v2 as the start vertex of halfedge2
 he2->SetVertex(newVert);

 // Add two new halfedges to the loop
 lp->AddHalfEdge(he1, he2);

 // Set the new edge to new halfedges
 he1->edge = he2->edge = newEdge;
 newEdge->he1 = he1;
 newEdge->he2 = he2;

 // Add the new edge to the solid
 pSolid->AddEdge(newEdge);

 // Add the new vertex to the solid
 pSolid->AddVertex(newVert);

 return he1;
}

CLoop* CEulerDoc::mef(GLdouble *point1, GLdouble *point2, CLoop* lp)
{
 CSolid  *pSolid = lp->host_f->host_s;
 CVertex  *v1, *v2;
 // Find the two given vertex
 v1 = pSolid->FindVertex(point1);
 if(!v1)
 {
  AfxMessageBox("Can't find the point1!");
  return NULL;
 }
 v2 = pSolid->FindVertex(point2);
 if(!v2)
 {
  AfxMessageBox("Can't find the point2!");
  return NULL;
 }
 // two vertex must in the same loop
 if(!lp->IsVertexIn(v1) && !lp->IsVertexIn(v2))
 {
  AfxMessageBox("该两点不位于同一个loop中");
  return NULL;
 }

 CFace *newFace;
 CLoop *newLoop;
 CEdge *newEdge;
 CHalfEdge *he1, *he2, *temphe1, *temphe2;
 newFace = new CFace;
 newLoop = new CLoop;
 newEdge = new CEdge;
 he1 = new CHalfEdge;
 he2 = new CHalfEdge;

 // Find two halfedges start with two vertexs
 temphe1 = lp->FindHostHalfEdge(v1);
 temphe2 = lp->FindHostHalfEdge(v2);

 // Change halfedges' host loop to new loop
 temphe1->prev->next = NULL;
 newLoop->AddHalfEdge(temphe1, NULL);
 while(temphe1 != temphe2)
  temphe1 = temphe1->next;
 temphe1->prev->next = he2;
 he2->prev = temphe1->prev;
 he2->next = newLoop->GetHalfEdgeHead();
 newLoop->GetHalfEdgeHead()->prev = he2;
 temphe1->prev = NULL;

 // Add halfedge start with vertex one to the old loop % close this loop
 lp->AddHalfEdge(he1, NULL);
 he1->next = temphe2;
 temphe2->prev = he1;

 // Set two halfedges' start vertex and adjacent
 he1->SetVertex(v1);
 he2->SetVertex(v2);
 he1->adj = he2;
 he2->adj = he1;

 // Set the new edge and add to the solid
 newEdge->he1 = he1;
 newEdge->he2 = he2;
 pSolid->AddEdge(newEdge);

 // Add new face to the solid
 pSolid->AddFace(newFace);

 // Add new loop to the new face
 newFace->AddLoop(newLoop);

 return newLoop;
}


CLoop* CEulerDoc::kemr(GLdouble *point1, GLdouble *point2, CLoop* lp)
{
 CSolid  *pSolid = lp->host_f->host_s;
 CVertex  *v1, *v2;
 // Find the two given vertex
 v1 = pSolid->FindVertex(point1);
 if(!v1)
 {
  AfxMessageBox("Can't find the point1!");
  return NULL;
 }
 v2 = pSolid->FindVertex(point2);
 if(!v2)
 {
  AfxMessageBox("Can't find the point2!");
  return NULL;
 }
 // two vertex must in the same loop
 if(!lp->IsVertexIn(v1) && !lp->IsVertexIn(v2))
  return NULL;

 CLoop  *newLoop;
 CHalfEdge *he1, *he2;
 CEdge  *edge;
 newLoop = new CLoop;

 // Find two halfedges start with two vertexs
 he1 = lp->GetHalfEdgeHead();
 while(he1)
 {
  if(he1->GetVertex() == v1 && he1->next->GetVertex() == v2)
   break;
  he1 = he1->next;
 }
 he2 = he1->adj;

 // Make a newloop and delete two halfedges
 newLoop->AddHalfEdge(he1->next, NULL);
 he2->prev->next = he1->next;
 he1->next->prev = he2->prev;
 he1->prev->next = he2->next;
 he2->next->prev = he1->prev;
 he1->next = he1->prev = he2->next = he2->prev = NULL;
 delete he1;
 delete he2;

 // Find the edge and delete it
 edge = pSolid->GetEdgeHead();
 while(edge)
 {
  if(edge->he1 == he1)
   break;
  edge = edge->next;
 }
 edge->prev->next = edge->next;
 edge->next->prev = edge->prev;
 edge->next = edge->prev = NULL;

 // Add new loop to the face
 lp->host_f->AddLoop(newLoop);

 return newLoop;
}

void CEulerDoc::kfmrh(CLoop* outlp, CLoop* lp)
{
 if(!outlp || !lp)
 {
  AfxMessageBox("The loop is NULL!");
  return;
 }

 CSolid  *pSolid = lp->host_f->host_s;

 // Add the loop to the face
 outlp->host_f->AddLoop(lp);

 // Get the face need to be killed
 CFace* pFace = pSolid->GetFaceEnd();

 // Delete it
 pFace->prev->next = NULL;

 delete pFace;
}

void CEulerDoc::sweep(CFace* pFace, GLdouble dx, GLdouble dy, GLdouble dz)
{
 CFace  *pEnd;
 CHalfEdge *pHe, *pHead;
 CLoop  *pLoop, *newLoop, *pOutLoop;
 GLdouble *pPoint;
 GLdouble point1[3], point2[3], first[3], last[3];
 BOOL  bOut = TRUE; // Show that if is the outloop of the top face

 // Remember the last inside loop's face 
 pEnd = pFace->host_s->GetFaceEnd();
 // Start with the second face, because the first face is for buttom
 pFace = pFace->next;
 while(pFace)
 {
  // Get the first point of the loop
  newLoop = pLoop = pFace->GetLoopHead();
  pHe = pHead = pLoop->GetHalfEdgeHead();
  pPoint = pHe->GetVertex()->vcoord;
  point1[0] = pPoint[0];
  point1[1] = pPoint[1];
  point1[2] = pPoint[2];
  // first[] is used for close the top face
  // last[] is used for side face
  first[0] = last[0] = point2[0] = point1[0] + dx;
  first[1] = last[1] = point2[1] = point1[1] + dy;
  first[2] = last[2] = point2[2] = point1[2] + dz;
  // Make the new edge
  mev(point1, point2, pLoop);
  // Goto next halfedge
  pHe = pHe->next;
  while(pHe->GetVertex() != pHead->GetVertex())
  {
   // Get the point
   pPoint = pHe->GetVertex()->vcoord;
   point1[0] = pPoint[0];
   point1[1] = pPoint[1];
   point1[2] = pPoint[2];
   point2[0] = point1[0] + dx;
   point2[1] = point1[1] + dy;
   point2[2] = point1[2] + dz;
   // Make the new edge
   mev(point1, point2, newLoop);
   // Make a new side face
   newLoop = mef(point2, last, newLoop);
   // Remember the lastest point
   last[0] = point2[0];
   last[1] = point2[1];
   last[2] = point2[2];
   pHe = pHe->next;
  }
  // Close the top face
  newLoop = mef(first, last, newLoop);

  if(bOut)
  {
   pOutLoop = newLoop;
   bOut = FALSE;
  }
  else
   kfmrh(pOutLoop, newLoop);

  if(pFace == pEnd)
   break;

  pFace = pFace->next;
 }
}

CSolid* CEulerDoc::MakeSolid(GLdouble point[][3], GLint* pointnum, GLint loopnum, GLdouble* vector, GLdouble len)
{
 CSolid *pSolid, *pTemp;
 CLoop *pLoop, *pHead;
 int  i, j, pos;

 // Create the solid
 pSolid = mvfs(point[1]);
 pHead = pLoop = pSolid->GetFaceHead()->GetLoopHead();

 // Create the out loop
 for(i = 1;i < pointnum[1]-1;i ++)
 {
  mev(point[i], point[i+1], pLoop);
 }
 mef(point[i], point[1], pLoop);
 pos = i+1;

 // Create the inside loops
 for(i = 2;i < loopnum; i ++)
 {
  mev(point[1], point[pos+1], pHead);
  for(j = 1;j < pointnum[i]-1;j ++)
  {
   mev(point[pos+j], point[pos+j+1], pHead);
  }
  mef(point[pos+j], point[pos+1], pHead);
  kemr(point[1], point[pos+1], pHead);
  pos = pos+j+1;
 }

 sweep(pSolid->GetFaceHead(), vector[0] * len, vector[1] * len, vector[2] * len);

 // Insert the new solid
 if(!solid)
  solid = pSolid;
 else
 {
  pTemp = solid;
  while(pTemp->next)
   pTemp = pTemp->next;
  pTemp->next = pSolid;
 }

 return pSolid;
}


void CEulerView::RenderScene(void)
{
 CEulerDoc *pDoc = GetDocument();
 CSolid  *pSolid;
 CFace  *pFace;
 CLoop  *pLoop;
 CHalfEdge *pHalfEdge, *pHeHead; 
 GLint  i, j, pos = 0;
 GLfloat  draw_ambient[] = { 1.0, 1.0, 1.0},
    mat_ambient[] = { 0.5, 0.5, 0.5 }, 
    mat_specular[] = { 1.0, 1.0, 1.0, 1.0 },
    shininess[] = { 50.0 };
 GLfloat  position1[] = { 10.0, 10.0, 10.0, 0.0 };

 glLoadIdentity(); 
 glTranslatef(m_xPos, m_yPos, m_zPos);
 glRotatef(m_xAngle, 1.0f,0.0f,0.0f);
 glRotatef(m_yAngle, 0.0f,1.0f,0.0f);

 if(m_bCoord)
  RenderCoordinate(1);

 glLightfv(GL_LIGHT0, GL_POSITION, position1);

 //
 // Draw
 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, draw_ambient);
 for(i = 1; i <= m_iLoopNum ;i ++)
 {
  pos += m_iLoopPointNum[i-1];
  glBegin(GL_LINE_STRIP);
  for(j = 1;j <= m_iLoopPointNum[i]; j++)
   glVertex3d(m_dPoint[pos + j][0], m_dPoint[pos + j][1], m_dPoint[pos + j][2]);
  glEnd();
 }
 //
 pSolid = pDoc->solid;

 if(m_bWire)
 {
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, draw_ambient);
  glLineWidth(2.0);
  glBegin(GL_LINES);
  while(pSolid)
  {
   pFace = pSolid->GetFaceHead();
   while(pFace)
   {
    pLoop = pFace->GetLoopHead();
    while(pLoop)
    {
     pHalfEdge = pHeHead = pLoop->GetHalfEdgeHead();
     while(pHalfEdge)
     {
      glVertex3dv(pHalfEdge->GetVertex()->vcoord);
      glVertex3dv(pHalfEdge->next->GetVertex()->vcoord);
      pHalfEdge = pHalfEdge->next;
      if(pHalfEdge == pHeHead)
       break;
     }
     pLoop = pLoop->next;
    }
    pFace = pFace->next;   
   }
   pSolid = pSolid->next;
  }
  glEnd();
 }
 else
 {
  glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, mat_ambient);
  glMaterialfv(GL_FRONT, GL_SPECULAR, mat_specular);
  glMaterialfv(GL_FRONT, GL_SHININESS, shininess);
  glEnable(GL_NORMALIZE);
  while(pSolid)
  {
   pFace = pSolid->GetFaceHead();
   while(pFace)
   {
    gluTessBeginPolygon(tessobj, NULL);
    glNormal3dv(pFace->feq);
    pLoop = pFace->GetLoopHead();
    while(pLoop)
    {
     gluTessBeginContour(tessobj);
     pHalfEdge = pHeHead = pLoop->GetHalfEdgeHead();
     while(pHalfEdge)
     {
      gluTessVertex(tessobj, pHalfEdge->GetVertex()->vcoord, pHalfEdge->GetVertex()->vcoord);
      pHalfEdge = pHalfEdge->next;
      if(pHalfEdge == pHeHead)
       break;
     }
     gluTessEndContour(tessobj);
     pLoop = pLoop->next;
    }
    gluTessEndPolygon(tessobj);
    pFace = pFace->next;   
   }
   pSolid = pSolid->next;
  }
 }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值