]> SALOME platform Git repositories - modules/med.git/commitdiff
Salome HOME
Addition of MEDCouplingUMesh::colinearize2D
authorgeay <anthony.geay@cea.fr>
Tue, 1 Apr 2014 10:56:44 +0000 (12:56 +0200)
committergeay <anthony.geay@cea.fr>
Tue, 1 Apr 2014 10:56:44 +0000 (12:56 +0200)
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdge.hxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdgeArcCircle.cxx
src/INTERP_KERNEL/Geometric2D/InterpKernelGeo2DEdgeArcCircle.hxx
src/MEDCoupling/MEDCouplingUMesh.cxx
src/MEDCoupling/MEDCouplingUMesh.hxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest.py
src/MEDCoupling_Swig/MEDCouplingCommon.i

index dd67a8000c3c1ae7786a66d4a7a3a02d69d08bca..1f05e54d369d6f5c891152a9e30c32fab0d1bef0 100644 (file)
@@ -148,6 +148,7 @@ namespace INTERP_KERNEL
   public:
     virtual ~EdgeIntersector() { }
     virtual bool keepOrder() const = 0;
+    virtual bool areColinears() const = 0;
     //!to call only if 'areOverlapped' have been set to true when areOverlappedOrOnlyColinears was called
     virtual bool haveTheySameDirection() const = 0;
     //!to call only if 'areOverlapped' have been set to true when areOverlappedOrOnlyColinears was called
index def67310b6597b011b4b6fe9af85eafa2bf476fc..9511658fee03d513d63144ad092e44cc4f714642 100644 (file)
@@ -38,6 +38,14 @@ bool ArcCArcCIntersector::haveTheySameDirection() const
   return (getE1().getAngle()>0. &&  getE2().getAngle()>0.) || (getE1().getAngle()<0. &&  getE2().getAngle()<0.);
 }
 
+bool ArcCArcCIntersector::areColinears() const
+{
+  double radiusL,radiusB;
+  double centerL[2],centerB[2];
+  double tmp,cst;
+  return internalAreColinears(getE1(),getE2(),tmp,cst,radiusL,centerL,radiusB,centerB);
+}
+
 /*!
  * Precondition 'start' and 'end' are on the same curve than this.
  */
@@ -108,10 +116,10 @@ double ArcCArcCIntersector::getAngle(Node *node) const
   return EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect(((*node)[0]-getE1().getCenter()[0])/getE1().getRadius(),((*node)[1]-getE1().getCenter()[1])/getE1().getRadius());
 }
 
-bool ArcCArcCIntersector::areArcsOverlapped(const EdgeArcCircle& a1, const EdgeArcCircle& a2)
+bool ArcCArcCIntersector::internalAreColinears(const EdgeArcCircle& a1, const EdgeArcCircle& a2, double& distBetweenCenters, double& cst,
+                                               double& radiusL, double centerL[2], double& radiusB, double centerB[2])
 {
-  double centerL[2],radiusL,angle0L,angleL;
-  double centerB[2],radiusB;
+  double angle0L,angleL;
   double lgth1=fabs(a1.getAngle()*a1.getRadius());
   double lgth2=fabs(a2.getAngle()*a2.getRadius());
   if(lgth1<lgth2)
@@ -125,24 +133,28 @@ bool ArcCArcCIntersector::areArcsOverlapped(const EdgeArcCircle& a1, const EdgeA
       a1.getCenter(centerB); radiusB=a1.getRadius();
     }
   // dividing from the begining by radiusB^2 to keep precision
-  double tmp=Node::distanceBtw2PtSq(centerL,centerB);
-  double cst=tmp/(radiusB*radiusB);
+  distBetweenCenters=Node::distanceBtw2PtSq(centerL,centerB);
+  cst=distBetweenCenters/(radiusB*radiusB);
   cst+=radiusL*radiusL/(radiusB*radiusB);
-  if(!Node::areDoubleEqualsWP(cst,1.,2.))
+  return Node::areDoubleEqualsWP(cst,1.,2.);
+}
+
+bool ArcCArcCIntersector::areArcsOverlapped(const EdgeArcCircle& a1, const EdgeArcCircle& a2)
+{
+  double radiusL,radiusB;
+  double centerL[2],centerB[2];
+  double tmp(0.),cst(0.);
+  if(!internalAreColinears(a1,a2,tmp,cst,radiusL,centerL,radiusB,centerB))
     return false;
   //
+  double angle0L,angleL;
   Bounds *merge=a1.getBounds().nearlyAmIIntersectingWith(a2.getBounds());
   merge->getInterceptedArc(centerL,radiusL,angle0L,angleL);
   delete merge;
   //
   tmp=sqrt(tmp);
   if(Node::areDoubleEqualsWP(tmp,0.,1/(10*std::max(radiusL,radiusB))))
-    {
-      if(Node::areDoubleEquals(radiusL,radiusB))
-        return true;
-      else
-        return false;
-    }
+    return Node::areDoubleEquals(radiusL,radiusB);
   double phi=EdgeArcCircle::GetAbsoluteAngleOfNormalizedVect((centerL[0]-centerB[0])/tmp,(centerL[1]-centerB[1])/tmp);
   double cst2=2*radiusL*tmp/(radiusB*radiusB);
   double cmpContainer[4];
@@ -323,6 +335,14 @@ void ArcCSegIntersector::areOverlappedOrOnlyColinears(const Bounds *whereToFind,
     obviousNoIntersection=true;   
 }
 
+/*!
+ * By construction, no chance that an arc of circle and line to be colinear.
+ */
+bool ArcCSegIntersector::areColinears() const
+{
+  return false;
+}
+
 void ArcCSegIntersector::getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const
 {
   throw Exception("Internal error. Should never been called : no overlapping possible between arc of circle and a segment.");
index 2732a80f7dc9d3a6a64b6849d9b5822ea34efacd..8153150a499b19a081bb054a2dcd1931f3214367 100644 (file)
@@ -31,12 +31,14 @@ namespace INTERP_KERNEL
   public:
     ArcCArcCIntersector(const EdgeArcCircle& e1, const EdgeArcCircle& e2);
     bool haveTheySameDirection() const;
+    bool areColinears() const;
     void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const;
     void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped);
     std::list< IntersectElement > getIntersectionsCharacteristicVal() const;
   private:
     //! return angle in ]-Pi;Pi[ - 'node' must be on curve of '_e1'
     double getAngle(Node *node) const;
+    static bool internalAreColinears(const EdgeArcCircle& a1, const EdgeArcCircle& a2, double& distBetweenCenters, double& cst, double& radiusL, double centerL[2], double& raduisB, double centerB[2]);
     static bool areArcsOverlapped(const EdgeArcCircle& a1, const EdgeArcCircle& a2);
   private:
     const EdgeArcCircle& getE1() const { return (const EdgeArcCircle&)_e1; }
@@ -50,6 +52,7 @@ namespace INTERP_KERNEL
   public:
     ArcCSegIntersector(const EdgeArcCircle& e1, const EdgeLin& e2, bool reverse=true);
     //virtual overloading
+    bool areColinears() const;
     void getPlacements(Node *start, Node *end, TypeOfLocInEdge& whereStart, TypeOfLocInEdge& whereEnd, MergePoints& commonNode) const;
     void areOverlappedOrOnlyColinears(const Bounds *whereToFind, bool& obviousNoIntersection, bool& areOverlapped);
     std::list< IntersectElement > getIntersectionsCharacteristicVal() const;
index 0f1dee158dbae13f46a138c7d659f93e40378134..f34a8f2f4007f6984f3b965d78b9d27828778b87 100644 (file)
@@ -4458,6 +4458,7 @@ void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps)
  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
  *
  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
+ * \sa MEDCouplingUMesh::colinearize2D
  */
 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
 {
@@ -8989,6 +8990,62 @@ DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
   return ret.retn();
 }
 
+/*!
+ * This non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
+ * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
+ * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
+ * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
+ * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
+ * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
+ *
+ * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
+ * using new instance, idem for coordinates.
+ *
+ * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
+ * 
+ * \return DataArrayInt  * - The list of cellIds in \a this that have at least one edge colinearized.
+ *
+ * \throw If \a this is not coherent.
+ * \throw If \a this has not spaceDim equal to 2.
+ * \throw If \a this has not meshDim equal to 2.
+ * 
+ * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
+ */
+DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
+{
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
+  checkCoherency();
+  if(getSpaceDimension()!=2 || getMeshDimension()!=2)
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
+  INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
+  INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
+  int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
+  const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
+  MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
+  MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
+  const double *coords(_coords->begin());
+  int *newciptr(newci->getPointer());
+  for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
+    {
+      if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
+        ret->pushBackSilent(i);
+      newciptr[1]=newc->getNumberOfTuples();
+    }
+  //
+  if(ret->empty())
+    return ret.retn();
+  if(!appendedCoords->empty())
+    {
+      appendedCoords->rearrange(2);
+      MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
+      //non const part
+      setCoords(newCoords);
+    }
+  //non const part
+  setConnectivity(newc,newci,true);
+  return ret.retn();
+}
+
 /*!
  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
  * It builds the descending connectivity of the two meshes, and then using a binary tree
@@ -10097,7 +10154,7 @@ void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataAr
   _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
 }
 
-int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
+int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
 {
   if(id!=-1)
     return id;
@@ -10111,6 +10168,142 @@ int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, in
     }
 }
 
+/// @cond INTERNAL
+
+void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
+{
+  int tmp[3];
+  int trueStart(start>=0?start:nbOfEdges+start);
+  tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
+  newConnOfCell->insertAtTheEnd(tmp,tmp+3);
+  if(linOrArc)
+    {
+      if(stp-start>1)
+        {
+          int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
+          InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
+          middles.push_back(tmp3+offset);
+        }
+      else
+        middles.push_back(connBg[trueStart+nbOfEdges]);
+    }
+}
+
+void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
+{
+  int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
+  newConnOfCell->pushBackSilent(tmpEnd);
+  if(linOrArc)
+    {
+      if(stp-start>1)
+        {
+          int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
+          InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
+          middles.push_back(tmp3+offset);
+        }
+      else
+        middles.push_back(connBg[start+nbOfEdges]);
+    }
+}
+
+void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
+{
+  if(linOrArc)
+    {
+      if(stp-start>1)
+        {
+          int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
+          int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
+          InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
+          middles.push_back(tmp3+offset);
+        }
+      else
+        middles.push_back(connBg[start+nbOfEdges]);
+    }
+}
+
+/// @cond INTERNAL
+
+/*!
+ * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
+ * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
+ */
+bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
+{
+  std::size_t sz(std::distance(connBg,connEnd));
+  if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
+    throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
+  sz--;
+  INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
+  const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
+  unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
+  int posBaseElt(0),posEndElt(0),nbOfTurn(0);
+  INTERP_KERNEL::NormalizedCellType typeOfSon;
+  std::vector<int> middles;
+  bool ret(false);
+  for(;nbOfHit<nbs;nbOfTurn++)
+    {
+      cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
+      std::map<INTERP_KERNEL::Node *,int> m;
+      INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
+      posEndElt++;
+      nbOfHit++;
+      unsigned endI(nbs-nbOfHit);
+      for(unsigned i=0;i<endI;i++)
+        {
+          cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
+          INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
+          INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
+          bool isColinear(eint->areColinears());
+          if(isColinear)
+            {
+              nbOfHit++;
+              posEndElt++;
+              ret=true;
+            }
+          delete eint;
+          eCand->decrRef();
+          if(!isColinear)
+            {
+              if(nbOfTurn==0)
+                {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
+                  unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
+                  for(unsigned ii=0;ii<endII;ii++)
+                    {
+                      cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
+                      eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
+                      eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
+                      isColinear=eint->areColinears();
+                      if(isColinear)
+                        {
+                          nbOfHit++;
+                          posBaseElt--;
+                          ret=true;
+                        }
+                      delete eint;
+                      eCand->decrRef();
+                    }
+                }
+              break;
+            }
+        }
+      //push [posBaseElt,posEndElt) in newConnOfCell using e
+      if(nbOfTurn==0)
+        EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
+      else if(nbOfHit!=nbs)
+        EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
+      else
+        EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
+      posBaseElt=posEndElt;
+      for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
+        (*it).first->decrRef();
+      e->decrRef();
+    }
+  if(!middles.empty())
+    newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
+  return ret;
+}
+
 /*!
  * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
  *
@@ -10152,12 +10345,12 @@ int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const Data
           for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
             {
               cPtr[1]=subPtr[offset2+k];
-              cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
+              cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
             }
           int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
           if(j!=sz-1)
             { cPtr[1]=tmpEnd; }
-          cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
+          cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
         }
       prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
       ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
index 06d472ef9883838a9383607477a46aac162ded79..62c337bbc628cec2534d6b783dc4c9365c6a56e3 100644 (file)
@@ -220,6 +220,7 @@ namespace ParaMEDMEM
     MEDCOUPLING_EXPORT DataArrayDouble *getPartBarycenterAndOwner(const int *begin, const int *end) const;
     MEDCOUPLING_EXPORT DataArrayDouble *computePlaneEquationOf3DFaces() const;
     MEDCOUPLING_EXPORT DataArrayInt *conformize2D(double eps);
+    MEDCOUPLING_EXPORT DataArrayInt *colinearize2D(double eps);
     MEDCOUPLING_EXPORT int split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt=0, const DataArrayInt *midOptI=0);
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *Build0DMeshFromCoords(DataArrayDouble *da);
     MEDCOUPLING_EXPORT static MEDCouplingUMesh *MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2);
@@ -323,6 +324,7 @@ namespace ParaMEDMEM
                                     const int *desc, const int *descIndx, DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception);
     void split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI);
     int split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI);
+    static bool Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords);
   public:
     MEDCOUPLING_EXPORT static DataArrayInt *ComputeRangesFromTypeDistribution(const std::vector<int>& code);
     MEDCOUPLING_EXPORT static const int N_MEDMEM_ORDER=24;
index 2ecaa6d5b444da57aa5d82721a33472bc613680b..07152f4782f2cd3561d66aa18b4ab9d12015f6b7 100644 (file)
@@ -14530,6 +14530,73 @@ class MEDCouplingBasicsTest(unittest.TestCase):
         self.assertTrue(MEDCouplingStructuredMesh.Build1GTNodalConnectivityOfSubLevelMesh([3,7]).isEqual(DataArrayInt([0,3,3,6,6,9,9,12,12,15,15,18,1,4,4,7,7,10,10,13,13,16,16,19,2,5,5,8,8,11,11,14,14,17,17,20,0,1,1,2,3,4,4,5,6,7,7,8,9,10,10,11,12,13,13,14,15,16,16,17,18,19,19,20])))
         pass
 
+    def testSwig2Colinearize2D1(self):
+        coo=DataArrayDouble([-5.,0.,-1.,0.,4.,3.,7.,0.,1.,6.,1.,0.,-3.,0.,6.,1.,5.,0.,3.,0.],10,2)
+        #
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo) ; m.allocateCells()
+        m.insertNextCell(NORM_POLYGON,[5,9,8,3,7,2,4,0,6,1])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([5,0,3,4])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,4])))
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([5,0,3,4])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,4])))
+        #
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo) ; m.allocateCells()
+        m.insertNextCell(NORM_POLYGON,[8,3,7,2,4,0,6,1,5,9])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([5,0,3,4])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,4])))
+        #
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo) ; m.allocateCells()
+        m.insertNextCell(NORM_POLYGON,[3,7,2,4,0,6,1,5,9,8])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([5,3,4,0])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,4])))
+        #
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo) ; m.allocateCells()
+        m.insertNextCell(NORM_POLYGON,[4,0,6,1,5,9,8,3,7,2,])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([5,4,0,3])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,4])))
+        ## false quadratic
+        coo2=DataArrayDouble([(-5,0),(-1,0),(4,3),(7,0),(1,6),(1,0),(-3,0),(6,1),(5,0),(3,0),(2,0),(4,0),(6,0),(6.5,0.5),(5,2),(2.5,4.5),(-2,3),(-4,0),(-2,0),(0,0)])
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo2) ; m.allocateCells()
+        m.insertNextCell(NORM_QPOLYG,[5,9,8,3,7,2,4,0,6,1,10,11,12,13,14,15,16,17,18,19])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertNotEqual(refPtr,m.getCoords().getHiddenCppPointer())#not same coordinates here
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(coo2.isEqual(m.getCoords()[:20],1e-12))
+        self.assertTrue(m.getCoords()[20:].isEqual(DataArrayDouble([(1.,0.),(4.,3.)]),1e-12))
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([32,0,3,4,20,21,16])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,7])))
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([])))
+        self.assertEqual(refPtr,m.getCoords().getHiddenCppPointer())
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([32,0,3,4,20,21,16])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,7])))
+        # mix of quadratic and linear inside a QPOLYG cell
+        coo2=DataArrayDouble([(-5,0),(-1,0),(7.,6.),(7,0),(1,6),(1,0),(-3,0),(8.2426406871192839,3),(5,0),(3,0),  (2,0),(4,0),(6,0),(7.9196888946291288,1.3764116995614091),(7.9196888946291288,4.6235883004385911),(4,7.2426406871192848),(-2,3),(-4,0),(-2,0),(0,0)])
+        m=MEDCouplingUMesh("mesh",2) ; m.setCoords(coo2) ; m.allocateCells()
+        m.insertNextCell(NORM_QPOLYG,[5,9,8,3,7,2,4,0,6,1,10,11,12,13,14,15,16,17,18,19])
+        refPtr=m.getCoords().getHiddenCppPointer()
+        self.assertTrue(m.colinearize2D(1e-12).isEqual(DataArrayInt([0])))
+        self.assertNotEqual(refPtr,m.getCoords().getHiddenCppPointer())#not same coordinates here
+        self.assertTrue(coo2.isEqual(m.getCoords()[:20],1e-12))
+        self.assertTrue(m.getCoords()[20:].isEqual(DataArrayDouble([(1.,0.),(7.,6.)]),1e-12))
+        self.assertTrue(m.getNodalConnectivity().isEqual(DataArrayInt([32,0,3,4,20,21,16])))
+        self.assertTrue(m.getNodalConnectivityIndex().isEqual(DataArrayInt([0,7])))
+        pass
+
     def setUp(self):
         pass
     pass
index e7ebdf73a8f41397c9d7fcbd9bb0daba5343a5b8..46c499adda99ede69de2b505bafc78c2c39bac1d 100644 (file)
@@ -239,6 +239,7 @@ using namespace INTERP_KERNEL;
 %newobject ParaMEDMEM::MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed;
 %newobject ParaMEDMEM::MEDCouplingUMesh::buildNewNumberingFromCommNodesFrmt;
 %newobject ParaMEDMEM::MEDCouplingUMesh::conformize2D;
+%newobject ParaMEDMEM::MEDCouplingUMesh::colinearize2D;
 %newobject ParaMEDMEM::MEDCouplingUMesh::rearrange2ConsecutiveCellTypes;
 %newobject ParaMEDMEM::MEDCouplingUMesh::sortCellsInMEDFileFrmt;
 %newobject ParaMEDMEM::MEDCouplingUMesh::getRenumArrForMEDFileFrmt;
@@ -1505,6 +1506,7 @@ namespace ParaMEDMEM
     MEDCouplingUMesh *buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception);
     //tools
     DataArrayInt *conformize2D(double eps) throw(INTERP_KERNEL::Exception);
+    DataArrayInt *colinearize2D(double eps) throw(INTERP_KERNEL::Exception);
     void shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception);
     std::vector<bool> getQuadraticStatus() const throw(INTERP_KERNEL::Exception);
     DataArrayInt *findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception);