def bodies(self, offset, instance_attributes): """ Generated the bodies for the Via with instance attribute overrides. Returns placment attribute and body pairs. """ pos = Point(self.x, self.y) attached_layers = self.get_attr('attached_layers', '', instance_attributes).split(',') solder_mask_expansion = self.get_int_attr('solder_mask_expansion', 0, instance_attributes) plating_diameter = self.get_int_attr('plating_diameter', 0, instance_attributes) internal_diameter = self.get_int_attr('internal_diameter', 0, instance_attributes) solder_mask_radius = solder_mask_expansion + (plating_diameter / 2) # placment attribute + body pairs making up the generated object bodies = [] top_solder_mask = FBody() top_solder_mask.add_shape(Circle(pos.x, pos.y, solder_mask_radius)) bodies.append((FootprintAttribute(0, 0, 0, False, 'top solder mask'), top_solder_mask)) bottom_solder_mask = FBody() bottom_solder_mask.add_shape(Circle(pos.x, pos.y, solder_mask_radius)) 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(pos.x, 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() connected_layer.add_shape( Circle(pos.x, pos.y, plating_diameter / 2)) bodies.append((FootprintAttribute(0, 0, 0, False, layer_name), connected_layer)) return bodies
def parse_footprint_attribute(self, footprint_attribute): """ Extract attributes from a footprint. """ x = int(footprint_attribute.get('x') or 0) y = int(footprint_attribute.get('y') or 0) rotation = float(footprint_attribute.get('rotation')) try: flip = (footprint_attribute.get('flip').lower() == "true") except: flip = False layer = footprint_attribute.get('layer') footprint_attr = FootprintAttribute(x, y, rotation, flip, layer) return footprint_attr
def _convert_components(self, struct): """ Convert component """ for component in struct.placement.component: library_id = component.image_id for place in component.place: # Outside PCB boundary if not place.vertex: continue mirror = {90:270, 270:90} if place.side == 'back': rotation = place.rotation else: rotation = mirror.get(int(place.rotation), place.rotation) inst = ComponentInstance(place.component_id, component, library_id, 0) v = self.to_pixels(place.vertex) symbattr = FootprintAttribute(v[0], v[1], to_piradians(rotation), False) inst.add_symbol_attribute(symbattr) self.design.add_component_instance(inst)
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 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