def testHit(self, pt: QPoint, radius: int): return Geom.distPtToSegment(pt, self.pt1, self.pt2) <= radius
def touchesPt(self, pt): # check if point is on this segment # print("net touch: {} {} : {}".format(str(self), pt, Geom.pointOnSegment(self.pt1, self.pt2, pt))) return Geom.pointOnSegment(self.pt1, self.pt2, pt)
def intersectsNet(self, net): return Geom.segsIntersect(self.pt1, self.pt2, net.pt1, net.pt2)
def addNet(self, newNet): # print("new net ({},{})->({},{})".format(newNet.pt1.x(), newNet.pt1.y(), newNet.pt2.x(), newNet.pt2.y())) # this algorithm normalizes the nets such that nets touch only at endpoints origin = newNet.pt1 newDir = newNet.pt2 - newNet.pt1 unitNewDir = QPointF(newDir) unitNewDir /= Geom.norm(unitNewDir) # nets to be deleted netsDel = set() netsAdd = set() # find any non-parallel nets that need to be split splitP1 = self._ctrl.doc.findObjsNear(newNet.pt1, objType=NetObj) splitP2 = self._ctrl.doc.findObjsNear(newNet.pt2, objType=NetObj) for net in splitP1: if (net.touchesPt(newNet.pt1) and not Geom.isParallel(newDir, net.pt2-net.pt1) and not net.connVtx(newNet)): netsDel.add(net) netsAdd.add(NetObj(newNet.pt1, net.pt1)) netsAdd.add(NetObj(newNet.pt1, net.pt2)) for net in splitP2: if (net.touchesPt(newNet.pt2) and not Geom.isParallel(newDir, net.pt2-net.pt1) and not net.connVtx(newNet)): netsDel.add(net) netsAdd.add(NetObj(newNet.pt2, net.pt1)) netsAdd.add(NetObj(newNet.pt2, net.pt2)) # find all intersecting nets xsnets = {net for net in self._ctrl.doc.findObjsInRect(newNet.bbox(), objType=NetObj) if newNet.intersectsNet(net)} # collinear nets (which need to be replaced) clnets = {net for net in xsnets if Geom.isParallel(newDir, net.pt2-net.pt1)} # print("collinear: " + str(clnets)) xsnets -= clnets # remove collinear nets from set of intersections # compute union of all nets to be replaced # coordinates of united nets (projected onto newDir); initialize with new net coords coords = {0, Geom.dotProd(unitNewDir, newNet.pt2-origin)} for net in clnets: if net.touchesPt(newNet.pt1) and net.touchesPt(newNet.pt2): # print("Not adding redundant net") return # new net is redundant because it is on top of an existing net coords.add(Geom.dotProd(unitNewDir, net.pt1-origin)) coords.add(Geom.dotProd(unitNewDir, net.pt2-origin)) netsDel |= clnets # find all intersection points minc = min(coords) maxc = max(coords) unitedNet = NetObj((origin+minc*unitNewDir).toPoint(), (origin+maxc*unitNewDir).toPoint()) # these nets touch the new net with an endpoint xsP1 = {net for net in xsnets if unitedNet.touchesPt(net.pt1) and not unitedNet.connVtx(net)} xsP2 = {net for net in xsnets if unitedNet.touchesPt(net.pt2) and not unitedNet.connVtx(net)} # print("touching: " + str(xsP1 | xsP2)) xscoords = {minc, maxc} for net in xsP1: xscoords.add(Geom.dotProd(unitNewDir, net.pt1-origin)) for net in xsP2: xscoords.add(Geom.dotProd(unitNewDir, net.pt2-origin)) xscoords = list(xscoords) xscoords.sort() # print(xscoords) p1 = xscoords.pop(0) while xscoords: p2 = xscoords.pop(0) netsAdd.add(NetObj((origin+p1*unitNewDir).toPoint(), (origin+p2*unitNewDir).toPoint())) p1 = p2 cmd = QUndoCommand() for obj in netsDel: # print("deleting {}".format(str(obj))) sch.document.ObjDelCmd(obj, doc=self._ctrl.doc, parent=cmd) for obj in netsAdd: # print("adding: {}".format(str(obj))) sch.document.ObjAddCmd(obj, doc=self._ctrl.doc, parent=cmd) self._ctrl.doc.doCommand(cmd)