• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Allegro X Scripting - Skill
  3. skill to create shape based on vias

Stats

  • State Suggested Answer
  • Replies 13
  • Answers 2
  • Subscribers 18
  • Views 5382
  • Members are here 0
More Content

skill to create shape based on vias

zpofrp
zpofrp over 1 year ago

Hi 

Attached,

i want use skill to create a shape based on select via,but i can't wirte the skill.

 Play this video

  • Sign in to reply
  • Cancel
  • zpofrp
    0 zpofrp over 1 year ago in reply to Hoangkhoipcb

    I find one bug, show the pic1.

    big via and small via, the shape is hollow,same as pic1.

    I want to create shape same as pic2 or pic3.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • eDave
    0 eDave over 1 year ago in reply to zpofrp

    Here's a more complex alternative:

    axlCmdRegister("createShapeByVia" 'CreateShapeByVia)

    defun( CreateShapeByVia ()
    let((visViaSubclasses, subclass, etchLayer, popupAllActive, popupGrayOops, mark, (oopsCount 0), selectedVias, polys, nets, net, viaPairs, via1, via2, dia1, dia2, lineWidth, path, poly, oShape, shp)
    visViaSubclasses = setof(sc, axlSubclassRoute(?field, 'isEtch), axlIsVisibleLayer(strcat("VIA CLASS/", sc)))
    if(!onep(length(visViaSubclasses)) then
    axlUIConfirm("Only one etch layer can be visible")
    else
    subclass = car(visViaSubclasses)
    etchLayer = strcat("ETCH/", subclass); Use strcat("BOUNDARY/", subclass) if the shape needs to be dynamic
    axlClearSelSet()
    axlSetFindFilter(?enabled '(noall, vias), ?onButtons '(noall, vias))
    popupAllActive = axlUIPopupDefine(nil '(
    ("Done", "axlDBTransactionCommit(mark), axlFinishEnterFun()")
    ("Oops", "axlDBTransactionOops(mark), when(zerop(--oopsCount), axlUIPopupSet(popupGrayOops))")
    ("Cancel", "axlDBTransactionRollback(mark), axlCancelEnterFun()")
    ))
    popupGrayOops = axlUIPopupDefine(nil, '(
    ("Done", "axlDBTransactionCommit(mark), axlFinishEnterFun()")
    ("Cancel", "axlDBTransactionRollback(mark), axlCancelEnterFun()")
    ))
    axlUIPopupSet(popupGrayOops)
    mark = axlDBTransactionStart()

    while(axlSelect(?prompt "Select vias...")
    selectedVias = axlGetSelSet()
    axlClearSelSet()
    polys = nil
    nets = selectedVias ~>net
    net = cadar(sortcar(mapcar(lambda((n), list(length(setof(nt, nets, nt == n)), n)), unique(nets)), 'greaterp)); Select the net of the most number of vias
    viaPairs = CreateShapeByVia_PairCombinations(setof(v, selectedVias, v ->net == net))
    foreach(viaPair, viaPairs; Create a line or a shape polygon between each and every via
    via1 = car(viaPair)
    via2 = cadr(viaPair)
    dia1 = CreateShapeByVia_viaDia(via1, subclass)
    dia2 = CreateShapeByVia_viaDia(via2, subclass)
    if(dia1 == dia2 then
    lineWidth = max(dia1,dia2)
    path = axlPathStart(list(via1 ->xy, via2 ->xy), lineWidth)
    poly = car(axlPolyFromDB(path, ?line2poly t, ?endCapType 'ROUND)); Use a line polygon if the via pads are the same diameter
    else
    poly = CreateShapeByVia_circleCircleTangentialPoly(via1 ->xy, dia1 / 2, via2 ->xy, dia2 / 2); Use a tangential polygon if the via pads are different diameters
    )
    polys = cons(poly, polys)
    )
    when(polys
    poly = car(axlPolyOperation(car(polys), cdr(polys), 'OR)); Combine all the line polys into one polygon
    axlDBTransactionMark(mark)
    oShape = axlDBCreateOpenShape(poly, t, etchLayer, net)
    axlShapeDeleteVoids(oShape)
    shp = car(axlDBCreateCloseShape(oShape))
    when(shp
    axlShapeAutoVoid(shp); Try to void any objects that shouldn't be included. ie on a different net. Doesn't work well.
    oopsCount++
    axlUIPopupSet(popupAllActive)
    )
    )
    )

    axlDBTransactionCommit(mark)
    )
    ))

    ;Return the via pad diameter from the selected subclass
    defun( CreateShapeByVia_viaDia (via @optional (subclass, "TOP"))
    let((pad, bbox)
    pad = axlDBGetPad(via, strcat("VIA CLASS/", subclass), "regular")
    bbox = pad ->bBox
    if(pad ->figureName == "CIRCLE" then
    max(abs(caadr(bbox) - caar(bbox)), abs(cadadr(bbox) - cadar(bbox))); Maximum of x and y extents.
    else
    axlDistance(car(bbox), cadr(bbox))
    )
    ))

    ;Return a list of all the pair combinations of the objects passed.
    defun( CreateShapeByVia_PairCombinations (objs)
    let((obj1, objPairs)
    while(objs
    obj1 = car(objs)
    objs = cdr(objs)
    foreach(obj2, objs, objPairs = cons(list(obj1, obj2), objPairs))
    )
    objPairs
    ))

    ; Create a polygon that encompasses the tangential boundaries of two circles of differeing sizes.
    defun( CreateShapeByVia_circleCircleTangentialPoly (cpt1, r1, cpt2, r2 @optional layer, netName, parent)
    let((x1, y1, x2, y2, ang1, ang2, ang, pt1, pt2, pt3, pt4, path, poly)
    x1 = car(cpt1), y1 = cadr(cpt1)
    x2 = car(cpt2), y2 = cadr(cpt2)
    ;en.wikipedia.org/.../Tangent_lines_to_circles
    ang1 = -atan2(y2-y1, x2 - x1)
    ang2 = asin((r2 - r1) / sqrt((x2 - x1)**2 + (y2 - y1)**2))
    ang = ang1 - ang2
    pt1 = list(x1 + r1 * sin(ang), y1 + r1 * cos(ang))
    pt3 = list(x2 + r2 * sin(ang), y2 + r2 * cos(ang))
    ang = ang1 + ang2
    pt2 = list(x1 - r1 * sin(ang), y1 - r1 * cos(ang))
    pt4 = list(x2 - r2 * sin(ang), y2 - r2 * cos(ang))
    path = axlPathStart(list(pt1, pt3))
    axlPathArcCenter(path, nil, pt4, t, cpt2)
    axlPathLine(path, nil, pt2)
    axlPathArcCenter(path, nil, pt1, t, cpt1)
    poly = car(axlPolyFromDB(path))
    when(layer, axlDBCreateShape(poly, t, layer, netName, parent))
    poly
    ))

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Reject Answer
    • Cancel
  • eDave
    0 eDave over 1 year ago in reply to zpofrp

    axlCmdRegister("createShapeByVia" 'CreateShapeByVia)

    defun( CreateShapeByVia ()
    let((visViaSubclasses, subclass, etchLayer, popupAllActive, popupGrayOops, mark, (oopsCount 0), selectedVias, polys, nets, net, viaPairs, via1, via2, dia1, dia2, lineWidth, path, poly, oShape, shp)
    visViaSubclasses = setof(sc, axlSubclassRoute(?field, 'isEtch), axlIsVisibleLayer(strcat("VIA CLASS/", sc)))
    if(!onep(length(visViaSubclasses)) then
    axlUIConfirm("Only one etch layer can be visible")
    else
    subclass = car(visViaSubclasses)
    etchLayer = strcat("ETCH/", subclass); Use strcat("BOUNDARY/", subclass) if the shape needs to be dynamic
    axlClearSelSet()
    axlSetFindFilter(?enabled '(noall, vias), ?onButtons '(noall, vias))
    popupAllActive = axlUIPopupDefine(nil '(
    ("Done", "axlDBTransactionCommit(mark), axlFinishEnterFun()")
    ("Oops", "axlDBTransactionOops(mark), when(zerop(--oopsCount), axlUIPopupSet(popupGrayOops))")
    ("Cancel", "axlDBTransactionRollback(mark), axlCancelEnterFun()")
    ))
    popupGrayOops = axlUIPopupDefine(nil, '(
    ("Done", "axlDBTransactionCommit(mark), axlFinishEnterFun()")
    ("Cancel", "axlDBTransactionRollback(mark), axlCancelEnterFun()")
    ))
    axlUIPopupSet(popupGrayOops)
    mark = axlDBTransactionStart()

    while(axlSelect(?prompt "Select vias...")
    selectedVias = axlGetSelSet()
    axlClearSelSet()
    polys = nil
    nets = selectedVias ~>net
    net = cadar(sortcar(mapcar(lambda((n), list(length(setof(nt, nets, nt == n)), n)), unique(nets)), 'greaterp)); Select the net of the most number of vias
    viaPairs = CreateShapeByVia_PairCombinations(setof(v, selectedVias, v ->net == net))
    foreach(viaPair, viaPairs; Create a line or a shape polygon between each and every via
    via1 = car(viaPair)
    via2 = cadr(viaPair)
    dia1 = CreateShapeByVia_viaDia(via1, subclass)
    dia2 = CreateShapeByVia_viaDia(via2, subclass)
    if(dia1 == dia2 then
    lineWidth = max(dia1,dia2)
    path = axlPathStart(list(via1 ->xy, via2 ->xy), lineWidth)
    poly = car(axlPolyFromDB(path, ?line2poly t, ?endCapType 'ROUND)); Use a line polygon if the via pads are the same diameter
    else
    poly = CreateShapeByVia_circleCircleTangentialPoly(via1 ->xy, dia1 / 2, via2 ->xy, dia2 / 2); Use a tangential polygon if the via pads are different diameters
    )
    polys = cons(poly, polys)
    )
    when(polys
    poly = car(axlPolyOperation(car(polys), cdr(polys), 'OR)); Combine all the line polys into one polygon
    axlDBTransactionMark(mark)
    oShape = axlDBCreateOpenShape(poly, t, etchLayer, net)
    axlShapeDeleteVoids(oShape)
    shp = car(axlDBCreateCloseShape(oShape))
    when(shp
    axlShapeAutoVoid(shp); Try to void any objects that shouldn't be included. ie on a different net. Doesn't work well.
    oopsCount++
    axlUIPopupSet(popupAllActive)
    )
    )
    )

    axlDBTransactionCommit(mark)
    )
    ))

    ;Return the via pad diameter from the selected subclass
    defun( CreateShapeByVia_viaDia (via @optional (subclass, "TOP"))
    let((pad, bbox)
    pad = axlDBGetPad(via, strcat("VIA CLASS/", subclass), "regular")
    bbox = pad ->bBox
    if(pad ->figureName == "CIRCLE" then
    max(abs(caadr(bbox) - caar(bbox)), abs(cadadr(bbox) - cadar(bbox))); Maximum of x and y extents.
    else
    axlDistance(car(bbox), cadr(bbox))
    )
    ))

    ;Return a list of all the pair combinations of the objects passed.
    defun( CreateShapeByVia_PairCombinations (objs)
    let((obj1, objPairs)
    while(objs
    obj1 = car(objs)
    objs = cdr(objs)
    foreach(obj2, objs, objPairs = cons(list(obj1, obj2), objPairs))
    )
    objPairs
    ))

    ; Create a polygon that encompasses the tangential boundaries of two circles of differeing sizes.
    defun( CreateShapeByVia_circleCircleTangentialPoly (cpt1, r1, cpt2, r2 @optional layer, netName, parent)
    let((x1, y1, x2, y2, ang1, ang2, ang, pt1, pt2, pt3, pt4, path, poly)
    x1 = car(cpt1), y1 = cadr(cpt1)
    x2 = car(cpt2), y2 = cadr(cpt2)
    ang1 = -atan2(y2-y1, x2 - x1)
    ang2 = asin((r2 - r1) / sqrt((x2 - x1)**2 + (y2 - y1)**2))
    ang = ang1 - ang2
    pt1 = list(x1 + r1 * sin(ang), y1 + r1 * cos(ang))
    pt3 = list(x2 + r2 * sin(ang), y2 + r2 * cos(ang))
    ang = ang1 + ang2
    pt2 = list(x1 - r1 * sin(ang), y1 - r1 * cos(ang))
    pt4 = list(x2 - r2 * sin(ang), y2 - r2 * cos(ang))
    path = axlPathStart(list(pt1, pt3))
    axlPathArcCenter(path, nil, pt4, t, cpt2)
    axlPathLine(path, nil, pt2)
    axlPathArcCenter(path, nil, pt1, t, cpt1)
    poly = car(axlPolyFromDB(path))
    when(layer, axlDBCreateShape(poly, t, layer, netName, parent))
    poly
    ))

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • eDave
    0 eDave over 1 year ago in reply to eDave

    This is a more complex solution but should get around your problem.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
  • zpofrp
    0 zpofrp over 1 year ago in reply to eDave

    nice, thanks you very much.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel
<>
Cadence Guidelines

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information