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$
3
  • $\begingroup$ see: stackoverflow.com/questions/1185408/… (for lat/lon to xyz) $\endgroup$
    – zeffii
    Commented Sep 1, 2015 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
    Commented Sep 1, 2015 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
    Commented Sep 1, 2015 at 11:42

1 Answer 1

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$
4
  • $\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
    Commented Sep 1, 2015 at 6:48
  • $\begingroup$ fixed it - wasn't converting the strings from the CSV to floats $\endgroup$
    – quollism
    Commented Sep 1, 2015 at 7:17
  • $\begingroup$ Getting a sphere from the data, when it should return a partial sphere... $\endgroup$
    – 3pointedit
    Commented Sep 1, 2015 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
    Commented Sep 1, 2015 at 13:07

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .