📄 autosilkutils.il
字号:
pbLayer, gap, boundShp, pkgHgt, boundShps, minHgt, airGap, airGap2, sym2, chkObjs, expected, smObjTypeText
smObjPoly, delShp, drcPt, smObjShp, gapData, actual, txt, drcTxt, drcMsg, drcMsgs, smObjLoc, objPoly, intersectPoly)
precisionFactor = 10.0 ** ASU_precision
layer = obj ->layer
side = ASU_getLayerSide(layer, obj)
objType = obj ->objType
bbox = bBoxAdd(obj ->bBox, list(list(-spacing, -spacing) list(spacing, spacing)))
when(pinChk, smObjTypes = '("PINS"))
when(viaChk, smObjTypes = cons("VIAS", smObjTypes))
when(smObjTypes, smObjs = findTypeObjects(smObjTypes, ?bbox bbox))
when(pinChk && solderedPadsOnlyChk
smObjs = setof(pin, smObjs
or(
pin ->objType == "via"; Check all via pads
car(pin ->startEnd) == cadr(pin ->startEnd); Check all SMD pads
cadr(parseString(cadr(pin ->startEnd), "/")) == side; Check only pads on opposite side from leaded device
)
)
)
when(smShpChk
smObjTypes = cons("SHAPES", smObjTypes)
smLayers = list(strcat("BOARD GEOMETRY/SOLDERMASK_", side), strcat("PACKAGE GEOMETRY/SOLDERMASK_", side))
smObjs = remove(obj, append(smObjs, findTypeObjects("SHAPES", ?layers smLayers ?bbox bbox)))
)
case(objType
("text"
text = obj ->text, tempShps = ASU_textToShape(obj, ?quickChk (txtChk == "QUICK"))
/* Next few lines are for ref desig location checking */
when(refdesLocChk
symb = obj ->parent
class = symb ->component ->class
when(symb && (symb ->objType == "symbol") && (symb ->refdes == text)
tempShp1 = car(if(txtChk == "QUICK", tempShps, ASU_textToShape(obj, ?quickChk t)))
pbLayer = strcat("PACKAGE GEOMETRY/PLACE_BOUND_", side)
foreach(shp, setof(shp, symb ->children, shp ->layer == pbLayer)
gap = caddr(AFn_getAirGap(tempShp1, shp)) || 0
when(!airGap || gap < airGap, boundShp = shp, airGap = gap)
)
pkgHgt = AFn_getProperty(boundShp, "PACKAGE_HEIGHT_MAX")
pkgHgt = if(pkgHgt, readstring(pkgHgt), 0)
when(airGap && airGap > 0
bbox = bBoxAdd(tempShp1 ->bBox, list(list(-airGap, -airGap), list(airGap, airGap)))
boundShps = setof(shp, remove(boundShp, findTypeObjects("SHAPES", ?layers pbLayer ?bbox bbox))
and(sym2 = shp ->parent, sym2 ->objType == "symbol", sym2 ->component ->class == class))
foreach(shp, boundShps
minHgt = AFn_getProperty(shp, "PACKAGE_HEIGHT_MIN")
minHgt = if(minHgt, readstring(minHgt), 0)
gapData = AFn_getAirGap(tempShp1, shp)
airGap2 = caddr(gapData) || 0
when(airGap2 < airGap && minHgt <= pkgHgt
sym2 = shp ->parent
actual = round((airGap - airGap2) * precisionFactor) / precisionFactor; round number to precision
sprintf(actual, "%g %s", actual, ASU_designUnits)
sprintf(drcTxt, "%s text ('%s') is %s closer to %s than its own parent symbol", side, text, actual, sym2 ->refdes)
sprintf(drcMsg, "%s text ('%s') at %L is %s closer to %s than its own parent symbol", side, text, obj ->xy, actual, sym2 ->refdes)
drcMsgs = cons(drcMsg, drcMsgs)
drcPt = cadr(gapData) || obj ->xy
axlDBCreateExternalDRC(drcTxt, drcPt, drcLayer, list(boundShp, obj), sym2 ->xy, actual)
)
)
)
unless(txtChk == "QUICK", axlDeleteObject(tempShp1))
)
unless(txtChk, axlDeleteObject(tempShps), tempShps = nil)
)
/* ************************************************* */
)
("shape", chkObjs = list(obj))
("path"
if(isCallable('axlAirGap) then chkObjs = list(obj)
else
foreach(poly, axlPolyFromDB(obj, ?endCapType 'ROUND)
tempShps = cons(car(axlDBCreateShape(poly, t, layer)), tempShps)
)
)
)
)
sprintf(expected, "%g %s", spacing, ASU_designUnits)
foreach(tempObj, append(tempShps, chkObjs)
foreach(soldermaskObj, smObjs
case(soldermaskObj ->objType
("pin", smObjTypeText = "Pin Soldermask Pad")
("via", smObjTypeText = "Via Soldermask Pad")
("shape", smObjTypeText = "Soldermask Shape")
(t, "Unexpected Soldermask object")
)
if(member(soldermaskObj ->objType, '("pin", "via")) then
smObjPoly = car(axlPolyFromDB(soldermaskObj, ?layer strcat("PIN/SOLDERMASK_", side), ?padType "REGULAR"))
delShp = smObjShp = car(axlDBCreateShape(smObjPoly, t, layer))
else
unless(isCallable('axlAirGap), smObjPoly = car(axlPolyFromDB(soldermaskObj)))
delShp = nil, smObjShp = soldermaskObj
)
when(smObjShp
actual = nil
if(isCallable('axlAirGap) && (objType == "path") then
foreach(seg, tempObj ->segments
gapData = AFn_getAirGap(seg, smObjShp)
airGap = caddr(gapData) || 0.0; axlAirGap returns nil if overlap
when(!actual || (airGap < actual), actual = airGap, drcPt = getRectangleCentre(gapData))
)
else
if(isCallable('axlAirGap) then
gapData = AFn_getAirGap(tempObj, smObjShp)
drcPt = getRectangleCentre(gapData)
actual = caddr(gapData) || 0.0; axlAirGap returns nil if overlap
else
objPoly = car(axlPolyExpand(axlPolyFromDB(tempObj, ?endCapType 'ROUND), spacing, 'ALL_ARC))
intersectPoly = car(axlPolyOperation(objPoly, smObjPoly, "AND"))
when(intersectPoly
gapData = intersectPoly ->bBox
drcPt = getRectangleCentre(gapData)
actual = caddr(AFn_getAirGap(tempObj, smObjShp)) || 0.0
)
)
)
axlDeleteObject(delShp)
when(actual
actual = round(actual * precisionFactor) / precisionFactor; round number to precision
unless(actual >= spacing - axlMKSConvert(0.2, "MILS"); Add a tad to allow for rounding problems
actual = if(zerop(actual), "Overlap", sprintf(nil, "%g %s", actual, ASU_designUnits))
txt = if(objType == "text", strcat(" ('", text, "')"), "")
sprintf(drcTxt, "%s %s%s to %s/req:%s; actual:%s", side, objType, txt, smObjTypeText, expected, actual)
sprintf(drcMsg, "%s %s%s to %s/req:%s; actual:%s at %L", side, objType, txt, smObjTypeText, expected, actual, drcPt)
drcMsgs = cons(drcMsg, drcMsgs)
smObjLoc = soldermaskObj ->xy || car(soldermaskObj ->bBox)
axlDBCreateExternalDRC(drcTxt, drcPt, drcLayer, list(obj, soldermaskObj), smObjLoc, actual)
)
)
)
)
)
axlDeleteObject(tempShps)
drcMsgs
))
defun( ASU_textToShape (txtObjs @key quickChk, shpLayer, propValue)
let((layer, tad, text, loc, x0, y0, rot, tbParam, photoWidth, txtHgt, chWid, chSpc, txtLen
lx, txtLst, txtCh, mergedPolys, unmergedPolys, line, shp, shps, bbox, w, corners, rpath, mergedPoly)
unless(listp(txtObjs), txtObjs = list(txtObjs))
tad = axlMKSConvert(0.001, "mm")
and(shpLayer, !axlIsLayer(shpLayer), axlLayerCreateNonConductor(shpLayer))
foreach(obj, txtObjs
layer = shpLayer || obj ->layer
text = obj ->text, loc = obj ->xy, x0 = car(loc), y0 = cadr(loc), rot = -obj ->rotation
tbParam = axlGetParam(strcat("paramTextBlock:" obj ->textBlock))
photoWidth = tbParam ->photoWidth
when(zerop(photoWidth), photoWidth = tad)
txtHgt = tbParam ->height, chWid = tbParam ->width, chSpc = tbParam ->charSpace
txtLen = strlen(text) * (tbParam ->width + chSpc) - chSpc
when(obj ->isMirrored, txtLen = -txtLen, chWid = -chWid, chSpc = -chSpc)
lx = case(obj ->justify, ("LEFT", x0), ("CENTER", x0 - txtLen / 2.0), ("RIGHT", x0 - txtLen))
txtLst = parseString(text, "")
while(txtLst
txtCh = car(txtLst), txtLst = cdr(txtLst)
mergedPolys = unmergedPolys = nil
foreach(pts, ASU_getChLines(txtCh, chWid, txtHgt, lx, y0)
if(quickChk then bbox = ASU_getLinesBbox(pts, bbox), mergedPolys = t
else
unless(zerop(rot), pts = rotatePoints(pts, rot, loc))
line = caar(axlDBCreateLine(pts, photoWidth, layer))
foreach(poly, axlPolyFromDB(line, ?endCapType 'ROUND)
mergedPoly = axlPolyOperation(mergedPolys, poly, 'or)
; Polys with isHole == t might occur.
;A bug with axlPolyOperation appears to have this affect sometimes.
if(mergedPoly && !member(t, mergedPoly ~>isHole)
then mergedPolys = mergedPoly
else unmergedPolys = cons(poly, unmergedPolys)
)
)
axlDeleteObject(line)
)
)
unless(quickChk
foreach(poly, append(mergedPolys, unmergedPolys)
if(poly ->isHole ; This shouldn't occur. A bug with axlPolyOperation appears to have this affect sometimes.
then shp = car(axlDBCreateRectangle(poly ->bBox, t, layer))
else shp = car(axlDBCreateShape(poly, t, layer))
)
when(shp
when(propValue, AFn_addProperty(shp, "TEXTSHAPE", propValue))
shps = cons(shp, shps)
)
)
)
lx = lx + chWid + chSpc
)
)
when(quickChk
w = photoWidth / 2.0
bbox = list(list(caar(bbox) - w, cadar(bbox) - w), list(caadr(bbox) + w, cadadr(bbox) + w))
if(orthogonalp(rot) then
unless(zerop(rot), bbox = rotatePoints(bbox, rot, loc))
shp = car(axlDBCreateRectangle(bbox, t, layer))
else
corners = list(car(bbox), list(caar(bbox), cadadr(bbox)), cadr(bbox), list(caadr(bbox), cadar(bbox)), car(bbox))
corners = rotatePoints(corners, rot, loc)
rpath = axlPathStart(corners)
shp = car(axlDBCreateShape(rpath, t, layer))
)
when(propValue, AFn_addProperty(shp, "TEXTSHAPE", propValue))
shps = list(shp)
)
shps
))
defun( ASU_getLinesBbox (pts, bbox)
let((lx, ly, rx, uy)
if(bbox
then lx = caar(bbox), ly = cadar(bbox), rx = caadr(bbox), uy = cadadr(bbox)
else lx = rx = caar(pts), ly = uy = cadar(pts), pts = cdr(pts)
)
foreach(pt, pts, lx = min(lx, car(pt)), ly = min(ly, cadr(pt)), rx = max(rx, car(pt)), uy = max(uy, cadr(pt)))
list(lx:ly, rx:uy)
))
defun( ASU_getChLines (txtCh, chWid, txtHgt, lx, ly)
let((lines, lineList, result)
lines = case(txtCh
("\"", '(((0.567 0.783) (0.65 1.0)) ((0.433 1.0) (0.35 0.783))))
("#", '(((0.0 0.5) (1.0 0.5)) ((1.0 0.167) (0.0 0.167)) ((0.5 -0.333) (0.833 1.0)) ((0.5 1.0) (0.167 -0.333))))
("$", '(((0.333 1.0) (0.333 -0.333)) ((0.667 -0.333) (0.667 1.0)) ((1.0 0.567) (1.0 0.667) (0.833 0.833) (0.167 0.833) (0.0 0.667) (0.0 0.5) (0.167 0.333) (0.833 0.333) (1.0 0.167) (1.0 0.0) (0.833 -0.167) (0.167 -0.167) (0.0 0.0) (0.0 0.1))))
("%", '(((0.8 0.333) (0.9 0.3) (0.95 0.25) (0.983 0.15) (0.95 0.05) (0.9 0.0) (0.8 -0.033) (0.7 0.0) (0.65 0.05) (0.617 0.15) (0.65 0.25) (0.7 0.3) (0.8 0.333)) ((0.2 1.0) (0.3 0.967) (0.35 0.917) (0.383 0.817) (0.35 0.717) (0.3 0.667) (0.2 0.633) (0.1 0.667) (0.05 0.717) (0.017 0.817) (0.05 0.917) (0.1 0.967) (0.2 1.0)) ((0.8 1.0) (0.2 -0.033))))
("&", '(((1.0 0.0) (0.667 -0.333) (0.167 -0.333) (0.0 -0.167) (0.0 0.167) (0.167 0.333) (0.5 0.5) (0.667 0.667) (0.667 0.833) (0.5 1.0) (0.333 1.0) (0.167 0.833) (0.167 0.667) (1.0 -0.333))))
("'", '(((0.667 0.875) (0.542 0.875) (0.542 1.0) (0.667 1.0) (0.667 0.875) (0.5 0.667))))
("(", '(((0.417 1.0) (0.25 0.833) (0.167 0.667) (0.167 0.0) (0.25 -0.167) (0.417 -0.333))))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -