Abaqus Python getByBoundingBox command - python

I have a 2D part in Abaqus with many partitions and I therefore want to select many edges with the getByBoundingBox command to create a surface set. This is the bit of code I have:
p = mdb.models['Model-1'].parts['Plate']
s = p.edges
edges = s.getByBoundingBox((0,0.02,0,0.003,0.04,0))
p.Surface(side1Edges=edges, name='r1')
But it gives me the following error: "edges = s.getByBoundingBox((0,0.02,0,0.003,0.04,0)) TypeError: arg1; found tuple, expecting float".
Any advice much appreciated.

The corners of the bounding box should be provided as 6 separate numbers and not as a single tuple. The solution is very simple, just change the leading "((" and trailing "))" to single "(" and ")". So the call looks like this s.getByBoundingBox(0,0.02,0,0.003,0.04,0).

this comes quite late but in case anyone enters and has the same doubt:
When telling to Abaqus which edge/face/element you are actually selecting, sometimes you need to specify the "ID" of that object, that's why it's asking for a float instead of a tuple in the error message. This can be solved as:
You select the edge/face/node/element you want:
edge = s.getByBoundingBox((0,0.02,0,0.003,0.04,0))
Create a intermediate variable to know the "ID" of the element:
edge_id = edge.id
You now can refenciate it in the dialog for creating surfaces:
p.Surface(side1Edges=p.edges[edge_id], name='r1')
In this case, you're telling Abaqus to select the edge with the id "edge_id" from all the edges that your part "p" has.
This happens many times and you've to be aware what Abaqus is expecting from the code. Sometimes can be the object itselft, a tuple of elements or simply a float expressed as a tupple e.g: edge = (number, )
Regards

I tried the modified code on a 2D plate with the following code
p = mdb.models['Model-1'].parts['Plate']
s = p.edges
edges=s.getByBoundingBox(0,0,0,25,25,1)
And it does not crash. But its not really clear how you can create a surface using this. You need to use a different strategy to achieve what you want. You can find create a surface using the 'pointOn' method.

Related

Corner Refine Method, CORNER_REFINE_SUBPIX, from AcUro with Python and OpenCV

Hi There
I want to increase the accuracy of the marker detection from aruco.detectMarkers. So, I want to use Corner Refine Method with CORNER_REFINE_SUBPIX, but I do not understand how it is implemented in python.
Sample code:
frame = cv.imread("test.png")
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
para = aruco.DetectorParameters_create()
det_corners, ids, rejected = aruco.detectMarkers(gray,dictionary,parameters=para)
aruco.drawDetectedMarkers(frame,det_corners,ids)
Things I have tried:
para.cornerRefinementMethod()
para.cornerRefinementMethod(aruco.CORNER_REFINE_SUBPIX)
para.cornerRefinementMethod.CORNER_REFINE_SUBPIX
para = aruco.DetectorParameters_create(aruco.CORNER_REFINE_SUBPIX)
para = aruco.DetectorParameters_create(para.cornerRefinementMethod(aruco.CORNER_REFINE_SUBPIX))
They did not work, I’m pretty new to python ArUco so I hope that there is a simple and obvious solution.
I would also Like to implement enclosed markers like in the Documentation(Page 4). Do you happen to know if there is a way to generate these enclosed markers in python?
Concerning the first part of your question, you were pretty close: I assume your trouble is in switching and tweaking the "para" options. If so, you only need to set the corresponding values in the parameters object like
para.cornerRefinementMethod = aruco.CORNER_REFINE_SUBPIX
Note that "aruco.CORNER_REFINE_SUBPIX" is simply an integer. You can verify this by typing type(aruco.CORNER_REFINE_SUBPIX) in the console. Thus assigning values to the "para" object works like mentioned above.
You might also want to tweak the para.cornerRefinementWinSize which seems to be implemented in units of code pixels, not actual image pixel units.
Concerning the second part, you might have to write a function, that adds the boxes at the corner points, which you can get using the detectMarker function. Note that the corner points are always ordered clockwise, thus you can easily assign the correct offset values (like "up & left", "up & right" etc.).
para.cornerRefinementMethod = 1
may work.

How to create set from list of sets in Python?

In abaqus Python script, several Plies have a large number of copies, each of which has many fibers. In each Fiber, a set of edges has been selected: App1-1, App1-2, ..., App99-1, App99-2, ..., App99-88. How to create a new set that will contain all or some of these set of edges?
Thank you.
Code:
allApps=[]
...
for i in range(Plies):
...
for j in range (Fiber):
appSet = Model.rootAssembly.Set(edges=
Model.rootAssembly.instances['Part'+str(i+1)+'-'+str(1+j)].edges[0:0+1],
name='App'+str(i+1)+'-'+str(1+j))
allApps.append(appSet)
I can guess it should be something like this:
Model.rootAssembly.Set(name='allAppEdges', edges=.?.Array(allApps))
but I'm not sure about this and I have no idea about correct syntax
I tested the following on a simple part and it worked for me. I think you could adapt this to achieve what you're trying to do for your specific model. The key is the part.EdgeArray type. For whatever reason Abaqus requires your edges be supplied within that type, rather than a simple list or tuple. The Abaqus documentation is not clear on this, and when you pass a list of edges it will fail with a vague error: Feature creation failed.
from abaqus import *
import part
mdl = mdb.models['Model-1']
inst = mdl.rootAssembly.instances['Part-1-1']
# Loop through all edges in the instance and add them to a list
my_edges = []
for e in inst.edges:
my_edges.append(e)
# Create a new set with these edges
#mdl.rootAssembly.Set(name='my_edges', edges=my_edges) # This will fail because my_edges needs to be an EdgeArray
mdl.rootAssembly.Set(name='my_edges', edges=part.EdgeArray(my_edges))
For others that may find themselves here - similar types are available for vertices, faces, and cells: part.VertexArray, part.FaceArray, and part.CellArray.

Maya, Python, How do i get the name of an object based on vertex selection?

I got the code working like this until i realized that the vertex index changes for geometry with over 100 vertices...
I assumed i could just split the string and everything would be dandy
import maya.cmds as mc
selPoints = mc.ls(sl = True) # list of names of selected vertices
objName = (str(selPoints[0]))[:-9]
print selPoints
print objName
Heres what it returned:
[u'pCylinder25.vtx[4]', u'pCylinder25.vtx[24]']
pCylinder
I'm trying to hack off the portion with '.vtx[integer]'
I may be going about this completely wrong, and there may be a dead simple way to do this.
Thanks
You can get the object from any valid selection string with the -o flag:
cmds.ls("pCube1.vtx[0]", o=True)
# pCubeShape1
Note that will be the shape, not the transform -- that's Maya being pedantic but it is correct. The transform would be
cmds.listRelatives(cmds.ls("pCube1.vtx[0]", o=True), p=True)
You may also find it helpful to split the components using partition:
object, _, component = "pCube1.vtx[0]".partition(".")
where the _ is python slang for 'ignore me'.
Wouldn't it be awesome if it were easy to get the object from Maya? From experience, I know it can be frustrating since MEL/maya.cmds doesn't use an object-oriented approach.
Anyhow, you should refer to the documentation often for more info on the variety of string methods you can use. Really comes in handy all the time!
To answer your question, you can use .split or .find, whichever you prefer.
print selPoints[0].split('.vtx')[0]
print selPoints[0][0:selPoints[0].find('.vtx')]
The split method returns a list of strings created by the delimiter string '.vtx'. Then, taking the first element from that list will always be the object name.
The find method returns the index of the substring '.vtx', so the second example simply uses slicing syntax to return the correct string.
just for stuff, using vanilla maya commands:
as mentioned with ls:
cm.ls("pCube1.vtx[0]", o=1) # will return shape pCubeShape1
with plugNode (opposite plugAttr):
cm.plugNode("pCube1.vtx[0]") # will return transform pCube1

Scene object selective export using Blender Python API 2.6

I am writing a custom export script to parse all the objects in a blender file, filter them by name, then check to make sure that they meet some specific criteria.
I am using Blender 2.68a. I've created a blender file with some basic 2d and 3d meshes, as well as some that should fail my test criteria. I am working in the internal Python console inside of Blender. This is the only way to work with the blender python API, as their python environment is customized.
I've sorted how to iterate through the objects using a for loop and the D.objects iterator, then check for name matches using regular expressions, and then get a mesh from the object using:
mesh = obj.to_mesh(C.scene, True, 'RENDER') #where obj is an bpy.data.object[index] in the scene
mesh.update(True, True)
mesh.polygons[index].<long list of possible functions>
lets me access an array of polygons to know if there is a set of vertices with edges that form a polygon, and what their key values are.
What I can't sort out is how to determine from the python console if a poly is a face or just a poly. Is there a built in function, or what tests can i perform to programmatically determine this? For example, I can have a mesh 4 vertices with 4 edges that do not have a face, and I do not want to export this, but if i were to edit the same 4 vertices/edges and put a face on it, then it becomes a desirable export.
Can anyone explain the bpy.data.object data structure or explain where the "faces" are stored? it seems as though it would be a property of the npolys themselves, but the API does not make it obvious. Any assistance in clarifying this would be greatly appreciated. Cheers.
So, i asked this question on the blender.org forums, http://www.blender.org/forum/viewtopic.php?t=28286&postdays=0&postorder=asc&start=0 and a very helpful individual has helped me over the past few days each time I got stuck in my own efforts to plow through this.
The short list of answers is:
1) All polygons are faces. If it isnt stored as a polygon, it isnt a face.
2) using the to_mesh() function on an object returns a copy of the function, and so any selections that are done to the copy are not reflected by the context and therefore the methodology I was using was flawed. The only way to access the live object is through use of:
bpy.data.objects[<index or object name>].data.vertices[<index>].co[<0,1,2> which correspond to x,y,z respectively]
bpy.data.objects[<index or object name>].data.polygons[<index>].edge_keys
The first one gives you access to an ordered index of all the vertices in the object(assuming it is of type 'MESH'), and their coordinates.
The second one gives you access to an 2d array of ordered pairs which represent edges. The numbers it contains within the tuples correspond to the index value in the vertices list from the first command, and so you can get the coordinates which the edge goes between.
One can also create a new BMesh object and copy the object you are interested in into the BMesh. This gives you a lot more functionality that you can't access on the live object. The code in answer 3 shows an example of this.
3)see below for answer to my question regarding checking faces in a mesh.
it turns out that one way to determine if an object has faces and all edges are a part of a face is to use the following code snippet written by a helpful user, CoDEmanX on the above thread.
import bpy, bmesh
for ob in bpy.context.scene.objects:
if ob.type != 'MESH':
continue
bm = bmesh.new()
bm.from_object(ob, bpy.context.scene)
if len(bm.faces) > 0 and 0 not in (len(e.link_faces) for e in bm.edges):
print(ob.name, "is valid")
else:
print(ob.name, "has errors")
I changed this a little bit, as i didnt want it to loop through all the objects, and instead i've got this as a function that returns true if the object passed in is valid and false otherwise. This lets me serialize my calls so that my addon only tries to validate the objects which have a name which matches a regex.
def validate(obj):
import bpy, bmesh
if obj.type == 'MESH':
bm = bmesh.new()
bm.from_object(obj, bpy.context.scene)
if len(bm.faces) > 0 and 0 not in (len(e.link_faces) for e in bm.edges):
return True
return False

How to get edge indices from selection?

Is there's a way to get the indices properly from a Pymel/Maya API function?
I know Pymel has a function called getEdges() however according to their docs this get's them from the selected face, however I just need them from the selected edges.
Is this possible?
While your answer will work theodox, I did find a much simpler resolution, after some serious digging!
Turns out, hiding and not very well documented, was a function ironically called indices(), I did search for this but nothing came up in the docs.
Pymel
selection[0].indices()[0]
The above will give us the integer of the selected edge. Simple and elegant!
Do you mean you just the expanded list of selected edges? That's just FilterExpand -sm 32 or cmds.filterExpand(sm=32) or pm.filterExpand(sm=32) on an edge selection. Those commands are always strings, you grab the indices out them with a regular expression:
# where objs is a list of edges, for example cmds.ls(sl=True) on an edge selection
cList = "".join(cmds.filterExpand( *objs, sm=32))
outList = set(map ( int, re.findall('\[([0-9]+)\]', cList ) ) )
which will give you a set containing the integer indices of the edges (I use sets so its easy to do things like find edges common to two groups without for loops or if tests)

Categories