Skip to content

Commit

Permalink
OCC: viz of lonelyEdges
Browse files Browse the repository at this point in the history
  • Loading branch information
benoit128 committed Nov 29, 2024
1 parent f4f915f commit 85b13fe
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 18 deletions.
84 changes: 76 additions & 8 deletions Cassiopee/CPlot/apps/tkCADFix.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import CPlot.Tk as CTK
import Converter.Internal as Internal
import CPlot.iconics as iconics
import math

# local widgets list
WIDGETS = {}; VARS = []
Expand Down Expand Up @@ -121,7 +122,13 @@ def filletCAD(event=None):
CTK.setCursor(2, WIDGETS['frame'])
CTK.setCursor(2, WIDGETS['filletButton'])

OCC._addFillet(hook, edges, radius)
try:
OCC._addFillet(hook, edges, radius)
except:
CTK.setCursor(0, WIDGETS['frame'])
CTK.setCursor(0, WIDGETS['filletButton'])
CTK.TXT.insert('START', 'Add fillet fails.\n')
return

# remesh CAD and redisplay
edges = Internal.getNodeFromName1(CTK.t, 'EDGES')
Expand Down Expand Up @@ -193,6 +200,51 @@ def removeFaces(event=None):

CTK.TXT.insert('START', 'Faces removed from CAD.\n')

#==============================================================================
# filter lonelyEdges based on color
def filterLonelyEdges(event=None):
EDGES = Internal.getNodeFromName1(CTK.t, 'EDGES')
if EDGES is None: return
FACES = Internal.getNodeFromName1(CTK.t, 'FACES')
activeMode = 1
activeList = []
if FACES is not None:
zones = Internal.getZones(FACES)
if len(zones) > 0:
noz = CPlot.getCPlotNumber(CTK.t, 'FACES', zones[0][0])
activeMode = CPlot.getActiveStatus(noz)

if activeMode == 0: # previously deactivated
for z in zones:
noz = CPlot.getCPlotNumber(CTK.t, 'FACES', z[0])
#CPlot.setActiveZones([(noz,1)])
activeList.append((noz,1))
else:
for z in zones:
noz = CPlot.getCPlotNumber(CTK.t, 'FACES', z[0])
#CPlot.setActiveZones([(noz,0)])
activeList.append((noz,0))

if activeMode == 1:
for z in Internal.getZones(EDGES):
noz = CPlot.getCPlotNumber(CTK.t, 'EDGES', z[0])
p = Internal.getNodeFromPath(z, '.RenderInfo/Color')
active = 0
if p is not None:
if Internal.getValue(p) == 'Red': active = 1
#CPlot.setActiveZones([(noz,active)])
activeList.append((noz,active))

else:
for z in Internal.getZones(EDGES):
noz = CPlot.getCPlotNumber(CTK.t, 'EDGES', z[0])
#CPlot.setActiveZones([(noz,1)])
activeList.append((noz,1))

CPlot.setActiveZones(activeList)

CTK.TXT.insert('START', 'Lonely edges displayed.\n')

#==============================================================================
def fillHole(event=None):
import OCC.PyTree as OCC
Expand Down Expand Up @@ -339,25 +391,34 @@ def checkWatertight(event=None):
return
import Transform.PyTree as T
import Post.PyTree as P
import Generator.PyTree as G

CTK.setCursor(2, WIDGETS['frame'])
CTK.setCursor(2, WIDGETS['checkWatertight'])

CTK.saveTree()
p = Internal.getNodesFromName1(CTK.t, 'LEAKS')
p = Internal.getNodeFromName1(CTK.t, 'LEAKS')
if p is not None:
zones = []
for z in Internal.getZones(p): zones.append('LEAKS'+Internal.SEP1+z[0])
CPlot.delete(zones)
gnob = C.getNobOfBase(p, CTK.t)
del CTK.t[2][gnob]

tol = 1.e-6
CAD = Internal.getNodeFromName1(CTK.t, 'CAD')
if CAD is not None:
hmax = Internal.getNodeFromName1(CAD, 'hmax')
hmax = Internal.getValue(hmax)
tol = hmax/10.

CTK.t = C.addBase2PyTree(CTK.t, 'LEAKS', 1)
p = Internal.getNodesFromName1(CTK.t, 'LEAKS')
p = Internal.getNodeFromName1(CTK.t, 'LEAKS')
gnob = C.getNobOfBase(p, CTK.t)

f = Internal.getZones(b)
f = T.join(f, tol=1.e-6)
f = T.join(f)
f = G.close(f, tol)
ef = T.splitConnexity(f)
VARS[6].set('Components: %d'%(len(ef)))

Expand All @@ -379,8 +440,8 @@ def checkWatertight(event=None):
if isWatertight: TTK.setButtonGreen(WIDGETS['checkWatertight'])
else: TTK.setButtonRed(WIDGETS['checkWatertight'])

if isWatertight: CTK.TXT.insert('START', 'CAD is watertight.\n')
else: CTK.TXT.insert('START', 'CAD is not watertight.\n')
if isWatertight: CTK.TXT.insert('START', 'CAD is watertight with tol %g.\n'%tol)
else: CTK.TXT.insert('START', 'CAD is not watertight with tol %g.\n'%tol)

#==============================================================================
# Create app widgets
Expand All @@ -406,19 +467,25 @@ def createApp(win):
WIDGETS['frameMenu'] = FrameMenu

#- VARS -
tol = 1.e-6
if CTK.CADHOOK is not None:
import OCC.PyTree as OCC
fileName, fileFmt = OCC.getFileAndFormat(CTK.CADHOOK)
CAD = Internal.getNodeFromName1(CTK.t, 'CAD')
if CAD is not None: NL = OCC.getNbLonelyEdges(CTK.t)
if CAD is not None:
NL = OCC.getNbLonelyEdges(CTK.t)
tol = Internal.getNodeFromName1(CAD, 'hmax')
tol = Internal.getValue(tol)
power = math.floor(math.log10(abs(tol)))
tol = round(tol, -power)
else: fileName = ''; fileFmt = 'fmt_step'; NL = 0

# -0- CAD file name -
V = TK.StringVar(win); V.set(fileName); VARS.append(V)
# -1- CAD file format -
V = TK.StringVar(win); V.set(fileFmt); VARS.append(V)
# -2- Sewing tolerance -
V = TK.StringVar(win); V.set('1.e-6'); VARS.append(V)
V = TK.StringVar(win); V.set(str(tol)); VARS.append(V)
# -3- Fillet radius -
V = TK.StringVar(win); V.set('0.1'); VARS.append(V)
# -4- Bilan des edges lonely
Expand Down Expand Up @@ -448,6 +515,7 @@ def createApp(win):

# Lonely edges
B = TTK.Label(Frame, textvariable=VARS[4])
B.bind("<Button-1>", filterLonelyEdges)
B.grid(row=2, column=0, columnspan=1, sticky=TK.EW)
BB = CTK.infoBulle(parent=B, text='Number of lonely edges.')

Expand Down
26 changes: 22 additions & 4 deletions Cassiopee/OCC/OCC/Atomic/addFillet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "ShapeBuild_ReShape.hxx"
#include "BRep_Builder.hxx"
#include "BRepFilletAPI_MakeFillet.hxx"
#include "StdFail_NotDone.hxx"

void getEdgeMap(TopTools_IndexedMapOfShape& oldFaces, TopTools_IndexedMapOfShape& newFaces, PyObject*& faceMap);
void getFaceMap(TopTools_IndexedMapOfShape& oldFaces, TopTools_IndexedMapOfShape& newFaces, PyObject*& faceMap);
Expand Down Expand Up @@ -54,15 +55,32 @@ PyObject* K_OCC::addFillet(PyObject* self, PyObject* args)

// get edges
BRepFilletAPI_MakeFillet mkFillet(*shp);
bool fail = false;
for (E_Int no = 0; no < PyList_Size(listEdges); no++)
{
PyObject* noEdgeO = PyList_GetItem(listEdges, no);
E_Int noEdge = PyInt_AsLong(noEdgeO);
const TopoDS_Edge& E = TopoDS::Edge(edges(noEdge));
mkFillet.Add(radius, E);
try {
mkFillet.Add(radius, E);
} catch (StdFail_NotDone& e) { fail = true; }
}
if (fail)
{
PyErr_SetString(PyExc_TypeError, "addFillet: failed.");
return NULL;
}
TopoDS_Shape shc = mkFillet.Shape();

TopoDS_Shape shc;
try {
shc = mkFillet.Shape();
} catch (StdFail_NotDone& e) { fail = true; }
if (fail)
{
PyErr_SetString(PyExc_TypeError, "addFillet: failed.");
return NULL;
}

// export
TopoDS_Shape* newshp = new TopoDS_Shape(shc);
TopTools_IndexedMapOfShape* sf = new TopTools_IndexedMapOfShape();
Expand All @@ -79,8 +97,8 @@ PyObject* K_OCC::addFillet(PyObject* self, PyObject* args)
packet[0] = newshp;
packet[1] = sf;
packet[2] = se;
printf("INFO: after removeFaces: Nb edges=%d\n", se->Extent());
printf("INFO: after removeFaces: Nb faces=%d\n", sf->Extent());
printf("INFO: after addFillet: Nb edges=%d\n", se->Extent());
printf("INFO: after addFillet: Nb faces=%d\n", sf->Extent());

Py_INCREF(Py_None);
return Py_None;
Expand Down
41 changes: 41 additions & 0 deletions Cassiopee/OCC/OCC/Atomic/addLabel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
// add label to CAD
#include "occ.h"

#include <XCAFDoc_ShapeTool.hxx>
#include <TDF_Label.hxx>
#include <TopoDS_Shape.hxx>
#include <TopExp_Explorer.hxx>
#include <TopAbs.hxx>

// Assuming you have a document and a shape
Handle(XCAFDoc_ShapeTool) shapeTool = XCAFDoc_DocumentTool::ShapeTool(myDocument->Main());
TopoDS_Shape myShape = ...; // Your shape

// Iterate over faces
for (TopExp_Explorer exp(myShape, TopAbs_FACE); exp.More(); exp.Next())
{
TopoDS_Shape face = exp.Current();
TDF_Label label;
if (shapeTool->FindShape(face, label))
{
// Do something with the label
}
}
2 changes: 1 addition & 1 deletion Cassiopee/OCC/OCC/Atomic/addSphere.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include "BRep_Builder.hxx"

//=====================================================================
// Add a sphere to hook
// Add a sphere to CAD hook
//=====================================================================
PyObject* K_OCC::addSphere(PyObject* self, PyObject* args)
{
Expand Down
17 changes: 12 additions & 5 deletions Cassiopee/OCC/OCC/PyTree.py
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,7 @@ def _meshAllFacesStruct(hook, t, faceList=None):
# set color red to lonelyEdges
def _setLonelyEdgesColor(t):
import CPlot.PyTree as CPlot
import Geom.PyTree as D
b = Internal.getNodeFromName1(t, 'EDGES')
if b is None: return None
zones = Internal.getZones(b)
Expand All @@ -942,16 +943,19 @@ def _setLonelyEdgesColor(t):
faceList = Internal.getNodeFromName1(CAD, 'faceList')
if faceList is not None:
size = faceList[1].size
if size == 2: # ok: blue
if size == 2: # ok: green
CPlot._addRender2Zone(ze, color='Green')
elif size == 1: # lonely: red
CPlot._addRender2Zone(ze, color='Red')
else: # strange!!
CPlot._addRender2Zone(ze, color='Red')
L = D.getLength(ze)
if L > 1.e-16: CPlot._addRender2Zone(ze, color='Red')
else: CPlot._addRender2Zone(ze, color='Green')
else: # strange!!
CPlot._addRender2Zone(ze, color='Green')
return None

# Return the number of lonely edges in t
def getNbLonelyEdges(t):
import Geom.PyTree as D
b = Internal.getNodeFromName1(t, 'EDGES')
if b is None: return 0
nb = 0
Expand All @@ -961,7 +965,10 @@ def getNbLonelyEdges(t):
faceList = Internal.getNodeFromName1(CAD, 'faceList')
if faceList is not None:
size = faceList[1].size
if size == 1: nb += 1
if size == 1:
# check that edge is not degenerated
L = D.getLength(ze)
if L > 1.e-16: nb += 1
return nb

#===========================================================================================
Expand Down

0 comments on commit 85b13fe

Please sign in to comment.