Exemplo n.º 1
0
bool ON_Mesh::CollapseEdge( int topei )
{
  ON_Mesh& mesh = *this;

  ON__MESHEDGE me;
  memset(&me,0,sizeof(me));
  const ON_MeshTopology& top = mesh.Topology();  
  const int F_count = mesh.m_F.Count();
  const int V_count = mesh.m_V.Count();
  const int topv_count = top.m_topv.Count();
  //const int tope_count = top.m_tope.Count();

  if ( topei < 0 || topei >= top.m_tope.Count() )
  {
    return false;
  }

  const ON_MeshTopologyEdge& tope = top.m_tope[topei];

  if (    tope.m_topf_count < 1 
       || tope.m_topvi[0] == tope.m_topvi[1] 
       || tope.m_topvi[0] < 0
       || tope.m_topvi[1] < 0
       || tope.m_topvi[0] >= topv_count
       || tope.m_topvi[1] >= topv_count )
  {
    return false;
  }

  const ON_MeshTopologyVertex& topv0 = top.m_topv[tope.m_topvi[0]];
  const ON_MeshTopologyVertex& topv1 = top.m_topv[tope.m_topvi[1]];
  if ( topv0.m_v_count < 1 || topv1.m_v_count < 1 )
  {
    return false;
  }
  if ( topv0.m_vi[0] < 0 || topv0.m_vi[0] >= V_count )
  {
    return false;
  }
  if ( topv1.m_vi[0] < 0 || topv1.m_vi[0] >= V_count )
  {
    return false;
  }
  
  // create a ON__MESHEDGE for each face (usually one or two) that uses the edge
  ON__MESHEDGE* me_list = (ON__MESHEDGE*)alloca(tope.m_topf_count*sizeof(me_list[0]));
  int me_list_count = 0;
  int efi;
  for ( efi = 0; efi < tope.m_topf_count; efi++ )
  {
    int fi = tope.m_topfi[efi];
    if ( fi < 0 || fi >= F_count )
      continue;
    const ON_MeshFace& f = mesh.m_F[fi];
    if ( !f.IsValid(V_count) )
      continue;
    me.vi1 = f.vi[3];
    me.topvi1 = top.m_topv_map[me.vi1];
    int fvi;
    for ( fvi = 0; fvi < 4; fvi++ )
    {
      me.vi0 = me.vi1;
      me.topvi0 = me.topvi1;
      me.vi1 = f.vi[fvi];
      me.topvi1 = top.m_topv_map[me.vi1];
      if ( me.vi0 != me.vi1 )
      {
        if (    (me.topvi0 == tope.m_topvi[0] && me.topvi1 == tope.m_topvi[1])
             || (me.topvi0 == tope.m_topvi[1] && me.topvi1 == tope.m_topvi[0]) )
        {
          if ( me.vi0 > me.vi1 )
          {
            int i = me.vi0; me.vi0 = me.vi1; me.vi1 = i;
            i = me.topvi0; me.topvi0 = me.topvi1; me.topvi1 = i;
          }
          me_list[me_list_count++] = me;
          break;
        }
      }
    }
  }

  if (me_list_count<1)
  {
    return false;
  }

  // Sort me_list[] so edges using same vertices are adjacent
  // to each other in the list.  This is needed so that non-manifold
  // crease edges will be properly collapsed.
  ON_qsort(me_list,me_list_count,sizeof(me_list[0]),(QSORTCMPFUNC)CompareMESHEDGE);

  // create new vertex or vertices that edge will be
  // collapsed to.
  mesh.m_C.Destroy();
  mesh.m_K.Destroy();
  
  int mei;
  bool bHasVertexNormals = mesh.HasVertexNormals();
  bool bHasTextureCoordinates = mesh.HasTextureCoordinates();
  bool bHasFaceNormals = mesh.HasFaceNormals();
  if ( topv0.m_v_count == 1 || topv1.m_v_count == 1 )
  {
    // a single new vertex
    ON_Line Vline(ON_origin,ON_origin);
    ON_Line Tline(ON_origin,ON_origin);
    ON_3dVector N0(0,0,0);
    ON_3dVector N1(0,0,0);
    ON_3dPoint P;
    int vi, tvi, cnt;

    int newvi = topv0.m_vi[0];

    cnt = 0;
    for ( tvi = 0; tvi < topv0.m_v_count; tvi++ )
    {
      vi = topv0.m_vi[tvi];
      if ( vi < 0 || vi > V_count )
        continue;
      if ( vi < newvi )
        newvi = vi;
      cnt++;
      P = mesh.m_V[vi];
      Vline.from += P;
      if ( bHasVertexNormals )
      {
        N0 += ON_3dVector(mesh.m_N[vi]);
      }
      if ( bHasTextureCoordinates )
      {
        P = mesh.m_T[vi];
        Tline.from += P;
      }
    }

    if (cnt > 1)
    {
      double s = 1.0/((double)cnt);
      Vline.from.x *= s;
      Vline.from.y *= s;
      Vline.from.z *= s;
      Tline.from.x *= s;
      Tline.from.y *= s;
      Tline.from.z *= s;
      N0 = s*N0;
    }

    cnt = 0;
    for ( tvi = 0; tvi < topv1.m_v_count; tvi++ )
    {
      vi = topv1.m_vi[tvi];
      if ( vi < 0 || vi > V_count )
        continue;
      if ( vi < newvi )
        newvi = vi;
      cnt++;
      P = mesh.m_V[vi];
      Vline.to += P;
      if ( bHasVertexNormals )
      {
        N1 += ON_3dVector(mesh.m_N[vi]);
      }
      if ( bHasTextureCoordinates )
      {
        P = mesh.m_T[vi];
        Tline.to += P;
      }
    }

    if (cnt > 1)
    {
      double s = 1.0/((double)cnt);
      Vline.to.x *= s;
      Vline.to.y *= s;
      Vline.to.z *= s;
      Tline.to.x *= s;
      Tline.to.y *= s;
      Tline.to.z *= s;
      N1 = s*N1;
    }

    ON_3fPoint newV(Vline.PointAt(0.5));
    ON_3fVector newN;
    ON_2fPoint newT;
    if ( bHasVertexNormals )
    {
      N0.Unitize();
      N1.Unitize();
      ON_3dVector N = N0+N1;
      if ( !N.Unitize() )
      {
        N = (topv0.m_v_count == 1) ? mesh.m_N[topv0.m_vi[0]] :mesh.m_N[topv1.m_vi[0]];
      }
      newN = N;
    }
    if ( bHasTextureCoordinates )
    {
      newT = Tline.PointAt(0.5);
    }
    for ( mei = 0; mei < me_list_count; mei++ )
    {
      me_list[mei].newvi = newvi;
      me_list[mei].newV = newV;
      me_list[mei].newN = newN;
      me_list[mei].newT = newT;
    }
  }
  else
  {
    // collapsing a "crease" edge - attempt to preserve
    // the crease.
    memset(&me,0,sizeof(me));
    me.vi0 = -1;
    me.vi1 = -1;
    for ( mei = 0; mei < me_list_count; mei++ )
    {
      if ( 0 == mei && CompareMESHEDGE(&me,me_list+mei) )
      {
        // cook up new vertex
        me_list[mei].newvi = mesh.m_V.Count();
        me = me_list[mei];
        ON_Line line;
        line.from = mesh.m_V[me.vi0];
        line.to   = mesh.m_V[me.vi1];
        me.newV = line.PointAt(0.5);
        if ( bHasVertexNormals )
        {
          ON_3dVector N0(mesh.m_N[me.vi0]);
          ON_3dVector N1(mesh.m_N[me.vi1]);
          ON_3dVector N = N0 + N1;
          if ( !N.Unitize() )
            N = N0;
          me.newN = N;
        }
        if ( bHasTextureCoordinates )
        {
          line.from = mesh.m_T[me.vi0];
          line.to   = mesh.m_T[me.vi1];
          me.newT = line.PointAt(0.5);
        }
        me.newvi = (me.vi0 < me.vi1) ? me.vi0 : me.vi1;
      }
      else
      {
        me_list[mei].newvi = me.newvi;
        me_list[mei].newV = me.newV;
        me_list[mei].newN = me.newN;
        me_list[mei].newT = me.newT;
      }
    }
  }

  // We are done averaging old mesh values.
  // Change values in mesh m_V[], m_N[] and m_T[] arrays.
  for ( mei = 0; mei < me_list_count; mei++ )
  {
    mesh.m_V[me_list[mei].vi0] = me_list[mei].newV;
    mesh.m_V[me_list[mei].vi1] = me_list[mei].newV;
    if ( bHasVertexNormals )
    {
      mesh.m_N[me_list[mei].vi0] = me_list[mei].newN;
      mesh.m_N[me_list[mei].vi1] = me_list[mei].newN;
    }
    if ( bHasTextureCoordinates )
    {
      mesh.m_T[me_list[mei].vi0] = me_list[mei].newT;
      mesh.m_T[me_list[mei].vi1] = me_list[mei].newT;
    }
  }

  // make a map of old to new
  int old2new_map_count = 0;
  ON__NEWVI* old2new_map = (ON__NEWVI*)alloca(2*me_list_count*sizeof(old2new_map[0]));

  for ( mei = 0; mei < me_list_count; mei++ )
  {
    old2new_map[old2new_map_count].oldvi = me_list[mei].vi0;
    old2new_map[old2new_map_count].newvi = me_list[mei].newvi;
    old2new_map_count++;
    old2new_map[old2new_map_count].oldvi = me_list[mei].vi1;
    old2new_map[old2new_map_count].newvi = me_list[mei].newvi;
    old2new_map_count++;
  }

  // sort old2new_map[] so we can use a fast bsearch() call
  // to update faces.
  ON_qsort(old2new_map,old2new_map_count,sizeof(old2new_map[0]),(QSORTCMPFUNC)CompareNEWVI);

  // count faces that use the vertices that are being changed
  int bad_fi_count = 0;
  int topv_end, vei, fi, fvi23, fvi;
  ON__NEWVI nvi;

  for ( topv_end = 0; topv_end < 2; topv_end++ )
  {
    const ON_MeshTopologyVertex& topv = (topv_end) ? topv1 : topv0;
    for ( vei = 0; vei < topv.m_tope_count; vei++ )
    {
      topei = topv.m_topei[vei];
      if ( topei < 0 && topei >= top.m_tope.Count() )
        continue;
      bad_fi_count += top.m_tope[topei].m_topf_count;
    }
  }
  int* bad_fi = (int*)alloca(bad_fi_count*sizeof(*bad_fi));
  bad_fi_count = 0;

  // Go through all the faces that use the vertices at the
  // ends of the edge and update the vi[] values to use the
  // new vertices.
  for ( topv_end = 0; topv_end < 2; topv_end++ )
  {
    const ON_MeshTopologyVertex& topv = (topv_end) ? topv1 : topv0;
    for ( vei = 0; vei < topv.m_tope_count; vei++ )
    {
      topei = topv.m_topei[vei];
      if ( topei < 0 && topei >= top.m_tope.Count() )
        continue;
      const ON_MeshTopologyEdge& e = top.m_tope[topei];
      for ( efi = 0; efi < e.m_topf_count; efi++ )
      {
        fi = e.m_topfi[efi];
        if ( fi < 0 || fi >= F_count )
          continue;
        bool bChangedFace = false;
        ON_MeshFace& f = mesh.m_F[fi];
        for ( fvi = 0; fvi < 4; fvi++ )
        {
          nvi.oldvi = f.vi[fvi];
          ON__NEWVI* p = (ON__NEWVI*)bsearch(&nvi,old2new_map,old2new_map_count,sizeof(old2new_map[0]),(QSORTCMPFUNC)CompareNEWVI);
          if ( 0 != p && p->oldvi != p->newvi)
          {
            f.vi[fvi] = p->newvi;
            bChangedFace = true;
          }
        }
        if ( bChangedFace )
        {
          if ( !f.IsValid(V_count) )
          {
            if ( f.vi[3] == f.vi[0] )
            {
              f.vi[0] = f.vi[1];
              f.vi[1] = f.vi[2];
              f.vi[2] = f.vi[3];
            }
            else if ( f.vi[0] == f.vi[1] )
            {
              fvi23 = f.vi[0];
              f.vi[0] = f.vi[2];
              f.vi[1] = f.vi[3];
              f.vi[2] = fvi23;
              f.vi[3] = fvi23;
            }
            else if ( f.vi[1] == f.vi[2] )
            {
              fvi23 = f.vi[1];
              f.vi[1] = f.vi[0];
              f.vi[0] = f.vi[3];
              f.vi[2] = fvi23;
              f.vi[3] = fvi23;
            }
            if ( f.vi[0] == f.vi[1] || f.vi[1] == f.vi[2] || f.vi[2] == f.vi[0] || f.vi[2] != f.vi[3] )
            {
              bad_fi[bad_fi_count++] = fi;
            }
          }
          if ( bHasFaceNormals )
          {
            // invalid faces are removed below
            ON_3fVector a, b, n;
            a = mesh.m_V[f.vi[2]] - mesh.m_V[f.vi[0]];
            b = mesh.m_V[f.vi[3]] - mesh.m_V[f.vi[1]];
            n = ON_CrossProduct( a, b );
            n.Unitize();
            mesh.m_FN[fi] = n;
          }
        }
      }
    }
  }

  if ( bad_fi_count > 0 )
  {
    // remove collapsed faces
    ON_qsort(bad_fi,bad_fi_count,sizeof(bad_fi[0]),CompareInt);
    int bfi = 1;
    int dest_fi = bad_fi[0];
    for ( fi = dest_fi+1; fi < F_count && bfi < bad_fi_count; fi++ )
    {
      if ( fi == bad_fi[bfi] )
      {
        bfi++;
      }
      else
      {
        mesh.m_F[dest_fi++] = mesh.m_F[fi];
      }
    }
    while (fi<F_count)
    {
      mesh.m_F[dest_fi++] = mesh.m_F[fi++];
    }
    mesh.m_F.SetCount(dest_fi);

    if ( bHasFaceNormals )
    {
      bfi = 1;
      dest_fi = bad_fi[0];
      for ( fi = dest_fi+1; fi < F_count && bfi < bad_fi_count; fi++ )
      {
        if ( fi == bad_fi[bfi] )
        {
          bfi++;
        }
        else
        {
          mesh.m_FN[dest_fi++] = mesh.m_FN[fi];
        }
      }
      while (fi<F_count)
      {
        mesh.m_FN[dest_fi++] = mesh.m_FN[fi++];
      }
      mesh.m_FN.SetCount(dest_fi);
    }
  }

  mesh.Compact();
  mesh.DestroyTopology();
  mesh.DestroyPartition();

  return true;
}
Exemplo n.º 2
0
// -----------------------------------------------
// ProgressBar
// -----------------------------------------------
void * ehzProgressBar(struct OBJ *objCalled,EN_MESSAGE cmd,LONG info,void *ptr)
{
	 EH_DISPEXT *DExt=ptr;
//	 SINT *lpi;
	 SINT iLx,iLy;
	 SINT iRiemp;
	 SINT iPos;
	 SINT iBar;
	 SINT iDiv;
	 SINT a;
	 SINT ThePoint;
	 SINT iMyShadow;
	 SINT iEnd;
	 EH_PROGRESS_BAR * psBar;

	 //lpi=(SINT *) objCalled->text;
	 psBar=(EH_PROGRESS_BAR *) objCalled->pOther;

	 switch(cmd) {
		case WS_INF: return NULL;

		case WS_CREATE:
			psBar=objCalled->pOther=ehAllocZero(sizeof(EH_PROGRESS_BAR));
			psBar->iMax=100;
			psBar->cBar=sys.Color3DHighLight;
			if (!strcmp(objCalled->text,"WIN")) {
				objCalled->hWnd=CreateWindowEx(0,
								   PROGRESS_CLASS, 
								   NULL,
								   WS_CHILD|WS_VISIBLE,
								   0,0,
								   10,10,//-(MENU_HEIGHT),
								   WindowNow(),//sGMSetup.hwAnagTB,//sGMSetup.hwAnag,
								   (HMENU) NULL,
								   sys.EhWinInstance,
								   NULL);
				SendMessage(objCalled->hWnd, PBM_SETRANGE,0,MAKELPARAM(0,100));
				SendMessage(objCalled->hWnd, PBM_SETSTEP, MAKEWPARAM(1, 0), 0);
			} else objCalled->hWnd=NULL;

			break;

		case WS_DESTROY:
			ehFreePtr(&objCalled->pOther);
			if (objCalled->hWnd) DestroyWindow(objCalled->hWnd);
			break;

		case WS_DO: // Spostamento / Ridimensionamento
			MoveWindow(objCalled->hWnd,DExt->px,DExt->py,DExt->lx,DExt->ly,TRUE);
			break;

		case WS_SETFLAG:

			if (!strcmp(ptr,"MAX")) // Setta lo stile della finestra
			{
				if (info<1) info=1;
				//*psBar->iMax=info;
				psBar->iMax=info;
			}
			
			if (!strcmp(ptr,"COL")) // Setta lo stile della finestra
			{
//				*(lpi+3)=info;
				psBar->cBar=info;
				obj_vedisolo(objCalled->nome);
			}
			
			if (!strcmp(ptr,"CNT")) // Setta lo stile della finestra
			{
				//*lpi=info;
				psBar->iCount=info;

				// Calcolo percentuale
				iRiemp=psBar->iCount; if (iRiemp>(psBar->iMax)) iRiemp=psBar->iMax; 
				iPos=0;
				if (psBar->iMax) iPos=100*iRiemp/psBar->iMax;// calcolo percntuale di riempimento
			
				// Se la percentuale è cambiata ristampo il tutto
				if (psBar->iPerc!=iPos) {
					psBar->iPerc=iPos; 
					if (objCalled->hWnd)
						SendMessage(objCalled->hWnd, PBM_SETPOS, psBar->iPerc, 0); 
						else
						obj_vedisolo(objCalled->nome);
				}

				//if (*lpi!=info) {*lpi=info; obj_vedisolo(objCalled->nome);}
			}

			break;


		case WS_DISPLAY: 
			if (objCalled->hWnd) {InvalidateRect(objCalled->hWnd,NULL,TRUE); break;}

			iLx=DExt->px+DExt->lx-1; iLy=DExt->py+DExt->ly-1;
			iRiemp=psBar->iCount;  if (iRiemp>(psBar->iMax)) iRiemp=psBar->iMax;
			iPos=100*iRiemp/psBar->iMax;// calcolo percentuale di riempimento
			iBar=(DExt->lx-3)*iRiemp/psBar->iMax;// Calcolo dimensione barra pieno
			iDiv=(DExt->px+iBar);

 			//Tbox(DExt->px,DExt->py,iLx,iLy,0,SET);
			box3d(DExt->px,DExt->py,iLx,iLy,1);
//			dispf(iText,DExt->py,15,-1,ON,"SMALL F",3,szServ);
			ThePoint=(DExt->ly/3);
			iMyShadow=ColorLum(sys.Color3DShadow,-30);
			if (iBar>0) 
			{
				 Tline(DExt->px+1,DExt->py+1,iDiv,DExt->py+1,iMyShadow,SET);
				 for (a=2;a<DExt->ly-2;a++) {

					 LONG Col;
					 if (a<ThePoint) 
						Col=ColorFusion(sys.Color3DShadow,psBar->cBar,(100/ThePoint*a));
						else
						Col=ColorFusion(sys.Color3DShadow,psBar->cBar,(100/(DExt->ly-ThePoint)*(DExt->ly-a)));
//					 iEnd=iDiv+a-2; if (iEnd>iLx-1) iEnd=iLx-1;
					 iEnd=iDiv-2; if (iEnd>iLx-1) iEnd=iLx-1;
					 Tline(DExt->px+2,DExt->py+a,iEnd,DExt->py+a,Col,SET);
				 }
				 Tline(DExt->px+1,iLy-1,iEnd,iLy-1,ColorLum(sys.Color3DShadow,-40),SET);
			}

			ThePoint=DExt->ly-ThePoint;
			if (iBar<(DExt->lx-2)) 
			{//Tboxp(iDiv+1,DExt->py+2,iDiv+1,iLy-2,0,SET);
			 //Tboxp(iDiv+2,DExt->py+1,iLx-1,iLy-1,ColorLum(sys.Color3DShadow,-10),SET);
			 for (a=1;a<DExt->ly-1;a++)
			 {
			  LONG Col;
			  if (a<ThePoint) Col=ColorFusion(iMyShadow,sys.Color3DLight,(100/ThePoint*a));
							  else
							  Col=ColorFusion(iMyShadow,sys.Color3DLight,(100/(DExt->ly-ThePoint)*(DExt->ly-a)));
//				if (iBar>0) {iEnd=iDiv+a; if (iEnd>iLx-1) iEnd=iLx-1;} else iEnd=iDiv+1;
				if (iBar>0) {iEnd=iDiv-1; if (iEnd>iLx-1) iEnd=iLx-1;} else iEnd=iDiv+1;
				Tline(iEnd,DExt->py+a,iLx-1,DExt->py+a,Col,SET);
			 }
			}

			//sys.fFontBold=FALSE;
			break;
	}
	return NULL;
}