# Is it possible to filter an instance on a circular shape ?

Hello,
I want to remove instances which do not overlap with a circular form using a Python script.
For sure, Klayout gives the possibility to check the overlap betwwen two boxes, but I don't see how to check the overlap between a box and a circular form.

``````box=....
if not box.overlaps(db.Box(inst.bbox())):
inst.delete()
``````

Thank you.

Regards,

## Comments

• @ahmedo

This will find all boxes outside of a layer/circle
Run the script and you will see a circle with boxes inside,
click undo and you can see what has been removed

``````# Enter your Python code here
import pya
import array
import sys
import math
import time

mw = pya.Application.instance().main_window()
layout = pya.Application.instance().main_window().current_view().active_cellview().layout()
topcell = pya.Application.instance().main_window().current_view().active_cellview().cell
lv = pya.Application.instance().main_window().current_view()

if layout == None:
raise Exception("No layout")

cv = pya.Application.instance().main_window().current_view().active_cellview()

dbu =layout.dbu

cell = pya.Application.instance().main_window().current_view().active_cellview().cell
if cell == None:
raise Exception("No cell")

n =   2000 # number of points
r =   2*2  # radius
da = 2 * math.pi / n

def coords(path):
result = []
for p in path:
result.append(DPoint.new(p/dbu,p/dbu))
return result

def create_polygon(crd,lay):
layer_info = LayerInfo.new(lay,0)
layer_index = layout.layer(layer_info)
cv.cell.shapes(layer_index).insert(Polygon.new(crd))

def create_box(crd,lay):
layer_info = LayerInfo.new(lay,0)
layer_index = layout.layer(layer_info)
cv.cell.shapes(layer_index).insert(Box.new(crd,crd))

circle = []
for i in range(0, n):
path = r * math.cos(i * da), r * math.sin(i * da)
circle.append(path)

lay1 = 9
lay2 = 5

pth = coords(circle)
create_polygon(pth,lay1)

box = [(-6.818,-1.185), (-5.195,3.591)]
crd = coords(box)
create_box(crd,lay2)

box = [(5.742,-2.333), (7.674,2.771)]
crd = coords(box)
create_box(crd,lay2)

box = [(-2.827,0.849), (-1.326,2.469)]
crd = coords(box)
create_box(crd,lay2)

box = [(0.730,-2.708), (2.231,-1.088)]
crd = coords(box)
create_box(crd,lay2)

def cut_region(lay1,lay2):
lv.transaction("Undo")

lif1 = LayerInfo.new(lay1,0)
li1 = layout.layer(lif1)

lif2 = LayerInfo.new(lay2,0)
li2 = layout.layer(lif2)
r1 = pya.Region(topcell.begin_shapes_rec(li1))
r2 = pya.Region(topcell.begin_shapes_rec(li2))

#Boolean Functions
#outside  = r1 -  r2
#outside  = r2 - r1
#outside  = r2 + r1
#outside  = r1 + r2
#outside  = r1 & r2
outside  = r2 & r1
#outside  = r2 ^ r1
#outside  = r1 ^ r2

layout.clear_layer(li2)
output = layout.layer(lif2)
topcell.shapes(output).insert(outside)

lay1 = 9
lay2 = 5
cut_region(lay1,lay2)

lv.commit()

``````
• If I understand @ahmedo correctly he said not overlapping, so instead of
`outside = r2 & r1`
it should be
`not_outside = r2.select_not_outside(r1)`
and then
`topcell.shapes(output).insert(not_outside)`

`r1 & r2` will cut parts of boxes that are outside of the circle.

• @sebastian

I may have misread .. but good point and thanks for highlighting this, we all learn

• No worries ^^. I also think overlapping is not clearly defined in daily speech, so you may very well be correct. Regions were confusing when I started with KLayout, so I wanted to point out that there are fancy options in the regions included that might save a lot of time.

• Thank you @tagger5896 and @sebastian for your valuable help.

I will make a test with your code. I see that the code looks for the name of the layout at the beginning, so I guess I need to run the script using the command line:
`klayout -r <script.py> my.gds`

Is it right ?

By the way I have implemented a solution that allows me to check the overlap:

``````filter_poly = db.Polygon(circular_shape.polygon)
for inst in layout_insts:
# Define the 4 points of the instance box
llp = db.Point(inst.bbox().left,inst.bbox().bottom)
lrp = db.Point(inst.bbox().right,inst.bbox().bottom)
tlp = db.Point(inst.bbox().left,inst.bbox().top)
trp = db.Point(inst.bbox().right,inst.bbox().top)

let = 0
if filter_poly.inside(llp) or filter_poly.inside(lrp) or filter_poly.inside(tlp) or filter_poly.inside(trp):
let = 1

# if let = 0 , then remove instance.
if let == 0 :
inst.delete()
``````

Regards

• For my question I think that I have undestood that @tagger5896 's code should be executed from macro menu I'm used to creating scripts that I execute always in batch mode.

Regards

• @ahmedo
You should have an open layout and run the code from the Macro IDE menu yes.

• @tagger5896

Thank you so much for your help.

Regards

• @sebastian
thanks for pointing this out ... floodgates open and the sea's part,
and yes this makes it easier not_outside = r2.select_not_outside(r1)

Sign In or Register to comment.
{"ft_lang_label":"__label__en","ft_lang_prob":0.9204679,"math_prob":0.9238991,"size":2218,"snap":"2021-04-2021-17","text_gpt3_token_len":545,"char_repetition_ratio":0.10117435,"word_repetition_ratio":0.0,"special_character_ratio":0.23038773,"punctuation_ratio":0.11633109,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9812172,"pos_list":[0,1,2,3,4,5,6],"im_url_duplicate_count":[null,null,null,null,null,8,null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2021-04-17T22:50:28Z\",\"WARC-Record-ID\":\"<urn:uuid:b782cee5-3d4f-4e3c-931d-4b914abbc8d8>\",\"Content-Length\":\"44637\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:90a8af8e-9b6a-4c43-9916-ca178d8506d6>\",\"WARC-Concurrent-To\":\"<urn:uuid:523720d1-07a1-4408-bf55-b90ca12711bc>\",\"WARC-IP-Address\":\"185.21.102.151\",\"WARC-Target-URI\":\"https://www.klayout.de/forum/discussion/1789/is-it-possible-to-filter-an-instance-on-a-circular-shape\",\"WARC-Payload-Digest\":\"sha1:UVSBBJ6LZ7SWSAOOVXI5TUVSAAOM4WVC\",\"WARC-Block-Digest\":\"sha1:TYDVK5A2GZNRFC4Z5XZOKPWCKDGG525G\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2021/CC-MAIN-2021-17/CC-MAIN-2021-17_segments_1618038464065.57_warc_CC-MAIN-20210417222733-20210418012733-00210.warc.gz\"}"}