• 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 program for creating shapes from closed polygon lines...

Stats

  • Replies 2
  • Subscribers 19
  • Views 6993
  • Members are here 0
More Content

SKILL program for creating shapes from closed polygon lines.

KAUSHAL S
KAUSHAL S over 3 years ago

I am working on composing shape from closed polygon lines ( Rectangle/ Square/ Circle/ Rounded corners polygon).

The Polygon lines are manually drawn in Allegro tool (*.dra  file)

Element type: Lines

Shape to be composed in Package Geometry-> Soldermask_Top

Problem I face is I'm able to get the dbid from all lines. but unable to compose the shape.  Could anyone help me to guide me in creating the SKILL

  • Cancel
  • Sign in to reply
Parents
  • ebecheto
    ebecheto over 3 years ago

    Hi Kaushal,

    A long time ago, i played a little with Allegro skill. I can share an example of drawing a losange using axlDBCreateOpenShape and axlDBCreateCloseShape

    Maybe that will help you, maybe not. In any case; i cannot give support on that code since i do not use anymore allegro.

    procedure( losangeA(@optional (xy 0:0) (a 50) (d 0.2) (net "GND") (via t))
    (let (x y xy1) x=car(xy) y=cadr(xy)
    when(via (axlDBCreateVia "via" x+a/2:y+a*sqrt(3)/2 net))
    segments=(list
    xy1=x+d/sqrt(3):y+d
    x+2*a-d*sqrt(3):y+d
    x+a-d/sqrt(3):y+a*sqrt(3)-d
    x+d*sqrt(3)-a:y+a*sqrt(3)-d
    xy1)
    (setq shape (axlDBCreateOpenShape (axlPathStart segments) t "ETCH/TOP" net))
    (axlDBCreateCloseShape shape)))
    
    losangeA(8000:1000 5000 100 "GND_POWER" nil)
    
    procedure( losangeB(@optional (xy 0:0) (a 50) (d 0.2) (net "GND") (via t))
    (let (x y xy1)
    x=car(xy) y=cadr(xy)
    when(via (axlDBCreateVia "via" x+a/2:y-a*sqrt(3)/2 net))
    segments=(list
    xy1=x+d/sqrt(3):y-d
    x+2*a-d*sqrt(3):y-d
    x+a-d/sqrt(3):y-a*sqrt(3)+d
    x+d*sqrt(3)-a:y-a*sqrt(3)+d
    xy1)
    (setq shape (axlDBCreateOpenShape (axlPathStart segments) t "ETCH/TOP" net))
    (axlDBCreateCloseShape shape)))
    
    procedure( losangeC(@optional (xy 0:0) (a 50) (d 0.2) (net "GND") (via t))
    (let (x y xy1)
    x=car(xy) y=cadr(xy)
    when(via (axlDBCreateVia "via" x-a:y net))
    segments=(list
    xy1=x-2*d/sqrt(3):y
    x-a:y+a*sqrt(3)-2*d
    x-2*a+2*d/sqrt(3):y
    x-a:y+2*d-a*sqrt(3)
    xy1)
    ;printf("check segments:%L\n" segments)
    (setq shape (axlDBCreateOpenShape (axlPathStart segments) t "ETCH/TOP" net))
    (axlDBCreateCloseShape shape)))
    
    
    ; --
    
    ;; ;losangeA()
    ;; ; losangeA(400:400 50 0.5 nil)
    ; losangeA(280:230 10 0.5 nil)
    ;; losangeB(280:230 10 0.5 nil)
    ;; losangeC(280:230 10 0.5 nil)
    
    procedure( trihexa(@optional (xy 280:230) (a 10) (d 0.2)(nets nil) (lays nil)(wirs nil)(siz nil))
    (let (x y)
    unless(nets nets='("Neta" "Netb" "Netc" ))
    unless(lays lays='("ETCH/SOUSTOP" "ETCH/SURBOTTOM" "ETCH/BOTTOM"))
    unless(wirs wirs='(0 0 0))
    unless(siz siz=0.2)
    x=car(xy) y=cadr(xy)
    losangeA(xy a d nth(0 nets))
    losangeB(xy a d nth(1 nets))
    losangeC(xy a d nth(2 nets))
    ; printf("wire:%L\n" wirs)
    wire=nth(0 wirs)(cond
    (wire==1 pts=list(x+a/2:y+a*sqrt(3)/2 x+2*a:y+2*a*sqrt(3)))
    (wire==2 pts=list(x+a/2:y+a*sqrt(3)/2 x-a:y-a*sqrt(3)))
    (wire==0 pts=list(x-2*a:y-2*a*sqrt(3) x+a:y+a*sqrt(3) ))(t pts='()))
    axlDBCreatePath(axlPathStart(pts siz) nth(0 lays) nth(0 nets))
    wire=nth(1 wirs)(cond
    (wire==1 pts=list(x+a/2:y-a*sqrt(3)/2 x+2*a:y-2*a*sqrt(3)))
    (wire==2 pts=list(x+a/2:y+a*sqrt(3)/2 x-a:y-a*sqrt(3)))
    (wire==0 pts=list(x-2*a:y+2*a*sqrt(3) x+a:y-a*sqrt(3) ))(t pts='()))
    axlDBCreatePath(axlPathStart(pts siz) nth(1 lays) nth(1 nets))
    wire=nth(2 wirs)(cond
    (wire==1 pts=list(x-a:y x+4*a:y))
    (wire==2 pts=list(x-2*a:y x-a:y))
    (wire==0 pts=list(x-2*a:y x+4*a:y))(t pts='()))
    axlDBCreatePath(axlPathStart(pts siz) nth(2 lays) nth(2 nets))
    ))
    
    ;; trihexa(100:300 10 4)
    ;; trihexa(100:300 10 0 gnd bot)
    
    defun(add (a b) list(car(a)+car(b) cadr(a)+cadr(b)))
    ;add(xy1 xy2)
    
    
    defun( guidhexa (@optional (xy 200:200) (a 10) (d 3)(nets nil) (lays nil))
    unless(nets nets='("GND" "GND" "GND"))
    unless(d d=a/3)
    bot='("ETCH/BOTTOM" "ETCH/BOTTOM" "ETCH/BOTTOM")
    trihexa(xy a d )
    ;trihexa(xy a 0 nets bot)
    ;; --- hexagonal surrounding
    pts='() pt0=car(xy)+2*a:cadr(xy)
    for(i 0 6 pts=append(pts list(axlGeoRotatePt(i*60.0 pt0 xy))))
    axlDBCreatePath(axlPathStart(pts) car(lays) car(nets))
    ;; --- hexagonal surrounding
    axlDBCreateCircle((list xy 2*a))
    axlDBCreateCircle((list xy 2*d/sqrt(3)))
    xyc=add(xy 2*a:0)
    for(i 0 5 axlDBCreateCircle( (list axlGeoRotatePt(i*60.0 xyc xy) 2*d/sqrt(3))))
    xys=foreach(mapcar n '(-1 0 1) X=2*a+d*sqrt(3) Y=n*d list(X:Y X*(-1):Y))
    xyds=foreach(mapcar s xys list(add(xy car(s)) add(xy cadr(s))))
    for(i 0 2
    foreach( xyr xyds  ;xyr=car( xyds)
    lft=car(xyr) rgt=cadr(xyr)
    lftr=axlGeoRotatePt(i*60.0 lft xy)
    rgtr=axlGeoRotatePt(i*60.0 rgt xy)
    axlDBCreateLine(list(lftr rgtr))
    ))
    dold=d
    d=2*a*sqrt(3)
    axlDBCreateLine(list(add(xy 1.5*a:sqrt(3)*a/2) add(xy 1.5*a-sqrt(3)*d/2:sqrt(3)*a/2-d/2)) 0 "etch/blabla")
    d=dold
    )
    
    guidhexa(450:300)
    
    ;; axlGeoRotatePt(60.0 pt0 xy)
    ;; x=60 y=60 a=10
    ;; xy=x:y
    ;; pts='()
    ;; pt0=x+2*a:y
    ;; for(i 0 6 pts=append(pts list(axlGeoRotatePt(i*60.0 pt0 xy))))
    ;; axlDBCreatePath(axlPathStart(pts) car(lays) car(nets))
    
    xy=450:200 pts='() a=10 pt0=car(xy)+2*a:cadr(xy)
    for(i 0 6 pts=append(pts list(axlGeoRotatePt(i*60.0 pt0 xy))))
    axlDBCreatePath(axlPathStart(pts))
    

    Hope it helps,

    ++

    • Cancel
    • Vote Up -1 Vote Down
    • Sign in to reply
    • Cancel
  • mstaub
    mstaub over 3 years ago in reply to ebecheto

    I actually just wrote a tool that does this exact thing.

    For 17.2 users this process is a littler more complex (similar to what ebecheto shows above). To summarize you will want to use a combination of the follow:

    Once you have the dbid/s of the line you will want to create a path object from the line segments (o_lineDbid->segments) using the path functions:

    axlPathStart()

    axlPathLine()

    axlPathArcRadius()

    and so on...

    Once you have this path object you can then use it to create a poly object using

    axlPolyFromDB()

    Note: this function returns a list and you will want to use the first element to create your shape (ie. myPoly = car(axlPolyFromDB(...)) )

    Finally we can use this poly object to create our shape using:

    axlDBCreateShape()

    or 

    axlDBCreateOpenShape() and axlDBCreateCloseShape()

    Note: Both methods accept and r_path obect to define the boundary of the shape so you might even be able to skip creating the poly object. I haven't tried this to see how it works.

    Why is the 17.2 method more complex? Say you draw a rectangle but want to use that to create a shape with rounded corners. This will require you to go down a fun path of trig to modify your r_path object to change the segments and add arcs. I recently did this, and it might be what ebecheto is doing as well (I just haven't thoroughly looked at the code). This just complicates the code.

    Luckily all of this is simplified if you are using 17.4...

    For 17.4 this process has become a lot easier. There is a new Skill function that mimics that of Shape->Compose Shape. 

    All you need to do is have the dbids of the line you draw and pass o_lineDbid->segments as the first argument in the function below and you shape is created!

    axlDBComposeShapesFromLines(
    o_dbid/lo_dbids
    n_maxGap
    n_cornerRadius
    t_layer
    b_shapeFill
    [t_netName]
    [b_deleteLines]
    )
    ⇒ o_dbid/lo_dbids/error string

    o_dbid/lo_dbids

    Any combination of line segments, lines, and shapes in the database for conversion. The shapes may become voids in other shapes, and so on, based on the nesting of the resulting shapes that are created.

    n_maxGap

    The maximum air gap between vertices, which should be close enough to create a closed shape outline. This argument corresponds to the Maximum gap option of the compose shape command. If nil, the value is computed from the provided segments.

    n_cornerRadius

    Radius for corners, if corners are to be rounded. This argument corresponds to the Radius option of the compose shape command. If nil, corners are not rounded.

    t_layer

    Destination layer on which shape is to be created

    b_shapeFill

    Either t or nil:

    • t: creates a solid-filled shape
    • nil: creates an unfilled shape

    Certain layers are allowed to have only one type of shape. If the specified destination layer only allows one shape fill state, this argument is ignored, and the layer's required shape type is used.

    [t_netName]

    Net assigned to the shape. Only applicable when creating shapes on cross-section layers.

    [b_deleteLines]

    t/nil indicates whether the lines used in the construction of the shapes should be deleted. Lines not incorporated into a shape are never deleted.

    Like I said, I literally just did this using both the 17.2 and 17.4 implementations. Let me know if you need any additional help.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
Reply
  • mstaub
    mstaub over 3 years ago in reply to ebecheto

    I actually just wrote a tool that does this exact thing.

    For 17.2 users this process is a littler more complex (similar to what ebecheto shows above). To summarize you will want to use a combination of the follow:

    Once you have the dbid/s of the line you will want to create a path object from the line segments (o_lineDbid->segments) using the path functions:

    axlPathStart()

    axlPathLine()

    axlPathArcRadius()

    and so on...

    Once you have this path object you can then use it to create a poly object using

    axlPolyFromDB()

    Note: this function returns a list and you will want to use the first element to create your shape (ie. myPoly = car(axlPolyFromDB(...)) )

    Finally we can use this poly object to create our shape using:

    axlDBCreateShape()

    or 

    axlDBCreateOpenShape() and axlDBCreateCloseShape()

    Note: Both methods accept and r_path obect to define the boundary of the shape so you might even be able to skip creating the poly object. I haven't tried this to see how it works.

    Why is the 17.2 method more complex? Say you draw a rectangle but want to use that to create a shape with rounded corners. This will require you to go down a fun path of trig to modify your r_path object to change the segments and add arcs. I recently did this, and it might be what ebecheto is doing as well (I just haven't thoroughly looked at the code). This just complicates the code.

    Luckily all of this is simplified if you are using 17.4...

    For 17.4 this process has become a lot easier. There is a new Skill function that mimics that of Shape->Compose Shape. 

    All you need to do is have the dbids of the line you draw and pass o_lineDbid->segments as the first argument in the function below and you shape is created!

    axlDBComposeShapesFromLines(
    o_dbid/lo_dbids
    n_maxGap
    n_cornerRadius
    t_layer
    b_shapeFill
    [t_netName]
    [b_deleteLines]
    )
    ⇒ o_dbid/lo_dbids/error string

    o_dbid/lo_dbids

    Any combination of line segments, lines, and shapes in the database for conversion. The shapes may become voids in other shapes, and so on, based on the nesting of the resulting shapes that are created.

    n_maxGap

    The maximum air gap between vertices, which should be close enough to create a closed shape outline. This argument corresponds to the Maximum gap option of the compose shape command. If nil, the value is computed from the provided segments.

    n_cornerRadius

    Radius for corners, if corners are to be rounded. This argument corresponds to the Radius option of the compose shape command. If nil, corners are not rounded.

    t_layer

    Destination layer on which shape is to be created

    b_shapeFill

    Either t or nil:

    • t: creates a solid-filled shape
    • nil: creates an unfilled shape

    Certain layers are allowed to have only one type of shape. If the specified destination layer only allows one shape fill state, this argument is ignored, and the layer's required shape type is used.

    [t_netName]

    Net assigned to the shape. Only applicable when creating shapes on cross-section layers.

    [b_deleteLines]

    t/nil indicates whether the lines used in the construction of the shapes should be deleted. Lines not incorporated into a shape are never deleted.

    Like I said, I literally just did this using both the 17.2 and 17.4 implementations. Let me know if you need any additional help.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • Cancel
Children
No Data
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