def __init__(self, doc, name='helix'): self.data = { 'len lo': 70., # mm 'len up': 120., # mm 'int diameter': 36., # mm 'thick': 1., # mm } len_lo = self.data['len lo'] # blocking thread (pas de vis de blocage) radius = self.data['int diameter'] / 2 helix = Part.makeHelix(4., 16., radius) p0 = (radius, 0, 0) p1 = (radius, 0, 3) p2 = (radius - 1, 0, 2) p3 = (radius - 1, 0, 1) e0 = Part.makeLine(p0, p1) e1 = Part.makeLine(p1, p2) e2 = Part.makeLine(p2, p3) e3 = Part.makeLine(p3, p0) section = Part.Wire([e0, e1, e2, e3]) helix = Part.Wire(helix).makePipeShell([section], 1, 1) helix.translate(Vector(0, 0, len_lo - 20)) helix = helix.fuse(helix) comp = helix MecaComponent.__init__(self, doc, comp, name, (1., 1., 0.))
def execute(self, fp): #main part of script steps=fp.Segments #get value from property dang=math.radians(360/steps) r2=fp.Radius2 r1=fp.Radius1 f1 = r1 + r2 f2 = f1 / r2 d=fp.Distance ang=0 z=0 if r2 == 0: raise ValueError("Exterior radius must not be zero") for i in range(steps): if i==0: x1=f1*math.cos(ang)-d*math.cos(f2*ang) #coords for line startpoint y1=f1*math.sin(ang)-d*math.sin(f2*ang) ang=dang x2=f1*math.cos(ang)-d*math.cos(f2*ang) #coords for line endpoint y2=f1*math.sin(ang)-d*math.sin(f2*ang) seg=Part.makeLine((x1,y1,z),(x2,y2,z)) wire=Part.Wire([seg]) x1=x2 y1=y2 else: x2=f1*math.cos(ang)-d*math.cos(f2*ang) y2=f1*math.sin(ang)-d*math.sin(f2*ang) seg=Part.makeLine((x1,y1,z),(x2,y2,z)) wire=Part.Wire([wire,seg]) x1=x2 y1=y2 ang=ang+dang #increment angle fp.Shape = wire #result shape
def linesFromPoints(points, closed=False): lines = [] for i in range(0, len(points) - 1): lines.append(Part.makeLine(points[i], points[(i + 1) % len(points)])) if closed: lines.append(Part.makeLine(points[len(points) - 1], points[0])) return lines
def makeSurfaceVolume(filename): import FreeCAD,Part f1=open(filename) coords=[] miny=1 for line in f1.readlines(): sline=line.strip() if sline and not sline.startswith('#'): ycoord=len(coords) lcoords=[] for xcoord, num in enumerate(sline.split()): fnum=float(num) lcoords.append(FreeCAD.Vector(float(xcoord),float(ycoord),fnum)) miny=min(fnum,miny) coords.append(lcoords) s=Part.BSplineSurface() s.interpolate(coords) plane=Part.makePlane(len(coords[0])-1,len(coords)-1,FreeCAD.Vector(0,0,miny-1)) l1=Part.makeLine(plane.Vertexes[0].Point,s.value(0,0)) l2=Part.makeLine(plane.Vertexes[1].Point,s.value(1,0)) l3=Part.makeLine(plane.Vertexes[2].Point,s.value(0,1)) l4=Part.makeLine(plane.Vertexes[3].Point,s.value(1,1)) f0=plane.Faces[0] f0.reverse() f1=Part.Face(Part.Wire([plane.Edges[0],l1.Edges[0],s.vIso(0).toShape(),l2.Edges[0]])) f2=Part.Face(Part.Wire([plane.Edges[1],l3.Edges[0],s.uIso(0).toShape(),l1.Edges[0]])) f3=Part.Face(Part.Wire([plane.Edges[2],l4.Edges[0],s.vIso(1).toShape(),l3.Edges[0]])) f4=Part.Face(Part.Wire([plane.Edges[3],l2.Edges[0],s.uIso(1).toShape(),l4.Edges[0]])) f5=s.toShape().Faces[0] solid=Part.Solid(Part.Shell([f0,f1,f2,f3,f4,f5])) return solid,(len(coords[0])-1)/2.0,(len(coords)-1)/2.0
def update(self, L, B, T): """ Update the 3D view printing annotations. @param L Ship length. @param B Ship beam. @param T Ship draft. """ # Destroy all previous entities self.clean() # Draw base line xStart = -0.6*L; xEnd = 0.6*L; baseLine = Part.makeLine((xStart,0,0),(xEnd,0,0)) Part.show(baseLine) objs = FreeCAD.ActiveDocument.Objects self.baseLine = objs[len(objs)-1] self.baseLine.Label = 'BaseLine' text = str(QtGui.QApplication.translate("ship_create","Base line", None,QtGui.QApplication.UnicodeUTF8)) self.baseLineLabel = DrawText('BaseLineText', text, Base.Vector(xEnd,0,0)) # Draw free surface fsLine = Part.makeLine((xStart,0,T),(xEnd,0,T)) Part.show(fsLine) objs = FreeCAD.ActiveDocument.Objects self.fsLine = objs[len(objs)-1] self.fsLine.Label = 'FreeSurface' text = str(QtGui.QApplication.translate("ship_create","Free surface", None,QtGui.QApplication.UnicodeUTF8)) self.fsLineLabel = DrawText('FSText', text, Base.Vector(xEnd,0,T)) # Draw forward perpendicular zStart = -0.1*T zEnd = 1.1*T fpLine = Part.makeLine((0.5*L,0,zStart),(0.5*L,0,zEnd)) Part.show(fpLine) objs = FreeCAD.ActiveDocument.Objects self.fpLine = objs[len(objs)-1] self.fpLine.Label = 'ForwardPerpendicular' text = str(QtGui.QApplication.translate("ship_create","Forward perpendicular", None,QtGui.QApplication.UnicodeUTF8)) self.fpLineLabel = DrawText('FPText', text, Base.Vector(0.5*L,0,zEnd)) # Draw after perpendicular apLine = Part.makeLine((-0.5*L,0,zStart),(-0.5*L,0,zEnd)) Part.show(apLine) objs = FreeCAD.ActiveDocument.Objects self.apLine = objs[len(objs)-1] self.apLine.Label = 'AfterPerpendicular' text = str(QtGui.QApplication.translate("ship_create","After perpendicular", None,QtGui.QApplication.UnicodeUTF8)) self.apLineLabel = DrawText('APText', text, Base.Vector(-0.5*L,0,zEnd)) # Draw amin frame amLine = Part.makeLine((0,-0.5*B,zStart),(0,-0.5*B,zEnd)) Part.show(amLine) objs = FreeCAD.ActiveDocument.Objects self.amLine = objs[len(objs)-1] self.amLine.Label = 'AminFrame' text = str(QtGui.QApplication.translate("ship_create","Main frame", None,QtGui.QApplication.UnicodeUTF8)) self.amLineLabel = DrawText('AMText', text, Base.Vector(0,-0.5*B,zEnd))
def testIssue2985(self): v1 = App.Vector(0.0,0.0,0.0) v2 = App.Vector(10.0,0.0,0.0) v3 = App.Vector(10.0,0.0,10.0) v4 = App.Vector(0.0,0.0,10.0) edge1 = Part.makeLine(v1, v2) edge2 = Part.makeLine(v2, v3) edge3 = Part.makeLine(v3, v4) edge4 = Part.makeLine(v4, v1)
def test04(self): '''Verify isWireClockwise for unoriented wires.''' e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 0, 180) e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter)) self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e3]))) e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 0, 180) e3 = Part.makeLine(e0.valueAt(e0.FirstParameter), e0.valueAt(e0.LastParameter)) self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e3])))
def test03(self): '''Verify isWireClockwise for two edge wires with an arc.''' e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, -1), 0, 180) e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter)) self.assertTrue(PathOpTools.isWireClockwise(Part.Wire([e0, e2]))) e0 = Part.makeCircle(5, Vector(1, 2, 3), Vector(0, 0, +1), 0, 180) e2 = Part.makeLine(e0.valueAt(e0.LastParameter), e0.valueAt(e0.FirstParameter)) self.assertFalse(PathOpTools.isWireClockwise(Part.Wire([e0, e2])))
def execute(self, fp): fp.thread="M"+str(float(fp.d)) c=Part.makeCircle(fp.C/2,FreeCAD.Vector(0,0,0),FreeCAD.Vector(0,0,1),0,180) l1=Part.makeLine((fp.C/2,0,0),(fp.C/2,fp.C/2-fp.H,0)) l2=Part.makeLine((-fp.C/2,0,0),(-fp.C/2,fp.C/2-fp.H,0)) p=Part.Face(Part.Wire(Part.makeCircle(fp.d/2,c.valueAt(c.FirstParameter),c.tangentAt(c.FirstParameter)))) path=Part.Wire([c,l1,l2]) fp.Shape=path.makePipe(p) fp.Ports=[FreeCAD.Vector(0,0,1)]
def testRuledSurface(self): """ Tests making a ruled surface from two edges/wires. """ edge1 = Shape(Part.makeLine((0, 0, 5), (0, 10, 5))) edge2 = Shape(Part.makeLine((5, 5, 0), (10, 10, 0))) surf1 = Face.makeRuledSurface(edge1, edge2) self.assertEquals(surf1.ShapeType(), 'Face') self.assertTrue(surf1.isValid())
def findInterPoint(edge1,edge2): # give two edges and then return the inter_point pt1a = edge1.Vertex1.Point pt1b = edge1.Vertex2.Point pt2a = edge2.Vertex1.Point pt2b = edge2.Vertex2.Point nor1 = pt1a.sub(pt1b).normalize() nor2 = pt2a.sub(pt2b).normalize() line1 = Part.makeLine(pt1a+nor1*1000,pt1a+nor1*-1000) line2 = Part.makeLine(pt2a+nor2*1000,pt2a+nor2*-1000) p=DraftGeomUtils.findIntersection(line1,line2) if p: return(p[0]) return(prf('cen not find the inter point!'))
def draw_rectangle(ai_position_x, ai_position_y, ai_size_x, ai_size_y): p1 = Base.Vector(ai_position_x+0*ai_size_x, ai_position_y+0*ai_size_y, 0) p2 = Base.Vector(ai_position_x+1*ai_size_x, ai_position_y+0*ai_size_y, 0) p3 = Base.Vector(ai_position_x+1*ai_size_x, ai_position_y+1*ai_size_y, 0) p4 = Base.Vector(ai_position_x+0*ai_size_x, ai_position_y+1*ai_size_y, 0) r_rectangle_outline=[] r_rectangle_outline.append(Part.makeLine(p1, p2)) r_rectangle_outline.append(Part.makeLine(p2, p3)) r_rectangle_outline.append(Part.makeLine(p3, p4)) r_rectangle_outline.append(Part.makeLine(p4, p1)) #r_rectangle = Part.Face(Part.Wire(r_rectangle_outline)) r_rectangle = r_rectangle_outline return(r_rectangle)
def profile(): """make a profile by extrusion""" # retreive configuration side = profile_data["side"] thick = profile_data["thick"] length = profile_data["len"] radius = profile_data["radius"] # make profile shape shape = [] shape.append(Part.makeLine((0, 0, 0), (side, 0, 0))) shape.append(Part.makeLine((side, 0, 0), (side, side, 0))) shape.append(Part.makeLine((side, side, 0), (0, side, 0))) shape.append(Part.makeLine((0, side, 0), (0, side - thick, 0))) shape.append(Part.makeLine((0, side - thick, 0), (side - thick, side - thick, 0))) shape.append(Part.makeLine((side - thick, side - thick, 0), (side - thick, thick, 0))) shape.append(Part.makeLine((side - thick, thick, 0), (0, thick, 0))) shape.append(Part.makeLine((0, thick, 0), (0, 0, 0))) wire = Part.Wire(shape) face = Part.Face(wire) profil = face.extrude(Vector(0, 0, length)) profil.translate(Vector(0, -side / 2, 0)) return profil
def __init__(self, doc, name='profile'): # profiles alu en U self.data = { 'side': 20., # mm 'len': 2000., # mm 'thick': 1.5, # mm 'radius': 60.5 + 1.5 - 20., # mm // bague['len'] + thick - side } """make a profile by extrusion""" # retreive configuration side = self.data['side'] thick = self.data['thick'] length = self.data['len'] # make profile shape shape = [] shape.append(Part.makeLine((0, 0, 0), (side, 0, 0))) shape.append(Part.makeLine((side, 0, 0), (side, side, 0))) shape.append(Part.makeLine((side, side, 0), (0, side, 0))) shape.append(Part.makeLine((0, side, 0), (0, side - thick, 0))) shape.append(Part.makeLine((0, side - thick, 0), (side - thick, side - thick, 0))) shape.append(Part.makeLine((side - thick, side - thick, 0), (side - thick, thick, 0))) shape.append(Part.makeLine((side - thick, thick, 0), (0, thick, 0))) shape.append(Part.makeLine((0, thick, 0), (0, 0, 0))) wire = Part.Wire(shape) wire.translate(Vector(0, -side / 2, 0)) face = Part.Face(wire) profil = face.extrude(Vector(0, 0, length)) MecaComponent.__init__(self, doc, profil, name, (0.95, 1., 1.))
def testCut(self): """ Tests cutting one face from another. """ # Face 1 edge1 = Part.makeLine((0, 0, 0), (0, 10, 0)) edge2 = Part.makeLine((0, 10, 0), (10, 10, 0)) edge3 = Part.makeLine((10, 10, 0), (10, 0, 0)) edge4 = Part.makeLine((10, 0, 0), (0, 0, 0)) wire1 = Part.Wire([edge1,edge2,edge3,edge4]) face1 = Part.Face(wire1) cqFace1 = Face(face1) # Face 2 (face to cut out of face 1) edge1 = Part.makeLine((0, 0, 0), (0, 5, 0)) edge2 = Part.makeLine((0, 5, 0), (5, 5, 0)) edge3 = Part.makeLine((5, 5, 0), (5, 0, 0)) edge4 = Part.makeLine((5, 0, 0), (0, 0, 0)) wire1 = Part.Wire([edge1,edge2,edge3,edge4]) face2 = Part.Face(wire1) cqFace2 = Face(face2) # Face resulting from cut cqFace3 = cqFace1.cut(cqFace2) self.assertEquals(len(cqFace3.Faces()), 1) self.assertEquals(len(cqFace3.Edges()), 6)
def edge_fillet(edges,radius): """ when given a list of two lines connected lines, returns a list of three curves (line, arc, line) corresponding to a filleted edge """ l1 = edges[0] l2 = edges[1] assert(l1.Curve.EndPoint == l2.Curve.StartPoint) dir1 =l1.Curve.EndPoint - l1.Curve.StartPoint dir2 =l2.Curve.EndPoint - l2.Curve.StartPoint normal = dir1.cross(dir2) raw_angle = math.asin(normal[2]/dir1.Length/dir2.Length) #This is the smaller angle enclosed by the two lines in radians angle = math.pi - abs(raw_angle) #to find the transition points of the fillet, we consider a rectangular #triangle with one kathete equal to the radius and the other one lying on #one of the input lines with length a a = radius/math.tan(0.5*angle) #parameter per length ppl1 = (l1.Curve.LastParameter-l1.Curve.FirstParameter)/l1.Curve.length() ppl2 = (l2.Curve.LastParameter-l2.Curve.FirstParameter)/l2.Curve.length() t1 = l1.Curve.value(l1.Curve.LastParameter - a*ppl1) t2 = l2.Curve.value(l1.Curve.FirstParameter + a*ppl2) #to fine the center of the fillet radius, we construct the angle bisector #between the two input lines, and get the distance of the center from the #common point by a trigonometric consideration bis = Part.makeLine(l1.Curve.EndPoint,(t1+t2).scale(0.5,0.5,0.5)) pplb = (bis.Curve.LastParameter-bis.Curve.FirstParameter)/bis.Curve.length() d = radius/math.sin(0.5*angle) center = bis.Curve.value(bis.Curve.FirstParameter + d*pplb) #to construct the circle we need start and end angles r1 = t1 - center r2 = t2 - center if raw_angle > 0: alpha1 = math.atan2(r1[1],r1[0])*180/math.pi alpha2 = math.atan2(r2[1],r2[0])*180/math.pi else: alpha2 = math.atan2(r1[1],r1[0])*180/math.pi alpha1 = math.atan2(r2[1],r2[0])*180/math.pi normal *= -1 return [Part.makeLine(l1.Curve.StartPoint,t1), Part.makeCircle(radius,center,normal,alpha1,alpha2), Part.makeLine(t2,l2.Curve.EndPoint)]
def testFace(self): """ Test basic face functions, cast and instantiation """ edge1 = Part.makeLine((0, 0, 0), (0, 10, 0)) edge2 = Part.makeLine((0, 10, 0), (10, 10, 0)) edge3 = Part.makeLine((10, 10, 0), (10, 0, 0)) edge4 = Part.makeLine((10, 0, 0), (0, 0, 0)) wire1 = Part.Wire([edge1,edge2,edge3,edge4]) face1 = Part.Face(wire1) mplanec = Face.cast(face1) mplane = Face(face1) self.assertTupleAlmostEquals((5.0, 5.0, 0.0), mplane.Center().toTuple(), 3)
def arcoCoronaCircular(rInt,rExt,vectorCentro,angIni,angFin): # Devuelve el arco de la corona circular (en el plano XY) definido por: # rInt: radio interior # rExt: radio exterior # vectorCentro: centro del cÃrculo (coordenadas x,y) # angIni: ángulo inicial (0 a 360º) # angFin: ángulo final (0 a 360º) # Los ángulos crecen en sentido contrario a las agujas del reloj arcoExt=Part.makeCircle(rExt,vectorCentro,Base.Vector(0,0,1),angIni,angFin) arcoInt=Part.makeCircle(rInt,vectorCentro,Base.Vector(0,0,1),angIni,angFin) angIni=angIni*math.pi/180.0 angFin=angFin*math.pi/180.0 r1=Part.makeLine(vectorCentro.add(Base.Vector(rInt*math.cos(angIni),rInt*math.sin(angIni))),vectorCentro.add(Base.Vector(rExt*math.cos(angIni),rExt*math.sin(angIni)))) r2=Part.makeLine(vectorCentro.add(Base.Vector(rInt*math.cos(angFin),rInt*math.sin(angFin))),vectorCentro.add(Base.Vector(rExt*math.cos(angFin),rExt*math.sin(angFin)))) arcCoron=Part.Face(Part.Wire([arcoExt,r1,arcoInt,r2])) return arcCoron
def AddPoint(self, x, z): curPoint = FreeCAD.Base.Vector(x,0,z) if (self.firstPoint == None): self.firstPoint = curPoint else: self.edges.append(Part.makeLine(self.lastPoint, curPoint)) self.lastPoint = curPoint
def update(self, names, pos): """ Update the 3D view printing annotations. @param names Weight names. @param pos Weight positions (FreeCAD::Base::Vector). """ # Destroy all previous entities self.clean() for i in range(0, len(names)): # Draw gravity line line = Part.makeLine((pos[i].x,pos[i].y,pos[i].z),(pos[i].x,pos[i].y,pos[i].z - 9.81)) Part.show(line) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'Line' # Draw circles circle = Part.makeCircle(0.5, pos[i], Base.Vector(1.0,0.0,0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleX' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,1.0,0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleY' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,0.0,1.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleZ' # Draw annotation self.objects.append(DrawText(names[i] + 'Text', names[i], Base.Vector(pos[i].x+1.0,pos[i].y,pos[i].z)))
def test(): from FreeCAD import Base import Part P1 = Base.Vector(1, -5, 0) P2 = Base.Vector(-5, 2, 0) P3 = Base.Vector(1, 5, 0) #Q=Base.Vector(5,10,0) #Q=Base.Vector(5,11,0) Q = Base.Vector(5, 0, 0) r2 = 3.0 axis = Base.Vector(0, 0, 1) ccw = False arc = Part.ArcOfCircle(P1, P2, P3) C = arc.Center Part.show(Part.makeLine(P3, Q)) Part.show(arc.toShape()) (S1, S2, M2) = makeArc( Vector(C.x, C.y, C.z), Vector(P3.x, P3.y, P3.z), Vector(Q.x, Q.y, Q.z), Vector(axis.x, axis.y, axis.z), r2, ccw) circle = Part.Circle( Base.Vector(M2.x, M2.y, M2.z), Base.Vector(0, 0, 1), math.fabs(r2)) Part.show(circle.toShape())
def updateTrajectoryLines(): EAFolder = FreeCAD.ActiveDocument.ExplodedAssembly.Group # remove all the previous trajectory lines for traj in EAFolder: for lines in traj.Group: FreeCAD.ActiveDocument.removeObject(lines.Name) # re-draw all trajectories for traj in EAFolder: lines_compound = [] objects = [] for name in traj.names: objects.append(FreeCAD.ActiveDocument.getObject(name)) inc_D = traj.Distance dir_vectors = [] rot_centers = [] for s in xrange(len(objects)): dir_vectors.append(FreeCAD.Vector(tuple(traj.dir_vectors[s]))) rot_centers.append(FreeCAD.Vector(tuple(traj.rot_centers[s]))) for n in xrange(len(objects)): pa = rot_centers[n]# objects[n].Placement.Base pb = rot_centers[n] + dir_vectors[n]*inc_D lines_compound.append(Part.makeLine(pa, pb)) l_obj = FreeCAD.ActiveDocument.addObject('Part::Feature','trajectory_line') l_obj.Shape = Part.makeCompound(lines_compound) l_obj.ViewObject.DrawStyle = "Dashed" l_obj.ViewObject.LineWidth = 1.0 traj.addObject(l_obj) FreeCAD.Gui.updateGui()
def execute(self, fp): "Create all of the assosiated goemetry" fp.Shape = Part.makeLine(fp.StartPoint,fp.EndPoint) #this is just the basic line shape #create snap points (start, midpoint and end point of line) sps = [] midPoint = FreeCAD.Vector(0,0,0) midPoint.x = (fp.EndPoint.x + fp.StartPoint.x)/2 midPoint.y = (fp.EndPoint.y + fp.StartPoint.y)/2 midPoint.z = (fp.EndPoint.z + fp.StartPoint.z)/2 sps.append(fp.StartPoint) sps.append(fp.EndPoint) sps.append(midPoint) fp.SnapPoints = sps #create a vector that points in direction of start point to end point startVec = FreeCAD.Vector(0,0,0) startVec.x = fp.EndPoint.x - fp.StartPoint.x startVec.y = fp.EndPoint.y - fp.StartPoint.y startVec.z = fp.EndPoint.z - fp.StartPoint.z startVec.normalize() #fill out index list. index and vector list must be same length fp.SnapLinesIndex = [0,0,1,0,1,0,1] #create all the snap vectors v1 = startVec #line direction v2 = FreeCAD.Vector(startVec.y,-startVec.x,startVec.z) #this rotates vector by 90deg in clockwise direction (for perpendicular snap) v3 = FreeCAD.Vector(0,1,0)#vertical v4 = FreeCAD.Vector(1,0,0)#horizontal spvs = [v1,v2,v2,v3,v3,v4,v4] fp.SnapDirections = spvs # I don't know why I have to do it like this and not just add directly
def lineTo(self, x, y): """ Draw a line from the current point to (x, y) update the current point """ x0, y0 = self.x, self.y self.x, self.y = x, y e = Part.makeLine((x0, y0, 0), (x, y, 0)) self.addEdge(e)
def makeRayBundle(self, raybundle, offset): raysorigin = raybundle.o nrays = np.shape(raysorigin)[1] pp = Points.Points() sectionpoints = [] res = [] for i in range(nrays): if abs(raybundle.t[i]) > 1e-6: x1 = raysorigin[0, i] + offset[0] y1 = raysorigin[1, i] + offset[1] z1 = raysorigin[2, i] + offset[2] x2 = x1 + raybundle.t[i] * raybundle.rayDir[0, i] y2 = y1 + raybundle.t[i] * raybundle.rayDir[1, i] z2 = z1 + raybundle.t[i] * raybundle.rayDir[2, i] res.append(Part.makeLine((x1,y1,z1),(x2,y2,z2))) # draw ray sectionpoints.append((x2,y2,z2)) pp.addPoints(sectionpoints) #Points.show(pp) # draw intersection points per raybundle per field point return (pp, res)
def points2face(points): fc_profile1_elems = [] for p1, p2 in zip(points, points[1:]): fc_profile1_elems.append(Part.makeLine(p1, p2)) fc_profile1_wire = Part.Wire(fc_profile1_elems) return Part.Face(fc_profile1_wire)
def makeLine(cls, v1, v2): """ Create a line between two points :param v1: Vector that represents the first point :param v2: Vector that represents the second point :return: A linear edge between the two provided points """ return Edge(FreeCADPart.makeLine(v1.toTuple(), v2.toTuple()))
def AddPoint(self, x, z): curPoint = FreeCAD.Base.Vector(x,0,z) if (self.firstPoint == None): self.firstPoint = curPoint else: self.edges.append(Part.makeLine(self.lastPoint, curPoint)) self.lastPoint = curPoint FreeCAD.Console.PrintLog("Add Point: " + str(curPoint) + "\n")
def make5Wheel(self,pnt=Base.Vector(axis['length']-fwheel['bxoffset'],floor['width']/2,0),dir=Base.Vector(0, 0, 1)): s = Part.makeCylinder(self.fwheel['fwheelRadius'],self.fwheel['thickness'],pnt,dir) h = Part.makeCylinder(self.fwheel['innerHoleRadius'],self.fwheel['thickness'],pnt,dir) tv1 = pnt + Base.Vector(0,self.fwheel['innerHoleRadius'],0); tv2 = pnt + Base.Vector(0,-self.fwheel['innerHoleRadius'],0); tv3 = pnt + Base.Vector(self.fwheel['fwheelRadius'],-self.fwheel['insertionTrapezeBigBase']/2,0); tv4 = pnt + Base.Vector(self.fwheel['fwheelRadius'],self.fwheel['insertionTrapezeBigBase']/2,0); tl1 = Part.makeLine(tv1,tv2) tl2 = Part.makeLine(tv2,tv3) tl3 = Part.makeLine(tv3,tv4) tl4 = Part.makeLine(tv4,tv1) twire = Part.Wire([tl1, tl2, tl3, tl4]); t = Part.Face(twire).extrude(Base.Vector(0,0,self.fwheel['thickness'])); return s.cut(h).cut(t)
def makeFront(self,pnt=Base.Vector(0,side['thickness'],floor['thickness']),dir=Base.Vector(0, 0, 1)): front_p = Part.makeBox(self.front['thickness'],self.front['width'],self.front['height'],pnt,dir) wsv1 = pnt + Base.Vector(0,self.front['width']-self.front['windshield-smalledge'],self.front['windshield-botedge']); wsv2 = pnt + Base.Vector(0,self.front['width']-self.front['windshield-bigedge'],self.front['height']-self.front['windshield-topedge']); wsv3 = pnt + Base.Vector(0,self.front['windshield-bigedge'],self.front['height']-self.front['windshield-topedge']); wsv4 = pnt + Base.Vector(0,self.front['windshield-smalledge'],self.front['windshield-botedge']); wsl1 = Part.makeLine(wsv1,wsv2) wsl2 = Part.makeLine(wsv2,wsv3) wsl3 = Part.makeLine(wsv3,wsv4) wsl4 = Part.makeLine(wsv4,wsv1) wswire = Part.Wire([wsl1, wsl2, wsl3, wsl4]); windshield_p = Part.Face(wswire).extrude(Base.Vector(self.front['thickness'],0,0)); return front_p.cut(windshield_p)
def setup(doc=None, solvertype="ccxtools"): if doc is None: doc = init_doc() # geometry object # name is important because the other method in this module use obj name l1 = Part.makeLine((-142.5, -142.5, 0), (142.5, -142.5, 0)) l2 = Part.makeLine((142.5, -142.5, 0), (142.5, 142.5, 0)) l3 = Part.makeLine((142.5, 142.5, 0), (-142.5, 142.5, 0)) l4 = Part.makeLine((-142.5, 142.5, 0), (-142.5, -142.5, 0)) wire = Part.Wire([l1, l2, l3, l4]) shape = wire.extrude(Vector(0, 0, 1000)) geom_obj = doc.addObject('Part::Feature', 'SquareTube') geom_obj.Shape = shape doc.recompute() if FreeCAD.GuiUp: geom_obj.ViewObject.Document.activeView().viewAxonometric() geom_obj.ViewObject.Document.activeView().fitAll() # analysis analysis = ObjectsFem.makeAnalysis(doc, "Analysis") # solver if solvertype == "calculix": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") )[0] elif solvertype == "ccxtools": solver_object = analysis.addObject( ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools") )[0] solver_object.WorkingDir = u"" else: FreeCAD.Console.PrintWarning( "Not known or not supported solver type: {}. " "No solver object was created.\n".format(solvertype) ) if solvertype == "calculix" or solvertype == "ccxtools": solver_object.SplitInputWriter = False solver_object.AnalysisType = "static" solver_object.GeometricalNonlinearity = "linear" solver_object.ThermoMechSteadyState = False solver_object.MatrixSolverType = "default" solver_object.IterationsControlParameterTimeUse = False # shell thickness thickness = analysis.addObject( ObjectsFem.makeElementGeometry2D(doc, 0, "ShellThickness") )[0] thickness.Thickness = 15.0 # material material_object = analysis.addObject( ObjectsFem.makeMaterialSolid(doc, "FemMaterial") )[0] mat = material_object.Material mat["Name"] = "Steel-Generic" mat["YoungsModulus"] = "200000 MPa" mat["PoissonRatio"] = "0.30" mat["Density"] = "7900 kg/m^3" material_object.Material = mat # fixed_constraint fixed_constraint = analysis.addObject( ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed"))[0] fixed_constraint.References = [ (doc.SquareTube, "Edge4"), (doc.SquareTube, "Edge7"), (doc.SquareTube, "Edge10"), (doc.SquareTube, "Edge12")] # force_constraint1 force_constraint1 = analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce1"))[0] force_constraint1.References = [(doc.SquareTube, "Edge9")] force_constraint1.Force = 100000.00 force_constraint1.Direction = (doc.SquareTube, ["Edge9"]) force_constraint1.Reversed = True # force_constraint2 force_constraint2 = analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce2"))[0] force_constraint2.References = [(doc.SquareTube, "Edge3")] force_constraint2.Force = 100000.00 force_constraint2.Direction = (doc.SquareTube, ["Edge3"]) force_constraint2.Reversed = True # force_constraint3 force_constraint3 = analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce3"))[0] force_constraint3.References = [(doc.SquareTube, "Edge11")] force_constraint3.Force = 100000.00 force_constraint3.Direction = (doc.SquareTube, ["Edge11"]) force_constraint3.Reversed = True # force_constraint4 force_constraint4 = analysis.addObject( ObjectsFem.makeConstraintForce(doc, name="ConstraintForce4"))[0] force_constraint4.References = [(doc.SquareTube, "Edge6")] force_constraint4.Force = 100000.00 force_constraint4.Direction = (doc.SquareTube, ["Edge6"]) force_constraint4.Reversed = True # mesh from .meshes.mesh_square_pipe_end_twisted_tria6 import create_nodes, create_elements fem_mesh = Fem.FemMesh() control = create_nodes(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating nodes.\n") control = create_elements(fem_mesh) if not control: FreeCAD.Console.PrintError("Error on creating elements.\n") femmesh_obj = analysis.addObject( ObjectsFem.makeMeshGmsh(doc, mesh_name) )[0] femmesh_obj.FemMesh = fem_mesh femmesh_obj.Part = geom_obj femmesh_obj.SecondOrderLinear = False doc.recompute() return doc
def WrapFace(Face, Radius, axis, normal, zeroVert, cent, zeroVertNormal): # circent = cent Edges = [] for e in Face.Edges: #print(type(e.Curve)) if isinstance(e.Curve, (Part.Circle, Part.ArcOfCircle)): #bspline = gg.Curve.toBSpline() poles = e.discretize(Number=50) bspline = Part.BSplineCurve() bspline.interpolate(poles) #bs = bspline.toShape() #Part.show(bs,"bspline") Edges.append( WrapBSpline(bspline, Radius, zeroVert, cent, axis, zeroVertNormal)) elif isinstance(e.Curve, Part.BSplineCurve): Edges.append( WrapBSpline(e.Curve, Radius, zeroVert, cent, axis, zeroVertNormal)) elif isinstance(e.Curve, Part.Line): sp = e.valueAt(e.FirstParameter) ep = e.valueAt(e.LastParameter) dist1 = abs(sp.distanceToPlane(cent, normal)) dist2 = abs(ep.distanceToPlane(cent, normal)) #print(dist1,dist2) linenormal = ep - sp mp = sp + linenormal / 2.0 linenormal.normalize() #print(linenormal.dot(axis)) #print(linenormal.dot(normal)) if linenormal.dot(axis) == 0.0 and (dist2 - dist1) == 0.0: Point1 = getPointOnCylinder(zeroVert, sp, Radius, cent, axis, zeroVertNormal) Point2 = getPointOnCylinder(zeroVert, mp, Radius, cent, axis, zeroVertNormal) Point3 = getPointOnCylinder(zeroVert, ep, Radius, cent, axis, zeroVertNormal) arc = Part.Arc(Point1, Point2, Point3) Edges.append(arc.toShape()) elif linenormal.dot(axis) == 1.0 or linenormal.dot(axis) == -1.0: Point1 = getPointOnCylinder(zeroVert, sp, Radius, cent, axis, zeroVertNormal) Point2 = getPointOnCylinder(zeroVert, ep, Radius, cent, axis, zeroVertNormal) #print([Point1,Point2]) Edges.append(Part.makeLine(Point1, Point2)) elif linenormal.dot(normal) == 1.0 or linenormal.dot( normal) == -1.0: Point1 = getPointOnCylinder(zeroVert, sp, Radius, cent, axis, zeroVertNormal) Point2 = getPointOnCylinder(zeroVert, ep, Radius, cent, axis, zeroVertNormal) #print([Point1,Point2]) Edges.append(Part.makeLine(Point1, Point2)) else: poles = e.discretize(Number=50) #print(poles) bspline = Part.BSplineCurve() bspline.interpolate(poles, PeriodicFlag=False) #bs = bspline.toShape() #Part.show(bs,"bspline") #bspline = disgg.toBSpline() Edges.append( WrapBSpline(bspline, Radius, zeroVert, cent, axis, zeroVertNormal)) return Edges
def draw(dialog, size): obj = dialog.ob lines = [] if obj.showhelper: lines.append(Part.makeLine(obj.P0, obj.P1)) lines.append(Part.makeLine(obj.P0, obj.P3)) lines.append(Part.makeLine(obj.P0, obj.P5)) lines.append(Part.makeLine(obj.P3, obj.P4)) lines.append(Part.makeLine(obj.P4, obj.P5)) lines.append(Part.makeLine(obj.P1, obj.P2)) lines.append(Part.makeLine(obj.P2, obj.P3)) p0 = numpo(obj.P0) p1 = numpo(obj.P1) p2 = numpo(obj.P2) p3 = numpo(obj.P3) p4 = numpo(obj.P4) p5 = numpo(obj.P5) d = docs() # punkte im image space/perspective/2D ip0 = createMP2("P0", d.i(), obj.P0) ip0.type = 'IP' ip1 = createMP2("P1", d.i(), obj.P1) ip1.type = 'IP' ip2 = createMP2("P2", d.i(), obj.P2) ip2.type = 'IP' ip3 = createMP2("P3", d.i(), obj.P3) ip3.type = 'IBP' obj.basePoint = ip3 ip3.ViewObject.PointColor = (1.0, .0, .0) ip4 = createMP2("P4", d.i(), obj.P4) ip4.type = 'IP' ip5 = createMP2("P5", d.i(), obj.P5) ip5.type = 'IP' # punkte im model space/ortho/3D # hier koordinaten uaf lwh anpassen if False: mp0 = createMP2("P0", d.m(), FreeCAD.Vector(0, 0, obj.height)) mp0.type = 'MP' mp1 = createMP2("P1", d.m(), FreeCAD.Vector(-obj.length, 0, obj.height)) mp1.type = 'MP' mp2 = createMP2("P2", d.m(), FreeCAD.Vector(-obj.length, 0, 0)) mp2.type = 'MP' mp3 = createMP2("P3", d.m(), FreeCAD.Vector()) mp3.type = 'MBP' mp3.ViewObject.PointColor = (1.0, .0, .0) mp4 = createMP2("P4", d.m(), FreeCAD.Vector(0, obj.width, 0)) mp4.type = 'MP' mp5 = createMP2("P5", d.m(), FreeCAD.Vector(0, obj.width, obj.height)) mp5.type = 'MP' try: sr = schnittpunkt(p3, p4, p0, p5) except: sr = None try: sl = schnittpunkt(p3, p2, p0, p1) except: sl = None try: sz = schnittpunkt(p1, p2, p0, p3) except: sz = None # fehlerausgleich try: sz1 = schnittpunkt(p1, p2, p0, p3) sz2 = schnittpunkt(p4, p5, p0, p3) sz = np.array([(sz1[0] + sz2[0]) / 2, (sz1[1] + sz2[1]) / 2]) p5 = schnittpunkt(p0, sr, sz, p4) p1 = schnittpunkt(p0, sl, sz, p2) except: pass if obj.showhorizon: try: lines.append(Part.makeLine(vec(p4), vec(sr))) lines.append(Part.makeLine(vec(p5), vec(sr))) lines.append(Part.makeCircle(size, vec(sr))) except: pass try: lines.append(Part.makeLine(vec(p1), vec(sl))) lines.append(Part.makeLine(vec(p2), vec(sl))) lines.append(Part.makeCircle(size, vec(sl))) except: pass try: lines.append(Part.makeLine(vec(p0), vec(sz))) lines.append(Part.makeLine(vec(p1), vec(sz))) lines.append(Part.makeCircle(size, vec(sz))) except: pass if sr <> None: obj.rpol = vec(sr) if sl <> None: obj.lpol = vec(sl) if sz <> None: obj.zpol = vec(sz) docs().run() if dialog.root.ids['eyepoint'].isChecked(): lines.append(Part.makeCircle(size, FreeCAD.Vector())) if dialog.root.ids['vanishing'].isChecked(): lines.append(Part.makeLine(vec(sr), vec(sl))) lines.append(Part.makeLine(vec(sl), vec(sz))) lines.append(Part.makeLine(vec(sz), vec(sr))) if obj.part: App.ActiveDocument.removeObject(obj.part.Name) c = Part.makeCompound(lines) obj.Shape = c vo = obj.ViewObject vo.PointColor = (1.0, 0.0, 0.0) vo.PointSize = 5 vo.LineColor = (1.0, 1.0, 0.0) obj.Placement.Base.z = 0.01 d = docs() if False: # vertexes of the basebox createBaseBox(d.m(), obj.length, obj.width, obj.height) # a basebox placeholder bx = d.m().getObject('BaseBox') if bx == None: bx = d.m().addObject("Part::Box", "BaseBox") bx.Width = obj.width bx.Length = obj.length bx.Height = obj.height bx.Placement.Base.x = -obj.length bx.ViewObject.Transparency = 90 print("draw done")
def draw_strip_automatically_in_mat_foundation( foundation=None, openings: Union[list, bool] = None, x_width: float = 1000, y_width: Union[float, bool] = None, equal: bool = False, x_layer_name='A', y_layer_name='B', draw_x: bool = True, draw_y: bool = True, consider_openings: bool = True, ): if foundation is None: foundation = FreeCAD.ActiveDocument.Foundation x_coords_width, y_coords_width = get_xy_coords_width_in_mat_foundation( foundation, openings, x_width, y_width, equal, consider_openings=consider_openings, ) foundation_bb = foundation.Shape.BoundBox x_min_f = foundation_bb.XMin y_min_f = foundation_bb.YMin x_max_f = foundation_bb.XMax y_max_f = foundation_bb.YMax z = foundation.level.Value import BOPTools.SplitAPI as sp from safe.punch import strip i = j = 0 if draw_x: x_strips = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "x_strips") y_lines = [] for y in y_coords_width.keys(): p1 = (x_min_f, y, z) p2 = (x_max_f, y, z) y_lines.append(Part.makeLine(p1, p2)) y_slices = sp.slice(foundation.plan, y_lines, 'Split') for edge in y_slices.Edges: bb = edge.BoundBox if bb.YLength == 0: y = bb.YMin width = y_coords_width.get(y, None) if width is not None: i += 1 points = [v.Point for v in edge.Vertexes] s = strip.make_strip(points, layer=x_layer_name, width=width) s.Label = f'CS{x_layer_name}{i}' x_strips.addObject(s) if draw_y: y_strips = FreeCAD.ActiveDocument.addObject("App::DocumentObjectGroup", "y_strips") x_lines = [] for x in x_coords_width.keys(): p1 = (x, y_min_f, z) p2 = (x, y_max_f, z) x_lines.append(Part.makeLine(p1, p2)) x_slices = sp.slice(foundation.plan, x_lines, 'Split') for edge in x_slices.Edges: bb = edge.BoundBox if bb.XLength == 0: x = bb.XMin width = x_coords_width.get(x, None) if width is not None: j += 1 points = [v.Point for v in edge.Vertexes] s = strip.make_strip(points, layer=y_layer_name, width=width) s.Label = f'CS{y_layer_name}{j}' y_strips.addObject(s)
def fclinev2(x1, y1, x2, y2): v = FreeCAD.Vector(float(x1) * scaler, float(y1) * scaler, 0) v2 = FreeCAD.Vector(float(x2) * scaler, float(y2) * scaler, 0) l = Part.makeLine(v, v2) return l
def execute(self, obj): if self.clone(obj): return import Part, math, DraftGeomUtils pl = obj.Placement #self.baseface = None self.flip = False if hasattr(obj, "Flip"): if obj.Flip: self.flip = True base = None w = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: base = obj.Base.Shape #pl = obj.Base.Placement else: if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = Part.__sortEdges__(w.Edges) l = len(edges) for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for i in range(l): self.calcEdgeGeometry(edges, i) for i in range(l): self.calcDraftEdges(i) for i in range(l): self.calcEave(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): self.getRoofPaneProject(i) profilCurrent = self.findProfil(i) midpoint = DraftGeomUtils.findMidpoint( profilCurrent["edge"]) ptsPaneProject = profilCurrent["points"] lp = len(ptsPaneProject) if lp != 0: ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for p in range(lp): edge = Part.makeLine(ptsPaneProject[p], ptsPaneProject[p + 1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profilCurrent["thickness"] / (math.cos( math.radians(profilCurrent["angle"]))) overhangV = profilCurrent["overhang"] * math.tan( math.radians(profilCurrent["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude( FreeCAD.Vector( 0, 0, profilCurrent["height"] + 1000000.0)) f.translate( FreeCAD.Vector(0.0, 0.0, -2 * overhangV)) ptsPaneProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector( profilCurrent["run"], profilCurrent["height"] + thicknessV, 0.0), FreeCAD.Vector(-profilCurrent["overhang"], -overhangV + thicknessV, 0.0) ] self.shps.append( self.createProfilShape(ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## subVolume shape ptsSubVolumeProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"] + 900000.0, 0.0), FreeCAD.Vector(-profilCurrent["overhang"], profilCurrent["height"] + 900000.0, 0.0) ] self.subVolshps.append( self.createProfilShape(ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = self.shps.pop() for s in self.shps: base = base.fuse(s) base = self.processSubShapes(obj, base) self.applyShape(obj, base, pl, allownosolid=True) elif base: base = self.processSubShapes(obj, base) self.applyShape(obj, base, pl, allownosolid=True) else: FreeCAD.Console.PrintMessage( translate("Arch", "Unable to create a roof"))
def update(self, L, B, T): """Update the 3D view printing the annotations. Keyword arguments: L -- Selected ship length. B -- Selected ship breadth. T -- Selected ship draft. """ self.clean() # Move to the international system units L *= Units.Metre.Value B *= Units.Metre.Value T *= Units.Metre.Value # Draw the base line xStart = -0.6 * L xEnd = 0.6 * L baseLine = Part.makeLine((xStart, 0, 0), (xEnd, 0, 0)) Part.show(baseLine) objs = FreeCAD.ActiveDocument.Objects self.baseLine = objs[len(objs) - 1] self.baseLine.Label = 'BaseLine' try: text = str( QtGui.QApplication.translate("ship_create", "Base line", None, QtGui.QApplication.UnicodeUTF8)) except: text = "Base line" self.baseLineLabel = DrawText('BaseLineText', text, Base.Vector(xEnd, 0, 0)) # Draw the free surface line fsLine = Part.makeLine((xStart, 0, T), (xEnd, 0, T)) Part.show(fsLine) objs = FreeCAD.ActiveDocument.Objects self.fsLine = objs[len(objs) - 1] self.fsLine.Label = 'FreeSurface' try: text = str( QtGui.QApplication.translate("ship_create", "Free surface", None, QtGui.QApplication.UnicodeUTF8)) except: text = "Free surface" self.fsLineLabel = DrawText('FSText', text, Base.Vector(xEnd, 0, T)) # Draw the forward perpendicular zStart = -0.1 * T zEnd = 1.1 * T fpLine = Part.makeLine((0.5 * L, 0, zStart), (0.5 * L, 0, zEnd)) Part.show(fpLine) objs = FreeCAD.ActiveDocument.Objects self.fpLine = objs[len(objs) - 1] self.fpLine.Label = 'ForwardPerpendicular' try: text = str( QtGui.QApplication.translate("ship_create", "Forward perpendicular", None, QtGui.QApplication.UnicodeUTF8)) except: text = "Forward perpendicular" self.fpLineLabel = DrawText('FPText', text, Base.Vector(0.5 * L, 0, zEnd)) # Draw the after perpendicular apLine = Part.makeLine((-0.5 * L, 0, zStart), (-0.5 * L, 0, zEnd)) Part.show(apLine) objs = FreeCAD.ActiveDocument.Objects self.apLine = objs[len(objs) - 1] self.apLine.Label = 'AfterPerpendicular' try: text = str( QtGui.QApplication.translate("ship_create", "After perpendicular", None, QtGui.QApplication.UnicodeUTF8)) except: text = "After perpendicular" self.apLineLabel = DrawText('APText', text, Base.Vector(-0.5 * L, 0, zEnd)) # Draw the amin frame amLine = Part.makeLine((0, -0.5 * B, zStart), (0, -0.5 * B, zEnd)) Part.show(amLine) objs = FreeCAD.ActiveDocument.Objects self.amLine = objs[len(objs) - 1] self.amLine.Label = 'AminFrame' try: text = str( QtGui.QApplication.translate("ship_create", "Main frame", None, QtGui.QApplication.UnicodeUTF8)) except: text = "Main frame" self.amLineLabel = DrawText('AMText', text, Base.Vector(0, -0.5 * B, zEnd))
def externalFaces(self, shape): """ Returns detected external faces. @param shape Shape where external faces wanted. @return List of external faces detected. """ result = [] faces = shape.Faces bbox = shape.BoundBox L = bbox.XMax - bbox.XMin B = bbox.YMax - bbox.YMin T = bbox.ZMax - bbox.ZMin dist = math.sqrt(L*L + B*B + T*T) msg = QtGui.QApplication.translate( "ship_console", "Computing external faces", None) App.Console.PrintMessage(msg + '...\n') # Valid/unvalid faces detection loop for i in range(len(faces)): App.Console.PrintMessage("\t{} / {}\n".format(i + 1, len(faces))) f = faces[i] # Create a line normal to surface at middle point u = 0.0 v = 0.0 try: surf = f.Surface u = 0.5*(surf.getUKnots()[0]+surf.getUKnots()[-1]) v = 0.5*(surf.getVKnots()[0]+surf.getVKnots()[-1]) except: cog = f.CenterOfMass [u, v] = f.Surface.parameter(cog) p0 = f.valueAt(u, v) try: n = f.normalAt(u, v).normalize() except: continue p1 = p0 + n.multiply(1.5 * dist) line = Part.makeLine(p0, p1) # Look for faces in front of this nPoints = 0 for j in range(len(faces)): f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints = nPoints + len(section) - 2 # In order to avoid special directions we can modify line # normal a little bit. angle = 5 line.rotate(p0, Vector(1, 0, 0), angle) line.rotate(p0, Vector(0, 1, 0), angle) line.rotate(p0, Vector(0, 0, 1), angle) nPoints2 = 0 for j in range(len(faces)): if i == j: continue f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints2 = nPoints + len(section) - 2 # If the number of intersection points is pair, is a # external face. So if we found an odd points intersection, # face must be discarded. if (nPoints % 2) or (nPoints2 % 2): continue result.append(f) self.timer.start(0.0) self.loop.exec_() if(not self.running): break return result
def compute(): QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) if FreeCAD.ActiveDocument is None: FreeCAD.newDocument("Gear") oldDocumentObjects = App.ActiveDocument.Objects try: N = int(l1.text()) p = float(l2.text()) alfa = int(l3.text()) y = float( l4.text()) # standard value y<1 for gear drives y>1 for Gear pumps m = p / math.pi # standard value 0.06, 0.12, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 60 (polish norm) c = float(l5.text()) * m # standard value 0,1*m - 0,3*m j = float(l6.text()) * m # standard value 0,015 - 0,04*m width = float(l7.text()) # gear width except ValueError: FreeCAD.Console.PrintError("Wrong input! Only numbers allowed...\n") # tooth height h = 2 * y * m + c # pitch diameter d = N * m # root diameter df = d - 2 * y * m - 2 * c # df=d-2hf where and hf=y*m+c # addendum diameter da = d + 2 * y * m # da=d+2ha where ha=y*m # base diameter for involute db = d * math.cos(math.radians(alfa)) #Base circle baseCircle = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "BaseCircle") Draft._Circle(baseCircle) Draft._ViewProviderDraft(baseCircle.ViewObject) baseCircle.Radius = db / 2 baseCircle.FirstAngle = 0.0 baseCircle.LastAngle = 0.0 # Root circle rootCircle = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "RootCircle") Draft._Circle(rootCircle) Draft._ViewProviderDraft(rootCircle.ViewObject) rootCircle.Radius = df / 2 rootCircle.FirstAngle = 0.0 rootCircle.LastAngle = 0.0 # Addendum circle addendumCircle = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "AddendumCircle") Draft._Circle(addendumCircle) Draft._ViewProviderDraft(addendumCircle.ViewObject) addendumCircle.Radius = da / 2 addendumCircle.FirstAngle = 0.0 addendumCircle.LastAngle = 0.0 # Pitch circle pitchCircle = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "PitchCircle") Draft._Circle(pitchCircle) Draft._ViewProviderDraft(pitchCircle.ViewObject) pitchCircle.Radius = d / 2 pitchCircle.FirstAngle = 0.0 pitchCircle.LastAngle = 0.0 #************ Calculating right sides of teeth # Involute of base circle involute = [] involutee = [] involutesav = [] for t in range(0, 60, 1): x = db / 2 * (math.cos(math.radians(t)) + math.radians(t) * math.sin(math.radians(t))) y = db / 2 * (math.sin(math.radians(t)) - math.radians(t) * math.cos(math.radians(t))) involute.append(Part.Vertex(x, y, 0).Point) #************ Drawing right sides of teeth involutesav.extend(involute) involutee.extend(involute) for angle in range(1, N + 1, 1): involuteobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", "InvoluteL" + str(angle)) involutee.insert(0, (0, 0, 0)) involuteshape = Part.makePolygon(involutee) involuteobj.Shape = involuteshape involutee = [] for num in range(0, 60, 1): point = involute.pop() pointt = Part.Vertex( point.x * math.cos(math.radians(angle * 360 / N)) - point.y * math.sin(math.radians(angle * 360 / N)), point.x * math.sin(math.radians(angle * 360 / N)) + point.y * math.cos(math.radians(angle * 360 / N)), 0).Point involutee.insert(0, pointt) involute.extend(involutesav) involutee = [] #************ Calculating difference between tooth spacing on BaseCircle and PitchCircle pc = App.ActiveDocument.getObject("PitchCircle") inv = App.ActiveDocument.getObject("InvoluteL1") cut = inv.Shape.cut(pc.Shape) # FreeCAD.ActiveDocument.addObject("Part::Feature","CutInv").Shape=cut invPoint = cut.Vertexes[0].Point diff = invPoint.y * 2 # instead of making axial symmetry and calculating point distance. anglediff = 2 * math.asin(diff / d) #************ Calculating left sides of teeth #************ Inversing Involute for num in range(0, 60, 1): point = involute.pop() pointt = Part.Vertex(point.x, point.y * -1, 0).Point involutee.insert(0, pointt) involute.extend(involutee) involutee = [] #Normal tooth size calculated as: 0,5* p - j j = m * 0,1 below are calculations # 0,5* p - m * 0,1 # 0,5* p - p /pi * 0,1 # 0,5*360/N - ((360/N)/pi)* 0,1 # 0,5*360/N - (360/N)*((1/pi)*0,1) j = (p/pi)*0,1 # 0,5*360/N - (360/N)*((p/pi)*0,1)/p # 0,5*360/N - (360/N)*( j )/p for num in range(0, 60, 1): point = involute.pop() pointt = Part.Vertex( point.x * math.cos(math.radians(180 / N - (360 / N) * (j / p)) + anglediff) - point.y * math.sin(math.radians(180 / N - (360 / N) * (j / p)) + anglediff), point.x * math.sin(math.radians(180 / N - (360 / N) * (j / p)) + anglediff) + point.y * math.cos(math.radians(180 / N - (360 / N) * (j / p)) + anglediff), 0).Point involutee.insert(0, pointt) involute.extend(involutee) involutesav = [] involutesav.extend(involute) #************ Drawing left sides of teeth for angle in range(1, N + 1, 1): involuteobj = FreeCAD.ActiveDocument.addObject( "Part::Feature", "InvoluteR" + str(angle)) involutee.insert(0, (0, 0, 0)) involuteshape = Part.makePolygon(involutee) involuteobj.Shape = involuteshape involutee = [] for num in range(0, 60, 1): point = involute.pop() pointt = Part.Vertex( point.x * math.cos(math.radians(angle * 360 / N)) - point.y * math.sin(math.radians(angle * 360 / N)), point.x * math.sin(math.radians(angle * 360 / N)) + point.y * math.cos(math.radians(angle * 360 / N)), 0).Point involutee.insert(0, pointt) involute.extend(involutesav) Gui.SendMsgToActiveView("ViewFit") #************ Forming teeth cutCircle = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", "CutCircle") Draft._Circle(cutCircle) Draft._ViewProviderDraft(cutCircle.ViewObject) cutCircle.Radius = da # da because must be bigger than addendumCircle and bigger than whole construction da is right for this but it not has to be. cutCircle.FirstAngle = 0.0 cutCircle.LastAngle = 0.0 cutTool = cutCircle.Shape.cut(addendumCircle.Shape) # cutshape = Part.show(cutTool) gearShape = rootCircle.Shape for invNum in range(1, N + 1, 1): invL = App.ActiveDocument.getObject("InvoluteL" + str(invNum)) invR = App.ActiveDocument.getObject("InvoluteR" + str(invNum)) cutL = invL.Shape.cut(cutTool) cutR = invR.Shape.cut(cutTool) pointL = cutL.Vertexes.pop().Point pointR = cutR.Vertexes.pop().Point faceEdge = Part.makeLine(pointL, pointR) toothWhole = cutL.fuse(cutR) toothWhole = toothWhole.fuse(faceEdge) toothWire = Part.Wire(toothWhole.Edges) toothShape = Part.Face(toothWire) # tooth = App.ActiveDocument.addObject("Part::Feature", "Tooth" +str(invNum)) # tooth.Shape=toothShape gearShape = gearShape.fuse(toothShape) for o in App.ActiveDocument.Objects: if oldDocumentObjects.count(o) == 0: App.ActiveDocument.removeObject(o.Name) gearFlat = App.ActiveDocument.addObject("Part::Feature", "GearFlat") gearFlat.Shape = gearShape Gui.ActiveDocument.getObject(gearFlat.Name).Visibility = False gear = App.ActiveDocument.addObject("Part::Extrusion", "Gear3D") gear.Base = gearFlat gear.Dir = (0, 0, width) App.ActiveDocument.recompute() if c1.isChecked(): gearMesh = App.ActiveDocument.addObject("Mesh::Feature", "Gear3D-mesh") faces = [] triangles = gear.Shape.tessellate( 1) # the number represents the precision of the tessellation) for tri in triangles[1]: face = [] for i in range(3): vindex = tri[i] face.append(triangles[0][vindex]) faces.append(face) mesh = Mesh.Mesh(faces) gearMesh.Mesh = mesh App.ActiveDocument.removeObject(gear.Name) App.ActiveDocument.removeObject(gearFlat.Name) App.ActiveDocument.recompute() Gui.SendMsgToActiveView("ViewFit") QtGui.QApplication.restoreOverrideCursor() hide()
def runSimulation(complete_raw_path): # FreeCAD.ActiveDocument.WirePath.ViewObject.Visibility = False projected_trajectory_A = [] projected_trajectory_B = [] Z0 = FreeCAD.ActiveDocument.NiCrMachine.FrameDiameter*1.1*0 ZL = FreeCAD.ActiveDocument.NiCrMachine.ZLength Z1 = ZL + Z0 - FreeCAD.ActiveDocument.NiCrMachine.FrameDiameter*0.2 for i in range(len(complete_raw_path[0])): PA = complete_raw_path[0][i] PB = complete_raw_path[1][i] proj_A, proj_B = projectEdgeToTrajectory(PA, PB, Z0, Z1) projected_trajectory_A.append(proj_A) projected_trajectory_B.append(proj_B) machine_path = (projected_trajectory_A, projected_trajectory_B) # simulate machine path import time # create wire try: wire = FreeCAD.ActiveDocument.Wire except: wire = FreeCAD.ActiveDocument.addObject('Part::Feature', 'Wire') FreeCAD.ActiveDocument.NiCrMachine.addObject(wire) try: # remove previous trajectories for obj in FreeCAD.ActiveDocument.WireTrajectory.Group: FreeCAD.ActiveDocument.removeObject(obj.Name) FreeCAD.ActiveDocument.removeObject('WireTrajectory') except: pass wire_tr_folder = FreeCAD.ActiveDocument.addObject('App::DocumentObjectGroup', 'WireTrajectory') FreeCAD.ActiveDocument.NiCrMachine.addObject(wire_tr_folder) # retrieve machine shapes XA = FreeCAD.ActiveDocument.XA XB = FreeCAD.ActiveDocument.XB YA = FreeCAD.ActiveDocument.YA YB = FreeCAD.ActiveDocument.YB # ofsets xoff = FreeCAD.ActiveDocument.NiCrMachine.FrameDiameter*1.5*0 yoff = FreeCAD.ActiveDocument.NiCrMachine.FrameDiameter*1.8*0 wire_t_list = [] animation_delay = FreeCAD.ActiveDocument.NiCrMachine.AnimationDelay wire_trajectory = FreeCAD.ActiveDocument.addObject('Part::Feature','wire_tr') wire_tr_folder.addObject(wire_trajectory) # n iterator (for wire color) n = 0 # visualization color vcolor = FreeCAD.ActiveDocument.WirePath.TrajectoryColor # determine the first value for the wire color if vcolor == 'Speed': mxspeed = FreeCAD.ActiveDocument.WirePath.MaxCutSpeed cpspeed = complete_raw_path[2][n][1] wire_color = WireColor(cpspeed, mxspeed, 'Speed') if vcolor == 'Temperature': mxtemp = FreeCAD.ActiveDocument.WirePath.MaxWireTemp cptemp = complete_raw_path[2][n][1] wire_color = WireColor(cptemp, mxtemp, 'Temperature') # animation loop for i in range(len(machine_path[0])): pa = machine_path[0][i] pb = machine_path[1][i] # draw wire w = Part.makeLine(pa, pb) wire.Shape = w wire.ViewObject.LineColor = wire_color if i < complete_raw_path[2][n][0]: # draw wire trajectory wire_t_list.append(w) wire_trajectory.Shape = Part.makeCompound(wire_t_list) wire_trajectory.ViewObject.LineColor = wire_color else: n += 1 # create new wire trajectory object wire_trajectory = FreeCAD.ActiveDocument.addObject('Part::Feature', 'wire_tr') wire_tr_folder.addObject(wire_trajectory) # reset compound list wire_t_list = [] wire_t_list.append(w) wire_trajectory.Shape = Part.makeCompound(wire_t_list) # establish wire color if vcolor == 'Speed': mxspeed = FreeCAD.ActiveDocument.WirePath.MaxCutSpeed cpspeed = complete_raw_path[2][n][1] wire_color = WireColor(cpspeed, mxspeed, 'Speed') if vcolor == 'Temperature': mxtemp = FreeCAD.ActiveDocument.WirePath.MaxWireTemp cptemp = complete_raw_path[2][n][1] wire_color = WireColor(cptemp, mxtemp, 'Temperature') # assign wire color wire_trajectory.ViewObject.LineColor = wire_color # move machine --------------------------------------------------- # side A # -XA base_XA = XA.Placement.Base rot_XA = XA.Placement.Rotation base_XA = FreeCAD.Vector(pa.x-xoff, base_XA.y, base_XA.z) XA.Placement = FreeCAD.Placement(base_XA, rot_XA) # -YA base_YA = YA.Placement.Base rot_YA = YA.Placement.Rotation base_YA = FreeCAD.Vector(pa.x-xoff, pa.y-yoff, base_XA.z) YA.Placement = FreeCAD.Placement(base_YA, rot_XA) # -XB base_XB = XB.Placement.Base rot_XB = XB.Placement.Rotation base_XB = FreeCAD.Vector(pb.x-xoff, base_XB.y, base_XB.z) XB.Placement = FreeCAD.Placement(base_XB, rot_XB) # -YB base_YB = YB.Placement.Base rot_YB = YB.Placement.Rotation base_YB = FreeCAD.Vector(pb.x-xoff, pb.y-yoff, base_XB.z) YB.Placement = FreeCAD.Placement(base_YB, rot_XB) # gui update ------------------------------------------------------- FreeCAD.Gui.updateGui() time.sleep(animation_delay)
def test_get_extended_wire(self): """Test the DraftGeomUtils.get_extended_wire function.""" operation = "DraftGeomUtils.get_extended_wire" _msg(" Test '{}'".format(operation)) # Build wires made with straight edges and various combination of Orientation: the wires 1-4 are all equivalent points = [FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(1500.0, 2000.0, 0.0), FreeCAD.Vector(4500.0, 2000.0, 0.0), FreeCAD.Vector(4500.0, 2000.0, 2500.0)] edges = [] for start, end in zip(points[:-1], points[1:]): edge = Part.makeLine(start, end) edges.append(edge) wire1 = Part.Wire(edges) edges = [] for start, end in zip(points[:-1], points[1:]): edge = Part.makeLine(end, start) edge.Orientation = "Reversed" edges.append(edge) wire2 = Part.Wire(edges) edges = [] for start, end in zip(points[:-1], points[1:]): edge = Part.makeLine(start, end) edge.Orientation = "Reversed" edges.insert(0, edge) wire3 = Part.Wire(edges) wire3.Orientation = "Reversed" edges = [] for start, end in zip(points[:-1], points[1:]): edge = Part.makeLine(end, start) edges.insert(0, edge) wire4 = Part.Wire(edges) wire4.Orientation = "Reversed" # Build wires made with arcs and various combination of Orientation: the wires 5-8 are all equivalent points = [FreeCAD.Vector(0.0, 0.0, 0.0), FreeCAD.Vector(1000.0, 1000.0, 0.0), FreeCAD.Vector(2000.0, 0.0, 0.0), FreeCAD.Vector(3000.0, 0.0, 1000.0), FreeCAD.Vector(4000.0, 0.0, 0.0)] edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): edge = Part.Arc(start, mid, end).toShape() edges.append(edge) wire5 = Part.Wire(edges) edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): edge = Part.Arc(end, mid, start).toShape() edge.Orientation = "Reversed" edges.append(edge) wire6 = Part.Wire(edges) edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): edge = Part.Arc(start, mid, end).toShape() edge.Orientation = "Reversed" edges.insert(0, edge) wire7 = Part.Wire(edges) wire7.Orientation = "Reversed" edges = [] for start, mid, end in zip(points[:-2], points[1:-1], points[2:]): edge = Part.Arc(end, mid, start).toShape() edges.insert(0, edge) wire8 = Part.Wire(edges) wire8.Orientation = "Reversed" # Run "get_extended_wire" for all the wires with various offset_start, offset_end combinations num_subtests = 0 offset_values = (2000.0, 0.0, -1000, -2000, -3000, -5500) for i, wire in enumerate((wire1, wire2, wire3, wire4, wire5, wire6, wire7, wire8)): _msg(" Running tests with wire{}".format(i + 1)) for offset_start in offset_values: for offset_end in offset_values: if offset_start + offset_end > -wire.Length: subtest = "get_extended_wire(wire{0}, {1}, {2})".format(i + 1, offset_start, offset_end) num_subtests += 1 # TODO: it should be "with self.subtest(subtest):" but then it doesn't report failures. extended = DraftGeomUtils.get_extended_wire(wire, offset_start, offset_end) # Test that the extended wire's length is correctly changed self.assertAlmostEqual(extended.Length, wire.Length + offset_start + offset_end, DraftGeomUtils.precision(), "'{0}.{1}' failed".format(operation, subtest)) if offset_start == 0.0: # If offset_start is 0.0, check that the wire's start point is unchanged self.assertAlmostEqual(extended.OrderedVertexes[0].Point.distanceToPoint(wire.OrderedVertexes[0].Point), 0.0, DraftGeomUtils.precision(), "'{0}.{1}' failed".format(operation, subtest)) if offset_end == 0.0: # If offset_end is 0.0, check that the wire's end point is unchanged self.assertAlmostEqual(extended.OrderedVertexes[-1].Point.distanceToPoint(wire.OrderedVertexes[-1].Point), 0.0, DraftGeomUtils.precision(), "'{0}.{1}' failed".format(operation, subtest)) _msg(" Test completed, {} subtests run".format(num_subtests))
def _getRegularWire(self): """_getRegularWire()... Private method to retrieve the extension area, pertaining to the feature and sub element provided at class instantiation, as a closed wire. If no closed wire is possible, a `None` value is returned.""" PathLog.track() length = self.length.Value if PathGeom.isRoughly(0, length) or not self.sub: PathLog.debug("no extension, length=%.2f, sub=%s" % (length, self.sub)) return None feature = self.obj.Shape.getElement(self.feature) edges = self._getEdges() sub = Part.Wire(Part.sortEdges(edges)[0]) if 1 == len(edges): PathLog.debug("Extending single edge wire") edge = edges[0] if Part.Circle == type(edge.Curve): PathLog.debug("is Part.Circle") circle = edge.Curve # for a circle we have to figure out if it's a hole or a cylinder p0 = edge.valueAt(edge.FirstParameter) normal = (edge.Curve.Center - p0).normalize() direction = self._getDirectedNormal(p0, normal) if direction is None: return None if PathGeom.pointsCoincide(normal, direction): r = circle.Radius - length else: r = circle.Radius + length # assuming the offset produces a valid circle - go for it if r > 0: PathLog.debug("radius > 0 - extend outward") e3 = Part.makeCircle( r, circle.Center, circle.Axis, edge.FirstParameter * 180 / math.pi, edge.LastParameter * 180 / math.pi, ) # Determine if rotational alignment is necessary for new arc rotationAdjustment = arcAdjustmentAngle(edge, e3) if not PathGeom.isRoughly(rotationAdjustment, 0.0): e3.rotate( edge.Curve.Center, FreeCAD.Vector(0.0, 0.0, 1.0), rotationAdjustment, ) if endPoints(edge): PathLog.debug("Make section of donut") # need to construct the arc slice e0 = Part.makeLine( edge.valueAt(edge.FirstParameter), e3.valueAt(e3.FirstParameter), ) e2 = Part.makeLine( edge.valueAt(edge.LastParameter), e3.valueAt(e3.LastParameter), ) wire = Part.Wire([e0, edge, e2, e3]) # Determine if calculated extension collides with model (wrong direction) face = Part.Face(wire) if face.common(feature).Area < face.Area * 0.10: return wire # Calculated extension is correct else: return None # Extension collides with model extWire = Part.Wire([e3]) self.extFaces = [self._makeCircularExtFace(edge, extWire)] return extWire PathLog.debug("radius < 0 - extend inward") # the extension is bigger than the hole - so let's just cover the whole hole if endPoints(edge): # if the resulting arc is smaller than the radius, create a pie slice PathLog.track() center = circle.Center e0 = Part.makeLine(center, edge.valueAt(edge.FirstParameter)) e2 = Part.makeLine(edge.valueAt(edge.LastParameter), center) return Part.Wire([e0, edge, e2]) PathLog.track() return Part.Wire([edge]) else: PathLog.debug("else is NOT Part.Circle") PathLog.track(self.feature, self.sub, type(edge.Curve), endPoints(edge)) direction = self._getDirection(sub) if direction is None: return None return self._extendEdge(feature, edges[0], direction) elif sub.isClosed(): PathLog.debug("Extending multi-edge closed wire") subFace = Part.Face(sub) featFace = Part.Face(feature.Wires[0]) isOutside = True if not PathGeom.isRoughly(featFace.Area, subFace.Area): length = -1.0 * length isOutside = False try: off2D = sub.makeOffset2D(length) except FreeCAD.Base.FreeCADError as ee: PathLog.debug(ee) return None if isOutside: self.extFaces = [Part.Face(off2D).cut(featFace)] else: self.extFaces = [subFace.cut(Part.Face(off2D))] return off2D PathLog.debug("Extending multi-edge open wire") extendedWire = extendWire(feature, sub, length) if extendedWire is None: return extendedWire # Trim wire face using model extFace = Part.Face(extendedWire) trimmedWire = extFace.cut(self.obj.Shape).Wires[0] return trimmedWire.copy()
def smCornerR(reliefsketch="Circle", size=3.0, ratio=1.0, xoffset=0.0, yoffset=0.0, kfactor=0.5, sketch='', flipped=False, selEdgeNames='', MainObject=None): resultSolid = MainObject.Shape.copy() REdgelist = [] for selEdgeName in selEdgeNames: REdge = resultSolid.getElement(selEdgeName) REdgelist.append(REdge) DetailList = getBendDetail(resultSolid, REdgelist[0], REdgelist[1], kfactor) cornerPoint, centerPoint, LargeFace, thk, unfoldLength, neturalRadius = DetailList normal = LargeFace.normalAt(0, 0) SplitLineVector = centerPoint - cornerPoint if "Scaled" in reliefsketch: size = ratio * abs(SplitLineVector.Length) SplitLineVector.normalize() #print([centerPoint, cornerPoint, SplitLineVector] ) SplitLine = Part.makeLine(centerPoint + SplitLineVector * size * 3, cornerPoint + SplitLineVector * -size * 3) #Part.show(SplitLine,"SplitLine") if reliefsketch != "Sketch": sketch = makeSketch(reliefsketch, size, ratio, centerPoint, normal, SplitLineVector) reliefFace = Part.Face(sketch) else: reliefFace = Part.Face(sketch.Shape.Wires[0]) #Part.show(reliefFace,'reliefFace') #To check face direction coeff = normal.dot(reliefFace.Faces[0].normalAt(0, 0)) if coeff < 0: reliefFace.reverse() # to get top face cut First_face = LargeFace.common(reliefFace) #Part.show(First_face,'First_face') Balance_Face = reliefFace.cut(First_face) #Part.show(Balance_Face,'Balance_Face') #To get bend solid face SplitFaces = BOPTools.SplitAPI.slice(Balance_Face.Faces[0], SplitLine.Edges, "Standard", 0.0) #Part.show(SplitFaces,"SplitFaces") #To get top face normal, flatsolid solidlist = [] if First_face.Faces: Flatsolid = First_face.extrude(normal * -thk) #Part.show(Flatsolid,"Flatsolid") solidlist.append(Flatsolid) if SplitFaces.Faces: for BalanceFace in SplitFaces.Faces: #Part.show(BalanceFace,"BalanceFace") TopFace = LargeFace #Part.show(TopFace,"TopFace") while BalanceFace.Faces: BendEdgelist = smGetEdgelist(BalanceFace, TopFace) for BendEdge in BendEdgelist: #Part.show(BendEdge,"BendEdge") edge_facelist = resultSolid.ancestorsOfType( BendEdge, Part.Face) for cyl_face in edge_facelist: print(type(cyl_face.Surface)) if issubclass(type(cyl_face.Surface), Part.Cylinder): break if issubclass(type(cyl_face.Surface), Part.Cylinder): break #Part.show(BendEdge,"BendEdge") facelist = resultSolid.ancestorsOfType(BendEdge, Part.Face) #To get bend radius, bend angle for cylface in facelist: if issubclass(type(cylface.Surface), Part.Cylinder): break if not (issubclass(type(cylface.Surface), Part.Cylinder)): break #Part.show(cylface,"cylface") for planeface in facelist: if issubclass(type(planeface.Surface), Part.Plane): break #Part.show(planeface,"planeface") normal = planeface.normalAt(0, 0) revAxisV = cylface.Surface.Axis revAxisP = cylface.Surface.Center bendA = bendAngle(cylface, revAxisP) #print([bendA, revAxisV, revAxisP, cylface.Orientation]) #To check bend direction offsetface = cylface.makeOffsetShape(-thk, 0.0, fill=False) #Part.show(offsetface,"offsetface") if offsetface.Area < cylface.Area: bendR = cylface.Surface.Radius - thk flipped = True else: bendR = cylface.Surface.Radius flipped = False #To arrive unfold Length, neturalRadius unfoldLength = (bendR + kfactor * thk) * abs(bendA) * math.pi / 180.0 neturalRadius = (bendR + kfactor * thk) #print([unfoldLength,neturalRadius]) #To get faceNormal, bend face faceNormal = normal.cross(revAxisV).normalize() #print(faceNormal) if bendR < cylface.Surface.Radius: offsetSolid = cylface.makeOffsetShape(bendR / 2.0, 0.0, fill=True) else: offsetSolid = cylface.makeOffsetShape(-bendR / 2.0, 0.0, fill=True) #Part.show(offsetSolid,"offsetSolid") tool = BendEdge.copy() FaceArea = tool.extrude(faceNormal * -unfoldLength) #Part.show(FaceArea,"FaceArea") #Part.show(BalanceFace,"BalanceFace") SolidFace = offsetSolid.common(FaceArea) if not (SolidFace.Faces): faceNormal = faceNormal * -1 FaceArea = tool.extrude(faceNormal * -unfoldLength) BendSolidFace = BalanceFace.common(FaceArea) #Part.show(FaceArea,"FaceArea") #Part.show(BendSolidFace,"BendSolidFace") #print([bendR, bendA, revAxisV, revAxisP, normal, flipped, BendSolidFace.Faces[0].normalAt(0,0)]) bendsolid = SheetMetalBendSolid.BendSolid( BendSolidFace.Faces[0], BendEdge, bendR, thk, neturalRadius, revAxisV, flipped) #Part.show(bendsolid,"bendsolid") solidlist.append(bendsolid) if flipped == True: bendA = -bendA if not (SolidFace.Faces): revAxisV = revAxisV * -1 sketch_face = BalanceFace.cut(BendSolidFace) sketch_face.translate(faceNormal * unfoldLength) #Part.show(sketch_face,"sketch_face") sketch_face.rotate(revAxisP, -revAxisV, bendA) #Part.show(sketch_face,"Rsketch_face") CylEdge = smGetEdge(sketch_face, cylface) #Part.show(CylEdge,"CylEdge") edgefacelist = resultSolid.ancestorsOfType(CylEdge, Part.Face) for TopFace in edgefacelist: if not (issubclass(type(TopFace.Surface), Part.Cylinder)): break #Part.show(TopFace,"TopFace") #To get top face normal, flatsolid normal = TopFace.normalAt(0, 0) Flatface = sketch_face.common(TopFace) BalanceFace = sketch_face.cut(Flatface) #Part.show(BalanceFace,"BalanceFace") if Flatface.Faces: BalanceFace = sketch_face.cut(Flatface) #Part.show(BalanceFace,"BalanceFace") Flatsolid = Flatface.extrude(normal * -thk) #Part.show(Flatsolid,"Flatsolid") solidlist.append(Flatsolid) else: BalanceFace = sketch_face #To get relief Solid fused if len(solidlist) > 1: SMSolid = solidlist[0].multiFuse(solidlist[1:]) #Part.show(SMSolid,"SMSolid") SMSolid = SMSolid.removeSplitter() else: SMSolid = solidlist[0] #Part.show(SMSolid,"SMSolid") resultSolid = resultSolid.cut(SMSolid) return resultSolid
def execute(self, selfobj): """ Doing a recomputation. """ m_properties_list = ['Points', "VectorIndex", ] for m_property in m_properties_list: if m_property not in selfobj.PropertiesList: return if M_DEBUG: print("running NPointsLine.execute !") # To be compatible with previous version > 2019 if 'Parametric' in selfobj.PropertiesList: # Create the object the first time regardless # the parametric behavior if selfobj.Parametric == 'Not' and self.created: return if selfobj.Parametric == 'Interactive' and self.created: return try: import numpy as np except ImportError: m_msg = "You MUST install numpy to use this function !" printError_msg(m_msg, title=M_MACRO) try: line = None m_points = [] m_x = [] m_y = [] m_z = [] if selfobj.Points is not None: for p in linkSubList_convertToOldStyle(selfobj.Points): # n = eval(p[1].lstrip('Vertex')) m_n = re.sub('[^0-9]', '', p[1]) m_n = int(m_n) if M_DEBUG: print("p " + str(p)) print_msg("m_n = " + str(m_n)) m_point = p[0].Shape.Vertexes[m_n - 1].Point m_points.append(m_point) m_x.append(m_point.x) m_y.append(m_point.y) m_z.append(m_point.z) m_np_x = np.asfarray(m_x) m_np_y = np.asfarray(m_y) m_np_z = np.asfarray(m_z) if M_DEBUG: print_msg(" m_np_x=" + str(m_np_x)) print_msg(" m_np_y=" + str(m_np_y)) print_msg(" m_np_z=" + str(m_np_z)) m_data = np.concatenate((m_np_x[:, np.newaxis], m_np_y[:, np.newaxis], m_np_z[:, np.newaxis]), axis=1) if M_DEBUG: print_msg(" m_data=" + str(m_data)) # Calculate the mean of the points, i.e. the 'center' of the # cloud m_data_mean = m_data.mean(axis=0) axis_eo = Base.Vector( m_data_mean[0], m_data_mean[1], m_data_mean[2]) # Do an SVD on the mean-centered data. m_uu, m_dd, m_vv = np.linalg.svd(m_data - m_data_mean) if M_DEBUG: print_msg(" m_uu=" + str(m_uu)) print_msg(" m_dd=" + str(m_dd)) print_msg(" m_vv=" + str(m_vv)) # Now vv[0] contains the first principal component, i.e. the direction # vector of the 'best fit' line in the least squares sense. axis_dir = Base.Vector(m_vv[0][0], m_vv[0][1], m_vv[0][2]) point1 = axis_eo - axis_dir.normalize().multiply(m_dd[0] / 2.) if selfobj.VectorIndex == '1': point2 = axis_eo + \ axis_dir.normalize().multiply(m_dd[0] / 2.) if selfobj.VectorIndex == '2': axis_dir = Base.Vector(m_vv[1][0], m_vv[1][1], m_vv[1][2]) point1 = axis_eo - \ axis_dir.normalize().multiply(m_dd[0] / 2.) point2 = axis_eo + \ axis_dir.normalize().multiply(m_dd[1] / 2.) # point2 = axis_eo + axis_dir if selfobj.VectorIndex == '3': axis_dir = Base.Vector(m_vv[2][0], m_vv[2][1], m_vv[2][2]) point1 = axis_eo - \ axis_dir.normalize().multiply(m_dd[0] / 2.) point2 = axis_eo + \ axis_dir.normalize().multiply(m_dd[2] / 2.) # point2 = axis_eo + axis_dir line = Part.makeLine(coordVectorPoint(point1), coordVectorPoint(point2)) if line is not None: selfobj.Shape = line propertiesLine(selfobj.Label, self.color) selfobj.Point1_X = float(point1.x) selfobj.Point1_Y = float(point1.y) selfobj.Point1_Z = float(point1.z) selfobj.Point2_X = float(point2.x) selfobj.Point2_Y = float(point2.y) selfobj.Point2_Z = float(point2.z) # To be compatible with previous version 2018 if 'Parametric' in selfobj.PropertiesList: self.created = True except AttributeError as err: print("AttributeError" + str(err)) except Exception as err: printError_msg(err.args[0], title=M_MACRO)
def getElementShape(obj, tp=None, transform=False, noElementMap=True): if not isinstance(obj, (tuple, list)): shape = obj else: sub = obj[1] shape, mat, sobj = Part.getShape(obj[0], subname=sub, needSubElement=True, retType=2, transform=transform, noElementMap=noElementMap) if not sobj: logger.trace('no sub object {}', obj, frame=1) return if sobj.isDerivedFrom('App::Line'): if tp not in (None, Part.Shape, Part.Edge): logger.trace('wrong type of shape {}', obj) return size = sobj.ViewObject.Size shape = Part.makeLine(FreeCAD.Vector(-size, 0, 0), FreeCAD.Vector(size, 0, 0)) shape.transformShape(mat, False, True) elif sobj.isDerivedFrom('App::Plane'): if tp not in (None, Part.Shape, Part.Face): logger.trace('wrong type of shape {}', obj) return size = sobj.ViewObject.Size shape = Part.makePlane(size * 2, size * 2, FreeCAD.Vector(-size, -size, 0)) shape.transformShape(mat, False, True) elif sobj.isDerivedFrom('App::Placement'): sub = sub.split('.')[-1] dmap = { '': (0, 0, 1), 'Origin': (0, 0, 1), 'Z-Axis': (0, 0, 1), 'XY-Plane': (0, 0, -1), 'X-Axis': (1, 0, 0), 'YZ-Plane': (-1, 0, 0), 'Y-Axis': (0, 1, 0), 'XZ-Plane': (0, -1, 0) } shape = Part.Face( Part.Plane(FreeCAD.Vector(), FreeCAD.Vector(*dmap[sub]))) shape.transformShape(mat, False, True) elif shape.isNull(): logger.trace('no shape {}', obj) return if not isinstance(shape, Part.Shape) or shape.isNull(): logger.trace('null shape {}', obj) return if not tp or isinstance(shape, tp): return shape elif isinstance(shape, (Part.Vertex, Part.Edge, Part.Face)): logger.trace('wrong shape type {}', obj) return elif tp is Part.Vertex: if shape.countElement('Edge'): return if shape.countElement('Vertex') == 1: return shape.Vertex1 elif tp is Part.Edge: if shape.countElement('Face'): return if shape.countElement('Edge') == 1: return shape.Edge1 elif tp is Part.Face: if shape.countElement('Face') == 1: return shape.Face1 else: logger.trace('wrong shape type {}', obj)
def execute(self,obj): if self.clone(obj): return import Part,DraftGeomUtils pl = obj.Placement # test properties if not obj.Base: FreeCAD.Console.PrintLog(obj.Label+": no base\n") return if not hasattr(obj.Base,"Shape"): FreeCAD.Console.PrintLog(obj.Label+": invalid base\n") return if obj.VerticalMullionProfile: if not hasattr(obj.VerticalMullionProfile,"Shape"): FreeCAD.Console.PrintLog(obj.Label+": invalid vertical mullion profile\n") return if obj.HorizontalMullionProfile: if not hasattr(obj.HorizontalMullionProfile,"Shape"): FreeCAD.Console.PrintLog(obj.Label+": invalid horizontal mullion profile\n") return if obj.DiagonalMullionProfile: if not hasattr(obj.DiagonalMullionProfile,"Shape"): FreeCAD.Console.PrintLog(obj.Label+": invalid diagonal mullion profile\n") return facets = [] faces = [] if obj.Base.Shape.Faces: faces = obj.Base.Shape.Faces elif obj.Height.Value and obj.VerticalDirection.Length: ext = FreeCAD.Vector(obj.VerticalDirection) ext.normalize() ext = ext.multiply(obj.Height.Value) faces = [edge.extrude(ext) for edge in obj.Base.Shape.Edges] if not faces: FreeCAD.Console.PrintLog(obj.Label+": unable to build base faces\n") return # subdivide the faces into quads for face in faces: fp = face.ParameterRange # guessing horizontal/vertical directions vdir = obj.VerticalDirection if not vdir.Length: vdir = FreeCAD.Vector(0,0,1) vdir.normalize() basevector = face.valueAt(fp[1],fp[3]).sub(face.valueAt(fp[0],fp[2])) a = basevector.getAngle(vdir) if (a <= math.pi/2+ANGLETOLERANCE) and (a >= math.pi/2-ANGLETOLERANCE): facedir = True vertsec = obj.VerticalSections horizsec = obj.HorizontalSections else: facedir = False vertsec = obj.HorizontalSections horizsec = obj.VerticalSections hstep = (fp[1]-fp[0]) if vertsec: hstep = hstep/vertsec vstep = (fp[3]-fp[2]) if horizsec: vstep = vstep/horizsec # construct facets for i in range(vertsec or 1): for j in range(horizsec or 1): p0 = face.valueAt(fp[0]+i*hstep,fp[2]+j*vstep) p1 = face.valueAt(fp[0]+(i+1)*hstep,fp[2]+j*vstep) p2 = face.valueAt(fp[0]+(i+1)*hstep,fp[2]+(j+1)*vstep) p3 = face.valueAt(fp[0]+i*hstep,fp[2]+(j+1)*vstep) facet = Part.Face(Part.makePolygon([p0,p1,p2,p3,p0])) facets.append(facet) if not facets: FreeCAD.Console.PrintLog(obj.Label+": failed to subdivide shape\n") return baseshape = Part.makeShell(facets) # make edge/normal relation table edgetable = {} for face in baseshape.Faces: for edge in face.Edges: ec = edge.hashCode() if ec in edgetable: edgetable[ec].append(face) else: edgetable[ec] = [face] self.edgenormals = {} for ec,faces in edgetable.items(): if len(faces) == 1: self.edgenormals[ec] = faces[0].normalAt(0,0) else: n = faces[0].normalAt(0,0).add(faces[1].normalAt(0,0)) if n.Length > 0.001: n.normalize() else: # adjacent faces have same normals n = faces[0].normalAt(0,0) self.edgenormals[ec] = n # sort edges between vertical/horizontal hedges = [] vedges = [] for edge in baseshape.Edges: v = edge.Vertexes[-1].Point.sub(edge.Vertexes[0].Point) a = v.getAngle(vdir) if (a <= math.pi/2+ANGLETOLERANCE) and (a >= math.pi/2-ANGLETOLERANCE): hedges.append(edge) else: vedges.append(edge) # construct vertical mullions vmullions = [] vprofile = self.getMullionProfile(obj,"Vertical") if vprofile and vertsec: for vedge in vedges: vn = self.edgenormals[vedge.hashCode()] if (vn.x != 0) or (vn.y != 0): avn = FreeCAD.Vector(vn.x,vn.y,0) rot = FreeCAD.Rotation(FreeCAD.Vector(0,-1,0),avn) else: rot = FreeCAD.Rotation() if obj.VerticalMullionAlignment: ev = vedge.Vertexes[-1].Point.sub(vedge.Vertexes[0].Point) rot = FreeCAD.Rotation(FreeCAD.Vector(1,0,0),ev).multiply(rot) vmullions.append(self.makeMullion(vedge,vprofile,rot,obj.CenterProfiles)) # construct horizontal mullions hmullions = [] hprofile = self.getMullionProfile(obj,"Horizontal") if hprofile and horizsec: for hedge in hedges: rot = FreeCAD.Rotation(FreeCAD.Vector(0,1,0),-90) vn = self.edgenormals[hedge.hashCode()] if (vn.x != 0) or (vn.y != 0): avn = FreeCAD.Vector(vn.x,vn.y,0) rot = FreeCAD.Rotation(FreeCAD.Vector(0,-1,0),avn).multiply(rot) if obj.HorizontalMullionAlignment: rot = FreeCAD.Rotation(avn,vn).multiply(rot) hmullions.append(self.makeMullion(hedge,hprofile,rot,obj.CenterProfiles)) # construct panels panels = [] dedges = [] if obj.PanelThickness.Value: for face in baseshape.Faces: verts = [v.Point for v in face.OuterWire.OrderedVertexes] if len(verts) == 4: if DraftGeomUtils.isPlanar(verts): panel = self.makePanel(verts,obj.PanelThickness.Value) panels.append(panel) else: verts1 = [verts[0],verts[1],verts[2]] panel = self.makePanel(verts1,obj.PanelThickness.Value) panels.append(panel) verts2 = [verts[0],verts[2],verts[3]] panel = self.makePanel(verts2,obj.PanelThickness.Value) panels.append(panel) dedges.append(Part.makeLine(verts[0],verts[2])) # construct diagonal mullions dmullions = [] if dedges: n = (dedges[0].Vertexes[-1].Point.sub(dedges[0].Point)) dprofile = self.getMullionProfile(obj,"Diagonal") if dprofile: for dedge in dedges: rot = FreeCAD.Rotation(FreeCAD.Vector(0,0,1),dedge.Vertexes[-1].Point.sub(dedge.Vertexes[0].Point)) dmullions.append(self.makeMullion(dedge,dprofile,rot,obj.CenterProfiles)) # perform subtractions if obj.Refine: subvmullion = None subhmullion = None subdmullion = None if vmullions: subvmullion = vmullions[0].copy() for m in vmullions[1:]: subvmullion = subvmullion.fuse(m) if hmullions: subhmullion = hmullions[0].copy() for m in hmullions[1:]: subhmullion = subhmullion.fuse(m) if dmullions: subdmullion = dmullions[0].copy() for m in dmullions[1:]: subdmullion = subdmullion.fuse(m) if subvmullion: hmullions = [m.cut(subvmullion) for m in hmullions] if subhmullion: dmullions = [m.cut(subvmullion) for m in dmullions] dmullions = [m.cut(subhmullion) for m in dmullions] panels = [m.cut(subvmullion) for m in panels] panels = [m.cut(subhmullion) for m in panels] if subdmullion: panels = [m.cut(subdmullion) for m in panels] # mount shape obj.VerticalMullionNumber = len(vmullions) obj.HorizontalMullionNumber = len(hmullions) obj.DiagonalMullionNumber = len(dmullions) obj.PanelNumber = len(panels) shape = Part.makeCompound(vmullions+hmullions+dmullions+panels) shape = self.processSubShapes(obj,shape,pl) self.applyShape(obj,shape,pl)
def onChanged(self, fp, prop): if prop == "p1" or prop == "p2": ''' Print the name of the property that has changed ''' fp.Shape = Part.makeLine(fp.p1, fp.p2)
def execute(self, obj): if self.clone(obj): return import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base: if not obj.Angles: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: base = obj.Base.Shape.copy() else: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient " + str(l) + " aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for i in range(l): self.calcEdgeGeometry(edges, i) for i in range(l): self.calcDraftEdges(i) for i in range(l): self.calcEave(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): self.getRoofPaneProject(i) profilCurrent = self.findProfil(i) midpoint = DraftGeomUtils.findMidpoint( profilCurrent["edge"]) ptsPaneProject = profilCurrent["points"] lp = len(ptsPaneProject) if lp != 0: #print FreeCAD.Vector(ptsPaneProject[0]) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for p in range(lp): edge = Part.makeLine( ptsPaneProject[p], ptsPaneProject[p + 1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profilCurrent["thickness"] / ( math.cos( math.radians(profilCurrent["angle"]))) overhangV = profilCurrent[ "overhang"] * math.tan( math.radians(profilCurrent["angle"])) if wire.isClosed(): f = Part.Face(wire) #Part.show(f) f = f.extrude( FreeCAD.Vector( 0, 0, profilCurrent["height"] + 2 * thicknessV + 2 * overhangV)) f.translate( FreeCAD.Vector(0.0, 0.0, -2 * overhangV)) ptsPaneProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector( profilCurrent["run"], profilCurrent["height"] + thicknessV, 0.0), FreeCAD.Vector(-profilCurrent["overhang"], -overhangV + thicknessV, 0.0) ] self.createProfilShape(ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector( profilCurrent["run"], profilCurrent["height"] + 10000, 0.0), FreeCAD.Vector( 0.0, profilCurrent["height"] + 10000, 0.0) ] self.createProfilShape(ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, self.subVolshps, f) ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj, base) if base: if not base.isNull(): obj.Shape = base
def stl_write(faces, filename, thickness=0): """ Writes a graph object represented by faces to an STL file. Args: faces (list): list of faces that compose the object. filename (str): filename to write STL to. thickness (int or float): thickness of each face to draw. """ import triangle shape = None shells = [] triangles = [] for f in faces: r = f[0] # print ("the tramsform function is ",r) # if r is None: # continue # if r is None: #No transform # r = np.eye(4) A = f[1] facets = [] B = triangle.triangulate(A, opts='p') if not 'triangles' in B: print "No triangles in " + f[2] continue if thickness: for t in [ np.transpose( np.array([ list(B['vertices'][x]) + [0, 1] for x in (face[0], face[1], face[2]) ])) for face in B['triangles'] ]: facets.extend( [np.dot(r, x) for x in inflate(t, thickness=thickness)]) for t in [ np.transpose( np.array([ list(A['vertices'][x]) + [0, 1] for x in (edge[0], edge[1]) ])) for edge in A['segments'] ]: facets.extend([ np.dot(r, x) for x in inflate(t, thickness=thickness, edges=True) ]) else: for t in [ np.transpose( np.array([ list(B['vertices'][x]) + [0, 1] for x in (face[0], face[1], face[2]) ])) for face in B['triangles'] ]: #print "Here",r,t facets.append(np.dot(r, t)) triangles.extend(facets) if thickness: FREECADPATH = '/usr/lib64/freecad/lib' import sys sys.path.append(FREECADPATH) import Part meshes = [] for f in (np.transpose(t[0:3, :]) for t in facets): try: meshes.append( Part.Face( Part.Wire([ Part.makeLine(tuple(f[x]), tuple(f[x - 1])) for x in range(3) ]))) except RuntimeError: print "Skipping face: " + repr(f) shell = Part.makeShell(meshes) shells.append(shell) if shape is None: shape = shell else: shape = shape.fuse(shell) if shape: with open("freecad" + filename, 'wb') as fp: shape.exportStl("freecad" + filename) from stlwriter import Binary_STL_Writer faces = triangles with open(filename, 'wb') as fp: writer = Binary_STL_Writer(fp) writer.add_faces(faces) writer.close()
def execute(self, fp): ''' Print a short message when doing a recomputation, this method is mandatory ''' fp.Shape = Part.makeLine(fp.p1, fp.p2)
def circularHoleExecute(self, obj, holes): """circularHoleExecute(obj, holes) ... generate drill operation for each hole in holes.""" PathLog.track() machine = PathMachineState.MachineState() self.commandlist.append(Path.Command("(Begin Drilling)")) # rapid to clearance height command = Path.Command("G0", {"Z": obj.ClearanceHeight.Value}) machine.addCommand(command) self.commandlist.append(command) self.commandlist.append(Path.Command("G90")) # Absolute distance mode # Calculate offsets to add to target edge endoffset = 0.0 if obj.ExtraOffset == "Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) elif obj.ExtraOffset == "2x Drill Tip": endoffset = PathUtils.drillTipLength(self.tool) * 2 # http://linuxcnc.org/docs/html/gcode/g-code.html#gcode:g98-g99 self.commandlist.append(Path.Command(obj.ReturnLevel)) holes = PathUtils.sort_locations(holes, ["x", "y"]) # This section is technical debt. The computation of the # target shapes should be factored out for re-use. # This will likely mean refactoring upstream CircularHoleBase to pass # spotshapes instead of holes. startHeight = obj.StartDepth.Value + self.job.SetupSheet.SafeHeightOffset.Value edgelist = [] for hole in holes: v1 = FreeCAD.Vector(hole["x"], hole["y"], obj.StartDepth.Value) v2 = FreeCAD.Vector(hole["x"], hole["y"], obj.FinalDepth.Value - endoffset) edgelist.append(Part.makeLine(v1, v2)) # iterate the edgelist and generate gcode for edge in edgelist: PathLog.debug(edge) # move to hole location command = Path.Command("G0", {"X": hole["x"], "Y": hole["y"]}) self.commandlist.append(command) machine.addCommand(command) command = Path.Command("G0", {"Z": startHeight}) self.commandlist.append(command) machine.addCommand(command) command = Path.Command("G1", {"Z": obj.StartDepth.Value}) self.commandlist.append(command) machine.addCommand(command) # Technical Debt: We are assuming the edges are aligned. # This assumption should be corrected and the necessary rotations # performed to align the edge with the Z axis for drilling # Perform drilling dwelltime = obj.DwellTime if obj.DwellEnabled else 0.0 peckdepth = obj.PeckDepth.Value if obj.PeckEnabled else 0.0 repeat = 1 # technical debt: Add a repeat property for user control try: drillcommands = generator.generate(edge, dwelltime, peckdepth, repeat) except ValueError as e: # any targets that fail the generator are ignored PathLog.info(e) continue for command in drillcommands: self.commandlist.append(command) machine.addCommand(command) # Cancel canned drilling cycle self.commandlist.append(Path.Command("G80")) command = Path.Command("G0", {"Z": obj.SafeHeight.Value}) self.commandlist.append(command) machine.addCommand(command) # Apply feedrates to commands PathFeedRate.setFeedRate(self.commandlist, obj.ToolController)
def process(filename): """Process the filename and create a Draft Wire from the data. The common airfoil dat format has many flavors. This code should work with almost every dialect. Parameters ---------- filename : str The path to the filename to be opened. Returns ------- Part::Part2DObject or None. The created Draft Wire object or None if the file contains less than 3 points. """ # Regex to identify data rows and throw away unused metadata xval = r'(?P<xval>\-?\s*\d*\.*\d*([Ee]\-?\d+)?)' yval = r'(?P<yval>\-?\s*\d*\.*\d*([Ee]\-?\d+)?)' _regex = r'^\s*' + xval + r'\,?\s*' + yval + r'\s*$' regex = re.compile(_regex) afile = pythonopen(filename, 'r') # read the airfoil name which is always at the first line airfoilname = afile.readline().strip() coords = [] # upside = True # last_x = None # Collect the data for lin in afile: curdat = regex.match(lin) if (curdat is not None and curdat.group("xval") and curdat.group("yval")): x = float(curdat.group("xval")) y = float(curdat.group("yval")) # Some files specify the number of upper and lower points on the 2nd line: # " 67. 72." # See: http://airfoiltools.com/airfoil # This line must be skipped: if x < 2 and y < 2: # the normal processing coords.append(Vector(x, y, 0)) afile.close() if len(coords) < 3: FCC.PrintError(translate("ImportAirfoilDAT", "Did not find enough coordinates") + "\n") return None # sometimes coords are divided in upper an lower side # so that x-coordinate begin new from leading or trailing edge # check for start coordinates in the middle of list if coords[0:-1].count(coords[0]) > 1: flippoint = coords.index(coords[0], 1) upper = coords[0:flippoint] lower = coords[flippoint+1:] lower.reverse() for i in lower: upper.append(i) coords = upper # do we use the parametric Draft Wire? if useDraftWire: obj = Draft.make_wire(coords, True) # obj.label = airfoilname else: # alternate solution, uses common Part Faces lines = [] first_v = None last_v = None for v in coords: if first_v is None: first_v = v # Line between v and last_v if they're not equal if (last_v is not None) and (last_v != v): lines.append(Part.makeLine(last_v, v)) # The new last_v last_v = v # close the wire if needed if last_v != first_v: lines.append(Part.makeLine(last_v, first_v)) wire = Part.Wire(lines) face = Part.Face(wire) obj = FreeCAD.ActiveDocument.addObject('Part::Feature', airfoilname) obj.Shape = face return obj
def scalepoint(self): print "scale" sels = Gui.Selection.getSelection() if sels == []: return sel = sels[0] print sel.Label name = sel.Label import re m = re.match(r"axis cross (.*)", name) if m: print "gefunden" name = m.group(1) print "gefunden", name jj = App.ActiveDocument.getObjectsByLabel(name) print jj if len(jj) == 1: sel = jj[0] else: return print "verarbeite ", sel docs().i() yy = "axis cross " + name print("!" + yy + "!") obs = App.ActiveDocument.getObjectsByLabel("axis cross " + name) print obs if len(obs) > 0: print "gefunden" print obs[0] obj = obs[0] scaler = self.root.ids['scalepoint'].value() / 10.0 if scaler == 0: scaler = 0.1 self.root.ids['scalepointlabel'].setText( "Scale factor of the axis cross " + str(self.root.ids['scalepoint'].value() / 10.0)) # scaler=-1.0 print "scaler value is ", scaler lines = [] point = sel.clickPoint rone = sel.runit lone = sel.lunit zone = sel.zunit j = Part.makeLine(FreeCAD.Vector(), vec(rone).sub(point).multiply(scaler)) #j.Placement.Base=point lines.append(j) #mylpi.lunit=sc j = Part.makeLine(FreeCAD.Vector(), vec(lone).sub(point).multiply(scaler)) #j.Placement.Base=point lines.append(j) j = Part.makeLine(FreeCAD.Vector(), vec(zone).sub(point).multiply(scaler)) #j.Placement.Base=point lines.append(j) print lines comp = Part.makeCompound(lines) comp.Placement.Base = point obj.Shape = comp App.ActiveDocument.recompute()
def smgetSubface(face, obj, edge, thk): # Project thickness side edge to get one side rectangle normal = face.normalAt(0, 0) faceVert = face.Vertexes[0].Point pt1 = edge.Vertexes[0].Point.projectToPlane(faceVert, normal) pt2 = edge.Vertexes[1].Point.projectToPlane(faceVert, normal) vec1 = (pt2 - pt1) # find min & max point of cut shape wallsolidlist = [] for solid in obj.Solids: pt_list = [] for vertex in solid.Vertexes: poi = vertex.Point pt = poi.projectToPlane(faceVert, normal) pt_list.append(pt) p1 = Base.Vector(min([pts.x for pts in pt_list]), min([pts.y for pts in pt_list]), min([pts.z for pts in pt_list])) p2 = Base.Vector(max([pts.x for pts in pt_list]), max([pts.y for pts in pt_list]), max([pts.z for pts in pt_list])) #print([p1, p2]) # Find angle between diagnoal & thickness side edge vec2 = (p2 - p1) angle1 = vec2.getAngle(vec1) angle = math.degrees(angle1) #print(angle) # Check & correct orientation of diagnoal edge rotation e = Part.makeLine(p1, p2) e.rotate(p1, normal, -angle) vec2 = (e.valueAt(e.LastParameter) - e.valueAt(e.FirstParameter)).normalize() coeff = vec2.dot(vec1.normalize()) #print(coeff) if coeff != 1.0: angle = 90 - angle # Create Cut Rectangle Face from min/max points & angle e = Part.Line(p1, p2).toShape() e1 = e.copy() e1.rotate(p1, normal, -angle) e2 = e.copy() e2.rotate(p2, normal, 90 - angle) section1 = e1.section(e2) #Part.show(section1,'section1') p3 = section1.Vertexes[0].Point e3 = e.copy() e3.rotate(p1, normal, 90 - angle) e4 = e.copy() e4.rotate(p2, normal, -angle) section2 = e3.section(e4) #Part.show(section2,'section2') p4 = section2.Vertexes[0].Point w = Part.makePolygon([p1, p3, p2, p4, p1]) #Part.show(w, "wire") face = Part.Face(w) wallSolid = face.extrude(normal * -thk) wallsolidlist.append(wallSolid) return wallsolidlist
def show_lines(e1, e2, params, title=""): lines = list() for q1, q2 in params: lines.append(Part.makeLine(e1.valueAt(q1), e2.valueAt(q2))) com = Part.Compound(lines) Part.show(com, title)
def GetFace(self): self.edges.append(Part.makeLine(self.lastPoint, self.firstPoint)) w = Part.Wire(self.edges) return Part.Face(w)
def getpoint(self, event_cb): event = event_cb.getEvent() if event.getState() == SoMouseButtonEvent.DOWN: button = event.getButton() # process only left buttons if button <> 1: return pos = event.getPosition() point = self.view.getPoint(pos[0], pos[1]) point.z = 0 self.view.removeEventCallbackPivy( SoMouseButtonEvent.getClassTypeId(), self.callback) lines = [] p = Part.makeCircle(20, point) lines.append(p) ### lines.append(Part.makeLine(point,self.dialog.ob.zpol)) pp = numpo(point) obj = self.dialog.ob p0 = numpo(obj.P0) # p1=numpo(obj.P1) p2 = numpo(obj.P2) p3 = numpo(obj.P3) p4 = numpo(obj.P4) # p5=numpo(obj.P5) lp = numpo(obj.lpol) rp = numpo(obj.rpol) zp = numpo(obj.zpol) [lp, rp, zp] = self.dialog.polset [p0, p2, p3, p4] = self.dialog.basepoints print "berechnung basepoints" print self.dialog.basepoints # fehlerausgleich # try: # sz1=schnittpunkt(p1,p2,p0,p3) # sz2=schnittpunkt(p4,p5,p0,p3) # # sz=np.array([(sz1[0]+sz2[0])/2,(sz1[1]+sz2[1])/2]) # p5=schnittpunkt(p0,sr,sz,p4) # p1=schnittpunkt(p0,sl,sz,p2) # zp=zp # except: pass #------------------------------------- rval = 0.0 lval = 0.0 zval = 0.0 lrevpos = 0.0 rrevpos = 0.0 mylpv = FreeCAD.Vector() myrpv = FreeCAD.Vector() myzpv = FreeCAD.Vector() if self.mode == 'l': ### lines.append(Part.makeLine(point,self.dialog.ob.lpol)) ls = schnittpunkt(lp, pp, p0, zp) ls2 = schnittpunkt(lp, pp, p2, zp) lines.append(Part.makeLine(vec(ls), vec(pp))) lval = perspos(pp, ls, ls2, lp) lval = round(lval, 4) lval2 = perspos(pp, ls2, ls, lp) lval2 = round(lval2, 4) print("y lval lval2", lval, lval2) lls = ls lls2 = ls2 pos = np.sqrt(len2(ls, pp)) ls = schnittpunkt(zp, pp, p0, lp) ls2 = schnittpunkt(zp, pp, p3, lp) lines.append(Part.makeLine(vec(ls2), vec(pp))) zval = perspos(pp, ls2, ls, zp) zval = round(zval, 4) zval2 = perspos(pp, ls, ls2, zp) zval2 = round(lval2, 4) print("zval zval2", zval, zval2) vls = ls vls2 = ls2 print "lval", lval if self.mode == 'r': ### lines.append(Part.makeLine(point,self.dialog.ob.lpol)) ls = schnittpunkt(rp, pp, p0, zp) ls2 = schnittpunkt(rp, pp, p4, zp) lines.append(Part.makeLine(vec(ls), vec(pp))) rval = perspos(pp, ls, ls2, rp) rval = round(rval, 4) rval2 = perspos(pp, ls2, ls, rp) rval2 = round(rval2, 4) print("y rval ", rval, rval2) lls = ls lls2 = ls2 pos = np.sqrt(len2(ls, pp)) ls = schnittpunkt(zp, pp, p0, rp) ls2 = schnittpunkt(zp, pp, p3, rp) lines.append(Part.makeLine(vec(ls2), vec(pp))) zval = perspos(pp, ls2, ls, zp) zval = round(zval, 4) zval2 = perspos(pp, ls, ls2, zp) zval2 = round(zval2, 4) print("zval zval2", zval, zval2) vls = ls vls2 = ls2 print "rval", rval if self.mode == 'z': ### lines.append(Part.makeLine(point,self.dialog.ob.lpol)) ls = schnittpunkt(lp, pp, p3, rp) ls2 = schnittpunkt(lp, pp, p2, rp) lines.append(Part.makeLine(vec(ls), vec(pp))) lines.append(Part.makeLine(vec(ls2), vec(pp))) lval = perspos(pp, ls, ls2, lp) lval = round(lval, 4) lval2 = perspos(pp, ls2, ls, lp) lval2 = round(lval2, 4) print("y lval lval2", lval, lval2) ls = schnittpunkt(rp, pp, p3, lp) ls2 = schnittpunkt(rp, pp, p4, lp) lines.append(Part.makeLine(vec(ls), vec(pp))) lines.append(Part.makeLine(vec(ls2), vec(pp))) rval = perspos(pp, ls, ls2, rp) rval = round(rval, 4) rval2 = perspos(pp, ls2, ls, rp) rval2 = round(rval2, 4) print("y rval ", rval, rval2) #------------------------- #create real point sx = obj.length sy = obj.width sz = obj.height docs().run() if False: c = Part.makeCompound(lines) Part.show(c) App.ActiveDocument.ActiveObject.Label = "coord lines for " + str( [str(-lval), str(rval), str(zval)]) App.ActiveDocument.ActiveObject.ViewObject.LineColor = (.0, 0.0, 1.0) App.ActiveDocument.ActiveObject.ViewObject.LineWidth = 5 App.ActiveDocument.ActiveObject.ViewObject.PointColor = (1.0, 0.0, 1.0) App.ActiveDocument.ActiveObject.ViewObject.PointSize = 10 ##App.ActiveDocument.ActiveObject.ViewObject.hide() tcl = App.ActiveDocument.ActiveObject #App.ActiveDocument.ActiveObject.Label=str([str(-lval),str(rval),str(zval)]) #vo=App.ActiveDocument.ActiveObject.ViewObject #vo.PointSize=6 #vo.PointColor=(1.0,0.3,0.0) d = docs() yp = "LP" + str(time.time()) mylp = createMP2( yp, docs().m(), FreeCAD.Vector(-lval * sx, rval * sy, zval * sz).add(self.dialog.mpos)) mylp.Label = str([str(-lval), str(rval), str(zval)]) print "-----------------------" print("pos lval ", FreeCAD.Vector(-lval * sx, rval * sy, zval * sz)) print("mpos", (self.dialog.mpos)) mylp.pos = FreeCAD.Vector(-lval * sx, rval * sy, zval * sz).add(self.dialog.mpos) print("position", mylp.pos) mylpi = createMP2(yp, docs().i(), point) # mylpi.Label="MyLPI "+ str([str(-lval+self.dialog.mpos[0]/sx),str(rval+self.dialog.mpos[1]/sy),str(zval+self.dialog.mpos[3]/sz)]) mylpi.Label = str([str(-lval), str(rval), str(zval)]) mylpi.clickPoint = point mylpi.pos = mylp.pos mylpi.ViewObject.PointColor = (.0, 1.0, 1.0) mylpi.ViewObject.PointSize = 10 if self.mode == 'l': lone = makeBase(lval + 1, zval, lp, zp, p2, p0, p3) zone = makeBase(lval, zval + 1, lp, zp, p2, p0, p3) rone = [0, 0] sa = schnittpunkt(lp, pp, zp, p3) sb = schnittpunkt(sa, rp, zp, p4) sc = schnittpunkt(lp, sb, pp, rp) if self.mode == 'r': zone = makeBase(rval, zval + 1, rp, zp, p4, p0, p3) rone = makeBase(rval + 1, zval, rp, zp, p4, p0, p3) lone = [0, 0] sa = schnittpunkt(rp, pp, zp, p3) sb = schnittpunkt(sa, lp, zp, p2) sc = schnittpunkt(rp, sb, pp, lp) if self.mode == 'z': # gheht noch nicht lone = makeBase(lval + 1, rval, lp, zp, p2, p0, p3) rone = makeBase(rval + 1, lval, rp, zp, p4, p0, p3) zone = [0, 0] #lone=[0,0] #rone=[0,0] # sa=schnittpunkt(rp,pp,zp,p3) # sb=schnittpunkt(sa,lp,zp,p2) # sc=schnittpunkt(rp,sb,pp,lp) sc = [0, 0] mylpi.lunit = vec(lone) mylpi.zunit = vec(zone) mylpi.runit = vec(rone) if self.mode == 'l': mylpi.runit = vec(sc) if self.mode == 'r': mylpi.lunit = vec(sc) # if self.mode=='z': # mylpi.zunit=vec(sc) # c=Part.makeCircle(10000,vec(sc)) # Part.show(c) lines = [] if self.mode <> 'z': lines.append(Part.makeLine(point, vec(zone))) lines.append(Part.makeLine(point, vec(sc))) if self.mode == 'l': lines.append(Part.makeLine(point, vec(lone))) #mylpi.runit=sc if self.mode == 'r': lines.append(Part.makeLine(point, vec(rone))) #mylpi.lunit=sc # if self.mode=='z': # lines.append(Part.makeLine(point,vec(zone))) # lines.append(Part.makeLine(point,vec(lone))) # lines.append(Part.makeLine(point,vec(rone))) # lines.append(Part.makeLine(point,vec(zone))) if self.mode <> 'z': comp = Part.makeCompound(lines) Part.show(comp) App.ActiveDocument.ActiveObject.ViewObject.LineColor = (1.0, 0.0, 1.0) App.ActiveDocument.ActiveObject.ViewObject.LineWidth = 10 App.ActiveDocument.ActiveObject.ViewObject.PointColor = (.0, 0.0, 1.0) App.ActiveDocument.ActiveObject.ViewObject.PointSize = 10 ##App.ActiveDocument.ActiveObject.ViewObject.hide() App.ActiveDocument.ActiveObject.Label = "axis cross " + str( [str(-lval), str(rval), str(zval)]) tax = App.ActiveDocument.ActiveObject if False: comp = Part.makeCompound([tax.Shape, tcl.Shape, mylpi.Shape]) Part.show(comp) App.ActiveDocument.ActiveObject.Label = "Helper for " + mylpi.Label App.ActiveDocument.ActiveObject.ViewObject.hide() # mylpi.lp=vec(lp) # mylpi.rp=vec(rp) # mylpi.zp=vec(zp) # mylpi.refLink=docs().i().getObject('P2') # mylpi.refName='P2' # mylpi.Shape=c # vo=App.ActiveDocument.ActiveObject.ViewObject # vo.PointSize=6 # vo.PointColor=(1.0,0.3,0.0) # mylpi.lp=mylpv # mylpi.rp=myrpv # mylpi.zp=myzpv # c=Part.makeLine(mylpv,myzpv) # Part.show(c) # QApplication.restoreOverrideCursor() self.view.removeEventCallbackPivy( SoMouseButtonEvent.getClassTypeId(), self.callback)
def execute(self, obj): if hasattr(obj, "Base") and obj.Base: edges = obj.Base.Shape.Edges obj.n = len(edges) w = Part.Wire(edges) f = Part.Face(w) base_obj = FreeCAD.ActiveDocument.addObject("Part::Part2DObjectPython", "wire") base_obj.Shape = f base_obj.ViewObject.Proxy = 0 projection_face_points, wire_edges = extrude_pieces.create_3D_roof(base_obj, obj.angle, [], obj.angles) edegs_height = obj.edegs_height obj.edegs_height = adjust_list_len(edegs_height, obj.n, 0) edges_angle = obj.angles obj.angles = adjust_list_len(edges_angle, obj.n, int(obj.angle.Value)) faces = [] if len(set(obj.edegs_height)) > 1: bb = w.BoundBox xmin, xmax, ymin, ymax = bb.XMin, bb.XMax, bb.YMin, bb.YMax p1 = (xmin, ymin, 0) p2 = (xmax, ymin, 0) p3 = (xmax, ymax, 0) p4 = (xmin, ymax, 0) e1 = Part.makeLine(p1, p2) e2 = Part.makeLine(p2, p3) e3 = Part.makeLine(p3, p4) e4 = Part.makeLine(p4, p1) wire = Part.Wire([e1, e2, e3, e4]) cut_face = Part.Face(wire) for j, points in enumerate(projection_face_points): n = len(points) points.append(points[0]) edges = [] for i in range(n): e = Part.makeLine(points[i], points[i + 1]) edges.append(e) wire = Part.Wire(edges) face = Part.Face(wire) if len(set(obj.edegs_height)) > 1: h = obj.edegs_height[j] if h > 0: f = cut_face.copy() f.Placement.Base.z = h sh = extrude_pieces.split(face, [f]) for cutted_face in sh: if cutted_face.BoundBox.ZMax > h + 1: face = cutted_face break faces.append(face) obj.face_compound = Part.makeCompound(faces) shell = Part.Shell(faces) obj.Shape = shell.removeSplitter() # obj.Base.ViewObject.Visibility = False # obj.Base.ViewObject.LineColor = (1.00,0.00,0.00) obj.Base.ViewObject.LineWidth = .5 FreeCAD.ActiveDocument.removeObject(base_obj.Name) else: return
def generateNaca(number, n=240, finite_TE=False, half_cosine_spacing=True, scale=1, posX=0, posY=0, posZ=0, rotX=0, rotY=0, rotZ=0, rot=0, useSpline=True, splitSpline=False): coords = generateNacaCoords(number, n, finite_TE, half_cosine_spacing, scale, posX, posY, posZ, rotX, rotY, rotZ) if useSpline: if splitSpline: splineLower = Part.BSplineCurve() splineUpper = Part.BSplineCurve() splineUpper.interpolate(coords[:len(coords) // 2 + 1]) splineLower.interpolate(coords[len(coords) // 2:]) if coords[0] != coords[-1]: wire = Part.Wire([ splineUpper.toShape(), splineLower.toShape(), Part.makeLine(coords[0], coords[-1]) ]) else: wire = Part.Wire( [splineUpper.toShape(), splineLower.toShape()]) else: spline = Part.BSplineCurve() spline.interpolate(coords) if coords[0] != coords[-1]: wire = Part.Wire( [spline.toShape(), Part.makeLine(coords[0], coords[-1])]) else: wire = Part.Wire(spline.toShape()) else: # alternate solution, uses common Part Faces lines = [] first_v = None last_v = None for v in coords: if first_v is None: first_v = v # End of if first_v is None # Line between v and last_v if they're not equal if (last_v != None) and (last_v != v): lines.append(Part.makeLine(last_v, v)) # End of if (last_v != None) and (last_v != v) # The new last_v last_v = v # End of for v in upper # close the wire if needed if last_v != first_v: lines.append(Part.makeLine(last_v, first_v)) wire = Part.Wire(lines) face = Part.Face(wire).scale(scale) #Scale the foil #face.Placement.Rotation.Axis.x=rotX #face.Placement.Rotation.Axis.y=rotY #face.Placement.Rotation.Axis.z=rotZ #face.Placement.Rotation.Angle=rot return face, coords
def get_continuous_base_foundation_shape( base_foundation, points_common_shape, height: float, ): ''' This function gets the one base of foundation object, common shapes with other of base foundations and return a solid shape ''' def get_cut_faces(sh1, sh2): cut = sh1.cut(sh2) if len(cut.Faces) > 1: faces = cut.Faces areas = [f.Area for f in faces] i = areas.index(max(areas)) faces.remove(faces[i]) return faces else: return None shapes = [] cut_shape = [] first_point = tuple(base_foundation.main_wire_first_point) last_point = tuple(base_foundation.main_wire_last_point) comm = points_common_shape.get(first_point, None) if comm is not None: shapes.append(comm) faces = get_cut_faces(base_foundation.Shape, comm) if faces is not None: cut_shape.extend(faces) for e in comm.Edges: intersection = DraftGeomUtils.findIntersection( e, base_foundation.extended_first_edge, ) if intersection: base_foundation.first_edge = \ Part.makeLine( intersection[0], FreeCAD.Vector(*first_point)) break comm = points_common_shape.get(last_point, None) if comm is not None: shapes.append(comm) faces = get_cut_faces(base_foundation.Shape, comm) if faces is not None: cut_shape.extend(faces) for e in comm.Edges: intersection = DraftGeomUtils.findIntersection( e, base_foundation.extended_last_edge, ) if intersection: base_foundation.last_edge = \ Part.makeLine( FreeCAD.Vector(*last_point), intersection[0] ) break shapes.append(base_foundation.Shape) shapes = [shape.extrude(FreeCAD.Vector(0, 0, -height)) for shape in shapes] if len(shapes) > 1: shape = shapes[0].fuse(shapes[1:]) shape = shape.removeSplitter() else: shape = shapes[0] if cut_shape: cut_shape = [ shape.extrude(FreeCAD.Vector(0, 0, -height)) for shape in cut_shape ] shape = shape.cut(cut_shape) return shape