def test_create_rnd_frm_corners(self):
     '''Test for RoundedRectangle.from_corners()'''
     rrect = RoundedRectangle.from_corners(0, 1, 2, 4, 5)
     self.assertEqual(rrect.x, 0)
     self.assertEqual(rrect.y, 1)
     self.assertEqual(rrect.width, 2)
     self.assertEqual(rrect.height, 3)
     self.assertEqual(rrect.radius, 5)
 def test_create_new_rounded(self):
     """ Test the creation of a new empty rounded rectangle. """
     rrect = RoundedRectangle(0, 1, 2, 3, 4)
     assert rrect.x == 0
     assert rrect.y == 1
     assert rrect.width == 2
     assert rrect.height == 3
     assert rrect.radius == 4
Exemple #3
0
    def parse_shape(self, shape):
        """ Extract a shape. """
        # pylint: disable=R0914
        # pylint: disable=R0911

        typ = shape.get('type')
        if 'rectangle' == typ:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            height = int(shape.get('height'))
            width = int(shape.get('width'))
            parsed_shape = Rectangle(x, y, width, height)
        elif 'rounded_rectangle' == typ:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            height = int(shape.get('height'))
            width = int(shape.get('width'))
            radius = int(shape.get('radius'))
            parsed_shape = RoundedRectangle(x, y, width, height, radius)
        elif 'arc' == typ:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            start_angle = float(shape.get('start_angle'))
            end_angle = float(shape.get('end_angle'))
            radius = int(shape.get('radius'))
            parsed_shape = Arc(x, y, start_angle, end_angle, radius)
        elif 'circle' == typ:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            radius = int(shape.get('radius'))
            parsed_shape = Circle(x, y, radius)
        elif 'label' == typ:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            rotation = float(shape.get('rotation'))
            text = shape.get('text')
            align = shape.get('align')
            parsed_shape = Label(x, y, text, align, rotation)
        elif 'line' == typ:
            p1 = self.parse_point(shape.get('p1'))
            p2 = self.parse_point(shape.get('p2'))
            parsed_shape = Line(p1, p2)
        elif 'polygon' == typ:
            parsed_shape = Polygon()
            for point in shape.get('points'):
                parsed_shape.add_point(self.parse_point(point))
        elif 'bezier' == typ:
            control1 = self.parse_point(shape.get('control1'))
            control2 = self.parse_point(shape.get('control2'))
            p1 = self.parse_point(shape.get('p1'))
            p2 = self.parse_point(shape.get('p2'))
            parsed_shape = BezierCurve(control1, control2, p1, p2)

        parsed_shape.styles = shape.get('styles') or {}
        parsed_shape.attributes = shape.get('attributes') or {}
        return parsed_shape
    def bodies(self, offset, instance_attributes):
        bodies = []

        attached_layers = self.get_attr('attached_layers', '',
                                        instance_attributes).split(',')
        width = self.get_int_attr('width', 0, instance_attributes)
        height = self.get_int_attr('height', 0, instance_attributes)
        radius = self.get_int_attr('radius', 0, instance_attributes)
        shape_type = self.get_attr('shape', '', instance_attributes)

        pos = Point(self.x, self.y)

        for layer_name in attached_layers:
            layer_name = layer_name
            pad = FBody()
            # invert top/bottom if the footprint is on the bottom of the board
            if offset.side == 'bottom':
                rev_sides = {'top': 'bottom', 'bottom': 'top'}
                layer_name = ' '.join([
                    rev_sides.get(piece, piece)
                    for piece in layer_name.split(' ')
                ])

            if shape_type == 'rectangle':
                pad.add_shape(
                    Rectangle((width / 2), -(height / 2), width, height))
            elif shape_type == 'rounded rectangle':
                pad.add_shape(
                    RoundedRectangle((width / 2), -(height / 2), width, height,
                                     radius))
            elif shape_type == 'circle':
                pad.add_shape(Circle(0, 0, radius))
            else:
                raise ValueError('unexpected shape type for padstack')

            pad.rotate(self.rotation)
            pad.shift(pos.x, pos.y)
            bodies.append((FootprintAttribute(0, 0, 0, False,
                                              layer_name), pad))

        return bodies
    def parse_shape(self, shape):
        """ Extract a shape. """
        # pylint: disable=R0914
        # pylint: disable=R0911

        rotation = shape.get('rotation', 0.0)
        flip_horizontal = shape.get('flip_horizontal', False)

        shape_type = shape.get('type')
        if 'rectangle' == shape_type:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            height = int(shape.get('height'))
            width = int(shape.get('width'))
            parsed_shape = Rectangle(x, y, width, height)
        elif 'rounded_rectangle' == shape_type:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            height = int(shape.get('height'))
            width = int(shape.get('width'))
            radius = int(shape.get('radius'))
            parsed_shape = RoundedRectangle(x, y, width, height, radius)
        elif 'arc' == shape_type:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            start_angle = float(shape.get('start_angle'))
            end_angle = float(shape.get('end_angle'))
            radius = int(shape.get('radius'))
            parsed_shape = Arc(x, y, start_angle, end_angle, radius)
        elif 'circle' == shape_type:
            x = int(shape.get('x'))
            y = int(shape.get('y'))
            radius = int(shape.get('radius'))
            parsed_shape = Circle(x, y, radius)
        elif 'label' == shape_type:
            parsed_shape = self.parse_label(shape)
        elif 'line' == shape_type:
            p1 = self.parse_point(shape.get('p1'))
            p2 = self.parse_point(shape.get('p2'))
            parsed_shape = Line(p1, p2)
        elif 'polygon' == shape_type:
            parsed_shape = Polygon()
            for point in shape.get('points'):
                parsed_shape.add_point(self.parse_point(point))
        elif 'bezier' == shape_type:
            control1 = self.parse_point(shape.get('control1'))
            control2 = self.parse_point(shape.get('control2'))
            p1 = self.parse_point(shape.get('p1'))
            p2 = self.parse_point(shape.get('p2'))
            parsed_shape = BezierCurve(control1, control2, p1, p2)
        elif 'rounded_segment' == shape_type:
            p1 = self.parse_point(shape.get('p1'))
            p2 = self.parse_point(shape.get('p2'))
            width = int(shape.get('width'))
            parsed_shape = RoundedSegment(p1, p2, width)

        parsed_shape.rotation = rotation
        parsed_shape.flip_horizontal = flip_horizontal

        parsed_shape.styles = shape.get('styles') or {}
        parsed_shape.attributes = shape.get('attributes') or {}
        return parsed_shape
    def bodies(self, offset, instance_attributes):
        """ Generated the bodies for the Via with instance attribute overrides. Returns placment attribute and body
            pairs.

        """
        attached_layers = self.get_attr('attached_layers', '',
                                        instance_attributes).split(',')
        internal_diameter = self.get_float_attr('internal_diameter', 0,
                                                instance_attributes)
        plating_shape = self.get_attr('plating_shape', '', instance_attributes)

        # Local vars for use in closures to generate shapes
        # XXX(shamer): The assignment of width and lenght are reversed from the javascript. Not sure why this is.
        plating_width = self.get_float_attr('plating_length', 0,
                                            instance_attributes)
        plating_height = self.get_float_attr('plating_width', 0,
                                             instance_attributes)
        plating_radius = self.get_float_attr('plating_radius', 0,
                                             instance_attributes)
        plating_diameter = self.get_float_attr('plating_diameter', 0,
                                               instance_attributes)

        solder_mask_expansion = self.get_float_attr('solder_mask_expansion', 0,
                                                    instance_attributes)
        #thermal_inner_diameter = self.get_float_attr('thermal_inner_diameter', 0, instance_attributes)
        #thermal_spoke_width = self.get_float_attr('thermal_spoke_width', 0, instance_attributes)
        #antipad_diameter = self.get_float_attr('antipad_diameter', 0, instance_attributes)

        # placment attribute + body pairs making up the generated object
        bodies = []

        pad_pos = Point(self.x, self.y)
        sme_pos = Point(self.x, self.y)

        # Debugging marker for displaying the placment position for generated objects.
        #marker = FBody()
        #marker.add_shape(Circle(pad_pos.x, pad_pos.y, 1000000))
        #bodies.append((FootprintAttribute(0, 0, 0, False, 'top silkscreen'), marker))

        if plating_shape == 'square':
            solder_mask_width = (solder_mask_expansion * 2) + plating_diameter

            create_shape = lambda: Rectangle(
                pad_pos.x, pad_pos.y, plating_diameter, plating_diameter)
            create_solder_mask_expansion = lambda: Rectangle(
                sme_pos.x, sme_pos.y, solder_mask_width, solder_mask_width)

        elif plating_shape == 'circle':
            create_shape = lambda: Circle(pad_pos.x, pad_pos.y,
                                          plating_diameter / 2)

            solder_mask_radius = solder_mask_expansion + (plating_diameter / 2)
            create_solder_mask_expansion = lambda: Circle(
                sme_pos.x, sme_pos.y, solder_mask_radius)

        elif plating_shape == 'rectangle':
            solder_mask_width = (solder_mask_expansion * 2) + plating_width
            solder_mask_height = (solder_mask_expansion * 2) + plating_height

            create_shape = lambda: Rectangle(pad_pos.x, pad_pos.y,
                                             plating_width, plating_height)
            create_solder_mask_expansion = lambda: Rectangle(
                sme_pos.x, sme_pos.y, solder_mask_width, solder_mask_height)

        elif plating_shape == 'rounded rectangle':
            solder_mask_width = (solder_mask_expansion * 2) + plating_width
            solder_mask_height = (solder_mask_expansion * 2) + plating_height

            create_shape = lambda: RoundedRectangle(
                pad_pos.x, pad_pos.y, plating_width, plating_height,
                plating_radius)
            create_solder_mask_expansion = lambda: RoundedRectangle(
                sme_pos.x, sme_pos.y, solder_mask_width, solder_mask_height,
                plating_radius)

        else:
            raise ValueError(
                'unexpected shape for plated through hole "{0}"'.format(
                    plating_shape))

        # cirle of radius 'solder_mask_expansion' + ('plating_diameter' / 2) in the top and bottom silkscreen layers
        solder_mask_radius = solder_mask_expansion + (plating_diameter / 2)
        top_solder_mask = FBody()
        top_solder_mask.add_shape(create_solder_mask_expansion())
        bodies.append((FootprintAttribute(0, 0, 0, False,
                                          'top solder mask'), top_solder_mask))

        bottom_solder_mask = FBody()
        bottom_solder_mask.add_shape(create_solder_mask_expansion())
        bodies.append(
            (FootprintAttribute(0, 0, 0, False,
                                'bottom solder mask'), bottom_solder_mask))

        # circle of diameter 'internal_diameter' on the hole layer
        hole = FBody()
        hole.add_shape(Circle(pad_pos.x, pad_pos.y, internal_diameter / 2))
        bodies.append((FootprintAttribute(0, 0, 0, False, 'hole'), hole))

        # circles of diameter 'plating_diameter' on each connection layer
        for layer_name in attached_layers:
            connected_layer = FBody()
            if layer_name == 'top copper' or layer_name == 'bottom copper':
                connected_layer.add_shape(create_shape())
            else:
                connected_layer.add_shape(
                    Circle(pad_pos.x, pad_pos.y, plating_diameter / 2))
            bodies.append((FootprintAttribute(0, 0, 0, False,
                                              layer_name), connected_layer))

        return bodies
 def test_rrectangle_max_point(self):
     '''Test RoundedRectangle.max_point()'''
     rrect = RoundedRectangle(-2, -3, 8, 5, 6)
     bottom_right = rrect.max_point()
     self.assertEqual(bottom_right.x, 6)
     self.assertEqual(bottom_right.y, 2)
 def test_rrectangle_min_point(self):
     '''Test RoundedRectangle.min_point()'''
     rrect = RoundedRectangle(-2, -3, 8, 5, 6)
     top_left = rrect.min_point()
     self.assertEqual(top_left.x, -2)
     self.assertEqual(top_left.y, -3)