diff --git a/addon/export.py b/addon/export.py index 1b3e95d..69b278e 100644 --- a/addon/export.py +++ b/addon/export.py @@ -777,6 +777,11 @@ def create_lanes(self, obj): lane.add_roadmark(road_mark) lanesection.add_right_lane(lane) lanes.add_lanesection(lanesection) + lanes.add_laneoffset(xodr.LaneOffset(0, + obj['lane_offset_coefficients']['a'], + obj['lane_offset_coefficients']['b'] / obj['geometry_total_length'], + obj['lane_offset_coefficients']['c'] / obj['geometry_total_length']**2, + obj['lane_offset_coefficients']['d'] / obj['geometry_total_length']**3)) return lanes diff --git a/addon/geometry.py b/addon/geometry.py index fe363a3..c5e1e13 100644 --- a/addon/geometry.py +++ b/addon/geometry.py @@ -15,6 +15,8 @@ from math import pi, copysign from numpy import linspace +from . import helpers + class DSC_geometry(): def __init__(self): @@ -22,6 +24,7 @@ def __init__(self): self.sections = [] self.section_curves = [] self.total_length = 0 + self.lane_offset_coefficients = {'a': 0, 'b': 0, 'c': 0, 'd': 0} def update_total_length(self): ''' @@ -125,7 +128,7 @@ def remove_last_section(self): self.update_total_length() self.matrix_world = None - def update(self, params_input, geometry_solver): + def update(self, params_input, lane_offset_start, lane_offset_end, geometry_solver): ''' Update parameters of the geometry and local to global tranformation matrix. @@ -135,6 +138,7 @@ def update(self, params_input, geometry_solver): self.update_local_to_global(params_input) self.update_local_and_section_params(params_input) self.update_plan_view(params_input, geometry_solver) + self.update_lane_offset_coefficients(lane_offset_start, lane_offset_end) self.update_elevation(params_input) self.update_total_length() @@ -178,6 +182,14 @@ def update_plan_view(self, params, geometry_solver): ''' raise NotImplementedError() + def update_lane_offset_coefficients(self, lane_offset_start, lane_offset_end): + ''' + Update lane offset coefficients of road geometry. + ''' + c = 3.0 * (lane_offset_end - lane_offset_start) + d = -2.0 * (lane_offset_end - lane_offset_start) + self.lane_offset_coefficients = {'a': lane_offset_start, 'b': 0, 'c': c, 'd': d} + def update_elevation(self, params_input): ''' Update elevation of road geometry based on predecessor, successor, @@ -406,7 +418,7 @@ def get_section_idx_and_s(self, s): break return idx_section, s_section - def get_elevation(self, s): + def calculate_elevation(self, s): ''' Return the elevation level for the given value of s in the geometry section with the given index and its curvature. @@ -440,13 +452,14 @@ def sample_cross_section(self, s, t_vec): reference line. ''' x_s, y_s, hdg, curvature_plan_view = self.sample_plan_view(s) - z, curvature_elevation = self.get_elevation(s) + z, curvature_elevation = self.calculate_elevation(s) curvature_abs = max(abs(curvature_plan_view), abs(curvature_elevation)) vector_hdg_t = Vector((1.0, 0.0)) vector_hdg_t.rotate(Matrix.Rotation(hdg + pi/2, 2)) xyz = [] for t in t_vec: - xy_vec = Vector((x_s, y_s)) + t * vector_hdg_t + lane_offset = helpers.calculate_lane_offset(s, self.lane_offset_coefficients, self.total_length) + xy_vec = Vector((x_s, y_s)) + t * vector_hdg_t + lane_offset * vector_hdg_t xyz += [(xy_vec.x, xy_vec.y, z)] return xyz, hdg, curvature_abs diff --git a/addon/helpers.py b/addon/helpers.py index 8e78274..b3f1958 100644 --- a/addon/helpers.py +++ b/addon/helpers.py @@ -355,6 +355,17 @@ def set_connecting_road_properties(context, joint_side_start, road_contact_point context.scene.dsc_properties.connecting_road_properties.lanes[0].road_mark_type = 'none' context.scene.dsc_properties.connecting_road_properties.lanes[1].road_mark_type = 'none' +def calculate_lane_offset(s, lane_offset_coefficients, total_length): + ''' + Return lane offset in [m] for the given s value based on the + pre-calculated polynomial coefficients. Note that 'b' is not + required for the implemented solution. + ''' + s_norm = s / total_length + lane_offset = lane_offset_coefficients['a'] + \ + (lane_offset_coefficients['c'] * s_norm**2 + lane_offset_coefficients['d'] * s_norm**3) + return lane_offset + def get_lane_widths_road_joint(obj, contact_point): ''' Return the widths of the left and right road side of the road end @@ -463,24 +474,30 @@ def point_to_road_connector(obj, point): dist_end_r = (Vector(obj['cp_end_r']) - point).length distances = [dist_start_l, dist_start_r, dist_end_l, dist_end_r] arg_min_dist = distances.index(min(distances)) - width_left_start, width_right_start = get_lane_widths_road_joint(obj, contact_point='start') - width_left_end, width_right_end = get_lane_widths_road_joint(obj, contact_point='end') + widths_left_start, widths_right_start = get_lane_widths_road_joint(obj, contact_point='start') + widths_left_end, widths_right_end = get_lane_widths_road_joint(obj, contact_point='end') if arg_min_dist == 0: + lane_offset = calculate_lane_offset(0, obj['lane_offset_coefficients'], obj['geometry_total_length']) return 'cp_start_l', Vector(obj['cp_start_l']), obj['geometry'][0]['heading_start'] - pi, \ - -obj['geometry'][0]['curvature_start'], -obj['geometry'][0]['slope_start'], \ - width_left_start, width_right_start, obj['lanes_left_types'], obj['lanes_right_types'] + -obj['geometry'][0]['curvature_start'], -obj['geometry'][0]['slope_start'], lane_offset, \ + widths_left_start, widths_right_start, obj['lanes_left_types'], obj['lanes_right_types'] if arg_min_dist == 1: + lane_offset = calculate_lane_offset(0, obj['lane_offset_coefficients'], obj['geometry_total_length']) return 'cp_start_r', Vector(obj['cp_start_r']), obj['geometry'][0]['heading_start'] - pi, \ - -obj['geometry'][0]['curvature_start'], -obj['geometry'][0]['slope_start'], \ - width_left_start, width_right_start, obj['lanes_left_types'], obj['lanes_right_types'] + -obj['geometry'][0]['curvature_start'], -obj['geometry'][0]['slope_start'], lane_offset, \ + widths_left_start, widths_right_start, obj['lanes_left_types'], obj['lanes_right_types'] elif arg_min_dist == 2: + lane_offset = calculate_lane_offset( + obj['geometry_total_length'], obj['lane_offset_coefficients'], obj['geometry_total_length']) return 'cp_end_l', Vector(obj['cp_end_l']), obj['geometry'][-1]['heading_end'], \ - obj['geometry'][-1]['curvature_end'], obj['geometry'][-1]['slope_end'], \ - width_left_end, width_right_end, obj['lanes_left_types'], obj['lanes_right_types'] + obj['geometry'][-1]['curvature_end'], obj['geometry'][-1]['slope_end'], lane_offset, \ + widths_left_end, widths_right_end, obj['lanes_left_types'], obj['lanes_right_types'] else: + lane_offset = calculate_lane_offset( + obj['geometry_total_length'], obj['lane_offset_coefficients'], obj['geometry_total_length']) return 'cp_end_r', Vector(obj['cp_end_r']), obj['geometry'][-1]['heading_end'], \ - obj['geometry'][-1]['curvature_end'], obj['geometry'][-1]['slope_end'], \ - width_left_end, width_right_end, obj['lanes_left_types'], obj['lanes_right_types'] + obj['geometry'][-1]['curvature_end'], obj['geometry'][-1]['slope_end'], lane_offset, \ + widths_left_end, widths_right_end, obj['lanes_left_types'], obj['lanes_right_types'] def point_to_junction_joint_exterior(obj, point): ''' @@ -516,8 +533,8 @@ def get_closest_joint_lane_contact_point(joint, point, joint_side): lane_id = 0 for width_left in list(joint['lane_widths_left']): lane_id += 1 - t_contact_point = t - t_lane_center = t + width_left/2 + t_contact_point = t + joint['lane_offset'] + t_lane_center = t + width_left/2 + joint['lane_offset'] t += width_left lane_ids_left.append(lane_id) vec_hdg = Vector((1.0, 0.0, 0.0)) @@ -531,8 +548,8 @@ def get_closest_joint_lane_contact_point(joint, point, joint_side): lane_id = 0 for width_right in joint['lane_widths_right']: lane_id -= 1 - t_contact_point = t - t_lane_center = t - width_right/2 + t_contact_point = t + joint['lane_offset'] + t_lane_center = t - width_right/2 + joint['lane_offset'] t -= width_right lane_ids_right.append(lane_id) vec_hdg = Vector((1.0, 0.0, 0.0)) @@ -651,6 +668,7 @@ def mouse_to_road_joint_params(context, event, road_type, joint_side='both'): heading = 0 curvature = 0 slope = 0 + lane_offset_coefficients = {'a': 0, 'b': 0, 'c': 0, 'd': 0} lane_widths_left = [] lane_widths_right = [] lane_types_left = [] @@ -663,7 +681,7 @@ def mouse_to_road_joint_params(context, event, road_type, joint_side='both'): if obj['dsc_category'] == 'OpenDRIVE': if obj['dsc_type'].startswith('road_') and obj['dsc_type'] != 'road_object': hit_type = 'road' - point_type, snapped_point, heading, curvature, slope, \ + point_type, snapped_point, heading, curvature, slope, lane_offset_coefficients, \ lane_widths_left, lane_widths_right, lane_types_left, lane_types_right \ = point_to_road_connector(obj, raycast_point) id_obj = obj['id_odr'] @@ -720,6 +738,7 @@ def mouse_to_road_joint_params(context, event, road_type, joint_side='both'): 'heading': heading, 'curvature': curvature, 'slope': slope, + 'lane_offset_coefficients': lane_offset_coefficients, 'lane_widths_left': lane_widths_left, 'lane_widths_right': lane_widths_right, 'lane_types_left': lane_types_left, diff --git a/addon/junction.py b/addon/junction.py index ddf2712..1b37c1e 100644 --- a/addon/junction.py +++ b/addon/junction.py @@ -24,7 +24,7 @@ class junction_joint: def __init__(self, id_joint, id_incoming, contact_point_type, contact_point_vec, - heading, curvature, slope, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right): + heading, curvature, slope, lane_offset, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right): self.id_joint = id_joint self.id_incoming = id_incoming self.contact_point_type = contact_point_type @@ -32,6 +32,7 @@ def __init__(self, id_joint, id_incoming, contact_point_type, contact_point_vec, self.heading = heading self.curvature = curvature self.slope = slope + self.lane_offset = lane_offset self.lane_widths_left = lane_widths_left self.lane_widths_right = lane_widths_right self.lane_types_left = lane_types_left @@ -65,7 +66,8 @@ def get_new_id_joint(self): return id_next def add_joint_incoming(self, id_incoming, contact_point_type, contact_point_vec, - heading, curvature, slope, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right): + heading, curvature, slope, lane_offset, + lane_widths_left, lane_widths_right, lane_types_left, lane_types_right): ''' Add a new joint, i.e. an incoming road to the junction if it does not exist yet. @@ -75,18 +77,20 @@ def add_joint_incoming(self, id_incoming, contact_point_type, contact_point_vec, else: id_joint = self.get_new_id_joint() joint = junction_joint(id_joint, id_incoming, contact_point_type, contact_point_vec, - heading, curvature, slope, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right) + heading, curvature, slope, lane_offset, + lane_widths_left, lane_widths_right, lane_types_left, lane_types_right) self.joints.append(joint) return True - def add_joint_open(self, contact_point_vec, heading, slope, + def add_joint_open(self, contact_point_vec, heading, slope, lane_offset, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right): ''' Add a new joint without connecting to an incoming road. ''' id_joint = self.get_new_id_joint() joint = junction_joint(id_joint, None, 'junction_joint_open', contact_point_vec, - heading, 0.0, slope, lane_widths_left, lane_widths_right, lane_types_left, lane_types_right) + heading, 0.0, slope, lane_offset, + lane_widths_left, lane_widths_right, lane_types_left, lane_types_right) self.joints.append(joint) return True @@ -231,10 +235,10 @@ def get_mesh(self, wireframe=False): # Find corner points of incoming road joint vector_s = Vector((1.0, 0.0, 0.0)) vector_s.rotate(Matrix.Rotation(joint.heading + pi/2, 3, 'Z')) - width_left = sum(joint.lane_widths_left) + width_left = sum(joint.lane_widths_left) + joint.lane_offset point_local_left = matrix_world.inverted() \ @ (joint.contact_point_vec + vector_s * width_left) - width_right = sum(joint.lane_widths_right) + width_right = sum(joint.lane_widths_right) - joint.lane_offset point_local_right = matrix_world.inverted() \ @ (joint.contact_point_vec - vector_s * width_right) joints_heading.append(joint.heading) diff --git a/addon/modal_junction_generic.py b/addon/modal_junction_generic.py index 83407e4..1c56cd2 100644 --- a/addon/modal_junction_generic.py +++ b/addon/modal_junction_generic.py @@ -68,12 +68,14 @@ def modal(self, context, event): contact_point_vec = self.params_snap['point'].copy() # Calculate width of junction joints based on road direction if self.params_snap['point_type'].startswith('cp_end'): + joint_lane_offset = self.params_snap['lane_offset_coefficients'] joint_widths_left = self.params_snap['lane_widths_left'] joint_widths_right = self.params_snap['lane_widths_right'] joint_lane_types_left = self.params_snap['lane_types_left'] joint_lane_types_right = self.params_snap['lane_types_right'] else: # Switch direction if road points away from junction joint + joint_lane_offset = self.params_snap['lane_offset_coefficients'] joint_widths_left = self.params_snap['lane_widths_right'] joint_widths_right = self.params_snap['lane_widths_left'] joint_lane_types_left = self.params_snap['lane_types_right'] @@ -81,7 +83,8 @@ def modal(self, context, event): joint_added = self.junction.add_joint_incoming(self.params_snap['id_obj'], self.params_snap['point_type'], contact_point_vec, self.params_snap['heading'], self.params_snap['curvature'], self.params_snap['slope'], - joint_widths_left, joint_widths_right, joint_lane_types_left, joint_lane_types_right) + joint_lane_offset, joint_widths_left, joint_widths_right, + joint_lane_types_left, joint_lane_types_right) if joint_added: self.junction.update_stencil() else: diff --git a/addon/modal_road_base.py b/addon/modal_road_base.py index 62b6038..2ab629d 100644 --- a/addon/modal_road_base.py +++ b/addon/modal_road_base.py @@ -391,6 +391,7 @@ def modal(self, context, event): self.selected_slope = 0 self.selected_normal_start = Vector((0.0,0.0,1.0)) if (event.alt or self.always_adjust_heading) \ + and self.state != 'SELECT_START' \ and self.params_input['connected_start'] == False \ and len(self.params_input['points']) == 2: # Calculate angular change to update start heading diff --git a/addon/modal_road_object_base.py b/addon/modal_road_object_base.py index aa9762e..d169c80 100644 --- a/addon/modal_road_object_base.py +++ b/addon/modal_road_object_base.py @@ -26,9 +26,9 @@ from . geometry_parampoly3 import DSC_geometry_parampoly3 -def load_geometry(road_type, section_data): +def load_geometry(road_type, section_data, lane_offset): ''' - Load geometry from stored sections data. + Load geometry from stored geometry data. ''' geometry = None if road_type == 'road_straight': @@ -44,6 +44,7 @@ def load_geometry(road_type, section_data): if geometry != None: geometry.load_sections(section_data) + geometry.lane_offset_coefficients = lane_offset return geometry diff --git a/addon/params_cross_section.py b/addon/params_cross_section.py index 87091b9..66a4905 100644 --- a/addon/params_cross_section.py +++ b/addon/params_cross_section.py @@ -21,9 +21,25 @@ 'road_mark_weights': ['none', 'standard', 'standard', 'standard', 'none'], 'road_mark_widths': [0.0, 0.12, 0.12, 0.12, 0.0], 'road_mark_colors': ['none', 'white', 'white', 'white', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 4, }, + 'two_lanes_turning_lane_offset_left_open': { + 'sides': ['left', 'left', 'center', 'right', 'right', 'right'], + 'widths_start': [0.20, 3.5, 0.0, 0.0, 3.5, 0.20], + 'widths_end': [0.20, 3.5, 0.0, 3.5, 3.5, 0.20], + 'types': ['border', 'driving', 'center', 'driving', 'driving', 'border'], + 'road_mark_types': ['none', 'solid', 'broken', 'broken', 'solid', 'none'], + 'road_mark_weights': ['none', 'standard', 'standard', 'standard', 'standard', 'none'], + 'road_mark_widths': [0.0, 0.12, 0.12, 0.12, 0.12, 0.0], + 'road_mark_colors': ['none', 'white', 'white', 'white', 'white', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 1, + 'road_split_type': 'none', + 'road_split_lane_idx': 5, + }, # Typical German road cross sections # See: # https://de.wikipedia.org/wiki/Richtlinien_f%C3%BCr_die_Anlage_von_Stra%C3%9Fen_%E2%80%93_Querschnitt @@ -42,6 +58,8 @@ 'road_mark_weights': ['none', 'none', 'standard', 'standard', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.12, 0.12, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 5, }, @@ -54,6 +72,8 @@ 'road_mark_weights': ['none', 'none', 'standard', 'standard', 'standard', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.12, 0.12, 0.12, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 6, }, @@ -66,6 +86,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 14, }, @@ -78,6 +100,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 15, }, @@ -90,6 +114,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'end', 'road_split_lane_idx': 11, }, @@ -102,6 +128,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 11, }, @@ -114,6 +142,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'start', 'road_split_lane_idx': 13, }, @@ -126,6 +156,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'end', 'road_split_lane_idx': 13, }, @@ -138,6 +170,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'start', 'road_split_lane_idx': 11, }, @@ -150,6 +184,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'bold', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.30, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 15, }, @@ -162,6 +198,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'standard', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.15, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 16, }, @@ -174,6 +212,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'standard', 'standard', 'standard', 'bold', 'none', 'none', 'none', 'bold', 'standard', 'standard', 'standard', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.15, 0.15, 0.15, 0.30, 0.0, 0.0, 0.0, 0.30, 0.15, 0.15, 0.15, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white', 'white', 'white', 'white', 'none', 'none', 'none', 'white', 'white', 'white', 'white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 18, }, @@ -186,6 +226,8 @@ 'road_mark_weights': ['bold', 'bold', 'none', 'none', 'none'], 'road_mark_widths': [0.30, 0.30, 0.0, 0.0, 0.0], 'road_mark_colors': ['white', 'white', 'none', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 5, }, @@ -198,6 +240,8 @@ 'road_mark_weights': ['none', 'none', 'bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'start', 'road_split_lane_idx': 1, }, @@ -210,6 +254,8 @@ 'road_mark_weights': ['none', 'none', 'bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 6, }, @@ -222,6 +268,8 @@ 'road_mark_weights': ['none', 'none','bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 0, }, @@ -234,6 +282,8 @@ 'road_mark_weights': ['none', 'none', 'none', 'bold', 'bold'], 'road_mark_widths': [0.0, 0.0, 0.0, 0.30, 0.30], 'road_mark_colors': ['none', 'none', 'none', 'white', 'white'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 4, }, @@ -246,6 +296,8 @@ 'road_mark_weights': ['none', 'none', 'bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'start', 'road_split_lane_idx': 4, }, @@ -258,6 +310,8 @@ 'road_mark_weights': ['none', 'none', 'bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 5, }, @@ -270,6 +324,8 @@ 'road_mark_weights': ['none', 'none', 'bold', 'bold', 'none', 'none'], 'road_mark_widths': [0.0, 0.0, 0.30, 0.30, 0.0, 0.0], 'road_mark_colors': ['none', 'none', 'white', 'white', 'none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 5, }, @@ -282,6 +338,8 @@ 'road_mark_weights': ['none', 'none'], 'road_mark_widths': [0.0, 0.0], 'road_mark_colors': ['none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 1, }, @@ -294,6 +352,8 @@ 'road_mark_weights': ['none', 'none'], 'road_mark_widths': [0.0, 0.0], 'road_mark_colors': ['none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 1, }, @@ -306,6 +366,8 @@ 'road_mark_weights': ['none', 'none'], 'road_mark_widths': [0.0, 0.0], 'road_mark_colors': ['none', 'none'], + 'lane_offset_start': 0, + 'lane_offset_end': 0, 'road_split_type': 'none', 'road_split_lane_idx': 1, }, diff --git a/addon/popup_road_properties.py b/addon/popup_road_properties.py index e323674..943bba2 100644 --- a/addon/popup_road_properties.py +++ b/addon/popup_road_properties.py @@ -124,6 +124,19 @@ def draw(self, context): row.prop(context.scene.dsc_properties.road_properties, 'num_lanes_right', text='') row.separator() + row = box.row() + row.label(text='Lane offset:') + row = box.row() + row.separator() + row.label(text='Start:') + row.prop(context.scene.dsc_properties.road_properties, 'lane_offset_start', text='') + row.separator() + row.separator() + row.separator() + row.label(text='End:') + row.prop(context.scene.dsc_properties.road_properties, 'lane_offset_end', text='') + row.separator() + row = box.row() row.label(text='Road split at:') row.prop(context.scene.dsc_properties.road_properties, 'road_split_type', text='') diff --git a/addon/road.py b/addon/road.py index f2a377a..1a82cd0 100644 --- a/addon/road.py +++ b/addon/road.py @@ -127,6 +127,7 @@ def create_object_3d(self, context, params_input): if self.geometry.sections[0]['curve_type'] == 'spiral_triple': # Store parameters for sub sections obj['geometry_subsections'] = [ section_curve.get_segment_params() for section_curve in self.geometry.section_curves ] + obj['lane_offset_coefficients'] = self.geometry.lane_offset_coefficients obj['lanes_left_num'] = self.params['lanes_left_num'] obj['lanes_right_num'] = self.params['lanes_right_num'] @@ -152,11 +153,6 @@ def update_params_get_mesh(self, context, params_input, wireframe): ''' Calculate and return the vertices, edges, faces and parameters to create a road mesh. ''' - # Update parameters based on selected points - self.geometry.update(params_input, self.geometry_solver) - if self.geometry.sections[-1]['valid'] == False: - valid = False - return valid, None, None, [] if self.road_type == 'junction_connecting_road': length_broken_line = context.scene.dsc_properties.connecting_road_properties.length_broken_line self.set_lane_params(context.scene.dsc_properties.connecting_road_properties) @@ -165,6 +161,11 @@ def update_params_get_mesh(self, context, params_input, wireframe): length_broken_line = context.scene.dsc_properties.road_properties.length_broken_line self.set_lane_params(context.scene.dsc_properties.road_properties) lanes = context.scene.dsc_properties.road_properties.lanes + # Update parameters based on selected points + self.geometry.update(params_input, self.params['lane_offset_start'], self.params['lane_offset_end'],self.geometry_solver) + if self.geometry.sections[-1]['valid'] == False: + valid = False + return valid, None, None, [] # Get values in t and s direction where the faces of the road start and end strips_s_boundaries = self.get_strips_s_boundaries(lanes, length_broken_line) # Calculate meshes for Blender @@ -195,6 +196,23 @@ def update_params_get_mesh(self, context, params_input, wireframe): valid = True return valid, mesh, self.geometry.matrix_world, materials + def calculate_lane_offset_start_end_in_m(self, lane_offset, lanes_left_width, lanes_right_width): + ''' + Calculate lane offset in [m] based on lane widths. + ''' + lane_offset_m = 0.0 + if lane_offset == 0: + return lane_offset_m + if lane_offset < 0: + for i in range(len(lanes_left_width)): + if i < abs(lane_offset): + lane_offset_m -= lanes_left_width[i] + else: + for i in range(len(lanes_right_width)): + if i < lane_offset: + lane_offset_m += lanes_right_width[i] + return lane_offset_m + def set_lane_params(self, road_properties): ''' Set the lane parameters dictionary for later export. @@ -216,6 +234,8 @@ def set_lane_params(self, road_properties): 'lane_center_road_mark_type': [], 'lane_center_road_mark_weight': [], 'lane_center_road_mark_color': [], + 'lane_offset_start': road_properties.lane_offset_start, + 'lane_offset_end': road_properties.lane_offset_end, 'road_split_type': road_properties.road_split_type, 'road_split_lane_idx': road_properties.road_split_lane_idx} for idx, lane in enumerate(road_properties.lanes): @@ -238,6 +258,10 @@ def set_lane_params(self, road_properties): self.params['lane_center_road_mark_type'] = lane.road_mark_type self.params['lane_center_road_mark_weight'] = lane.road_mark_weight self.params['lane_center_road_mark_color'] = lane.road_mark_color + self.params['lane_offset_start'] = self.calculate_lane_offset_start_end_in_m(road_properties.lane_offset_start, + self.params['lanes_left_widths_start'], self.params['lanes_right_widths_start']) + self.params['lane_offset_end'] = self.calculate_lane_offset_start_end_in_m(road_properties.lane_offset_end, + self.params['lanes_left_widths_end'], self.params['lanes_right_widths_end']) def get_split_cps(self): ''' @@ -461,10 +485,9 @@ def get_road_sample_points(self, lanes, strips_s_boundaries): # We need 2 vectors for each strip to later construct the faces with one # list per face on each side of each strip sample_points = [[[]] for _ in range(2 * (len(strips_t_values) - 1))] - t_offset = 0 for idx_t in range(len(strips_t_values) - 1): - sample_points[2 * idx_t][0].append((0, strips_t_values[idx_t], 0)) - sample_points[2 * idx_t + 1][0].append((0, strips_t_values[idx_t + 1], 0)) + sample_points[2 * idx_t][0].append(xyz_samples[idx_t]) + sample_points[2 * idx_t + 1][0].append(xyz_samples[idx_t + 1]) # Concatenate vertices until end of road idx_boundaries_strips = [0] * len(strips_s_boundaries) while s < length: @@ -487,8 +510,6 @@ def get_road_sample_points(self, lanes, strips_s_boundaries): point_index = -2 while point_index < len(sample_points) - 2: point_index = point_index + 2 - if not sample_points[point_index][0]: - continue idx_strip = point_index//2 # Get the boundaries of road marking faces for current strip plus left and right idx_boundaries = [0, 0, 0] @@ -564,9 +585,6 @@ def get_road_vertices_edges_faces(self, road_sample_points): point_index = 0 while point_index < len(road_sample_points): for idx_face_strip in range(len(road_sample_points[point_index])): - # ignore empty samplepoints, it may be none type line or any thing that doesn't need to build a mesh - if not road_sample_points[point_index][0]: - continue samples_right = road_sample_points[point_index + 1][idx_face_strip] samples_left = road_sample_points[point_index][idx_face_strip] num_vertices = len(samples_left) + len(samples_right) diff --git a/addon/road_properties.py b/addon/road_properties.py index 9e5cb92..ed46c22 100644 --- a/addon/road_properties.py +++ b/addon/road_properties.py @@ -28,6 +28,7 @@ def callback_road_mark_weight(self, context): def callback_road_split(self, context): self.update_road_split(context) + class DSC_enum_lane(bpy.types.PropertyGroup): idx: bpy.props.IntProperty(min=0) side: bpy.props.EnumProperty( @@ -188,6 +189,9 @@ class DSC_road_properties(bpy.types.PropertyGroup): num_lanes_left: bpy.props.IntProperty(default=2, min=0, max=20, update=callback_num_lanes) num_lanes_right: bpy.props.IntProperty(default=2, min=0, max=20, update=callback_num_lanes) + lane_offset_start: bpy.props.IntProperty(default=0, min=-20, max=20) + lane_offset_end: bpy.props.IntProperty(default=0, min=-20, max=20) + road_split_type: bpy.props.EnumProperty( name = 'Split type', items=(('none', 'None', '', 0), @@ -205,6 +209,7 @@ class DSC_road_properties(bpy.types.PropertyGroup): cross_section_preset: bpy.props.EnumProperty( items=( ('two_lanes_default','Two lanes (default)','Two lanes (default)'), + ('two_lanes_turning_lane_offset_left_open','Two lanes with offset left turning lane opening','Two lanes with opening offset left turning lane'), # Typical German road cross sections ('ekl4_rq9', 'EKL 4, RQ 9', 'EKL 4, RQ 9'), ('ekl3_rq11', 'EKL 3, RQ 11', 'EKL 3, RQ 11'), @@ -215,13 +220,13 @@ class DSC_road_properties(bpy.types.PropertyGroup): # ('eka3_rq38_5', 'EKA 3, RQ 38_5', 'EKA 3, RQ 38_5'), # ('eka2_rq28', 'EKA 1, RQ 28', 'EKA 1, RQ 28'), ('eka1_rq31', 'EKA 1, RQ 31', 'EKA 1, RQ 31'), - ('eka1_rq31_exit_lane_right_open', 'EKA 1, RQ 31 - exit lane right open', 'EKA 1, RQ 31 - exit lane right open'), + ('eka1_rq31_exit_lane_right_open', 'EKA 1, RQ 31 - exit lane right opening', 'EKA 1, RQ 31 - exit lane right opening'), ('eka1_rq31_exit_lane_right_to_off_ramp', 'EKA 1, RQ 31 - exit lane right to off-ramp', 'EKA 1, RQ 31 - exit lane right to off-ramp'), ('eka1_rq31_exit_right_continuation_begin_end', 'EKA 1, RQ 31 - exit right continuation begin/end', 'EKA 1, RQ 31 - exit right continuation begin/end'), ('eka1_rq31_exit_right_continuation_shoulder_begin', 'EKA 1, RQ 31 - exit right continuation shoulder begin', 'EKA 1, RQ 31 - exit right continuation shoulder begin'), ('eka1_rq31_exit_right_continuation_shoulder_end', 'EKA 1, RQ 31 - exit right continuation shoulder end', 'EKA 1, RQ 31 - exit right continuation shoulder end'), ('eka1_rq31_entry_right_from_on_ramp', 'EKA 1, RQ 31 - entry right from on-ramp', 'EKA 1, RQ 31 - entry right from on-ramp'), - ('eka1_rq31_entry_right_close', 'EKA 1, RQ 31 - entry right close', 'EKA 1, RQ 31 - entry right close'), + ('eka1_rq31_entry_right_close', 'EKA 1, RQ 31 - entry right closing', 'EKA 1, RQ 31 - entry right closing'), ('eka1_rq36', 'EKA 1, RQ 36', 'EKA 1, RQ 36'), ('eka1_rq43_5', 'EKA 1, RQ 43.5', 'EKA 1, RQ 43.5'), ('off_ramp_begin', 'Off-ramp begin', 'Off-ramp begin'), @@ -334,6 +339,8 @@ def update_cross_section(self): num_lanes_left += 1 if params['sides'][idx] == 'right': num_lanes_right += 1 + self.lane_offset_start = params['lane_offset_start'] + self.lane_offset_end = params['lane_offset_end'] self.road_split_type = params['road_split_type'] self.road_split_lane_idx = params['road_split_lane_idx'] for idx, lane in enumerate(self.lanes): diff --git a/tests/test_geometry_arc.py b/tests/test_geometry_arc.py index 0548a1f..9cfd24d 100644 --- a/tests/test_geometry_arc.py +++ b/tests/test_geometry_arc.py @@ -28,7 +28,7 @@ def test_geometry_arc_straight_case(): params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) params_input['heading_end'] = params_input['heading_start'] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) # Sample the first section length_0 = geometry.total_length @@ -39,7 +39,7 @@ def test_geometry_arc_straight_case(): # Add a second section params_input['points'] = [Vector((2.0, 1.0, 0.0)), Vector((6.0, 3.0, 0.0)), Vector((8.0, 4.0, 0.0))] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) # Sample the first section again length_0 = geometry.sections[0]['length'] @@ -61,7 +61,7 @@ def test_geometry_arc_180(): params_input['points'] = [Vector((0.0, 0.0, 0.0)), Vector((0.0, 2.0, 0.0))] params_input['heading_start'] = 0 geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length_0 = geometry.total_length xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0]) @@ -76,7 +76,7 @@ def test_geometry_arc_negative_start_heading(): params_input['points'] = [Vector((0.0, 0.0, 0.0)), Vector((-1.0, 1.0, 0.0))] params_input['heading_start'] = 3/4*pi geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) xyz_local, h, c = geometry.sample_cross_section(s=geometry.total_length, t_vec=[sqrt(2.0)]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -91,7 +91,7 @@ def test_geometry_arc_y_axis_straight(): params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) params_input['heading_end'] = params_input['heading_start'] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length_0 = geometry.total_length xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0/2, t_vec=[0.0]) @@ -107,7 +107,7 @@ def test_geometry_arc_270_three_pieces(): Vector((20.0, 20.0, 0.0))] params_input['heading_start'] = 0 geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length_0 = geometry.total_length xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[5.0]) @@ -118,7 +118,7 @@ def test_geometry_arc_270_three_pieces(): Vector((20.0, 20.0, 0.0)), Vector((10.0, 30.0, 0.0))] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length = geometry.total_length xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[2.0]) @@ -130,7 +130,7 @@ def test_geometry_arc_270_three_pieces(): Vector((10.0, 30.0, 0.0)), Vector((0.0, 20.0, 0.0))] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length = geometry.total_length xyz_local, h_0, c_0 = geometry.sample_cross_section(s=length, t_vec=[-5.0]) diff --git a/tests/test_geometry_clothoid.py b/tests/test_geometry_clothoid.py index 99db7e9..31cd736 100644 --- a/tests/test_geometry_clothoid.py +++ b/tests/test_geometry_clothoid.py @@ -27,7 +27,7 @@ def test_geometry_clothoid(): params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) params_input['heading_end'] = params_input['heading_start'] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length_0 = geometry.total_length xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0]) @@ -36,7 +36,7 @@ def test_geometry_clothoid(): params_input['points'] = [Vector((2.0, 1.0, 0.0)), Vector((6.0, 3.0, 0.0)), Vector((8.0, 4.0, 0.0))] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0 solver) length_0 = geometry.sections[0]['length'] xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0]) diff --git a/tests/test_geometry_line.py b/tests/test_geometry_line.py index b055d14..1f3a398 100644 --- a/tests/test_geometry_line.py +++ b/tests/test_geometry_line.py @@ -26,7 +26,7 @@ def test_geometry_line_1d(): params_input['points'] = [Vector((10.0, 10.0, 0.0)), Vector((20.0, 10.0, 0.0))] params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -34,7 +34,7 @@ def test_geometry_line_1d(): params_input['points'] = [Vector((10.0, 10.0, 0.0)), Vector((20.0, 10.0, 0.0)), Vector((30.0, 10.0, 0.0))] geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length length_section = geometry.sections[1]['length'] xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0]) @@ -49,7 +49,7 @@ def test_geometry_line_2d(): params_input['points'] = [Vector((20.0, 10.0, 0.0)), Vector((60.0, 30.0, 0.0))] params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -57,7 +57,7 @@ def test_geometry_line_2d(): params_input['points'] = [Vector((20.0, 10.0, 0.0)), Vector((60.0, 30.0, 0.0)), Vector((100.0, 50.0, 0.0))] geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length length_section = geometry.sections[1]['length'] xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0]) @@ -67,7 +67,7 @@ def test_geometry_line_2d(): params_input['points'] = [Vector((20.0, 10.0, 0.0)), Vector((60.0, 30.0, 0.0)), Vector((100.0, 50.0, 0.0)), Vector((320.0, 160.0, 0.0))] geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -81,7 +81,7 @@ def test_geometry_line_2d_projection(): params_input['points'] = [Vector((20.0, 10.0, 0.0)), Vector((60.0, 30.0, 0.0))] params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -89,7 +89,7 @@ def test_geometry_line_2d_projection(): params_input['points'] = [Vector((20.0, 10.0, 0.0)), Vector((60.0, 30.0, 0.0)), Vector((90.0, 70.0, 0.0))] geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length length_section = geometry.sections[1]['length'] xyz_local, h, c = geometry.sample_cross_section(s=length-length_section/2, t_vec=[0.0]) @@ -105,7 +105,7 @@ def test_geometry_line_3d(): params_input['points'] = [Vector((2.0, 1.0, 1.0)), Vector((6.0, 3.0, 2.0))] params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length/2.0, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) @@ -113,7 +113,7 @@ def test_geometry_line_3d(): params_input['points'] = [Vector((2.0, 1.0, 1.0)), Vector((6.0, 3.0, 2.0)), Vector((10.0, 5.0, 4.0))] geometry.add_section() - geometry.update(params_input, None) + geometry.update(params_input, 0.0, 0.0, None) length = geometry.total_length xyz_local, h, c = geometry.sample_cross_section(s=length, t_vec=[0.0]) xyz_global = geometry.matrix_world @ Vector(xyz_local[0]) diff --git a/tests/test_geometry_parampoly3.py b/tests/test_geometry_parampoly3.py index e312684..4a46fc8 100644 --- a/tests/test_geometry_parampoly3.py +++ b/tests/test_geometry_parampoly3.py @@ -27,7 +27,7 @@ def test_geometry_parampoly3(): params_input['heading_start'] = get_heading_start(params_input['points'][0], params_input['points'][1]) params_input['heading_end'] = params_input['heading_start'] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0, solver) length_0 = geometry.total_length xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0]) @@ -36,7 +36,7 @@ def test_geometry_parampoly3(): params_input['points'] = [Vector((10.0, 0.0, 0.0)), Vector((30.0, 0.0, 0.0)), Vector((40.0, 0.0, 0.0))] geometry.add_section() - geometry.update(params_input, solver) + geometry.update(params_input, 0.0, 0.0, solver) length_0 = geometry.sections[0]['length'] xyz_local_0, h_0, c_0 = geometry.sample_cross_section(s=length_0, t_vec=[0.0])