getting the whole border edges from the mesh in python - python

I am trying to create a polygon from a mesh. My idea is to get all the border edges and make a polygon.i found somewhat similar answer to mine in this question
Get border edges of mesh - in winding order
I tried to implement the algorithm mention there but i am only getting a small triangle as my border edges
import plyfile
def edges_to_polygon_loop(edges):
# Initialize an empty polygon loop
polygon_loop = []
# Pick an unvisited edge segment
start_edge = edges[0]
v_start, v_next = start_edge
polygon_loop.append(v_start)
polygon_loop.append(v_next)
# Initialize a set to keep track of visited edges
visited_edges = set()
visited_edges.add(start_edge)
# Iterate until we get back to the start vertex
while v_next != v_start:
# Find the next unvisited edge segment
for edge in edges:
if edge not in visited_edges:
v_i, v_j = edge
if v_i == v_next:
polygon_loop.append(v_j)
v_next = v_j
visited_edges.add(edge)
break
elif v_j == v_next:
polygon_loop.append(v_i)
v_next = v_i
visited_edges.add(edge)
break
# Return the polygon loop
return polygon_loop
with open('M:\\volume.ply', 'rb') as f:
# Read the .ply file
ply = plyfile.PlyData.read(f)
# Extract the vertex and face data
vertices = ply['vertex']
faces = ply['face']
# Initialize an empty list of edges
edges = []
# Iterate over the faces
for face in faces:
# Get the indices of the vertices in the face
vertex_indices = face['vertex_indices']
# Add the edges to the list
for i in range(len(vertex_indices)):
# Get the indices of the endpoints of the edge
v1_index = vertex_indices[i]
v2_index = vertex_indices[(i + 1) % len(vertex_indices)]
# Get the coordinates of the endpoints
v1 = (vertices[v1_index]['x'], vertices[v1_index]['y'], vertices[v1_index]['z'])
v2 = (vertices[v2_index]['x'], vertices[v2_index]['y'], vertices[v2_index]['z'])
# Add the edge to the list
edges.append((v1, v2))
# Print the edges
polygon = edges_to_polygon_loop(edges)

You would need to eliminate inner edges first, then you can compose the outer loop.
:
# Extract the vertex and face data
vertices = ply['vertex']
faces = ply['face']
# Initialize an empty list of indices-pairs
pairs = []
# Iterate over the faces
for face in faces:
# Get the indices of the vertices in the face
vertex_indices = face['vertex_indices']
# Add the edge-indices to the list
for i in range(len(vertex_indices)):
# Get the indices of the endpoints of the edge
v1_index = vertex_indices[i]
v2_index = vertex_indices[(i + 1) % len(vertex_indices)]
if ((v2_index, v1_index) not in pairs):
pairs.append((v1_index, v2_index))
else:
# Remove inner edge
pairs.remove((v2_index, v1_index))
# Initialize an empty list of edges
edges = []
# Add the edges to the list
for (v1_index, v2_index) in pairs:
# Get the coordinates of the endpoints
v1 = (vertices[v1_index]['x'], vertices[v1_index]['y'], vertices[v1_index]['z'])
v2 = (vertices[v2_index]['x'], vertices[v2_index]['y'], vertices[v2_index]['z'])
# Add the edge to the list
edges.append((v1, v2))
# Print the edges
polygon = edges_to_polygon_loop(edges)

Related

Create a mesh with boundary markers in Python, Fenics

My aim is to create a mesh in Python and setting markers on some 1-dimensional subset.
Up until now, I have always creates a set, for example a rectangle in gmsh, then put for example a circle in it. Then gmsh puts a mesh on my structure and I can mark the boundary of the rectangle and of the circle as facets (as xdmf files). I can then let Python read my mesh and boundary facets and using it, f.e. to solve PDEs.
What I want to do now is the following: I still want to have my rectangle with a mesh, but instead of defining the facet markes in gmsh, I want to define them using the image of a function.
More precicely: Instead of creating a circle in gmsh, I want to consider, for example, the function
Then I want to use as my facet and mark it in my mesh.
Is there a way to do this? I feel kind of lost here.
I am not sure if I understood everything in your question correctly, but here is some code that might help you. One thing I do not know is how to add element edges to physical groups in gmsh. But maybe you can figure that out.
So here is the code:
import gmsh
import numpy as np
def mapping(point):
x = point[0]
y = point[1]
z = point[2]
result = [2*x,3*y,z]
return result
def inverseMapping(point):
x = point[0]
y = point[1]
z = point[2]
result = [(1/2)*x,(1/3)*y,z]
return result
def getNodes():
nodeTags, nodeCoord, _ = gmsh.model.mesh.getNodes()
nodeCoord = np.reshape(nodeCoord,(len(nodeTags),3))
return nodeTags, nodeCoord
def getEdgeNodeCoordinates():
edgeTags, edgeNodes = gmsh.model.mesh.getAllEdges()
edgeNodes = np.reshape(edgeNodes,(len(edgeTags),2))
nodeTags, nodeCoord = getNodes()
coord = []
for i in range(0,len(edgeTags)):
tagNode1 = edgeNodes[i][0]
tagNode2 = edgeNodes[i][1]
nodeIndex1 = list(nodeTags).index(tagNode1)
nodeIndex2 = list(nodeTags).index(tagNode2)
nodeCoord1 = nodeCoord[nodeIndex1]
nodeCoord2 = nodeCoord[nodeIndex2]
coord.append([nodeCoord1,nodeCoord2])
return edgeTags, edgeNodes, nodeTags, coord
def getInverseNodeCoordinates(edgeNodeCoordinates):
coord = []
for edgeNodes in edgeNodeCoordinates:
nodeCoord1 = edgeNodes[0]
nodeCoord2 = edgeNodes[1]
newCoord1 = inverseMapping(nodeCoord1)
newCoord2 = inverseMapping(nodeCoord2)
coord.append([newCoord1, newCoord2])
return coord
def checkIntersection(edgeTags, edgeNodeCoordinates, inverseCoordinates):
intersectingEdgeTags = []
intersectingEdgeNodeCoord = []
# 1 = inside, 0 = outside
for i in range(0,len(inverseCoordinates)):
pair = inverseCoordinates[i]
coord1 = pair[0]
coord2 = pair[1]
e1 = 1 if np.linalg.norm(coord1) <= 1 else 0
e2 = 1 if np.linalg.norm(coord2) <= 1 else 0
s = e1 + e2 # s = 0 --> both nodes outside of manifold
# s = 1 --> one node inside and one node outside of manifold
# s = 2 --> both nodes inside of manifold
if s == 1:
intersectingEdgeTags.append(edgeTags[i])
intersectingEdgeNodeCoord.append(edgeNodeCoordinates[i])
return intersectingEdgeTags, intersectingEdgeNodeCoord
def visualizeEdges(intersectingEdgeNodeCoord):
for pair in intersectingEdgeNodeCoord:
p1 = pair[0]
p2 = pair[1]
t1 = gmsh.model.occ.addPoint(p1[0],p1[1],p1[2])
t2 = gmsh.model.occ.addPoint(p2[0],p2[1],p2[2])
line = gmsh.model.occ.addLine(t1, t2)
gmsh.model.occ.synchronize()
gmsh.model.setColor([(1,line)], 255, 0, 0)
gmsh.model.occ.synchronize()
gmsh.initialize()
# Create a rectangle which will be meshed later.
tag_vol_1 = gmsh.model.occ.addRectangle(-3, -4, 0, 6, 8)
# Sample the S1 manifold with n_points
S1_sampling_points = []
n_points = 100
maxAngle = 2*np.pi
angle = maxAngle/n_points
z = 0
for i in range(0,n_points):
x = np.cos(i*angle)
y = np.sin(i*angle)
S1_sampling_points.append([x,y,z])
# Map the sampled S1 points to 2*x, 3*y, z.
# This is only for "visualization" via a spline.
mappedPoints = []
mappedPointTags = []
for point in S1_sampling_points:
mappedPoint = mapping(point)
tag = gmsh.model.occ.addPoint(mappedPoint[0], mappedPoint[1], mappedPoint[2])
mappedPointTags.append(tag)
# Here the spline fitting is performed
# You will see it visualized when gmsh opens.
tagMappedS1 = gmsh.model.occ.addSpline(mappedPointTags + [mappedPointTags[0]]) # make the spline periodic by setting the last point equal to the first one
gmsh.model.occ.synchronize()
# Mesh the rectangle and tell gmsh to create edges which we can access.
gmsh.model.mesh.generate(2)
gmsh.model.mesh.createEdges() # You need to call this before using gmsh.model.mesh.getAllEdges()
# Get all these self-explanatory things
edgeTags, edgeNodes, nodeTags, edgeNodeCoordinates = getEdgeNodeCoordinates()
# Calculate the inverse-mapped coordinates of all nodes.
# With this we can just check if the transformed nodes are inside a circle of radius 1 or outside.
# If for every egde one node is inside, and the other node is outside the circle, then the edge is
# intersected by the mapped manifold f(S1) --> (2*x, 3*y, z). We then save the tag of such an edge.
inverseCoordinates = getInverseNodeCoordinates(edgeNodeCoordinates)
intersectingEdgeTags, intersectingEdgeNodeCoord = checkIntersection(edgeTags, edgeNodeCoordinates, inverseCoordinates)
# Here all intersecting edges are created within gmsh so you can see it.
# This is for visualization only. A lot of nodes with the same coordinates are created here twice.
visualizeEdges(intersectingEdgeNodeCoord)
gmsh.fltk.run()
gmsh.finalize()
And the result in gmsh looks like this:

Indexerror on prim's algorithm

I'm running this prim's algorithm code with negative weights, but I'm getting Indexerror: list assignment index out of range right here adjMatrix[G[i][0]][G[i][1]] = G[i][2], and I don't know what is the problem.
thanks for your time and help.
def createAdjMatrix(V, G):
adjMatrix = []
# create N x N matrix filled with 0 edge weights between all vertices
for i in range(0, V):
adjMatrix.append([])
for j in range(0, V):
adjMatrix[i].append(0)
# populate adjacency matrix with correct edge weights
for i in range(0, len(G)):
#IndexError starts right here
adjMatrix[G[i][0]][G[i][1]] = G[i][2]
adjMatrix[G[i][1]][G[i][0]] = G[i][2]
return adjMatrix
def prims(V, G):
# create adj matrix from graph
adjMatrix = createAdjMatrix(V, G)
# arbitrarily choose initial vertex from graph
vertex = 0
# initialize empty edges array and empty MST
MST = []
edges = []
visited = []
minEdge = [None,None,float('inf')]
# run prims algorithm until we create an MST
# that contains every vertex from the graph
while len(MST) != V-1:
# mark this vertex as visited
visited.append(vertex)
# add each edge to list of potential edges
for r in range(0, V):
if adjMatrix[vertex][r] != 0:
edges.append([vertex,r,adjMatrix[vertex][r]])
# find edge with the smallest weight to a vertex
# that has not yet been visited
for e in range(0, len(edges)):
if edges[e][2] < minEdge[2] and edges[e][1] not in visited:
minEdge = edges[e]
# remove min weight edge from list of edges
edges.remove(minEdge)
# push min edge to MST
MST.append(minEdge)
# start at new vertex and reset min edge
vertex = minEdge[1]
minEdge = [None,None,float('inf')]
return MST
graph = [
[0,1,6807],
[1,2,-8874],
[2,3,-1055],
[3,4,4414],
[4,5,1728],
[5,6,-2237],
[6,7,-7507],
[7,8,7990],
[8,9,-5012],
[9,10,7353]]
## pass the # of vertices and the graph to run prims algorithm
print (prims(11, graph))
Edit: this is the traceback
adjMatrix[G[i][0]][G[i][1]] = G[i][2]
IndexError: list assignment index out of range

Python Connected Components edges list

I use these algorithms in python for finding connected components from edges.
components = []
def connected_components(pairs):
for a, b in pairs:
for component in components:
if a in component:
for i, other_component in enumerate(components):
if b in other_component and other_component != component: # a, and b are already in different components: merge
component.extend(other_component)
components[i:i+1] = []
break # we don't have to look for other components for b
else: # b wasn't found in any other component
if b not in component:
component.append(b)
break # we don't have to look for other components for a
if b in component: # a wasn't in in the component
component.append(a)
break # we don't have to look further
else: # neither a nor b were found
components.append([a, b])
return components
This algorithms return components like this :
[ [n1,n2,n4],[n3,n5] ]
I would like to have the list of all edges in connected components like this :
[ [(n1,n2),(n2,n4),(n4,n1)],[(n3,n5)] ]
in the same order of the previous list but i don't know how creates this list
Thank you for your help.
Note: This doesn't require any python dependency.
I will share my approach, with recursive depth-first search. I am assuming graph is bi-directional and the following code can be easily manipulated for directed graph.
pairs = [] // edge list
adj_list = {} // adjacency list
vis = [] // visited_list
connected_components = [] // contains all the connected components
temp_component = []
// basic depth first search
def dfs( node ):
vis[node] = "true"
temp_component.append(node)
for neighbour in adj_list[node]:
if vis[neighbour] == "false":
dfs(neigbour)
//main
for a,b in pairs:
if a not in adj_list:
adj_list[a] = []
if b not in adj_list:
adj_list[b] = []
adj_list[a].append(b)
adj_list[b].append(a)
vis["a"] = "false"
vis["b"] = "false"
for a,b in pairs:
temp_component = []
if vis[a] == "false":
dfs(a)
if len(temp_component) > 0:
connected_components.append(temp_component)
// once you have connected components you can get the edge lists in connected component as well
answer = []
for component in connected_components:
temp_pairs = [] // contains the pair of edges for the current connected component
for node in component:
for i,j in pairs:
if (node == i or node == j) and (i,j) not in temp_node:
temp_node.append(i,j)
answer.append(temp_pairs)
Create a mini graph in python using apgl library.
You can use SparseGraph module from apgl. from apgl.graph import SparseGraph
Initiate a sparsegraph with number of nodes required.
graph = SparseGraph(num_vertices)
Then you can create a mini graph by adding edges between nodes of graph.
graph.addEdge(component1, component2)
Then just use findConnectedComponents function to find connected components.
graph.findConnectedComponents()
I know this is an old question, but I came across the same problem and was not glad with the performance of the given answers. So I wanted to share my own solution using scipy's connected_components and shortest_path functions to handle arbitrary edge-soups.
from scipy.sparse import csr_matrix, csgraph
import numpy as np
def coords_to_indices(coords):
"""
Decompose a set of primitives defined by vertex-coordinates to their shared vertices and primitive indices
Parameters
----------
coords : array like
A NxMxD array, where N is the number of primitives, M the number of vertices per primitive and D the number of dimensions of each vertex
Returns
-------
vertices : NDArray
UxD array containing the unique vertices
primitives : NDArray
NxM array containing the indices of vertices building the primitives
"""
coords = np.asarray(coords)
vert_dim = coords.shape[-1]
prim_dim = coords.shape[1]
vertices, rev_indx = np.unique(coords.reshape((-1, vert_dim)), axis=0, return_inverse=True)
primitives = rev_indx.reshape((coords.shape[0], prim_dim))
return vertices, primitives
def is_ordered(edge_indices) -> bool:
"""
Check if the edges are ordered or not
Parameters
----------
edge_indices : Nx2 array of indices
Indices of the edge vertices
Returns
-------
bool
True, if all edges are in order. That means, every edge is connected with the following one by its second vertex.
"""
edge_indices = np.asarray(edge_indices)
e_flat = edge_indices.flatten()[1:-1]
return all(e_flat[1::2] - e_flat[::2] == 0)
def reorder_edges(connected_edges):
"""
Reorder an unsorted list of edges (indices Nx2) or coordinates (Nx2xM) so that:
- Each edge is connected to the next edge
- The connection is made from the second vertex to the first vertex of the following edge
Parameters
----------
connected_edges : array-like, Nx2 indices or Nx2xM coordinates
edges that build the segment. all edges have to be connected, but every vertex has to be shared by exactly 2 edges.
If the segment is not closed, two vertices are allowed to rise up in only one edge (the ends).
Returns
-------
NDArray - like the input
The edges, reordered
"""
connected_edges = np.asarray(connected_edges)
if is_ordered(connected_edges):
return connected_edges
if connected_edges.ndim == 3 and connected_edges.shape[1] == 2 and np.issubdtype(connected_edges.dtype, np.floating):
# vertex coordinates given, transform to edge indices and back
verts, edges = coords_to_indices(connected_edges)
e_ordered = reorder_edges(edges)
return verts[e_ordered]
assert np.issubdtype(connected_edges.dtype, np.integer) and connected_edges.ndim == 2 and connected_edges.shape[1] == 2, "Wrong shape"
edges = connected_edges
n_edges = edges.shape[0]
n_verts = edges.max() + 1
# find the unique indices and counts of the vertices
idxs, counts = np.unique(connected_edges.flat, return_counts=True)
# translate edges to monotone space
if np.all(counts == 2):
# cyclic contour (all vertices are counted twice)
# wo have to cut the cycle and restore it afterwards. Otherwise, its hard to follow the two valid paths
edges = edges[1:]
n_edges -= 1
new_edges = reorder_edges(edges)
# add the missing piece. Due to the strict order of the indices, this should always be between the very first and very last index
new_edges = np.row_stack((new_edges, (new_edges[-1, -1], new_edges[0, 0])))
return new_edges
# open contour
# find the open ends in the chain of segments
ends = idxs[counts == 1]
assert len(ends) == 2, "More than 2 unconnected segments found. not a contiguous contour"
# lets begin the connection walk on one of the end-segments. I choose the minimum, so maybe the indices are rising again
start_index, end_index = np.sort(ends)
# build sparse matrix of edge relations
csm = csr_matrix((np.full(n_edges, 1, dtype=np.bool_), (edges[:, 0], edges[:, 1])), (n_verts, n_verts))
# get shortest path and number of hops
n_hops, prev_idx = csgraph.shortest_path(csm, directed=False, indices=start_index, return_predecessors=True, unweighted=True)
# limit to the existing vertices
n_hops = n_hops[idxs]
prev_idx = prev_idx[idxs]
vert_order = np.argsort(n_hops)
assert np.all(np.isfinite(n_hops)), "Unreachable parts detected"
# check that the hops are increasing monotonously, otherwise something went wrong
dst = n_hops[vert_order]
assert np.all(dst[1:] - dst[:-1] == 1), "path not contiguous... something went wrong"
# get indices of neighbors
ordered_idxs = prev_idx[vert_order][1:]
# add the farthest node
ordered_idxs = np.append(ordered_idxs, end_index)
new_edges = np.column_stack((ordered_idxs[:-1], ordered_idxs[1:]))
return new_edges
def find_connected(edges):
"""
Find and return connected components in a soup of edges. Each component will be returned as an ordered list of edges
Parameters
----------
edges : array_Like
A list of edges. Either as a Nx2 list of indices or as a Nx2xD list of vertex coordinates per edge
Returns
-------
List[NDArray]
A list of Mx2 or Mx2xD arrays (depending on the input type), each containing an ordered list of connected (and maybe cyclic) edges
"""
if edges.ndim == 3 and edges.shape[1] == 2 and np.issubdtype(edges.dtype, np.floating):
# vertex coordinates given, transform to edge indices and back
verts, edges = coords_to_indices(edges)
connected_edges = find_connected(edges)
# return the result as coordinate array
return [verts[e] for e in connected_edges]
# get number of edges and maximum number of vertices
n_edges = edges.shape[0]
n_verts = edges.max() + 1
# create a sparse matrix of the relations
csm = csr_matrix((np.full(n_edges, 1, dtype=np.bool_), (edges[:, 0], edges[:, 1])), (n_verts, n_verts))
# get number and labels of the connected components. labels refer to the vertices
n_c, labels = csgraph.connected_components(csm, directed=False, return_labels=True)
# get the association to the edges. should not matter which column
edge_labels = labels[edges]
assert np.all(edge_labels[:, 0] == edge_labels[:, 1])
connected_edges = []
for label in range(n_c):
# get mask for current label:
edge_mask = edge_labels[:, 0] == label
if not np.any(edge_mask):
#this vertex was no member of any edge
continue
# iterate labels and gather all edges of that label
edges_l = edges[edge_mask, :]
# reorder if necessary
if not is_ordered(edges_l):
edges_l = reorder_edges(edges_l)
connected_edges.append(edges_l)
return connected_edges
Short Example:
def makePoly(npts=360, r=10):
angles = np.linspace(0, 2*np.pi, npts)
x = np.sin(angles) * r
y = np.cos(angles) * r
return x, y
# create a polygon
verts = np.array(makePoly(16)).T
# create the edges
edges = np.column_stack((np.arange(verts.shape[0]), np.arange(verts.shape[0])+1))
# close the loop
edges[-1, -1] = 0
# shuffe all edges
np.random.seed(123)
np.random.shuffle(edges)
# remove some edges, so we get multiple chains
edges = np.delete(edges, [1, 2, 3], axis=0)
# swap some vertex orders
swap = [4, 5, 6, 7, 8, 9]
edges[swap, :] = edges[swap, :][:, [1, 0]]
# now reorder everything
edges_ordered = find_connected(edges)
print(edges_ordered)
Result is
[
array([[ 0, 15],
[15, 14],
[14, 13],
[13, 12],
[12, 11]]),
array([[1, 2],
[2, 3],
[3, 4]]),
array([[ 5, 6],
[ 6, 7],
[ 7, 8],
[ 8, 9],
[ 9, 10]])
]

python maya: Align group pivot to supplied position

What I have here is a script where I create a bundle of circles and place them into a group. I then center the groups pivot to the bounding box. Lastly I'm wanting to align the groups position to the location in space by first collecting the locators position. How can I fix this? Currently it doesn't seem to align properly. The error occurs in the last line of the code. Thank in advanced guys.
import maya.cmds as cmds
import random
cmds.file(new=True, f=True)
a = cmds.spaceLocator(n='pipeCtrl_00')
x = random.uniform(-10,10)
z = random.uniform(-10,10)
cmds.xform(a, t=(x,0,z) )
#select all the locators you want to make curves on
locList = cmds.ls(type='locator')
nodes = maya.cmds.listRelatives(locList, type='transform', parent=True)
sorted(nodes)
points = []
#get position points
for n in nodes:
pos = cmds.xform(n, q = True, ws = True, t = True)
points.append(pos)
# create 2D grid of circles
numRows = 4
numColumns = 4
#create empty group for nodes
nodeGroup = cmds.group(em=True, name='Pipe_group_00')
for r in range(0,numRows):
for c in range(0,numColumns):
# Create circle shape and transform it
node = cmds.circle(ch=True, o=True, nr=(0, 0, 1), c=(0, 0, 0), r=.5)
cmds.xform(node, t=(r*(.5*2), c*(.5*2), 0) )
# Parent node under the group node
cmds.parent(node[0], nodeGroup, relative=False)
# center pivot of group node
cmds.xform(nodeGroup, cp=True)
# align group to path
# ------------------------------------------------------------------
print points[0]
cmds.xform(nodeGroup, ws=True, t=points[0] )
I think you want
cmds.xform(nodeGroup, cp=True, p=True)
check the docs for the -p flag

python + maya: Returns me a list of nodes with incorrect names

I've created a function which creates a grid of circles and I need to collect the circle nodes created into a list so I can later manipulate the nodes. The problem is that I noticed the nodeList is given the nodes name before it's auto-renamed by maya to be unique. You'll notice when you run this script that the collected names are all the same but when you selected them in maya they are incremented to be unique.
I'm returned this
[u'mainShape_00', u'makeNurbCircle1']
[u'|mainShape_00', u'makeNurbCircle2']
[u'|mainShape_00', u'makeNurbCircle3']...
When it should be
[u'mainShape_00', u'makeNurbCircle1']
[u'|mainShape_01', u'makeNurbCircle2']
[u'|mainShape_02', u'makeNurbCircle3']...
Here is the script
# Import Modules
import maya.cmds as cmds
import random
# Scene setup
try:
cmds.select(all=True)
cmds.delete()
except:
pass
# create 2D grid of circles
numRows = 4
numColumns = 3
radiusMin = .1
radiusMax = .75
#create empty group for nodes
nodeGroup = cmds.group(em=True, name='main_group_00')
nodeList = []
for r in range(0,numRows):
for c in range(0,numColumns):
# Calculate random radius
radius = random.uniform(radiusMin,radiusMax)
# Create circle shape and transform it
node = cmds.circle(n='mainShape_00', ch=True, o=True, nr=(0, 0, 1), c=(0, 0, 0), r=radius)
cmds.xform(node, t=(r*(radiusMax*2), c*(radiusMax*2), 0) )
# Parent node under the group node
cmds.parent(node[0], nodeGroup, relative=False)
# Append nodes to list
nodeList.append(node)
for n in nodeList:
shape = n
print shape
node is 'mainShape_00' because at that time, that's what it's named. There is no collision until it's parented under nodeGroup. Grab the real name after parenting:
node[0] = cmds.parent(node[0], nodeGroup, relative=False)[0]
This substitutes the original node[0] with the newly parented node[0]
Why not naming yourself your nodes as this :
x = 0
padding = str(x).zfill(2)
mainShapeName = 'mainShape_' + padding
x += 1
# Create circle shape and transform it
node = cmds.circle(n=mainShapeName, ch=True, o=True, nr=(0, 0, 1), c=(0, 0, 0), r=radius)
cmds.xform(node, t=(r*(radiusMax*2), c*(radiusMax*2), 0) )
By incrementing yourself, you avoid maya problems.
You should even gave unique name throught every groups.
Cheers.

Categories

Resources