; totalPathLength.il ;; Script from Google AI & tweaked to fix RJC ; Should calculate total path length of a path including touching segments ; select a path segment and run CalculateChainedPathLength() ; load("./skill/totalPathLength.il") in CIW ; ; Need to have local writeable library called scratch ; Can get double counting where paths overlap procedure(CalculateChainedPathLength() let((selectedObj cv lpp shapesToVisit visitedShapes totalLength currentObj bbox overlaps newLength) selectedObj = car(geGetSelectedSet()) cv = geGetEditCellView() if(!selectedObj || !(selectedObj~>objType == "pathSeg" || selectedObj~>objType == "path") then error("Please select a starting pathSeg or path object first.") ) lpp = selectedObj~>lpp shapesToVisit = list(selectedObj) visitedShapes = makeTable("visited" nil) totalLength = 0.0 while(shapesToVisit currentObj = car(shapesToVisit) shapesToVisit = cdr(shapesToVisit) unless(visitedShapes[currentObj] visitedShapes[currentObj] = t bbox = currentObj~>bBox ;; Calculate individual segment length case(currentObj~>objType ("pathSeg" ;; dx or dy based on straight paths totalLength = totalLength + dbGetSegLength(currentObj) printf(">> Add getseglen : %f \n" dbGetSegLength(currentObj)) ) ("path" ;; Fallback length calculation for multi-point paths let((prevPt ptLen) ptLen = 0.0 foreach(pt currentObj~>points if(prevPt then ptLen = ptLen + sqrt(expt(car(pt)-car(prevPt) 2) + expt(cadr(pt)-cadr(prevPt) 2)) prevPt = pt else prevPt = pt ) ) totalLength = totalLength + ptLen printf(">> Add mltpntpath len : %f \n" ptLen) ) ) ) ;; Automatically find geometrically touching/overlapping segments on the same layer ;; As bbox is rectangle doesn't work well for diagonals ; overlaps = dbGetTrueOverlaps(cv bbox lpp 0) ;;improved search which copes with diagonals overlaps = MyGetTrueNonOrthogonalOverlaps(cv currentObj lpp) foreach(overlap overlaps when(overlap && (overlap~>objType == "pathSeg" || overlap~>objType == "path") unless(visitedShapes[overlap] shapesToVisit = cons(overlap shapesToVisit) ) ) ) ) ) printf(">>> Total Chained Path Length for the selected trace: %f microns on layer %L\n" totalLength lpp) ) ) ;; Helper function for single straight pathSeg calculation procedure(dbGetSegLength(seg) let((bPt ePt) bPt = seg~>beginPt ePt = seg~>endPt sqrt(expt(car(ePt)-car(bPt) 2) + expt(cadr(ePt)-cadr(bPt) 2)) ) ) procedure(MyGetTrueNonOrthogonalOverlaps(cv searchShape lpp) let((overlaps scratchCv trueOverlaps searchShape_sized) ; 1. Coarse filtering using the bounding box of your search shape overlaps = dbGetTrueOverlaps(cv searchShape~>bBox lpp 0) ; Create a scratch cellview in memory to perform the layer operation safely scratchCv = dbOpenCellViewByType("scratch" "temp" "layout" "maskLayout" "w") ; size operation to create some overlap - assumes there is layer "text" searchShape_sized = dbLayerSize(scratchCv "text" list(searchShape) 0.001) foreach(overlap overlaps unless(overlap == searchShape ; 2. Perform a boolean AND between the shapes ; dbLayerAnd returns a list of resulting shapes if they truly overlap ;if(dbLayerAnd(scratchCv lpp list(searchShape overlap)) then if(dbLayerAnd(scratchCv lpp searchShape_sized list(overlap)) then trueOverlaps = cons(overlap trueOverlaps) ) ) ) ; Clean up the scratch cellview to avoid memory leaks dbClose(scratchCv) trueOverlaps ) ) ;; Bind the script to Shift + L hiSetBindKey("Layout" "Shiftl" "CalculateChainedPathLength()")