2
$\begingroup$

I want to create a simple 3d structure using the coordinates of a GIS polygon(latitutes and longitudes of vertices).

For example a coordinates of a polygon would be like this:-

{"type":"Polygon","coordinates":[[[-121.332737,38.722023],[-121.332895,38.722023],[-121.332895,38.721977],[-121.332946,38.721977],[-121.332946,38.721881],[-121.332737,38.721881],[-121.332737,38.722023]]]}

Polygon footprint

I want to create a simple structure with blender API using this footprint as a base.

$\endgroup$
1
$\begingroup$

This script will generate a mesh object from the coordinates provided in this specific structure.

enter image description here

It will also add edges (assumes the vertices are in order), and one ngon face from all verts.

Note that this mesh is huge and to see it with the default view settings, you need to either be in orthographic mode or set you view clipping to a much higher value.

import bpy, json, bmesh

data_string = '{"type":"Polygon","coordinates":[[[-121.332737,38.722023],[-121.332895,38.722023],[-121.332895,38.721977],[-121.332946,38.721977],[-121.332946,38.721881],[-121.332737,38.721881],[-121.332737,38.722023]]]}'

dataDict = json.loads( data_string )

coordinates = dataDict['coordinates'][0]

bm = bmesh.new()

# Generate vertices
for co in coordinates:
    # Add new vertex at the provided coordiante with z=0
    bm.verts.new( co + [0] )

# Generate edges
bm.verts.ensure_lookup_table()
for i in range(len( bm.verts )):
    if i == 0:
        bm.edges.new([ bm.verts[i], bm.verts[-1] ])
    else:
        bm.edges.new([ bm.verts[i], bm.verts[i-1] ])

# Generate one ngon face
bm.faces.new(bm.verts)

# Generate a mesh and transfer data from bmesh object
m = bpy.data.meshes.new('GIS')
bm.to_mesh(m)

# Create a new mesh object and link to scene
o = bpy.data.objects.new('GIS', m)

bpy.context.scene.objects.link(o)
$\endgroup$
  • $\begingroup$ Hey, thanks for the answer. But after running the script the mesh is not appearing. Can't even see in orthographic view. Am I missing something? $\endgroup$ – Apoorv Agarwal Aug 28 '18 at 13:39
  • $\begingroup$ After you go to orhtographic view, press Home on your keyboard to see everything, and all will be revealed (dramatic tone not intended lol) $\endgroup$ – TLousky Aug 28 '18 at 13:43
  • $\begingroup$ I feel stupid now, but I'm still not seeing it. Zoomed out as much as I could. It's running without any errors. But I just can't see anything. Tried exporting .dae and .obj files too. But even they appear to be empty. I'm on mac by the way (irrelevant, but still maybe helpful). $\endgroup$ – Apoorv Agarwal Aug 28 '18 at 14:05
  • $\begingroup$ Did you select the object? you can do it from the outliner if you can't see it at all $\endgroup$ – TLousky Aug 28 '18 at 14:41
  • 2
    $\begingroup$ Recommend subtracting first coordinate from all vert coordinates, which will put one coord of area of interest at global origin. Secondly remember that lat, long coordinates are spherical (the earth is an ellipsoid) and some georef / datum should be used when converting, as method above is basically a simple equirectangular projection, which will be way off as latitudes increase. Lastly is there a need to create edges? $\endgroup$ – batFINGER Aug 28 '18 at 16:07
2
$\begingroup$

With help of @TLousky's answer and @batFINGER's comment, finally this worked for me.

import bpy, json, bmesh
from math import *
from mathutils import Vector


data_string = '{"type":"Polygon","coordinates":[[[-121.332737,38.722023],[-121.332895,38.722023],[-121.332895,38.721977],[-121.332946,38.721977],[-121.332946,38.721881],[-121.332737,38.721881],[-121.332737,38.722023]]]}'

dataDict = json.loads( data_string )



coordinates = dataDict['coordinates'][0]

x_factor = coordinates[0][0]
y_factor = coordinates[0][1]


verts = tuple([((x[0] - x_factor)*10000, (x[1] - y_factor)*10000) for x in coordinates])

bm = bmesh.new()



bm = bmesh.new()
for v in verts:
    bm.verts.new((v[0], v[1], 0))




# Generate one ngon face
bottom = bm.faces.new(bm.verts)

top = bmesh.ops.extrude_face_region(bm, geom=[bottom])


bmesh.ops.translate(bm, vec=Vector((0,0,1)), verts=[v for v in top["geom"] if isinstance(v,bmesh.types.BMVert)])

bm.normal_update()

# Generate a mesh and transfer data from bmesh object
m = bpy.data.meshes.new('GIS')


bm.to_mesh(m)



# Create a new mesh object and link to scene
o = bpy.data.objects.new('GIS', m)

bpy.context.scene.objects.link(o)
$\endgroup$
  • $\begingroup$ Good one. Generally GIS data will give us coordinates that walk around a face, in which case bm.faces.new(...) works. Incase they are messed up could use contextual_create eg ret = bmesh.ops.contextual_create(bm, geom=bm.verts) new face is ret['faces'] ... bmesh.ops.solidify(...) is another way to add thickness. $\endgroup$ – batFINGER Aug 29 '18 at 15:52

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.