Move all nodes Y coordinates

Dear all,

I’d like to know how to move with a script all, say Y coordinates nodes of a mesh group (say, “symmetry”) to 0. I tried to follow the TUI script indicated at the end of the help section, yet I’m struggling a bit. I’ve the objects for the mesh and for the groups available in the python console, and tried to use “GetSubMeshNodesId” but throws me an error (think it does not like to receive the SMESH type).

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\SALOME-9.13.0\W64\SMESH\bin\salome\SMESH_Mesh_idl.py", line 1100, in GetSubMeshNodesId
    return self._obj.invoke("GetSubMeshNodesId", _0_SMESH.SMESH_Mesh._d_GetSubMeshNodesId, args)
omniORB.CORBA._omni_sys_exc: CORBA.BAD_PARAM(omniORB.BAD_PARAM_WrongPythonType, CORBA.COMPLETED_NO, ["Expecting long, got <class 'SMESH._objref_SMESH_GroupOnGeom'>", "Operation 'GetSubMeshNodesId' parameter 0"])

I’m using version 9.13. Thanks!!!

you can get the ids of the nodes using filter for example:

  1. you create a group in GEOM of your mesh
  2. you create a mesh group (of type nodes) based on the geom group
  3. you get the ids (the mesh group has the .GetIDs() or .GetNodesIDs()
  4. you use mesh.moveNode(ID, pos[0], pos[1], pos[2])
    bonus, you can get the original position using .GetNodeXYZ(ID) and then replace the Y term by 0
1 Like

Oh that’s great Franco, thanks!!! I’ve effectively followed 1,2,3 (and retrieved xyz coords with GetNodeXYZ), yet it fails when I ask to MoveNode.

Traceback (most recent call last):
  File "<input>", line 1, in <module>
AttributeError: 'meshProxy' object has no attribute 'MoveNode'

I’m a bit puzzled, as if it retrieves correctly mesh.GetNodeXYZ, I don’t understand why it can’t mesh.MoveNode (on the same nodes’ ID).

the mesh instance is a salome.smesh.smeshBuilder.meshProxy object, and if I

dir(mesh)

no MoveNode method is listed (yet there is a GetNodeXYZ), maybe the class is not the right in the first place, but I’m a bit stuck now. Possibly I’m missing something relatively simple.

you have:

#Compound_1=='geometry object'
Group_1 = geompy.CreateGroup(Compound_1, geompy.ShapeType["FACE"]) #create empty group
geompy.UnionList(Group_1 , listOfFacesOfSymmetryPlane ) #add corresponding faces to group
Mesh_1 = smesh.Mesh(Compound_1,'Mesh_1') #mesh object
meshGroup=Mesh_1.GroupOnGeom(Group_1,'group name',SMESH.NODE) #create mesh group from geometry group
nodeIDs=meshGroup.GetIDs() #get the nodes ids in the group
positions=[Mesh_1.GetNodeXYZ(nodeID) for nodeID in nodeIDs]
[Mesh_1.MoveNode(nodeID,positions[n][0],0,positions[n][2]) for n,nodeID in enumerate(nodeIDs)]
1 Like

Oh that’s brilliant, thanks Franco, I’ll give it a try ASAP! Thanks!

It took me a bit as I was using

meshProxy = salome.myStudy.FindObjectByName("Mesh_2", "SMESH")[0].GetObject()

To get the object, but it was actually a meshProxy class object, almost the same properties (could access to all the nodes etc), but no MoveNodes method.

But after checking with dir() like half of the properties of salome modules :slight_smile: I managed to find that to get the mesh class out of a meshProxy, one simply needs to :

# Convert MeshProxy into mesh class
mesh=smesh.Mesh(meshProxy)

I’d like to create a script that by simply indicating a Name of the mesh (or ideally the selected item in the GUI), and a geometry (or geometry group) name, is able to retrieve everything and move all the points in the 0 (for Symmetry planes).

you can do like this:
select in the object browser the two objects (mesh and geometry object)
sorry for the ugly script

obj0=salome.IDToObject(salome.sg.getSelected(0))
obj1=salome.IDToObject(salome.sg.getSelected(1))
if 'GEOM' in str(type(obj0):
 geo=obj0
 mesh=obj1.GetMesh()
else:
 geo=obj1
 mesh=obj0.GetMesh()
 #mesh will be meshproxy, so you need to go back to the mesh object!
#you can also get I think get the geo object from geo=mesh.geom and select only one, but not sure that it carries (most probably yes) the groups, but too lazy to test..
allGroups=geompy.GetGroups(geo)
allGroups_2D=[i for i in allGroups if str(i.GetMaxShapeType())=='FACE']
meshGroups=[meshGroup=mesh.GroupOnGeom(group,'group name',SMESH.NODE) for group in allGroups_2D]
nodesIDsOfGroups=[meshGroup.GetIDs() for meshGroup in meshGroups]
positions=[[mesh.GetNodeXYZ(nodeID) for nodeID in nodeIDs] for nodeIDs in nodesIDsOfGroups]
[[Mesh_1.MoveNode(nodeID,positions[i][n][0],0,positions[i][n][2]) for n,nodeID in enumerate(nodeIDs)] for i,nodeIDs in enumerate(nodesIDsOfGroups)]

with this you have more material to work with i have ever found for salome ^^ , hope it helps you to go deeper and achieve what you want.

That’s a really neat implementation! Thanks franco. Indeed franco, the scripting is really a great feature, but somewhat difficult to learn.

I like the GUI / selection implementation, I was writing a function, (didn’t test it extensively so still wip):


import sys
import salome

import GEOM
from salome.geom import geomBuilder
import math

import  SMESH, SALOMEDS
from salome.smesh import smeshBuilder
smesh = smeshBuilder.New()



def flattenToPlane(  meshName = None, geoGroupName = None, plane = ["Y"] ):
	"""
	

Description:
	Flatten the nodes on a given geometrical entity (X, Y or Z coordinates) to 0.

Example:
	flattenToPlane( "Mesh_2", "Symmetry", "X" )
	flattenToPlane( "Mesh_2", "Symmetry", "Y" )

Arguments:
	# meshName
		Description:	 The mesh object to be modified.
		Type:			 String
		Default value:	 None

	# geoGroupName
		Description:	 The list of names of groups to export, excluding the others.
		Type:			 String
		Default value:	 None

	# plane
		Description:		The coordinate to operate on, either X, Y or Z.
		Type: 				String
		Default value:	 "Y"

Conditions of use:
	The mesh has to be computed and to contain groups describing the desired boundary conditions (inlet, outlet, wall, farfield, etc.).
	"""
	
	# Checking that user provided an input	
	if not meshName: 
		print("Incorrect input provided. meshName must be defined")
		return
        
	# Checking that user provided an input
	if not geoGroupName:
		print("Incorrect input provided. geoGroup must be defined")
		return
	
	# Checking that user provided an input that is actually available in the hdf
	try:
		meshProxy = salome.myStudy.FindObjectByName(meshName, "SMESH")[0].GetObject()
	except:
		print("The specified input for meshName can not be found")
		return

	# Checking that user provided an input that is actually available in the hdf	
	try:
		geoGroup  = salome.myStudy.FindObjectByName(geoGroupName, "GEOM")[0].GetObject()
	except:
		print("The specified input for geoGroupName can not be found")
		return
	
	groups = meshProxy.GetGroups()
	
	# Convert MeshProxy into mesh class
	mesh=smesh.Mesh(meshProxy)
	
	# Retrieves the nodes group if it is already there
	try:
		SymNodes = salome.myStudy.FindObjectByName(geoGroup, "SMESH")[0].GetObject()
	
	# Create one otherwise
	except:
		SymNodes = mesh.GroupOnGeom(geoGroup,'SymNodes',SMESH.NODE)
	
	
	# Get all the ids of the nodes that belong to the groupGeom geometric entity
	nodeIDs = SymNodes.GetIDs()
	
	# Get the nodes position	
	positions=[mesh.GetNodeXYZ(nodeID) for nodeID in nodeIDs]
	
	# Retrieve X, Z from nodes, and set Y to 0 on each node laying on symmetry
	if plane == "X" :
		[mesh.MoveNode(nodeID,0,positions[n][1],positions[n][2]) for n,nodeID in enumerate(nodeIDs)]
	elif plane == "Y" :
		[mesh.MoveNode(nodeID,positions[n][0],0,positions[n][2]) for n,nodeID in enumerate(nodeIDs)]
	elif plane == "Z" :
		[mesh.MoveNode(nodeID,positions[n][0],positions[n][1],0) for n,nodeID in enumerate(nodeIDs)]
	else :
		print("Incorrect plane input provided. plane input must be either X, Y, or Z")
		return
	
	

The control on the inputs is a bit more extensive when dealing with functions, but it opens the door to specify other inputs as well (the plane on which to proceed, for example), but the GUI selection is really cool to have a macro like function.

1 Like

Neat code I must say. I need to improve my coding readiness…
Regards and good luck.