TransWikia.com

Data Visualization - Iterate through a Collection of objects and set Z scale to a value from a specific csv file column index

Blender Asked by drivethrulake on January 2, 2022

Summary:
Scale height of 77 mesh objects, by a csv file column with 77 float values.
*iterate through csv column drop head and save row value to list.
*iterate through objects in collection and apply Z scale from respective csv column row

Hello,
I’m swirling now and can’t seem to lock in my code.
I am working on a data visualization map project and attempting to scale parts of a map in relation to a column of values in a csv file. I have 77 custom mesh objects in a collection and all of their origins are set to bottom surface center (for the purpose of scaling their height. Respectively, I have a csv file with column values with 77 rows. Each column has different stats, so I can change the index and get a different height map. I successfully can iterate over my csv file and see the correct values in a list.
Now, I’m having trouble iterating through my "77 objects" in my collection and assigning the correct row value to each object. I have looked at ‘[3pointedit][1]’ similar question, but it doesn’t address my specific workflow and I tried the code and I had trouble getting it to apply. I understand I have a counter in the ‘for loop’ I probably don’t need and maybe another variable holder, but I was just experimenting. If anyone has an idea, let me know! thanks!!!!

Here is my current (non-working) code. I don’t mind selecting all my collection objects before I run it, if that helps.

import bpy
import csv
import numpy as np

with open('csv_file') as csv_file:
readout = csv.reader(csv_file)

next(readout, None)


col_values = []
counter = 0

for row in readout:
    current_row_val = float(row[1])
    col_values.append(current_row_val)
    counter = counter + 1
    current_value = row[:]

    sel_objs = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']
    bpy.ops.object.select_all(action='DESELECT')

if sel_objs:
    obj1 = sel_objs.pop()
    obj1.select = True
    bpy.context.scene.objects.active = obj1
    bpy.ops.transform.resize(value=(1.0, 1.0, float(current_value), orient_type='GLOBAL', orient_matrix=((0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0)), orient_matrix_type='GLOBAL', constraint_axis=(False, False, False), mirror=False, use_proportional_edit=False, proportional_edit_falloff='SMOOTH', proportional_size=1.0, use_proportional_connected=False, use_proportional_projected=False, snap=False, snap_target='CLOSEST', snap_point=(0.0, 0.0, 0.0), snap_align=False, snap_normal=(0.0, 0.0, 0.0), gpencil_strokes=False, texture_space=False, remove_on_cancel=False, center_override=(0.0, 0.0, 0.0), release_confirm=False, use_accurate=False)

I updated my code. I get one object changing it’s scale, but not all respectively.

import bpy
import csv
import numpy as np

# **make sure to set csv file path**
with open('..../test_csv.csv') as csv_file:
    readout = csv.reader(csv_file)
    
    next(readout, None)
    

    col_values = []
    counter = 0
    
    for row in readout:
        current_row_val = float(row[1])
        col_values.append(current_row_val)
        counter = counter + 1
        current_value = row[:]
        #print(current_row_val)
        
    for object in bpy.context.selected_objects:
        bpy.context.object.scale[2] = ((col_values[1]) + 1) / 10

v03 Update. This code worked last night, but I may refine it based on user ‘thorst’ comments below.

import bpy
import csv
import numpy as np

# **make sure to set csv file path**
with open('..../test_csv.csv') as csv_file:
    readout = csv.reader(csv_file)
    
    next(readout, None)
    

    col_values = []
    #counter = 0
    
    for row in readout:
        #***************************^CHANGE_CSV_'column'row[]!
        current_row_val = float(row[2])
        col_values.append(current_row_val)
        #counter = counter + 1
        current_value = row[:]
        print(current_row_val)
        
    obj_counter = -1
    for active in bpy.context.selected_objects:
        obj_counter = obj_counter + 1
        bpy.context.view_layer.objects.active = active 
        
        # **Change the multiple divide value below, so the bars look better!
        
        # **FOR DATA BETWEEN 1000-100000 - sample 'Per Capita Income' INDEX 2!!!!!
        bpy.context.object.scale[2] = (col_values[obj_counter] / 7000) * 3

[My github repo for this test file][2]


  [1]: https://blender.stackexchange.com/questions/139160/how-to-use-csv-values-to-drive-object-scale
  [2]: https://github.com/gitgranthub/blender_scale_objects_csv.git

One Answer

In your updated answer, the last loop should be

object_no = 0
for object in bpy.context.selected_objects:
    object.scale[2] = ((col_values[object_no]) + 1) / 10
    object_no += 1

object is your iterator object which is defined via the for-loop

for object in bpy.context.selected_objects:

bpy.context.object is a separate variable in Blender's API and unaffected by the loop. It points to the same object in your scene in each iteration (probably the active one as it looks in a test I did with two cubes, but the API description doesn't clear this up). This is why you see one object changing and all the others stay the same.

Furthermore, you also need to iterate over the scaling-values from your ascii-table, this can be done with a second iterator variable object_no, initialised to the first entry before the loop and then increasing it at the end of each iteration.

Answered by thorst on January 2, 2022

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP