예제 #1
0
 def test_four_line_sets_should_result(self):
     lines = [LineSegment.from_points([Point(0, 0), Point(1, 0)]), \
              LineSegment.from_points([Point(0.5, 1), Point(1.5, 1)])]
     traj_lines = [TrajectoryLineSegment(lines[0], 0), \
                   TrajectoryLineSegment(lines[1], 1)]
     res = get_representative_trajectory_average_inputs(trajectory_line_segments=traj_lines, \
                                                       min_prev_dist=0.5, min_lines=1)
     expected = 4
     self.assertEquals(len(res), expected)
예제 #2
0
 def test_two_short_line_endpoints_get_picked(self):
     lines = [LineSegment.from_points([Point(0, 0), Point(1, 0)]), \
              LineSegment.from_points([Point(0, 1), Point(1, 1)])]
     traj_lines = [TrajectoryLineSegment(lines[0], 0), \
                   TrajectoryLineSegment(lines[1], 1)]
     res = get_representative_trajectory_average_inputs(trajectory_line_segments=traj_lines, \
                                                       min_prev_dist=1, min_lines=2)
     expected = 2
     self.assertEquals(len(res), expected)
예제 #3
0
    def from_points(cls, points: Iterable[Tuple[Point, Point]]) -> "Track":
        segments: List[TrackSegment] = []
        for (s1, s2), (e1, e2) in pairwise(points):
            segments.append(
                TrackSegment(
                    Wall(LineSegment.from_points((s1, e1))),
                    Wall(LineSegment.from_points((s2, e2))),
                )
            )

        return cls(segments)
예제 #4
0
파일: relation.py 프로젝트: marcovzla/bolt
    def get_orientation_ray(cls, perspective, landmark):

        standard_direction = Vec2(0,1)

        top_primary_axes = landmark.get_top_parent().get_primary_axes()

        our_axis = None
        for axis in top_primary_axes:
            if axis.contains_point(perspective):
                our_axis = axis
        assert( our_axis != None )

        new_axis = our_axis.parallel(landmark.representation.middle)
        new_perspective = new_axis.project(perspective)

        p_segment = LineSegment.from_points( [new_perspective, landmark.representation.middle] )

        angle = standard_direction.angle_to(p_segment.vector)
        rotation = Affine.rotation(angle)
        o = [cls.orientation]
        rotation.itransform(o)
        direction = o[0]
        ori_ray = Ray(p_segment.end, direction)

        return ori_ray
예제 #5
0
파일: landmark.py 프로젝트: wrightjb/bolt
    def __init__(self,
                 orientation='height',
                 line=LineSegment.from_points([Vec2(0, 0),
                                               Vec2(1, 0)]),
                 alt_of=None):
        super(LineRepresentation, self).__init__(alt_of)
        self.line = line
        # extend the LineSegment to include a bounding_box field, planar doesn't have that originally
        self.line.bounding_box = BoundingBox.from_points(self.line.points)
        self.num_dim = 1
        self.middle = line.mid
        self.alt_representations = [PointRepresentation(self.line.mid, self)]

        classes = [Landmark.END, Landmark.MIDDLE, Landmark.END] if orientation == 'height' \
             else [Landmark.SIDE, Landmark.MIDDLE, Landmark.SIDE]

        self.landmarks = {
            'start':
            Landmark('start', PointRepresentation(self.line.start), self,
                     classes[0]),
            'end':
            Landmark('end', PointRepresentation(self.line.end), self,
                     classes[2]),
            'middle':
            Landmark('middle', PointRepresentation(self.line.mid), self,
                     classes[1]),
        }
예제 #6
0
    def get_orientation_ray(cls, perspective, landmark):

        standard_direction = Vec2(0, 1)

        top_primary_axes = landmark.get_top_parent().get_primary_axes()

        our_axis = None
        for axis in top_primary_axes:
            if axis.contains_point(perspective):
                our_axis = axis
        assert (our_axis != None)

        new_axis = our_axis.parallel(landmark.representation.middle)
        new_perspective = new_axis.project(perspective)

        p_segment = LineSegment.from_points(
            [new_perspective, landmark.representation.middle])

        angle = standard_direction.angle_to(p_segment.vector)
        rotation = Affine.rotation(angle)
        o = [cls.orientation]
        rotation.itransform(o)
        direction = o[0]
        ori_ray = Ray(p_segment.end, direction)

        return ori_ray
예제 #7
0
파일: relation.py 프로젝트: echan3/bolt
    def __init__(self, perspective, landmark, poi, orientation):
        super(OrientationRelation, self).__init__(perspective, landmark, poi)
        self.standard = Vec2(0,1)
        self.orientation = orientation

        top_primary_axes = landmark.get_top_parent().get_primary_axes()

        our_axis = None
        for axis in top_primary_axes:
            if axis.contains_point(perspective):
                our_axis = axis
        assert( our_axis != None )

        new_axis = our_axis.parallel(self.landmark.representation.middle)
        new_perspective = new_axis.project(perspective)

        p_segment = LineSegment.from_points( [new_perspective, self.landmark.representation.middle] )

        angle = self.standard.angle_to(p_segment.vector)
        rotation = Affine.rotation(angle)
        o = [self.orientation]
        rotation.itransform(o)
        direction = o[0]
        self.ori_ray = Ray(p_segment.end, direction)
        self.projected = self.ori_ray.line.project(poi)

        self.distance = self.ori_ray.start.distance_to(self.projected)
        self.measurement = Measurement(self.distance, required=False)
예제 #8
0
def get_line_features(lmk):
       ps = [Vec2(0, 0), Vec2(1, 0)]
       ls = LineSegment.from_points(ps)

       dist_start = lmk.distance_to(ls.start)
       dist_end = lmk.distance_to(ls.end)
       dist_mid = lmk.distance_to(ls.mid)

       tl = Line.from_normal(ls.direction, ls.start.x)
       dir_start = -1 if tl.point_left(lmk) else 1

       tl = Line.from_normal(ls.direction, ls.end.x)
       dir_end = -1 if tl.point_left(lmk) else 1

       tl = Line.from_normal(ls.direction, ls.mid.x)
       dir_mid = -1 if tl.point_left(lmk) else 1

       return {
               'dist_start': dist_start,
               'dist_mid': dist_mid,
               'dist_end': dist_end,
               'dir_start': dir_start,
               'dir_mid': dir_mid,
               'dir_end': dir_end,
              }
예제 #9
0
    def __init__(self, lmk_group, alt_of=None):
        centers = np.array([lmk.representation.middle for lmk in lmk_group])
        x = centers[:,0]
        y = centers[:,1]
        A = np.vstack([x, np.ones(len(x))]).T
        m, c = np.linalg.lstsq(A, y)[0]
        lxy = zip(x, m*x + c)
        points = [Vec2(px,py) for px,py in sorted(lxy)]

        super(GroupLineRepresentation, self).__init__(line=LineSegment.from_points(points),alt_of=alt_of)

        sorted_idx = sorted(range(len(lxy)), key=lxy.__getitem__)
        self.landmark_group = [lmk_group[idx] for idx in sorted_idx]
예제 #10
0
 def create_line(self,
                 horizontal_start,
                 horizontal_end,
                 line_set_ids,
                 trajectory_id,
                 orig_pos=None):
     if orig_pos == None:
         orig_pos = random.randint(0, 1000)
     return {'trajectory_line_segment': \
             TrajectoryLineSegment(LineSegment.from_points([Point(horizontal_start, random.randint(0, 1000)), \
                                                            Point(horizontal_end, random.randint(0, 1000))]), \
                                   trajectory_id, orig_pos), \
             'line_set_ids': line_set_ids}
예제 #11
0
파일: landmark.py 프로젝트: marcovzla/bolt
    def __init__(self, lmk_group, alt_of=None):
        centers = np.array([lmk.representation.middle for lmk in lmk_group])
        x = centers[:,0]
        y = centers[:,1]
        A = np.vstack([x, np.ones(len(x))]).T
        m, c = np.linalg.lstsq(A, y)[0]
        lxy = zip(x, m*x + c)
        points = [Vec2(px,py) for px,py in sorted(lxy)]

        super(GroupLineRepresentation, self).__init__(line=LineSegment.from_points(points),alt_of=alt_of)

        sorted_idx = sorted(range(len(lxy)), key=lxy.__getitem__)
        self.landmark_group = [lmk_group[idx] for idx in sorted_idx]
예제 #12
0
파일: landmark.py 프로젝트: marcovzla/bolt
    def __init__(self, orientation='height', line=LineSegment.from_points([Vec2(0, 0), Vec2(1, 0)]), alt_of=None):
        super(LineRepresentation, self).__init__(alt_of)
        self.line = line
        # extend the LineSegment to include a bounding_box field, planar doesn't have that originally
        self.line.bounding_box = BoundingBox.from_points(self.line.points)
        self.num_dim = 1
        self.middle = line.mid
        self.alt_representations = [PointRepresentation(self.line.mid, self)]

        classes = [Landmark.END, Landmark.MIDDLE, Landmark.END] if orientation == 'height' \
             else [Landmark.SIDE, Landmark.MIDDLE, Landmark.SIDE]

        self.landmarks = {
            'start':  Landmark('start',  PointRepresentation(self.line.start), self, classes[0]),
            'end':    Landmark('end',    PointRepresentation(self.line.end),   self, classes[2]),
            'middle': Landmark('middle', PointRepresentation(self.line.mid),   self, classes[1]),
        }
예제 #13
0
파일: landmark.py 프로젝트: dpfried/bolt
    def __init__(self, ratio=None, line=LineSegment.from_points([Vec2(0, 0), Vec2(1, 0)]), alt_of=None):
        super(LineRepresentation, self).__init__(alt_of)
        self.line = line
        # extend the LineSegment to include a bounding_box field, planar doesn't have that originally
        self.line.bounding_box = BoundingBox.from_points(self.line.points)
        self.num_dim = 1
        self.middle = line.mid
        self.alt_representations = [PointRepresentation(self.line.mid, self)]
        self.ratio_limit = 2


        if ratio is None or ratio >= self.ratio_limit:
            self.landmarks = {
                'start':  Landmark('start',  PointRepresentation(self.line.start), self, Landmark.END),
                'middle': Landmark('middle', PointRepresentation(self.line.mid),   self, Landmark.MIDDLE),
                'end':    Landmark('end',    PointRepresentation(self.line.end),   self, Landmark.END),
            }
        else:
            self.landmarks = {
                'start':  Landmark('start',  PointRepresentation(self.line.start), self, Landmark.SIDE),
                'end':    Landmark('end',    PointRepresentation(self.line.end),   self, Landmark.SIDE)
            }
예제 #14
0
    def __init__(self, ratio=None, line=LineSegment.from_points([Vec2(0, 0), Vec2(1, 0)]), alt_of=None):
        super(LineRepresentation, self).__init__(alt_of)
        self.ratio = ratio
        self.line = line
        # extend the LineSegment to include a bounding_box field, planar doesn't have that originally
        self.line.bounding_box = BoundingBox.from_points(self.line.points)
        self.num_dim = 1
        self.middle = line.mid
        self.alt_representations = [PointRepresentation(self.line.mid, self)]
        self.ratio_limit = 2

        if ratio is None or ratio >= self.ratio_limit:
            self.landmarks = {
                'start':  Landmark('start',  PointRepresentation(self.line.start), self, Landmark.END),
                'middle': Landmark('middle', PointRepresentation(self.line.mid),   self, Landmark.MIDDLE),
                'end':    Landmark('end',    PointRepresentation(self.line.end),   self, Landmark.END),
            }
        else:
            self.landmarks = {
                'start':  Landmark('start',  PointRepresentation(self.line.start), self, Landmark.SIDE),
                'end':    Landmark('end',    PointRepresentation(self.line.end),   self, Landmark.SIDE)
            }
예제 #15
0
파일: landmark.py 프로젝트: marcovzla/bolt
    def __init__(self, rect=BoundingBox([Vec2(0, 0), Vec2(1, 2)]),
                 landmarks_to_get=['ll_corner','ur_corner','lr_corner','ul_corner','middle','l_edge','r_edge','n_edge','f_edge','l_surf','r_surf','n_surf','f_surf','m_surf'],
                 alt_of=None):
        super(RectangleRepresentation, self).__init__(alt_of)
        self.rect = rect
        self.num_dim = 2
        self.middle = rect.center
        self.alt_representations = [LineRepresentation('width',
                                                        LineSegment.from_points([Vec2(self.rect.min_point.x, self.rect.center.y),
                                                                                 Vec2(self.rect.max_point.x, self.rect.center.y)],),
                                                        self),
                                    LineRepresentation('height',
                                                        LineSegment.from_points([Vec2(self.rect.center.x, self.rect.min_point.y),
                                                                                 Vec2(self.rect.center.x, self.rect.max_point.y)]),
                                                        self)]

        lrc = Vec2(self.rect.min_point.x + self.rect.width, self.rect.min_point.y)
        ulc = Vec2(self.rect.max_point.x - self.rect.width, self.rect.max_point.y)

        landmark_constructors = {
                'll_corner': '''Landmark('ll_corner', PointRepresentation(self.rect.min_point), self, Landmark.CORNER)''',
                'ur_corner': '''Landmark('ur_corner', PointRepresentation(self.rect.max_point), self, Landmark.CORNER)''',
                'lr_corner': '''Landmark('lr_corner', PointRepresentation(lrc), self, Landmark.CORNER)''',
                'ul_corner': '''Landmark('ul_corner', PointRepresentation(ulc), self, Landmark.CORNER)''',
                'middle':    '''Landmark('middle',    PointRepresentation(self.rect.center), self, Landmark.MIDDLE)''',
                'l_edge':    '''Landmark('l_edge',    LineRepresentation('height', LineSegment.from_points([self.rect.min_point, ulc])), self, Landmark.EDGE)''',
                'r_edge':    '''Landmark('r_edge',    LineRepresentation('height', LineSegment.from_points([lrc, self.rect.max_point])), self, Landmark.EDGE)''',
                'n_edge':    '''Landmark('n_edge',    LineRepresentation('width', LineSegment.from_points([self.rect.min_point, lrc])), self, Landmark.EDGE)''',
                'f_edge':    '''Landmark('f_edge',    LineRepresentation('width', LineSegment.from_points([ulc, self.rect.max_point])), self, Landmark.EDGE)''',

                'l_surf':    '''Landmark('l_surf',    SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                       Vec2(rect.min_point.x+rect.width/2.0,
                                                                                            rect.max_point.y)]),
                                                                          landmarks_to_get=['ll_corner','ul_corner','l_edge']),
                                      self, Landmark.HALF)''',
                'r_surf':    '''Landmark('r_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x+rect.width/2.0,
                                                                                            rect.min_point.y),
                                                                                       rect.max_point]),
                                                                          landmarks_to_get=['lr_corner','ur_corner','r_edge']),
                                      self, Landmark.HALF)''',
                'n_surf':    '''Landmark('n_surf',    SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                       Vec2(rect.max_point.x,
                                                                                            rect.min_point.y+rect.height/2.0)]),
                                                                          landmarks_to_get=['ll_corner','lr_corner','n_edge']),
                                      self, Landmark.HALF)''',
                'f_surf':    '''Landmark('f_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x,
                                                                                            rect.min_point.y+rect.height/2.0),
                                                                                       rect.max_point]),
                                                                          landmarks_to_get=['ul_corner','ur_corner','f_edge']),
                                      self, Landmark.HALF)''',

                'm_surf':    '''Landmark('m_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x+rect.width/4.0,
                                                                                            rect.min_point.y+rect.height/4.0),
                                                                                       Vec2(rect.max_point.x-rect.width/4.0,
                                                                                            rect.max_point.y-rect.height/4.0)])), self, Landmark.MIDDLE)''',
        }

        self.landmarks = {}
        for lmk_name in landmarks_to_get:
            if lmk_name in landmark_constructors:
                self.landmarks[lmk_name] = eval(landmark_constructors[lmk_name])
예제 #16
0
def linesegment_from_dict(dikt):
    return LineSegment.from_points([vec2_from_dict(v) for v in dikt['points']])
예제 #17
0
def linesegment_from_dict(dikt):
    return LineSegment.from_points([vec2_from_dict(v) for v in dikt['points']])
예제 #18
0
 def back_wall(self) -> Wall:
     return Wall(
         LineSegment.from_points([
             self.left_wall.line_segment.start,
             self.right_wall.line_segment.start
         ]))
예제 #19
0
def get_line_segment_from_points(point_a, point_b):
    return LineSegmentWrapper(LineSegment.from_points([point_a, point_b]))
예제 #20
0
    def __init__(self, rect=BoundingBox([Vec2(0, 0), Vec2(1, 2)]),
                 landmarks_to_get=['ll_corner','ur_corner','lr_corner','ul_corner',
                                   'middle',
                                   'l_edge','r_edge','n_edge','f_edge',
                                   'l_surf','r_surf','n_surf','f_surf',
                                   'm_surf',
                                   'll_corner_surf','ur_corner_surf','lr_corner_surf','ul_corner_surf',
                                   'l_edge_surf','r_edge_surf','n_edge_surf','f_edge_surf'],
                 alt_of=None):
        super(RectangleRepresentation, self).__init__(alt_of)
        self.rect = rect
        self.num_dim = 2
        self.middle = rect.center
        self.landmarks_to_get = landmarks_to_get
        vert_ratio = self.rect.height / self.rect.width
        horiz_ratio = self.rect.width / self.rect.height
        self.alt_representations = [LineRepresentation( horiz_ratio,
                                                        LineSegment.from_points([Vec2(self.rect.min_point.x, self.rect.center.y),
                                                                                 Vec2(self.rect.max_point.x, self.rect.center.y)],),
                                                        self),
                                    LineRepresentation( vert_ratio,
                                                        LineSegment.from_points([Vec2(self.rect.center.x, self.rect.min_point.y),
                                                                                 Vec2(self.rect.center.x, self.rect.max_point.y)]),
                                                        self)]

        lrc = Vec2(self.rect.min_point.x + self.rect.width, self.rect.min_point.y)
        ulc = Vec2(self.rect.max_point.x - self.rect.width, self.rect.max_point.y)

        min_dimension = min(self.rect.height,self.rect.width)
        landmark_constructors = {
                'll_corner': '''Landmark('ll_corner', PointRepresentation(self.rect.min_point), self, Landmark.CORNER)''',
                'ur_corner': '''Landmark('ur_corner', PointRepresentation(self.rect.max_point), self, Landmark.CORNER)''',
                'lr_corner': '''Landmark('lr_corner', PointRepresentation(lrc), self, Landmark.CORNER)''',
                'ul_corner': '''Landmark('ul_corner', PointRepresentation(ulc), self, Landmark.CORNER)''',
                'middle':    '''Landmark('middle',    PointRepresentation(self.rect.center), self, Landmark.MIDDLE)''',
                'l_edge_surf':    '''Landmark('l_edge',    LineRepresentation(vert_ratio, LineSegment.from_points([self.rect.min_point, ulc])), self, Landmark.EDGE)''',
                'r_edge':    '''Landmark('r_edge',    LineRepresentation(vert_ratio, LineSegment.from_points([lrc, self.rect.max_point])), self, Landmark.EDGE)''',
                'n_edge':    '''Landmark('n_edge',    LineRepresentation(horiz_ratio, LineSegment.from_points([self.rect.min_point, lrc])), self, Landmark.EDGE)''',
                'f_edge':    '''Landmark('f_edge',    LineRepresentation(horiz_ratio, LineSegment.from_points([ulc, self.rect.max_point])), self, Landmark.EDGE)''',

                'l_surf':    '''Landmark('l_surf',    SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                       Vec2(rect.min_point.x+rect.width/2.0,
                                                                                            rect.max_point.y)]),
                                                                          landmarks_to_get=['ll_corner','ul_corner','l_edge']),
                                      self, Landmark.HALF)''',
                'r_surf':    '''Landmark('r_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x+rect.width/2.0,
                                                                                            rect.min_point.y),
                                                                                       rect.max_point]),
                                                                          landmarks_to_get=['lr_corner','ur_corner','r_edge']),
                                      self, Landmark.HALF)''',
                'n_surf':    '''Landmark('n_surf',    SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                       Vec2(rect.max_point.x,
                                                                                            rect.min_point.y+rect.height/2.0)]),
                                                                          landmarks_to_get=['ll_corner','lr_corner','n_edge']),
                                      self, Landmark.HALF)''',
                'f_surf':    '''Landmark('f_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x,
                                                                                            rect.min_point.y+rect.height/2.0),
                                                                                       rect.max_point]),
                                                                          landmarks_to_get=['ul_corner','ur_corner','f_edge']),
                                      self, Landmark.HALF)''',

                'm_surf':    '''Landmark('m_surf',    SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x+rect.width/4.0,
                                                                                            rect.min_point.y+rect.height/4.0),
                                                                                       Vec2(rect.max_point.x-rect.width/4.0,
                                                                                            rect.max_point.y-rect.height/4.0)])), self, Landmark.MIDDLE)''',
                'll_corner_surf': '''Landmark('ll_corner_surf', SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                                    Vec2(rect.min_point.x+min_dimension/4.0,
                                                                                                         rect.min_point.y+min_dimension/4.0)])), self, Landmark.CORNER)''',
                'ur_corner_surf': '''Landmark('ur_corner_surf', SurfaceRepresentation( BoundingBox([Vec2(rect.max_point.x-min_dimension/4.0,
                                                                                                         rect.max_point.y-min_dimension/4.0),
                                                                                                    rect.max_point])), self, Landmark.CORNER)''',
                'lr_corner_surf': '''Landmark('lr_corner_surf', SurfaceRepresentation( BoundingBox([Vec2(rect.max_point.x-min_dimension/4.0,
                                                                                                         rect.min_point.y),
                                                                                                    Vec2(rect.max_point.x,
                                                                                                         rect.min_point.y+min_dimension/4.0)])), self, Landmark.CORNER)''',
                'ul_corner_surf': '''Landmark('ul_corner_surf', SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x,
                                                                                                         rect.max_point.y-min_dimension/4.0),
                                                                                                    Vec2(rect.min_point.x+min_dimension/4.0,
                                                                                                         rect.max_point.y)])), self, Landmark.CORNER)''',
                'l_edge_surf':    '''Landmark('l_edge_surf', SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                                 Vec2(rect.min_point.x+min_dimension/8.0,
                                                                                                      rect.max_point.y)])), self, Landmark.EDGE)''',
                'r_edge_surf':    '''Landmark('r_edge_surf', SurfaceRepresentation( BoundingBox([Vec2(rect.max_point.x-min_dimension/8.0,
                                                                                                      rect.min_point.y),
                                                                                                 rect.max_point])), self, Landmark.EDGE)''',
                'n_edge_surf':    '''Landmark('n_edge_surf', SurfaceRepresentation( BoundingBox([rect.min_point,
                                                                                                 Vec2(rect.max_point.x,
                                                                                                      rect.min_point.y+min_dimension/8.0)])), self, Landmark.EDGE)''',
                'f_edge_surf':    '''Landmark('f_edge_surf', SurfaceRepresentation( BoundingBox([Vec2(rect.min_point.x,
                                                                                                      rect.max_point.y-min_dimension/8.0),
                                                                                                 rect.max_point])), self, Landmark.EDGE)''',
        }

        self.landmarks = {}
        for lmk_name in landmarks_to_get:
            if lmk_name in landmark_constructors:
                self.landmarks[lmk_name] = eval(landmark_constructors[lmk_name])
예제 #21
0
 def front_wall(self) -> Wall:
     return Wall(
         LineSegment.from_points([
             self.left_wall.line_segment.end,
             self.right_wall.line_segment.end
         ]))
예제 #22
0
파일: landmark.py 프로젝트: marcovzla/bolt
def poly_to_edges(poly):
    edges = []
    for i in range(1, len(poly)):
        edges.append( LineSegment.from_points([poly[i-1],poly[i]]) )
    edges.append( LineSegment.from_points([poly[i],poly[0]]) )
    return edges
예제 #23
0
def poly_to_edges(poly):
    edges = []
    for i in range(1, len(poly)):
        edges.append(LineSegment.from_points([poly[i - 1], poly[i]]))
    edges.append(LineSegment.from_points([poly[i], poly[0]]))
    return edges