Commit 0d56213d authored by Kirill Terekhov's avatar Kirill Terekhov

fix normal orientation loss during mesh modification; function to check for...

fix normal orientation loss during mesh modification; function to check for cell convexity; add topology check for cell convexity; topology checks for modified elemetns; faster algorithms for orientation calculation; fixes for algorithms in modification state
parent 204f4cf8
This diff is collapsed.
...@@ -19,6 +19,7 @@ namespace INMOST ...@@ -19,6 +19,7 @@ namespace INMOST
/// Prepare sets for coarsements. /// Prepare sets for coarsements.
/// Do not do this in constructor, since mesh may contain no cells. /// Do not do this in constructor, since mesh may contain no cells.
void PrepareSet(); void PrepareSet();
void CheckClosure(std::string file, int line);
//void PrintSetLocal(std::string offset, ElementSet it, std::stringstream& ss); //void PrintSetLocal(std::string offset, ElementSet it, std::stringstream& ss);
//void SynchronizeIndicated(TagInteger& indicator); //void SynchronizeIndicated(TagInteger& indicator);
public: public:
......
...@@ -6,7 +6,7 @@ bool output_file = true; ...@@ -6,7 +6,7 @@ bool output_file = true;
bool balance_mesh = true; bool balance_mesh = true;
bool balance_mesh_refine = false; bool balance_mesh_refine = false;
bool balance_mesh_coarse = false; bool balance_mesh_coarse = false;
std::string file_format = ".pmf"; std::string file_format = ".pvtu";
#ifndef M_PI #ifndef M_PI
#define M_PI 3.1415926535897932 #define M_PI 3.1415926535897932
...@@ -26,21 +26,31 @@ int main(int argc, char ** argv) ...@@ -26,21 +26,31 @@ int main(int argc, char ** argv)
else if( m.GetProcessorRank() == 0 ) else if( m.GetProcessorRank() == 0 )
m.Load(argv[1]); m.Load(argv[1]);
//m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON | PROHIBIT_MULTILINE //~ m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON | PROHIBIT_MULTILINE
// | DEGENERATE_CELL | DEGENERATE_EDGE | DEGENERATE_FACE //~ | PROHIBIT_CONCAVE_CELL
// | PRINT_NOTIFY | TRIPLE_SHARED_FACE | FLATTENED_CELL //~ | FACE_EDGES_ORDER
// | INTERLEAVED_FACES | NEED_TEST_CLOSURE //~ | DEGENERATE_CELL | DEGENERATE_EDGE | DEGENERATE_FACE
// | DUPLICATE_EDGE | DUPLICATE_FACE | DUPLICATE_CELL //~ | PRINT_NOTIFY | TRIPLE_SHARED_FACE | FLATTENED_CELL
// | ADJACENT_DUPLICATE | ADJACENT_HIDDEN | ADJACENT_VALID | ADJACENT_DIMENSION); //~ | INTERLEAVED_FACES | NEED_TEST_CLOSURE
//~ | DUPLICATE_EDGE | DUPLICATE_FACE | DUPLICATE_CELL
//~ | ADJACENT_DUPLICATE | ADJACENT_HIDDEN | ADJACENT_VALID | ADJACENT_DIMENSION);
//m.RemTopologyCheck(THROW_EXCEPTION); //m.RemTopologyCheck(THROW_EXCEPTION);
{
Mesh::GeomParam table;
table[ORIENTATION] = FACE;
table[NORMAL] = FACE;
table[CENTROID] = CELL | FACE;
m.PrepareGeometricData(table);
}
#if defined(USE_PARTITIONER) #if defined(USE_PARTITIONER)
std::vector<Storage::integer> nc(m.GetProcessorsNumber()); std::vector<Storage::integer> nc(m.GetProcessorsNumber());
Partitioner p(&m); Partitioner p(&m);
if( true ) if( true )
{ {
std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "init before "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "init before "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
p.SetMethod(Partitioner::INNER_KMEANS,Partitioner::Partition); //p.SetMethod(Partitioner::INNER_KMEANS,Partitioner::Partition);
//p.SetMethod(Partitioner::Parmetis,Partitioner::Partition); p.SetMethod(Partitioner::Parmetis,Partitioner::Partition);
//p.SetMethod(Partitioner::Parmetis,Partitioner::Refine); //p.SetMethod(Partitioner::Parmetis,Partitioner::Refine);
p.Evaluate(); p.Evaluate();
m.Redistribute(); m.Redistribute();
...@@ -48,7 +58,7 @@ int main(int argc, char ** argv) ...@@ -48,7 +58,7 @@ int main(int argc, char ** argv)
std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "init after "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "init after "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
m.Barrier(); m.Barrier();
//p.SetMethod(Partitioner::Parmetis,Partitioner::Repartition); p.SetMethod(Partitioner::Parmetis,Partitioner::Repartition);
} }
#endif #endif
m.ExchangeGhost(1,FACE); m.ExchangeGhost(1,FACE);
...@@ -61,6 +71,9 @@ int main(int argc, char ** argv) ...@@ -61,6 +71,9 @@ int main(int argc, char ** argv)
#if defined(USE_PARTITIONER) #if defined(USE_PARTITIONER)
p.SetWeight(wgt); p.SetWeight(wgt);
#endif #endif
//m.Save("init"+file_format);
/* /*
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it) for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
indicator[*it] = 1; indicator[*it] = 1;
...@@ -112,7 +125,7 @@ int main(int argc, char ** argv) ...@@ -112,7 +125,7 @@ int main(int argc, char ** argv)
m.ClearFile(); m.ClearFile();
//std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "start "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "start "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
ref_time = Timer(); ref_time = Timer();
Storage::integer numref; Storage::integer numref;
...@@ -142,6 +155,7 @@ int main(int argc, char ** argv) ...@@ -142,6 +155,7 @@ int main(int argc, char ** argv)
numref = m.Integrate(numref); numref = m.Integrate(numref);
if( numref ) if( numref )
{ {
//~ std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "refine_" << k << "_" << refcnt << " "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
tmp_time = Timer(); tmp_time = Timer();
#if defined(USE_PARTITIONER) #if defined(USE_PARTITIONER)
if( balance_mesh_refine && refcnt == 0) if( balance_mesh_refine && refcnt == 0)
...@@ -224,6 +238,7 @@ int main(int argc, char ** argv) ...@@ -224,6 +238,7 @@ int main(int argc, char ** argv)
numref = m.Integrate(numref); numref = m.Integrate(numref);
if( numref ) if( numref )
{ {
//~ std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "coarse_" << k << "_" << refcnt << " "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
tmp_time = Timer(); tmp_time = Timer();
#if defined(USE_PARTITIONER) #if defined(USE_PARTITIONER)
if( balance_mesh_coarse && refcnt == 0) if( balance_mesh_coarse && refcnt == 0)
...@@ -286,20 +301,20 @@ int main(int argc, char ** argv) ...@@ -286,20 +301,20 @@ int main(int argc, char ** argv)
{ {
//m.Barrier(); //m.Barrier();
p.SetWeight(Tag()); p.SetWeight(Tag());
//std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish before "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} //~ std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish before "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
if( m.GetProcessorRank() == 0 ) std::cout << "call Evaluate" << std::endl; if( m.GetProcessorRank() == 0 ) std::cout << "call Evaluate" << std::endl;
p.Evaluate(); p.Evaluate();
if( m.GetProcessorRank() == 0 ) std::cout << "call Redistribute" << std::endl; if( m.GetProcessorRank() == 0 ) std::cout << "call Redistribute" << std::endl;
m.Redistribute(); m.Redistribute();
if( m.GetProcessorRank() == 0 ) std::cout << "balance done" << std::endl; if( m.GetProcessorRank() == 0 ) std::cout << "balance done" << std::endl;
//std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish after "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} //~ std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish after "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
//m.Barrier(); //m.Barrier();
} }
#endif #endif
tmp_time = Timer() - tmp_time; tmp_time = Timer() - tmp_time;
redist_time += tmp_time; redist_time += tmp_time;
//std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;} std::fill(nc.begin(),nc.end(),0); nc[m.GetProcessorRank()] = m.NumberOfCells(); m.Integrate(&nc[0],nc.size()); if( !m.GetProcessorRank() ) {std::cout << "finish "; for(unsigned q = 0; q < nc.size(); ++q) std::cout << nc[q] << " "; std::cout << std::endl;}
...@@ -314,16 +329,28 @@ int main(int argc, char ** argv) ...@@ -314,16 +329,28 @@ int main(int argc, char ** argv)
tag_owner[*it] = tag_owner0[*it]; tag_owner[*it] = tag_owner0[*it];
tag_stat[*it] = it->GetStatus(); tag_stat[*it] = it->GetStatus();
} }
std::stringstream file; {
file << "step_" << k << file_format; std::stringstream file;
m.Save(file.str()); file << "step_" << k << file_format;
if( m.GetProcessorRank() == 0 ) m.Save(file.str());
std::cout << "Save " << file.str() << std::endl; if( m.GetProcessorRank() == 0 )
std::cout << "Save " << file.str() << std::endl;
}
if( false )
{
std::stringstream file;
file << "step_" << k << ".pmf";
m.Save(file.str());
if( m.GetProcessorRank() == 0 )
std::cout << "Save " << file.str() << std::endl;
}
} }
else if( m.GetProcessorRank() == 0 ) std::cout << "step " << k << std::endl; else if( m.GetProcessorRank() == 0 ) std::cout << "step " << k << std::endl;
step_time = Timer() - step_time; step_time = Timer() - step_time;
if( m.GetProcessorRank() == 0 ) std::cout << "step time " << step_time << " refine " << ref_time << " coarse " << crs_time << " balance " << redist_time << std::endl; if( m.GetProcessorRank() == 0 ) std::cout << "step time " << step_time << " refine " << ref_time << " coarse " << crs_time << " balance " << redist_time << std::endl;
//~ MPI_Barrier(MPI_COMM_WORLD);
//~ MPI_Abort(MPI_COMM_WORLD,-1);
} }
......
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
// output xml files for debugging of parallel algorithms // output xml files for debugging of parallel algorithms
// search for style.xsl within examples for comfortable // search for style.xsl within examples for comfortable
// view of generated xml files // view of generated xml files
//~ #define USE_PARALLEL_WRITE_TIME #define USE_PARALLEL_WRITE_TIME
// this will revert Mesh::PrepareReceiveInner to always // this will revert Mesh::PrepareReceiveInner to always
// use MPI point to point functionality disregarding problem type // use MPI point to point functionality disregarding problem type
......
...@@ -641,7 +641,7 @@ namespace INMOST ...@@ -641,7 +641,7 @@ namespace INMOST
void UnitNormal (real * nrm) const; void UnitNormal (real * nrm) const;
void OrientedNormal (Cell c, real * nrm) const; void OrientedNormal (Cell c, real * nrm) const;
void OrientedUnitNormal (Cell c, real * nrm) const; void OrientedUnitNormal (Cell c, real * nrm) const;
bool FixNormalOrientation () const; //returns true if orientation was corrected, otherwise returns false bool FixNormalOrientation (bool allow_swap = true) const; //returns true if orientation was corrected, otherwise returns false
bool CheckNormalOrientation () const; //returns true if orientation is correct, otherwise returns false bool CheckNormalOrientation () const; //returns true if orientation is correct, otherwise returns false
bool Closure () const; // test integrity of polygon bool Closure () const; // test integrity of polygon
bool Inside (const real * point) const; //is point inside face bool Inside (const real * point) const; //is point inside face
...@@ -938,6 +938,8 @@ namespace INMOST ...@@ -938,6 +938,8 @@ namespace INMOST
bool Closure () const; bool Closure () const;
/// For each adjacent cell make me a front cell and fix normal orientation accordingly. /// For each adjacent cell make me a front cell and fix normal orientation accordingly.
void SwapBackCell () const; void SwapBackCell () const;
bool CheckConvexity () const;
}; };
/// ///
...@@ -3239,6 +3241,7 @@ namespace INMOST ...@@ -3239,6 +3241,7 @@ namespace INMOST
/// If marker is set then face is reversed. /// If marker is set then face is reversed.
/// Then all faces are oriented either inside or outside of the cell. /// Then all faces are oriented either inside or outside of the cell.
void FacesOrientation(ElementArray<Face> & faces, MarkerType rev); void FacesOrientation(ElementArray<Face> & faces, MarkerType rev);
bool CheckConvexity(const ElementArray<Face> & faces) const;
void PrepareGeometricData(GeomParam table); void PrepareGeometricData(GeomParam table);
void RemoveGeometricData(GeomParam table); void RemoveGeometricData(GeomParam table);
bool HaveGeometricData (GeometricData type, ElementType mask) const {return remember[type][ElementNum(mask)-1];} // requests to only one geometric and element type allowed bool HaveGeometricData (GeometricData type, ElementType mask) const {return remember[type][ElementNum(mask)-1];} // requests to only one geometric and element type allowed
...@@ -3350,7 +3353,7 @@ namespace INMOST ...@@ -3350,7 +3353,7 @@ namespace INMOST
/// ///
/// \todo /// \todo
/// list checks performed inside in description. /// list checks performed inside in description.
TopologyCheck EndTopologyCheck (HandleType e); //check created element bool EndTopologyCheck (HandleType e, TopologyCheck begin_check); //check created element
/// This will return tag by which you can retrieve error mark to any element on which topogy check failed. /// This will return tag by which you can retrieve error mark to any element on which topogy check failed.
/// As this is sparse tag you can check presence of error by Element::HaveData or Mesh::HaveData check. /// As this is sparse tag you can check presence of error by Element::HaveData or Mesh::HaveData check.
/// This tag will be valid only if you pass MARK_ON_ERROR to Mesh::GetTopologyCheck /// This tag will be valid only if you pass MARK_ON_ERROR to Mesh::GetTopologyCheck
......
...@@ -645,7 +645,7 @@ namespace INMOST ...@@ -645,7 +645,7 @@ namespace INMOST
buconv.read_iByteOrder(header); buconv.read_iByteOrder(header);
buconv.read_iByteSize(header); buconv.read_iByteSize(header);
REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(uconv.get_iByteOrder())); REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(buconv.get_iByteOrder()));
REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize()); REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize());
...@@ -777,7 +777,7 @@ namespace INMOST ...@@ -777,7 +777,7 @@ namespace INMOST
REPORT_VAL("file position",fin.tellg()); REPORT_VAL("file position",fin.tellg());
REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(uconv.get_iByteOrder())); REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(buconv.get_iByteOrder()));
REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize()); REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize());
...@@ -924,7 +924,7 @@ namespace INMOST ...@@ -924,7 +924,7 @@ namespace INMOST
REPORT_VAL("file position",fin.tellg()); REPORT_VAL("file position",fin.tellg());
REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(uconv.get_iByteOrder())); REPORT_VAL("integer_byte_order",buconv.str_iByteOrder(buconv.get_iByteOrder()));
REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize()); REPORT_VAL("integer_byte_size",(int)buconv.get_iByteSize());
INMOST_DATA_ENUM_TYPE datanum,k; INMOST_DATA_ENUM_TYPE datanum,k;
......
...@@ -68,15 +68,18 @@ namespace INMOST ...@@ -68,15 +68,18 @@ namespace INMOST
else if ( !(last == rlc[k1] || last == rlc[k2]) ) else if ( !(last == rlc[k1] || last == rlc[k2]) )
return false; return false;
adj_type::size_type it = 1, iend = lc.size()-1; adj_type::size_type it = 1, iend = lc.size()-1;
while(it != iend) if( !m->GetMarker(lc[it],hm) ) //loop over edges while(it != iend)
{ {
adj_type const & ilc = m->LowConn(lc[it]); if( !m->GetMarker(lc[it],hm) ) //loop over edges
k1 = ENUMUNDEF; {
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); adj_type const & ilc = m->LowConn(lc[it]);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); k1 = ENUMUNDEF;
if( last == ilc[k1] ) last = ilc[k2]; k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else if( last == ilc[k2] ) last = ilc[k1]; k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else return false; if( last == ilc[k1] ) last = ilc[k2];
else if( last == ilc[k2] ) last = ilc[k1];
else return false;
}
++it; ++it;
} }
} }
...@@ -215,29 +218,32 @@ namespace INMOST ...@@ -215,29 +218,32 @@ namespace INMOST
else if( !(last == rlc[k1] || last == rlc[k2]) ) else if( !(last == rlc[k1] || last == rlc[k2]) )
{ {
adj_type::size_type jt = i+1, jend = lc.size(); adj_type::size_type jt = i+1, jend = lc.size();
while(jt < jend) if( !m->GetMarker(lc[jt],hm) ) //loop over edges while(jt < jend)
{ {
adj_type const & ilc = m->LowConn(lc[jt]); if( !m->GetMarker(lc[jt],hm) ) //loop over edges
if( m->Count(ilc.data(),ilc.size(),hm) != 2 ) return false;
k1 = ENUMUNDEF;
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( first == ilc[k1] || first == ilc[k2] )
{ {
HandleType temp = lc[i]; adj_type const & ilc = m->LowConn(lc[jt]);
lc[i] = lc[jt]; if( m->Count(ilc.data(),ilc.size(),hm) != 2 ) return false;
lc[jt] = temp; k1 = ENUMUNDEF;
temp = first; k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
first = last; k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
last = temp; if( first == ilc[k1] || first == ilc[k2] )
break; {
} HandleType temp = lc[i];
else if( last == ilc[k1] || last == ilc[k2] ) lc[i] = lc[jt];
{ lc[jt] = temp;
HandleType temp = lc[i]; temp = first;
lc[i] = lc[jt]; first = last;
lc[jt] = temp; last = temp;
break; break;
}
else if( last == ilc[k1] || last == ilc[k2] )
{
HandleType temp = lc[i];
lc[i] = lc[jt];
lc[jt] = temp;
break;
}
} }
++jt; ++jt;
} }
...@@ -281,7 +287,7 @@ namespace INMOST ...@@ -281,7 +287,7 @@ namespace INMOST
} }
if( jt == jend ) return false; //no matching edge if( jt == jend ) return false; //no matching edge
} }
} } else ++it;
//check that the loop is closed //check that the loop is closed
adj_type const & ilc = m->LowConn(lc[iend]); adj_type const & ilc = m->LowConn(lc[iend]);
if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false; if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false;
...@@ -447,16 +453,19 @@ namespace INMOST ...@@ -447,16 +453,19 @@ namespace INMOST
} }
} }
adj_type::size_type it = 1, iend = lc.size()-1; adj_type::size_type it = 1, iend = lc.size()-1;
while(it < iend) if( !m->GetMarker(lc[it],hm) ) //loop over edges while(it < iend)
{ {
adj_type const & ilc = m->LowConn(lc[it]); if( !m->GetMarker(lc[it],hm) ) //loop over edges
k1 = ENUMUNDEF; {
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); adj_type const & ilc = m->LowConn(lc[it]);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); k1 = ENUMUNDEF;
if( aret.atback() == ilc[k1] ) k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
aret.push_back(ilc[k2]); k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else if( aret.atback() == ilc[k1] )
aret.push_back(ilc[k1]); aret.push_back(ilc[k2]);
else
aret.push_back(ilc[k1]);
}
++it; ++it;
} }
} }
...@@ -579,16 +588,19 @@ namespace INMOST ...@@ -579,16 +588,19 @@ namespace INMOST
} }
} }
adj_type::size_type it = 1, iend = lc.size()-1; adj_type::size_type it = 1, iend = lc.size()-1;
while(it != iend) if( !m->GetMarker(lc[it],hm) ) //loop over edges while(it != iend)
{ {
adj_type const & ilc = m->LowConn(lc[it]); if( !m->GetMarker(lc[it],hm) ) //loop over edges
k1 = ENUMUNDEF; {
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); adj_type const & ilc = m->LowConn(lc[it]);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); k1 = ENUMUNDEF;
if( last == ilc[k1] ) k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
last = ilc[k2]; k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else last = ilc[k1]; if( last == ilc[k1] )
if( invert ^ m->GetPrivateMarker(last,mask) ) aret.push_back(last); last = ilc[k2];
else last = ilc[k1];
if( invert ^ m->GetPrivateMarker(last,mask) ) aret.push_back(last);
}
++it; ++it;
} }
} }
...@@ -703,16 +715,19 @@ namespace INMOST ...@@ -703,16 +715,19 @@ namespace INMOST
} }
} }
adj_type::size_type it = 1, iend = lc.size()-1; adj_type::size_type it = 1, iend = lc.size()-1;
while(it != iend) if( !m->GetMarker(lc[it],hm) ) //loop over edges while(it != iend)
{ {
adj_type const & ilc = m->LowConn(lc[it]); if( !m->GetMarker(lc[it],hm) ) //loop over edges
k1 = ENUMUNDEF; {
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); adj_type const & ilc = m->LowConn(lc[it]);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); k1 = ENUMUNDEF;
if( last == ilc[k1] ) k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
last = ilc[k2]; k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else last = ilc[k1]; if( last == ilc[k1] )
if( invert ^ m->GetMarker(last,mask) ) aret.push_back(last); last = ilc[k2];
else last = ilc[k1];
if( invert ^ m->GetMarker(last,mask) ) aret.push_back(last);
}
++it; ++it;
} }
} }
......
...@@ -191,6 +191,7 @@ namespace INMOST ...@@ -191,6 +191,7 @@ namespace INMOST
while(it < iend) //loop over edges while(it < iend) //loop over edges
{ {
adj_type const & ilc = m->LowConn(lc[it]); adj_type const & ilc = m->LowConn(lc[it]);
if( ilc.size() != 2 ) return false;
if( last == ilc[0] ) last = ilc[1]; if( last == ilc[0] ) last = ilc[1];
else if( last == ilc[1] ) last = ilc[0]; else if( last == ilc[1] ) last = ilc[0];
else return false; else return false;
...@@ -233,15 +234,20 @@ namespace INMOST ...@@ -233,15 +234,20 @@ namespace INMOST
else if ( !(last == rlc[k1] || last == rlc[k2]) ) else if ( !(last == rlc[k1] || last == rlc[k2]) )
return false; return false;
adj_type::size_type it = 1, iend = lc.size()-1; adj_type::size_type it = 1, iend = lc.size()-1;
while(it != iend) if( !m->GetMarker(lc[it],hm) ) //loop over edges while(it != iend)
{ {
adj_type const & ilc = m->LowConn(lc[it]); if( !m->GetMarker(lc[it],hm) ) //loop over edges
k1 = ENUMUNDEF; {
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); adj_type const & ilc = m->LowConn(lc[it]);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm); if( m->Count(ilc.data(),ilc.size(),hm) != 2 ) return false;
if( last == ilc[k1] ) last = ilc[k2]; k1 = ENUMUNDEF;
else if( last == ilc[k2] ) last = ilc[k1]; k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
else return false; k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( k1 == ilc.size() || k2 == ilc.size() ) return false;
if( last == ilc[k1] ) last = ilc[k2];
else if( last == ilc[k2] ) last = ilc[k1];
else return false;
}
++it; ++it;
} }
} }
...@@ -378,29 +384,32 @@ namespace INMOST ...@@ -378,29 +384,32 @@ namespace INMOST
else if( !(last == rlc[k1] || last == rlc[k2]) ) else if( !(last == rlc[k1] || last == rlc[k2]) )
{ {
adj_type::size_type jt = i+1, jend = lc.size(); adj_type::size_type jt = i+1, jend = lc.size();
while(jt < jend) if( !m->GetMarker(lc[jt],hm) ) //loop over edges while(jt < jend)
{ {
adj_type const & ilc = m->LowConn(lc[jt]); if( !m->GetMarker(lc[jt],hm) ) //loop over edges
if( m->Count(ilc.data(),ilc.size(),hm) != 2 ) return false;
k1 = ENUMUNDEF;
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( first == ilc[k1] || first == ilc[k2] )
{
HandleType temp = lc[i];
lc[i] = lc[jt];
lc[jt] = temp;
temp = first;
first = last;
last = temp;
break;
}
else if( last == ilc[k1] || last == ilc[k2] )
{ {
HandleType temp = lc[i]; adj_type const & ilc = m->LowConn(lc[jt]);
lc[i] = lc[jt]; if( m->Count(ilc.data(),ilc.size(),hm) != 2 ) return false;
lc[jt] = temp; k1 = ENUMUNDEF;
break; k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( first == ilc[k1] || first == ilc[k2] )
{
HandleType temp = lc[i];
lc[i] = lc[jt];
lc[jt] = temp;
temp = first;
first = last;
last = temp;
break;
}
else if( last == ilc[k1] || last == ilc[k2] )
{
HandleType temp = lc[i];
lc[i] = lc[jt];
lc[jt] = temp;
break;
}
} }
++jt; ++jt;
} }
...@@ -427,25 +436,28 @@ namespace INMOST ...@@ -427,25 +436,28 @@ namespace INMOST
else//search for the connected edge and swap with current else//search for the connected edge and swap with current
{ {
adj_type::size_type jt = it+1, jend = lc.size(); adj_type::size_type jt = it+1, jend = lc.size();
while(jt < jend) if( !m->GetMarker(lc[jt],hm) ) //loop over edges while(jt < jend)
{ {
adj_type const & ilc = m->LowConn(lc[jt]); if( !m->GetMarker(lc[jt],hm) ) //loop over edges
if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false;
k1 = ENUMUNDEF;
k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( last == ilc[k1] || last == ilc[k2] )
{ {
HandleType temp = lc[it]; adj_type const & ilc = m->LowConn(lc[jt]);
lc[it] = lc[jt]; if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false;
lc[jt] = temp; k1 = ENUMUNDEF;
break; k1 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
k2 = m->getNext(ilc.data(),static_cast<enumerator>(ilc.size()),k1,hm);
if( last == ilc[k1] || last == ilc[k2] )
{
HandleType temp = lc[it];
lc[it] = lc[jt];
lc[jt] = temp;
break;
}
} }
++jt; ++jt;
} }
if( jt == jend ) return false; //no matching edge if( jt == jend ) return false; //no matching edge
} }
} } else ++it;
//check that the loop is closed //check that the loop is closed