コード例 #1
0
    def calculate_graph_layout(self, draw, font):
        text_size = draw.textsize(text=self.label_string, font=font)
        text_width = text_size[0]
        text_height = text_size[1]

        total_width = 0.0
        margin = 2.0
        for key in self.sub_node_map:
            sub_node = self.sub_node_map[key]
            sub_node.calculate_graph_layout(draw, font)
            sub_node.calculate_bounding_box()
            total_width += sub_node.bounding_box.Width() + 2.0 * margin

        location = Vector(-total_width / 2.0 + margin, -2.0 * text_height)
        for key in self.sub_node_map:
            sub_node = self.sub_node_map[key]
            transform = AffineTransform()
            upper_left_corner = Vector(sub_node.bounding_box.min_point.x,
                                       sub_node.bounding_box.max_point.y)
            transform.Translation(location - upper_left_corner)
            sub_node.transform_graph_layout(transform)
            location.x += sub_node.bounding_box.Width() + 2.0 * margin

        self.label_box.min_point = Vector(-text_width / 2.0 - 3.0,
                                          -text_height / 2.0 - 3.0)
        self.label_box.max_point = Vector(text_width / 2.0 + 3.0,
                                          text_height / 2.0 + 3.0)
コード例 #2
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(8, 1.0)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(8, 2.0)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(8, 3.0)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(8, 4.0)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(0.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(4.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(4.0 * math.cos(math.pi / 4.0), 4.0 * math.sin(math.pi / 4)))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        transform = AffineTransform()
        transform.Rotation(Vector(0.0, 0.0), math.pi / 2.0 - math.pi / 8.0)
        for cut_region in self.cut_region_list:
            cut_region.Transform(transform)
コード例 #3
0
 def Render(self, point, arrow_head_length=0.3):
     from OpenGL.GL import glBegin, glEnd, glVertex2f, GL_LINES
     from math2d_affine_transform import AffineTransform
     from math2d_line_segment import LineSegment
     transform = AffineTransform()
     transform.linear_transform.x_axis = self.Normalized()
     transform.linear_transform.y_axis = transform.linear_transform.x_axis.Rotated(
         math.pi / 2.0)
     transform.translation = point
     line_segment_list = []
     head = Vector(self.Length(), 0.0)
     line_segment_list.append(LineSegment(Vector(0.0, 0.0), head))
     if arrow_head_length > 0.0:
         line_segment_list.append(
             LineSegment(
                 head, head + Vector(radius=arrow_head_length,
                                     angle=(7.0 / 8.0) * math.pi)))
         line_segment_list.append(
             LineSegment(
                 head, head + Vector(radius=arrow_head_length,
                                     angle=-(7.0 / 8.0) * math.pi)))
     glBegin(GL_LINES)
     try:
         for line_segment in line_segment_list:
             line_segment = transform * line_segment
             glVertex2f(line_segment.point_a.x, line_segment.point_a.y)
             glVertex2f(line_segment.point_b.x, line_segment.point_b.y)
     finally:
         glEnd()
コード例 #4
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 7.0 * math.sqrt(2.0))
        hole = Polygon()
        hole.MakeRegularPolygon(4, 5.0 * math.sqrt(2.0))
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(3.0, 3.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 7.0 * math.sqrt(2.0))
        hole = Polygon()
        hole.MakeRegularPolygon(4, 5.0 * math.sqrt(2.0))
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(-3.0, -3.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 3.0 * math.sqrt(2.0))
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(0.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #5
0
    def __init__(self):
        super().__init__()

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(0.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(0.0, -3.0))
        sub_region.polygon.vertex_list.append(Vector(3.0, -3.0))
        sub_region.polygon.vertex_list.append(Vector(3.0, 0.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.region = Region()
        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(0.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(0.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 0.0))
        cut_region.region.sub_region_list.append(sub_region)
        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(2.0, -2.0))
        sub_region.polygon.vertex_list.append(Vector(2.0, -3.0))
        sub_region.polygon.vertex_list.append(Vector(3.0, -3.0))
        sub_region.polygon.vertex_list.append(Vector(3.0, -2.0))
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 2.0))
        sub_region.polygon.vertex_list.append(Vector(-2.0, 2.0))
        sub_region.polygon.vertex_list.append(Vector(-2.0, -1.0))
        hole = Polygon()
        hole.vertex_list.append(Vector(0.0, 0.0))
        hole.vertex_list.append(Vector(0.0, 1.0))
        hole.vertex_list.append(Vector(-1.0, 1.0))
        hole.vertex_list.append(Vector(-1.0, 0.0))
        sub_region.hole_list.append(hole)
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        transform = AffineTransform()
        transform.Rotation(Vector(0.0, 0.0), math.pi / 4.0)
        for cut_region in self.cut_region_list:
            cut_region.Transform(transform)
コード例 #6
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(5, 5.0)
        hole = Polygon()
        hole.MakeRegularPolygon(5, 4.0)
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(5, 3.0)
        hole = Polygon()
        hole.MakeRegularPolygon(5, 2.0)
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        self.cut_region_list.append(cut_region)

        # This is almost like puzzle 4, but with a subtle difference.
        cut_region = CutRegion()
        cut_region.GenerateRectangle(5.0, 1.0)
        transform = AffineTransform()
        transform.translation = Vector(-3.0, 0.0)
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #7
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(5, 5.0)
        hole = Polygon()
        hole.MakeRegularPolygon(5, 4.0)
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(5, 3.0)
        hole = Polygon()
        hole.MakeRegularPolygon(5, 2.0)
        cut_region.region.sub_region_list[0].hole_list.append(hole)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRectangle(5.0, 1.0)
        transform = AffineTransform()
        transform.translation = Vector(3.5 * math.cos(math.pi * 4.0 / 5.0),
                                       0.0)
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #8
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 3.0 * math.sqrt(2.0))
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(0.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, math.sqrt(2.0))
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(-1.5, -1.5))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, math.sqrt(2.0))
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 4.0, Vector(3.0, 3.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #9
0
    def __init__(self):
        super().__init__()
        
        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(3, 4.0)
        transform = AffineTransform()
        transform.Translation(Vector(-2.5, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(3, 4.0)
        transform = AffineTransform()
        transform.RigidBodyMotion(math.pi / 3.0, Vector(2.5, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #10
0
    def __init__(self):
        super().__init__()

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 3.0)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 3.5)
        transform = AffineTransform()
        transform.RigidBodyMotion(0.0, Vector(-4.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        cut_region = CutRegion()
        cut_region.GenerateRegularPolygon(4, 3.0)
        transform = AffineTransform()
        transform.RigidBodyMotion(0.0, Vector(4.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)
コード例 #11
0
    def __init__(self):
        super().__init__()

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        transform = AffineTransform()
        transform.Translation(Vector(2.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        transform = AffineTransform()
        transform.Translation(Vector(-2.0, 0.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        transform = AffineTransform()
        transform.Translation(Vector(2.0, -2.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, -1.0))
        sub_region.polygon.vertex_list.append(Vector(1.0, 1.0))
        sub_region.polygon.vertex_list.append(Vector(-1.0, 1.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        transform = AffineTransform()
        transform.Translation(Vector(-2.0, 2.0))
        cut_region.Transform(transform)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(-2.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(2.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(2.0, -4.0))
        sub_region.polygon.vertex_list.append(Vector(4.0, -4.0))
        sub_region.polygon.vertex_list.append(Vector(4.0, 2.0))
        sub_region.polygon.vertex_list.append(Vector(-2.0, 2.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)

        sub_region = SubRegion()
        sub_region.polygon.vertex_list.append(Vector(2.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(-2.0, 0.0))
        sub_region.polygon.vertex_list.append(Vector(-2.0, 4.0))
        sub_region.polygon.vertex_list.append(Vector(-4.0, 4.0))
        sub_region.polygon.vertex_list.append(Vector(-4.0, -2.0))
        sub_region.polygon.vertex_list.append(Vector(2.0, -2.0))
        cut_region = CutRegion()
        cut_region.region = Region()
        cut_region.region.sub_region_list.append(sub_region)
        self.cut_region_list.append(cut_region)
コード例 #12
0
    def GenerateLineMesh(self, thickness=0.5, epsilon=1e-7):
        half_thickness = thickness / 2.0
        from math2d_tri_mesh import TriangleMesh, Triangle
        from math2d_polygon import Polygon
        from math2d_affine_transform import AffineTransform
        mesh = TriangleMesh()

        def SortKey(vector):
            angle = Vector(1.0, 0.0).SignedAngleBetween(vector)
            if angle < 0.0:
                angle += 2.0 * math.pi
            return angle

        polygon_list = []
        for i in range(len(self.vertex_list)):
            center = self.vertex_list[i]
            vector_list = []
            adj_list = self.FindAllAdjacencies(i,
                                               ignore_direction=True,
                                               vertices=True)
            for j in adj_list:
                vector_list.append(self.vertex_list[j] - center)
            vector_list.sort(key=SortKey)
            polygon = Polygon()
            for j in range(len(vector_list)):
                vector_a = vector_list[j]
                vector_b = vector_list[(j + 1) % len(vector_list)]
                angle = vector_a.SignedAngleBetween(vector_b)
                if angle < 0.0:
                    angle += 2.0 * math.pi
                if math.fabs(angle - math.pi) < epsilon or angle < math.pi:
                    affine_transform = AffineTransform()
                    affine_transform.translation = center
                    affine_transform.linear_transform.x_axis = vector_a.Normalized(
                    )
                    affine_transform.linear_transform.y_axis = affine_transform.linear_transform.x_axis.RotatedCCW90(
                    )
                    if math.fabs(angle - math.pi) < epsilon:
                        length = 0.0
                    else:
                        length = half_thickness / math.tan(angle / 2.0)
                    point = affine_transform * Vector(length, half_thickness)
                    polygon.vertex_list.append(point)
                else:
                    # Here we might create a rounded joint or something fancy, but this is good for now.
                    polygon.vertex_list.append(vector_a.Normalized(
                    ).RotatedCCW90().Scaled(half_thickness) + center)
                    polygon.vertex_list.append(vector_b.Normalized(
                    ).RotatedCW90().Scaled(half_thickness) + center)
            polygon.Tessellate()
            mesh.AddMesh(polygon.mesh)
            polygon_list.append(polygon)
        for edge in self.edge_list:
            center_a = self.vertex_list[edge[0]]
            center_b = self.vertex_list[edge[1]]
            line_segment = LineSegment(center_a, center_b)

            def FindEdgeSegment(polygon):
                for edge_segment in polygon.GenerateLineSegments():
                    point = edge_segment.IntersectWith(line_segment)
                    if point is not None:
                        return edge_segment
                else:
                    raise Exception('Failed to find line quad end.')

            polygon_a = polygon_list[edge[0]]
            polygon_b = polygon_list[edge[1]]
            edge_segment_a = FindEdgeSegment(polygon_a)
            edge_segment_b = FindEdgeSegment(polygon_b)
            triangle_a = Triangle(edge_segment_a.point_a,
                                  edge_segment_b.point_b,
                                  edge_segment_b.point_a)
            triangle_b = Triangle(edge_segment_a.point_a,
                                  edge_segment_b.point_a,
                                  edge_segment_a.point_b)
            area_a = triangle_a.Area()
            area_b = triangle_b.Area()
            if area_a < 0.0 or area_b < 0.0:
                raise Exception('Miscalculated line quad triangles.')
            mesh.AddTriangle(triangle_a)
            mesh.AddTriangle(triangle_b)
        return mesh
コード例 #13
0
    def GenerateSymmetries(self):
        reflection_list = []
        center_reflection_list = []
        center = self.AveragePoint()
        for i in range(len(self.point_list)):
            for j in range(i + 1, len(self.point_list)):
                line_segment = LineSegment(self.point_list[i],
                                           self.point_list[j])
                mid_point = line_segment.Lerp(0.5)
                normal = line_segment.Direction().Normalized().RotatedCCW90()
                reflection = AffineTransform()
                reflection.Reflection(mid_point, normal)
                center_reflected = reflection.Transform(center)
                if center_reflected.IsPoint(center):
                    center_reflection_list.append({
                        'reflection': reflection,
                        'normal': normal
                    })
                is_symmetry, total_error = self.IsSymmetry(reflection)
                if is_symmetry:
                    new_entry = {
                        'reflection': reflection,
                        'total_error': total_error,
                        'center': mid_point,
                        'normal': normal
                    }
                    for k, entry in enumerate(reflection_list):
                        if entry['reflection'].IsTransform(reflection):
                            if entry['total_error'] > total_error:
                                reflection_list[k] = new_entry
                            break
                    else:
                        reflection_list.append(new_entry)

        # Rotations are just double-reflections.  We return here a CCW rotational symmetry that generates
        # the sub-group of rotational symmetries of the overall group of symmetries of the cloud.  We also
        # return its inverse for convenience.  Of course, not all point clouds have any rotational symmetry.
        epsilon = 1e-7

        def SortKey(entry):
            if entry['normal'].y <= -epsilon:
                entry['normal'] = -entry['normal']
            angle = Vector(1.0, 0.0).SignedAngleBetween(entry['normal'])
            if angle < 0.0:
                angle += 2.0 * math.pi
            return angle

        ccw_rotation = None
        cw_rotation = None
        if len(reflection_list) >= 2:
            reflection_list.sort(key=SortKey)
            # Any 2 consecutive axes should be as close in angle between each other as possible.
            reflection_a = reflection_list[0]['reflection']
            reflection_b = reflection_list[1]['reflection']
            ccw_rotation = reflection_a * reflection_b
            cw_rotation = reflection_b * reflection_a
            # The following are just sanity checks.
            is_symmetry, total_error = self.IsSymmetry(ccw_rotation)
            if not is_symmetry:
                raise Exception('Failed to generate CCW rotational symmetry.')
            is_symmetry, total_error = self.IsSymmetry(cw_rotation)
            if not is_symmetry:
                raise Exception('Failed to generate CW rotational symmetry.')
        elif len(reflection_list) == 1:
            # If we found exactly one reflection, then I believe the cloud has no rotational symmetry.
            # Note that the identity transform is not considered a symmetry.
            pass
        else:
            # If we found no reflective symmetry, the cloud may still have rotational symmetry.
            # Furthermore, if it does, it must rotate about the average point.  I think there is a way
            # to prove this using strong induction.  Note that the statement holds for all point-clouds
            # made from vertices taken from regular polygons.  Now for any given point-cloud with any
            # given rotational symmetry, consider 1 point of that cloud.  Removing that point along
            # with the minimum number of other points necessary to keep the given rotational symmetry,
            # we must remove points making up a regular polygon's vertices.  By inductive hypothesis,
            # the remaining cloud has its average point at the center of the rotational symmetry.  Now
            # see that adding the removed points back does not change the average point of the cloud.
            # Is it true that every line of symmetry of the cloud contains the average point?  I believe
            # the answer is yes.  Take any point-cloud with a reflective symmetry and consider all but
            # 2 of its points that reflect into one another along that symmetry.  If the cloud were just
            # these 2 points, then the average point is on the line of symmetry.  Now notice that as you
            # add back points by pairs, each pair reflecting into one another, the average point of the
            # cloud remains on the line of symmetry.
            center_reflection_list.sort(key=SortKey)
            found = False
            for i in range(len(center_reflection_list)):
                for j in range(i + 1, len(center_reflection_list)):
                    ccw_rotation = center_reflection_list[i][
                        'reflection'] * center_reflection_list[j]['reflection']
                    is_symmetry, total_error = self.IsSymmetry(ccw_rotation)
                    if is_symmetry:
                        # By stopping at the first one we find, we should be minimizing the angle of rotation.
                        found = True
                        break
                if found:
                    break
            if found:
                cw_rotation = ccw_rotation.Inverted()
            else:
                ccw_rotation = None

        return reflection_list, ccw_rotation, cw_rotation