Place objects randomly within a range in Blender Python - python

I have 10 objects, I would like to place these objects randomly within a range x, y, z (with minimum and maximum). Something like that:
import bpy
import bpy_extras
import random
import math
bpy.data.objects["Sasso_1"].select_set(True)
bpy.ops.rigidbody.objects_add(type='ACTIVE')
bpy.context.object.rigid_body.mass = 0.25
for obj in bpy.data.collections['Sassi'].all_objects:
obj.select_set(True)
bpy.ops.rigidbody.object_settings_copy()
bpy.ops.transform.translate(value=random.uniform(12,27), orient_axis='X')
bpy.ops.transform.translate(value=random.uniform(-15,15), orient_axis='Y')
bpy.ops.transform.translate(value=random.uniform(13,28), orient_axis='Z')
for obj in bpy.data.collections['Sassi'].all_objects:
bpy.ops.transform.rotate(value=random.uniform(0,360), orient_axis='X')
bpy.ops.transform.rotate(value=random.uniform(0,360), orient_axis='Y')
In my script, the objects "sassi" rotate and translate in a random way, but not in a range that I want.
The result is that the objects are unpredictable.
Tnx for the attention. :)

The translate operator does a relative movement:
https://docs.blender.org/api/blender_python_api_2_67_1/bpy.ops.transform.html
In your case you want to set an absolute position. How to do that is explained here:
https://blender.stackexchange.com/a/89581
bpy.data.objects["Cube"].location.x = 3.0
bpy.data.objects["Cube"].location.y = 2.0
bpy.data.objects["Cube"].location.z = 1.0
bpy.context.scene.update()

I resolve the problem with the randomize trasform function.
this is the code for do it:
bpy.ops.object.randomize_transform(random_seed = random.randint(0,100), loc=(6, 6, 6), scale=(1, 1, 1))

Related

Why can't I import my module into my main code?

I wrote some code (named exercise 2) where I define a function (named is_divisible) and it has worked perfectly.
Afterwards to learn how to import functions, I wrote the same code but without the defined function, and created a second module (named is_divisible). But whenever I import this module into the original "exercise 2" I get
No module named 'is_divisible'
I have checked that both python files are in the same folder, the name of the file is correct, and I know the code is well written because it has worked before and it is from a lecturer's of mine. I have also attempted to name the module and the function differently and to instead write:
from divis import is_divisible
but this was also unsuccessful.
Where am I going wrong? I will leave the code below:
import random
import math
import numpy as np
random_list=[]
for i in range (0,5):
r=random.randint(0,10)
random_list.append(r)
print(random_list) #five numbers from 0 to 10 are chosen and appended to a list
new_result=[print('right' for x in random_list if round(np.cosh(x)**2 - np.sinh(x)**2,2) == 1]
#checking the numbers following a maths rule
import is_divisible #trying to import the function is_divisible
divisor=3
idx = is_divisible(random_list, divisor)
for i in idx:
print(f'Value {random_list[i]} (at index {i}) is divisible by {divisor}')
the code for the function is_divisible is:
def is_divisible(x, n):
""" Find the indices of x where the element is exactly divisible by n.
Arguments:
x - list of numbers to test
n - single divisor
Returns a list of the indices of x for which the value of the element is
divisible by n (to a precision of 1e-6 in the case of floats).
Example:
>>> is_divisible([3, 1, 3.1415, 6, 7.5], 3)
[0, 3]
"""
r = []
small = 1e-6
for i, m in enumerate(x):
if m % n < small:
r.append(i)
return r
I know this question has been answered multiple times, but none of the answers seem to work for me or maybe I am not doing it correctly.
Generally, when you type import <Module> the module is the name of the file. So, if you had the function is_divisible inside a Python file named a.py, then to import it you will write from a import is_divisible. If instead, you would like to import the whole file, then you'd write import a.py, then to use the function you would use a.is_divisible(random_list, divisor).
You should also make sure that both files are in the same folder.

Pyautogui use size() to get two integers

so I am trying to create a bot in python, and for that cause I would need the size of the screen as two integers (x coordinate and y coordinate). I use pyautogui for that case, but the function size() only returns a string:
Size(width=2560, height=1440)
How would i go about "extracting" these values into integer variables?
edit: I managed to fix my problem, it's some spagetthi code, but I can clean it up later, just in case someone has the same problem:
import pyautogui
screen_size = str(pyautogui.size())
screen_size_x, screen_size_y = screen_size.split(",")
screen_size_x= screen_size_x.replace("Size(width=","")
screen_size_y = screen_size_y.replace("height=","")
screen_size_y = screen_size_y.replace(")","")
screen_size_y = screen_size_y.replace(" ","")
screen_size_x = int(screen_size_x)
screen_size_y = int(screen_size_y)
print(screen_size_x)
print(screen_size_y)
from inspect import getsource
print(getsource(pyautogui.size))
output:
def size():
"""Returns the width and height of the screen as a two-integer tuple.
Returns:
(width, height) tuple of the screen size, in pixels.
"""
return Size(*platformModule._size())
nicer code:
import pyautogui
x,y = pyautogui.size()
x,y=int(str(x)),int(str(y))
print(x)
print(y)
I've found multiple examples online of using pyautogui.size(). In all those examples, that method returns a two-item tuple containing width and height. So it seems that your code could be as simple as:
screen_size_x, screen_size_y = pyautogui.size()
print(screen_size_x)
print(screen_size_y)
This is shown in the first example in the pyautogui docs: https://github.com/asweigart/pyautogui/blob/master/README.md
If you did need to parse the string you mention, here's a cleaner way to do that:
import re
str = "Size(width=2560, height=1440)"
m = re.search(r"width=(\d+).*height=(\d+)", str)
screen_size_x, screen_size_y = int(m.group(1)), int(m.group(2))
print(screen_size_x)
print(screen_size_y)

Get an object's position in another object's coordinate system

Is there a way in MEL or Python in Maya to get one object's position in the coordinate system of another object? I have a camera in a scene that may be rotated in any direction and am trying to measure the distance in its local Z axis to the vertices of various objects in the scene. This obviously needs to be fast, since it will likely be run thousands of times across the scene.
In Maxscript the command would be something like
" in coordsys $camera "
but I have yet to find something like this in Maya. If there's no direct command to do this, does anyone have a way to calculate it using matrix math?
There is no one liner similar to the MXS idiom -- and no easy way to do it in mel. However in Python you can do this fairly easily.
First you need to get the matrix for the coordinate system you want as an MMatrix, which is part of the OpenMaya api. Then get the position you want to check as an MPoint, which is another api class. Here's the cheap way to get them (there are faster methods but they're much wordier):
from maya.api.OpenMaya import MVector, MMatrix, MPoint
import maya.cmds as cmds
def world_matrix(obj):
"""'
convenience method to get the world matrix of <obj> as a matrix object
"""
return MMatrix( cmds.xform(obj, q=True, matrix=True, ws=True))
def world_pos(obj):
"""'
convenience method to get the world position of <obj> as an MPoint
"""
return MPoint( cmds.xform(obj, q=True, t=True, ws=True))
Once you have the matrix and the point, the relative position is simply point times the inverse of the matrix:
relative_position = world_pos('pSphere1') * world_matrix('pCube1').inverse()
print relative_position
# (0.756766, -0.0498943, 3.38499, 1)
The result will be an MPoint, which has 4 numbers (x, y, z and w); the 4th will always be 1 so you can just ignore it, although the math needs it to account for scales and shears.
Use this MEL script to calculate the distance from camera1 to nurbsSphere1 primitive:
vector $p1 = `getAttr camera1.translate`;
vector $p2 = `getAttr nurbsSphere1.translate`;
vector $result = $p1 - $p2;
print (mag($result))
Printed result must be like this:
# MEL 40.1965
Or use this Python script to calculate the distance from camera1 to nurbsSphere1 primitive:
import maya.cmds as cmds
import math
distance = math.sqrt(pow((float)(cmds.getAttr("nurbsSphere1.tx") - cmds.getAttr("camera1.tx")),2) +
pow((float)(cmds.getAttr("nurbsSphere1.ty") - cmds.getAttr("camera1.ty")),2) +
pow((float)(cmds.getAttr("nurbsSphere1.tz") - cmds.getAttr("camera1.tz")),2) )
print(distance)
Printed result must be like this:
# Python 40.1964998512

How do you make a list of numpy.float64?

I am using python. I made this numpy.float64 and this shows the Chicago Cubs' win times by decades.
yr1874to1880 = np.mean(wonArray[137:143])
yr1881to1890 = np.mean(wonArray[127:136])
yr1891to1900 = np.mean(wonArray[117:126])
yr1901to1910 = np.mean(wonArray[107:116])
yr1911to1920 = np.mean(wonArray[97:106])
yr1921to1930 = np.mean(wonArray[87:96])
yr1931to1940 = np.mean(wonArray[77:86])
yr1941to1950 = np.mean(wonArray[67:76])
yr1951to1960 = np.mean(wonArray[57:66])
yr1961to1970 = np.mean(wonArray[47:56])
yr1971to1980 = np.mean(wonArray[37:46])
yr1981to1990 = np.mean(wonArray[27:36])
yr1991to2000 = np.mean(wonArray[17:26])
yr2001to2010 = np.mean(wonArray[7:16])
yr2011to2016 = np.mean(wonArray[0:6])
I want to put them together but I don't know how to. I tried for the list but it did not work. Does anyone know how to put them together in order to put them in the graph? I want to make a scatter graph with matplotlib. Thank you.
So with what you've shown, each variable you're setting becomes a float value. You can make them into a list by declaring:
list_of_values = [yr1874to1880, yr1881to1890, ...]
Adding all of the declared values to this results in a list of floats. For example, with just the two values above added:
>>>print list_of_values
[139.5, 131.0]
So that should explain how to obtain a list with the data from np.mean(). However, I'm guessing another question being asked is "how do I scatter plot this?" Using what is provided here, we have one axis of data, but to plot we need another (can't have a graph without x and y). Decide what the average wins is going to be compared against, and then that can be iterated over. For example, I'll use a simple integer in "decade" to act as the x axis:
import matplotlib.pyplot as plt
decade = 1
for i in list_of_values:
y = i
x = decade
decade += 1
plt.scatter(x, y)
plt.show()

'module' has no attribute 'translateX' error in Maya

I have just recently started writing Python code to be used in Maya.
My code looks like this:
import maya.cmds as cmds;
import random as rand;
for x in range (0,10):
cmds.polyCube(cmds.translateX == rand(0,100));
x += 1;
Maya then gives the error, 'module' has no attribute 'translateX'
I am not sure what is going on. Thank you!
translateX isn't a command or part of the argument for a polyCube.
What you want is something more like
import maya.cmds as cmds;
import random as rand;
for x in range (10):
# create the cube at origin
cmds.polyCube()
# move it to a random X
cmds.xform( t = (rand.randrange(0,100), 0, 0) )
When you create the polyCube it will be selected, so issuing the xform() immediately afterward will only affect the most recently created cube. You could also use cmds.setAttr(".translateX" = rand(0,100)) but that's less flexible if you also want to set the Y or Z directions

Categories

Resources