-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathjunction_four_way.py
152 lines (134 loc) · 5.95 KB
/
junction_four_way.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTIBILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import bpy
from mathutils import Vector, Matrix
from math import pi
import os
import sys
import imp
dir = os.path.dirname(bpy.data.filepath)
if not dir in sys.path:
sys.path.append(dir)
# Below this, import all the other python scripts in this project.
# Reload if the module python script has changed.
import helper
imp.reload(helper)
class DSC_OT_junction_four_way(bpy.types.Operator):
bl_idname = 'pr.junction_four_way'
bl_label = '4-way junction'
bl_description = 'Create a junction'
bl_options = {'REGISTER', 'UNDO'}
object_type = 'junction_4way'
snap_filter = 'OpenDRIVE'
def create_3d_object(self, context):
'''
Create a junction object
'''
valid, mesh, matrix_world, materials = self.update_params_get_mesh(context, wireframe=False)
if not valid:
return None
else:
id_obj = helper.get_new_id_opendrive(context)
mesh.name = self.object_type + '_' + str(id_obj)
obj = bpy.data.objects.new(mesh.name, mesh)
obj.matrix_world = matrix_world
helper.link_object_opendrive(context, obj)
helper.assign_road_materials(obj)
helper.select_activate_object(context, obj)
# Metadata
obj['dsc_category'] = 'OpenDRIVE'
obj['dsc_type'] = 'junction'
# Remember connecting points for snapping
obj['cp_left'] = obj.matrix_world @ obj.data.vertices[1].co
obj['cp_down'] = obj.matrix_world @ obj.data.vertices[3].co
obj['cp_right'] = obj.matrix_world @ obj.data.vertices[5].co
obj['cp_up'] = obj.matrix_world @ obj.data.vertices[7].co
# Set OpenDRIVE custom properties
obj['id_xodr'] = id_obj
obj['junction_type'] = 'default'
obj['planView_geometry_x'] = self.params['point_start'].x
obj['planView_geometry_y'] = self.params['point_start'].y
obj['hdg_left'] = self.params['hdg_left']
obj['hdg_down'] = self.params['hdg_down']
obj['hdg_right'] = self.params['hdg_right']
obj['hdg_up'] = self.params['hdg_up']
obj['elevation_level'] = self.params['point_start'].z
obj['incoming_roads'] = {}
return obj
def update_params_get_mesh(self, context, wireframe):
'''
Calculate and return the vertices, edges and faces to create a road
mesh and road parameters.
'''
if self.params_input['connected_start']:
# Constrain point end
point_end = helper.project_point_vector(self.params_input['point_start'],
self.params_input['heading_start'], self.params_input['point_end'])
else:
point_end = self.params_input['point_end']
if self.params_input['point_start'] == point_end:
if not wireframe:
self.report({'WARNING'}, 'Start and end point can not be the same!')
valid = False
return valid, None, None, None
# Parameters
vector_start_end = point_end - self.params_input['point_start']
vector_1_0 = Vector((1.0, 0.0))
heading = vector_start_end.to_2d().angle_signed(vector_1_0)
vector_hdg_left = Vector((-1.0, 0.0))
vector_hdg_down = Vector((0.0, -1.0))
vector_hdg_right = Vector((1.0, 0.0))
vector_hdg_up = Vector((0.0, 1.0))
vector_hdg_left.rotate(Matrix.Rotation(heading, 2))
vector_hdg_down.rotate(Matrix.Rotation(heading, 2))
vector_hdg_right.rotate(Matrix.Rotation(heading, 2))
vector_hdg_up.rotate(Matrix.Rotation(heading, 2))
hdg_left = vector_hdg_left.angle_signed(vector_1_0)
hdg_down = vector_hdg_down.angle_signed(vector_1_0)
hdg_right = vector_hdg_right.angle_signed(vector_1_0)
hdg_up = vector_hdg_up.angle_signed(vector_1_0)
self.params = {'point_start': self.params_input['point_start'],
'hdg_left': hdg_left,
'hdg_down': hdg_down,
'hdg_right': hdg_right,
'hdg_up': hdg_up,
}
# Mesh
vertices = [(-4.00, 4.00, 0.0),
(-4.00, 0.0, 0.0),
(-4.00, -4.00, 0.0),
(0.0, -4.00, 0.0),
(4.00, -4.00, 0.0),
(4.00, 0.0, 0.0),
(4.00, 4.00, 0.0),
(0.0, 4.00, 0.0),
]
edges = [[0, 1],[1, 2],[2, 3],[3, 4],[4, 5],[5, 6],[6, 7],[7, 0]]
if wireframe:
faces = []
else:
# Make sure we define faces counterclockwise for correct normals
faces = [[0, 1, 2, 3, 4, 5, 6, 7]]
# Shift origin to connecting point
if self.params_input['connected_start']:
vertices[:] = [(v[0] + 4.00, v[1], v[2]) for v in vertices]
mat_translation = Matrix.Translation(self.params_input['point_start'])
mat_rotation = Matrix.Rotation(heading, 4, 'Z')
matrix_world = mat_translation @ mat_rotation
# Create blender mesh
mesh = bpy.data.meshes.new('temp')
mesh.from_pydata(vertices, edges, faces)
valid = True
# TODO implement material dictionary for the faces
materials = {}
return valid, mesh, matrix_world, materials