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
/// Prepare sets for coarsements.
/// Do not do this in constructor, since mesh may contain no cells.
void PrepareSet();
void CheckClosure(std::string file, int line);
//void PrintSetLocal(std::string offset, ElementSet it, std::stringstream& ss);
//void SynchronizeIndicated(TagInteger& indicator);
public:
......
......@@ -6,7 +6,7 @@ bool output_file = true;
bool balance_mesh = true;
bool balance_mesh_refine = false;
bool balance_mesh_coarse = false;
std::string file_format = ".pmf";
std::string file_format = ".pvtu";
#ifndef M_PI
#define M_PI 3.1415926535897932
......@@ -26,21 +26,31 @@ int main(int argc, char ** argv)
else if( m.GetProcessorRank() == 0 )
m.Load(argv[1]);
//m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON | PROHIBIT_MULTILINE
// | DEGENERATE_CELL | DEGENERATE_EDGE | DEGENERATE_FACE
// | PRINT_NOTIFY | TRIPLE_SHARED_FACE | FLATTENED_CELL
// | INTERLEAVED_FACES | NEED_TEST_CLOSURE
// | DUPLICATE_EDGE | DUPLICATE_FACE | DUPLICATE_CELL
// | ADJACENT_DUPLICATE | ADJACENT_HIDDEN | ADJACENT_VALID | ADJACENT_DIMENSION);
//~ m.SetTopologyCheck(PROHIBIT_MULTIPOLYGON | PROHIBIT_MULTILINE
//~ | PROHIBIT_CONCAVE_CELL
//~ | FACE_EDGES_ORDER
//~ | DEGENERATE_CELL | DEGENERATE_EDGE | DEGENERATE_FACE
//~ | PRINT_NOTIFY | TRIPLE_SHARED_FACE | FLATTENED_CELL
//~ | INTERLEAVED_FACES | NEED_TEST_CLOSURE
//~ | DUPLICATE_EDGE | DUPLICATE_FACE | DUPLICATE_CELL
//~ | ADJACENT_DUPLICATE | ADJACENT_HIDDEN | ADJACENT_VALID | ADJACENT_DIMENSION);
//m.RemTopologyCheck(THROW_EXCEPTION);
{
Mesh::GeomParam table;
table[ORIENTATION] = FACE;
table[NORMAL] = FACE;
table[CENTROID] = CELL | FACE;
m.PrepareGeometricData(table);
}
#if defined(USE_PARTITIONER)
std::vector<Storage::integer> nc(m.GetProcessorsNumber());
Partitioner p(&m);
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;}
p.SetMethod(Partitioner::INNER_KMEANS,Partitioner::Partition);
//p.SetMethod(Partitioner::Parmetis,Partitioner::Partition);
//p.SetMethod(Partitioner::INNER_KMEANS,Partitioner::Partition);
p.SetMethod(Partitioner::Parmetis,Partitioner::Partition);
//p.SetMethod(Partitioner::Parmetis,Partitioner::Refine);
p.Evaluate();
m.Redistribute();
......@@ -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;}
m.Barrier();
//p.SetMethod(Partitioner::Parmetis,Partitioner::Repartition);
p.SetMethod(Partitioner::Parmetis,Partitioner::Repartition);
}
#endif
m.ExchangeGhost(1,FACE);
......@@ -61,6 +71,9 @@ int main(int argc, char ** argv)
#if defined(USE_PARTITIONER)
p.SetWeight(wgt);
#endif
//m.Save("init"+file_format);
/*
for(Mesh::iteratorCell it = m.BeginCell(); it != m.EndCell(); ++it)
indicator[*it] = 1;
......@@ -112,7 +125,7 @@ int main(int argc, char ** argv)
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();
Storage::integer numref;
......@@ -142,6 +155,7 @@ int main(int argc, char ** argv)
numref = m.Integrate(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();
#if defined(USE_PARTITIONER)
if( balance_mesh_refine && refcnt == 0)
......@@ -224,6 +238,7 @@ int main(int argc, char ** argv)
numref = m.Integrate(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();
#if defined(USE_PARTITIONER)
if( balance_mesh_coarse && refcnt == 0)
......@@ -286,20 +301,20 @@ int main(int argc, char ** argv)
{
//m.Barrier();
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;
p.Evaluate();
if( m.GetProcessorRank() == 0 ) std::cout << "call Redistribute" << std::endl;
m.Redistribute();
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();
}
#endif
tmp_time = Timer() - 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)
tag_owner[*it] = tag_owner0[*it];
tag_stat[*it] = it->GetStatus();
}
std::stringstream file;
file << "step_" << k << file_format;
m.Save(file.str());
if( m.GetProcessorRank() == 0 )
std::cout << "Save " << file.str() << std::endl;
{
std::stringstream file;
file << "step_" << k << file_format;
m.Save(file.str());
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;
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;
//~ MPI_Barrier(MPI_COMM_WORLD);
//~ MPI_Abort(MPI_COMM_WORLD,-1);
}
......
......@@ -59,7 +59,7 @@
// output xml files for debugging of parallel algorithms
// search for style.xsl within examples for comfortable
// view of generated xml files
//~ #define USE_PARALLEL_WRITE_TIME
#define USE_PARALLEL_WRITE_TIME
// this will revert Mesh::PrepareReceiveInner to always
// use MPI point to point functionality disregarding problem type
......
......@@ -641,7 +641,7 @@ namespace INMOST
void UnitNormal (real * nrm) const;
void OrientedNormal (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 Closure () const; // test integrity of polygon
bool Inside (const real * point) const; //is point inside face
......@@ -938,6 +938,8 @@ namespace INMOST
bool Closure () const;
/// For each adjacent cell make me a front cell and fix normal orientation accordingly.
void SwapBackCell () const;
bool CheckConvexity () const;
};
///
......@@ -3239,6 +3241,7 @@ namespace INMOST
/// If marker is set then face is reversed.
/// Then all faces are oriented either inside or outside of the cell.
void FacesOrientation(ElementArray<Face> & faces, MarkerType rev);
bool CheckConvexity(const ElementArray<Face> & faces) const;
void PrepareGeometricData(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
......@@ -3350,7 +3353,7 @@ namespace INMOST
///
/// \todo
/// 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.
/// 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
......
......@@ -645,7 +645,7 @@ namespace INMOST
buconv.read_iByteOrder(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());
......@@ -777,7 +777,7 @@ namespace INMOST
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());
......@@ -924,7 +924,7 @@ namespace INMOST
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());
INMOST_DATA_ENUM_TYPE datanum,k;
......
......@@ -68,15 +68,18 @@ namespace INMOST
else if ( !(last == rlc[k1] || last == rlc[k2]) )
return false;
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]);
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];
else if( last == ilc[k2] ) last = ilc[k1];
else return false;
if( !m->GetMarker(lc[it],hm) ) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
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];
else if( last == ilc[k2] ) last = ilc[k1];
else return false;
}
++it;
}
}
......@@ -215,29 +218,32 @@ namespace INMOST
else if( !(last == rlc[k1] || last == rlc[k2]) )
{
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->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] )
if( !m->GetMarker(lc[jt],hm) ) //loop over edges
{
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;
adj_type const & ilc = m->LowConn(lc[jt]);
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];
lc[i] = lc[jt];
lc[jt] = temp;
break;
}
}
++jt;
}
......@@ -281,7 +287,7 @@ namespace INMOST
}
if( jt == jend ) return false; //no matching edge
}
}
} else ++it;
//check that the loop is closed
adj_type const & ilc = m->LowConn(lc[iend]);
if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false;
......@@ -447,16 +453,19 @@ namespace INMOST
}
}
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]);
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( aret.atback() == ilc[k1] )
aret.push_back(ilc[k2]);
else
aret.push_back(ilc[k1]);
if( !m->GetMarker(lc[it],hm) ) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
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( aret.atback() == ilc[k1] )
aret.push_back(ilc[k2]);
else
aret.push_back(ilc[k1]);
}
++it;
}
}
......@@ -579,16 +588,19 @@ namespace INMOST
}
}
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]);
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];
else last = ilc[k1];
if( invert ^ m->GetPrivateMarker(last,mask) ) aret.push_back(last);
if( !m->GetMarker(lc[it],hm) ) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
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];
else last = ilc[k1];
if( invert ^ m->GetPrivateMarker(last,mask) ) aret.push_back(last);
}
++it;
}
}
......@@ -703,16 +715,19 @@ namespace INMOST
}
}
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]);
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];
else last = ilc[k1];
if( invert ^ m->GetMarker(last,mask) ) aret.push_back(last);
if( !m->GetMarker(lc[it],hm) ) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
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];
else last = ilc[k1];
if( invert ^ m->GetMarker(last,mask) ) aret.push_back(last);
}
++it;
}
}
......
......@@ -191,6 +191,7 @@ namespace INMOST
while(it < iend) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
if( ilc.size() != 2 ) return false;
if( last == ilc[0] ) last = ilc[1];
else if( last == ilc[1] ) last = ilc[0];
else return false;
......@@ -233,15 +234,20 @@ namespace INMOST
else if ( !(last == rlc[k1] || last == rlc[k2]) )
return false;
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]);
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];
else if( last == ilc[k2] ) last = ilc[k1];
else return false;
if( !m->GetMarker(lc[it],hm) ) //loop over edges
{
adj_type const & ilc = m->LowConn(lc[it]);
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( 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;
}
}
......@@ -378,29 +384,32 @@ namespace INMOST
else if( !(last == rlc[k1] || last == rlc[k2]) )
{
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->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] )
if( !m->GetMarker(lc[jt],hm) ) //loop over edges
{
HandleType temp = lc[i];
lc[i] = lc[jt];
lc[jt] = temp;
break;
adj_type const & ilc = m->LowConn(lc[jt]);
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];
lc[i] = lc[jt];
lc[jt] = temp;
break;
}
}
++jt;
}
......@@ -427,25 +436,28 @@ namespace INMOST
else//search for the connected edge and swap with current
{
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->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] )
if( !m->GetMarker(lc[jt],hm) ) //loop over edges
{
HandleType temp = lc[it];
lc[it] = lc[jt];
lc[jt] = temp;
break;
adj_type const & ilc = m->LowConn(lc[jt]);
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];
lc[it] = lc[jt];
lc[jt] = temp;
break;
}
}
++jt;
}
if( jt == jend ) return false; //no matching edge
}
}
} else ++it;
//check that the loop is closed
adj_type const & ilc = m->LowConn(lc[iend]);
if(m->Count(ilc.data(),ilc.size(),hm)!=2) return false;
......@@ -698,7 +710,7 @@ namespace INMOST
last = ilc[k1];
}
++it;
}
} else ++it;
}
}
......
This diff is collapsed.
......@@ -985,6 +985,14 @@ namespace INMOST
if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(DEGENERATE_CELL) << std::endl;
}
}
if( GetTopologyCheck(PROHIBIT_CONCAVE_CELL) )
{
if( !CheckConvexity(ElementArray<Face>(this,adj,adj+s)) )
{
chk |= PROHIBIT_CONCAVE_CELL;
if( GetTopologyCheck(PRINT_NOTIFY) ) std::cerr << TopologyCheckNotifyString(PROHIBIT_CONCAVE_CELL) << std::endl;
}
}
break;
}
}
......@@ -1035,9 +1043,9 @@ namespace INMOST
return chk;
}
TopologyCheck Mesh::EndTopologyCheck(HandleType he)
bool Mesh::EndTopologyCheck(HandleType he, TopologyCheck begin_checks)
{
TopologyCheck chk = 0;
TopologyCheck chk = begin_checks;
Element e = ElementByHandle(he);
switch(e->GetGeometricDimension(e->GetGeometricType()))
{
......@@ -1121,7 +1129,14 @@ namespace INMOST
}
}
errorset |= chk;
return chk;
if( chk != 0 )
{
if( GetTopologyCheck(MARK_ON_ERROR) ) Integer(he,TopologyErrorTag()) = chk;
if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
return false;
}
return true;
}
Node Mesh::CreateNode(const real * coords)
......@@ -1220,6 +1235,8 @@ namespace INMOST
ComputeGeometricType(he);
SetMarker(he,NewMarker());
RecomputeGeometricData(he);
EndTopologyCheck(he,chk);
/*
chk |= EndTopologyCheck(he);
if( chk != 0 )
{
......@@ -1227,6 +1244,7 @@ namespace INMOST
if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
}
*/
}
return std::make_pair(Edge(this,he),true);
}
......@@ -1316,6 +1334,8 @@ namespace INMOST
ComputeGeometricType(he);
SetMarker(he,NewMarker());
RecomputeGeometricData(he);
EndTopologyCheck(he,chk);
/*
chk |= EndTopologyCheck(he);
if( chk != 0 )
{
......@@ -1323,6 +1343,7 @@ namespace INMOST
if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
}
*/
}
return std::make_pair(Face(this,he),true);
}
......@@ -1741,6 +1762,8 @@ namespace INMOST
//END DEBUG
SetMarker(he,NewMarker());
RecomputeGeometricData(he);
EndTopologyCheck(he,chk);
/*
chk |= EndTopologyCheck(he);
if( chk != 0 )
{
......@@ -1748,6 +1771,7 @@ namespace INMOST
if( GetTopologyCheck(DELETE_ON_ERROR) ) { Destroy(he); he = InvalidHandle();}
if( GetTopologyCheck(THROW_EXCEPTION) ) throw TopologyCheckError;
}
*/
}
......
......@@ -657,6 +657,7 @@ namespace INMOST
hc.replace(hc.begin(),hc.end(),nodes.begin(),nodes.end());
//recompute geometric data
m->RecomputeGeometricData(cells[it]);
m->EndTopologyCheck(cells[it],0);
}
return ret;
......@@ -928,10 +929,48 @@ namespace INMOST
for(dynarray<adj_type::size_type,64>::size_type k = 0; k < insert_pos.size(); k++)
{
adj_type & lc = m->LowConn(faces[k]);
std::vector<HandleType> tlc(lc.begin(),lc.end());
lc.insert(lc.begin()+insert_pos[k],e->GetHandle());
ehc.push_back(faces[k]);
m->ComputeGeometricType(faces[k]);
m->RecomputeGeometricData(faces[k]);
m->EndTopologyCheck(faces[k],0);
/*
if( !m->EndTopologyCheck(faces[k],0) )
{
for(std::map<HandleType,int>::iterator it = nodes.begin(); it != nodes.end(); it++)
{
Storage::real_array c = m->NodeByLocalID(GetHandleID(it->first)).Coords();
std::cout << "node " << it->first << " at " << c[0] << " " << c[1] << " " << c[2] << " dup " << it->second << std::endl;
}
ElementArray<Edge> edges = m->FaceByLocalID(GetHandleID(faces[k])).getEdges();
std::cout << "edges: " << edges.size() << " lc: " << lc.size() << std::endl;
for(int mt = 0; mt < lc.size(); ++mt) std::cout << lc[mt] << " " << (m->GetMarker(lc[mt],hm) ? "hidden":"visible") << " ";
std::cout << std::endl;
for(ElementArray<Edge>::iterator mt = edges.begin(); mt != edges.end(); ++mt)
{
std::cout << "(" << mt->getBeg()->Coords()[0] << "," << mt->getBeg()->Coords()[1] << "," << mt->getBeg()->Coords()[2] << ")";
std::cout << "<->";
std::cout << "(" << mt->getEnd()->Coords()[0] << "," << mt->getEnd()->Coords()[1] << "," << mt->getEnd()->Coords()[2] << ")";
std::cout << std::endl;
}
std::cout << "lc insert pos: " << insert_pos[k] << " before insert: " << tlc.size() << " after: " << lc.size() << std::endl;
for(int mi = 0; mi != lc.size(); ++mi) std::cout << " " << lc[mi]; std::cout << std::endl;
for(int mi = 0; mi != tlc.size(); ++mi) std::cout << " " << tlc[mi]; std::cout << std::endl;
for(int mi = 0; mi != tlc.size(); ++mi)
{
int eid = GetHandleID(tlc[mi]);
Edge mt = m->EdgeByLocalID(eid);
std::cout << "(" << mt->getBeg()->Coords()[0] << "," << mt->getBeg()->Coords()[1] << "," << mt->getBeg()->Coords()[2] << ")";
std::cout << "<->";
std::cout << "(" << mt->getEnd()->Coords()[0] << "," << mt->getEnd()->Coords()[1] << "," << mt->getEnd()->Coords()[2] << ")";
std::cout << std::endl;
}