• 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. PCell Designer
  3. How to split a shape along a defined line?

Stats

  • State Not Answered
  • Replies 1
  • Subscribers 9
  • Views 66
  • Members are here 0

How to split a shape along a defined line?

Kevin Earls
Kevin Earls 3 days ago

I've found myself wanting to split shapes into multiple shapes many times. What is the best way to split a rectangle into multiple pieces along lines/or edges that bisects the shape?


The geo->tile command doesn't work on a rectangle.
The geo->bisect command only gives you half the shape and you can't specify the split line.
Any use of land or lor merges any abutting shapes I've already split.
I even looked into dropping into skill to try to use leSplitShape, but that doesn't really create multiple shapes.

Ideally, I'd have one command that takes a named shape (which can contain multiple rectangles or polygons) and a named shape consisting of edges that may or may not bisect the shapes, and return all the shapes, where those shapes which are bisected by the edges are split into multiple shapes along the edges.

Think of a big square where I want to make an asymmetrical tic-tac-toe box out of it.

Anyone have a solution that doesn't take half a dozen complex geo commands, a couple of stretch commands, and a bunch of intermediary measurement steps?

  • Cancel
  • Sign in to reply
  • Andrew Beckett
    0 Andrew Beckett 9 hours ago

    We don't have (as far as I know) anything direct that does this, but it's not too difficult to achieve with the chop command. The chop command requires a shape (not just an edge), but with a little bit of manipulation this can be achieved. The basic approach I used was:

    1. resize (shrink) the source shape by a small amount (e.g. -0.001)
    2. Chop using everyedge of some shapes to identify the places to split, with these edges grown by 0.001
    3. resize (grow) the results by the same small amount (0.001) to remove the gaps caused by the grown edges

    Attached is a pcd.txt file doing this with a gpdk045-based example. I created a custom command to make it a bit clearer.  Some pictures showing the steps:

    The green (Poly) shape is what is going to be split, and I'm going to use the yellow (Nimp) edges to identify the split points. The custom command I've created "split on edge" has these inputs/outputs:

    Here's the method itself - hopefully from this (without showing the geo query editor) you can see it's just doing a grow on the "edges" input, and the edges input above is using the everyedge operator on the splitRegions group.. The resize commands below are sizing down the input shape and then sizing up the results afterwards.

    This then gives this result:

    Hope that helps! We'll also think whether a more direct (this is not too indirect, though) split command could be added. Note using leSplitShape won't be an option because that's not PCell-safe.

    Regards,

    Andrew

    Fullscreen Split_layout.pcd.txt Download
    ;;; PCell Designer File (format version 2.2)
    
    ;;; File-out of the PCell Designer pcell "NmosDemo24"/"KevinEarlsSplit"/"layout"
    
    (pcdPcell
    
    ;; Mixins
    ?mixins
    nil
    
    ;; Create CDF?
    ?createCDF
    t
    
    ;; Reference cell for CDF
    ?referenceCDF
    nil
    
    ;; Main points
    ?mainPoints
    nil
    
    ;; Initial size
    ?initSize
    nil
    
    ;; Device Variables
    ?devVars
    nil
    
    ;; Device Variables visible to the commands
    ?guiVisibleDevVarNames
    nil
    
    ;; Methods used as commands
    ?methodCommands
    nil
    
    ;; PCell and CDF Parameters
    ?classEditorChanges
    ()
    
    ;; Simulation Information
    ?simulation
    (simulation)
    
    ;; Source Cell View
    ?sourceCellView
    ("NmosDemo24" "KevinEarlsSplit" "layout")
    
    ;; Last Edited with PCell Designer Version
    ?pcdVersion
    "2-5-28"
    
    ;; Method definitions
    ?methods
    (
      (newCommand command (newCommand
                           ?name split\ on\ edge
                           ?commandClass pcmdCommand
                           ?category "Custom"
                           ?help "Split shapes based on edges passed in"
                           ?parameters (result (lvalue nil ?valuep t ?requiredp t ?isExpression t ?keyword t) shapes (geo (geo grow 0 type "Group" points nil group nil name nil net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Shapes to split") edges (geo (geo grow 0 type "Group" points nil group nil name nil net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Edges to use to split shape on") edge_grow_factor (float "0.001" ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Small dimension used to grow edges for chopping")))
        body (
        (resize 
          source (geo (geo type "Name" points nil group "shapeToSplit" name "shapes" net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The shapes to modify.")
          amount (enclosure "-edge_grow_factor" ?valuep t ?requiredp t ?isExpression t ?keyword ?enclosure ?help "The amount to grow."))
        (chop 
          name (lvalue "result" ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The resulting shapes.")
          source (geo (geo type "Name" points nil group "shapeToSplit" name "shapes" net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The shapes to chop.")
          chop (geo (geo type "Expression" points nil group "splitRegions" name nil net nil expression (append (grow evalstring("edge_grow_factor") (name "edges")))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The mask to remove from the shapes in <i>source</i>.")
          layer (layer "nil" ?valuep nil ?requiredp nil ?isExpression nil ?keyword t ?help "If provided, the chopped shapes will be moved to this layer.")
          cut_path (boolean nil ?valuep t ?requiredp t ?isExpression nil ?keyword t ?help "If true, paths will be cut instead of chopped. This works only with manhattan path segments")
          chop_layers (boolean nil ?valuep t ?requiredp t ?isExpression nil ?keyword t ?help "If true, shapes in *chop* will only chop shapes on the same layer, with the exception being any shapes in notch on y0 being treated as wildcards -- they will chop all layers. If false (the default) all area in *notch* will chop all shapes in *source*."))
        (resize 
          source (geo (geo type "Name" points nil group "shapeToSplit" name "result" net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The shapes to modify.")
          amount (enclosure "edge_grow_factor" ?valuep t ?requiredp t ?isExpression t ?keyword ?enclosure ?help "The amount to grow."))
        
        ))
        
      (method command draw
        body (
        (group 
          ?renderInfo (?renderAsFigGroup nil)
          name (group "shapeToSplit" ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The name of the group to create")
          body 
          (body (
            (rectangle 
              name (lvalue "" ?valuep t ?requiredp nil ?isExpression nil ?keyword nil ?help "The created rectangles, if any.")
              layer (layer ("Poly" "drawing") ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The layer or LPP for the created rectangles.")
              source (geo (geo type "Points" points ((0.865 1.37) (26.005 1.37) (26.005 14.11) (0.865 14.11))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The bounding boxes of the rectangles to create."))
            )
            ?valuep t
            ?requiredp t
            ?isExpression t
            ?keyword nil
          )
          lock (boolean nil ?valuep t ?requiredp t ?isExpression nil ?keyword t ?help "Add the shapes to a figGroup rather than a group"))
        (group 
          ?renderInfo (?renderAsFigGroup nil)
          name (group "splitRegions" ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The name of the group to create")
          body 
          (body (
            (para 
              body 
              (body (
                (rectangle 
                  name (lvalue "" ?valuep t ?requiredp nil ?isExpression nil ?keyword nil ?help "The created rectangles, if any.")
                  layer (layer ("Nimp" "drawing") ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The layer or LPP for the created rectangles.")
                  source (geo (geo type "Points" points ((-0.25 6.845) (27.685 6.845) (27.685 9.19) (-0.25 9.19))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The bounding boxes of the rectangles to create."))
                )
                ?valuep t
                ?requiredp t
                ?isExpression t
                ?keyword nil
              )
              scratch (boolean t ?valuep t ?requiredp t ?isExpression nil ?keyword t))
            (para 
              body 
              (body (
                (rectangle 
                  name (lvalue "" ?valuep t ?requiredp nil ?isExpression nil ?keyword nil ?help "The created rectangles, if any.")
                  layer (layer ("Nimp" "drawing") ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The layer or LPP for the created rectangles.")
                  source (geo (geo type "Points" points ((6.005 -1.87) (8.91 -1.87) (8.91 16.12) (6.005 16.12))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The bounding boxes of the rectangles to create."))
                )
                ?valuep t
                ?requiredp t
                ?isExpression t
                ?keyword nil
              )
              scratch (boolean t ?valuep t ?requiredp t ?isExpression nil ?keyword t))
            (para 
              body 
              (body (
                (rectangle 
                  name (lvalue "" ?valuep t ?requiredp nil ?isExpression nil ?keyword nil ?help "The created rectangles, if any.")
                  layer (layer ("Nimp" "drawing") ?valuep t ?requiredp t ?isExpression nil ?keyword nil ?help "The layer or LPP for the created rectangles.")
                  source (geo (geo type "Points" points ((15.95 -1.985) (18.52 -1.985) (18.52 16.23) (15.95 16.23))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword nil ?help "The bounding boxes of the rectangles to create."))
                )
                ?valuep t
                ?requiredp t
                ?isExpression t
                ?keyword nil
              )
              scratch (boolean t ?valuep t ?requiredp t ?isExpression nil ?keyword t))
            )
            ?valuep t
            ?requiredp t
            ?isExpression t
            ?keyword nil
          )
          lock (boolean nil ?valuep t ?requiredp t ?isExpression nil ?keyword t ?help "Add the shapes to a figGroup rather than a group"))
        (split\ on\ edge 
          result (lvalue "aftersplit" ?valuep t ?requiredp t ?isExpression nil ?keyword t)
          shapes (geo (geo grow 0 type "Group" points nil group "shapeToSplit" name nil net nil expression nil) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Shapes to split")
          edges (geo (geo type "Expression" points nil group nil name nil net nil expression (append (everyedge (group ("splitRegions"))))) ?lazyp nil ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Edges to use to split shape on")
          edge_grow_factor (float "0.001" ?valuep t ?requiredp t ?isExpression t ?keyword t ?help "Small dimension used to grow edges for chopping"))
        
        ))
        )
    
    ;; Imported local (Skill++) definitions
    ?importedCode
    nil
    
    ;; Saved state of the GUI
    ?guiData
    (nil
     selectedCommands nil
     activeTab "draw"
     openTabs ("split on edge" "draw")
     commandPaletteSelection (pcdGuiNK_CommandPalette_AllCommand_split_20on_20edge)
     commandPalette (nil
                     Modify t))
    
    )
    

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • Verify Answer
    • Cancel

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