]> SALOME platform Git repositories - tools/medcoupling.git/commitdiff
Salome HOME
Edges OK. Now ready for one last optim.
authorabn <adrien.bruneton@cea.fr>
Mon, 20 Mar 2017 15:33:29 +0000 (16:33 +0100)
committerabn <adrien.bruneton@cea.fr>
Mon, 20 Mar 2017 15:33:29 +0000 (16:33 +0100)
src/MEDCoupling/MEDCouplingUMesh_intersection.cxx
src/MEDCoupling_Swig/MEDCouplingBasicsTest5.py
src/MEDCoupling_Swig/MEDCouplingIntersectTest.py

index 940c9199b222d008a2790312e2a455ea58c1ef4d..c3c3459152888beadecad07068661951145c8ad0 100644 (file)
@@ -2006,7 +2006,7 @@ DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
  */
 bool MEDCouplingUMesh::OrderPointsAlongLine(const double * coo, int startNode, int endNode,
                                             const int * c, const int * cI, const int *idsBg, const int *endBg,
-                                            std::vector<int> & pointIds)
+                                            std::vector<int> & pointIds/*, std::vector<int> & hitSegs*/)
 {
   using namespace std;
 
@@ -2032,10 +2032,8 @@ bool MEDCouplingUMesh::OrderPointsAlongLine(const double * coo, int startNode, i
       const int idx = (*it).second;
       if (!go)
         {
-          if (idx == startNode)
-            go = 1;
-          if (idx == endNode)
-            go = 2;
+          if (idx == startNode) go = 1;
+          if (idx == endNode)   go = 2;
           continue;
         }
       if (idx == endNode || idx == startNode)
@@ -2064,7 +2062,7 @@ void MEDCouplingUMesh::ReplaceEdgeInFace(const int * sIdxConn, const int * sIdxC
   if (endPos == shortEnd)
     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ReplaceEdgeInFace: internal error, should never happen!");
   int d = distance(startPos, endPos);
-  if (d > 0 || d == (dst-1))
+  if (d == 1 || d == (1-dst)) // don't use modulo, for neg numbers, result is implementation defined ...
     modifiedFace.insert(++startPos, insidePoints.begin(), insidePoints.end());
   else
     modifiedFace.insert(++endPos, insidePoints.rbegin(), insidePoints.rend());
@@ -2109,9 +2107,6 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
   const double * coo(_coords->begin());
   MCAuto<DataArrayInt> ret(DataArrayInt::New());
 
-  std::cout << "BEGIN\n";
-  std::cout << connSla->simpleRepr();
-
   {
     /*************************
      *  STEP 1  -- faces
@@ -2148,16 +2143,16 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
 
     for( vector<pair<double,int>>::const_iterator it = S.begin(); it != S.end(); it++)
       {
-        int sIdx = (*it).second;
-        if (hit[sIdx]) continue;
+        int faceIdx = (*it).second;
+        if (hit[faceIdx]) continue;
 
         vector<int> candidates, cands2;
-        myTree.getIntersectingElems(bbox+sIdx*2*SPACEDIM,candidates);
+        myTree.getIntersectingElems(bbox+faceIdx*2*SPACEDIM,candidates);
         // Keep only candidates whose normal matches the normal of current face
         for(vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
           {
-            bool col = INTERP_KERNEL::isColinear3D(normalsP + sIdx*SPACEDIM, normalsP + *(it)*SPACEDIM, eps);
-            if (*it != sIdx && col)
+            bool col = INTERP_KERNEL::isColinear3D(normalsP + faceIdx*SPACEDIM, normalsP + *(it)*SPACEDIM, eps);
+            if (*it != faceIdx && col)
               cands2.push_back(*it);
           }
         if (!cands2.size())
@@ -2165,11 +2160,11 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
 
         // Now rotate, and match barycenters -- this is where we will bring Intersect2DMeshes later
         INTERP_KERNEL::TranslationRotationMatrix rotation;
-        INTERP_KERNEL::TranslationRotationMatrix::Rotate3DTriangle(coo+SPACEDIM*(cDesc[cIDesc[sIdx]+1]),
-                                                                   coo+SPACEDIM*(cDesc[cIDesc[sIdx]+2]),
-                                                                   coo+SPACEDIM*(cDesc[cIDesc[sIdx]+3]), rotation);
+        INTERP_KERNEL::TranslationRotationMatrix::Rotate3DTriangle(coo+SPACEDIM*(cDesc[cIDesc[faceIdx]+1]),
+                                                                   coo+SPACEDIM*(cDesc[cIDesc[faceIdx]+2]),
+                                                                   coo+SPACEDIM*(cDesc[cIDesc[faceIdx]+3]), rotation);
 
-        MCAuto<MEDCouplingUMesh> mPartRef(mDesc->buildPartOfMySelfSlice(sIdx, sIdx+1,1,false));  // false=zipCoords is called
+        MCAuto<MEDCouplingUMesh> mPartRef(mDesc->buildPartOfMySelfSlice(faceIdx, faceIdx+1,1,false));  // false=zipCoords is called
         MCAuto<MEDCouplingUMesh> mPartCand(mDesc->buildPartOfMySelf(&cands2[0], &cands2[0]+cands2.size(), false)); // false=zipCoords is called
         double * cooPartRef(mPartRef->_coords->getPointer());
         double * cooPartCand(mPartCand->_coords->getPointer());
@@ -2177,16 +2172,17 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
           rotation.transform_vector(cooPartRef+SPACEDIM*ii);
         for (int ii = 0; ii < mPartCand->_coords->getNumberOfTuples(); ii++)
           rotation.transform_vector(cooPartCand+SPACEDIM*ii);
-        double ze_z = cooPartRef[2];
 
         // Localize faces in 2D thanks to barycenters
         MCAuto<DataArrayDouble> baryPart = mPartCand->computeCellCenterOfMass();
         vector<int> compo; compo.push_back(2);
         MCAuto<DataArrayDouble> baryPartZ = baryPart->keepSelectedComponents(compo);
-        MCAuto<DataArrayInt> idsGoodPlane = baryPartZ->findIdsInRange(ze_z-eps, ze_z+eps);
+        MCAuto<DataArrayInt> idsGoodPlane = baryPartZ->findIdsInRange(-eps, +eps);
         if (!idsGoodPlane->getNumberOfTuples())
           continue;
 
+        baryPart = baryPart->selectByTupleId(*idsGoodPlane);
+
         compo[0] = 0; compo.push_back(1);
         MCAuto<DataArrayDouble> baryPartXY = baryPart->keepSelectedComponents(compo);
         mPartRef->changeSpaceDimension(2,0.0);
@@ -2200,7 +2196,11 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
         {
           MCAuto<DataArrayInt> tmp = dsi->findIdsInRange(0, 2);
           if (tmp->getNumberOfTuples() != dsi->getNumberOfTuples())
-            throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize3D: Non expected non-conformity. Only simple (=partition-like) non-conformities are handled.");
+            {
+              ostringstream oss;
+              oss << "MEDCouplingUMesh::conformize3D: Non expected non-conformity. Only simple (=partition-like) non-conformities are handled. Face #" << faceIdx << " violates this condition!";
+              throw INTERP_KERNEL::Exception(oss.str());
+            }
         }
 
         MCAuto<DataArrayInt> ids = dsi->findIdsEqual(1);
@@ -2209,28 +2209,29 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
           continue;
 
         double checkSurf=0.0;
+        const int * idsGoodPlaneP(idsGoodPlane->begin());
         for (const int * ii = ids->begin(); ii != ids->end(); ii++)
           {
-            int faceIdx = cands2[idsGoodPlane->begin()[*ii]];
+            int faceIdx = cands2[idsGoodPlaneP[*ii]];
             hit[faceIdx] = true;
             checkSurf += surfs->begin()[faceIdx];
           }
-        if (fabs(checkSurf - surfs->begin()[sIdx]) > eps)
+        if (fabs(checkSurf - surfs->begin()[faceIdx]) > eps)
           {
             ostringstream oss;
-            oss << "MEDCouplingUMesh::conformize3D: Non expected non-conformity. Only simple (=partition-like) non-conformities are handled. Face #" << sIdx << " violates this condition!";
+            oss << "MEDCouplingUMesh::conformize3D: Non expected non-conformity. Only simple (=partition-like) non-conformities are handled. Face #" << faceIdx << " violates this condition!";
             throw INTERP_KERNEL::Exception(oss.str());
           }
 
         // For all polyhedrons using this face, replace connectivity:
         vector<int> polyIndices, packsIds, facePack;
-        for (int ii=revDescIP[sIdx]; ii < revDescIP[sIdx+1]; ii++)
+        for (int ii=revDescIP[faceIdx]; ii < revDescIP[faceIdx+1]; ii++)
           polyIndices.push_back(revDescP[ii]);
         ret->pushBackValsSilent(polyIndices.data(),polyIndices.data()+polyIndices.size());
 
         // Current face connectivity
-        const int * sIdxConn = cDesc + cIDesc[sIdx] + 1;
-        const int * sIdxConnE = cDesc + cIDesc[sIdx+1];
+        const int * sIdxConn = cDesc + cIDesc[faceIdx] + 1;
+        const int * sIdxConnE = cDesc + cIDesc[faceIdx+1];
         connSla->findPackIds(polyIndices, sIdxConn, sIdxConnE, packsIds);
         // Deletion of old faces
         int jj=0;
@@ -2238,7 +2239,7 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
           {
             if (packsIds[jj] == -1)
               // The below should never happen - if a face is used several times, with a different layout of the nodes
-              // it means that is is already conform, so it is not hit by the algorithm. The algorithm only hits
+              // it means that is is already conform, so it is *not* hit by the algorithm. The algorithm only hits
               // faces which are actually used only once, by a single cell. This is different for edges below.
               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize3D: Could not find face in connectivity! Internal error.");
             else
@@ -2250,24 +2251,19 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
             // Build pack from the face to insert:
             int faceIdx = cands2[idsGoodPlane->getIJ(*ii,0)];
             int facePack2Sz;
-//            vector<int> toto;
-//            connSlaDesc->getSimplePackSafe(faceIdx, toto);
             const int * facePack2 = connSlaDesc->getSimplePackSafePtr(faceIdx, facePack2Sz); // contains the type!
             // Insert it in all hit polyhedrons:
             for (vector<int>::const_iterator it=polyIndices.begin(); it!=polyIndices.end(); ++it)
               connSla->pushBackPack(*it, facePack2+1, facePack2+facePack2Sz);  // without the type
           }
       }
-  }
+  }  // end step1
 
   // Set back modified connectivity
   MCAuto<DataArrayInt> cAuto; cAuto.takeRef(_nodal_connec);
   MCAuto<DataArrayInt> cIAuto; cIAuto.takeRef(_nodal_connec_index);
   connSla->convertToPolyhedronConn(cAuto, cIAuto);
 
-  std::cout << "BEFORE STEP2\n";
-  std::cout << connSla->simpleRepr();
-
   {
     /************************
      *  STEP 2 -- edges
@@ -2275,18 +2271,20 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
     // Now we have a face-conform mesh.
 
     // Recompute descending
-    MCAuto<DataArrayInt> descDNU(DataArrayInt::New()),descIDNU(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescI(DataArrayInt::New());
+    MCAuto<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),revDesc(DataArrayInt::New()),revDescI(DataArrayInt::New());
     // Rebuild desc connectivity with orientation this time!!
-    MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(descDNU,descIDNU,revDesc,revDescI));
+    MCAuto<MEDCouplingUMesh> mDesc(buildDescendingConnectivity2(desc,descI,revDesc,revDescI));
     const int *revDescIP(revDescI->getConstPointer()), *revDescP(revDesc->getConstPointer());
+    const int *descIP(descI->getConstPointer()), *descP(desc->getConstPointer());
     const int *cDesc(mDesc->getNodalConnectivity()->begin()),*cIDesc(mDesc->getNodalConnectivityIndex()->begin());
-    MCAuto<MEDCouplingSkyLineArray> connSlaDesc(MEDCouplingSkyLineArray::New(mDesc->getNodalConnectivityIndex(), mDesc->getNodalConnectivity()));
-    std::cout << "writing VTK!\n";
-    mDesc->writeVTK("/tmp/toto_desc_confInter.vtu", true);
+    MCAuto<DataArrayInt> ciDeepC(mDesc->getNodalConnectivityIndex()->deepCopy());
+    MCAuto<DataArrayInt> cDeepC(mDesc->getNodalConnectivity()->deepCopy());
+    MCAuto<MEDCouplingSkyLineArray> connSlaDesc(MEDCouplingSkyLineArray::New(ciDeepC, cDeepC));
     MCAuto<DataArrayInt> desc2(DataArrayInt::New()),descI2(DataArrayInt::New()),revDesc2(DataArrayInt::New()),revDescI2(DataArrayInt::New());
     MCAuto<MEDCouplingUMesh> mDesc2 = mDesc->buildDescendingConnectivity(desc2,descI2,revDesc2,revDescI2);
-    std::cout << "writing VTK2!\n";
-    mDesc2->writeVTK("/tmp/toto_desc2_confInter.vtu", true);
+//    std::cout << "writing!\n";
+//    mDesc->writeVTK("/tmp/toto_desc_confInter.vtu");
+//    mDesc2->writeVTK("/tmp/toto_desc2_confInter.vtu");
     const int *revDescIP2(revDescI2->getConstPointer()), *revDescP2(revDesc2->getConstPointer());
     const int *cDesc2(mDesc2->getNodalConnectivity()->begin()),*cIDesc2(mDesc2->getNodalConnectivityIndex()->begin());
     MCAuto<DataArrayDouble> bboxArr(mDesc2->getBoundingBoxForBBTree());
@@ -2352,7 +2350,7 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
           rotation.transform_vector(cooPartRef+SPACEDIM*ii);
         for (int ii = 0; ii < mPartCand->_coords->getNumberOfTuples(); ii++)
           rotation.transform_vector(cooPartCand+SPACEDIM*ii);
-        double ze_y = cooPartRef[1], ze_z = cooPartRef[2];
+
 
         // Eliminate all edges for which y or z is not null
         MCAuto<DataArrayDouble> baryPart = mPartCand->computeCellCenterOfMass();
@@ -2372,9 +2370,6 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
             mPartCand->getNodalConnectivity()->begin(), mPartCand->getNodalConnectivityIndex()->begin(),
             idsGoodLine->begin(), idsGoodLine->end(),
             /*out*/insidePoints);
-        std::cout << "edge " << eIdx << "\n";
-        for (int kk =0; kk < insidePoints.size(); kk++)
-          std::cout << "  " << nodeMapInv->begin()[insidePoints[kk]] << "\n";
 
         if (!isSplit)  // current segment remains in one piece
           continue;
@@ -2385,36 +2380,47 @@ DataArrayInt *MEDCouplingUMesh::conformize3D(double eps)
 
         vector<int> polyIndices, packsIds, facePack;
         // For each face implying this edge
-//        for (int ii=revDescIP2[eIdx]; ii < revDescIP2[eIdx+1]; ii++)
-//          {
-//            int faceIdx = abs(revDescP2[ii]) - 1;
-//
-//            //connSlaDesc
-//
-//            // Current face connectivity - find it in the original connectivity
-//            const int * sIdxConn = cDesc + cIDesc[faceIdx] + 1;
-//            const int * sIdxConnE = cDesc + cIDesc[faceIdx+1];
-//
-//            vector<int> modifiedFace;
-//            ReplaceEdgeInFace(sIdxConn, sIdxConnE, startNode, endNode, insidePoints, /*out*/modifiedFace);
-//            std::cout << "modifiedFace WAS " << eIdx << "\n";
-//            for (const int * kk =sIdxConn; kk < sIdxConnE; kk++)
-//              std::cout << "  " << *kk << "\n";
-//            std::cout << "modifiedFace IS " << eIdx << "\n";
-//            for (int kk =0; kk < modifiedFace.size(); kk++)
-//              std::cout << "  " << modifiedFace[kk] << "\n";
-//
-//            int k3 = 0;
-//            std::cout << "BEFORE\n";
-//            std::cout << connSla->simpleRepr();
-//            connSlaDesc->replacePack(faceIdx, modifiedFace);
-//            std::cout << "AFTER\n";
-//            std::cout << connSla->simpleRepr();
-//          }
+        for (int ii=revDescIP2[eIdx]; ii < revDescIP2[eIdx+1]; ii++)
+          {
+            int faceIdx = revDescP2[ii];
+            // each cell where this face is involved connectivity will be modified:
+            ret->pushBackValsSilent(revDescP + revDescIP[faceIdx], revDescP + revDescIP[faceIdx+1]);
+
+            // Current face connectivity
+            const int * sIdxConn = cDesc + cIDesc[faceIdx] + 1;
+            const int * sIdxConnE = cDesc + cIDesc[faceIdx+1];
+
+            vector<int> modifiedFace;
+            ReplaceEdgeInFace(sIdxConn, sIdxConnE, startNode, endNode, insidePoints, /*out*/modifiedFace);
+            modifiedFace.insert(modifiedFace.begin(), INTERP_KERNEL::NORM_POLYGON);
+            connSlaDesc->replaceSimplePack(faceIdx, modifiedFace.data(), modifiedFace.data()+modifiedFace.size());
+          }
       }
-  }
-  // Set back modified connectivity
-  connSla->convertToPolyhedronConn(cAuto, cIAuto);
+
+    // Rebuild 3D connectivity from descending:
+    MCAuto<MEDCouplingSkyLineArray> newConn(MEDCouplingSkyLineArray::New());
+    MCAuto<DataArrayInt> superIdx(DataArrayInt::New());  superIdx->alloc(getNumberOfCells()+1); superIdx->fillWithValue(0);
+    MCAuto<DataArrayInt> idx(DataArrayInt::New());       idx->alloc(1);                         idx->fillWithValue(0);
+    MCAuto<DataArrayInt> vals(DataArrayInt::New());      vals->alloc(0);
+    newConn->set3(superIdx, idx, vals);
+    for(int ii = 0; ii < getNumberOfCells(); ii++)
+      for (int jj=descIP[ii]; jj < descIP[ii+1]; jj++)
+        {
+          int sz, faceIdx = abs(descP[jj])-1;
+          bool orient = descP[jj]>0;
+          const int * p = connSlaDesc->getSimplePackSafePtr(faceIdx, sz);
+          if (orient)
+            newConn->pushBackPack(ii, p+1, p+sz);  // +1 to skip type
+          else
+            {
+              vector<int> rev(sz-1);
+              for (int kk=0; kk<sz-1; kk++) rev[kk]=*(p+sz-kk-1);
+              newConn->pushBackPack(ii, rev.data(), rev.data()+sz-1);
+            }
+        }
+    // And finally:
+    newConn->convertToPolyhedronConn(cAuto, cIAuto);
+  } // end step2
 
   ret = ret->buildUniqueNotSorted();
   return ret.retn();
index 0dd4550a3d6f8a2f80c774177df0e55dd7665fbc..43ef390fa7596e405273c8b985338c31f3794771 100644 (file)
@@ -3720,6 +3720,17 @@ class MEDCouplingBasicsTest5(unittest.TestCase):
         self.assertEqual(idxRef, idx.getValues())
         self.assertEqual(cRef, val.getValues())
 
+        print 'toto'
+        a, b, c = [0,0,0], [0], []
+        sla1 = MEDCouplingSkyLineArray()
+        sla1.set3(DataArrayInt(a),DataArrayInt(b),DataArrayInt(c))
+        print sla1
+        sla1.pushBackPack(0, [2,3,4])
+        print sla1
+        sla1.pushBackPack(1, [4,5,6])
+        print sla1
+        sla1.pushBackPack(0, [7,8,9])
+        print sla1
         pass
 
     def testMEDCouplingUMeshgenerateGraph(self):
index 0e2469a68d4b56466f709a516da760822230c6ab..8b3666c962f826edb6b97c2e1666cd8ff1838d22 100644 (file)
@@ -930,7 +930,6 @@ class MEDCouplingIntersectTest(unittest.TestCase):
         ret = mesh.conformize3D(1.0e-8)
 
         mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
-        mretDesc.writeVTK("/tmp/toto_conf_desc.vtu")
         c, cI = mretDesc.getNodalConnectivity().getValues(), mretDesc.getNodalConnectivityIndex().getValues()
         cRef = [5, 1, 0, 2, 3, 5, 5, 7, 6, 4, 5, 1, 5, 4, 0, 5, 0, 4, 6, 2, 5, 2, 6, 7, 3, 5, 3, 7, 8, 5,
                 7, 5, 8, 5, 5, 1, 8, 5, 1, 3, 8, 5, 9, 1, 3, 10, 5, 11, 12, 7, 5, 5, 9, 11, 5, 1, 5, 3,
@@ -956,35 +955,80 @@ class MEDCouplingIntersectTest(unittest.TestCase):
                           7, 11, 21, 19, -1, 19, 21, 20, 18])
         cI = DataArrayInt([0, 37, 74, 104, 134])
         mesh.setConnectivity(c, cI)
-
-        mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
-        mretDesc2, _, _, _, _ = mretDesc.buildDescendingConnectivity()
-        mretDesc.writeVTK("/tmp/toto_desc.vtu")
-        mretDesc2.writeVTK("/tmp/toto_desc2.vtu")
+#         mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
+#         mretDesc2, _, _, _, _ = mretDesc.buildDescendingConnectivity()
+#         mretDesc.writeVTK("/tmp/toto_desc.vtu")
+#         mretDesc2.writeVTK("/tmp/toto_desc2.vtu")
 
         ret = mesh.conformize3D(1.0e-8)
 
         mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
         mretDesc2, _, _, _, _ = mretDesc.buildDescendingConnectivity()
-        mretDesc.writeVTK("/tmp/toto_conf_desc.vtu")
-        mretDesc2.writeVTK("/tmp/toto_conf_desc2.vtu")
+#         mretDesc.writeVTK("/tmp/toto_conf_desc.vtu")
+#         mretDesc2.writeVTK("/tmp/toto_conf_desc2.vtu")
+        c0, cI0 = mesh.getNodalConnectivity().getValues(), mesh.getNodalConnectivityIndex().getValues()
         c, cI = mretDesc.getNodalConnectivity().getValues(), mretDesc.getNodalConnectivityIndex().getValues()
-        c2, cI2 = mretDesc.getNodalConnectivity().getValues(), mretDesc.getNodalConnectivityIndex().getValues()
-        cRef = []
-        cIRef = []
-        cRef2 = []
-        cIRef2 = []
-        print mretDesc2.getNumberOfCells()
-        return
+        c2, cI2 = mretDesc2.getNodalConnectivity().getValues(), mretDesc2.getNodalConnectivityIndex().getValues()
+        cRef0 = [31, 1, 0, 2, 3, 12, -1, 5, 14, 13, 7, 6, 4, -1, 1, 5, 4, 0, -1, 0, 4, 6, 2, -1, 2, 6, 7, 3, -1, 3, 7, 13, 12, -1, 5, 1, 12, 13, 14, 31, 9, 15, 11, 10, 8, -1, 5, 9, 8, 4, -1, 4, 8, 10, 6, -1, 6, 10, 11, 7, -1, 7, 11, 15, 14, 13, -1, 9, 5, 14, 15, -1, 5, 14, 13, 7, 6, 4, 31, 16, 1, 12, 3, 17, -1, 18, 19, 7, 13, 14, 5, -1, 16, 18, 5, 1, -1, 3, 7, 19, 17, -1, 17, 19, 18, 16, -1, 5, 1, 12, 13, 14, -1, 3, 7, 13, 12, 31, 5, 14, 13, 7, 19, 18, -1, 20, 21, 11, 15, 9, -1, 18, 20, 9, 5, -1, 7, 11, 21, 19, -1, 19, 21, 20, 18, -1, 9, 5, 14, 15, -1, 7, 11, 15, 14, 13]
+        cIRef0 = [0, 39, 78, 117, 156]
+        cRef = [5, 1, 0, 2, 3, 12, 5, 5, 14, 13, 7, 6, 4, 5, 1, 5, 4, 0, 5, 0, 4, 6, 2, 5, 2, 6, 7, 3, 5, 3, 7, 13, 12, 5, 5, 1, 12, 13, 14, 5, 9, 15, 11, 10, 8, 5, 5, 9, 8, 4, 5, 4, 8, 10, 6, 5, 6, 10, 11, 7, 5, 7, 11, 15, 14, 13, 5, 9, 5, 14, 15, 5, 16, 1, 12, 3, 17, 5, 18, 19, 7, 13, 14, 5, 5, 16, 18, 5, 1, 5, 3, 7, 19, 17, 5, 17, 19, 18, 16, 5, 20, 21, 11, 15, 9, 5, 18, 20, 9, 5, 5, 7, 11, 21, 19, 5, 19, 21, 20, 18]
+        cIRef = [0, 6, 13, 18, 23, 28, 33, 39, 45, 50, 55, 60, 66, 71, 77, 84, 89, 94, 99, 105, 110, 115, 120]
+        cRef2 = [1, 1, 0, 1, 0, 2, 1, 2, 3, 1, 3, 12, 1, 12, 1, 1, 5, 14, 1, 14, 13, 1, 13, 7, 1, 7, 6, 1, 6, 4, 1, 4, 5, 1, 1, 5, 1, 4, 0, 1, 6, 2, 1, 7, 3, 1, 13, 12, 1, 9, 15, 1, 15, 11, 1, 11, 10, 1, 10, 8, 1, 8, 9, 1, 5, 9, 1, 8, 4, 1, 10, 6, 1, 11, 7, 1, 15, 14, 1, 16, 1, 1, 3, 17, 1, 17, 16, 1, 18, 19, 1, 19, 7, 1, 5, 18, 1, 16, 18, 1, 19, 17, 1, 20, 21, 1, 21, 11, 1, 9, 20, 1, 18, 20, 1, 21, 19]
+        cIRef2 = [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117]
         self.assertEqual(22, mretDesc.getNumberOfCells())
-        self.assertEqual(40, mretDesc2.getNumberOfCells())
+        self.assertEqual(39, mretDesc2.getNumberOfCells())
+        self.assertEqual(cRef0, c0)
+        self.assertEqual(cIRef0, cI0)
         self.assertEqual(cRef, c)
         self.assertEqual(cIRef, cI)
         self.assertEqual(cRef2, c2)
         self.assertEqual(cIRef2, cI2)
-        self.assertEqual([0,1,2,3], ret.getValues())
+        self.assertEqual(set([0,1,2,3]), set(ret.getValues()))
         pass
 
+    def testSwig2Conformize3D3(self):
+        """ LMEC's case (hexagonal prism) """
+        eps = 1.0e-7   # 1.0e-8 is too fine
+        mesh = MEDCouplingUMesh('merge', 3)
+        coo = DataArrayDouble([(0,0,0),(-0.0054,-0.00935307,0),(0.0054,-0.00935307,0),(0.0108,0,0),(0.0054,0.00935307,0),(-0.0054,0.00935307,0),(-0.0108,6.93889e-18,0),(-0.0054,-0.0153031,0),(0.0054,-0.0153031,0),(0.0105529,-0.0123281,0),(0.0159529,-0.002975,0),(0.0159529,0.002975,0),(0.0105529,0.0123281,0),(0.0054,0.0153031,0),(-0.0054,0.0153031,0),(-0.0105529,0.0123281,0),(-0.0159529,0.002975,0),(-0.0159529,-0.002975,0),(-0.0105529,-0.0123281,0),(-0.00883523,-0.0153031,0),(0.00883523,-0.0153031,0),(0.0176705,0,0),(0.00883523,0.0153031,0),(-0.00883523,0.0153031,0),(-0.0176705,2.16401e-18,0),(0,0,0.05),(-0.0054,-0.00935307,0.05),(0.0054,-0.00935307,0.05),(0.0108,0,0.05),(0.0054,0.00935307,0.05),(-0.0054,0.00935307,0.05),(-0.0108,6.93889e-18,0.05),(-0.0054,-0.0153031,0.05),(0.0054,-0.0153031,0.05),(0.0105529,-0.0123281,0.05),(0.0159529,-0.002975,0.05),(0.0159529,0.002975,0.05),(0.0105529,0.0123281,0.05),(0.0054,0.0153031,0.05),(-0.0054,0.0153031,0.05),(-0.0105529,0.0123281,0.05),(-0.0159529,0.002975,0.05),(-0.0159529,-0.002975,0.05),(-0.0105529,-0.0123281,0.05),(-0.00883523,-0.0153031,0.05),(0.00883523,-0.0153031,0.05),(0.0176705,0,0.05),(0.00883523,0.0153031,0.05),(-0.00883523,0.0153031,0.05),(-0.0176705,2.16401e-18,0.05),(0.0176705,0,0.05),(0.00883523,0.0153031,0.05),(-0.00883523,0.0153031,0.05),(-0.0176705,2.16401e-18,0.05),(-0.00883523,-0.0153031,0.05),(0.00883523,-0.0153031,0.05),(0.0176705,0,0.15),(0.00883523,0.0153031,0.15),(-0.00883523,0.0153031,0.15),(-0.0176705,2.16401e-18,0.15),(-0.00883523,-0.0153031,0.15),(0.00883523,-0.0153031,0.15)])
+        mesh.setCoords(coo)
+        c = DataArrayInt([31, 1, 0, 2, -1, 25, 26, 27, -1, 2, 27, 26, 1, -1, 0, 25, 27, 2, -1, 1, 26, 25, 0, 31, 2, 0, 3, -1, 25, 27, 28, -1, 3, 28, 27, 2, -1, 0, 25, 28, 3, -1, 2, 27, 25, 0, 31, 3, 0, 4, -1, 25, 28, 29, -1, 4, 29, 28, 3, -1, 0, 25, 29, 4, -1, 3, 28, 25, 0, 31, 4, 0, 5, -1, 25, 29, 30, -1, 5, 30, 29, 4, -1, 0, 25, 30, 5, -1, 4, 29, 25, 0, 31, 5, 0, 6, -1, 25, 30, 31, -1, 6, 31, 30, 5, -1, 0, 25, 31, 6, -1, 5, 30, 25, 0, 31, 6, 0, 1, -1, 25, 31, 26, -1, 1, 26, 31, 6, -1, 0, 25, 26, 1, -1, 6, 31, 25, 0, 31, 1, 2, 8, 7, -1, 27, 26, 32, 33, -1, 7, 32, 26, 1, -1, 8, 33, 32, 7, -1, 2, 27, 33, 8, -1, 1, 26, 27, 2, 31, 2, 3, 10, 9, -1, 28, 27, 34, 35, -1, 9, 34, 27, 2, -1, 10, 35, 34, 9, -1, 3, 28, 35, 10, -1, 2, 27, 28, 3, 31, 3, 4, 12, 11, -1, 29, 28, 36, 37, -1, 11, 36, 28, 3, -1, 12, 37, 36, 11, -1, 4, 29, 37, 12, -1, 3, 28, 29, 4, 31, 4, 5, 14, 13, -1, 30, 29, 38, 39, -1, 13, 38, 29, 4, -1, 14, 39, 38, 13, -1, 5, 30, 39, 14, -1, 4, 29, 30, 5, 31, 5, 6, 16, 15, -1, 31, 30, 40, 41, -1, 15, 40, 30, 5, -1, 16, 41, 40, 15, -1, 6, 31, 41, 16, -1, 5, 30, 31, 6, 31, 6, 1, 18, 17, -1, 26, 31, 42, 43, -1, 17, 42, 31, 6, -1, 18, 43, 42, 17, -1, 1, 26, 43, 18, -1, 6, 31, 26, 1, 31, 19, 18, 1, 7, -1, 43, 44, 32, 26, -1, 7, 32, 44, 19, -1, 1, 26, 32, 7, -1, 18, 43, 26, 1, -1, 19, 44, 43, 18, 31, 20, 8, 2, 9, -1, 33, 45, 34, 27, -1, 9, 34, 45, 20, -1, 2, 27, 34, 9, -1, 8, 33, 27, 2, -1, 20, 45, 33, 8, 31, 21, 10, 3, 11, -1, 35, 46, 36, 28, -1, 11, 36, 46, 21, -1, 3, 28, 36, 11, -1, 10, 35, 28, 3, -1, 21, 46, 35, 10, 31, 22, 12, 4, 13, -1, 37, 47, 38, 29, -1, 13, 38, 47, 22, -1, 4, 29, 38, 13, -1, 12, 37, 29, 4, -1, 22, 47, 37, 12, 31, 23, 14, 5, 15, -1, 39, 48, 40, 30, -1, 15, 40, 48, 23, -1, 5, 30, 40, 15, -1, 14, 39, 30, 5, -1, 23, 48, 39, 14, 31, 24, 16, 6, 17, -1, 41, 49, 42, 31, -1, 17, 42, 49, 24, -1, 6, 31, 42, 17, -1, 16, 41, 31, 6, -1, 24, 49, 41, 16, 31, 50, 51, 52, 53, 54, 55, -1, 56, 61, 60, 59, 58, 57, -1, 50, 56, 57, 51, -1, 51, 57, 58, 52, -1, 52, 58, 59, 53, -1, 53, 59, 60, 54, -1, 54, 60, 61, 55, -1, 55, 61, 56, 50])
+        cI = DataArrayInt([0, 23, 46, 69, 92, 115, 138, 168, 198, 228, 258, 288, 318, 348, 378, 408, 438, 468, 498, 542])
+        mesh.setConnectivity(c, cI)
+        mesh.mergeNodes(eps) # the initial case has double nodes
+
+#         mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
+#         mretDesc2, _, _, _, _ = mretDesc.buildDescendingConnectivity()
+#         mretDesc.writeVTK("/tmp/toto_desc.vtu")
+#         mretDesc2.writeVTK("/tmp/toto_desc2.vtu")
+#         print mretDesc2.getNumberOfCells()
+
+        ret = mesh.conformize3D(eps)
+
+        mretDesc, _, _, _, _ = mesh.buildDescendingConnectivity()
+        mretDesc2, _, _, _, _ = mretDesc.buildDescendingConnectivity()
+#         mesh.writeVTK("/tmp/toto_conf.vtu")
+#         mretDesc.writeVTK("/tmp/toto_conf_desc.vtu")
+#         mretDesc2.writeVTK("/tmp/toto_conf_desc2.vtu")
+        c0, cI0 = mesh.getNodalConnectivity().getValues(), mesh.getNodalConnectivityIndex().getValues()
+        c, cI = mretDesc.getNodalConnectivity().getValues(), mretDesc.getNodalConnectivityIndex().getValues()
+        c2, cI2 = mretDesc2.getNodalConnectivity().getValues(), mretDesc2.getNodalConnectivityIndex().getValues()
+        cRef0 = [31, 1, 0, 2, -1, 25, 26, 27, -1, 2, 27, 26, 1, -1, 0, 25, 27, 2, -1, 1, 26, 25, 0, 31, 2, 0, 3, -1, 25, 27, 28, -1, 3, 28, 27, 2, -1, 0, 25, 28, 3, -1, 2, 27, 25, 0, 31, 3, 0, 4, -1, 25, 28, 29, -1, 4, 29, 28, 3, -1, 0, 25, 29, 4, -1, 3, 28, 25, 0, 31, 4, 0, 5, -1, 25, 29, 30, -1, 5, 30, 29, 4, -1, 0, 25, 30, 5, -1, 4, 29, 25, 0, 31, 5, 0, 6, -1, 25, 30, 31, -1, 6, 31, 30, 5, -1, 0, 25, 31, 6, -1, 5, 30, 25, 0, 31, 6, 0, 1, -1, 25, 31, 26, -1, 1, 26, 31, 6, -1, 0, 25, 26, 1, -1, 6, 31, 25, 0, 31, 1, 2, 8, 7, -1, 27, 26, 32, 33, -1, 7, 32, 26, 1, -1, 8, 33, 32, 7, -1, 2, 27, 33, 8, -1, 1, 26, 27, 2, 31, 2, 3, 10, 9, -1, 28, 27, 34, 35, -1, 9, 34, 27, 2, -1, 10, 35, 34, 9, -1, 3, 28, 35, 10, -1, 2, 27, 28, 3, 31, 3, 4, 12, 11, -1, 29, 28, 36, 37, -1, 11, 36, 28, 3, -1, 12, 37, 36, 11, -1, 4, 29, 37, 12, -1, 3, 28, 29, 4, 31, 4, 5, 14, 13, -1, 30, 29, 38, 39, -1, 13, 38, 29, 4, -1, 14, 39, 38, 13, -1, 5, 30, 39, 14, -1, 4, 29, 30, 5, 31, 5, 6, 16, 15, -1, 31, 30, 40, 41, -1, 15, 40, 30, 5, -1, 16, 41, 40, 15, -1, 6, 31, 41, 16, -1, 5, 30, 31, 6, 31, 6, 1, 18, 17, -1, 26, 31, 42, 43, -1, 17, 42, 31, 6, -1, 18, 43, 42, 17, -1, 1, 26, 43, 18, -1, 6, 31, 26, 1, 31, 19, 18, 1, 7, -1, 43, 44, 32, 26, -1, 7, 32, 44, 19, -1, 1, 26, 32, 7, -1, 18, 43, 26, 1, -1, 19, 44, 43, 18, 31, 20, 8, 2, 9, -1, 33, 45, 34, 27, -1, 9, 34, 45, 20, -1, 2, 27, 34, 9, -1, 8, 33, 27, 2, -1, 20, 45, 33, 8, 31, 21, 10, 3, 11, -1, 35, 46, 36, 28, -1, 11, 36, 46, 21, -1, 3, 28, 36, 11, -1, 10, 35, 28, 3, -1, 21, 46, 35, 10, 31, 22, 12, 4, 13, -1, 37, 47, 38, 29, -1, 13, 38, 47, 22, -1, 4, 29, 38, 13, -1, 12, 37, 29, 4, -1, 22, 47, 37, 12, 31, 23, 14, 5, 15, -1, 39, 48, 40, 30, -1, 15, 40, 48, 23, -1, 5, 30, 40, 15, -1, 14, 39, 30, 5, -1, 23, 48, 39, 14, 31, 24, 16, 6, 17, -1, 41, 49, 42, 31, -1, 17, 42, 49, 24, -1, 6, 31, 42, 17, -1, 16, 41, 31, 6, -1, 24, 49, 41, 16, 31, 50, 55, 54, 53, 52, 51, -1, 46, 50, 51, 47, 37, 36, -1, 47, 51, 52, 48, 39, 38, -1, 48, 52, 53, 49, 41, 40, -1, 49, 53, 54, 44, 43, 42, -1, 44, 54, 55, 45, 33, 32, -1, 45, 55, 50, 46, 35, 34, -1, 25, 26, 27, -1, 25, 31, 26, -1, 27, 26, 32, 33, -1, 26, 31, 42, 43, -1, 43, 44, 32, 26, -1, 41, 49, 42, 31, -1, 25, 29, 30, -1, 25, 30, 31, -1, 30, 29, 38, 39, -1, 31, 30, 40, 41, -1, 39, 48, 40, 30, -1, 25, 27, 28, -1, 28, 27, 34, 35, -1, 33, 45, 34, 27, -1, 35, 46, 36, 28, -1, 25, 28, 29, -1, 29, 28, 36, 37, -1, 37, 47, 38, 29]
+        cIRef0 = [0, 23, 46, 69, 92, 115, 138, 168, 198, 228, 258, 288, 318, 348, 378, 408, 438, 468, 498, 631]
+        cRef = [5, 1, 0, 2, 5, 25, 26, 27, 5, 2, 27, 26, 1, 5, 0, 25, 27, 2, 5, 1, 26, 25, 0, 5, 2, 0, 3, 5, 25, 27, 28, 5, 3, 28, 27, 2, 5, 0, 25, 28, 3, 5, 3, 0, 4, 5, 25, 28, 29, 5, 4, 29, 28, 3, 5, 0, 25, 29, 4, 5, 4, 0, 5, 5, 25, 29, 30, 5, 5, 30, 29, 4, 5, 0, 25, 30, 5, 5, 5, 0, 6, 5, 25, 30, 31, 5, 6, 31, 30, 5, 5, 0, 25, 31, 6, 5, 6, 0, 1, 5, 25, 31, 26, 5, 1, 26, 31, 6, 5, 1, 2, 8, 7, 5, 27, 26, 32, 33, 5, 7, 32, 26, 1, 5, 8, 33, 32, 7, 5, 2, 27, 33, 8, 5, 2, 3, 10, 9, 5, 28, 27, 34, 35, 5, 9, 34, 27, 2, 5, 10, 35, 34, 9, 5, 3, 28, 35, 10, 5, 3, 4, 12, 11, 5, 29, 28, 36, 37, 5, 11, 36, 28, 3, 5, 12, 37, 36, 11, 5, 4, 29, 37, 12, 5, 4, 5, 14, 13, 5, 30, 29, 38, 39, 5, 13, 38, 29, 4, 5, 14, 39, 38, 13, 5, 5, 30, 39, 14, 5, 5, 6, 16, 15, 5, 31, 30, 40, 41, 5, 15, 40, 30, 5, 5, 16, 41, 40, 15, 5, 6, 31, 41, 16, 5, 6, 1, 18, 17, 5, 26, 31, 42, 43, 5, 17, 42, 31, 6, 5, 18, 43, 42, 17, 5, 1, 26, 43, 18, 5, 19, 18, 1, 7, 5, 43, 44, 32, 26, 5, 7, 32, 44, 19, 5, 19, 44, 43, 18, 5, 20, 8, 2, 9, 5, 33, 45, 34, 27, 5, 9, 34, 45, 20, 5, 20, 45, 33, 8, 5, 21, 10, 3, 11, 5, 35, 46, 36, 28, 5, 11, 36, 46, 21, 5, 21, 46, 35, 10, 5, 22, 12, 4, 13, 5, 37, 47, 38, 29, 5, 13, 38, 47, 22, 5, 22, 47, 37, 12, 5, 23, 14, 5, 15, 5, 39, 48, 40, 30, 5, 15, 40, 48, 23, 5, 23, 48, 39, 14, 5, 24, 16, 6, 17, 5, 41, 49, 42, 31, 5, 17, 42, 49, 24, 5, 24, 49, 41, 16, 5, 50, 55, 54, 53, 52, 51, 5, 46, 50, 51, 47, 37, 36, 5, 47, 51, 52, 48, 39, 38, 5, 48, 52, 53, 49, 41, 40, 5, 49, 53, 54, 44, 43, 42, 5, 44, 54, 55, 45, 33, 32, 5, 45, 55, 50, 46, 35, 34]
+        cIRef = [0, 4, 8, 13, 18, 23, 27, 31, 36, 41, 45, 49, 54, 59, 63, 67, 72, 77, 81, 85, 90, 95, 99, 103, 108, 113, 118, 123, 128, 133, 138, 143, 148, 153, 158, 163, 168, 173, 178, 183, 188, 193, 198, 203, 208, 213, 218, 223, 228, 233, 238, 243, 248, 253, 258, 263, 268, 273, 278, 283, 288, 293, 298, 303, 308, 313, 318, 323, 328, 333, 338, 343, 348, 353, 358, 363, 368, 373, 378, 385, 392, 399, 406, 413, 420, 427]
+        cRef2 = [1, 1, 0, 1, 0, 2, 1, 2, 1, 1, 25, 26, 1, 26, 27, 1, 27, 25, 1, 2, 27, 1, 26, 1, 1, 0, 25, 1, 0, 3, 1, 3, 2, 1, 27, 28, 1, 28, 25, 1, 3, 28, 1, 0, 4, 1, 4, 3, 1, 28, 29, 1, 29, 25, 1, 4, 29, 1, 0, 5, 1, 5, 4, 1, 29, 30, 1, 30, 25, 1, 5, 30, 1, 0, 6, 1, 6, 5, 1, 30, 31, 1, 31, 25, 1, 6, 31, 1, 1, 6, 1, 31, 26, 1, 2, 8, 1, 8, 7, 1, 7, 1, 1, 26, 32, 1, 32, 33, 1, 33, 27, 1, 7, 32, 1, 8, 33, 1, 3, 10, 1, 10, 9, 1, 9, 2, 1, 27, 34, 1, 34, 35, 1, 35, 28, 1, 9, 34, 1, 10, 35, 1, 4, 12, 1, 12, 11, 1, 11, 3, 1, 28, 36, 1, 36, 37, 1, 37, 29, 1, 11, 36, 1, 12, 37, 1, 5, 14, 1, 14, 13, 1, 13, 4, 1, 29, 38, 1, 38, 39, 1, 39, 30, 1, 13, 38, 1, 14, 39, 1, 6, 16, 1, 16, 15, 1, 15, 5, 1, 30, 40, 1, 40, 41, 1, 41, 31, 1, 15, 40, 1, 16, 41, 1, 1, 18, 1, 18, 17, 1, 17, 6, 1, 31, 42, 1, 42, 43, 1, 43, 26, 1, 17, 42, 1, 18, 43, 1, 19, 18, 1, 7, 19, 1, 43, 44, 1, 44, 32, 1, 44, 19, 1, 20, 8, 1, 9, 20, 1, 33, 45, 1, 45, 34, 1, 45, 20, 1, 21, 10, 1, 11, 21, 1, 35, 46, 1, 46, 36, 1, 46, 21, 1, 22, 12, 1, 13, 22, 1, 37, 47, 1, 47, 38, 1, 47, 22, 1, 23, 14, 1, 15, 23, 1, 39, 48, 1, 48, 40, 1, 48, 23, 1, 24, 16, 1, 17, 24, 1, 41, 49, 1, 49, 42, 1, 49, 24, 1, 50, 55, 1, 55, 54, 1, 54, 53, 1, 53, 52, 1, 52, 51, 1, 51, 50, 1, 46, 50, 1, 51, 47, 1, 52, 48, 1, 53, 49, 1, 54, 44, 1, 55, 45]
+        cIRef2 = [0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150, 153, 156, 159, 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195, 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231, 234, 237, 240, 243, 246, 249, 252, 255, 258, 261, 264, 267, 270, 273, 276, 279, 282, 285, 288, 291, 294, 297, 300, 303, 306, 309, 312, 315, 318, 321, 324, 327, 330, 333, 336, 339, 342, 345, 348, 351, 354, 357, 360, 363]
+        self.assertEqual(85, mretDesc.getNumberOfCells())
+        self.assertEqual(121, mretDesc2.getNumberOfCells())
+        self.assertEqual(cRef0, c0)
+        self.assertEqual(cIRef0, cI0)
+        self.assertEqual(cRef, c)
+        self.assertEqual(cIRef, cI)
+        self.assertEqual(cRef2, c2)
+        self.assertEqual(cIRef2, cI2)
+        self.assertEqual(set([18]), set(ret.getValues()))
+        pass
 
 if __name__ == '__main__':
     unittest.main()