Inventree
This commit is contained in:
425
.scripts/foot_gen.py
Normal file
425
.scripts/foot_gen.py
Normal file
@@ -0,0 +1,425 @@
|
||||
from copy import deepcopy
|
||||
import sys
|
||||
import os
|
||||
|
||||
import pcbnew
|
||||
from pcbnew import FOOTPRINT, FP_3DMODEL, VECTOR3D, FootprintLoad, FromMM, ToMM, LoadBoard, SaveBoard, PCB_TEXT
|
||||
|
||||
filename = sys.argv[1]
|
||||
|
||||
os.mkdir("test")
|
||||
|
||||
pcb = LoadBoard(filename)
|
||||
|
||||
box = pcb.GetBoardEdgesBoundingBox()
|
||||
brd_cent = box.GetCenter()
|
||||
brd_width = ToMM(box.GetWidth())
|
||||
brd_height = ToMM(box.GetHeight())
|
||||
|
||||
print("Box: ", box)
|
||||
print("W: ", brd_width, "H: ", brd_height)
|
||||
|
||||
# layers = pcb.GetEnabledLayers()
|
||||
top_layer_id = pcb.GetLayerID("F.Cu")
|
||||
|
||||
new_foots = {}
|
||||
brd_drawings = []
|
||||
foot_name = ""
|
||||
foot_path = ""
|
||||
z_offset = 0
|
||||
for item in pcb.GetDrawings():
|
||||
if type(item) is PCB_TEXT and "User.Drawings" in item.GetLayerName():
|
||||
lines = str(item.GetText()).splitlines()
|
||||
# Must have the correct header
|
||||
if "Foot Pinout" not in lines[0]:
|
||||
brd_drawings.append(item)
|
||||
continue
|
||||
if not lines[1].startswith("Name:"):
|
||||
continue
|
||||
foot_name = lines[1].split(":")[-1].strip()
|
||||
if not lines[2].startswith("Path:"):
|
||||
continue
|
||||
foot_path = lines[2].split(":")[-1].strip()
|
||||
if not lines[3].startswith("Z:"):
|
||||
continue
|
||||
z_offset = float(lines[3].split(":")[-1].strip())
|
||||
for line in lines[4:]:
|
||||
sp = line.split(':', 1)
|
||||
if len(sp) != 2:
|
||||
continue
|
||||
# Path to substitue footprint
|
||||
ref = sp[0]
|
||||
foot_sp = sp[1].split(';')
|
||||
foot = foot_sp[0].strip()
|
||||
offset = (0,0)
|
||||
# Optional offset tuple
|
||||
if len(foot_sp) == 2:
|
||||
print("Foot sp: ", foot_sp)
|
||||
offset = foot_sp[1].strip(" ()").split(',')
|
||||
print("Offset: ", offset)
|
||||
offset[0] = FromMM(float(offset[0]))
|
||||
offset[1] = FromMM(float(offset[1]))
|
||||
|
||||
new_foots[ref] = [foot, offset]
|
||||
# pins = sp[1]
|
||||
# pin_refs = []
|
||||
# for pin in pins.split(','):
|
||||
# pin_refs.push(int(pin))
|
||||
|
||||
break
|
||||
elif "Edge.Cuts" in item.GetLayerName():
|
||||
brd_drawings.append(item)
|
||||
# print("Text: ", item.GetText())
|
||||
# print("Layer: ", item.GetLayerName())
|
||||
elif "F.Courtyard" in item.GetLayerName():
|
||||
brd_drawings.append(item)
|
||||
# print("Text: ", item.GetText())
|
||||
# print("Layer: ", item.GetLayerName())
|
||||
|
||||
print("")
|
||||
print("New Footprint List: ", new_foots)
|
||||
|
||||
|
||||
if len(new_foots) == 0:
|
||||
exit(0)
|
||||
|
||||
# Clear tracks
|
||||
pcb.Tracks().clear()
|
||||
# Clear zones
|
||||
pcb.Zones().clear()
|
||||
# Clear Drawings
|
||||
pcb.Drawings().clear()
|
||||
# Add back in the outline
|
||||
for d in brd_drawings:
|
||||
pcb.Drawings().append(d)
|
||||
|
||||
# Keep only required foots
|
||||
saved = []
|
||||
while len(pcb.Footprints()) > 1:
|
||||
foot = pcb.Footprints().pop()
|
||||
if foot.GetReference() in new_foots.keys():
|
||||
saved.append(foot)
|
||||
saved.sort(key=lambda foot: list(new_foots.keys()).index(foot.GetReference()))
|
||||
# just in case
|
||||
pcb.DeleteAllFootprints()
|
||||
# Add them back
|
||||
sorted_foots = []
|
||||
for foot in saved:
|
||||
vals = new_foots[foot.GetReference()]
|
||||
# Change the footprint
|
||||
path_split = vals[0].split(':')
|
||||
folder = sys.path[0] + "/../../libs/melonlib/"+ path_split[0] + ".pretty"
|
||||
load_foot = FootprintLoad(folder, path_split[1])
|
||||
# foot.SetFPIDAsString(vals[0])
|
||||
# Save the original postion of footprint + pads
|
||||
orig_cent = foot.GetBoundingBox(False,False).Centre()
|
||||
orig_orient = foot.GetOrientation()
|
||||
pads = []
|
||||
for pad in foot.Pads():
|
||||
pads.append([pad.GetNumber(), pad.GetCenter(), pad.GetNet()])
|
||||
|
||||
# # Flip to other side
|
||||
# foot.SetLayerAndFlip(top_layer_id)
|
||||
# Put back in original position with an offset
|
||||
load_foot.SetOrientation(orig_orient)
|
||||
new_cent = load_foot.GetBoundingBox(False,False).Centre()
|
||||
cent_diff = orig_cent - new_cent
|
||||
load_foot.SetX(load_foot.GetX() + cent_diff.x + vals[1][0])
|
||||
load_foot.SetY(load_foot.GetY() + cent_diff.y + vals[1][1])
|
||||
# Flip the net assignments of the pads
|
||||
pad_map = {}
|
||||
for pad in load_foot.Pads():
|
||||
if len(pad.GetNumber()) == 0:
|
||||
continue
|
||||
# Check position diff from old
|
||||
# to new
|
||||
new_cent = pad.GetCenter()
|
||||
diffs = []
|
||||
for [_, old_cent,_] in pads:
|
||||
diffs.append(new_cent - old_cent)
|
||||
min_diff = min(diffs)
|
||||
# If pad is within 0.05mm it's a match
|
||||
if (min_diff.x**2 + min_diff.y**2)**0.5 < 50000:
|
||||
# Set the net to what the old pad was
|
||||
i = diffs.index(min_diff)
|
||||
match_num = pads[i][0]
|
||||
match_pad = pads[i][2:]
|
||||
pad.SetNet(match_pad[0])
|
||||
pad_map[pad.GetNumber()] = match_num
|
||||
elif "mounting" in str(foot.GetKeywords()).lower():
|
||||
match_num = pads[0][0]
|
||||
match_pad = pads[0][2:]
|
||||
pad.SetNet(match_pad[0])
|
||||
pad_map[pad.GetNumber()] = match_num
|
||||
|
||||
sorted_foots.append([load_foot, pad_map])
|
||||
pcb.Add(load_foot)
|
||||
|
||||
|
||||
# # Sort by Y
|
||||
# sorted_foots.sort(key=lambda foot: foot[0].GetY())
|
||||
|
||||
# Export the step file
|
||||
os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o /tmp/dummy.step " + sys.argv[1])
|
||||
|
||||
# Import the 3d model of the actual PCB
|
||||
dummy = FOOTPRINT(pcb)
|
||||
dummy.SetPosition(brd_cent)
|
||||
dummy_model = FP_3DMODEL()
|
||||
dummy_model.m_Filename = "/tmp/dummy.step"
|
||||
dummy_model.m_Offset = VECTOR3D(0.0, 0.0, z_offset)
|
||||
dummy.Add3DModel(dummy_model)
|
||||
pcb.Add(dummy)
|
||||
|
||||
# # Set the pcb thickness to 0
|
||||
# des_sett = pcb.GetDesignSettings()
|
||||
# stackup = des_sett.GetStackupDescriptor()
|
||||
|
||||
# Save and export step of board + mating connectors
|
||||
SaveBoard("test/test.kicad_pcb", pcb)
|
||||
final_model_path = sys.path[0] + "/../../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".step"
|
||||
os.system("kicad-cli pcb export step -f --subst-models --user-origin " + str(ToMM(brd_cent.x)) + "x" + str(ToMM(brd_cent.y)) + "mm -o " + final_model_path + " test/test.kicad_pcb")
|
||||
|
||||
# Generate footprint
|
||||
|
||||
sys.path.append(os.path.join(sys.path[0],"../kicad-footprint-generator"))
|
||||
|
||||
from KicadModTree import *
|
||||
from KicadModTree.nodes.specialized.PadArray import PadArray
|
||||
|
||||
# init kicad footprint
|
||||
kicad_mod = Footprint(foot_name, FootprintType.SMD)
|
||||
kicad_mod.setDescription("A example footprint")
|
||||
kicad_mod.setTags("example")
|
||||
|
||||
# set general values
|
||||
kicad_mod.append(Text(type='reference', text='REF**', at=[0,-3], layer='F.SilkS'))
|
||||
kicad_mod.append(Text(type='value', text=foot_name, at=[1.5,3], layer='F.Fab'))
|
||||
|
||||
# create courtyard
|
||||
# for [foot, pad_map] in sorted_foots:
|
||||
|
||||
# kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.CrtYd', width=0.05, offset=0.5))
|
||||
|
||||
# create pads
|
||||
print(sorted_foots)
|
||||
keepouts = []
|
||||
pad_cnt = 0
|
||||
for [foot, pad_map] in sorted_foots:
|
||||
local_box = foot.GetBoundingBox(False,False)
|
||||
local_cent = ToMM(local_box.GetCenter() - brd_cent)
|
||||
local_size = ToMM(local_box.GetSize())
|
||||
print("Bounding: ", local_cent, local_size)
|
||||
keepouts.append([local_cent, local_size])
|
||||
mounting_flag = "mounting" in str(foot.GetKeywords()).lower()
|
||||
custom_paste_flag = False
|
||||
if mounting_flag:
|
||||
for pad in foot.Pads():
|
||||
if pad.IsAperturePad():
|
||||
custom_paste_flag = True
|
||||
# size = foot.GetBoundingBox(False,False).GetSize()
|
||||
# cent = foot.GetCenter() - brd_cent
|
||||
# x_flag = abs(cent.x) - brd_width/2 > -size.x/2
|
||||
# y_flag = abs(cent.y) - brd_height/2 > -size.y/2
|
||||
# if x_flag or y_flag:
|
||||
# shape_type = foot.GetEffectiveShape()
|
||||
# cent_mm = ToMM(cent)
|
||||
# size_mm = ToMM(size)
|
||||
# start_x = brd_width/2
|
||||
# start_y = brd_height/2
|
||||
# if cent.x < 0:
|
||||
# start_x = -1*start_x
|
||||
# if cent.y < 0:
|
||||
# start_y = -1*start_y
|
||||
# if not x_flag:
|
||||
# start_x = cent_mm[0]
|
||||
# if not y_flag:
|
||||
# start_y = cent_mm[1]
|
||||
# print("Silk: ", cent_mm, size_mm)
|
||||
# if shape_type == pcbnew.SHAPE_T_RECT:
|
||||
# start = [start_x, start_y + size_mm[1]/2]
|
||||
# end = [start[0] + size_mm[0]/2, start[1]]
|
||||
# kicad_mod.append(Line(start=start, end=end, layer='F.Silkscreen', width=0.05))
|
||||
# start = [end[0], end[1]]
|
||||
# end = [start[0], start[1] - size[1]]
|
||||
# kicad_mod.append(Line(start=start, end=end, layer='F.Silkscreen', width=0.05))
|
||||
# start = [end[0], end[1]]
|
||||
# end = [start[0] - size[0]/2, start[1]]
|
||||
# kicad_mod.append(Line(start=start, end=end, layer='F.Silkscreen', width=0.05))
|
||||
# start = [cent_mm[0] - size_mm[0], cent_mm[1] - size_mm[1]]
|
||||
# end = [cent_mm[0] + size_mm[0], cent_mm[1] + size_mm[1]]
|
||||
# kicad_mod.append(RectLine(start=start, end=end, layer='F.Silkscreen', width=0.05, offset=0.2))
|
||||
# elif shape_type == pcbnew.SHAPE_T_CIRCLE:
|
||||
# start = [cent_mm[0], cent_mm[1] + size_mm[1]/2]
|
||||
# end = [start[0], start[1]]
|
||||
# radius = size.x/2
|
||||
# kicad_mod.append(Arc(center=cent, start=radius, layer='F.Silkscreen', width=0.05))
|
||||
# radius = size_mm[0]/2 + 0.2
|
||||
# kicad_mod.append(Circle(center=cent_mm, radius=radius, layer='F.Silkscreen', width=0.05))
|
||||
|
||||
for d in foot.GraphicalItems():
|
||||
if type(d) is pcbnew.FP_SHAPE and "F.Courtyard" in d.GetLayerName():
|
||||
shape_type = d.GetShape()
|
||||
cent = d.GetCenter() - brd_cent
|
||||
print("Courtyard: ", cent, shape_type)
|
||||
if shape_type == pcbnew.SHAPE_T_SEGMENT:
|
||||
start = d.GetStart() - brd_cent
|
||||
end = d.GetEnd() - brd_cent
|
||||
print("Seg: ", ToMM(start), ToMM(end))
|
||||
kicad_mod.append(Line(start=ToMM(start), end=ToMM(end), layer='F.CrtYd', width=0.05))
|
||||
elif shape_type == pcbnew.SHAPE_T_RECT:
|
||||
start = d.GetStart() - brd_cent
|
||||
end = d.GetEnd() - brd_cent
|
||||
print("Rect: ", ToMM(start), ToMM(end))
|
||||
kicad_mod.append(RectLine(start=ToMM(start), end=ToMM(end), layer='F.CrtYd', width=0.05))
|
||||
elif shape_type == pcbnew.SHAPE_T_CIRCLE:
|
||||
radius = ToMM(d.GetRadius())
|
||||
cent = ToMM(cent)
|
||||
print("Circ: ", cent, radius)
|
||||
kicad_mod.append(Circle(center=cent, radius=radius, layer='F.CrtYd', width=0.05))
|
||||
|
||||
|
||||
real_pads = 0
|
||||
for pad in foot.Pads():
|
||||
cent = ToMM(pad.GetCenter() - brd_cent)
|
||||
pad_size = ToMM(pad.GetSize())
|
||||
drill_size = ToMM(pad.GetDrillSize())
|
||||
curr_pad_num = pad.GetNumber()
|
||||
attr_type = pad.GetAttribute()
|
||||
shape_type = pad.GetShape()
|
||||
offset = pad.GetOffset()
|
||||
|
||||
|
||||
pad_type = Pad.TYPE_THT
|
||||
pad_layers = Pad.LAYERS_THT
|
||||
if attr_type == pcbnew.PAD_ATTRIB_SMD:
|
||||
pad_type = Pad.TYPE_SMT
|
||||
if custom_paste_flag:
|
||||
pad_layers = ["F.Cu", "F.Mask"]
|
||||
else:
|
||||
pad_layers = Pad.LAYERS_SMT
|
||||
elif attr_type == pcbnew.PAD_ATTRIB_NPTH:
|
||||
pad_type = Pad.TYPE_NPTH
|
||||
pad_layers = Pad.LAYERS_NPTH
|
||||
elif attr_type == pcbnew.PAD_ATTRIB_CONN:
|
||||
pad_type = Pad.TYPE_CONNECT
|
||||
pad_layers = Pad.LAYERS_NPTH
|
||||
|
||||
if pad.IsAperturePad():
|
||||
pad_layers = ["F.Paste"]
|
||||
|
||||
primitives = []
|
||||
pad_number = pad.GetNumber()
|
||||
pad_shape = Pad.SHAPE_RECT
|
||||
if shape_type == pcbnew.PAD_SHAPE_CIRCLE:
|
||||
pad_shape = Pad.SHAPE_CIRCLE
|
||||
elif shape_type == pcbnew.PAD_SHAPE_OVAL:
|
||||
pad_shape = Pad.SHAPE_OVAL
|
||||
elif shape_type == pcbnew.PAD_SHAPE_CHAMFERED_RECT:
|
||||
pad_shape = Pad.SHAPE_TRAPEZE
|
||||
elif shape_type == pcbnew.PAD_SHAPE_ROUNDRECT:
|
||||
pad_shape = Pad.SHAPE_ROUNDRECT
|
||||
elif shape_type == pcbnew.PAD_SHAPE_CUSTOM:
|
||||
pad_shape = Pad.SHAPE_CUSTOM
|
||||
for d in foot.GraphicalItems():
|
||||
if type(d) is pcbnew.FP_TEXT and "User.Drawings" in d.GetLayerName():
|
||||
txt_sp = d.GetText().split(':',1)
|
||||
if pad_number != txt_sp[0]:
|
||||
continue
|
||||
print("Item:", txt_sp[1].strip())
|
||||
exec("tmp = " + txt_sp[1].strip())
|
||||
primitives.append(tmp)
|
||||
# primitives.append(Arc(center=[0, 0], start=[-2.95, 0], width=1.5, angle=360, layer='F.Cu'))
|
||||
|
||||
# print(dir(pad.GetPrimitives()))
|
||||
# for prim in pad.GetPrimitives():
|
||||
# shape = prim.GetEffectiveShape()
|
||||
# print("Shape: ", shape)
|
||||
|
||||
if len(pad_number) > 0:
|
||||
pad_number = pad_cnt + int(pad_map[curr_pad_num])
|
||||
|
||||
# primitives = [Arc(center=[0, 0], start=[-2.95, 0], width=1.5, angle=360, layer='F.Cu')]
|
||||
print("offset: ", [ToMM(offset.x), ToMM(offset.y)])
|
||||
final_pad = Pad(number=pad_number, type=pad_type, shape=pad_shape, at=list(cent), size=list(pad_size), drill=list(drill_size), offset=list(ToMM(offset)), layers=pad_layers, primitives=primitives)
|
||||
# for prim in primitives:
|
||||
# final_pad.addPrimitive(prim)
|
||||
kicad_mod.append(final_pad)
|
||||
real_pads += len(pad.GetNumber()) > 0
|
||||
pad_cnt += real_pads
|
||||
|
||||
|
||||
# create silkscreen
|
||||
print("keepouts: ", keepouts)
|
||||
corners = [[-brd_width/2, -brd_height/2], [-brd_width/2, brd_height/2], [brd_width/2, brd_height/2], [brd_width/2, -brd_height/2]]
|
||||
for i in range(len(corners)):
|
||||
if i == len(corners)-1:
|
||||
j = 0
|
||||
else:
|
||||
j = i+1
|
||||
start = deepcopy(corners[i])
|
||||
end = deepcopy(start)
|
||||
y_dir = False
|
||||
if corners[i][0] == corners[j][0]:
|
||||
y_dir = True
|
||||
sign = -1
|
||||
if corners[j][y_dir] > corners[i][y_dir]:
|
||||
sign = 1
|
||||
# Find intersections with keepouts
|
||||
intersects = []
|
||||
for k in keepouts:
|
||||
if abs(start[not y_dir] - k[0][not y_dir]) < k[1][not y_dir]/2:
|
||||
intersects.append(k)
|
||||
intersects.sort(key=lambda k: abs(start[y_dir] - k[0][y_dir]))
|
||||
|
||||
|
||||
print("Start: ", start)
|
||||
print("end: ", corners[j])
|
||||
print("Flag: ", y_dir)
|
||||
print("intersects: ", intersects)
|
||||
if len(intersects):
|
||||
intersect = intersects[0]
|
||||
skip_flag = abs(start[y_dir]) < abs(intersect[0][y_dir] - sign * intersect[1][y_dir]/2)
|
||||
print("Skip params: ", abs(start[y_dir]), abs(intersect[0][y_dir] - sign * intersect[1][y_dir]/2))
|
||||
|
||||
for intersect in intersects:
|
||||
end[y_dir] = intersect[0][y_dir] - sign * intersect[1][y_dir]/2
|
||||
# if y_dir:
|
||||
# end[0] = intersect[0][0] - sign * intersect[1][0]/2
|
||||
# else:
|
||||
# end[1] = intersect[0][1] - sign * intersect[1][1]/2
|
||||
|
||||
if not skip_flag:
|
||||
print("Silk: ", start, end)
|
||||
kicad_mod.append(Line(start=start, end=end, layer='F.SilkS', width=0.1))
|
||||
skip_flag = False
|
||||
start[y_dir] = intersect[0][y_dir] + sign * intersect[1][y_dir]/2
|
||||
# if y_dir:
|
||||
# start[0] = intersect[0][0] + sign * intersect[1][0]/2
|
||||
# else:
|
||||
# start[1] = intersect[0][1] + sign * intersect[1][1]/2
|
||||
|
||||
print("End params: ", abs(start[y_dir]), abs(corners[j][y_dir]))
|
||||
if abs(start[y_dir]) <= abs(corners[j][y_dir]):
|
||||
print("End Fake: ", start, end)
|
||||
print("End: ", start, corners[j])
|
||||
kicad_mod.append(Line(start=start, end=corners[j], layer='F.SilkS', width=0.1))
|
||||
|
||||
|
||||
# kicad_mod.append(RectLine(start=[-brd_width/2,-brd_height/2], end=[brd_width/2,brd_height/2], layer='F.SilkS', width=0.15))
|
||||
|
||||
|
||||
final_model_path = "${KIPRJMOD}/../libs/melon3d/" + foot_path + ".3dshapes/" + foot_name + ".step"
|
||||
kicad_mod.append(Model(filename=final_model_path
|
||||
,at=[0,0,-1.6]
|
||||
,scale=[1,1,1]
|
||||
,rotate=[0,0,0]))
|
||||
|
||||
# write file
|
||||
file_handler = KicadFileHandler(kicad_mod)
|
||||
final_foot_path = sys.path[0] + "/../../libs/melonlib/" + foot_path + ".pretty/" + foot_name + ".kicad_mod"
|
||||
file_handler.writeFile(final_foot_path)
|
||||
|
||||
import shutil
|
||||
|
||||
shutil.rmtree("test")
|
||||
1
.scripts/ki-ntree
Submodule
1
.scripts/ki-ntree
Submodule
Submodule .scripts/ki-ntree added at 65cfbb5b2a
@@ -115,8 +115,8 @@ def comp_format(filt, offset):
|
||||
t[p] = "{:.2f}".format(abs(float(t[p]) - offset[n]))
|
||||
rotation = float(t[rot])
|
||||
rotation = rotation + offset[2]
|
||||
if rotation > 180.0:
|
||||
rotation = -1 * (360.0 - rotation)
|
||||
# Wrap the phase [-180, 180]
|
||||
rotation = (rotation + 180.0) % (2 * 180.0) - 180.0
|
||||
t[rot] = "{:.2f}".format(rotation)
|
||||
out.append(t)
|
||||
return out
|
||||
|
||||
@@ -1,11 +1,42 @@
|
||||
import json
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
proj = sys.argv[1]
|
||||
pcb = sys.argv[2]
|
||||
|
||||
print("Starting post_panel script")
|
||||
|
||||
dest_folder = '/'.join(proj.split('/')[:-1])
|
||||
dest_name = proj.split('/')[-1].removesuffix(".kicad_pro")
|
||||
|
||||
src_name = pcb.removesuffix(".kicad_pcb")
|
||||
src_proj = src_name + ".kicad_pro"
|
||||
|
||||
try:
|
||||
shutil.copy(src_name + ".kicad_dru", dest_folder + "/" + dest_name + ".kicad_dru")
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
json_file = open(src_proj)
|
||||
json_str = json_file.read()
|
||||
src = json.loads(json_str)
|
||||
|
||||
json_file = open(proj)
|
||||
json_str = json_file.read()
|
||||
d = json.loads(json_str)
|
||||
d["board"]["design_settings"]["rule_severities"]["lib_footprint_issues"] = "ignore"
|
||||
d["board"]["design_settings"]["rule_severities"]["lib_footprint_mismatch"] = "ignore"
|
||||
dest = json.loads(json_str)
|
||||
dest["board"]["design_settings"]["rule_severities"]["lib_footprint_issues"] = "ignore"
|
||||
dest["board"]["design_settings"]["rule_severities"]["lib_footprint_mismatch"] = "ignore"
|
||||
dest["board"]["design_settings"]["rule_severities"]["hole_near_hole"] = "ignore"
|
||||
dest["board"]["design_settings"]["rule_severities"]["silk_overlap"] = "ignore"
|
||||
dest["board"]["design_settings"]["rule_severities"]["silk_over_copper"] = "ignore"
|
||||
dest["board"]["design_settings"]["rule_severities"]["drill_out_of_range"] = "ignore"
|
||||
# This one is just until kibot image is updated to 7.0.5
|
||||
dest["board"]["design_settings"]["rule_severities"]["copper_sliver"] = "ignore"
|
||||
dest["net_settings"]["classes"] = src["net_settings"]["classes"]
|
||||
dest["net_settings"]["netclass_patterns"] = src["net_settings"]["netclass_patterns"]
|
||||
|
||||
with open(proj, mode="w") as json_file:
|
||||
json.dump(d, json_file, indent=2)
|
||||
json.dump(dest, json_file, indent=2)
|
||||
|
||||
print("Finished post_panel script")
|
||||
|
||||
69
.scripts/rot_pick.py
Executable file
69
.scripts/rot_pick.py
Executable file
@@ -0,0 +1,69 @@
|
||||
import csv
|
||||
import sys
|
||||
import math
|
||||
import ast
|
||||
|
||||
if len(sys.argv) != 4:
|
||||
print("Invalid num args:", len(sys.argv),", should be 4")
|
||||
exit(1)
|
||||
|
||||
file = sys.argv[1]
|
||||
rot_deg = float(sys.argv[2])
|
||||
dims = [float(i) for i in ast.literal_eval(sys.argv[3])]
|
||||
|
||||
corrected_rows = []
|
||||
with open(file,'r', newline='') as csvfile:
|
||||
spamreader = csv.reader(csvfile, delimiter=',',
|
||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
# Read until the header row
|
||||
for row in spamreader:
|
||||
corrected_rows.append(row)
|
||||
# Header row
|
||||
# Designator,Comment,Footprint,Mid X(mm),Mid Y(mm) ,Rotation,Head ,FeederNo,Mount Speed(%),Pick Height(mm),Place Height(mm),Mode,Skip
|
||||
if "Designator" in row:
|
||||
break;
|
||||
|
||||
# Now the remaining rows should all be placement items
|
||||
# e.g
|
||||
# U2,AH1806-W,SC-59,220.50,11.10,-0.00,0,53,50,0.0,0.0,1,0
|
||||
for row in spamreader:
|
||||
# Skip empty rows
|
||||
if len(row) < 10:
|
||||
continue
|
||||
# To rotate we need to change cols: 3,4,5 (x,y,rot)
|
||||
# Easisest way is to conver to polar
|
||||
x = float(row[3])
|
||||
y = float(row[4])
|
||||
print("Before: ", x,y)
|
||||
# rot = float(row[5])
|
||||
|
||||
r = (x**2 + y**2)**0.5
|
||||
theta = math.atan(y/x)
|
||||
|
||||
# Add the rot
|
||||
rot_rad = math.pi * rot_deg/180
|
||||
theta += rot_rad
|
||||
|
||||
# Convert back to cartesian
|
||||
x = r * math.cos(theta)
|
||||
y = r * math.sin(theta)
|
||||
|
||||
# Shift x so that the origin can be maintained
|
||||
x += math.sin(rot_rad) * dims[1]
|
||||
|
||||
print("After: ", x,y)
|
||||
|
||||
# Add the rotation to the component rotation
|
||||
comp_rot = float(row[5]) + rot_deg
|
||||
|
||||
row[3] = str(x)
|
||||
row[4] = str(y)
|
||||
row[5] = str(comp_rot)
|
||||
|
||||
corrected_rows.append(row)
|
||||
|
||||
with open(file.split('.csv')[0] + '_rot' + '.csv','w', newline='') as csvfile:
|
||||
spamwriter = csv.writer(csvfile, delimiter=',',
|
||||
quotechar='|', quoting=csv.QUOTE_MINIMAL)
|
||||
for row in corrected_rows:
|
||||
spamwriter.writerow(row)
|
||||
Reference in New Issue
Block a user