diff --git a/Cassiopee/CPlot/apps/tkCADFix.py b/Cassiopee/CPlot/apps/tkCADFix.py index c49f0f596..72054bc67 100644 --- a/Cassiopee/CPlot/apps/tkCADFix.py +++ b/Cassiopee/CPlot/apps/tkCADFix.py @@ -384,6 +384,7 @@ def trimFaces(event=None): #============================================================================== def checkWatertight(event=None): + import OCC.PyTree as OCC if CTK.t == []: return b = Internal.getNodeFromName1(CTK.t, 'FACES') if b is None: @@ -416,19 +417,18 @@ def checkWatertight(event=None): p = Internal.getNodeFromName1(CTK.t, 'LEAKS') gnob = C.getNobOfBase(p, CTK.t) - f = Internal.getZones(b) - f = G.zip(f, tol) - f = T.join(f) - #f = G.close(f, tol) - ef = T.splitConnexity(f) + ef = OCC.getComponents(CTK.t, tol) + VARS[6].set('Components: %d'%(len(ef))) isWatertight = False try: - ext = P.exteriorFaces(f) - ext = T.splitConnexity(ext) - for i in ext: CTK.add(CTK.t, gnob, -1, i) - if len(ext) == 0: isWatertight = True + isWatertight = True + for f in ef: + ext = P.exteriorFaces(f) + ext = T.splitConnexity(ext) + for i in ext: CTK.add(CTK.t, gnob, -1, i) + if len(ext) != 0: isWatertight = False except: isWatertight = True (CTK.Nb, CTK.Nz) = CPlot.updateCPlotNumbering(CTK.t) diff --git a/Cassiopee/CPlot/apps/tkTree.py b/Cassiopee/CPlot/apps/tkTree.py index d9d50a3e4..d3160c892 100644 --- a/Cassiopee/CPlot/apps/tkTree.py +++ b/Cassiopee/CPlot/apps/tkTree.py @@ -903,7 +903,7 @@ def PVT_displayNode(self, clear=False): for z in zones: base, c = Internal.getParentOfNode(CTK.t, z) #noz = CPlot.getCPlotNumber(CTK.t, base[0], z[0]) - noz = dnz[base[0], z[0]] + noz = dnz[base[0]][z[0]] selected.append((noz, s)) if clear: CPlot.unselectAllZones() CPlot.setSelectedZones(selected) diff --git a/Cassiopee/OCC/OCC/Atomic/identifyTags.cpp b/Cassiopee/OCC/OCC/Atomic/identifyTags.cpp new file mode 100644 index 000000000..c43c6dbcc --- /dev/null +++ b/Cassiopee/OCC/OCC/Atomic/identifyTags.cpp @@ -0,0 +1,75 @@ +/* + Copyright 2013-2024 Onera. + + This file is part of Cassiopee. + + Cassiopee is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Cassiopee is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Cassiopee. If not, see . +*/ + +#include "occ.h" +#include + +// ============================================================================ +/* Identify int in __tag__ array */ +// ============================================================================ +PyObject* K_OCC::identifyTags(PyObject* self, PyObject* args) +{ + PyObject* array; + if (!PYPARSETUPLE_(args, O_, &array)) return NULL; + + // Check array + E_Int nil, njl, nkl; + FldArrayF* f; FldArrayI* cn; + char* varString; char* eltType; + E_Int res; + res = K_ARRAY::getFromArray3(array, varString, f, nil, njl, nkl, + cn, eltType); + + if (res != 1 && res != 2) + { + PyErr_SetString(PyExc_TypeError, + "identifyTags: invalid array."); + return NULL; + } + + E_Int post = K_ARRAY::isNamePresent(varString, "__tag__"); + if (post < 0) + { + RELEASESHAREDB(res, array, f, cn); + PyErr_SetString(PyExc_TypeError, + "identifyTags: __tag__ not found."); + return NULL; + } + post++; + E_Float* ft = f->begin(post); + + std::map kmap; + E_Int n = f->getSize(); + E_Int val; + for (E_Int i = 0; i < n; i++) + { + val = round(ft[i]); + kmap[val] = 1; + } + + // Export a list + PyObject* l = PyList_New(0); + for (const auto& pair : kmap) + { + PyObject* o = PyLong_FromLong(pair.first); + PyList_Append(l, o); + } + RELEASESHAREDB(res, array, f, cn); + return l; +} \ No newline at end of file diff --git a/Cassiopee/OCC/OCC/OCC.py b/Cassiopee/OCC/OCC/OCC.py index be2606f04..48ae4372b 100644 --- a/Cassiopee/OCC/OCC/OCC.py +++ b/Cassiopee/OCC/OCC/OCC.py @@ -14,7 +14,8 @@ __all__ = ['convertCAD2Arrays', 'switch2UV', 'switch2UV2', '_scaleUV', '_unscaleUV', 'meshSTRUCT', 'meshSTRUCT__', 'meshTRI', 'meshTRI__', 'meshTRIU__', 'meshTRIHO', 'meshQUAD', 'meshQUAD__', 'meshQUADHO', 'meshQUADHO__', - 'ultimate', 'meshAllEdges', 'meshAllFacesTri', 'meshAllFacesStruct'] + 'ultimate', 'meshAllEdges', 'meshAllFacesTri', 'meshAllFacesStruct', + 'identifyTags__'] # algo=0: mailleur open cascade (chordal_error) # algo=1: algorithme T3mesher (h, chordal_error, growth_ratio) @@ -734,3 +735,7 @@ def getNbFaces(hook): # Return the file and format used to load CAD in hook def getFileAndFormat(hook): return occ.getFileAndFormat(hook) + +# identify tag component +def identifyTags__(a): + return occ.identifyTags(a) \ No newline at end of file diff --git a/Cassiopee/OCC/OCC/PyTree.py b/Cassiopee/OCC/OCC/PyTree.py index 3a48a9168..c3fa11ba1 100644 --- a/Cassiopee/OCC/OCC/PyTree.py +++ b/Cassiopee/OCC/OCC/PyTree.py @@ -1376,4 +1376,43 @@ def _updateTree(t, oldNbEdges, oldNbFaces, new2OldEdgeMap, new2OldFaceMap): # recolor _setLonelyEdgesColor(t) - return None \ No newline at end of file + return None + +def identifyTags__(a): + array = C.getFields(Internal.__FlowSolutionNodes__, a, "__tag__", api=3)[0] + return OCC.identifyTags__(array) + +def getComponents(t, tol=1.e-10): + """Return the number of components in t, taggings faces with component number.""" + import Transform.PyTree as T + # init FACES with a tag + FACES = Internal.getNodeFromName1(t, 'FACES') + zones = Internal.getZones(FACES) + for z in zones: + # Get face number + CAD = Internal.getNodeFromName1(z, 'CAD') + no = Internal.getNodeFromName1(CAD, 'no') + no = Internal.getValue(no) + # init tag + C._initVars(z, '__tag__ = %d'%no) + + # join all zones + a = G.zip(zones, tol) + a = T.join(zones) + a = T.splitConnexity(a) + + # Identify faces in component + tags = {} + for c, z in enumerate(a): + tags[c] = identifyTags__(z) + + # Get the component number for each zone + pos = getAllPos(t) + for k in tags: + C._addFamily2Base(FACES, 'Component%02d'%k) + faces = tags[k] + for f in faces: + z = getFace(t, pos, f) + C._tagWithFamily(z, 'Component%02d'%k) + + return a \ No newline at end of file diff --git a/Cassiopee/OCC/OCC/occ.cpp b/Cassiopee/OCC/OCC/occ.cpp index 6bc988ced..acfd713ef 100644 --- a/Cassiopee/OCC/OCC/occ.cpp +++ b/Cassiopee/OCC/OCC/occ.cpp @@ -87,6 +87,7 @@ static PyMethodDef Pyocc [] = {"rotate", K_OCC::rotate, METH_VARARGS}, {"getOppData", K_OCC::getOppData, METH_VARARGS}, + {"identifyTags", K_OCC::identifyTags, METH_VARARGS}, {NULL, NULL} }; diff --git a/Cassiopee/OCC/OCC/occ.h b/Cassiopee/OCC/OCC/occ.h index 77d90bf06..1b4c233ae 100644 --- a/Cassiopee/OCC/OCC/occ.h +++ b/Cassiopee/OCC/OCC/occ.h @@ -86,7 +86,7 @@ namespace K_OCC PyObject* rotate(PyObject* self, PyObject* args); PyObject* getOppData(PyObject* self, PyObject* args); - + PyObject* identifyTags(PyObject* self, PyObject* args); } #endif diff --git a/Cassiopee/OCC/srcs.py b/Cassiopee/OCC/srcs.py index f3184826e..bf64c3627 100644 --- a/Cassiopee/OCC/srcs.py +++ b/Cassiopee/OCC/srcs.py @@ -73,7 +73,8 @@ def getFiles(module): 'OCC/Atomic/scale.cpp', 'OCC/Atomic/rotate.cpp', - 'OCC/Atomic/getOppData.cpp'] + 'OCC/Atomic/getOppData.cpp', + 'OCC/Atomic/identifyTags.cpp'] import KCore.Dist as Dist