def is_edition_needed(lst_coord_0, lst_coord_1, lst_coord_2): p0 = lst_coord_0[0] l1 = lst_coord_0[1] l2 = lst_coord_1[1] l3 = lst_coord_2[1] angle_1 = GenUtil.compute_angle(l1, p0, l2, type=GenUtil.DEGREE) angle_2 = GenUtil.compute_angle(l1, p0, l3, type=GenUtil.DEGREE) angle_3 = GenUtil.compute_angle(l2, p0, l3, type=GenUtil.DEGREE) if angle_1 >= 165. or angle_2 >= 165. or angle_3 >= 165.: edition_needed = False else: edition_needed = True return edition_needed
def _extract_linked_lines(self, coord): linked_lines = [] b_box = GenUtil.build_bounding_box(self. search_tolerance, coord) potential_lines = self.s_container.get_features(b_box, remove_features=[self.line]) for potential_line in potential_lines: if potential_line.distance(Point(coord)) <= GenUtil.ZERO: linked_lines.append(potential_line) return linked_lines
def calculate_mid_point(lst_coord_0, lst_coord_1, lst_coord_2): lst_coord = [[[None], [None], [None]], [[None], [None], [None]], [[None], [None], [None]]] for i, coords in enumerate([lst_coord_0, lst_coord_1, lst_coord_2]): if len(coords) <= 2: lst_coord[i][0] = coords[0] mid_point = LineString((coords[0], coords[1])).interpolate(.5, normalized=True) lst_coord[i][1] = (mid_point.x, mid_point.y) lst_coord[i][2] = coords[1] else: for j in range(3): lst_coord[i][j] = coords[j] try_0 = (lst_coord[0], lst_coord[1]) try_1 = (lst_coord[1], lst_coord[2]) try_2 = (lst_coord[0], lst_coord[2]) max_sum_angles = -1. max_mid_p01_p11 = None for (lst_coord_a, lst_coord_b) in (try_0, try_1, try_2 ): p0 = lst_coord_a[0] p01 = lst_coord_a[1] p02 = lst_coord_a[2] p11 = lst_coord_b[1] p12 = lst_coord_b[2] tmp_mid_p01_p11 = LineString((p01, p11)).interpolate(.5, normalized=True) mid_p01_p11 = (tmp_mid_p01_p11.x, tmp_mid_p01_p11.y) line_mid_p0 = LineString((mid_p01_p11, p0)) length_y_junction = line_mid_p0.length angle_mid_p01_p02 = GenUtil.compute_angle(mid_p01_p11, p01, p02, type=GenUtil.DEGREE) angle_mid_p11_p12 = GenUtil.compute_angle(mid_p01_p11, p11, p12, type=GenUtil.DEGREE) if length_y_junction <= command.yjunction: sum_angles = angle_mid_p01_p02 + angle_mid_p11_p12 if sum_angles > max_sum_angles: max_sum_angles = sum_angles max_mid_p01_p11 = mid_p01_p11 return max_mid_p01_p11
def _calculate_adj_area(self, coords): """Calculates the adjusted area of a polygon Parameters ---------- coords : list List of x,y coordinates defining a polygon Returns ------- float Minimum adjusted area """ pol = Polygon(coords) cmp_index = GenUtil.calculate_compactness_index(pol.area, pol.length) adj_area = GenUtil.calculate_adjusted_area(pol.area, cmp_index) return adj_area
def vertex_orientation(self): """This method calculates the orientation of the vertex List containing the orientation at each vertex of the line. -1: anti clockwise, +1 Clockwise; 0 Straight line For closed line the first and last vertice bear the same value For open line the first and last value are None Parameters ---------- None Returns ------- None """ try: return self._vertex_orientation except AttributeError: self._vertex_orientation = [] for i in range( 1, len(self.coords) - 1): # '1' and 'cnt-1' to 'forget' first and last vertice orient = GenUtil.orientation(self.coords[i - 1], self.coords[i], self.coords[i + 1]) self._vertex_orientation.append(orient) if self.is_closed: # Case of a closed line or polygon; we do not copy the first and lat even if they are the same orient = GenUtil.orientation(self.coords[-2], self.coords[0], self.coords[1]) self._vertex_orientation = [orient] + self._vertex_orientation else: # Case of an open line; the first and last are None orient = None self._vertex_orientation = [ orient ] + self._vertex_orientation + [orient] return self._vertex_orientation
def cmp_index(self): """Calculates the value of the compactness index Parameters ---------- None Returns ------- float Value of the compactness index """ try: return self._cmp_index except AttributeError: self._cmp_index = GenUtil.calculate_compactness_index( self.area, self.perimeter) return self._cmp_index
def join_lines(s_container, command, geo_content, tolerance): # Loop over each line in the list for line in s_container.get_features(): # Loop over the first and last vertice of the line for ind in [FIRST, LAST]: line_topology = Topology(s_container, line) if ind == LAST: line_topology.reverse() lst_coord_line = list(line.coords) if len(line_topology.start_linked_lines) == 0: b_box = GenUtil.build_bounding_box(tolerance, lst_coord_line[0]) potential_lines = s_container.get_features(b_box, remove_features=[line]) target_line = None for potential_line in potential_lines: for i in [FIRST, LAST]: lst_coord_potential = list(potential_line.coords) if Point(lst_coord_line[0]).distance(Point(lst_coord_potential[i])) <= tolerance: target_line = potential_line target_coord = lst_coord_potential[i] if target_line: # We have a line to join with new_line = LineString((lst_coord_line[0], target_coord)) merged_line = linemerge([line, new_line, target_line]) if merged_line.geom_type == GenUtil.LINE_STRING: lst_merged_line_coord = list(merged_line.coords) line.coords = lst_merged_line_coord try: s_container.del_feature(target_line) except Exception: pass geo_content.nbr_join += 1 else: # Possible problem with the merged line go to next line pass else: # No line to merged with pass else: # Line is not open. Go to next line pass return
def adj_area(self): """Calculates the value of the compactness index of the polygon Parameters ---------- None Returns ------- float Value of the compactness index """ try: return self._adj_area except AttributeError: self._adj_area = GenUtil.calculate_adjusted_area( self.area, self.cmp_index) return self._adj_area
def base(self): """Length of the base of the bend. Distance between the first and last coordinate Parameters ---------- None Returns ------- Float Length of the bend of the polygon """ try: return self._base except AttributeError: self._base = GenUtil.distance(self.bend_coords[0], self.bend_coords[-1]) if self._base <= GenUtil.ZERO: self._base = GenUtil.ZERO # Avois a case of division by zero return self._base
def sb_is_closed(self): """This method tests if a line is closed (first/last coordinates are the same) Parameters ---------- None Returns ------- bool True: the line is closed or False the line is open """ try: return self._sb_is_closed except AttributeError: # A closed line need at least 4 vertex to be valid if len(self.coords) >= 4 and GenUtil.distance( self.coords[0], self.coords[-1]) <= GenUtil.ZERO: self._sb_is_closed = True else: self._sb_is_closed = False return self._sb_is_closed
def extend_line(s_container, command, geo_content, tolerance): # Loop over each line in the list for line in s_container.get_features(): # Loop over the first and last vertice of the line for ind in [FIRST, LAST]: line_topology = Topology(s_container, line) if ind == LAST: line_topology.reverse() lst_coord_line = list(line.coords) if len(line_topology.start_linked_lines) == 0: b_box = GenUtil.build_bounding_box(tolerance, lst_coord_line[0]) potential_lines = s_container.get_features(b_box, remove_features=[line]) new_coord = None distance_min = tolerance + 1. for potential_line in potential_lines: linear_ref = potential_line.project(Point(lst_coord_line[0])) point_on_line = potential_line.interpolate(linear_ref) distance = Point(lst_coord_line[0]).distance(point_on_line) if distance <= tolerance: if distance_min > distance: distance_min = distance new_coord = (point_on_line.x, point_on_line.y) if new_coord: # We have a line to join with lst_new_coord_line = [new_coord] + lst_coord_line line.coords = lst_new_coord_line geo_content.nbr_extend += 1 else: # No line to merged with pass else: # Line is not open. Go to next line pass return
in_nbr_points=0, in_nbr_line_strings=0, in_nbr_polygons=0, in_nbr_holes=0, out_nbr_points=0, out_nbr_line_strings=0, out_nbr_polygons=0, out_nbr_holes=0, nbr_del_polygons=0, nbr_del_holes=0) # Read the command line arguments command = manage_arguments() if command.dlayer: # Extract the list of layers to read in_layer_names = [layer_name for layer_name in command.dlayer_dict.keys()] else: # Read all the layers in the input file in_layer_names = None # Read and load the layers of the input file GenUtil.read_in_file(command.in_file, geo_content, in_layer_names) # Set the diameter for each layer tmp_dlayer_dict = {} for layer_name in geo_content.layer_names: if command.diameter is not None: # The same diameter value is applied to all the layers tmp_dlayer_dict[layer_name] = command.diameter else: # There is a specific diameter for each layer tmp_dlayer_dict[layer_name] = command.dlayer_dict[layer_name] # Reset the value of dlayer command.dlayer_dict = tmp_dlayer_dict # Only keep in the in features the ones where the diameter is not -1
in_nbr_line_strings: 0 out_nbr_line_strings: 0 bounds: List[object] = None geo_content = GeoContent(crs=None, driver=None, schemas={}, in_features=[], out_features=[], nbr_xjunction=0, nbr_yjunction=0, nbr_join=0, nbr_noise=0, nbr_extend=0, in_nbr_line_strings=0, out_nbr_line_strings=0, bounds=[]) # Read the command line arguments command = read_arguments() GenUtil.read_in_file (command.in_file, geo_content, [command.input_layer]) # test for Ycrossing a = LineStringSc(((5,5),(5,10))) b = LineStringSc(((0,4),(3,4),(5,5))) c = LineStringSc(((5,5),(7,4),(10,4))) d = LineStringSc(((5,10),(7,11), (10,11))) e = LineStringSc(((0,11),(3,11),(5,10))) lst_y_junction = [a,b,c,d,e] # Test for X crossing f = LineStringSc(((10,10), (10,15),(10,20))) g = LineStringSc(((6,21),(8,21),(10,20))) h = LineStringSc(((10,20),(12,21),(14,21))) i = LineStringSc(((10,10), (8,9), (6,9)))
def create_replacement_line(lst_coords, bend, diameter): """Calculate the replacement line for a bend""" # Extract the sub line containing the bend with one extra vertice on each side sub_line = LineStringSb(lst_coords[bend.i - 1:bend.j + 1]) bend_i = 1 bend_j = len(bend.j) - 1 # Translate to sub line so that the bend starts at 0,0 xoff, yoff = lst_coords[bend.i][0], lst_coords[bend.i][1] line_translate = affinity.affine_transform(sub_line, [1, 0, 0, 1, -xoff, -yoff]) # Extract the angle between the base of the bend (bendi, bendj) and the x axis lst_coord = list(line_translate.coords) p0 = (lst_coord[bend_j][0], lst_coord[bend_j][1]) p1 = (lst_coord[bend_i][0], lst_coord[bend_i][1]) p2 = (abs(p0[0]) + 1., 0) angle = GenUtil.angle_vecor(p0, p1, p2) # p0_x = line1_coord[bend_j][0] # p0_y = line1_coord[bend_j][1] # p1_x = abs(p0_x) + 1. # In case x == 0 # p1_y = 0. # dot = p0_x * p1_x + p0_y * p1_y # len_a = (p0_x ** 2 + p0_y ** 2) ** .5 # len_b = (p1_x ** 2 + p1_y ** 2) ** .5 angle = math.acos(dot / (len_a * len_b)) angle = (angle * 180 / math.pi) if p0[1] >= 0.: angle = -angle # Clockwise rotation # if p0_y >= 0.: # angle = -angle # Rotate the bend so it's on the x axis a = math.cos(angle) b = -math.sin(angle) d = math.sin(angle) e = math.cos(angle) line_rotate = affinity.rotate(line_translate, angle, origin=(0, 0)) lst_coords = list(line_rotate.coords) # line_i = LineString(lst_coords[0:3]) # line_j = LineString(lst_coords[-2:]) # Calculate the angle between the base of the bend of segment before and after the bend theta_i = lib_geobato.GenUtil.compute_angle(lst_coords[0], lst_coords[1], lst_coords[bend_j]) theta_j = lib_geobato.GenUtil.compute_angle(lst_coords[bend_j], lst_coords[-2], lst_coords[-1]) # Determine if the bend_line = LineString(lst_coord[bend_i:bend_j + 1]) (minx, miny, maxx, maxy) = bend_line.bounds y_dynamic = (abs(miny) + abs(maxy)) * 10. x_middle = (lst_coords[bend_i][0] + lst_coords[bend_j][0]) / 2. line_y_positive = LineString(((x_middle, 0), (x_middle, y_dynamic))) line_y_negative = LineString(((x_middle, 0), (x_middle, -y_dynamic))) if line4.crosses(line_y_positive): bend_side = +1 else: if line4.crosses(line_y_negative): bend_side = -1 if lst_coords[0][1] >= 0.: start_line_side = 1 else: start_line_side = -1 if lst_coords[-1][1] >= 0.: end_line_side = 1 else: end_line_side = -1 if (start_line_side * end_line_side == -1): print("Nothing to do....") line5 = LineString(lst_coords[0:bend_i + 1] + lst_coords[bend_j:]) else: # Both line are on the same side if start_line_side == 1 and end_line_side == 1: if bend_side == -1: angle_bias = 2. y_offset = -1 else: angle_bias = 3. y_offset = 1 if start_line_side == -1 and end_line_side == -1: if bend_side == 1: angle_bias = 2. y_offset = 1 else: angle_bias = 3. y_offset = 1 theta_i = (180. - theta_i) / angle_bias if theta_i >= 5.: hypothenus = x_middle / math.cos(theta_i * math.pi / 180.) y_height = math.sqrt(hypothenus**2 - x_middle**2) if bend_side == -1: y_height *= y_offset new_coord = (x_middle, y_height) line5 = LineString(lst_coords[0:bend_i + 1] + [new_coord] + lst_coords[bend_j:]) else: print("Nothing to do....") line5 = LineString(lst_coords[0:bend_i + 1] + lst_coords[bend_j:])