def _pyramidal_top(ac_object: ac.Object, x_centre: float, y_centre: float, top: float, roof_texture, roof_mat_idx: int, pyramid_height: float, ring: List[List[float]], object_node_index: int) -> None: """Adds the pyramidal top by adding the centre node and the necessary faces. ring is a list of x,y coordinates for the current top points of the roof. """ # add node for the middle of the roof ac_object.node(-1 * y_centre, top, -1 * x_centre) roof_texture_size = roof_texture.h_size_meters # loop on sides of the building n_pts = len(ring) # number of points for i in range(0, n_pts): dist_inwards = coord.calc_distance_local(ring[i][0], ring[i][1], x_centre, y_centre) j = (i+1) % n_pts dist_edge = coord.calc_distance_local(ring[i][0], ring[i][1], ring[j][0], ring[j][1]) len_roof_hypo = (dist_inwards ** 2 + pyramid_height ** 2) ** 0.5 repeat_x = dist_edge/roof_texture_size repeat_y = len_roof_hypo/roof_texture_size ac_object.face([(object_node_index + i, roof_texture.x(0), roof_texture.y(0)), (object_node_index + j, roof_texture.x(repeat_x), roof_texture.y(0)), (object_node_index + n_pts, roof_texture.x(0.5*repeat_x), roof_texture.y(repeat_y))], mat_idx=roof_mat_idx)
def _extend_trees_if_dist_ok(potential_trees: List[Tree], trees: List[Tree]) -> None: """Extend the existing list of trees with new trees if the new trees have a minimal dest from the existing ones.""" for a_tree in reversed(potential_trees): for other_tree in trees: if co.calc_distance_local(a_tree.x, a_tree.y, other_tree.x, other_tree.y) \ < parameters.C2P_TREES_DIST_MINIMAL: potential_trees.remove(a_tree) break trees.extend(potential_trees)
def _add_sides_gabled_facade_tex(ac_object, t, object_node_index: int, idx_offset_top: int, facade_mat_idx: int, roof_height: float, roof_texture_size_x: float, roof_texture_size_y: float, first_node, first_node_idx: int, second_node, second_node_idx: int, third_node, third_node_idx: int, fourth_node, fourth_node_idx: int) -> None: """Add the sides to roof through ac_object where it is gabled and facade texture.""" eaves_len = coord.calc_distance_local(first_node[0], first_node[1], second_node[0], second_node[1]) eaves_x = eaves_len / roof_texture_size_x repeat_y = roof_height / roof_texture_size_y ac_object.face([(object_node_index + first_node_idx, t.x(0), t.y(0)), (object_node_index + second_node_idx, t.x(eaves_x), t.y(0)), (object_node_index + 10 - idx_offset_top, t.x(0.5 * eaves_x), t.y(repeat_y))], # node_10 mat_idx=facade_mat_idx) eaves_len = coord.calc_distance_local(third_node[0], third_node[1], fourth_node[0], fourth_node[1]) eaves_x = eaves_len / roof_texture_size_x repeat_y = roof_height / roof_texture_size_y ac_object.face([(object_node_index + third_node_idx, t.x(0), t.y(0)), (object_node_index + fourth_node_idx, t.x(eaves_x), t.y(0)), # node_0 (object_node_index + 11 - idx_offset_top, t.x(0.5 * eaves_x), t.y(repeat_y))], # node_11 mat_idx=facade_mat_idx)
def match_local_coords_with_global_nodes( local_list: List[Tuple[float, float]], ref_list: List[int], all_nodes: Dict[int, op.Node], coords_transform: co.Transformation, osm_id: int, create_node: bool = False) -> List[int]: """Given a set of coordinates in local space find matching Node objects in global space. Matching is using a bit of tolerance (cf. parameter), which should be enough to account for conversion precision resp. float precision. If a node cannot be matched: if parameter create_node is False, then a ValueError is thrown - else a new Node is created and added to the all_nodes dict. """ matched_nodes = list() nodes_local = dict( ) # key is osm_id from Node, value is Tuple[float, float] for ref in ref_list: node = all_nodes[ref] nodes_local[node.osm_id] = coords_transform.to_local( (node.lon, node.lat)) for local in local_list: closest_distance = 999999 found_key = -1 for key, node_local in nodes_local.items(): distance = co.calc_distance_local(local[0], local[1], node_local[0], node_local[1]) if distance < closest_distance: closest_distance = distance if distance < parameters.TOLERANCE_MATCH_NODE: found_key = key break if found_key < 0: if create_node: lon, lat = coords_transform.to_global(local) new_node = op.Node( op.get_next_pseudo_osm_id( op.OSMFeatureType.building_relation), lat, lon) all_nodes[new_node.osm_id] = new_node matched_nodes.append(new_node.osm_id) else: raise ValueError( 'No match for parent with osm_id = %d. Closest: %f' % (osm_id, closest_distance)) else: matched_nodes.append(found_key) return matched_nodes
def separate_pyramidal(ac_object: ac.Object, b, roof_mat_idx: int) -> None: """Pyramidal, dome or onion roof.""" shape = b.roof_shape roof_texture = b.roof_texture roof_height = sanity_roof_height_complex(b, 'pyramidal') bottom = b.beginning_of_roof_above_sea_level # add nodes for each of the corners object_node_index = ac_object.next_node_index() prev_ring = list() for pt in b.pts_all: ac_object.node(-pt[1], bottom, -pt[0]) prev_ring.append([pt[0], pt[1]]) # calculate node for the middle node of the roof x_centre = sum([xi[0] for xi in b.pts_all])/len(b.pts_all) y_centre = sum([xi[1] for xi in b.pts_all])/len(b.pts_all) ring = b.pts_all top = bottom + roof_height if shape in [enu.RoofShape.dome, enu.RoofShape.onion]: # For dome and onion we need to add new rings and faces before the top height_share = list() # the share of the roof height by each ring radius_share = list() # the share of the radius by each ring if shape is enu.RoofShape.dome: # we use five additional rings height_share = [sin(radians(90 / 6)), sin(radians(90 * 2 / 6)), sin(radians(90 * 3 / 6)), sin(radians(90 * 4 / 6)), sin(radians(90 * 5 / 6))] radius_share = [cos(radians(90 / 6)), cos(radians(90 * 2 / 6)), cos(radians(90 * 3 / 6)), cos(radians(90 * 4 / 6)), cos(radians(90 * 5 / 6))] else: # we use five additional rings based on guessed values - onion diameter gets broader than drum height_share = [.1, .2, .3, .4, .5, .7] radius_share = [1.2, 1.25, 1.2, 1., .6, .2] # texture it roof_texture_size = roof_texture.h_size_meters # size of roof texture in meters n_pts = len(ring) for r in range(0, len(height_share)): ring = list() top = bottom + roof_height * height_share[r] # calculate the new points of the ring for pt in b.pts_all: x, y = coord.calc_point_on_line_local(pt[0], pt[1], x_centre, y_centre, 1 - radius_share[r]) ac_object.node(-y, top, -x) ring.append([x, y]) # create the faces prev_offset = r * n_pts this_offset = (r+1) * n_pts for i in range(0, n_pts): j = (i + 1) % n_pts # little trick to reset to 0 dist_edge = coord.calc_distance_local(ring[i][0], ring[i][1], ring[j][0], ring[j][1]) dist_edge_prev = coord.calc_distance_local(prev_ring[i][0], prev_ring[i][1], prev_ring[j][0], prev_ring[j][1]) ring_height_diff = height_share[r] * roof_height ring_radius_diff = coord.calc_distance_local(ring[i][0], ring[i][1], prev_ring[i][0], prev_ring[i][1]) len_roof_hypo = (ring_height_diff ** 2 + ring_radius_diff ** 2) ** 0.5 repeat_x = dist_edge / roof_texture_size repeat_y = len_roof_hypo / roof_texture_size ac_object.face([(object_node_index + i + prev_offset, roof_texture.x(0), roof_texture.y(0)), (object_node_index + j + prev_offset, roof_texture.x(repeat_x), roof_texture.y(0)), (object_node_index + j + this_offset, roof_texture.x(repeat_x), roof_texture.y(repeat_y)), (object_node_index + i + this_offset, roof_texture.x(0), roof_texture.y(repeat_y))], mat_idx=roof_mat_idx) prev_ring = copy.deepcopy(ring) # prepare for pyramidal top top = bottom + roof_height bottom = bottom + roof_height * height_share[-1] object_node_index += len(height_share) * n_pts # add the pyramidal top _pyramidal_top(ac_object, x_centre, y_centre, top, roof_texture, roof_mat_idx, top - bottom, ring, object_node_index)
def separate_gable(ac_object, b, roof_mat_idx: int, facade_mat_idx: int, inward_meters=0.) -> None: """Gabled or gambrel roof (or hipped if inward_meters > 0) with 4 nodes.""" t = b.roof_texture my_type = 'separate_gable' if inward_meters > 0: my_type = 'separate_hipped' roof_height = sanity_roof_height_complex(b, my_type) # get orientation if exits: osm_roof_orientation_exists = False if s.K_ROOF_ORIENTATION in b.tags: osm_roof_orientation_exists = True osm_roof_orientation = str(b.tags[s.K_ROOF_ORIENTATION]) if not (osm_roof_orientation in [s.V_ALONG, s.V_ACROSS]): osm_roof_orientation_exists = False osm_roof_orientation = s.V_ALONG else: osm_roof_orientation = s.V_ALONG # search smallest and longest sides i_small = 3 i_long = 3 l_side2 = (b.pts_all[0][0] - b.pts_all[3][0])**2 + (b.pts_all[0][1] - b.pts_all[3][1])**2 l_small = l_side2 l_long = l_side2 for i in range(0, 3): l_side2 = (b.pts_all[i+1][0] - b.pts_all[i][0])**2 + (b.pts_all[i+1][1] - b.pts_all[i][1])**2 if l_side2 > l_long: i_long = i l_long = l_side2 elif l_side2 < l_small: i_small = i l_small = l_side2 i_side = i_long # i.e. "along" if osm_roof_orientation_exists: if osm_roof_orientation == s.V_ACROSS: i_side = i_small elif b.roof_hint is not None and b.roof_hint.ridge_orientation >= 0.: # only override if we have neighbours # calculate the angle of the "along" along_angle = coord.calc_angle_of_line_local(b.pts_all[i_long % 4][0], b.pts_all[i_long % 4][1], b.pts_all[(i_long + 1) % 4][0], b.pts_all[(i_long + 1) % 4][1]) if along_angle >= 180.: along_angle -= 180. difference = fabs(b.roof_hint.ridge_orientation - along_angle) # if the difference is closer to 90 than parallel, then change the orientation if 45 < difference < 135: i_side = i_small seq_n = [] # the sequence of nodes such that 0-1 and 2-3 are along with ridge in parallel in the middle for i in range(0, 4): seq_n.append((i_side + i) % 4) object_node_index = ac_object.next_node_index() # must be before nodes are added! # -- 4 corners for i in range(0, 4): ac_object.node(-b.pts_all[seq_n[i]][1], b.beginning_of_roof_above_sea_level, -b.pts_all[seq_n[i]][0]) # We don't want the hipped part to be larger than the height, which is 45 deg inward_meters = min(roof_height, inward_meters) if inward_meters > 0. and b.roof_shape is enu.RoofShape.hipped: # -- tangential vector of long edge (always [0, 0] if not hipped (because inward meters = 0) tang = (b.pts_all[seq_n[1]]-b.pts_all[seq_n[0]])/b.edge_length_pts[seq_n[1]] * inward_meters else: tang = [0., 0.] # nodes for the ridge with indexes 4 and 5 point_4 = coord.calc_point_on_line_local(b.pts_all[seq_n[0]][0], b.pts_all[seq_n[0]][1], b.pts_all[seq_n[3]][0], b.pts_all[seq_n[3]][1], 0.5) point_5 = coord.calc_point_on_line_local(b.pts_all[seq_n[1]][0], b.pts_all[seq_n[1]][1], b.pts_all[seq_n[2]][0], b.pts_all[seq_n[2]][1], 0.5) ac_object.node(-point_4[1], b.top_of_roof_above_sea_level, -point_4[0]) ac_object.node(-point_5[1], b.top_of_roof_above_sea_level, -point_5[0]) # after the nodes now the faces # The front and back have not necessarily the same length, as the # 4 sides might not make a perfect rectangle) len_roof_bottom_front = b.edge_length_pts[seq_n[0]] len_roof_bottom_back = b.edge_length_pts[seq_n[2]] len_roof_ridge = (len_roof_bottom_front + len_roof_bottom_back) / 2. roof_texture_size_x = t.h_size_meters # size of roof texture in meters roof_texture_size_y = t.v_size_meters repeat_x_front = ((len_roof_bottom_front + len_roof_ridge) / 2) / roof_texture_size_x repeat_x_back = ((len_roof_bottom_back + len_roof_ridge) / 2) / roof_texture_size_x if b.roof_shape in [enu.RoofShape.gabled, enu.RoofShape.hipped]: # roofs len_roof_hypo = ((0.5*b.edge_length_pts[seq_n[1]])**2 + roof_height**2)**0.5 repeat_y = len_roof_hypo / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(0), t.y(0)), (object_node_index + 1, t.x(repeat_x_front), t.y(0)), (object_node_index + 5, t.x(repeat_x_front*(1-inward_meters/len_roof_bottom_front)), t.y(repeat_y)), (object_node_index + 4, t.x(repeat_x_front*(inward_meters/len_roof_bottom_front)), t.y(repeat_y))], mat_idx=roof_mat_idx) ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), (object_node_index + 3, t.x(repeat_x_back), t.y(0)), (object_node_index + 4, t.x(repeat_x_back*(1-inward_meters/len_roof_bottom_back)), t.y(repeat_y)), (object_node_index + 5, t.x(repeat_x_back*(inward_meters/len_roof_bottom_back)), t.y(repeat_y))], mat_idx=roof_mat_idx) # sides # if roof is hipped, then facade_mat_idx is actually roof_mat_idx base_len = (inward_meters**2 + b.edge_length_pts[seq_n[1]]**2)**0.5 len_roof_hypo = (base_len**2 + roof_height**2)**0.5 repeat_y = len_roof_hypo/roof_texture_size_y repeat_x = b.edge_length_pts[seq_n[1]]/roof_texture_size_x ac_object.face([(object_node_index + 1, t.x(0), t.y(0)), (object_node_index + 2, t.x(repeat_x), t.y(0)), (object_node_index + 5, t.x(0.5*repeat_x), t.y(repeat_y))], mat_idx=facade_mat_idx) base_len = (inward_meters**2 + b.edge_length_pts[seq_n[3]]**2)**0.5 len_roof_hypo = (base_len**2 + roof_height**2)**0.5 repeat_y = len_roof_hypo/roof_texture_size_y repeat_x = b.edge_length_pts[seq_n[3]]/roof_texture_size_x ac_object.face([(object_node_index + 3, t.x(0), t.y(0)), (object_node_index + 0, t.x(repeat_x), t.y(0)), (object_node_index + 4, t.x(0.5*repeat_x), t.y(repeat_y))], mat_idx=facade_mat_idx) else: # b.roof_shape is RoofShape.gambrel. point_4 and point_5 on ridge still valid away_from_edge = GAMBREL_HEIGHT_RATIO_LOWER_PART * roof_height / tan(radians(GAMBREL_ANGLE_LOWER_PART)) distance_across_left = coord.calc_distance_local(b.pts_all[seq_n[0]][1], b.pts_all[seq_n[0]][0], b.pts_all[seq_n[3]][1], b.pts_all[seq_n[3]][0]) distance_across_right = coord.calc_distance_local(b.pts_all[seq_n[1]][1], b.pts_all[seq_n[1]][0], b.pts_all[seq_n[2]][1], b.pts_all[seq_n[2]][0]) # indexes 6 and 7 on this side of the ridge and 8/9 on other side factor_left = away_from_edge / distance_across_left factor_right = away_from_edge / distance_across_right point_6 = coord.calc_point_on_line_local(b.pts_all[seq_n[0]][0], b.pts_all[seq_n[0]][1], b.pts_all[seq_n[3]][0], b.pts_all[seq_n[3]][1], factor_left) point_7 = coord.calc_point_on_line_local(b.pts_all[seq_n[1]][0], b.pts_all[seq_n[1]][1], b.pts_all[seq_n[2]][0], b.pts_all[seq_n[2]][1], factor_right) point_8 = coord.calc_point_on_line_local(b.pts_all[seq_n[1]][0], b.pts_all[seq_n[1]][1], b.pts_all[seq_n[2]][0], b.pts_all[seq_n[2]][1], 1 - factor_right) point_9 = coord.calc_point_on_line_local(b.pts_all[seq_n[0]][0], b.pts_all[seq_n[0]][1], b.pts_all[seq_n[3]][0], b.pts_all[seq_n[3]][1], 1 - factor_left) ratio_upper = 1 - GAMBREL_HEIGHT_RATIO_LOWER_PART ac_object.node(-point_6[1], b.top_of_roof_above_sea_level - ratio_upper * roof_height, -point_6[0]) ac_object.node(-point_7[1], b.top_of_roof_above_sea_level - ratio_upper * roof_height, -point_7[0]) ac_object.node(-point_8[1], b.top_of_roof_above_sea_level - ratio_upper * roof_height, -point_8[0]) ac_object.node(-point_9[1], b.top_of_roof_above_sea_level - ratio_upper * roof_height, -point_9[0]) # roofs lower_hypo = GAMBREL_HEIGHT_RATIO_LOWER_PART * roof_height / sin(radians(GAMBREL_ANGLE_LOWER_PART)) top_hypo_left = ((distance_across_left / 2 - away_from_edge)**2 + ((1 - GAMBREL_HEIGHT_RATIO_LOWER_PART) * roof_height)**2)**0.5 top_hypo_right = ((distance_across_right / 2 - away_from_edge)**2 + ((1 - GAMBREL_HEIGHT_RATIO_LOWER_PART) * roof_height)**2)**0.5 # lower faces front and back repeat_y = lower_hypo/roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(0), t.y(0)), (object_node_index + 1, t.x(repeat_x_front), t.y(0)), (object_node_index + 7, t.x(repeat_x_front), t.y(repeat_y)), (object_node_index + 6, t.x(0), t.y(repeat_y))], mat_idx=roof_mat_idx) ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), (object_node_index + 3, t.x(repeat_x_back), t.y(0)), (object_node_index + 9, t.x(repeat_x_back), t.y(repeat_y)), (object_node_index + 8, t.x(0), t.y(repeat_y))], mat_idx=roof_mat_idx) # upper faces front and back repeat_y = top_hypo_left/roof_texture_size_y ac_object.face([(object_node_index + 6, t.x(0), t.y(0)), (object_node_index + 7, t.x(repeat_x_front), t.y(0)), (object_node_index + 5, t.x(repeat_x_front), t.y(repeat_y)), (object_node_index + 4, t.x(0), t.y(repeat_y))], mat_idx=roof_mat_idx) repeat_y = top_hypo_right/roof_texture_size_y ac_object.face([(object_node_index + 8, t.x(0), t.y(0)), (object_node_index + 9, t.x(repeat_x_back), t.y(0)), (object_node_index + 4, t.x(repeat_x_back), t.y(repeat_y)), (object_node_index + 5, t.x(0), t.y(repeat_y))], mat_idx=roof_mat_idx) # side left repeat_y = roof_height / roof_texture_size_y repeat_x_base = b.edge_length_pts[seq_n[3]] / roof_texture_size_x middle_factor = away_from_edge / b.edge_length_pts[seq_n[3]] ac_object.face([(object_node_index + 3, t.x(0), t.y(0)), (object_node_index + 0, t.x(repeat_x_base), t.y(0)), (object_node_index + 6, t.x((1 - middle_factor) * repeat_x_base), t.y(GAMBREL_HEIGHT_RATIO_LOWER_PART * repeat_y)), (object_node_index + 4, t.x(0.5 * repeat_x_base), t.y(repeat_y)), (object_node_index + 9, t.x(middle_factor * repeat_x_base), t.y(GAMBREL_HEIGHT_RATIO_LOWER_PART * repeat_y))], mat_idx=roof_mat_idx) # side right repeat_x_base = b.edge_length_pts[seq_n[1]] / roof_texture_size_x middle_factor = away_from_edge / b.edge_length_pts[seq_n[1]] ac_object.face([(object_node_index + 1, t.x(0), t.y(0)), (object_node_index + 2, t.x(repeat_x_base), t.y(0)), (object_node_index + 8, t.x((1 - middle_factor) * repeat_x_base), t.y(GAMBREL_HEIGHT_RATIO_LOWER_PART * repeat_y)), (object_node_index + 5, t.x(0.5 * repeat_x_base), t.y(repeat_y)), (object_node_index + 7, t.x(middle_factor * repeat_x_base), t.y(GAMBREL_HEIGHT_RATIO_LOWER_PART * repeat_y))], mat_idx=roof_mat_idx)
def separate_gable_with_corner(ac_object, b, roof_mat_idx: int, facade_mat_idx: int) -> None: """Create a gabled roof around a corner - there can be 4, 5, or 6 nodes. By convention counting of nodes starts at the inner node (0) and is counter clockwise. The nodes on the top are numbered as follows: * First gable counter clockwise: node_10 * Second gable counter clockwise: node_11 * Centre node on top where ridges meet: node_12 See e.g. https://en.wikipedia.org/wiki/Roof#/media/File:Roof_diagram.jpg for the meaning of ridge, hip and eaves. """ t = b.roof_texture roof_height = sanity_roof_height_complex(b, 'gable_with_corner') # find the point closest to the RoofHint.inner_node shortest_dist = 9999999 shortest_index = 0 num_nodes = len(b.pts_all) # pts_all works because there are no inner points in a complex roof index = -1 # enumerate over b.pts_all does not seem to work due to ndarray for pt in b.pts_all: index += 1 dist = coord.calc_distance_local(pt[0], pt[1], b.roof_hint.inner_node[0], b.roof_hint.inner_node[1]) if dist < shortest_dist: shortest_dist = dist shortest_index = index node_0 = b.pts_all[shortest_index] node_1 = b.pts_all[(shortest_index + 1) % num_nodes] node_2 = b.pts_all[(shortest_index + 2) % num_nodes] node_3 = b.pts_all[(shortest_index + 3) % num_nodes] node_4 = None node_5 = None if num_nodes > 4: node_4 = b.pts_all[(shortest_index + 4) % num_nodes] if num_nodes == 6: node_5 = b.pts_all[(shortest_index + 5) % num_nodes] idx_offset_top = 10 - num_nodes # used to correct between node number and real index # point_10: the first gable first_node = node_0 second_node = node_1 if num_nodes == 5: if b.roof_hint.node_before_inner_is_shared: first_node = node_1 second_node = node_2 # else same as for 4 nodes elif num_nodes == 6: first_node = node_1 second_node = node_2 node_10 = coord.calc_point_on_line_local(first_node[0], first_node[1], second_node[0], second_node[1], 0.5) # point_11: the second gable first_node = node_3 second_node = node_0 if num_nodes == 5: if b.roof_hint.node_before_inner_is_shared: first_node = node_4 second_node = node_0 else: first_node = node_3 second_node = node_4 elif num_nodes == 6: first_node = node_4 second_node = node_5 node_11 = coord.calc_point_on_line_local(first_node[0], first_node[1], second_node[0], second_node[1], 0.5) # point_12: the centre point first_node = node_0 second_node = node_2 if num_nodes == 5: if b.roof_hint.node_before_inner_is_shared: second_node = node_3 # else same as for 4 nodes elif num_nodes == 6: second_node = node_3 node_12 = coord.calc_point_on_line_local(first_node[0], first_node[1], second_node[0], second_node[1], 0.5) # add nodes to ac-object object_node_index = ac_object.next_node_index() # must be before nodes are added! ac_object.node(-node_0[1], b.beginning_of_roof_above_sea_level, -node_0[0]) ac_object.node(-node_1[1], b.beginning_of_roof_above_sea_level, -node_1[0]) ac_object.node(-node_2[1], b.beginning_of_roof_above_sea_level, -node_2[0]) ac_object.node(-node_3[1], b.beginning_of_roof_above_sea_level, -node_3[0]) if num_nodes > 4: ac_object.node(-node_4[1], b.beginning_of_roof_above_sea_level, -node_4[0]) if num_nodes == 6: ac_object.node(-node_5[1], b.beginning_of_roof_above_sea_level, -node_5[0]) ac_object.node(-node_10[1], b.beginning_of_roof_above_sea_level + roof_height, -node_10[0]) ac_object.node(-node_11[1], b.beginning_of_roof_above_sea_level + roof_height, -node_11[0]) ac_object.node(-node_12[1], b.beginning_of_roof_above_sea_level + roof_height, -node_12[0]) # now the faces roof_texture_size_x = t.h_size_meters # size of roof texture in meters roof_texture_size_y = t.v_size_meters if num_nodes == 4: # first inside roof side ridge_len = coord.calc_distance_local(node_12[0], node_12[1], node_10[0], node_10[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_0[0], node_0[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(ridge_x), t.y(0)), # node_0 (object_node_index + 10 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_10 (object_node_index + 12 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # first outside/back roof side eaves_len = coord.calc_distance_local(node_1[0], node_1[1], node_2[0], node_2[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_10[0], node_10[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_1[0], node_1[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 1, t.x(0), t.y(0)), # node_1 (object_node_index + 2, t.x(eaves_x), t.y(0)), # node_2 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 10 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_10 mat_idx=roof_mat_idx) # second outside/back roof side eaves_len = coord.calc_distance_local(node_2[0], node_2[1], node_3[0], node_3[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_3[0], node_3[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), # node_2 (object_node_index + 3, t.x(eaves_x), t.y(0)), # node_3 (object_node_index + 11 - idx_offset_top, t.x(eaves_x), t.y(repeat_y)), # node_11 (object_node_index + 12 - idx_offset_top, t.x(eaves_x - ridge_x), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # second inside roof side ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_0[0], node_0[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(0), t.y(0)), # node_0 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 11 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_11 mat_idx=roof_mat_idx) # the sides where it is gabled and facade texture _add_sides_gabled_facade_tex(ac_object, t, object_node_index, idx_offset_top, facade_mat_idx, roof_height, roof_texture_size_x, roof_texture_size_y, node_0, 0, node_1, 1, node_3, 3, node_0, 0) elif num_nodes == 5: if b.roof_hint.node_before_inner_is_shared: # first inside roof side eaves_len = coord.calc_distance_local(node_0[0], node_0[1], node_1[0], node_1[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_10[0], node_10[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_1[0], node_1[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(ridge_x - eaves_x), t.y(0)), # node_0 (object_node_index + 1, t.x(ridge_x), t.y(0)), # node_1 (object_node_index + 10 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_10 (object_node_index + 12 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # first outside/back roof side eaves_len = coord.calc_distance_local(node_2[0], node_2[1], node_3[0], node_3[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_12[0], node_12[1], node_10[0], node_10[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_2[0], node_2[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), # node_2 (object_node_index + 3, t.x(eaves_x), t.y(0)), # node_3 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 10 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_10 mat_idx=roof_mat_idx) # second outside/back roof side eaves_len = coord.calc_distance_local(node_3[0], node_3[1], node_4[0], node_4[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_4[0], node_4[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 3, t.x(0), t.y(0)), # node_3 (object_node_index + 4, t.x(eaves_x), t.y(0)), # node_4 (object_node_index + 11 - idx_offset_top, t.x(eaves_x), t.y(repeat_y)), # node_11 (object_node_index + 12 - idx_offset_top, t.x(eaves_x - ridge_x), t.y(repeat_y))], mat_idx=roof_mat_idx) # second inside roof side ridge_len = coord.calc_distance_local(node_12[0], node_12[1], node_11[0], node_11[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_0[0], node_0[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(ridge_x), t.y(0)), # node_0 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 11 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_11 mat_idx=roof_mat_idx) # the sides where it is gabled and facade texture _add_sides_gabled_facade_tex(ac_object, t, object_node_index, idx_offset_top, facade_mat_idx, roof_height, roof_texture_size_x, roof_texture_size_y, node_1, 1, node_2, 2, node_4, 4, node_0, 0) else: # first inside roof side ridge_len = coord.calc_distance_local(node_12[0], node_12[1], node_10[0], node_10[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_0[0], node_0[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(ridge_x), t.y(0)), # node_0 (object_node_index + 10 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_10 (object_node_index + 12 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # first outside/back roof side eaves_len = coord.calc_distance_local(node_1[0], node_1[1], node_2[0], node_2[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_10[0], node_10[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_1[0], node_1[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 1, t.x(0), t.y(0)), # node_1 (object_node_index + 2, t.x(eaves_x), t.y(0)), # node_2 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 10 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_10 mat_idx=roof_mat_idx) # second outside/back roof side eaves_len = coord.calc_distance_local(node_2[0], node_2[1], node_3[0], node_3[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_3[0], node_3[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), # node_2 (object_node_index + 3, t.x(eaves_x), t.y(0)), # node_3 (object_node_index + 11 - idx_offset_top, t.x(eaves_x), t.y(repeat_y)), # node_11 (object_node_index + 12 - idx_offset_top, t.x(eaves_x - ridge_x), t.y(repeat_y))], mat_idx=roof_mat_idx) # second inside roof side eaves_len = coord.calc_distance_local(node_4[0], node_4[1], node_0[0], node_0[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_4[0], node_4[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 4, t.x(0), t.y(0)), # node_4 (object_node_index + 0, t.x(eaves_x), t.y(0)), # node_0 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 11 - idx_offset_top, t.x(0), t.y(repeat_y))], mat_idx=roof_mat_idx) # the sides where it is gabled and facade texture _add_sides_gabled_facade_tex(ac_object, t, object_node_index, idx_offset_top, facade_mat_idx, roof_height, roof_texture_size_x, roof_texture_size_y, node_0, 0, node_1, 1, node_3, 3, node_4, 4) elif num_nodes == 6: # first inside roof side eaves_len = coord.calc_distance_local(node_0[0], node_0[1], node_1[0], node_1[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_10[0], node_10[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_1[0], node_1[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 0, t.x(ridge_x - eaves_x), t.y(0)), # node_0 (object_node_index + 1, t.x(ridge_x), t.y(0)), # node_1 (object_node_index + 10 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_10 (object_node_index + 12 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # first outside/back roof side eaves_len = coord.calc_distance_local(node_2[0], node_2[1], node_3[0], node_3[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_12[0], node_12[1], node_10[0], node_10[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_2[0], node_2[1], node_10[0], node_10[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 2, t.x(0), t.y(0)), # node_2 (object_node_index + 3, t.x(eaves_x), t.y(0)), # node_3 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 10 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_10 mat_idx=roof_mat_idx) # second outside/back roof side eaves_len = coord.calc_distance_local(node_3[0], node_3[1], node_4[0], node_4[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_4[0], node_4[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 3, t.x(0), t.y(0)), # node_3 (object_node_index + 4, t.x(eaves_x), t.y(0)), # node_4 (object_node_index + 11 - idx_offset_top, t.x(eaves_x), t.y(repeat_y)), # node_11 (object_node_index + 12 - idx_offset_top, t.x(eaves_x - ridge_x), t.y(repeat_y))], # node_12 mat_idx=roof_mat_idx) # second inside roof side eaves_len = coord.calc_distance_local(node_5[0], node_5[1], node_0[0], node_0[1]) eaves_x = eaves_len / roof_texture_size_x ridge_len = coord.calc_distance_local(node_11[0], node_11[1], node_12[0], node_12[1]) ridge_x = ridge_len / roof_texture_size_x hip_len = (coord.calc_distance_local(node_5[0], node_5[1], node_11[0], node_11[1]) ** 2 + roof_height ** 2) ** 0.5 repeat_y = hip_len / roof_texture_size_y ac_object.face([(object_node_index + 5, t.x(0), t.y(0)), # node_5 (object_node_index + 0, t.x(eaves_x), t.y(0)), # node_0 (object_node_index + 12 - idx_offset_top, t.x(ridge_x), t.y(repeat_y)), # node_12 (object_node_index + 11 - idx_offset_top, t.x(0), t.y(repeat_y))], # node_11 mat_idx=roof_mat_idx) # the sides where it is gabled and facade texture _add_sides_gabled_facade_tex(ac_object, t, object_node_index, idx_offset_top, facade_mat_idx, roof_height, roof_texture_size_x, roof_texture_size_y, node_1, 1, node_2, 2, node_4, 4, node_5, 5)