Created
March 21, 2018 13:26
-
-
Save batFINGER/4c267146a5b7996e46e47985d77b546d to your computer and use it in GitHub Desktop.
OSM bits and pieces.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
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
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
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)
.