4
$\begingroup$

I have a table of Earthquake data in CSV, that includes Lat Long coordinates. CSV file download I want to convert them to Blender coordinates (on sphere or flat it doesn't matter as I can fit them to a map later). I hope to place an object at each location that references the magnitude value. Then I will make them appear in order over time, which is the other column of data.

I can import the CSV and convert to text objects for the magnitude with

import bpy # THIS IS A MUST TO IMPORT ALL BLENDER PYTHON MODULE
import csv # IMPORT CSV MODULE

# READ INPUT FILE

file = csv.reader(open('\\Users\mcsweend2c\Desktop\Bearthquakes 6-9.csv', newline=''), delimiter=',')

curRow = [] #empty placeholder for current row

for idx, row in enumerate(file):
    if idx<40: # this is hard coded at the moment

        curRow = row

        # display first data index as string
        bpy.ops.object.text_add(location=(0,idx,0), rotation=(0,0,0))
        bpy.ops.object.editmode_toggle()
        bpy.ops.font.delete()
        bpy.ops.font.text_insert(text=curRow[0])
        bpy.ops.object.editmode_toggle()

But I'm not sure how to separate and use the rest?

$\endgroup$
  • $\begingroup$ see: stackoverflow.com/questions/1185408/… (for lat/lon to xyz) $\endgroup$ – zeffii Sep 1 '15 at 5:41
  • $\begingroup$ that csv has mixed date information, .. 10/08/1997 and 1873/12/15, and it goes backwards in time (which makes sense) $\endgroup$ – zeffii Sep 1 '15 at 9:43
  • $\begingroup$ Yes the data was cleaned in excel which doesn't recognize dates before 1900. And yes it goes backward in time. Although I'm happy to reverse that. I wasn't going to set the time accurately anyway, just straight progression. $\endgroup$ – 3pointedit Sep 1 '15 at 11:42
7
$\begingroup$

Here's how you read the CSV, reformat the dates, sort the quakes by date, convert lat/long to x/y/z then output each row as a text object on the outside of a hypothetical sphere (with the object name set to the date of the quake in YYYY-MM-DD format) with the text oriented so that it sits flat on the surface. Fonts and materials and other tweaks to be supplied by you. :)

Based this off https://stackoverflow.com/questions/10473852/convert-latitude-and-longitude-to-point-in-3d-space

# imports to make all the things work
from math import sin, cos, radians, pi, atan, tan
import csv
import bpy

# define some helpful functions for later

# a function to make, scale and rotate text objects into place
def makeathing(coords, scale, lat, long, date):
    rotation = (radians(lat - 270), pi, radians(long - 90))
    bpy.ops.object.text_add(location=(coords), rotation=(rotation))
    ob = bpy.context.object
    # set object properties here
    ob.data.body = "{:.1f}".format(float(scale))
    ob.data.align = 'CENTER'
    ob.rotation_mode = 'YXZ'
    ob.data.size = 0.03
    ob.data.extrude = 0.002
    ob.data.name = date
    ob.name = date

# a function to turn 3D polar coordinates into 3D cartesian coordinates
def latlonger(lat_deg, lon_deg):
    lat = radians(lat_deg)
    lon = radians(lon_deg)
    # see: http://www.mathworks.de/help/toolbox/aeroblks/llatoecefposition.html
    alt = 0.01
    rad = 2                                     # radius of sphere in BUs
    f  = 0.0                                    # flattening
    ls = atan((1 - f)**2 * tan(lat))  # lambda
    x = rad * cos(lat) * cos(lon) + alt * cos(lat) * cos(lon)
    y = rad * cos(lat) * sin(lon) + alt * cos(lat) * sin(lon)
    z = rad * sin(lat) + alt * sin(lat)
    return (x, y, z)

# NB: no code has executed yet, we're just setting up functions we use further down

# read in the CSV file containing quake data
file = csv.reader(open('\\Users\mcsweend2c\Desktop\Bearthquakes 6-9.csv', newline=''), delimiter=',')

# make a blank dict variable to put quake data into
quakes = {}

# iterate through the CSV row by row and pull the data into variables
# then put the variables into a tuple and use a corrected date as the dict key
# see the last line of the for block for data order
# NB: could have used a dict instead of a tuple
# would have meant looking up e.g. quakes[x]['scale'] instead of quakes[x][0]
for idx, (scale, date, lat, lon) in enumerate(file):
    (yd, m, dy) = date.split("/")
    if int(yd) > int(dy):
        year = yd
        day = dy
    else:
        year = dy
        day = yd
    key = "{}-{:02g}-{:02g}".format( year, int(m), int(day) )
    quakes[key] = (scale, lat, lon)

# go through the sorted dates in the quakes dict
# get latitude and longitude and turn into x/y/z coords with latlonger function
# then send x/y/z coordinates to makeathing function to create them in 3D space
for k in sorted(quakes.keys()):
    latitude = float(quakes[k][1])
    longitude = float(quakes[k][2])
    coords = latlonger(latitude, longitude)
    makeathing(coords, quakes[k][0], latitude, longitude, k)

You may need to offset the X of the world map texture to align the letters to their correct positions on the globe, e.g. using this texture map I had to offset X by 0.25.

$\endgroup$
  • $\begingroup$ Hmm getting error, "A float is required". Should I convert the result somehow or is the result string a mismatch of type? $\endgroup$ – 3pointedit Sep 1 '15 at 6:48
  • $\begingroup$ fixed it - wasn't converting the strings from the CSV to floats $\endgroup$ – quollism Sep 1 '15 at 7:17
  • $\begingroup$ Getting a sphere from the data, when it should return a partial sphere... $\endgroup$ – 3pointedit Sep 1 '15 at 9:04
  • $\begingroup$ Yep because sin and cos expect radians not degrees, have fixed that now along with a bunch of other things. :) $\endgroup$ – quollism Sep 1 '15 at 13:07

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.