5
$\begingroup$

I have csv catalogue(s) of earthquakes occurring in time and xyz space that can be individually represented as cubes or spheres of differing sizes depending on the earthquake magnitude. I have little experience on Blender/Python and am wondering whether I can learn enough of these subjects in a few days to create a nice 3D visualization of my various date,x,y,z,m, and maybe some other attributes. The appearance of the earthquakes might be additionally accompanied by some sound. No physics required. The earthquakes are in local areas so no spherical surfaces required. I have been attempting to do these displays using two different programs as shown following, but Blender would be vastly better. I am stalled here: existing script I have been able to find for csv import appears to be limited to 3 variablesenter image description here

$\endgroup$
  • 2
    $\begingroup$ I needed something similar and had a bunch of historic quakes and locations in a CSV file. With lots of help I ended up with a script that placed the locations on a sphere to place animation and text. Here it is blender.stackexchange.com/questions/36837/… $\endgroup$ – 3pointedit Feb 28 '18 at 6:02
  • 2
    $\begingroup$ And here is the result - youtube.com/watch?v=19otdCjlIg4 I must say that it wasn't as automated as I would like but I had no time for that. It is a more advanced problem. Consider what the output is as well. Are you rendering to a movie file or should it play in a webpage or game engine? This will indicate how to place audio. If its a movie then you simply add the sound in Blender's Video Editor, after rendering the animation. $\endgroup$ – 3pointedit Feb 28 '18 at 6:04
  • 6
    $\begingroup$ Possible duplicate of Import coordinates from CSV and create sphere at each position as well as here $\endgroup$ – batFINGER Mar 5 '18 at 14:13
  • $\begingroup$ Is the data (x,y,z) or (lat,long,depth)? $\endgroup$ – Scott Milner Mar 5 '18 at 16:56
3
$\begingroup$

The good thing about comma separated values files is that they are pretty easy to read if they don't contain errors. The amount of Python you need to learn isn't too much.

I made this example file and saved it next to my blendfile:

number,long,lat,mag
1,37.9230,18.1445,3.5
2,47.1948,23.1326,0.1
3,40.9674,16.6782,1.5
4,45.1434,23.3850,4.2
5,39.4629,21.7380,1.4
6,34.7125,16.9653,5.3
7,34.3573,17.9092,3.3
8,40.9570,24.7064,4.4
9,34.9255,17.1371,3.4
10,45.9753,20.9662,0.7
11,31.0126,20.1624,3.4
12,47.6929,20.7224,5.6

My script is not elegant at all. I focused on it being readable. It can be done much shorter and prettier but not everybody is an experienced coder.

The script imports the csv file, separates it into lines and puts the values into a list.

From there it's not hard to let Blender generate circles or spheres with the right diameter and the right location.

Under Linux it's better to start Blender from a terminal. Otherwise you won't see what the script is printing. Under Windows, the System console can be toggled in the Window menu at the top.

import bpy

blendPath = bpy.path.abspath("//") # path to the blendfile because my .csv is in the same directory
fileName = "example.csv" # name of the csv

txt = open(blendPath + fileName, "r") # open the file to read
quakeTxt = txt.read() # read the entire file into a string
txt.close() # close the file
print(quakeTxt)

quakeLines = quakeTxt.split("\n") # split into a list divided by linebreaks
print(quakeLines)
quakeData = [] # this will hold the actual data

flag = 1 # that flag helps omit the first line
for a in quakeLines:
    if flag: # if it's the first time
        flag = 0 
        continue # continue with the next iteration of the loop
    if len(a) > 0: # ignore empty lines
        # this is a good place to turn the strings into numbers
        quakeData.append(a.split(",")) # append the data as a list

for a in quakeData: # go through the data
    number = a[0]
    locX   = a[1]
    locY   = a[2]
    mag    = a[3]
    print("Nr " + number + ": Location: " + locX + " " + locY + " Magnitude: " + mag)
    # the print statement only works because all the numbers are still strings. That has to change if you want to use them for blender objects
$\endgroup$
  • 1
    $\begingroup$ Thanks for all the commenting, the non-coders salute you ;-) $\endgroup$ – 3pointedit Mar 5 '18 at 7:32
  • 1
    $\begingroup$ For test prints consider using print("Nr ", number, ": Location: ", loxX) Doesn't matter what type the vars are, and avoids unnecessary string concatenation. $\endgroup$ – batFINGER Mar 5 '18 at 11:01
1
$\begingroup$

This can be done with Animation Nodes. Download and install the linked add-on. The first thing we need to do is to parse our data. In the Node Editor, create a new Animation Nodes NodeTree:

new NodeTree button

Add a Text Block Reader node (nodes can be added with Shift + A or you can search by name with Ctrl + A). Press the "+" button, then the magnifying glass button and click to create a new Text Editor window.

adding text block

Now, paste your .csv file into the Text Editor. Here is mine:

36.0071678,-120.5664978,3.37,1.25
39.361,-120.0015,0.2,1.2
61.0127,-152.3792,109.2,1.9
34.2196667,-117.5191667,4.28,2.01
19.1678333,-155.692337,4.33,1.84
52.5276,160.5151,37.6,5.2
33.5093333,-116.7995,3.67,0.6
63.7417,-149.4625,117.7,1.4
39.3438,-120.0228,5.4,1.2
33.497,-116.7903333,6.16,1.09
33.4935,-116.7871667,6.63,0.39
33.3825,-116.8723333,5.13,1
37.6496658,-118.9426651,5.26,0.74
33.765,-116.9028333,11,0.95
60.9685,-150.2176,25.3,1

The data is ordered x,y,z,mag. Add a Split Text node, and set it to "Lines." Now we have a list of strings, each containing the data for one earthquake.

split text node

Next, we need to extract a location vector and a magnitude from these text lists. We'll use Expression nodes for this. Add an Expression node and create a new input from the Text List output of the Split Text node. Use the gear icon to set the output type to Vector List. Paste the following code into the text box:

[[float(p) for p in e.split(",")[:3]] for e in t]

Duplicate the Expression node, change the output type to Float List and paste this code:

[float(e.split(",")[3]) for e in t]

Current NodeTree:

enter image description here

Next, add a Combine Vector node and a Compose Matrix node:

new nodes

Last, add an Object Instancer node. Select the mesh that you want to represent the earthquakes (I'm using an Icosphere). Set the number of Instances to the number of earthquakes in your data. Add an Object Matrix Output node, and use it to position the Icospheres:

new nodes

Result:

final result


(requires Animation Nodes)

$\endgroup$

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.