def filter_long_distance_lines_raw(lines, sheet_dict): # 去掉roi里面的线 lines_tmp1 = [] for index, region_box in enumerate(sheet_dict): coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] ymin = coordinates['ymin'] xmax = coordinates['xmax'] ymax = coordinates['ymax'] box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) for line in lines: line_tmp = LineString([(line[0], line[1]), (line[2], line[3])]) # line_tmp = LineString([(750, 502), (1035, 502)]) decision = [ line_tmp.within(box_polygon), line_tmp.contains(box_polygon), line_tmp.overlaps(box_polygon) ] # attention:[179, 440, 1092, 729] # 横线 750, 502, 1035, 509 if True in decision: lines_tmp1.append(line) lines_tmp = [line for line in lines if line not in lines_tmp1] return lines_tmp
def filter_line_in_mark(lines, sheet_dict): # 去掉roi里面的线 lines_tmp1 = [] for index, region_box in enumerate(sheet_dict): class_name = region_box['class_name'] if region_box['class_name'] == 'mark': coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] ymin = coordinates['ymin'] xmax = coordinates['xmax'] ymax = coordinates['ymax'] box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) for line in lines: line_tmp = LineString([(line[0], line[1]), (line[2], line[3])]) # line_tmp = LineString([(750, 502), (1035, 502)]) decision = [ line_tmp.within(box_polygon), line_tmp.contains(box_polygon), line_tmp.overlaps(box_polygon) ] # attention:[179, 440, 1092, 729] # 横线 750, 502, 1035, 509 if True in decision: lines_tmp1.append(line) lines_tmp = [line for line in lines if line not in lines_tmp1] for line in lines_tmp: cv2.line(image, (int(line[0]), int(line[1])), (int(line[2]), int(line[3])), (0, 255, 0), 1, cv2.LINE_AA) # cv2.imwrite(r'E:\December\math_12_18\1_18\test_img\save3\mark.jpg', image) return lines_tmp
def planets_are_aligned(self, day): """ We need to check if all planets in this galaxy are in a straight line We will calculate a line from the first two planets and see if all others are inside of it. """ line = LineString([ self.planets[0].calculate_planet_position(day), self.planets[1].calculate_planet_position(day) ]) for p in self.planets[2::]: if not line.contains(Point(p.calculate_planet_position(day))): return PlanetsPosition.NOT_ALIGNED if line.contains(Point(0, 0)): return PlanetsPosition.ALIGNED_WITH_THE_SUN return PlanetsPosition.ALIGNED_WITH_EACHOTHER
def test_concave_polygon(self): """ Finds pole of inaccessibility for a concave polygon and ensures that the point is inside. """ concave_polygon = LineString([(500, 0), (0, 0), (0, 500), (500, 500)]).buffer(100) label = polylabel(concave_polygon) self.assertTrue(concave_polygon.contains(label))
def is_oob(road_nodes, simulation_states): # Create the road geometry from the nodes. At this point nodes have been reversed already if needed. road_geometry = get_geometry(road_nodes) # Compute right polygon # Create the right lane polygon from the geometry left_edge_x = np.array([e['middle'][0] for e in road_geometry]) left_edge_y = np.array([e['middle'][1] for e in road_geometry]) right_edge_x = np.array([e['right'][0] for e in road_geometry]) right_edge_y = np.array([e['right'][1] for e in road_geometry]) # Compute the "short" edge at the end of the road to rule out false positives shorty = LineString([(left_edge_x[-1], left_edge_y[-1]), (right_edge_x[-1], right_edge_y[-1])]).buffer(2.0) # Note that one must be in reverse order for the polygon to close correctly right_edge = LineString(zip(right_edge_x[::-1], right_edge_y[::-1])) left_edge = LineString(zip(left_edge_x, left_edge_y)) l_edge = left_edge.coords r_edge = right_edge.coords right_lane_polygon = Polygon(list(l_edge) + list(r_edge)) #middle = [e['middle'] for e in road_geometry] #right = [e['right'] for e in road_geometry] #road_poly = [(p[0], p[1]) for p in middle] #right = [(p[0], p[1]) for p in right] #road_poly.extend(right[::-1]) #right_polygon = Polygon(road_poly) first_oob_state = None position_of_first_oob_state = None for idx, simulation_state in enumerate(simulation_states): position = Point(simulation_state["pos"][0], simulation_state["pos"][1]) if not right_lane_polygon.contains(position): # As soon as an observation is outside the lane polygon we mark the OOB, and return that position. All the # subsequent states will be removed/discarded log.debug("First OOB state found at %d", idx) first_oob_state = idx position_of_first_oob_state = position break if first_oob_state is not None: if shorty.contains(position_of_first_oob_state): log.info("* False Positive. Short Edge") return False, None else: return True, first_oob_state else: return False, None
def find_points_in_region(positions: np.ndarray, region: LineString): """Find the points in a region. Parameters ---------- positions: np.ndarray The positions of a trajectory. region: LineString The line region. """ if region.is_empty: return [] out = [] for i, pt in enumerate(positions): if region.contains(Point(pt)): out.append(i) return out
def main(): map = read_map("day10.txt") items = [] points = [] for line_id, line in enumerate(map): for item_id, item in enumerate(line): if item is "#": items.append((item_id, line_id)) points.append(Point(item_id, line_id)) best_el = None best_val = 0 print("Number of asteroids: {}".format(len(items))) the_lazor_pos = (22, 19) t0 = time.time() for location in items: # check how many asteroids are visible cur_val = 0 for asteroid in items: if asteroid is not location: line = LineString([location, asteroid]) has_blocker = False for obs_id, obstacle in enumerate(items): if (obstacle is not location) and (obstacle is not asteroid): if line.contains(points[obs_id]): has_blocker = True break if has_blocker is False: cur_val += 1 if cur_val > best_val: best_val = cur_val best_el = location t1 = time.time() print("Time: {}", t1 - t0) print("Element {} sees {}".format(best_el, best_val))
def check_in_park(self, lat, lon): try: cell = Polygon(self.get_s2_cell_as_polygon(lat, lon, 20)) # s2 lvl 20 if len(self.PARKS_CACHE) > 0: for p in self.PARKS_CACHE: coords = p['coords'] # osm polygon can be a line if len(coords) == 2: shape = LineString(coords) if shape.within(cell.centroid): return { 'id' : p['id'], 'internal' : p['internal'], 'name' : p['name'] } if len(coords) > 2: shape = Polygon(coords) if shape.contains(cell.centroid): return {'id': p['id'], 'internal' : p['internal'], 'name': p['name']} return None except Exception as e: self.log.error('Unknown error: in check_in_park: {}',e) return None
def get_steps(point, route): """ Calculate distance between start and intersection point :param point: :param route: :return: """ result = 0 route_len = len(route) for index in range(1, route_len): line = LineString([route[index - 1], route[index]]) part_of = line.contains(point) if part_of: line = LineString([route[index - 1], (point.x, point.y)]) result = result + line.length break else: result = result + line.length return result
def gym_data(): gyms = [] parks = get_all_parks() for g in get_gym_markers(): gym_point = Point(g['lat'], g['lon']) cell = Polygon(get_s2_cell_as_polygon(g['lat'], g['lon'], 20)) # s2 lvl 20 for p in parks: coords = p['coords'] # osm polygon can be a line if len(coords) == 2: shape = LineString(coords) if shape.within(cell.centroid): gyms.append(g) break if len(coords) > 2: shape = Polygon(coords) if shape.contains(cell.centroid): gyms.append(g) break return jsonify(gyms)
def get_heading_angle(self): """ Return the heading angle of the car before it went OBE """ # https://stackoverflow.com/questions/56710732/how-to-efficiently-calculate-full-2pi-angles-between-three-vectors-of-2d-point # https://stackoverflow.com/questions/14066933/direct-way-of-computing-clockwise-angle-between-2-vectors # https://newtonexcelbach.com/2014/03/01/the-angle-between-two-vectors-python-version/ # dot = x1*x2 + y1*y2 # dot product between [x1, y1] and [x2, y2] # det = x1*y2 - y1*x2 # determinant # angle = atan2(det, dot) # atan2(y, x) or atan2(sin, cos) # Obtain the right vectors from the various points A = np.array( [[self.state_before_obe.pos_x, self.state_before_obe.pos_y]]) B = np.array([[self.obe_states[0].pos_x, self.obe_states[0].pos_y]]) AB = B - A AB = AB proj = self.state_before_obe.get_path_projection() # This might be useful to add to asfault directly # Process the path two points at the time. The path define the road direction # https://gis.stackexchange.com/questions/84512/get-the-vertices-on-a-linestring-either-side-of-a-point # plt.show() # x, y = self.state_before_obe.test.get_path_polyline().coords.xy # plt.plot(x, y, color="yellow") # plt.plot(proj.x, proj.y, marker="o", color="blue") road_direction = None for pair in self._pairs( list(self.state_before_obe.test.get_path_polyline().coords)): # Check whether this pair contains the projection which by definition lies on the path # print("Checking if ", pair[0], pair[1], "contains", proj) # x, y = LineString([pair[0], pair[1]]).coords.xy # plt.plot(x, y, color="red") # plt.plot(proj.x, proj.y, marker="o") # This does not work despite segment = LineString([pair[0], pair[1]]) if segment.contains(proj) or segment.buffer(EPS).contains(proj): road_direction = np.array([pair[0]]) - np.array([pair[1]]) break P = np.array([[proj.x, proj.y]]) # TODO How to decide this w.r.t. direction of the road? # Direction of the road might be given by the PATH of the test N = np.array([[-(P[0][1] - A[0][1]), (P[0][0] - A[0][0])]]) N1 = np.array([[(P[0][1] - A[0][1]), -(P[0][0] - A[0][0])]]) if road_direction is not None: if self.dot(road_direction, N) > 0: N = N1 else: l.warning("CANNOT FIND THE ROAD DIRECTION FOR %s", str(self.state_before_obe)) # Vector defined by the last point before OBE and the first point of OBE # angle, is_cc = self.angle(N, AB) # print(angle, is_cc) angle = self.angle(AB, N) return angle[0]
def fld_demo4(image, sheet_dict, split_x, name, save_path): image_ = image.copy() img = Image.fromarray(image) t = time.time() img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # ret, binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) fld = cv2.ximgproc.createFastLineDetector() dlines = fld.detect(img_gray) lines = [line[0] for line in dlines.tolist()] lines_arr = np.array(lines) width_ = lines_arr[:, 2] - lines_arr[:, 0] height_ = lines_arr[:, 3] - lines_arr[:, 1] lines_index1 = np.where(width_ > 50)[0] lines_index2 = np.where(height_ > 50)[0] lines_index = np.hstack([lines_index1, lines_index2]) new_lines = [lines[ele] for ele in lines_index] new_lines = clean_repeat_lines(new_lines) lines_tmp = filter_long_distance_lines(new_lines, sheet_dict) # lines_without_mark = filter_line_in_mark(new_lines, sheet_dict) # 检验滤线这一步骤有没有问题 for dline in lines_tmp: x0 = int(round(dline[0])) y0 = int(round(dline[1])) x1 = int(round(dline[2])) y1 = int(round(dline[3])) cv2.line(image, (x0, y0), (x1, y1), (0, 255, 0), 1, cv2.LINE_AA) text = str([x0, y0, x1, y1]) # cv2.putText(image, text, (x1, y1), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1) # write_single_img(image, os.path.join(save_path, name + '_raw_lines' + '.jpg')) # get roi polygon 适当放大一点区域,使的线能包含在面里 roi_box_polygon = [] for index, region_box in enumerate(sheet_dict): if region_box['class_name'] in class_above_edge: coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] - 5 ymin = coordinates['ymin'] - 5 xmax = coordinates['xmax'] + 5 ymax = coordinates['ymax'] + 5 box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) roi_box_polygon.append(box_polygon) # cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (0, 0, 255), 1) # cv2.imwrite(r'E:\111_4_26_test_img\aa\save\enlarge_box.jpg', image) # print(roi_box_polygon) # 对line进行分横向纵向 landscape_list_tmp = [] # 横向 longitudinal_list_tmp = [] # 纵向 for ele in lines_tmp: if int(ele[2]) - int(ele[0]) < 10: # 纵向 longitudinal_list_tmp.append(ele) elif int(ele[3]) - int(ele[1]) < 10: # 横向 landscape_list_tmp.append(ele) # print(longitudinal_list_tmp) points_all_list = [] points_list = [] for index, box_polygon in enumerate(roi_box_polygon): extend_line_lan = LineString() extend_line_lon = LineString() # points_list = [] for line1 in landscape_list_tmp: for line2 in longitudinal_list_tmp: # 这部分对原先出来的线进行增大 raw_line_lan = LineString([(line1[0], line1[1]), (line1[2], line1[3])]) # 横向增加5个像素 line_start_lan, line_end_lan = raw_line_lan.bounds[ 0], raw_line_lan.bounds[1] raw_line_lon = LineString([(line2[0], line2[1]), (line2[2], line2[3])]) # 纵向的增加5个像素 line_start_lon, line_end_lon = raw_line_lon.bounds[ 0], raw_line_lon.bounds[1] # decision1 = [raw_line_lan.within(box_polygon), raw_line_lan.contains(box_polygon), raw_line_lan.overlaps(box_polygon)] # decision2 = [raw_line_lon.within(box_polygon), raw_line_lon.contains(box_polygon), raw_line_lon.overlaps(box_polygon)] decision1 = [ raw_line_lan.within(box_polygon), raw_line_lan.contains(box_polygon) ] decision2 = [ raw_line_lon.within(box_polygon), raw_line_lon.contains(box_polygon) ] if True in decision1 and True in decision2: # 这里需要考虑延长左边还是右边 bbox_xmin, bbox_ymin, bbox_xmax, bbox_ymax = box_polygon.bounds[0], box_polygon.bounds[1], \ box_polygon.bounds[2], box_polygon.bounds[3] # if abs(line_start_lan - bbox_xmin) < abs(bbox_xmax - line_end_lan): extend_line_lan = LineString([ (box_polygon.bounds[0], line1[1]), (box_polygon.bounds[2], line1[3]) ]) # elif abs(line_start_lon - bbox_ymin) < abs(bbox_ymax - line_end_lon): extend_line_lon = LineString([ (line2[0], box_polygon.bounds[1]), (line2[2], box_polygon.bounds[3]) ]) cond1 = raw_line_lan.intersects(raw_line_lon) cond2 = raw_line_lan.crosses(raw_line_lon) cond3 = extend_line_lan.intersects(extend_line_lon) # 十字交叉 cond4 = extend_line_lan.crosses(extend_line_lon) # 十字交叉 xp, yp = 0.0, 0.0 if cond1: (xp, yp ) = raw_line_lan.intersection(raw_line_lon).bounds[:2] elif cond3: (xp, yp) = extend_line_lan.intersection( extend_line_lon).bounds[:2] points_list.append([(xp, yp), (raw_line_lan, raw_line_lon), (extend_line_lan, extend_line_lon), box_polygon]) # TODO 验证找所有点的正确性 # template = r'F:\exam\sheet_resolve\exam_info\000000-template.xml' # tree = ET.parse(template) # for ele in points_list: # # for points2 in ele: # # points1 = points_[1][0].bounds # # points2 = points_[1][1].bounds # # create_xml(str(points_[0]), tree, int(points1[0]), int(points1[1]), int(points1[2]), int(points1[3])) # # create_xml(str(points_[0]), tree, int(points2[0]), int(points2[1]), int(points2[2]), int(points2[3])) # points2 = ele[0] # create_xml('points', tree, int(points2[0]), int(points2[1]), int(points2[0] + 1), int(points2[1] + 1)) # tree.write(os.path.join(save_path, name + '.xml')) # 找出角点最优的那个 # check points 判断点周围有没有黑色像素 points_list_x = sorted(points_list, key=lambda k: k[0][0]) sort_by_x = [ele[0] for ele in points_list_x] differ_new1 = np.array(sort_by_x[1:]) - np.array(sort_by_x[:-1]) index_new1 = sorted(list(set(np.where(differ_new1 > 10.0)[0]))) points_list_new_x = [points_list_x[ele] for ele in index_new1] points_list_y = sorted(points_list_new_x, key=lambda k: k[0][1]) sort_by_y = [ele[0] for ele in points_list_y] differ_new2 = np.array(sort_by_y[1:]) - np.array(sort_by_y[:-1]) index_new2 = sorted(list(set(np.where(differ_new2 > 10.0)[0]))) points_list_new_y = [points_list_y[ele] for ele in index_new2] print('points_list:', points_list_new_y) pixel_point_all = judge_cross_point(points_list_new_y, image, name, thresh=30)
def get_direction(points_and_lines, box_polygon, image): image_height, image_width = image.shape[:2] gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ret, binary = cv2.threshold(gray, 240, 255, cv2.THRESH_BINARY_INV) # raw # cv2.imwrite(os.path.join(r'E:\December\math_12_18\1_18\test_img\save3\\', 'THRESH_BINARY_INV' + '.jpg'), binary) # DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT = 1, 2, 4, 8 DIR_UP, DIR_DOWN, DIR_LEFT, DIR_RIGHT = False, False, False, False # c++ 规则 # CROSS_TL = DIR_UP | DIR_LEFT # CROSS_TR = DIR_UP | DIR_RIGHT # CROSS_TLR = DIR_UP | DIR_LEFT | DIR_RIGHT # CROSS_BL = DIR_DOWN | DIR_LEFT # CROSS_BR = DIR_DOWN | DIR_RIGHT # CROSS_BLR = DIR_DOWN | DIR_LEFT | DIR_RIGHT # CROSS_TBL = DIR_UP | DIR_DOWN | DIR_LEFT # CROSS_TBR = DIR_UP | DIR_DOWN | DIR_RIGHT # CROSS_TBLR = DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT # python 规则 # CROSS_TL = DIR_UP and DIR_LEFT # CROSS_TR = DIR_UP and DIR_RIGHT # CROSS_TLR = DIR_UP and DIR_LEFT and DIR_RIGHT # CROSS_BL = DIR_DOWN and DIR_LEFT # CROSS_BR = DIR_DOWN and DIR_RIGHT # CROSS_BLR = DIR_DOWN and DIR_LEFT and DIR_RIGHT # CROSS_TBL = DIR_UP and DIR_DOWN and DIR_LEFT # CROSS_TBR = DIR_UP and DIR_DOWN and DIR_RIGHT # CROSS_TBLR = DIR_UP and DIR_DOWN and DIR_LEFT and DIR_RIGHT # rule_list = [CROSS_TL, CROSS_TR, CROSS_TLR, CROSS_BL, CROSS_BR, CROSS_BLR, CROSS_TBL, CROSS_TBR, CROSS_TBLR] # 因为延长的线可能出问题,这里用的是原始的线 print('points_and_lines:', points_and_lines) points = points_and_lines[0] raw_line = points_and_lines[1] point_x = int(points[0]) point_y = int(points[1]) # if point_x == 1620 and point_y == 3260: bbox = box_polygon.bounds left_boarder = int(bbox[0]) - point_x if int(bbox[0]) - point_x > 0 else 0 right_boarder = int(bbox[2]) + point_x if int( bbox[2]) + point_x < image_width else image_width top_boarder = int(bbox[1]) - point_y if int(bbox[1]) - point_y > 0 else 0 bottom_boarder = int(bbox[3]) + point_y if int( bbox[3]) + point_y < image_height else image_height cv2.rectangle(image, (left_boarder, top_boarder), (right_boarder, bottom_boarder), (255, 0, 255), 1) raw_line_lan_ = raw_line[0] raw_line_lon_ = raw_line[1] if abs(raw_line_lan_.bounds[2] - point_x) >= abs(raw_line_lan_.bounds[0] - point_x): raw_line_lan = LineString([(point_x, raw_line_lan_.bounds[1]), (raw_line_lan_.bounds[2], raw_line_lan_.bounds[3])]) else: raw_line_lan = LineString([(raw_line_lan_.bounds[0], raw_line_lan_.bounds[1]), (point_x, raw_line_lan_.bounds[3])]) if abs(raw_line_lon_.bounds[3] - point_y) <= abs(point_y - raw_line_lon_.bounds[1]): raw_line_lon = LineString([(raw_line_lon_.bounds[0], raw_line_lon_.bounds[1]), (raw_line_lon_.bounds[2], point_y)]) else: raw_line_lon = LineString([(raw_line_lon_.bounds[0], point_y), (raw_line_lon_.bounds[2], raw_line_lon_.bounds[3])]) # box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) right_area = Polygon([(point_x, point_y - 10), (right_boarder, point_y - 10), (right_boarder, point_y + 10), (point_x, point_y + 10)]) # 横线 cv2.line(image, (int(raw_line_lan.bounds[0]), int(raw_line_lan.bounds[1])), (int(raw_line_lan.bounds[2]), int(raw_line_lan.bounds[3])), (255, 0, 0), 1, cv2.LINE_AA) # cv2.line(image, (int(raw_line_lan_.bounds[0]), int(raw_line_lan_.bounds[1])), # (int(raw_line_lan_.bounds[2]), int(raw_line_lan_.bounds[3])), (255, 255, 0), 1, cv2.LINE_AA) # 纵线 cv2.line(image, (int(raw_line_lon.bounds[0]), int(raw_line_lon.bounds[1])), (int(raw_line_lon.bounds[2]), int(raw_line_lon.bounds[3])), (255, 0, 0), 1, cv2.LINE_AA) # cv2.line(image, (int(raw_line_lon_.bounds[0]), int(raw_line_lon_.bounds[1])), # (int(raw_line_lon_.bounds[2]), int(raw_line_lon_.bounds[3])), (255, 255, 0), 1, cv2.LINE_AA) cv2.rectangle(image, (int(right_area.bounds[0]), int(right_area.bounds[1])), (int(right_area.bounds[2]), int(right_area.bounds[3])), (255, 0, 255), 1) # cv2.imwrite(r'E:\December\math_12_18\1_18\test_img\save3\extend_lines_by_bbox.jpg', image) # 水平向右 decision = [ raw_line_lan.within(right_area), raw_line_lan.contains(right_area), raw_line_lan.crosses(right_area) ] if True in decision: DIR_RIGHT = True # 水平向左 left_area = Polygon([(left_boarder, point_y - 10), (point_x, point_y - 10), (point_x, point_y + 10), (left_boarder, point_y + 10)]) decision = [ raw_line_lan.within(left_area), raw_line_lan.contains(left_area), raw_line_lan.crosses(left_area) ] if True in decision: DIR_LEFT = True # box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) # 垂直向上 top_area = Polygon([(point_x - 10, top_boarder), (point_x + 10, top_boarder), (point_x + 10, point_y), (point_x - 10, point_y)]) decision = [ raw_line_lon.within(top_area), raw_line_lon.contains(top_area), raw_line_lon.crosses(top_area) ] if True in decision: DIR_UP = True # 垂直向下 bottom_area = Polygon([(point_x - 10, point_y), (point_x + 10, point_y), (point_x + 10, bottom_boarder), (point_x - 10, bottom_boarder)]) decision = [ raw_line_lon.within(bottom_area), raw_line_lon.contains(bottom_area), raw_line_lon.crosses(bottom_area) ] if True in decision: DIR_DOWN = True CROSS_TL = DIR_UP and DIR_LEFT CROSS_TR = DIR_UP and DIR_RIGHT CROSS_TLR = DIR_UP and DIR_LEFT and DIR_RIGHT CROSS_BL = DIR_DOWN and DIR_LEFT CROSS_BR = DIR_DOWN and DIR_RIGHT CROSS_BLR = DIR_DOWN and DIR_LEFT and DIR_RIGHT CROSS_TBL = DIR_UP and DIR_DOWN and DIR_LEFT CROSS_TBR = DIR_UP and DIR_DOWN and DIR_RIGHT CROSS_TBLR = DIR_UP and DIR_DOWN and DIR_LEFT and DIR_RIGHT direction_dict = { 0: 'CROSS_TL', 1: 'CROSS_TR', 2: 'CROSS_TLR', 3: 'CROSS_BL', 4: 'CROSS_BR', 5: 'CROSS_BLR', 6: 'CROSS_TBL', 7: 'CROSS_TBR', 8: 'CROSS_TBLR', } rule_list_tmp = [ CROSS_TL, CROSS_TR, CROSS_TLR, CROSS_BL, CROSS_BR, CROSS_BLR, CROSS_TBL, CROSS_TBR, CROSS_TBLR ] index_ = np.where(np.array(rule_list_tmp) == True)[0] if len(index_) == 0: print('没找到方向:', points) return None else: print('index_:', index_) direction = direction_dict[index_[0]] return direction
def seilingstid(hale_df, tellelinje1, tellelinje2, returner_hale_index=False): """ MODIFISERT MENON-KODE Klipper alle haler i hale_df som passerer både tellelinje 1 og 2 og returnerer segmentene som ligger mellom, samt tilhørende seilingstid brukt mellom linjene, lengde på seilasen mellom linjene i m og gjennomsnittlig hastighet i m/s. Funksjonen er så lang som den er for å håndtere edge-cases som i stor grad resulterer av at shapely.split() har en bug ved selv-kryssende linjer. Om denne skulle bli fikset så kan funksjonen potensielt skrives om. Input: hale_df: pandas dataframe med haler tellelinje 1/2: i vilkårlig rekkefølge, shapely geometrier returner_hale_index: hvis True, returnerer en liste indexer av samme lengde som klipp-outputen som korresponderer til halene brukt i hvert av klippene. Output: klipp_df: pandas dataframe som inneholder klippene [hale_indices]: liste med indexer (se returner_hale_index) ADVARSEL: behandler kun ca. 50 haler i sekundet """ #projeksjonen antar at input er en epsg:4326-projeksjon, som er standard for geosatelittdata #denne brukes for å regne om klippenes lengde fra epsg:4326-koordinater til nautiske mil #projeksjon = partial(pyproj.transform, #pyproj.Proj(init='epsg:4326'), #pyproj.Proj(init='epsg:32632')) klipp_df = gpd.GeoDataFrame() #hvis returner_hale_index er True vil denne fylles med indexer fra hale_df korresponderende til klippene i klipp_df hale_indices = [] #iterer over haler for idx, hale_serie in hale_df.iterrows(): hale = hale_serie.geometry hale_punkter = [Point(p) for p in hale.coords] #sjekker først om halen krysser begge tellelinjene if hale.intersects(tellelinje1) and hale.intersects(tellelinje2): #henter ut punktene der halen og tellelinjene krysser intersect_punkter_1 = hale.intersection(tellelinje1) intersect_punkter_2 = hale.intersection(tellelinje2) #dersom det kun finnes ett krysningspunkt per tellelinje puttes det i en liste for å funke i for-loopen senere if isinstance(intersect_punkter_1, Point): intersect_punkter_1 = [intersect_punkter_1] elif isinstance( intersect_punkter_1, LineString): #for aa vaere kompatibel med polygoner intersect_punkter_1 = [ Point(p) for p in intersect_punkter_1.coords ] elif isinstance( intersect_punkter_1[0], LineString): #for aa vaere kompatibel med polygoner temp = [] for l in intersect_punkter_1: temp.extend([Point(p) for p in l.coords]) intersect_punkter_1 = temp if isinstance(intersect_punkter_2, Point): intersect_punkter_2 = [intersect_punkter_2] elif isinstance( intersect_punkter_2, LineString): #for aa vaere kompatibel med polygoner intersect_punkter_2 = [ Point(p) for p in intersect_punkter_2.coords ] elif isinstance( intersect_punkter_2[0], LineString): #for aa vaere kompatibel med polygoner temp = [] for l in intersect_punkter_2: temp.extend([Point(p) for p in l.coords]) intersect_punkter_2 = temp intersect_idx_1 = [] intersect_idx_2 = [] intersect_time_1 = [] intersect_time_2 = [] #spar på punktene der halen krysser tellelinjene så de kan legges inn i klippet krysningspunkter_1 = [] krysningspunkter_2 = [] #iterer over krysningspunktene for punkt in intersect_punkter_1: #regn ut avstander fra hvert punkt i halen til krysningspunktene #(kan effektiviseres ved å filtrere ut hale-punkter utenfor loopen) point_distances = np.array([ hale_punkt.distance(punkt) for hale_punkt in hale_punkter ]) #henter lokale minimum i avstand for å finne potensielle krysningspunkter. #NB: antar at halen ikke begynner eller slutter på et krysningspunkt local_minima = np.where( np.r_[True, point_distances[1:] <= point_distances[:-1]] & np.r_[point_distances[:-1] <= point_distances[1:], True])[0] #iterer over de potensielle krysningspunktene for minima in local_minima: #hent avstand til forrige og neste punkt linje_bak, linje_frem = None, None if minima > 0: linje_bak = LineString( [hale_punkter[minima], hale_punkter[minima - 1]]).buffer(0.0001) if minima < len(hale_punkter) - 1: linje_frem = LineString( [hale_punkter[minima], hale_punkter[minima + 1]]).buffer(0.0001) if linje_bak is not None and linje_bak.contains(punkt): #legger til indexen til det nærmeste hale-punktet til krysningspunktet #(tiden hentes ut her fordi det tillater inerpolering, #men for øyeblikket støttes ikke dette) intersect_idx_1.append(minima) krysningspunkter_1.append(punkt) weight = point_distances[minima - 1] / hale_punkter[ minima - 1].distance(hale_punkter[minima]) intersect_time_1.append( hale_serie.times[minima - 1] + ((hale_serie.times[minima] - hale_serie.times[minima - 1]) * weight)) elif linje_frem is not None and linje_frem.contains(punkt): #krysning funnet intersect_idx_1.append(minima) krysningspunkter_1.append(punkt) weight = point_distances[minima] / hale_punkter[ minima].distance(hale_punkter[minima + 1]) intersect_time_1.append(hale_serie.times[minima] + ( (hale_serie.times[minima + 1] - hale_serie.times[minima]) * weight)) #se kommentarer for intersect_punkter_1 for punkt in intersect_punkter_2: point_distances = np.array([ hale_punkt.distance(punkt) for hale_punkt in hale_punkter ]) local_minima = np.where( np.r_[True, point_distances[1:] <= point_distances[:-1]] & np.r_[point_distances[:-1] <= point_distances[1:], True])[0] for minima in local_minima: linje_bak, linje_frem = None, None if minima > 0: linje_bak = LineString( [hale_punkter[minima], hale_punkter[minima - 1]]).buffer(0.01) if minima < len(hale_punkter) - 1: linje_frem = LineString( [hale_punkter[minima], hale_punkter[minima + 1]]).buffer(0.01) if linje_bak is not None and linje_bak.contains(punkt): intersect_idx_2.append(minima) krysningspunkter_2.append(punkt) weight = point_distances[minima - 1] / hale_punkter[ minima - 1].distance(hale_punkter[minima]) intersect_time_2.append( hale_serie.times[minima - 1] + ((hale_serie.times[minima] - hale_serie.times[minima - 1]) * weight)) elif linje_frem is not None and linje_frem.contains(punkt): intersect_idx_2.append(minima) krysningspunkter_2.append(punkt) weight = point_distances[minima] / hale_punkter[ minima].distance(hale_punkter[minima + 1]) intersect_time_2.append(hale_serie.times[minima] + ( (hale_serie.times[minima + 1] - hale_serie.times[minima]) * weight)) #henter ut de unike hale-punkt-indexene unq1, unq_idx1 = np.unique(intersect_idx_1, return_index=True) unq2, unq_idx2 = np.unique(intersect_idx_2, return_index=True) intersect_idx_1 = unq1 intersect_idx_2 = unq2 krysningspunkter_1 = [krysningspunkter_1[u] for u in unq_idx1] krysningspunkter_2 = [krysningspunkter_2[u] for u in unq_idx2] #henter ut de tilsvarende hale-tid indexene intersect_time_1 = np.array(intersect_time_1)[unq_idx1] intersect_time_2 = np.array(intersect_time_2)[unq_idx2] #i tilfelle punktene ikke er sortert etter tid time_sort_idx_1 = np.argsort(intersect_time_1) time_sort_idx_2 = np.argsort(intersect_time_2) #sorterer etter tid intersect_idx_1 = list(intersect_idx_1[time_sort_idx_1]) intersect_idx_2 = list(intersect_idx_2[time_sort_idx_2]) intersect_time_1 = list(intersect_time_1[time_sort_idx_1]) intersect_time_2 = list(intersect_time_2[time_sort_idx_2]) krysningspunkter_1 = [ krysningspunkter_1[t] for t in time_sort_idx_1 ] krysningspunkter_2 = [ krysningspunkter_2[t] for t in time_sort_idx_2 ] #iterer over krysningspunktene og hent ut krysningsparene. #lag så en dataframe av geometri, tidspunkter, utregnet avstand #samt hastighet. while len(intersect_idx_1) > 0 and len(intersect_idx_2) > 0: start_idx = None slutt_idx = None klipp_start = None klipp_slutt = None hale_klippet = None foerste_kryss = None if intersect_idx_1[0] < intersect_idx_2[0]: if len(intersect_idx_1 ) > 1 and intersect_idx_1[1] < intersect_idx_2[0]: krysningspunkter_1 = krysningspunkter_1[1:] intersect_idx_1 = intersect_idx_1[1:] intersect_time_1 = intersect_time_1[1:] else: start_idx = intersect_idx_1[0] slutt_idx = intersect_idx_2[0] klipp_start = intersect_time_1[0] klipp_slutt = intersect_time_2[0] foerste_kryss = 1 krysningspunkter_1 = krysningspunkter_1[1:] krysningspunkter_2 = krysningspunkter_2[1:] intersect_idx_1 = intersect_idx_1[1:] intersect_idx_2 = intersect_idx_2[1:] intersect_time_1 = intersect_time_1[1:] intersect_time_2 = intersect_time_2[1:] else: if len(intersect_idx_2 ) > 1 and intersect_idx_2[1] < intersect_idx_1[0]: krysningspunkter_2 = krysningspunkter_2[1:] intersect_idx_2 = intersect_idx_2[1:] intersect_time_2 = intersect_time_2[1:] else: start_idx = intersect_idx_2[0] slutt_idx = intersect_idx_1[0] intersect_idx_2 = intersect_idx_2[1:] intersect_idx_1 = intersect_idx_1[1:] klipp_start = intersect_time_2[0] klipp_slutt = intersect_time_1[0] intersect_time_2 = intersect_time_2[1:] intersect_time_1 = intersect_time_1[1:] foerste_kryss = 2 krysningspunkter_1 = krysningspunkter_1[1:] krysningspunkter_2 = krysningspunkter_2[1:] if slutt_idx is None or slutt_idx - start_idx <= 1: continue hale_klippet = LineString(hale_punkter[start_idx:slutt_idx]) lengde = distance_points( hale_punkter[start_idx], hale_punkter[slutt_idx]) * 1000 #metrisk meter tid_brukt = (klipp_slutt - klipp_start).total_seconds() klipp_df = klipp_df.append( gpd.GeoDataFrame([[ hale_serie.mmsi, klipp_start, klipp_slutt, lengde, lengde / tid_brukt, foerste_kryss, hale_klippet ]], columns=[ 'mmsi', 'start_tid', 'slutt_tid', 'lengde', 'obs_speed', 'første_linje_krysset', 'geometry' ], geometry='geometry')) if returner_hale_index: hale_indices.append(idx) if klipp_df.shape[0] > 0: klipp_df = klipp_df.set_geometry('geometry') if returner_hale_index: return klipp_df, hale_indices return klipp_df
def filter_long_distance_lines(lines, sheet_dict): # 去掉roi里面的线 也去掉mark里的线 lines_tmp1 = [] for index, region_box in enumerate(sheet_dict): if region_box['class_name'] in class_above_edge: coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] + 10 ymin = coordinates['ymin'] + 10 xmax = coordinates['xmax'] - 10 ymax = coordinates['ymax'] - 10 box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) for line in lines: line_tmp = LineString([(line[0], line[1]), (line[2], line[3])]) # line_tmp = LineString([(750, 502), (1035, 502)]) # decision = [line_tmp.within(box_polygon), line_tmp.contains(box_polygon), line_tmp.overlaps(box_polygon)] decision = [ line_tmp.within(box_polygon), line_tmp.contains(box_polygon) ] # attention:[179, 440, 1092, 729] # 横线 750, 502, 1035, 509 if True in decision: lines_tmp1.append(line) elif region_box['class_name'] == 'mark': coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] ymin = coordinates['ymin'] xmax = coordinates['xmax'] ymax = coordinates['ymax'] box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) for line in lines: line_tmp = LineString([(line[0], line[1]), (line[2], line[3])]) # line_tmp = LineString([(750, 502), (1035, 502)]) decision = [ line_tmp.within(box_polygon), line_tmp.contains(box_polygon) ] # attention:[179, 440, 1092, 729] # 横线 750, 502, 1035, 509 if True in decision: lines_tmp1.append(line) lines_tmp = [line for line in lines if line not in lines_tmp1] # 这里能去掉所有ROI里面的线,下面还要去掉离ROI很远的线,不然遍历费时间 lines_apart_from_box = [] for line0 in lines_tmp: # 考虑的是点而不是线 middle_point = [ 1 / 2 * (line0[2] - line0[0]), 1 / 2 * (line0[3] - line0[1]) ] middle_point = list(np.maximum(np.array(middle_point), 0)) start_point = [line0[0], line0[1]] end_point = [line0[2], line0[3]] key_point = [middle_point, end_point, start_point] for index, region_box in enumerate(sheet_dict): if region_box['class_name'] in class_above_edge: coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] - 10 ymin = coordinates['ymin'] - 10 xmax = coordinates['xmax'] + 10 ymax = coordinates['ymax'] + 10 for pp in key_point: if xmin <= pp[0] <= xmax and ymin <= pp[1] < ymax: lines_apart_from_box.append(line0) # line_tmp_ = LineString([(line[0], line[1]), (line[2], line[3])]) # for index, region_box in enumerate(sheet_dict): # if region_box['class_name'] in class_above_edge: # coordinates = region_box['bounding_box'] # xmin = coordinates['xmin'] + 10 # ymin = coordinates['ymin'] + 10 # xmax = coordinates['xmax'] - 10 # ymax = coordinates['ymax'] - 10 # box_polygon_ = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) # decision = [line_tmp_.contains(box_polygon_), line_tmp_.within(box_polygon_), # line_tmp_.crosses(box_polygon_), line_tmp_.overlaps(box_polygon_)] # if True in decision: # lines_apart_from_box.append(line) # 去掉重复线 lines_apart_from_box_array = np.array(lines_apart_from_box) former_one = lines_apart_from_box_array[1:, :] rear_one = lines_apart_from_box_array[:-1, :] differ = former_one - rear_one index_ = sorted(list(set(np.where(differ != 0)[0]))) lines_apart_from_box_ = [lines_apart_from_box[ele] for ele in index_] return lines_apart_from_box_
def fld_demo4(image, sheet_dict, name, save_path): img = Image.fromarray(image) t = time.time() img_gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # ret, binary = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU) fld = cv2.ximgproc.createFastLineDetector() dlines = fld.detect(img_gray) lines = [line[0] for line in dlines.tolist()] lines_arr = np.array(lines) width_ = lines_arr[:, 2] - lines_arr[:, 0] height_ = lines_arr[:, 3] - lines_arr[:, 1] lines_index1 = np.where(width_ > 50)[0] lines_index2 = np.where(height_ > 50)[0] lines_index = np.hstack([lines_index1, lines_index2]) new_lines = [lines[ele] for ele in lines_index] new_lines = clean_repeat_lines(new_lines) lines_tmp = filter_long_distance_lines(new_lines, sheet_dict) # lines_without_mark = filter_line_in_mark(new_lines, sheet_dict) # 检验滤线这一步骤有没有问题 for dline in lines_tmp: x0 = int(round(dline[0])) y0 = int(round(dline[1])) x1 = int(round(dline[2])) y1 = int(round(dline[3])) cv2.line(image, (x0, y0), (x1, y1), (0, 255, 0), 1, cv2.LINE_AA) text = str([x0, y0, x1, y1]) cv2.putText(image, text, (x1, y1), cv2.FONT_HERSHEY_COMPLEX, 1, (0, 0, 255), 1) write_single_img(image, os.path.join(save_path, name + '_raw_lines' + '.jpg')) # get roi polygon 适当放大一点区域,使的线能包含在面里 roi_box_polygon = [] for index, region_box in enumerate(sheet_dict): if region_box['class_name'] in class_above_edge: coordinates = region_box['bounding_box'] xmin = coordinates['xmin'] - 5 ymin = coordinates['ymin'] - 5 xmax = coordinates['xmax'] + 5 ymax = coordinates['ymax'] + 5 box_polygon = Polygon([(xmin, ymin), (xmax, ymin), (xmax, ymax), (xmin, ymax)]) roi_box_polygon.append(box_polygon) cv2.rectangle(image, (xmin, ymin), (xmax, ymax), (0, 0, 255), 1) cv2.imwrite(r'E:\111_4_26_test_img\aa\save\enlarge_box.jpg', image) # print(roi_box_polygon) # 对line进行分横向纵向 landscape_list_tmp = [] # 横向 longitudinal_list_tmp = [] # 纵向 for ele in lines_tmp: if int(ele[2]) - int(ele[0]) < 10: # 纵向 longitudinal_list_tmp.append(ele) elif int(ele[3]) - int(ele[1]) < 10: # 横向 landscape_list_tmp.append(ele) # print(longitudinal_list_tmp) points_all_list = [] points_list = [] for index, box_polygon in enumerate(roi_box_polygon): extend_line_lan = LineString() extend_line_lon = LineString() # points_list = [] for line1 in landscape_list_tmp: for line2 in longitudinal_list_tmp: # 这部分对原先出来的线进行增大 raw_line_lan = LineString([(line1[0], line1[1]), (line1[2], line1[3])]) # 横向增加5个像素 line_start_lan, line_end_lan = raw_line_lan.bounds[ 0], raw_line_lan.bounds[1] raw_line_lon = LineString([(line2[0], line2[1]), (line2[2], line2[3])]) # 纵向的增加5个像素 line_start_lon, line_end_lon = raw_line_lon.bounds[ 0], raw_line_lon.bounds[1] # decision1 = [raw_line_lan.within(box_polygon), raw_line_lan.contains(box_polygon), raw_line_lan.overlaps(box_polygon)] # decision2 = [raw_line_lon.within(box_polygon), raw_line_lon.contains(box_polygon), raw_line_lon.overlaps(box_polygon)] decision1 = [ raw_line_lan.within(box_polygon), raw_line_lan.contains(box_polygon) ] decision2 = [ raw_line_lon.within(box_polygon), raw_line_lon.contains(box_polygon) ] if True in decision1 and True in decision2: # 这里需要考虑延长左边还是右边 bbox_xmin, bbox_ymin, bbox_xmax, bbox_ymax = box_polygon.bounds[0], box_polygon.bounds[1], \ box_polygon.bounds[2], box_polygon.bounds[3] # if abs(line_start_lan - bbox_xmin) < abs(bbox_xmax - line_end_lan): extend_line_lan = LineString([ (box_polygon.bounds[0], line1[1]), (box_polygon.bounds[2], line1[3]) ]) # elif abs(line_start_lon - bbox_ymin) < abs(bbox_ymax - line_end_lon): extend_line_lon = LineString([ (line2[0], box_polygon.bounds[1]), (line2[2], box_polygon.bounds[3]) ]) cond1 = raw_line_lan.intersects(raw_line_lon) cond2 = raw_line_lan.crosses(raw_line_lon) cond3 = extend_line_lan.intersects(extend_line_lon) # 十字交叉 cond4 = extend_line_lan.crosses(extend_line_lon) # 十字交叉 xp, yp = 0.0, 0.0 if cond1: (xp, yp ) = raw_line_lan.intersection(raw_line_lon).bounds[:2] elif cond3: (xp, yp) = extend_line_lan.intersection( extend_line_lon).bounds[:2] points_list.append([(xp, yp), (raw_line_lan, raw_line_lon), (extend_line_lan, extend_line_lon), box_polygon]) # TODO 验证找所有点的正确性 # template = r'F:\exam\sheet_resolve\exam_info\000000-template.xml' # tree = ET.parse(template) # for ele in points_list: # # for points2 in ele: # # points1 = points_[1][0].bounds # # points2 = points_[1][1].bounds # # create_xml(str(points_[0]), tree, int(points1[0]), int(points1[1]), int(points1[2]), int(points1[3])) # # create_xml(str(points_[0]), tree, int(points2[0]), int(points2[1]), int(points2[2]), int(points2[3])) # points2 = ele[0] # create_xml('points', tree, int(points2[0]), int(points2[1]), int(points2[0] + 1), int(points2[1] + 1)) # tree.write(os.path.join(save_path, name + '.xml')) # 找出角点最优的那个 # check points 判断点周围有没有黑色像素 points_list = sorted(points_list, key=lambda k: k[0][0]) points_all1 = [ele[0] for ele in points_list] differ_new1 = np.array(points_all1[1:]) - np.array(points_all1[:-1]) index_new1 = np.where(differ_new1 > 6.0)[0] points_list = [points_list[ele] for ele in index_new1] print('points_list:', points_list) points_new = [] for points_ in points_list: pixel_point = img.getpixel((int(points_[0][0]), int(points_[0][1]))) if int(np.mean(np.array(pixel_point))) <= 245: points_new.append(points_) # print(points_new) # 验证这里每个点是不是黑色像素 template = r'F:\exam\sheet_resolve\exam_info\000000-template.xml' tree = ET.parse(template) for ele in points_list: points2 = ele[0] create_xml('points', tree, int(points2[0]), int(points2[1]), int(points2[0] + 1), int(points2[1] + 1)) tree.write(os.path.join(save_path, 'points_' + name + '.xml')) points_new = sorted(points_new, key=lambda k: k[0][0]) points_new_list = [] if len(points_new) == 1: points_new_list.extend(points_new) else: points_all_x = [ele[0][0] for ele in points_new] rear_one_x = np.array(points_all_x)[1:] former_one_x = np.array(points_all_x)[:-1] differ_x = rear_one_x - former_one_x index_x = list( np.where(differ_x >= 6.0)[0]) # 符合条件的说明不是同一个点,这些点都要加进列表里去 # 头和尾加进去 # if points_all_x[1] - points_all_x[0] >= 6.0: # index_x.insert(0, 0) # elif points_all_x[-1] - points_all_x[-1] >= 6.0: # index_x.append(len(points_all_x) - 1) points_all_y = [ele[0][1] for ele in points_new] rear_one_y = np.array(points_all_y)[1:] former_one_y = np.array(points_all_y)[:-1] differ_y = rear_one_y - former_one_y index_y = list( np.where(differ_y >= 6.0)[0]) # 符合条件的说明不是同一个点,这些点都要加进列表里去 # 头和尾加进去 # if points_all_y[1] - points_all_y[0] >= 6.0: # index_y.insert(0, 0) # elif points_all_y[-1] - points_all_y[-1] >= 6.0: # index_y.append(len(points_all_y) - 1) while len(index_x) == 0 and len(index_y) == 0: # 说明每个点都不重合,都是需要的点 points_new_list.extend(points_new) break if len(index_x) != 0: if len(index_x) > 2: index_x = list(index_x) index_x.insert(0, 0) index_x.append(len(points_new)) for index_a, ele in enumerate(index_x[1:]): block_one = points_new[index_x[index_a]:index_x[index_a + 1]] if len(block_one) == 1: points_new_list.extend(block_one) else: # 取均值 x_mean = np.mean( np.array([ele[0][0] for ele in block_one])) y_mean = np.mean( np.array([ele[0][1] for ele in block_one])) # 取最长的线 # max_index_lan = np.argsort(np.array([int(ele[1][0]) for ele in block_one])) # max_index_lon = np.argsort(np.array([int(ele[1][1]) for ele in block_one])) xx = [int(ele[1][0].length) for ele in block_one] max_index_lan = np.argsort( [int(ele[1][0].length) for ele in block_one]) yy = [int(ele[1][1].length) for ele in block_one] max_index_lon = np.argsort( [int(ele[1][1].length) for ele in block_one]) zz = block_one[max_index_lan[-1]][1][0] cc = block_one[max_index_lon[-1]][1][1] points_new_list.append([ (x_mean, y_mean), (block_one[max_index_lan[-1]][1][0], block_one[max_index_lon[-1]][1][1]), block_one[-1][-1] ]) print('points_new_list:', points_new_list) elif len(index_y) != 0: index_y = list(index_y) index_y.insert(0, 0) index_y.append(len(points_new)) if len(index_y) > 2: for index_a, ele in enumerate(index_y[1:]): block_one = points_new[index_y[index_a]:index_y[index_a + 1]] if len(block_one) == 1: points_new_list.extend(block_one) else: # 取均值 x_mean = np.mean( np.array([ele[0][0] for ele in block_one])) y_mean = np.mean( np.array([ele[0][1] for ele in block_one])) # 取最长的线 # max_index_lan = np.argsort(np.array([int(ele[1][0]) for ele in block_one])) # max_index_lon = np.argsort(np.array([int(ele[1][1]) for ele in block_one])) xx = [int(ele[1][0].length) for ele in block_one] max_index_lan = np.argsort( [int(ele[1][0].length) for ele in block_one]) yy = [int(ele[1][1].length) for ele in block_one] max_index_lon = np.argsort( [int(ele[1][1].length) for ele in block_one]) zz = block_one[max_index_lan[-1]][1][0] cc = block_one[max_index_lon[-1]][1][1] points_new_list.append([ (x_mean, y_mean), (block_one[max_index_lan[-1]][1][0], block_one[max_index_lon[-1]][1][1]), block_one[-1][-1] ]) print('points_new_list:', points_new_list) else: points_all_list.extend(points_new) # 合并points_new_list成一个list # points_new_list_tmp = [ele for ele in points_new_list] for points_and_lines in points_new_list: direction = get_direction(points_and_lines, points_and_lines[-1], image) if direction != None: points_dict = {} points_dict['points'] = points_and_lines[0] points_dict['direction'] = direction points_dict['extend_line'] = points_and_lines[-2] points_all_list.append(points_dict) print(points_all_list) template = r'F:\exam\sheet_resolve\exam_info\000000-template.xml' tree = ET.parse(template) for points_ in points_all_list: points = points_['points'] create_xml( str(points) + '_' + points_['direction'], tree, int(points[0]), int(points[1]), int(points[0] + 1), int(points[1] + 1)) tree.write(os.path.join(save_path, name + '.xml'))
def compare_range(standard, compare, buf): rangement = LineString(standard).buffer(buf) compare_line = LineString(compare) return rangement.contains(compare_line)
hull_pts = hull.exterior.coords.xy hull_points = [] for i in range(0, len(hull_pts[0])): hull_points.append((hull_pts[0][i], hull_pts[1][i])) polyg = Polygon(hull_points) line_polygon = LineString(polyg.exterior.coords) # (minx, miny, maxx, maxy) bounds = list(map(int, list(polyg.bounds))) polni_nivo[_nivo] = [] outer_nivo[_nivo] = [] for i in range(bounds[0], bounds[2]+1): for j in range(bounds[1], bounds[3]+1): if line_polygon.contains(Point(i,j)): outer_nivo[_nivo].append((i,j)) elif polyg.contains(Point(i,j)): polni_nivo[_nivo].append((i,j)) if _nivo == min_z or _nivo == max_z: outer_nivo[_nivo].append((i, j)) with open(f"polninivo{time.time()}.dat", "wb+") as f: pickle.dump(polni_nivo, f) with open(f"outernivo{time.time()}.dat", "wb+") as f: pickle.dump(outer_nivo, f) xdata_final = [] ydata_final = []
def filter_contained_points(line: LineString, points: List[Point]) -> List[Point]: return [point for point in points if line.contains(point)]
# Ponto de referência p1 = vertices[p1_num] for m in range(i - nivel_conect * espacamento, i + nivel_conect * espacamento + 1): if not (0 <= m <= malha_gs.shape[0] - 1): continue for n in range(j - nivel_conect * espacamento, j + nivel_conect * espacamento + 1): if 0 <= n <= malha_gs.shape[1] - 1: if (p2_num := malha_gs[m, n]) != 0: # Ponto de comparação p2 = vertices[p2_num] if not np.allclose(p1, p2): linha = LineString([p1, p2]) if not any( linha.contains(e) for e in elementos.values()): if poligono.contains( linha ) or contorno_com_buff.contains( linha): elementos[(p1_num, p2_num)] = linha return elementos, vertices @staticmethod def verificar_vertices_ociosos(vertices, elementos) -> tuple: # Apagar os vértices que não são utilizados verts_usados = [] for e in elementos:
# Defining the points for the obstacle obs_pt = [[2, 2], [2, 4], [4, 4], [4, 2]] obs_poly = Polygon(obs_pt) plt.gca().add_patch(plt.Polygon(obs_pt, fill=True, color='lightgrey')) # Inside point pt_i = [3, 3] plt.plot(pt_i[0], pt_i[1], 'ok') # Point on the boundary pt_b = [2, 3] plt.plot(pt_b[0], pt_b[1], 'ob') # Point outside pt_o = [1, 3] plt.plot(pt_o[0], pt_o[1], 'or') # Condition to check if point lies inside polygon # using polygon.contains(point) print(obs_poly.contains(Point(pt_i[0], pt_i[1])), obs_poly.contains(Point(pt_b[0], pt_b[1])), obs_poly.contains(Point(pt_o[0], pt_o[1]))) # Creating a linestring to verify the same line = LineString(obs_pt) print(line.contains(Point(pt_i[0], pt_i[1])), line.contains(Point(pt_b[0], pt_b[1])), line.contains(Point(pt_o[0], pt_o[1]))) plt.show()
def intersection(x1, y1, x2, y2, x3, y3, x4, y4): # wektory first_third_x = x3 - x1 first_third_y = y3 - y1 rx = x2 - x1 ry = y2 - y1 sx = x4 - x3 sy = y4 - y3 # obliczanie wyznaczników potrzebnych do wykorzystania metody Cramer'a numerator_t = determinant(first_third_x, first_third_y, sx, sy) numerator_u = determinant(first_third_x, first_third_y, rx, ry) denominator = determinant(rx, ry, sx, sy) try: t = numerator_t / denominator u = numerator_u / denominator if denominator != 0 and 0 <= t <= 1 and 0 <= u <= 1: i_x = x1 + t * rx i_y = y1 + u * ry msg = f"Odcinek przecina się w punkcie: ({i_x}, {i_y})" messagebox.showinfo('Odpowiedź', msg) plot_intersection(x1, y1, x2, y2, x3, y3, x4, y4, i_x, i_y) else: msg = "Odcninki nie przecinają się oraz nie są równoległe.\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) plot_intersection(x1, y1, x2, y2, x3, y3, x4, y4) except ZeroDivisionError: if denominator == 0 and numerator_u != 0: msg = "Odcinki są równoległe.\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) plot_intersection(x1, y1, x2, y2, x3, y3, x4, y4) if numerator_u == 0 and denominator == 0: # parametry potrzebne do ocenienia wspólniniowości odcinków t_0 = dot_product(first_third_x, first_third_y, rx, ry) / dot_product(rx, ry, rx, ry) t_1 = t_0 + dot_product(sx, sy, rx, ry) / dot_product( rx, ry, rx, ry) # zdefiniowanie punktów oraz odcinków (bibliotek shapely) segment_AB = LineString([(x1, y1), (x2, y2)]) segment_CD = LineString([(x3, y3), (x4, y4)]) point_A = Point(x1, y1) point_B = Point(x2, y2) point_C = Point(x3, y3) point_D = Point(x4, y4) if dot_product(sx, sy, rx, ry) > 0: # sprawdzenie czy wyliczone t_0 oraz t_1 mają część wspólną z [0,1] interval = portion.closed(t_0, t_1) if interval.overlaps(portion.closed(0, 1)): if segment_AB.contains(point_C) and segment_AB.contains( point_D): msg = f"Odcinki są współliniowe i odcinek CD zawiera się w odcinku AB.\n" \ f"Przedział wspólny: C({x3}, {y3}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_A) and segment_CD.contains( point_B): msg = f"Odcinki są współliniowe i odcinek AB zawiera się w odcinku CD.\n" \ f"Przedział wspólny: D({x1}, {y1}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_AB.contains(point_C): if distance.euclidean(point_D, point_A) > distance.euclidean( point_D, point_B): msg = f"Odcinki są współliniowe i pokrywają się w przedziale CB\n" \ f"C({x3}, {y3}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale AC\n" \ f"A({x1}, {y1}) - C({x3}, {y3})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_AB.contains(point_D): if distance.euclidean(point_C, point_A) > distance.euclidean( point_C, point_B): msg = f"Odcinki są współliniowe i pokrywają się w przedziale DB\n" \ f"D({x4}, {y4}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale AD\n" \ f"A({x1}, {y1}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_A): if distance.euclidean(point_B, point_C) > distance.euclidean( point_B, point_D): msg = f"Odcinki są współliniowe i pokrywają się w przedziale AD\n" \ f"A({x1}, {y1}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale CA\n" \ f"C({x3}, {y3}) - A({x1}, {y1})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_B): if distance.euclidean(point_A, point_C) > distance.euclidean( point_A, point_D): msg = f"Odcinki są współliniowe i pokrywają się w przedziale BD\n" \ f"B({x2}, {y2}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale CB\n" \ f"C({x3}, {y3}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = "Odcinki są współliniowe, ale nie nachodzą na siebie.\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) plot_intersection(x1, y1, x2, y2, x3, y3, x4, y4) if dot_product(sx, sy, rx, ry) < 0: interval = portion.closed(t_1, t_0) if interval.overlaps(portion.closed(0, 1)): if segment_AB.contains(point_C) and segment_AB.contains( point_D): msg = f"Odcinki są współliniowe i odcinek CD zawiera się w odcinku AB.\n" \ f"Przedział wspólny: C({x3}, {y3}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_A) and segment_CD.contains( point_B): msg = f"Odcinki są współliniowe i odcinek AB zawiera się w odcinku CD.\n" \ f"Przedział wspólny: D({x1}, {y1}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_AB.contains(point_C): if distance.euclidean(point_D, point_A) > distance.euclidean( point_D, point_B): msg = f"Odcinki są współliniowe i pokrywają się w przedziale CB\n" \ f"C({x3}, {y3}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale AC\n" \ f"A({x1}, {y1}) - C({x3}, {y3})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_AB.contains(point_D): if distance.euclidean(point_C, point_A) > distance.euclidean( point_C, point_B): msg = f"Odcinki są współliniowe i pokrywają się w przedziale DB\n" \ f"D({x4}, {y4}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale AD\n" \ f"A({x1}, {y1}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_A): if distance.euclidean(point_B, point_C) > distance.euclidean( point_B, point_D): msg = f"Odcinki są współliniowe i pokrywają się w przedziale AD\n" \ f"A({x1}, {y1}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale CA\n" \ f"C({x3}, {y3}) - A({x1}, {y1})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) elif segment_CD.contains(point_B): if distance.euclidean(point_A, point_C) > distance.euclidean( point_A, point_D): msg = f"Odcinki są współliniowe i pokrywają się w przedziale BD\n" \ f"B({x2}, {y2}) - D({x4}, {y4})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = f"Odcinki są współliniowe i pokrywają się w przedziale CB\n" \ f"C({x3}, {y3}) - B({x2}, {y2})\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) else: msg = "Odcinki są współliniowe, ale nie nachodzą na siebie.\nKliknij 'OK', żeby wyświetlić wizualizację." messagebox.showinfo('Odpowiedź', msg) plot_intersection(x1, y1, x2, y2, x3, y3, x4, y4) sys.exit()
def on_segment(p, q, r): line = LineString([Point(p.x, p.y), Point(r.x, r.y)]) return line.contains(Point(q.x, q.y))
class Polyline: """! @brief Custom (open or closed) polyline class """ def __init__(self, coordinates, attributes=None, z_array=None, m_array=None, id=None): self._nb_points = len(coordinates) self._is_2d = len(coordinates[0]) == 2 if z_array is not None: self._is_2d = False self._is_closed = False if tuple(coordinates[0]) == tuple(coordinates[-1]): self._is_closed = len( coordinates ) > 2 # line with 2 coordinates which are identical can not be a polygon if z_array is not None: self._is_closed = z_array[-1] == z_array[0] if z_array is None: coord = coordinates else: coord = [(x, y, z) for (x, y), z in zip(coordinates, z_array)] if self._is_closed: self._polyline = ClosedPolyline(coord) else: self._polyline = OpenPolyline(coord) if attributes is None: self._attributes = [] else: self._attributes = attributes[:] if m_array is None: self.m = [None] * self._nb_points else: if m_array: self.m = m_array[:] else: self.m = [None] * self._nb_points self.id = id def set_id(self, id): self.id = id def to_3d(self, z_array): return Polyline(self.coords(), self.attributes(), z_array) def to_2d(self): if self.is_2d(): return Polyline(self.coords(), self.attributes(), m_array=self.m) return Polyline(list(map(tuple, np.array(self.coords())[:, :2])), self.attributes(), m_array=self.m) def is_2d(self): return self._is_2d def is_closed(self): return self._is_closed def nb_points(self): return self._nb_points def attributes(self): return self._attributes def add_attribute(self, attribute): self._attributes.append(attribute) def coords(self): if self.is_closed(): return self._polyline.exterior.coords return self._polyline.coords def polyline(self): return self._polyline def project(self, x, y): return self._polyline.project(Point(x, y)) def segments(self): prev_x, prev_y = None, None for coord in self.coords(): x, y = coord[:2] # ignore elevation if 3D if prev_x is None: prev_x, prev_y = x, y else: yield x > prev_x, y > prev_y, Polyline([(prev_x, prev_y), (x, y)]) prev_x, prev_y = x, y def __str__(self): return ['Open', 'Closed'][self.is_closed( )] + ' polyline with coordinates %s' % str(list(self.coords())) def contains(self, item): return self._polyline.contains(item) def bounds(self): return self._polyline.bounds def length(self): return self._polyline.length def polygon_intersection(self, triangle): """! @brief (Used in volume calculation) Return the polygon or multipolygon intersection with the triangle @param triangle <shapely.geometry.Polygon>: A triangle @return <bool, shapely.geometry.Polygon or shapely.geometry.Multipolygon>: The intersection with the triangle """ inter = self._polyline.intersection(triangle) if inter.geom_type == 'Polygon' or inter.geom_type == 'MultiPolygon': return True, inter elif inter.geom_type == 'GeometryCollection': poly = list(filter(lambda x: x.geom_type == 'Polygon', inter.geoms)) if not poly: return False, None return True, MultiPolygon(poly) return False, None @staticmethod def triangle_difference(triangle, polygon): """! @brief (Used in volume calculation) Return the polygon or multipolygon in triangle but not in polygon @param triangle <shapely.geometry.Polygon>: A triangle @param polygon <shapely.geometry.Polygon>: A polygon @return <bool, shapely.geometry.Polygon or shapely.geometry.Multipolygon>: The difference between triangle and polygon """ diff = triangle.difference(polygon.polyline()) if diff.geom_type == 'Polygon' or diff.geom_type == 'MultiPolygon': return True, diff elif diff.geom_type == 'GeometryCollection': poly = list(filter(lambda x: x.geom_type == 'Polygon', diff.geoms)) if not poly: return False, None return True, MultiPolygon(poly) return False, None def linestring_intersection(self, triangle): """! @brief (Used in flux calculation) Returns the LinearString intersection with the triangle @param triangle <shapely.geometry.Polygon>: A triangle @return <bool, [shapely.geometry.LinearString]>: The intersection with the triangle """ inter = triangle.intersection(self._polyline) if inter.geom_type == 'LineString': return True, [inter] elif inter.geom_type == 'MultiLineString': return True, list(inter.geoms) elif inter.geom_type == 'GeometryCollection': return True, list( filter(lambda x: x.geom_type == 'LineString', inter.geoms)) return False, None def apply_transformations(self, transformations): new_coords = np.array(list(self.coords())) if self.is_2d(): new_coords = np.hstack((new_coords, np.zeros( (self.nb_points(), 1)))) for t in transformations: new_coords = np.apply_along_axis(t, 1, new_coords) if self.is_2d(): new_coords = new_coords[:, :2] return Polyline(list(map(tuple, new_coords)), self.attributes(), m_array=self.m) def resample(self, max_len): new_coords = [] new_m = [] coords = list(self.coords()) new_coords.append(coords[0]) new_m.append(self.m[0]) for i in range(self.nb_points() - 1): first_point, second_point = coords[i], coords[i + 1] segment = OpenPolyline([first_point, second_point]) nb_segments = int(np.ceil(segment.length / max_len)) inv_nb_segments = 1 / nb_segments first_m, second_m = self.m[i], self.m[i + 1] if first_m is None or second_m is None: interpolate_m = False else: interpolate_m = True for j in range(1, nb_segments): new_point = list( segment.interpolate(j * inv_nb_segments, normalized=True).coords)[0] new_coords.append(new_point) if interpolate_m: m = ((1 - j) * first_m + j * second_m) * inv_nb_segments new_m.append(m) else: new_m.append(None) new_coords.append(second_point) new_m.append(second_m) return Polyline(new_coords, self.attributes(), m_array=new_m) def __repr__(self): return "%sPolyline with %i vertices" % ('Closed ' if self.is_closed() else '', len(self.coords()))
def rings2geojson(rings): """Check for holes in the ring and fill them.""" outer_rings = [] holes = [] x = None # iterable outer_ring = None # current outer ring being evaluated hole = None # current hole being evaluated for ring in rings: if not all(np.isclose(ring[0], ring[-1])): ring.append(ring[0]) if len(ring) < 4: continue total = sum((pt2[0] - pt1[0]) * (pt2[1] + pt1[1]) for pt1, pt2 in zip(ring[:-1], ring[1:])) # Clock-wise check if total >= 0: outer_rings.append([ ring[::-1] ]) # wind outer rings counterclockwise for RFC 7946 compliance else: holes.append( ring[::-1] ) # wind inner rings clockwise for RFC 7946 compliance uncontained_holes = [] # while there are holes left... while holes: # pop a hole off out stack hole = holes.pop() # loop over all outer rings and see if they contain our hole. contained = False x = len(outer_rings) - 1 while x >= 0: outer_ring = outer_rings[x][0] l1, l2 = LineString(outer_ring), LineString(hole) p2 = Point(hole[0]) intersects = l1.intersects(l2) contains = l1.contains(p2) if not intersects and contains: # the hole is contained push it into our polygon outer_rings[x].append(hole) contained = True break x = x - 1 # ring is not contained in any outer ring # sometimes this happens https://github.com/Esri/esri-leaflet/issues/320 if not contained: uncontained_holes.append(hole) # if we couldn't match any holes using contains we can try intersects... while uncontained_holes: # pop a hole off out stack hole = uncontained_holes.pop() # loop over all outer rings and see if any intersect our hole. intersects = False x = len(outer_rings) - 1 while x >= 0: outer_ring = outer_rings[x][0] l1, l2 = LineString(outer_ring), LineString(hole) intersects = l1.intersects(l2) if intersects: # the hole is contained push it into our polygon outer_rings[x].append(hole) intersects = True break x = x - 1 if not intersects: outer_rings.append([hole[::-1]]) if len(outer_rings) == 1: return {"type": "Polygon", "coordinates": outer_rings[0]} return {"type": "MultiPolygon", "coordinates": outer_rings}
def get_ex_gyms(): ex_gyms = [] parks = get_all_parks() try: ex_gyms = load_pickle('ex_gyms', raise_exception=True) except (FileNotFoundError, TypeError, KeyError): for g in get_gym_markers(): g['id'] = 'ex-' + g['id'] gym_point = Point(g['lat'], g['lon']) cell = Polygon(get_s2_cell_as_polygon(g['lat'], g['lon'], level=20)) # s2 lvl 20 sponsor_value = 'park' if g['sponsor'] == 7: sponsor_value = 'starbucks' ex_gyms.append({ 'id': g['id'], 'external_id': g['external_id'], 'fort_id': g['fort_id'], 'name': g['gym_name'], 'lat': g['lat'], 'lon': g['lon'], 'sponsor': sponsor_value }) if g['sponsor'] == 9: sponsor_value = 'sprint' ex_gyms.append({ 'id': g['id'], 'external_id': g['external_id'], 'fort_id': g['fort_id'], 'name': g['gym_name'], 'lat': g['lat'], 'lon': g['lon'], 'sponsor': sponsor_value }) for p in parks: coords = p['coords'] # osm polygon can be a line if len(coords) == 2: shape = LineString(coords) if shape.within(cell.centroid): ex_gyms.append({ 'id': g['id'], 'external_id': g['external_id'], 'fort_id': g['fort_id'], 'name': g['gym_name'], 'lat': g['lat'], 'lon': g['lon'], 'sponsor': sponsor_value }) if len(coords) > 2: shape = Polygon(coords) if shape.contains(cell.centroid): ex_gyms.append({ 'id': g['id'], 'external_id': g['external_id'], 'fort_id': g['fort_id'], 'name': g['gym_name'], 'lat': g['lat'], 'lon': g['lon'], 'sponsor': sponsor_value }) dump_pickle('ex_gyms', ex_gyms) return ex_gyms