简体   繁体   中英

Remove Duplicates in Vector?

I have a vertex defined like this:

struct VERTEX
{
  XMFLOAT3 Pos  
  XMFLOAT2 UV    

}; 

And I defined an indices, Textures coordinated indices, UVcoordinate and Vertices like this

vector <int> indices ;
vector <int> Texcoordindex ; 
vector <XMFLOAT2> UVCoinate ;
vector <XMFLOAT3> Verices;

OK. I set up the indices, Textures coordinated indices, UVcoordinate and Vertices from a 3D file (an obj file in this case).

Now when I want to define a faces array, I find some of the vertices are defined with multiple UV coordinates. I want to remove the duplicated vertices that have the same UV coordinates and make new index and vertex vectors to store only non-duplicate vertices with new indices of the vertex.

Here is the obj file:

# This file uses centimeters as units for non-parametric coordinates.

v -12.830015 0.000000 12.061520
v 12.027525 0.000000 12.061520
v -12.830015 15.862570 12.061520
v 12.027525 15.862570 12.061520
v -12.830015 15.862570 -12.622024
v 12.027525 15.862570 -12.622024
v -12.830015 0.000000 -12.622024
v 12.027525 0.000000 -12.622024

vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.875000 0.000000
vt 0.875000 0.250000
vt 0.125000 0.000000
vt 0.125000 0.250000
f 1/1 2/2 3/3
f 3/3 2/2 4/4
f 3/3 4/4 5/5
f 5/5 4/4 6/6
f 5/5 6/6 7/7
f 7/7 6/6 8/8
f 7/7 8/8 1/9
f 1/9 8/8 2/10
f 2/2 8/11 4/4
f 4/4 8/11 6/12
f 7/13 1/1 5/14
f 5/14 1/1 3/3

I want the result to be something like this

# This file uses centimeters as units for non-parametric coordinates.

v -12.830015 0.000000 12.061520
v 12.027525 0.000000 12.061520
v -12.830015 15.862570 12.061520
v 12.027525 15.862570 12.061520
v -12.830015 15.862570 -12.622024
v 12.027525 15.862570 -12.622024
v -12.830015 0.000000 -12.622024
v 12.027525 0.000000 -12.622024

vt 0.375000 0.000000
vt 0.625000 0.000000
vt 0.375000 0.250000
vt 0.625000 0.250000
vt 0.375000 0.500000
vt 0.625000 0.500000
vt 0.375000 0.750000
vt 0.625000 0.750000
vt 0.375000 1.000000
vt 0.625000 1.000000
vt 0.875000 0.000000
vt 0.875000 0.250000
vt 0.125000 0.000000
vt 0.125000 0.250000

the new vertices after delete the duplicate

f 1/1 2/2 3/3
f 4/4 5/5 6/6 
f 7/7 8/8 1/9 
f 2/10 8/116/12
f7/13 5/14

I tried using sort and unique but I get compilation errors:

error C2784: 'bool std::operator <(const std::list<_Ty,_Ax> &,const std::list<_Ty,_Ax> &)' : could not deduce template argument for 'const std::list<_Ty,_Ax> &' from 'VERTEX'  c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'VERTEX' c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C2784: 'bool std::operator <(const _Elem *,const std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const _Elem *' from 'VERTEX'   c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C2784: 'bool std::operator <(const std::basic_string<_Elem,_Traits,_Alloc> &,const 
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'VERTEX'    c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C2784: 'bool std::operator <(const std::vector<_Ty,_Ax> &,const std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const std::vector<_Ty,_Ax> &' from 'VERTEX'    c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test


error C2784: 'bool std::operator <(const std::unique_ptr<_Ty,_Dx> &,const std::unique_ptr<_Ty2,_Dx2> &)' : could not deduce template argument for 'const std::unique_ptr<_Ty,_Dx> &' from 'VERTEX'  c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test


error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' : could not deduce template argument for 'const std::reverse_iterator<_RanIt> &' from 'VERTEX'    c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test


error C2784: 'bool std::operator <(const std::_Revranit<_RanIt,_Base> &,const std::_Revranit<_RanIt2,_Base2> &)' : could not deduce template argument for 'const std::_Revranit<_RanIt,_Base> &' from 'VERTEX'  c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test


error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const std::pair<_Ty1,_Ty2> &' from 'VERTEX'    c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C2676: binary '<' : 'VERTEX' does not define this operator or a conversion to a type acceptable to the predefined operator    c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

error C1903: unable to recover from previous error(s); stopping compilation c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm    3559    1   Mesh_test

Without code and the compiler errors it is impossible to diagnose the problem. But an example of using std::sort and std::unique to remove duplicates from the indices vector would be:

std::sort(indices.begin(), indices.end());
vector<int>::iterator it = std::unique(indices.begin(), indices.end());
indices.erase(it,indices.end());

I don't know what the XMLFLOAT3 and XMLFLOAT2 types are so it may be necessary to pass a predicate to std::sort and std::unique .

EDIT: for XMFLOAT3

bool xmfloat3_lt(const XMFLOAT3 f1, const XMFLOAT3 f2)
{
    if (f1.x < f2.x) return true;
    if (f1.y < f2.y) return true;
    if (f1.z < f2.z) return true;
    return false;
}

bool xmfloat3_eq(const XMFLOAT3 f1, const XMFLOAT3 f2)
{
    return f1.x == f2.x &&
           f1.y == f2.y &&
           f1.z == f2.z;
}

std::sort(Verices.begin(), Verices.end(), xmfloat3_lt);
vector<XMFLOAT3>::iterator it = std::unique(
    Verices.begin(), Verices.end(), xmfloat3_eq);
Verices.erase(it,Verices.end());

Hope this helps.

If it is no any kind of restriction in memory usage you can declare a new vector reserve size to be the same with your one and put in only values which are not already in this vector using std::find function to determinate if value is already in your new vector or not.

std::vector newVector;
newVector.reserve( oldVector.size() );

for all elements of your old vector:

if( newVector.find(element))
{
  if( find( newVector.begin(), newVector.end(), newVector.size() != newVector.end() )
  {
    newVector.push_back(element);
   }
}

Other algorithm can be the shifting all of elements in the vector one place back in preview place in case of duplicate ( this method works only for sorted array - list)

I know the compiler output is confusing, but what it is trying to tell you is that it doesn't know how to compare two VERTEX objects. You could define an operator< in your class:

struct VERTEX
{
  XMFLOAT3 Pos;  
  XMFLOAT2 UV;

  bool operator<(const VERTEX &that) const
  {
    // return true if you consider this vertex to be less than that vertex.
  }
};

or as a global function

bool operator<(const VERTEX &v1,const VERTEX &v2)
{
  // return true if you consider v1 to be less than v2
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM