def placeoTherElbow(c,v1=None,v2=None,P=None): ''' Like placeTheElbow() but with more math. ''' if not (v1 and v2): v1,v2=[e.tangentAt(0) for e in fCmd.edges()] try: P=fCmd.intersectionCLines(*fCmd.edges()) except: pass if hasattr(c,'PType') and hasattr(c,'BendAngle') and v1 and v2: v1.normalize() v2.normalize() ortho=rounded(fCmd.ortho(v1,v2)) bisect=rounded(v2-v1) cBisect=rounded(c.Ports[1].normalize()+c.Ports[0].normalize()) # math cZ=c.Ports[0].cross(c.Ports[1]) # more math ang=degrees(v1.getAngle(v2)) c.BendAngle=ang rot1=FreeCAD.Rotation(rounded(fCmd.beamAx(c,cZ)),ortho) c.Placement.Rotation=rot1.multiply(c.Placement.Rotation) rot2=FreeCAD.Rotation(rounded(fCmd.beamAx(c,cBisect)),bisect) c.Placement.Rotation=rot2.multiply(c.Placement.Rotation) if not P: P=c.Placement.Base c.Placement.Base=P
def placeTheElbow(c,v1=None,v2=None,P=None): ''' placeTheElbow(c,v1,v2,P=None) Puts the curve C between vectors v1 and v2. If point P is given, translates it in there. NOTE: v1 and v2 oriented in the same direction along the path! ''' if not (v1 and v2): v1,v2=[e.tangentAt(0) for e in fCmd.edges()] try: P=fCmd.intersectionCLines(*fCmd.edges()) except: pass if hasattr(c,'PType') and hasattr(c,'BendAngle') and v1 and v2: v1.normalize() v2.normalize() ortho=rounded(fCmd.ortho(v1,v2)) bisect=rounded(v2-v1) ang=degrees(v1.getAngle(v2)) c.BendAngle=ang rot1=FreeCAD.Rotation(rounded(fCmd.beamAx(c,FreeCAD.Vector(0,0,1))),ortho) c.Placement.Rotation=rot1.multiply(c.Placement.Rotation) rot2=FreeCAD.Rotation(rounded(fCmd.beamAx(c,FreeCAD.Vector(1,1,0))),bisect) c.Placement.Rotation=rot2.multiply(c.Placement.Rotation) if not P: P=c.Placement.Base c.Placement.Base=P
def makeW(): edges=fCmd.edges() if len(edges)>1: first=edges[0] last=edges[-1] points=list() while len(edges)>1: points.append(fCmd.intersectionCLines(edges.pop(0),edges[0])) delta1=(first.valueAt(0)-points[0]).Length delta2=(first.valueAt(first.LastParameter)-points[0]).Length if delta1>delta2: points.insert(0,first.valueAt(0)) else: points.insert(0,first.valueAt(first.LastParameter)) delta1=(last.valueAt(0)-points[0]).Length delta2=(last.valueAt(last.LastParameter)-points[0]).Length if delta1>delta2: points.append(last.valueAt(0)) else: points.append(last.valueAt(last.LastParameter)) from Draft import makeWire try: p=makeWire(points) except: FreeCAD.Console.PrintError('Missing intersection\n') return None p.Label='Path' drawAsCenterLine(p) return p elif FreeCADGui.Selection.getSelection(): obj=FreeCADGui.Selection.getSelection()[0] if hasattr(obj,'Shape') and type(obj.Shape)==Part.Wire: drawAsCenterLine(obj) return obj else: return None
def flatten(p1=None, p2=None, c=None): if not (p1 and p2) and len(fCmd.beams())>1: p1,p2=fCmd.beams()[:2] else: FreeCAD.Console.PrintError('Select two intersecting pipes\n') if not c: curves=[e for e in FreeCADGui.Selection.getSelection() if hasattr(e,'PType') and hasattr(e,'BendAngle')] if curves: c=curves[0] else: FreeCAD.Console.PrintError('Select at least one elbow') try: P=fCmd.intersectionCLines(p1,p2) com1=p1.Shape.Solids[0].CenterOfMass com2=p2.Shape.Solids[0].CenterOfMass v1=P-com1 v2=com2-P FreeCAD.ActiveDocument.openTransaction('Place one curve') placeoTherElbow(curves[0],v1,v2,P) FreeCAD.ActiveDocument.recompute() # recompute for the elbow port1,port2=portsPos(curves[0]) if (com1-port1).Length<(com1-port2).Length: fCmd.extendTheBeam(p1,port1) fCmd.extendTheBeam(p2,port2) else: fCmd.extendTheBeam(p1,port2) fCmd.extendTheBeam(p2,port1) FreeCAD.ActiveDocument.recompute() # recompute for the pipes FreeCAD.ActiveDocument.commitTransaction() except: FreeCAD.Console.PrintError('Intersection point not found\n')
def makeElbowBetweenThings(thing1=None, thing2=None, propList=None): ''' makeElbowBetweenThings(thing1, thing2, propList=None): Place one elbow at the intersection of thing1 and thing2. Things can be any combination of intersecting beams, pipes or edges. If nothing is passed as argument, the function attempts to take the first two edges selected in the view. propList is one optional list with 5 elements: DN (string): nominal diameter OD (float): outside diameter thk (float): shell thickness BA (float): bend angle - that will be recalculated! - BR (float): bend radius Default is "DN50 (SCH-STD)" Remember: property PRating must be defined afterwards ''' if not (thing1 and thing2): thing1,thing2=fCmd.edges()[:2] P=fCmd.intersectionCLines(thing1,thing2) directions=list() try: for thing in [thing1,thing2]: if fCmd.beams([thing]): directions.append(rounded((fCmd.beamAx(thing).multiply(thing.Height/2)+thing.Placement.Base)-P)) elif hasattr(thing,'ShapeType') and thing.ShapeType=='Edge': directions.append(rounded(thing.CenterOfMass-P)) except: return None ang=180-degrees(directions[0].getAngle(directions[1])) if ang==0 or ang==180: return None if not propList: propList=["DN50",60.3,3.91,ang,45.24] else: propList[3]=ang elb=makeElbow(propList,P,directions[0].negative().cross(directions[1].negative())) # mate the elbow ends with the pipes or edges b=fCmd.bisect(directions[0],directions[1]) elbBisect=rounded(fCmd.beamAx(elb,FreeCAD.Vector(1,1,0))) #if not rounded, fail in plane xz rot=FreeCAD.Rotation(elbBisect,b) elb.Placement.Rotation=rot.multiply(elb.Placement.Rotation) # trim the adjacent tubes #FreeCAD.activeDocument().recompute() # may delete this row? portA=elb.Placement.multVec(elb.Ports[0]) portB=elb.Placement.multVec(elb.Ports[1]) for tube in [t for t in [thing1,thing2] if fCmd.beams([t])]: vectA=tube.Shape.Solids[0].CenterOfMass-portA vectB=tube.Shape.Solids[0].CenterOfMass-portB if fCmd.isParallel(vectA,fCmd.beamAx(tube)): fCmd.extendTheBeam(tube,portA) else: fCmd.extendTheBeam(tube,portB) return elb
def extendTheTubes2intersection(pipe1=None,pipe2=None,both=True): ''' Does what it says; also with beams. If arguments are None, it picks the first 2 selected beams(). ''' if not (pipe1 and pipe2): try: pipe1,pipe2=fCmd.beams()[:2] except: FreeCAD.Console.PrintError('Insufficient arguments for extendTheTubes2intersection\n') P=fCmd.intersectionCLines(pipe1,pipe2) if P!=None: fCmd.extendTheBeam(pipe1,P) if both: fCmd.extendTheBeam(pipe2,P)
def setWP(): #TARGET [working]: deal with App::Parts 'function to change working plane' import FreeCAD, FreeCADGui, fCmd normal = point = None curves = [] straight = [] Z = FreeCAD.Vector(0, 0, 1) for edge in fCmd.edges(): if edge.curvatureAt(0) != 0: curves.append(edge) else: straight.append(edge) # define normal: 1st from face->2nd from curve->3rd from straight edges if fCmd.faces(): normal = fCmd.faces()[0].normalAt(0, 0) elif curves: normal = curves[0].tangentAt(0).cross(curves[0].normalAt(0)) elif len(straight) > 1: if straight and not fCmd.isParallel(straight[0].tangentAt(0), straight[1].tangentAt(0)): normal = straight[0].tangentAt(0).cross(straight[1].tangentAt(0)) elif FreeCADGui.Selection.getSelection(): normal = FreeCAD.DraftWorkingPlane.getRotation().multVec(Z) else: normal = Z # define point: 1st from vertex->2nd from centerOfCurvature->3rd from intersection->4th from center of edge points = [ v.Point for sx in FreeCADGui.Selection.getSelectionEx() for v in sx.SubObjects if v.ShapeType == 'Vertex' ] if not points: points = [edge.centerOfCurvatureAt(0) for edge in curves] if not points and len(straight) > 1: inters = fCmd.intersectionCLines(straight[0], straight[1]) if inters: points.append(inters) if not points and len(straight): points.append(straight[0].CenterOfMass) if points: point = points[0] else: point = FreeCAD.Vector() # move the draft WP FreeCAD.DraftWorkingPlane.alignToPointAndAxis(point, normal) FreeCADGui.Snapper.setGrid()