def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color): PathLog.track("(%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % (pivotEdge.Curve.Center.x, pivotEdge.Curve.Center.y, pivotEdge.Curve.Radius, edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y)) ppt = None pptDistance = 0 for pt in DraftGeomUtils.findIntersection(edge, pivotEdge, dts=False): #debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2) distance = (pt - refPt).Length PathLog.debug(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) if not ppt or pptDistance < distance: ppt = pt pptDistance = distance if not ppt: tangent = DraftGeomUtils.findDistance(pivot, edge) if tangent: PathLog.debug("Taking tangent as intersect %s" % tangent) ppt = pivot + tangent else: PathLog.debug("Taking chord start as intersect %s" % inChordStart) ppt = inChord.Start #debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2) PathLog.debug(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) return ppt
def calc(self): import Part if (self.p1 != None) and (self.p2 != None): points = [DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True),\ DraftVecUtils.tup(self.p1,True),DraftVecUtils.tup(self.p2,True)] if self.p3 != None: p1 = self.p1 p4 = self.p2 if DraftVecUtils.equals(p1, p4): proj = None else: base = Part.LineSegment(p1, p4).toShape() proj = DraftGeomUtils.findDistance(self.p3, base) if not proj: p2 = p1 p3 = p4 else: p2 = p1.add(proj.negative()) p3 = p4.add(proj.negative()) points = [ DraftVecUtils.tup(p1), DraftVecUtils.tup(p2), DraftVecUtils.tup(p3), DraftVecUtils.tup(p4) ] self.coords.point.setValues(0, 4, points)
def calc(self): import Part if (self.p1 != None) and (self.p2 != None): points = [ DraftVecUtils.tup(self.p1, True), DraftVecUtils.tup(self.p2, True), DraftVecUtils.tup(self.p1, True), DraftVecUtils.tup(self.p2, True), ] if self.p3 != None: p1 = self.p1 p4 = self.p2 if DraftVecUtils.equals(p1, p4): proj = None else: base = Part.Line(p1, p4).toShape() proj = DraftGeomUtils.findDistance(self.p3, base) if not proj: p2 = p1 p3 = p4 else: p2 = p1.add(proj.negative()) p3 = p4.add(proj.negative()) points = [DraftVecUtils.tup(p1), DraftVecUtils.tup(p2), DraftVecUtils.tup(p3), DraftVecUtils.tup(p4)] self.coords.point.setValues(0, 4, points)
def findPivotIntersection(self, pivot, pivotEdge, edge, refPt, d, color): debugPrint( "Intersection (%.2f, %.2f)^%.2f - [(%.2f, %.2f), (%.2f, %.2f)]" % ( pivotEdge.Curve.Center.x, pivotEdge.Curve.Center.y, pivotEdge.Curve.Radius, edge.Vertexes[0].Point.x, edge.Vertexes[0].Point.y, edge.Vertexes[1].Point.x, edge.Vertexes[1].Point.y, ) ) ppt = None pptDistance = 0 for pt in DraftGeomUtils.findIntersection(edge, pivotEdge, dts=False): # debugMarker(pt, "pti.%d-%s.in" % (self.boneId, d), color, 0.2) distance = (pt - refPt).Length debugPrint(" --> (%.2f, %.2f): %.2f" % (pt.x, pt.y, distance)) if not ppt or pptDistance < distance: ppt = pt pptDistance = distance if not ppt: tangent = DraftGeomUtils.findDistance(pivot, edge) if tangent: debugPrint("Taking tangent as intersect %s" % tangent) ppt = pivot + tangent else: debugPrint("Taking chord start as intersect %s" % inChordStart) ppt = inChord.Start # debugMarker(ppt, "ptt.%d-%s.in" % (self.boneId, d), color, 0.2) debugPrint(" --> (%.2f, %.2f)" % (ppt.x, ppt.y)) return ppt
def rotjoinTheBeam(beam=None, e1=None, e2=None): if not (beam and e1 and e2): beam = beams()[1] e1, e2 = edges() rot = FreeCAD.Rotation(e2.tangentAt(0), e1.tangentAt(0)) dist = dgu.findDistance(beam.Placement.Base, e1) delta = beam.Placement.Base - e2.CenterOfMass beam.Placement.Rotation = rot.multiply(beam.Placement.Rotation) beam.Placement.move(rounded(dist + rot.multVec(delta)))
def rotjoinTheBeam(beam=None,e1=None,e2=None): if not (beam and e1 and e2): beam=beams()[1] e1,e2=edges() rot=FreeCAD.Rotation(e2.tangentAt(0),e1.tangentAt(0)) dist=dgu.findDistance(beam.Placement.Base,e1) delta=beam.Placement.Base-e2.CenterOfMass beam.Placement.Rotation=rot.multiply(beam.Placement.Rotation) beam.Placement.move(rounded(dist+rot.multVec(delta)))
def updateData(self, obj, prop): """called when the base object is changed""" import DraftGui if prop in ["Start", "End", "Dimline", "Direction"]: if obj.Start == obj.End: return if not hasattr(self, "node"): return import Part, DraftGeomUtils from pivy import coin # calculate the 4 points self.p1 = obj.Start self.p4 = obj.End base = None if hasattr(obj, "Direction"): if not DraftVecUtils.isNull(obj.Direction): v2 = self.p1.sub(obj.Dimline) v3 = self.p4.sub(obj.Dimline) v2 = DraftVecUtils.project(v2, obj.Direction) v3 = DraftVecUtils.project(v3, obj.Direction) self.p2 = obj.Dimline.add(v2) self.p3 = obj.Dimline.add(v3) if DraftVecUtils.equals(self.p2, self.p3): base = None proj = None else: base = Part.LineSegment(self.p2, self.p3).toShape() proj = DraftGeomUtils.findDistance(self.p1, base) if proj: proj = proj.negative() if not base: if DraftVecUtils.equals(self.p1, self.p4): base = None proj = None else: base = Part.LineSegment(self.p1, self.p4).toShape() proj = DraftGeomUtils.findDistance(obj.Dimline, base) if proj: self.p2 = self.p1.add(proj.negative()) self.p3 = self.p4.add(proj.negative()) else: self.p2 = self.p1 self.p3 = self.p4 if proj: if hasattr(obj.ViewObject, "ExtLines") and hasattr( obj.ViewObject, "ScaleMultiplier"): dmax = obj.ViewObject.ExtLines.Value * obj.ViewObject.ScaleMultiplier if dmax and (proj.Length > dmax): if (dmax > 0): self.p1 = self.p2.add( DraftVecUtils.scaleTo(proj, dmax)) self.p4 = self.p3.add( DraftVecUtils.scaleTo(proj, dmax)) else: rest = proj.Length + dmax self.p1 = self.p2.add( DraftVecUtils.scaleTo(proj, rest)) self.p4 = self.p3.add( DraftVecUtils.scaleTo(proj, rest)) else: proj = (self.p3.sub(self.p2)).cross(App.Vector(0, 0, 1)) # calculate the arrows positions self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z)) self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z)) self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z)) self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z)) # calculate dimension and extension lines overshoots positions self.transDimOvershoot1.translation.setValue( (self.p2.x, self.p2.y, self.p2.z)) self.transDimOvershoot2.translation.setValue( (self.p3.x, self.p3.y, self.p3.z)) self.transExtOvershoot1.translation.setValue( (self.p2.x, self.p2.y, self.p2.z)) self.transExtOvershoot2.translation.setValue( (self.p3.x, self.p3.y, self.p3.z)) # calculate the text position and orientation if hasattr(obj, "Normal"): if DraftVecUtils.isNull(obj.Normal): if proj: norm = (self.p3.sub(self.p2).cross(proj)).negative() else: norm = App.Vector(0, 0, 1) else: norm = App.Vector(obj.Normal) else: if proj: norm = (self.p3.sub(self.p2).cross(proj)).negative() else: norm = App.Vector(0, 0, 1) if not DraftVecUtils.isNull(norm): norm.normalize() u = self.p3.sub(self.p2) u.normalize() v1 = norm.cross(u) rot1 = App.Placement(DraftVecUtils.getPlaneRotation( u, v1, norm)).Rotation.Q self.transDimOvershoot1.rotation.setValue( (rot1[0], rot1[1], rot1[2], rot1[3])) self.transDimOvershoot2.rotation.setValue( (rot1[0], rot1[1], rot1[2], rot1[3])) if hasattr(obj.ViewObject, "FlipArrows"): if obj.ViewObject.FlipArrows: u = u.negative() v2 = norm.cross(u) rot2 = App.Placement(DraftVecUtils.getPlaneRotation( u, v2, norm)).Rotation.Q self.trans1.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3])) self.trans2.rotation.setValue((rot2[0], rot2[1], rot2[2], rot2[3])) if self.p1 != self.p2: u3 = self.p1.sub(self.p2) u3.normalize() v3 = norm.cross(u3) rot3 = App.Placement( DraftVecUtils.getPlaneRotation(u3, v3, norm)).Rotation.Q self.transExtOvershoot1.rotation.setValue( (rot3[0], rot3[1], rot3[2], rot3[3])) self.transExtOvershoot2.rotation.setValue( (rot3[0], rot3[1], rot3[2], rot3[3])) if hasattr(obj.ViewObject, "TextSpacing") and hasattr( obj.ViewObject, "ScaleMultiplier"): ts = obj.ViewObject.TextSpacing.Value * obj.ViewObject.ScaleMultiplier offset = DraftVecUtils.scaleTo(v1, ts) else: offset = DraftVecUtils.scaleTo(v1, 0.05) rott = rot1 if hasattr(obj.ViewObject, "FlipText"): if obj.ViewObject.FlipText: rott = App.Rotation(*rott).multiply(App.Rotation( norm, 180)).Q offset = offset.negative() # setting text try: m = obj.ViewObject.DisplayMode except: # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet) m = ["2D", "3D"][utils.get_param("dimstyle", 0)] if m == "3D": offset = offset.negative() self.tbase = (self.p2.add( (self.p3.sub(self.p2).multiply(0.5)))).add(offset) if hasattr(obj.ViewObject, "TextPosition"): if not DraftVecUtils.isNull(obj.ViewObject.TextPosition): self.tbase = obj.ViewObject.TextPosition self.textpos.translation.setValue( [self.tbase.x, self.tbase.y, self.tbase.z]) self.textpos.rotation = coin.SbRotation(rott[0], rott[1], rott[2], rott[3]) su = True if hasattr(obj.ViewObject, "ShowUnit"): su = obj.ViewObject.ShowUnit # set text value l = self.p3.sub(self.p2).Length unit = None if hasattr(obj.ViewObject, "UnitOverride"): unit = obj.ViewObject.UnitOverride # special representation if "Building US" scheme if App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt( "UserSchema", 0) == 5: s = App.Units.Quantity(l, App.Units.Length).UserString self.string = s.replace("' ", "'- ") self.string = s.replace("+", " ") elif hasattr(obj.ViewObject, "Decimals"): self.string = DraftGui.displayExternal(l, obj.ViewObject.Decimals, 'Length', su, unit) else: self.string = DraftGui.displayExternal(l, None, 'Length', su, unit) if hasattr(obj.ViewObject, "Override"): if obj.ViewObject.Override: self.string = obj.ViewObject.Override.replace("$dim",\ self.string) self.text.string = self.text3d.string = utils.string_encode_coin( self.string) # set the lines if m == "3D": # calculate the spacing of the text textsize = (len(self.string) * obj.ViewObject.FontSize.Value) / 4.0 spacing = ((self.p3.sub(self.p2)).Length / 2.0) - textsize self.p2a = self.p2.add( DraftVecUtils.scaleTo(self.p3.sub(self.p2), spacing)) self.p2b = self.p3.add( DraftVecUtils.scaleTo(self.p2.sub(self.p3), spacing)) self.coords.point.setValues( [[self.p1.x, self.p1.y, self.p1.z], [self.p2.x, self.p2.y, self.p2.z], [self.p2a.x, self.p2a.y, self.p2a.z], [self.p2b.x, self.p2b.y, self.p2b.z], [self.p3.x, self.p3.y, self.p3.z], [self.p4.x, self.p4.y, self.p4.z]]) #self.line.numVertices.setValues([3,3]) self.line.coordIndex.setValues(0, 7, (0, 1, 2, -1, 3, 4, 5)) else: self.coords.point.setValues([[self.p1.x, self.p1.y, self.p1.z], [self.p2.x, self.p2.y, self.p2.z], [self.p3.x, self.p3.y, self.p3.z], [self.p4.x, self.p4.y, self.p4.z]]) #self.line.numVertices.setValue(4) self.line.coordIndex.setValues(0, 4, (0, 1, 2, 3))
def action(self, arg): """Handle the 3D scene events. This is installed as an EventCallback in the Inventor view. Parameters ---------- arg: dict Dictionary with strings that indicates the type of event received from the 3D view. """ import DraftGeomUtils if arg["Type"] == "SoKeyboardEvent": if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: viewdelta = DraftVecUtils.project(self.point.sub(self.center), App.DraftWorkingPlane.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True self.ui.switchUi(True) else: if self.altdown: self.altdown = False self.ui.switchUi(False) else: # choose radius if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom2tan1pt( self.tangents[0], self.tangents[1], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: cir = DraftGeomUtils.circleFrom1tan2pt( self.tangents[0], self.tanpoints[0], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True snapped = self.view.getObjectInfo( (arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom3tan( self.tangents[0], self.tangents[1], ed) cl = DraftGeomUtils.findClosestCircle( self.point, cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: self.rad = self.center.add( DraftGeomUtils.findDistance( self.center, ed).sub(self.center)).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: if self.altdown: self.altdown = False self.rad = DraftVecUtils.dist(self.point, self.center) self.ui.setRadiusValue(self.rad, 'Length') self.arctrack.setRadius(self.rad) gui_tool_utils.redraw3DView() elif (arg["Type"] == "SoMouseButtonEvent" and arg["State"] == "DOWN" and arg["Button"] == "BUTTON1"): # mouse click if self.point: if self.step == 0: # choose center if (not self.node) and (not self.support): gui_tool_utils.getSupport(arg) (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): snapped = self.view.getObjectInfo( (arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: self.arctrack.on() self.ui.radiusUi() self.step = 1 _msg(translate("draft", "Pick radius")) else: if len(self.tangents) == 1: self.tanpoints.append(self.point) else: self.center = self.point self.node = [self.point] self.arctrack.setCenter(self.center) self.arctrack.on() self.ui.radiusUi() self.step = 1 _msg(translate("draft", "Pick radius")) if self.planetrack: self.planetrack.set(self.point) elif self.step == 1: # choose radius self.drawPolygon()
def action(self, arg): """Handle the 3D scene events. This is installed as an EventCallback in the Inventor view. Parameters ---------- arg: dict Dictionary with strings that indicates the type of event received from the 3D view. """ import DraftGeomUtils plane = App.DraftWorkingPlane if arg["Type"] == "SoKeyboardEvent": if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True self.ui.switchUi(True) else: if self.altdown: self.altdown = False self.ui.switchUi(False) elif self.step == 1: # choose radius if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True if info: ob = self.doc.getObject(info['Object']) num = int(info['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) cl = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: self.rad = self.center.add(DraftGeomUtils.findDistance(self.center, ed).sub(self.center)).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: if self.altdown: self.altdown = False self.rad = DraftVecUtils.dist(self.point, self.center) self.ui.setRadiusValue(self.rad, "Length") self.arctrack.setRadius(self.rad) self.linetrack.p1(self.center) self.linetrack.p2(self.point) self.linetrack.on() elif (self.step == 2): # choose first angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) self.ui.setRadiusValue(math.degrees(angle), unit="Angle") self.firstangle = angle else: # choose second angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) self.updateAngle(angle) self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle") self.arctrack.setApertureAngle(self.angle) gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": # mouse click if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1": if self.point: if self.step == 0: # choose center if not self.support: gui_tool_utils.getSupport(arg) (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: self.arctrack.on() self.ui.radiusUi() self.step = 1 self.ui.setNextFocus() self.linetrack.on() _msg(translate("draft", "Pick radius")) else: if len(self.tangents) == 1: self.tanpoints.append(self.point) else: self.center = self.point self.node = [self.point] self.arctrack.setCenter(self.center) self.linetrack.p1(self.center) self.linetrack.p2(self.view.getPoint(arg["Position"][0], arg["Position"][1])) self.arctrack.on() self.ui.radiusUi() self.step = 1 self.ui.setNextFocus() self.linetrack.on() _msg(translate("draft", "Pick radius")) if self.planetrack: self.planetrack.set(self.point) elif self.step == 1: # choose radius if self.closedCircle: self.drawArc() else: self.ui.labelRadius.setText(translate("draft", "Start angle")) self.ui.radiusValue.setToolTip(translate("draft", "Start angle")) self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) self.linetrack.p1(self.center) self.linetrack.on() self.step = 2 _msg(translate("draft", "Pick start angle")) elif self.step == 2: # choose first angle self.ui.labelRadius.setText(translate("draft", "Aperture angle")) self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) self.step = 3 # scale center->point vector for proper display # u = DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad) obsolete? self.arctrack.setStartAngle(self.firstangle) _msg(translate("draft", "Pick aperture")) else: # choose second angle self.step = 4 self.drawArc()