1
$\begingroup$

I'm trying to import a list from a csv to create a series of circles.

I've created a few scripts that move and rotate objects with help of csv data, I used that csv routine as a template.

This time I wanted to create the object and thought I understood - for i, row in enumerate( rdr ): - however, if you look at this snippet code, you might think I missed the boat completely.

My biggest problem at this moment is that I do not understand how I can get the csv values parsed correctly with add_circle().

Then I have a second issue regarding the fact that it only creates the first circle from the csv and I really thought that this would work.

Can somebody explain what I'm missing to make it work? Or does anybody know a comprehensive paper so I can figure out why this is not working as I expected.

with open( fp ) as csvfile:

# make series of circles
rdr = csv.reader( csvfile )
for i, row in enumerate( rdr ):
    if i == 0: continue # Skip column titles
    FRAME, PARTS, XW = row[0:3]
    part_number = float(PARTS)
    add_circle(FRAME, part_number, float(XW))

CSV snippet:

FRAME, PARTS, XW
1001,8,0
1002,15,1.1
1003B,32,2
etc.

In case the full script is more helpful:

# -*- coding: utf-8 -*-
"""
Name: 'Add cirkel'
Blender: 2.80
Group: 'Add'
Tooltip: 'Creates a shape object'
"""

import bpy, csv
import bpy.types
import time
from mathutils import *
import math

fp = "C:/Users/Maarten/Documents/blender/csv/generate-object.csv"


def object_from_data(data, name, scene, select=True):
    """ Create a mesh object and link it to a scene """
    mesh = bpy.data.meshes.new(name)
    mesh.from_pydata(data['verts'], data['edges'], data['faces'])

    obj = bpy.data.objects.new(name, mesh)
    scene.collection.objects.link(obj)
    bpy.context.view_layer.objects.active = obj
    obj.select = True
    mesh.validate(verbose=True) 
    return obj

def vertex_circle(segments, z):
    """ Return a ring of vertices """
    verts = []
    verts.append(( 0, 0, z))
    for j in range(segments):
        angle = (math.pi*2) * j / segments
        verts.append((math.cos(angle), math.sin(angle), z))
    return verts

def add_circle(name, segments, z):
    """ Make a circle """

    data = {
    'verts': vertex_circle(segments, z),
    'edges': [],
    'faces': [],
    }
    data['faces'] = [(j, j+1, 0) for j in range(segments)]
    data['faces'].append((segments, 1, 0))

    scene = bpy.context.scene
    return object_from_data(data, name, scene)

with open( fp ) as csvfile:
    """ make series of circles """
    rdr = csv.reader( csvfile )
    for i, row in enumerate( rdr ):
        if i == 0: continue # Skip column titles
        FRAME, PARTS, XW = row[0:3]
        add_circle(FRAME, 8, 0)

#        FRAME, PARTS, XW, YW, Z, EXP1, EXP2, WALL = row[0:8]
#        parts_number = float(PARTS)
#        add_circle(FRAME, 8, 0, 2, 0, 1, 2)
#        add_circle(FRAME, parts_number, 0, 2, 0, 1, 2)
#        if WALL == 1: add_circle2() else: add_circle()



FRAME,PARTS,XW,YW,Z,EXP1,EXP2,WALL
1001,8,0,2,0,1,2,0
1002,15,1,2,1,1,2,1
1003,32,2,3,2,1,2,1
1004,64,3,4,3,1,2,1
1005,128,4,5,4,1,2,0

The first is the script, the second the csv (please remove .txt extension before use) In add_circle() I placed values PARTS=8 and XW=0. so the script creates one circle with only the name 1001 from CSV.

$\endgroup$
5
  • $\begingroup$ I think it would help for others to be able to replicate what you're trying to do if you included a sample CSV file. At the moment it's unclear of the format of the CSV without picking through your code, which could be a barrier to someone providing help. $\endgroup$ Jul 17 '20 at 7:09
  • $\begingroup$ thank you Rich, i'll do my best. there is a sample csv for download, however due to restrictions when sharing I gave it a .txt extension. and i included a small piece of the CSV here above, $\endgroup$
    – user74341
    Jul 17 '20 at 7:20
  • $\begingroup$ Please can you elaborate on the CSV contents a bit more? I think I have this working but aren't sure of what your final goal is... the columns are labelled FRAME, PARTS, XW, YW, Z, EXP1, EXP2, WALL. From what I gather, FRAME is actually NAME, Z is the Z coordinate. Are XW and YW the expected widths in X and Y directions?. What are EXP1, EXP2, WALL? $\endgroup$ Jul 17 '20 at 8:37
  • $\begingroup$ Yes, for this example I made XW the Z parameter in the script, so i did not have to clutter the question with more values. This way the script is more straightforward to understand I thought. FRAME=name, PARTS=segments (triangles) and XW=z (at this moment) but it will be expanded with XW and YW for the expected width of the circle/oval, the other values will also be used in the calculations when i have got this working. $\endgroup$
    – user74341
    Jul 17 '20 at 9:08
  • $\begingroup$ although most people can't tell in the end result: data['faces'] = [(j, j+1, 0) for j in range(segments)] should be replaced by data['faces'] = [(j+1, j+2, 0) for j in range(segments-1)] for proper distribution of faces...my bad. $\endgroup$
    – user74341
    Jul 17 '20 at 18:08
2
$\begingroup$

There were a couple of issues with the code.

  1. The 'obj.select = True' line was referencing an invalid property of 'obj'. I've simply disabled that line.
  2. I've put back in the commented out code in the last function to use the values extracted from the CSV. Note that the CSV data is returned as strings so each value needs 'casting' into the expected type - ie, to cast PARTS into an integer you can use `int(PARTS)'.

Here's my amended code - additionally implementing XW and YW for the width and depth of each circle (I changed the other functions to pass them through and use them in the calculation of the vertex position :

# -*- coding: utf-8 -*-
"""
Name: 'Add cirkel'
Blender: 2.80
Group: 'Add'
Tooltip: 'Creates a shape object'
"""

import bpy, csv
import bpy.types
import time
from mathutils import *
import math

fp = "C:/Users/rich/Desktop/generate-object.csv"


def object_from_data(data, name, scene, select=True):
    """ Create a mesh object and link it to a scene """
    mesh = bpy.data.meshes.new(name)
    mesh.from_pydata(data['verts'], data['edges'], data['faces'])

    obj = bpy.data.objects.new(name, mesh)
    scene.collection.objects.link(obj)
    bpy.context.view_layer.objects.active = obj
    #obj.select = True
    mesh.validate(verbose=True) 
    return obj

def vertex_circle(segments, xw, yw, z):
    """ Return a ring of vertices """
    verts = []
    verts.append(( 0, 0, z))
    for j in range(segments):
        angle = (math.pi*2) * j / segments
        verts.append((math.cos(angle)*xw, math.sin(angle)*yw, z))
    return verts

def add_circle(name, segments, xw, yw, z):
    """ Make a circle """

    data = {
    'verts': vertex_circle(segments, xw, yw, z),
    'edges': [],
    'faces': [],
    }
    data['faces'] = [(j, j+1, 0) for j in range(segments)]
    data['faces'].append((segments, 1, 0))

    scene = bpy.context.scene
    return object_from_data(data, name, scene)

with open( fp ) as csvfile:
    """ make series of circles """
    rdr = csv.reader( csvfile )
    for i, row in enumerate( rdr ):
        if i == 0: continue # Skip column titles
        #FRAME, PARTS, XW = row[0:3]
        #add_circle(FRAME, 8, 0)

        FRAME, PARTS, XW, YW, Z, EXP1, EXP2, WALL = row[0:8]
        parts_number = float(PARTS)
        #add_circle(FRAME, 8, 0, 2, 0, 1, 2)
        #add_circle(FRAME, parts_number, 0, 2, 0, 1, 2)
        #if WALL == 1: add_circle2() else: add_circle()
        add_circle(FRAME, int(PARTS), float(XW), float(YW), float(Z))

Here are the results from your sample CSV file (you need to amend the code to point at the location of the file if different to mine) :

result

$\endgroup$
5
  • 1
    $\begingroup$ thank you Rich, when I see your answer my thought was that I had tried this solution. but I made segments not an integer but a float(), that is why I could not get this working. $\endgroup$
    – user74341
    Jul 17 '20 at 9:48
  • $\begingroup$ obj.select = True has been replaced with obj.select_set(True) in 2.8. If the idea is to feed the context into another operator, often pays to have object of interest both active and selected. $\endgroup$
    – batFINGER
    Jul 17 '20 at 10:41
  • $\begingroup$ Thanks @batFINGER - I'm a bit behind on the API changes. Knew you'd be on the ball :-) $\endgroup$ Jul 17 '20 at 10:58
  • 2
    $\begingroup$ Often wonder if a "catch all" community wiki "Updating Scripts" akin to (or part of) "Resources for Blender" is worth looking into. Most have been covered, but can be hard to find among eg blender.stackexchange.com/questions/147683/… $\endgroup$
    – batFINGER
    Jul 17 '20 at 11:11
  • $\begingroup$ Thanks @batFINGER , that might come in handy. $\endgroup$
    – user74341
    Jul 17 '20 at 11:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.