Skip to content

Instantly share code, notes, and snippets.

@batFINGER
Created March 21, 2018 13:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save batFINGER/4c267146a5b7996e46e47985d77b546d to your computer and use it in GitHub Desktop.
Save batFINGER/4c267146a5b7996e46e47985d77b546d to your computer and use it in GitHub Desktop.
OSM bits and pieces.
import bpy
from bpy import context
from mathutils import Vector
import bmesh
up = Vector((0, 0, 1)) # z axis
north = Vector((0, 1, 0)) # y axis
def stroke(bm, v, n, w):
v1 = bm.verts.new(v + w / 2 * n)
v2 = bm.verts.new(v - w / 2 * n)
return bm.edges.new([v1, v2])
class RoadVert:
@property
def segments(self):
return [self.edges[e] for e in self.vert.link_edges]
@property
def build(self):
l = len(self.vert.link_edges)
if l == 1:
return self.build_terminus
elif l == 2:
return self.build_corner
return self.build_intersection
def build_intersection(self, bm, road_width):
verts = []
for s in self.segments:
dx = road_width * s.dir(self.vert)
e = stroke(bm, self.vert.co + dx, s.normal, road_width)
s.edges.append(e)
verts.extend(e.verts[:])
e.verts[0].select = True
#sort
bm.faces.new(sorted(verts,
key=lambda v: north.xy.angle_signed(self.vert.co.xy - v.co.xy),
reverse=True))
def build_corner(self, bm, road_width):
n = sum((s.normal for s in self.segments), Vector())
s1, s2 = self.segments
dot = s1.normal.dot(s2.normal) + 1
e = stroke(bm, self.vert.co, n, road_width / dot)
[s.edges.append(e) for s in self.segments]
def build_terminus(self, bm, road_width):
s = self.segments[0]
e = stroke(bm, self.vert.co, s.normal, road_width)
s.edges.append(e)
def __init__(self, vert, edges):
self.edges = edges
self.vert = vert
class RoadSegment():
def build(self, bm):
if len(self.edges) == 2:
ret = bmesh.ops.contextual_create(bm, geom=self.edges)
for f in ret['faces']:
f.normal = up
def calc_normal(self):
v1, v2 = self.edge.verts
return up.cross(v2.co - v1.co).normalized()
def dir(self, v):
return (self.edge.other_vert(v).co - v.co).normalized()
def __init__(self, edge):
self.edge = edge
self.normal = self.calc_normal()
self.edges = []
class RoadNetwork:
def build(self, roadwidth=0.1):
bm = bmesh.new()
[v.build(bm, roadwidth)
for v in self.waypoints.values()]
[s.build(bm)
for s in self.segments.values()]
me = bpy.data.meshes.new("RoadNetwork")
for f in bm.faces:
if f.normal.dot(up) < 0.5:
f.normal_flip()
bm.normal_update()
bm.to_mesh(me)
ob = bpy.data.objects.new("RoadNetwork", me)
context.scene.objects.link(ob)
context.scene.objects.active = ob
def __init__(self, context):
obs = [o for o in context.selected_objects if o.type == 'MESH'
and not len(o.data.polygons)]
self.bm = bmesh.new()
for o in obs:
me = o.to_mesh(context.scene, True, 'RENDER')
for v in me.vertices:
v.co = o.matrix_world * v.co
self.bm.from_mesh(me)
bmesh.ops.remove_doubles(self.bm, verts=self.bm.verts, dist=0.001)
self.segments = {e : RoadSegment(e) for e in self.bm.edges}
self.waypoints = {v : RoadVert(v, self.segments)
for v in self.bm.verts if len(v.link_edges)}
if __name__ == "__main__":
roads = RoadNetwork(context)
roads.build(3)
@batFINGER
Copy link
Author

Creating Stroked Roads from OSM import.

Handling of single edge roads imported from OSM to stroked roads of a given width. To use select roads in object mode and run script. Have to manually edit the stroke width, eg for width 4, roads.build(4).

@Mi-Pe
Copy link

Mi-Pe commented Dec 9, 2020

Hello!
I tried the shorter version of your script that you posted there:
https://blender.stackexchange.com/questions/103093/2d-solidify-is-it-possible
and it worked with my mesh. However, this version of the script here fails. Do you know why? Did I make the mesh wrong?
Please see the file:
https://drive.google.com/file/d/1SodVt6jTtOJrQH5Vv8m4WouJsWjdSjPq/view?usp=sharing
or here (only available for a week):
https://we.tl/t-m5IV4GgMFw

@Mi-Pe
Copy link

Mi-Pe commented Dec 13, 2020

Ok, it wasn't working because I used Blender 2.9. In Blender 2.79 it's fine.
Dude, this should be a top-rated addon for modelling roads! It is a game-changer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment