I have a bit of a specific case that I can't seem to figure out a solution to. I'm writing a shipping label template object in ReportLab for Python. I have the following code that creates a barcode as a drawing.
uspsBarcode = createBarcodeDrawing('USPS_4State', value=self.imbval, routing=self.zip4.replace('-',''))
print uspsBarcode.getBounds() # print out of position and scale
Using that code, I later add it to a shape group, and that shape group gets returned. So I need the barcode to be positioned relative to the object. I can't seem to find any way to pass positioning to this, even though I've dug through the inheritance. Though as you can see from the print, positioning is set somwhere.
Just for anyone else that runs across this issue. It turns out that if you put the barcode drawing in a shape group, the shape group container can be moved around numerically with the shift function.
uspsBarcode = shapes.Group()
bc = createBarcodeDrawing('USPS_4State', value=self.imbVal, routing=self.zip4.replace('-',''))
uspsBarcode.add(bc)
uspsBarcode.shift(self.x+(s*0.2), self.y)
Related
I am trying to generalize part of script for element selection in pre-processing and using the element sets for use in post processing. I have searched and thought I did using one of the othr questions, but I having a different error. I ran this in Abaqus PDE 2017 version.
I have read these questions at SO :
1. Selecting multiple partitioned regions in ABAQUS with findAt for setting mesh controls
2. Abaqus: script to select elements on a surface
length=float(120)
height1=float(3)
height2=float(0.7)
th=float(45)
ElemSize=float(0.1)
dms=float(4)
crack_offset=float(8.5)
a = mdb.models['sdfdsf'].rootAssembly
RP_Cent = a.ReferencePoint(point=(length-th+crack+crack_offset,2*height1+height2,0))
a.features.changeKey(fromName='RP-1', toName='RP_Cent')
e1 = a.instances['Upper_Adh'].elements
Cent = e1.getByBoundingBox( length-th+crack+crack_offset-dms/2, 2*height1+height2-ElemSize, 0,
length-th+crack+crack_offset+dms/2, 2*height1+height2, 0 )
a.Set(elements=Cent, name='Centroid_Elements')
I had expected the created set to be of element type and have 10 elements, however the set created is of geometry type and ofcourse has no elements.
Error-screenshot
All help is appreciated.
From the code you show us it seems that your bounding box is of 0 height. That method returns elements that are within the bounding box. Try to make it thicker. Also try printing the size of Cent so you can diagnose if you got the right number of elements.
#UN4
Hi sorry for the late reply. The reason it is 0 height, its because I am working on a 2D model. Having said that I did try to change the height, I am still getting the same error.
Additionally printing Cent does not help. There is no additional response and the error persists.
Also could you let me know how to extract the x,y,z co-ordinates for a particular reference point in pre-processing.
New to python (within the past couple months) and I'm enjoying it. It is easy to understand and to use. Except in this case!
I wrote a script that works for logging into a site with selenium, navigating to a particular page, entering date values and showing the results I need. It scrolls into position, then I need to screenshot just a portion of that page. At first I would just have it save the whole screen and I would crop it later, but I believe it is possible (and more efficient) to only screenshot the area I need.
I have tried multiple methods of locating where the corner would start and selecting the region, and ultimately decided to go with pyautogui using locateCenterOnScreen of a sample screenshot of just the spot I want, where the center marks the upper-left corner of the entire part I want to save. This ensures that if the window is not in the same place every time, it will accurately save the correct region no matter where it is.
Thus, using
location = pyautogui.locateCenterOnScreen('ctr_cornerScreenshot.PNG')
returns a correct (X, Y) value to properly locate the coordinates for the screenshot. Then, I'm using
screengrabPic = pyautogui.screenshot(region=(location, 720, 340))
screengrabPic.save("transactions.png")
the error turns out as
AssertionError: region argument must be a tuple of four ints
I'm sure because of the region parameter passed in as location, and I've tried (int(location) or 'locationX, locationY,
I figured I'd reach out for help rather than spin my wheels too much more. Thanks!
OK, so I did a lot more trial and error then found the final solution.
location = pyautogui.locateCenterOnScreen('ctr_cornerScreenshot.PNG')
print(location)
locationX, locationY = pyautogui.locateCenterOnScreen('ctr_cornerScreenshot.PNG')
screengrabPic = pyautogui.screenshot(region=(locationX, locationY, 720, 340))
screengrabPic.save("tolls_" + filename + ".png")
On pyautogui.readthedocs it explains this syntax, yet it wasn't specific that the requirement was to run locate center once first, then again for locationX and locationY.
How can I invert (rotate 180 degrees) a text object so that the text is kerned appropriately?
My example uses Python and the svgwrite package, but my question seems about any SVG.
Suppose I use the following code:
dwg = svgwrite.Drawing()
dwg.add(dwg.text(fullName, (int(width/2.),gnameHeight),
font_size=gnameFontSize, text_anchor="middle"))
The above code generates text looking like this:
dwg.text() objects accept a rotate parameter that is applied to all characters in a text string, so I've used the following code to reverse the string first:
pcRotate = [180]
ngap = 1
revFullName = fullName
rcl = []
for c in revFullName:
rcl.append(c)
for i in range(ngap):
rcl.append(' ')
rcl.reverse()
revFullName = ''.join(rcl)
dwg.add(dwg.text(revFullName, (int(width/2.),pcnameHeight),
font_size=gnameFontSize, text_anchor="middle", rotate=pcRotate))
But, this produces the very ugly version below:
and this is using an artificial space gap between characters to make it slightly less unreadable.
What's the best way to tap into whatever kerning is being used by standard text in this inverted situation?
The rotate attribute of a <text> element is intended for situations where you want to rotate individual characters. If you want to rotate the whole text object then you should be using a transform instead.
http://pythonhosted.org/svgwrite/classes/mixins.html#transform-mixin
I'm posting this as a self-answer, only to make formatting more clear. Two useful hints from #paul-lebeau happily acknowledged.
While the svgwrite package seems solid, its documentation is a bit thin. The two things I wish it had said:
The rotate attribute of a <text> element is intended for situations where you want to rotate individual characters. If you want to rotate the whole text object, then you should be using a transform mixin instead.
If you need to center the transformed text with respect to some center (other that the default current user coordinate system), add two additional parameters xctr,yctr. This differs from the doc which calls for a single center argument that is a (2-tuple).
The correct code is:
pcRotate = 'rotate(180,%s,%s)' % (int(width/2.),pcnameHeight)
textGroup = svgwrite.container.Group(transform=pcRotate)
textGroup.add(dwg.text(fullName, (int(width/2.),pcnameHeight),
font_size=gnameFontSize, text_anchor="middle"))
dwg.add(textGroup)
I am trying to make an algorithm that's able to solve a big tileset in the tiling problem. Right now it's able to find the correct Tiles to place based on their width and height, but there are some problems with making it properly recursive.
As you can see the idea is that after each tile that's placed the field will be separated in a Field Right and a Field Below. The algorithm will first try to fill the Field Right and as soon as that's done it has to start trying to fill Field Below.
The problem I have is that once Field Right is solved it has to be "send back" in a way (I think using recursion, though this is quite complex) to get it to go back a Tile and go to the Field Below that belongs to that Tile. I put the idea in some pseudocode to make it a bit easier to follow.
As you can see when FieldRightWidth is solved and the FieldBelowHeight is also solved I want to make it return to the previous tile to check if FieldBelow is solved. I think that's where I need to put some code to make this work, but after hours of Googling I still have no clue.
Pseudocode:
def Methods:
create global tileset
create local tileset (without duplicates)
If globaltiles is empty:
solved
end
else:
if fieldRightWidth == solved:
if fieldBelowHeight == solved:
return True???
#FIELD BELOW
else:
Search for Tile
Place Tile
Return Methods
#FIELD RIGHT
else:
Search for Tile
Place Tile
Return Methods
And a picture of what I want the algorithm to do:
And all of the code:
http://pastebin.com/8t4PeiZP
http://www.filedropper.com/tilingnew
I'm still a newbie in coding, so any advice or help is very appreciated!
alright, let's think the area you want to calculate are either square or rectangular,(not rotated), it start from minimum [x,y] and end maximum [x,y] right, like so:
SMaxX = 5
SMinX = 0
SMaxY = 5
SMinY = 0
or if you are familiar with 2D vector you can optimize it like so:
S = [5,5]
you might know about 2D vector, just in case i explain what is vector in 2D cartesian coordinate:
S = [5,5] means, if S start from [0,0], it will end at [5,5], (simpler right?)
so boxes also will be like so:
#space each box taking
box1 = [3,3]
box2 = [2,2]
box3 = [1,1]
and since there is priority for each box, let's say:
#priority of each box
box1 = 6
box2 = 4
box3 = 2
we can merge both space and priority into dictionary like so:
#Items
dic = {'box1':{'space':[3,3] , 'priority ':6},
'box2':{'space':[2,2] , 'priority ':4},
'box3':{'space':[1,1] , 'priority ':2}}
having priority and spaces of each boxes, looks like Knapsack problem algorithm.
if you are familiar about Knapsack problem algorithm, in a table we are trying to find the highest priority that fill the space perfectly, or in other word best possible way of fitting boxes. check this link1 and link2.
however Knapsack problem algorithm's chart is 1D solution, which if you do it, you will get 10, so Box1 and Box2. but since it's 2D and you have different height and width, so the standard 1D formula wont work, maybe you need to look into it see if you can come up with 2D formula or ask around see if someone done that before.
other than Knapsack problem algorithm you can try Flood fill algorithm which is a bit slower if you have huge area, but it work just like how Tetris game is.
you need to set standard size like 1x1, and then define the whole area with 1x1 data, and store it in a variable and set each True (Boolean), then with higher priority of boxes fill the area and set those 1x1 date to False, then really easy you can check if how many of the them are True and what area are they taking.
anyway, i'm trying to figure out the same thing in irregular shape, so that was all i found out, hope that help you.
(check this link as well, i got some useful answers.)
Edit: okay, if you use Tetris idea with defining the area and Knapsack problem algorithm in one axis and then base on standard Tetris area, use Knapsack problem algorithm again in other axis should work perfectly.
I'm using the python API for a "scatterplot" in blender.
The data is a dictionary which maps names to lists of 3D points, so there are named clouds of points.
I need to look at each cloud individually and hide the others, this is my setup:
for each name in the dict, I create an empty object
for each 3D point belonging to this name, I create a small cube, position it and reparent it to the empty object.
Now I can hide the parent objects in the 3D view.
The program works fine, but there is one strange problem: The names are important, I need to be able to find them in the sceneview. But blender changes the names. A name like "TopDown" becomes "TopDown.001". This happens despite the fact that there are no other objects with this name.
Here is my code:
for plotname, positions in points.items():
bpy.ops.object.add(type='EMPTY')
bpy.context.active_object.name = plotname
bpy.context.active_object.location=(0,0,0)
print(plotname) #<---------------here the name is still correct
for position in positions:
me = bpy.data.meshes.new(plotname + 'Mesh')
ob = bpy.data.objects.new(plotname+"Mesh", me)
ob.location = (position[0], position[1], position[2])
ob.show_name = True
bpy.context.scene.objects.link(ob)
me.from_pydata(verts_loc, [], faces)
me.update(calc_edges=True)
ob.parent=bpy.context.active_object
The actual program is a little longer, verts_loc and faces have been set up before this snippet. They represent a cube.
How can I ensure that plotname stays plotname and doesn't become plotname.001 ?
UPDATE
Clarification: It doesn't matter that points within the plot are renamed. Something like "plotnameMesh.001" and "plotnameMesh.002" is no problem. But the parent objects are renamed to.
In fact the sole purpose of appending "Mesh" to the object names is to keep the toplevel plotname unique.
The for position in positions: implies you are creating multiple objects at different locations for each plotname. One will keep the plotname while the others will get numeric extensions.
for position in positions:
me = bpy.data.meshes.new(plotname + 'Mesh')
ob = bpy.data.objects.new(plotname+"Mesh", me)
Is each position unique or are you adding multiple objects at each position?
You will also want to ensure you delete the previous creations before re-running your script.
When you have many objects with similar names you can use Select->Select Pattern to select them. In python you can do that with
[setattr(obj, 'select', True) for obj in bpy.data.objects if obj.name.startswith(plotname)]