def setTrackers(self): v = Draft.get3DView() if v in self.trackers[0]: i = self.trackers[0].index(v) self.grid = self.trackers[1][i] self.tracker = self.trackers[2][i] self.extLine = self.trackers[3][i] self.radiusTracker = self.trackers[4][i] self.dim1 = self.trackers[5][i] self.dim2 = self.trackers[6][i] else: if Draft.getParam("grid"): self.grid = DraftTrackers.gridTracker() else: self.grid = None self.tracker = DraftTrackers.snapTracker() self.extLine = DraftTrackers.lineTracker(dotted=True) self.radiusTracker = DraftTrackers.radiusTracker() self.dim1 = DraftTrackers.archDimTracker(mode=2) self.dim2 = DraftTrackers.archDimTracker(mode=3) self.trackers[0].append(v) self.trackers[1].append(self.grid) self.trackers[2].append(self.tracker) self.trackers[3].append(self.extLine) self.trackers[4].append(self.radiusTracker) self.trackers[5].append(self.dim1) self.trackers[6].append(self.dim2) if self.grid and (not self.forceGridOff): self.grid.set()
def snap(self,screenpos,lastpoint=None,active=True,constrain=False): """snap(screenpos,lastpoint=None,active=True,constrain=False): returns a snapped point from the given (x,y) screenpos (the position of the mouse cursor), active is to activate active point snapping or not (passive), lastpoint is an optional other point used to draw an imaginary segment and get additional snap locations. Constrain can be True to constrain the point against the closest working plane axis. Screenpos can be a list, a tuple or a coin.SbVec2s object.""" global Part,fcgeo import Part from draftlibs import fcgeo if not hasattr(self,"toolbar"): self.makeSnapToolBar() mw = getMainWindow() bt = mw.findChild(QtGui.QToolBar,"Draft Snap") if not bt: mw.addToolBar(self.toolbar) else: if Draft.getParam("showSnapBar"): bt.show() def cstr(point): "constrains if needed" if constrain: return self.constrain(point,lastpoint) else: self.unconstrain() return point snaps = [] self.snapInfo = None # type conversion if needed if isinstance(screenpos,list): screenpos = tuple(screenpos) elif isinstance(screenpos,coin.SbVec2s): screenpos = tuple(screenpos.getValue()) elif not isinstance(screenpos,tuple): print "snap needs valid screen position (list, tuple or sbvec2s)" return None # setup trackers if needed v = Draft.get3DView() if v in self.trackers[0]: i = self.trackers[0].index(v) self.grid = self.trackers[1][i] self.tracker = self.trackers[2][i] self.extLine = self.trackers[3][i] else: if Draft.getParam("grid"): self.grid = DraftTrackers.gridTracker() else: self.grid = None self.tracker = DraftTrackers.snapTracker() self.extLine = DraftTrackers.lineTracker(dotted=True) self.trackers[0].append(v) self.trackers[1].append(self.grid) self.trackers[2].append(self.tracker) self.trackers[3].append(self.extLine) # getting current snap Radius if not self.radius: self.radius = self.getScreenDist(Draft.getParam("snapRange"),screenpos) # set the grid if self.grid and Draft.getParam("grid"): self.grid.set() # activate snap oldActive = False if Draft.getParam("alwaysSnap"): oldActive = active active = True if not self.active: active = False self.setCursor('passive') if self.tracker: self.tracker.off() if self.extLine: self.extLine.off() point = self.getApparentPoint(screenpos[0],screenpos[1]) # check if we snapped to something self.snapInfo = Draft.get3DView().getObjectInfo((screenpos[0],screenpos[1])) # checking if parallel to one of the edges of the last objects or to a polar direction if active: eline = None point,eline = self.snapToPolar(point,lastpoint) point,eline = self.snapToExtensions(point,lastpoint,constrain,eline) if not self.snapInfo: # nothing has been snapped, check fro grid snap if active: point = self.snapToGrid(point) return cstr(point) else: # we have an object to snap to obj = FreeCAD.ActiveDocument.getObject(self.snapInfo['Object']) if not obj: return cstr(point) self.lastSnappedObject = obj if hasattr(obj.ViewObject,"Selectable"): if not obj.ViewObject.Selectable: return cstr(point) if not active: # passive snapping snaps = [self.snapToVertex(self.snapInfo)] else: # active snapping comp = self.snapInfo['Component'] if (Draft.getType(obj) == "Wall") and not oldActive: edges = [] for o in [obj]+obj.Additions: if Draft.getType(o) == "Wall": if o.Base: edges.extend(o.Base.Shape.Edges) for edge in edges: snaps.extend(self.snapToEndpoints(edge)) snaps.extend(self.snapToMidpoint(edge)) snaps.extend(self.snapToPerpendicular(edge,lastpoint)) snaps.extend(self.snapToIntersection(edge)) snaps.extend(self.snapToElines(edge,eline)) elif obj.isDerivedFrom("Part::Feature"): if (not self.maxEdges) or (len(obj.Edges) <= self.maxEdges): if "Edge" in comp: # we are snapping to an edge edge = obj.Shape.Edges[int(comp[4:])-1] snaps.extend(self.snapToEndpoints(edge)) snaps.extend(self.snapToMidpoint(edge)) snaps.extend(self.snapToPerpendicular(edge,lastpoint)) #snaps.extend(self.snapToOrtho(edge,lastpoint,constrain)) # now part of snapToPolar snaps.extend(self.snapToIntersection(edge)) snaps.extend(self.snapToElines(edge,eline)) if isinstance (edge.Curve,Part.Circle): # the edge is an arc, we have extra options snaps.extend(self.snapToAngles(edge)) snaps.extend(self.snapToCenter(edge)) elif "Vertex" in comp: # directly snapped to a vertex snaps.append(self.snapToVertex(self.snapInfo,active=True)) elif comp == '': # workaround for the new view provider snaps.append(self.snapToVertex(self.snapInfo,active=True)) else: # all other cases (face, etc...) default to passive snap snapArray = [self.snapToVertex(self.snapInfo)] elif Draft.getType(obj) == "Dimension": # for dimensions we snap to their 3 points for pt in [obj.Start,obj.End,obj.Dimline]: snaps.append([pt,'endpoint',pt]) elif Draft.getType(obj) == "Mesh": # for meshes we only snap to vertices snaps.extend(self.snapToEndpoints(obj.Mesh)) elif Draft.getType(obj) == "Points": # for points we only snap to points snaps.extend(self.snapToEndpoints(obj.Points)) # updating last objects list if not self.lastObj[1]: self.lastObj[1] = obj.Name elif self.lastObj[1] != obj.Name: self.lastObj[0] = self.lastObj[1] self.lastObj[1] = obj.Name if not snaps: return point # calculating the nearest snap point shortest = 1000000000000000000 origin = Vector(self.snapInfo['x'],self.snapInfo['y'],self.snapInfo['z']) winner = [Vector(0,0,0),None,Vector(0,0,0)] for snap in snaps: # if snap[0] == None: print "debug: Snapper: 'i[0]' is 'None'" delta = snap[0].sub(origin) if delta.Length < shortest: shortest = delta.Length winner = snap # see if we are out of the max radius, if any if self.radius: dv = point.sub(winner[2]) if (dv.Length > self.radius): if (not oldActive) and self.isEnabled("passive"): winner = self.snapToVertex(self.snapInfo) # setting the cursors if self.tracker: self.tracker.setCoords(winner[2]) self.tracker.setMarker(self.mk[winner[1]]) self.tracker.on() self.setCursor(winner[1]) # return the final point return cstr(winner[2])