-// Copyright (C) 2007-2012 CEA/DEN, EDF R&D
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
-// version 2.1 of the License.
+// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
#include "NormalizedUnstructuredMesh.hxx"
#include <fstream>
+#include <sstream>
#include <iomanip>
#include <cstring>
#include <limits>
std::ifstream stream(file);
stream.exceptions(std::ios_base::eofbit);
try
- {
+ {
do
stream.getline(currentLine,MAX_SIZE_OF_LINE_XFIG_FILE);
while(strcmp(currentLine,"1200 2")!=0);
pushBack(newEdge);
}
while(1);
- }
- catch(std::ifstream::failure&)
- {
- }
+ }
+ catch(const std::ifstream::failure&)
+ {
+ }
+ catch(const std::exception & ex)
+ {
+ // Some code before this catch throws the C++98 version of the exception (mangled
+ // name is " NSt8ios_base7failureE"), but FED24 compilation of the current version of the code
+ // tries to catch the C++11 version of it (mangled name "NSt8ios_base7failureB5cxx11E").
+ // So we have this nasty hack to catch both versions ...
+
+ // TODO: the below should be replaced by a better handling avoiding exception throwing.
+ if (std::string(ex.what()) == "basic_ios::clear")
+ {
+ //std::cout << "std::ios_base::failure C++11\n";
+ }
+ else
+ throw ex;
+ }
front()->changeStartNodeWith(back()->getEndNode());
}
QuadraticPolygon *QuadraticPolygon::BuildLinearPolygon(std::vector<Node *>& nodes)
{
- QuadraticPolygon *ret=new QuadraticPolygon;
+ QuadraticPolygon *ret(new QuadraticPolygon);
std::size_t size=nodes.size();
for(std::size_t i=0;i<size;i++)
{
QuadraticPolygon *QuadraticPolygon::BuildArcCirclePolygon(std::vector<Node *>& nodes)
{
- QuadraticPolygon *ret=new QuadraticPolygon;
+ QuadraticPolygon *ret(new QuadraticPolygon);
std::size_t size=nodes.size();
for(std::size_t i=0;i<size/2;i++)
+
{
EdgeLin *e1,*e2;
e1=new EdgeLin(nodes[i],nodes[i+size/2]);
return ret;
}
+Edge *QuadraticPolygon::BuildLinearEdge(std::vector<Node *>& nodes)
+{
+ if(nodes.size()!=2)
+ throw INTERP_KERNEL::Exception("QuadraticPolygon::BuildLinearEdge : input vector is expected to be of size 2 !");
+ Edge *ret(new EdgeLin(nodes[0],nodes[1]));
+ nodes[0]->decrRef(); nodes[1]->decrRef();
+ return ret;
+}
+
+Edge *QuadraticPolygon::BuildArcCircleEdge(std::vector<Node *>& nodes)
+{
+ if(nodes.size()!=3)
+ throw INTERP_KERNEL::Exception("QuadraticPolygon::BuildArcCircleEdge : input vector is expected to be of size 3 !");
+ EdgeLin *e1(new EdgeLin(nodes[0],nodes[2])),*e2(new EdgeLin(nodes[2],nodes[1]));
+ SegSegIntersector inters(*e1,*e2);
+ bool colinearity=inters.areColinears();
+ delete e1; delete e2;
+ Edge *ret(0);
+ if(colinearity)
+ ret=new EdgeLin(nodes[0],nodes[1]);
+ else
+ ret=new EdgeArcCircle(nodes[0],nodes[2],nodes[1]);
+ nodes[0]->decrRef(); nodes[1]->decrRef(); nodes[2]->decrRef();
+ return ret;
+}
+
void QuadraticPolygon::BuildDbgFile(const std::vector<Node *>& nodes, const char *fileName)
{
std::ofstream file(fileName);
}
/*!
- * This method splits 'this' with 'other' into smaller pieces localizable. 'mapThis' is a map that gives the correspondance between nodes contained in 'this' and node ids in a global mesh.
- * In the same way, 'mapOther' gives the correspondance between nodes contained in 'other' and node ids in a global mesh from wich 'other' is extracted.
- * This method has 1 out paramater : 'edgesThis', After the call of this method contains nodal connectivity (including type) of 'this' into globlal "this mesh".
- * This method has 2 in/out parameters : 'subDivOther' and 'addCoo'.'otherEdgeIds' is useful to put values in 'edgesThis', 'subDivOther' and 'addCoo'.
+ * This method splits 'this' with 'other' into smaller pieces localizable. 'mapThis' is a map that gives the correspondance
+ * between nodes contained in 'this' and node ids in a global mesh.
+ * In the same way, 'mapOther' gives the correspondance between nodes contained in 'other' and node ids in a
+ * global mesh from wich 'other' is extracted.
+ * This method has 1 out paramater : 'edgesThis', After the call of this method, it contains the nodal connectivity (including type)
+ * of 'this' into globlal "this mesh".
+ * This method has 2 in/out parameters : 'subDivOther' and 'addCoo'.'otherEdgeIds' is useful to put values in
+ * 'edgesThis', 'subDivOther' and 'addCoo'.
* Size of 'otherEdgeIds' has to be equal to number of ElementaryEdges in 'other'. No check of that will be done.
+ * The term 'abs' in the name recalls that we normalize the mesh (spatially) so that node coordinates fit into [0;1].
* @param offset1 is the number of nodes contained in global mesh from which 'this' is extracted.
* @param offset2 is the sum of nodes contained in global mesh from which 'this' is extracted and 'other' is extracted.
* @param edgesInOtherColinearWithThis will be appended at the end of the vector with colinear edge ids of other (if any)
- * @otherEdgeIds is a vector with the same size than other before calling this method. It gives in the same order the cell id in global other mesh.
+ * @param otherEdgeIds is a vector with the same size than other before calling this method. It gives in the same order
+ * the cell id in global other mesh.
*/
-void QuadraticPolygon::splitAbs(QuadraticPolygon& other, const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther, int offset1, int offset2 , const std::vector<int>& otherEdgeIds,
- std::vector<int>& edgesThis, int cellIdThis, std::vector< std::vector<int> >& edgesInOtherColinearWithThis, std::vector< std::vector<int> >& subDivOther, std::vector<double>& addCoo)
+void QuadraticPolygon::splitAbs(QuadraticPolygon& other,
+ const std::map<INTERP_KERNEL::Node *,int>& mapThis, const std::map<INTERP_KERNEL::Node *,int>& mapOther,
+ int offset1, int offset2 ,
+ const std::vector<int>& otherEdgeIds,
+ std::vector<int>& edgesThis, int cellIdThis,
+ std::vector< std::vector<int> >& edgesInOtherColinearWithThis, std::vector< std::vector<int> >& subDivOther,
+ std::vector<double>& addCoo, std::map<int,int>& mergedNodes)
{
double xBaryBB, yBaryBB;
double fact=normalizeExt(&other, xBaryBB, yBaryBB);
{
ElementaryEdge* curE1=it1.current();
merge.clear();
+ //
+ std::map<INTERP_KERNEL::Node *,int>::const_iterator thisStart(mapThis.find(curE1->getStartNode())),thisEnd(mapThis.find(curE1->getEndNode())),otherStart(mapOther.find(curE2->getStartNode())),otherEnd(mapOther.find(curE2->getEndNode()));
+ int thisStart2(thisStart==mapThis.end()?-1:(*thisStart).second),thisEnd2(thisEnd==mapThis.end()?-1:(*thisEnd).second),otherStart2(otherStart==mapOther.end()?-1:(*otherStart).second+offset1),otherEnd2(otherEnd==mapOther.end()?-1:(*otherEnd).second+offset1);
+ //
if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
{
if(!curE1->getDirection()) c1->reverse();
UpdateNeighbours(merge,it1,it2,curE1,curE2);
it1.next();
}
+ merge.updateMergedNodes(thisStart2,thisEnd2,otherStart2,otherEnd2,mergedNodes);
}
}
if(otherTmp.presenceOfOn())
}
/*!
- * This method builds from descending conn of a quadratic polygon stored in crude mode (MEDCoupling). Descending conn is in FORTRAN relative mode in order to give the
- * orientation of edge.
+ * This method builds 'this' from its descending conn stored in crude mode (MEDCoupling).
+ * Descending conn is in FORTRAN relative mode in order to give the
+ * orientation of edge (see buildDescendingConnectivity2() method).
+ * See appendEdgeFromCrudeDataArray() for params description.
*/
void QuadraticPolygon::buildFromCrudeDataArray(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
}
}
-void QuadraticPolygon::appendEdgeFromCrudeDataArray(std::size_t edgePos, const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords,
+void QuadraticPolygon::appendEdgeFromCrudeDataArray(std::size_t edgePos, const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad,
+ const int *nodalBg, const double *coords,
const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges)
{
if(!isQuad)
{
bool direct=descBg[edgePos]>0;
- int edgeId=abs(descBg[edgePos])-1;
+ int edgeId=abs(descBg[edgePos])-1; // back to C indexing mode
const std::vector<int>& subEdge=intersectEdges[edgeId];
std::size_t nbOfSubEdges=subEdge.size()/2;
for(std::size_t j=0;j<nbOfSubEdges;j++)
{//it is not a quadratic subedge
Node *start=(*mapp.find(direct?subEdge[2*j]:subEdge[2*nbOfSubEdges-2*j-1])).second;
Node *end=(*mapp.find(direct?subEdge[2*j+1]:subEdge[2*nbOfSubEdges-2*j-2])).second;
- ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
+ ElementaryEdge *e=ElementaryEdge::BuildEdgeFromStartEndDir(true,start,end);
pushBack(e);
}
else
*/
void QuadraticPolygon::buildFromCrudeDataArray2(const std::map<int,INTERP_KERNEL::Node *>& mapp, bool isQuad, const int *nodalBg, const double *coords, const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges,
const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1, const std::vector<std::vector<int> >& intersectEdges1,
- const std::vector< std::vector<int> >& colinear1)
+ const std::vector< std::vector<int> >& colinear1,
+ std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >& alreadyExistingIn2)
{
std::size_t nbOfSeg=std::distance(descBg,descEnd);
for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
{
bool direct=descBg[i]>0;
int edgeId=abs(descBg[i])-1;//current edge id of pol2
+ std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> >::const_iterator it1=alreadyExistingIn2.find(descBg[i]),it2=alreadyExistingIn2.find(-descBg[i]);
+ if(it1!=alreadyExistingIn2.end() || it2!=alreadyExistingIn2.end())
+ {
+ bool sameDir=(it1!=alreadyExistingIn2.end());
+ const std::vector<INTERP_KERNEL::ElementaryEdge *>& edgesAlreadyBuilt=sameDir?(*it1).second:(*it2).second;
+ if(sameDir)
+ {
+ for(std::vector<INTERP_KERNEL::ElementaryEdge *>::const_iterator it3=edgesAlreadyBuilt.begin();it3!=edgesAlreadyBuilt.end();it3++)
+ {
+ Edge *ee=(*it3)->getPtr(); ee->incrRef();
+ pushBack(new ElementaryEdge(ee,(*it3)->getDirection()));
+ }
+ }
+ else
+ {
+ for(std::vector<INTERP_KERNEL::ElementaryEdge *>::const_reverse_iterator it4=edgesAlreadyBuilt.rbegin();it4!=edgesAlreadyBuilt.rend();it4++)
+ {
+ Edge *ee=(*it4)->getPtr(); ee->incrRef();
+ pushBack(new ElementaryEdge(ee,!(*it4)->getDirection()));
+ }
+ }
+ continue;
+ }
bool directos=colinear1[edgeId].empty();
std::vector<std::pair<int,std::pair<bool,int> > > idIns1;
int offset1=0;
}
if(directos)
{//no subpart of edge 'edgeId' of pol2 is in pol1 so let's operate the same thing that QuadraticPolygon::buildFromCrudeDataArray method
+ std::size_t oldSz=_sub_edges.size();
appendEdgeFromCrudeDataArray(i,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
+ std::size_t newSz=_sub_edges.size();
+ std::size_t zeSz=newSz-oldSz;
+ alreadyExistingIn2[descBg[i]].resize(zeSz);
+ std::list<ElementaryEdge *>::const_reverse_iterator it5=_sub_edges.rbegin();
+ for(std::size_t p=0;p<zeSz;p++,it5++)
+ alreadyExistingIn2[descBg[i]][zeSz-p-1]=*it5;
}
else
{//there is subpart of edge 'edgeId' of pol2 inside pol1
bool direct1;//store if needed the direction in 1
int offset2;
std::size_t nbOfSubEdges1;
- for(std::vector<std::pair<int,std::pair<bool,int> > >::const_iterator it=idIns1.begin();it!=idIns1.end();it++)
+ for(std::vector<std::pair<int,std::pair<bool,int> > >::const_iterator it=idIns1.begin();it!=idIns1.end() && !found;it++)
{
int idIn1=(*it).first;//store if needed the cell id in 1
direct1=(*it).second.first;
//appendEdgeFromCrudeDataArray(j,mapp,isQuad,nodalBg,coords,descBg,descEnd,intersectEdges);
Node *start=(*mapp.find(idBg)).second;
Node *end=(*mapp.find(idEnd)).second;
- ElementaryEdge *e=ElementaryEdge::BuildEdgeFromCrudeDataArray(true,start,end);
+ ElementaryEdge *e=ElementaryEdge::BuildEdgeFromStartEndDir(true,start,end);
pushBack(e);
+ alreadyExistingIn2[descBg[i]].push_back(e);
}
else
{//the current subedge of edge 'edgeId' of pol2 is part of the colinear edge 'idIn1' of pol1 -> reuse Edge instance of pol1
ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
Edge *ee=e->getPtr();
- ee->incrRef(); ee->declareOn();
- pushBack(new ElementaryEdge(ee,!(direct1^direction11)));
+ ee->incrRef();
+ ElementaryEdge *e2=new ElementaryEdge(ee,!(direct1^direction11));
+ pushBack(e2);
+ alreadyExistingIn2[descBg[i]].push_back(e2);
+ }
+ }
+ }
+ }
+}
+
+/*!
+ * Method expected to be called on pol2. Every params not suffixed by numbered are supposed to refer to pol2 (this).
+ * Method to find edges that are ON.
+ */
+void QuadraticPolygon::updateLocOfEdgeFromCrudeDataArray2(const int *descBg, const int *descEnd, const std::vector<std::vector<int> >& intersectEdges,
+ const INTERP_KERNEL::QuadraticPolygon& pol1, const int *descBg1, const int *descEnd1,
+ const std::vector<std::vector<int> >& intersectEdges1, const std::vector< std::vector<int> >& colinear1) const
+{
+ std::size_t nbOfSeg=std::distance(descBg,descEnd);
+ for(std::size_t i=0;i<nbOfSeg;i++)//loop over all edges of pol2
+ {
+ bool direct=descBg[i]>0;
+ int edgeId=abs(descBg[i])-1;//current edge id of pol2
+ const std::vector<int>& c=colinear1[edgeId];
+ if(c.empty())
+ continue;
+ const std::vector<int>& subEdge=intersectEdges[edgeId];
+ std::size_t nbOfSubEdges=subEdge.size()/2;
+ //
+ std::size_t nbOfEdgesIn1=std::distance(descBg1,descEnd1);
+ int offset1=0;
+ for(std::size_t j=0;j<nbOfEdgesIn1;j++)
+ {
+ int edgeId1=abs(descBg1[j])-1;
+ if(std::find(c.begin(),c.end(),edgeId1)!=c.end())
+ {
+ for(std::size_t k=0;k<nbOfSubEdges;k++)
+ {
+ int idBg=direct?subEdge[2*k]:subEdge[2*nbOfSubEdges-2*k-1];
+ int idEnd=direct?subEdge[2*k+1]:subEdge[2*nbOfSubEdges-2*k-2];
+ int idIn1=edgeId1;
+ bool direct1=descBg1[j]>0;
+ const std::vector<int>& subEdge1PossiblyAlreadyIn1=intersectEdges1[idIn1];
+ std::size_t nbOfSubEdges1=subEdge1PossiblyAlreadyIn1.size()/2;
+ int offset2=0;
+ bool found=false;
+ for(std::size_t kk=0;kk<nbOfSubEdges1 && !found;kk++)
+ {
+ found=(subEdge1PossiblyAlreadyIn1[2*kk]==idBg && subEdge1PossiblyAlreadyIn1[2*kk+1]==idEnd) || (subEdge1PossiblyAlreadyIn1[2*kk]==idEnd && subEdge1PossiblyAlreadyIn1[2*kk+1]==idBg);
+ if(!found)
+ offset2++;
+ }
+ if(found)
+ {
+ ElementaryEdge *e=pol1[offset1+(direct1?offset2:nbOfSubEdges1-offset2-1)];
+ e->getPtr()->declareOn();
+ }
}
}
+ offset1+=intersectEdges1[edgeId1].size()/2;//offset1 is used to find the INTERP_KERNEL::Edge * instance into pol1 that will be part of edge into pol2
}
}
}
}
/*!
- * This method make the hypothesis that 'this' and 'other' are splited at the minimum into edges that are fully IN, OUT or ON.
- * This method returns newly created polygons in 'conn' and 'connI' and the corresponding ids ('idThis','idOther') are stored respectively into 'nbThis' and 'nbOther'.
+ * This method make the hypothesis that \a this and \a other are split at the minimum into edges that are fully IN, OUT or ON.
+ * This method returns newly created polygons in \a conn and \a connI and the corresponding ids ( \a idThis, \a idOther) are stored respectively into \a nbThis and \a nbOther.
+ * @param [in,out] edgesThis, parameter that keep informed the caller about the edges in this not shared by the result of intersection of \a this with \a other
+ * @param [in,out] edgesBoundaryOther, parameter that stores all edges in result of intersection that are not
*/
-void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, const std::map<INTERP_KERNEL::Node *,int>& mapp, int idThis, int idOther, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nbThis, std::vector<int>& nbOther)
+void QuadraticPolygon::buildPartitionsAbs(QuadraticPolygon& other, std::set<INTERP_KERNEL::Edge *>& edgesThis, std::set<INTERP_KERNEL::Edge *>& edgesBoundaryOther, const std::map<INTERP_KERNEL::Node *,int>& mapp, int idThis, int idOther, int offset, std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nbThis, std::vector<int>& nbOther)
{
double xBaryBB, yBaryBB;
double fact=normalizeExt(&other, xBaryBB, yBaryBB);
- //Locate 'this' relative to 'other'
- other.performLocatingOperation(*this);
+ //Locate \a this relative to \a other (edges of \a this, aka \a pol1 are marked as IN or OUT)
+ other.performLocatingOperationSlow(*this); // without any assumption
std::vector<QuadraticPolygon *> res=buildIntersectionPolygons(other,*this);
for(std::vector<QuadraticPolygon *>::iterator it=res.begin();it!=res.end();it++)
{
(*it)->appendCrudeData(mapp,xBaryBB,yBaryBB,fact,offset,addCoordsQuadratic,conn,connI);
+ INTERP_KERNEL::IteratorOnComposedEdge it1(*it);
+ for(it1.first();!it1.finished();it1.next())
+ {
+ Edge *e=it1.current()->getPtr();
+ if(edgesThis.find(e)!=edgesThis.end())
+ edgesThis.erase(e);
+ else
+ {
+ if(edgesBoundaryOther.find(e)!=edgesBoundaryOther.end())
+ edgesBoundaryOther.erase(e);
+ else
+ edgesBoundaryOther.insert(e);
+ }
+ }
nbThis.push_back(idThis);
nbOther.push_back(idOther);
delete *it;
for(std::list<ElementaryEdge *>::const_iterator it=cpyOfOther._sub_edges.begin();it!=cpyOfOther._sub_edges.end();it++)
{
switch((*it)->getLoc())
- {
+ {
case FULL_IN_1:
{
ret += fabs((*it)->getPtr()->getCurveLength());
default:
{
}
- }
+ }
}
return ret * fact;
}
{
barycenter[0]=barycenter[0]/ret*fact+xBaryBB;
barycenter[1]=barycenter[1]/ret*fact+yBaryBB;
-
+
}
return ret*fact*fact;
}
it1=curE2->getIterator();
for(;!it1.finished();)
{
-
+
ElementaryEdge* curE1=it1.current();
merge.clear(); nbOfSplits++;
if(curE1->getPtr()->intersectWith(curE2->getPtr(),merge,*c1,*c2))
Delete(c2);
}
-void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol2) const
+void QuadraticPolygon::performLocatingOperation(QuadraticPolygon& pol1) const
{
- IteratorOnComposedEdge it(&pol2);
+ IteratorOnComposedEdge it(&pol1);
TypeOfEdgeLocInPolygon loc=FULL_ON_1;
for(it.first();!it.finished();it.next())
{
ElementaryEdge *cur=it.current();
- loc=cur->locateFullyMySelf(*this,loc);
+ loc=cur->locateFullyMySelf(*this,loc);//*this=pol2=other
+ }
+}
+
+void QuadraticPolygon::performLocatingOperationSlow(QuadraticPolygon& pol2) const
+{
+ IteratorOnComposedEdge it(&pol2);
+ for(it.first();!it.finished();it.next())
+ {
+ ElementaryEdge *cur=it.current();
+ cur->locateFullyMySelfAbsolute(*this);
}
}
/*!
- * Given 2 polygons 'pol1' and 'pol2' (localized) the resulting polygons are returned.
+ * Given 2 polygons \a pol1 and \a pol2 (localized) the resulting polygons are returned.
*
* this : pol2 simplified.
- * @param pol1 pol1 split.
- * @param pol2 pol2 split.
+ * @param [in] pol1 pol1 split.
+ * @param [in] pol2 pol2 split.
*/
std::vector<QuadraticPolygon *> QuadraticPolygon::buildIntersectionPolygons(const QuadraticPolygon& pol1, const QuadraticPolygon& pol2) const
{
std::vector<QuadraticPolygon *> ret;
std::list<QuadraticPolygon *> pol2Zip=pol2.zipConsecutiveInSegments();
if(!pol2Zip.empty())
- closePolygons(pol2Zip,pol1,ret);
+ ClosePolygons(pol2Zip,pol1,*this,ret);
else
{//borders of pol2 do not cross pol1,and pol2 borders are outside of pol1. That is to say, either pol2 and pol1
//do not overlap or pol1 is fully inside pol2. So in the first case no intersection, in the other case
std::list<QuadraticPolygon *> QuadraticPolygon::zipConsecutiveInSegments() const
{
std::list<QuadraticPolygon *> ret;
- IteratorOnComposedEdge it((ComposedEdge *)this);
+ IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(this));
int nbOfTurns=recursiveSize();
int i=0;
if(!it.goToNextInOn(false,i,nbOfTurns))
}
/*!
- * 'this' should be considered as pol2Simplified.
- * @param pol2zip is a list of set of edges (openned polygon) coming from split polygon 2.
- * @param pol1 is split pol1.
- * @param results the resulting \b CLOSED polygons.
+ * @param [in] pol2zip is a list of set of edges (=an opened polygon) coming from split polygon 2.
+ * @param [in] pol1 is split pol1.
+ * @param [in] pol2 should be considered as pol2Simplified.
+ * @param [out] results the resulting \b CLOSED polygons.
*/
-void QuadraticPolygon::closePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1,
- std::vector<QuadraticPolygon *>& results) const
+void QuadraticPolygon::ClosePolygons(std::list<QuadraticPolygon *>& pol2Zip, const QuadraticPolygon& pol1, const QuadraticPolygon& pol2,
+ std::vector<QuadraticPolygon *>& results)
{
bool directionKnownInPol1=false;
bool directionInPol1;
}
if(!directionKnownInPol1)
{
- if(!(*iter)->amIAChanceToBeCompletedBy(pol1,*this,directionInPol1))
+ if(!(*iter)->haveIAChanceToBeCompletedBy(pol1,pol2,directionInPol1))
{ delete *iter; iter=pol2Zip.erase(iter); continue; }
else
directionKnownInPol1=true;
/*!
* 'this' is expected to be set of edges (not closed) of pol2 split.
*/
-bool QuadraticPolygon::amIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
+bool QuadraticPolygon::haveIAChanceToBeCompletedBy(const QuadraticPolygon& pol1Splitted,const QuadraticPolygon& pol2NotSplitted, bool& direction)
{
IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1Splitted));
bool found=false;
it.next();
}
if(!found)
- throw Exception("Internal error : polygons uncompatible each others. Should never happend");
+ throw Exception("Internal error: polygons incompatible with each others. Should never happen!");
//Ok we found correspondance between this and pol1. Searching for right direction to close polygon.
ElementaryEdge *e=_sub_edges.back();
if(e->getLoc()==FULL_ON_1)
}
/*!
- * This method fills as much as possible 'this' (part of pol2 split) with edges of 'pol1Splitted'.
+ * This method fills as much as possible \a this (a sub-part of pol2 split) with edges of \a pol1Splitted.
*/
std::list<QuadraticPolygon *>::iterator QuadraticPolygon::fillAsMuchAsPossibleWith(const QuadraticPolygon& pol1Splitted,
std::list<QuadraticPolygon *>::iterator iStart,
if(!direction)
it.previousLoop();
Node *nodeToTest;
+ int szMax(pol1Splitted.size()+1),ii(0);// here a protection against agressive users of IntersectMeshes of invalid input meshes
std::list<QuadraticPolygon *>::iterator ret;
do
{
ret=CheckInList(nodeToTest,iStart,iEnd);
if(completed())
return iEnd;
+ ii++;
}
- while(ret==iEnd);
+ while(ret==iEnd && ii<szMax);
+ if(ii==szMax)// here a protection against agressive users of IntersectMeshes of invalid input meshes
+ throw INTERP_KERNEL::Exception("QuadraticPolygon::fillAsMuchAsPossibleWith : Something is invalid with input polygons !");
return ret;
}
return iter;
return iEnd;
}
+
+void QuadraticPolygon::ComputeResidual(const QuadraticPolygon& pol1, const std::set<Edge *>& notUsedInPol1, const std::set<Edge *>& edgesInPol2OnBoundary, const std::map<INTERP_KERNEL::Node *,int>& mapp, int offset, int idThis,
+ std::vector<double>& addCoordsQuadratic, std::vector<int>& conn, std::vector<int>& connI, std::vector<int>& nb1, std::vector<int>& nb2)
+{
+ pol1.initLocations();
+ for(std::set<Edge *>::const_iterator it9=notUsedInPol1.begin();it9!=notUsedInPol1.end();it9++)
+ { (*it9)->initLocs(); (*it9)->declareOn(); }
+ for(std::set<Edge *>::const_iterator itA=edgesInPol2OnBoundary.begin();itA!=edgesInPol2OnBoundary.end();itA++)
+ { (*itA)->initLocs(); (*itA)->declareIn(); }
+ ////
+ std::set<Edge *> notUsedInPol1L(notUsedInPol1);
+ IteratorOnComposedEdge it(const_cast<QuadraticPolygon *>(&pol1));
+ int sz=pol1.size();
+ std::list<QuadraticPolygon *> pol1Zip;
+ if(pol1.size()==(int)notUsedInPol1.size() && edgesInPol2OnBoundary.empty())
+ {
+ pol1.appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
+ return ;
+ }
+ while(!notUsedInPol1L.empty())
+ {
+ for(int i=0;i<sz && (it.current()->getStartNode()->getLoc()!=IN_1 || it.current()->getLoc()!=FULL_ON_1);i++)
+ it.nextLoop();
+ if(it.current()->getStartNode()->getLoc()!=IN_1 || it.current()->getLoc()!=FULL_ON_1)
+ throw INTERP_KERNEL::Exception("Presence of a target polygon fully included in source polygon ! The partition of this leads to a non simply connex cell (with hole) ! Impossible ! Such resulting cell cannot be stored in MED cell format !");
+ QuadraticPolygon *tmp1=new QuadraticPolygon;
+ do
+ {
+ Edge *ee=it.current()->getPtr();
+ if(ee->getLoc()==FULL_ON_1)
+ {
+ ee->incrRef(); notUsedInPol1L.erase(ee);
+ tmp1->pushBack(new ElementaryEdge(ee,it.current()->getDirection()));
+ }
+ it.nextLoop();
+ }
+ while(it.current()->getStartNode()->getLoc()!=IN_1 && !notUsedInPol1L.empty());
+ pol1Zip.push_back(tmp1);
+ }
+ ////
+ std::list<QuadraticPolygon *> retPolsUnderContruction;
+ std::list<Edge *> edgesInPol2OnBoundaryL(edgesInPol2OnBoundary.begin(),edgesInPol2OnBoundary.end());
+ std::map<QuadraticPolygon *, std::list<QuadraticPolygon *> > pol1ZipConsumed;
+ std::size_t maxNbOfTurn=edgesInPol2OnBoundaryL.size(),nbOfTurn=0,iiMNT=0;
+ for(std::list<QuadraticPolygon *>::const_iterator itMNT=pol1Zip.begin();itMNT!=pol1Zip.end();itMNT++,iiMNT++)
+ nbOfTurn+=(*itMNT)->size();
+ maxNbOfTurn=maxNbOfTurn*nbOfTurn; maxNbOfTurn*=maxNbOfTurn;
+ nbOfTurn=0;
+ while(nbOfTurn<maxNbOfTurn && ((!pol1Zip.empty() || !edgesInPol2OnBoundaryL.empty())))
+ {
+ for(std::list<QuadraticPolygon *>::iterator it1=retPolsUnderContruction.begin();it1!=retPolsUnderContruction.end();)
+ {
+ if((*it1)->getStartNode()==(*it1)->getEndNode())
+ {
+ it1++;
+ continue;
+ }
+ Node *curN=(*it1)->getEndNode();
+ bool smthHappened=false;
+ for(std::list<Edge *>::iterator it2=edgesInPol2OnBoundaryL.begin();it2!=edgesInPol2OnBoundaryL.end();)
+ {
+ if(curN==(*it2)->getStartNode())
+ { (*it2)->incrRef(); (*it1)->pushBack(new ElementaryEdge(*it2,true)); curN=(*it2)->getEndNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
+ else if(curN==(*it2)->getEndNode())
+ { (*it2)->incrRef(); (*it1)->pushBack(new ElementaryEdge(*it2,false)); curN=(*it2)->getStartNode(); smthHappened=true; it2=edgesInPol2OnBoundaryL.erase(it2); }
+ else
+ it2++;
+ }
+ if(smthHappened)
+ {
+ for(std::list<QuadraticPolygon *>::iterator it3=pol1Zip.begin();it3!=pol1Zip.end();)
+ {
+ if(curN==(*it3)->getStartNode())
+ {
+ for(std::list<ElementaryEdge *>::const_iterator it4=(*it3)->_sub_edges.begin();it4!=(*it3)->_sub_edges.end();it4++)
+ { (*it4)->getPtr()->incrRef(); bool dir=(*it4)->getDirection(); (*it1)->pushBack(new ElementaryEdge((*it4)->getPtr(),dir)); }
+ smthHappened=true;
+ pol1ZipConsumed[*it1].push_back(*it3);
+ curN=(*it3)->getEndNode();
+ it3=pol1Zip.erase(it3);
+ }
+ else
+ it3++;
+ }
+ }
+ if(!smthHappened)
+ {
+ for(std::list<ElementaryEdge *>::const_iterator it5=(*it1)->_sub_edges.begin();it5!=(*it1)->_sub_edges.end();it5++)
+ {
+ Edge *ee=(*it5)->getPtr();
+ if(edgesInPol2OnBoundary.find(ee)!=edgesInPol2OnBoundary.end())
+ edgesInPol2OnBoundaryL.push_back(ee);
+ }
+ for(std::list<QuadraticPolygon *>::iterator it6=pol1ZipConsumed[*it1].begin();it6!=pol1ZipConsumed[*it1].end();it6++)
+ pol1Zip.push_front(*it6);
+ pol1ZipConsumed.erase(*it1);
+ delete *it1;
+ it1=retPolsUnderContruction.erase(it1);
+ }
+ }
+ if(!pol1Zip.empty())
+ {
+ QuadraticPolygon *tmp=new QuadraticPolygon;
+ QuadraticPolygon *first=*(pol1Zip.begin());
+ for(std::list<ElementaryEdge *>::const_iterator it4=first->_sub_edges.begin();it4!=first->_sub_edges.end();it4++)
+ { (*it4)->getPtr()->incrRef(); bool dir=(*it4)->getDirection(); tmp->pushBack(new ElementaryEdge((*it4)->getPtr(),dir)); }
+ pol1ZipConsumed[tmp].push_back(first);
+ retPolsUnderContruction.push_back(tmp);
+ pol1Zip.erase(pol1Zip.begin());
+ }
+ nbOfTurn++;
+ }
+ if(nbOfTurn==maxNbOfTurn)
+ {
+ std::ostringstream oss; oss << "Error during reconstruction of residual of cell ! It appears that either source or/and target mesh is/are not conform !";
+ oss << " Number of turns is = " << nbOfTurn << " !";
+ throw INTERP_KERNEL::Exception(oss.str().c_str());
+ }
+ for(std::list<QuadraticPolygon *>::iterator it1=retPolsUnderContruction.begin();it1!=retPolsUnderContruction.end();it1++)
+ {
+ if((*it1)->getStartNode()==(*it1)->getEndNode())
+ {
+ (*it1)->appendCrudeData(mapp,0.,0.,1.,offset,addCoordsQuadratic,conn,connI); nb1.push_back(idThis); nb2.push_back(-1);
+ for(std::list<QuadraticPolygon *>::iterator it6=pol1ZipConsumed[*it1].begin();it6!=pol1ZipConsumed[*it1].end();it6++)
+ delete *it6;
+ delete *it1;
+ }
+ }
+}