def arma8ptos(fi,recubrN,sepFi,radDobl,pto1,pto2,pto3,pto4,pto5,pto6,pto7,pto8,gap1,gap2): recubrG=recubrN+float(fi)/1000/2.0 v=pto6.sub(pto2) recArmPlano=(v.Length-2*recubrG-int((v.Length-2.0*recubrG)/sepFi)*sepFi)/2.0 v1=GeomUtils.vectorUnitario(pto2,pto1) v2=GeomUtils.vectorUnitario(pto2,pto3) v3=GeomUtils.vectorUnitario(pto3,pto4) v4=GeomUtils.vectorUnitario(pto2,pto6) v5=GeomUtils.vectorUnitario(pto3,pto7) v6=GeomUtils.vectorUnitario(pto6,pto5) v7=GeomUtils.vectorUnitario(pto6,pto7) v8=GeomUtils.vectorUnitario(pto7,pto8) pto1a=pto1.add(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(gap1,v1)) pto2a=pto2.add(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(recubrG,v1)) pto3a=pto3.add(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(recubrG,v3)) pto4a=pto4.add(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v2)).add(GeomUtils.escalarPorVector(gap2,v3)) pto5a=pto5.sub(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(gap1,v6)) pto6a=pto6.sub(GeomUtils.escalarPorVector(recArmPlano,v4)).add(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(recubrG,v6)) pto7a=pto7.sub(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(recubrG,v8)) pto8a=pto8.sub(GeomUtils.escalarPorVector(recArmPlano,v5)).sub(GeomUtils.escalarPorVector(recubrG,v7)).add(GeomUtils.escalarPorVector(gap2,v8)) cara1=Part.Face(Part.makePolygon([pto1a,pto2a,pto6a,pto5a,pto1a])) cara2=Part.Face(Part.makePolygon([pto2a,pto6a,pto7a,pto3a,pto2a])) cara3=Part.Face(Part.makePolygon([pto3a,pto4a,pto8a,pto7a,pto3a])) arma=cara1.fuse(cara2.fuse(cara3)) armadura=arma.makeFillet(radDobl,arma.Edges) return armadura
def makeCylinder(p1,p2,p3,p4): s=Part.makePolygon([p1,p2,p3,p1]) f=Part.makeFilledFace(s.Edges) n=f.Faces[0].normalAt(0,0) # Drehung n2=FreeCAD.Vector(0,0,1) r=FreeCAD.Rotation(n,n2) k1=r.multVec(p1) sp1=sympy.point.Point2D(k1.x,k1.y) z=k1.z sp1 k2=r.multVec(p2) sp2=sympy.point.Point2D(k2.x,k2.y) sp2 k3=r.multVec(p3) sp3=sympy.point.Point2D(k3.x,k3.y) sp3 k4=r.multVec(p4) sp4=sympy.point.Point2D(k4.x,k4.y) sp4 t=sympy.Triangle(sp1,sp2,sp3) rad=t.circumradius.evalf() center=t.circumcenter print rad print center x=center.x.evalf() y=center.y.evalf() circ=Part.makeCircle(rad,FreeCAD.Vector(x,y,z)) Part.show(circ) cb=App.ActiveDocument.ActiveObject h=k4.z-k3.z # und wieder zurueck r2=FreeCAD.Rotation(n2,n) ex=App.ActiveDocument.addObject("Part::Extrusion","Extrude") ex.Base = cb ex.Dir = (0,0,h) ex.Solid = (True) ex.Placement.Rotation=r2 ex.ViewObject.Transparency=80 cb.ViewObject.hide() s2=Part.makePolygon([p1,p2,p3,p4]) Part.show(s2) for p in [p1,p2,p3,p4]: k1=App.ActiveDocument.addObject("Part::Sphere","Sphere") k1.Placement.Base=p k1.Radius=0.5 k1.ViewObject.ShapeColor=(1.0,0.0,0.0) App.activeDocument().recompute()
def execute(self, fp): scale = fp.Radius/1.2247448 a = scale * 0.70710678118 #1/sqrt(2) f = list() for i in (-scale,scale): f.append(Part.Face(Part.makePolygon([(0,scale,a), (0,-scale,a), (i,0,-a),(0,scale,a)]))) f.append(Part.Face(Part.makePolygon([(scale,0,-a), (-scale,0,-a), (0,i,a),(scale,0,-a)]))) fp.Shape = Part.Solid(Part.Shell(f))
def make_blinds_top(self, blinds_height): # Top 1 V1 = self.parts_left['top'].Vertex3.Point V2 = self.parts_left['top'].Vertex11.Point alpha = np.arctan(605./560) move_x = self.thickness/np.sin(alpha) V3 = V2 + Base.Vector(move_x,0,0) V4 = V1 + Base.Vector(move_x,0,0) blind_top1 = Part.makePolygon([V1,V2,V3,V4,V1]) blind_top1 = Part.Face(blind_top1) self.parts_left['blind_top1'] = blind_top1.extrude(Base.Vector(0,0,blinds_height)) # Top 2 V1 = self.parts_left['top'].Vertex16.Point V2 = self.parts_left['top'].Vertex13.Point V4 = V1 + Base.Vector(move_x,0,0) gamma = (np.pi-alpha)/2. move_x = self.thickness/np.tan(gamma) V3 = V2 + Base.Vector(move_x, -self.thickness, 0) blind_top2 = Part.makePolygon([V1,V2,V3,V4,V1]) blind_top2 = Part.Face(blind_top2) self.parts_left['blind_top2'] = blind_top2.extrude(Base.Vector(0,0,blinds_height)) # Top 3 V1 = V2 V4 = V3 V2 = self.parts_left['top'].Vertex12.Point V3 = V2 + Base.Vector(0,-self.thickness,0) blind_top3 = Part.makePolygon([V1,V2,V3,V4,V1]) blind_top3 = Part.Face(blind_top3) self.parts_left['blind_top3'] = blind_top3.extrude(Base.Vector(0,0,blinds_height)) # Top 4 (right work surface) V1 = self.parts_right['top'].Vertex3.Point V2 = self.parts_right['top'].Vertex7.Point V3 = V2 + Base.Vector(-self.thickness, -self.thickness, 0) V4 = V1 + Base.Vector(0,-self.thickness,0) blind_top4 = Part.makePolygon([V1,V2,V3,V4,V1]) blind_top4 = Part.Face(blind_top4) self.parts_right['blind_top4'] = blind_top4.extrude(Base.Vector(0,0,blinds_height)) # Top 5 (right works surface) V1 = V2 V2 = self.parts_right['top'].Vertex5.Point V4 = V3 V3 = V2 + Base.Vector(-self.thickness, 0, 0) blind_top5 = Part.makePolygon([V1,V2,V3,V4,V1]) blind_top5 = Part.Face(blind_top5) self.parts_right['blind_top5'] = blind_top5.extrude(Base.Vector(0,0,blinds_height))
def makePrism(l): print l hp=l[-1] p1=l[0] bl=l[:-1] bl.append(p1) print bl s=Part.makePolygon(bl) f=Part.makeFilledFace(s.Edges) Part.show(f) cb=App.ActiveDocument.ActiveObject cb.Label="Prism Bottom Face" cb.ViewObject.hide() n=f.Faces[0].normalAt(0,0) n2=FreeCAD.Vector(0,0,1) r=FreeCAD.Rotation(n,n2) k1=r.multVec(p1) sp1=sympy.point.Point2D(k1.x,k1.y) z=k1.z sp1 k4=r.multVec(hp) sp4=sympy.point.Point2D(k4.x,k4.y) sp4 bl2=[] for p in bl: k=r.multVec(p) bl2.append(k) s=Part.makePolygon(bl2) f=Part.makeFilledFace(s.Edges) Part.show(f) cb=App.ActiveDocument.ActiveObject cb.Label="Prism Bottom Face Helper" cb.ViewObject.hide() h=k4.z-k1.z # und wieder zurueck r2=FreeCAD.Rotation(n2,n) ex=App.ActiveDocument.addObject("Part::Extrusion","Extrude") ex.Base = cb ex.Dir = (0,0,h) ex.Solid = (True) ex.Placement.Rotation=r2 ex.ViewObject.Transparency=80 ex.Label="Prism" App.activeDocument().recompute()
def execute(self, fp): scale = fp.Radius/1.7320508075689 phy = 1.61803398875 f = list() k = scale for i in (-scale,scale): for j in (-scale,scale): f.append(Part.Face(Part.makePolygon([(i,j,-k), (i/phy,j*phy,0), (i,j,k), (i*phy,0,k/phy), (i*phy,0,-k/phy), (i,j,-k)]))) f.append(Part.Face(Part.makePolygon([(j,-k,i), (j*phy,0,i/phy), (j,k,i), (0,k/phy,i*phy), (0,-k/phy,i*phy), (j,-k,i)]))) f.append(Part.Face(Part.makePolygon([(-k,i,j), (0,i/phy,j*phy), (k,i,j), (k/phy,i*phy,0), (-k/phy,i*phy,0), (-k,i,j)]))) fp.Shape = Part.Solid(Part.Shell(f))
def createGeometry(self,fp): import FreeCAD,Part,math,sys #tangle = -twist #openscad uses degrees clockwise if fp.Base and fp.Angle and fp.Height and \ fp.Base.Shape.isValid(): #wire=fp.Base.Shape.Wires[0].transformGeometry(fp.Base.Placement.toMatrix()) solids=[] for faceb in fp.Base.Shape.Faces: #fp.Base.Shape.Faces[0].check() #faceb=fp.Base.Shape.Faces[0] #faceb=fp.Base.Shape.removeSplitter().Faces[0] faceu=faceb.copy() facetransform=FreeCAD.Matrix() facetransform.rotateZ(math.radians(fp.Angle.Value)) facetransform.move(FreeCAD.Vector(0,0,fp.Height.Value)) faceu.transformShape(facetransform) step = 2 + abs(int(fp.Angle.Value // 90)) #resolution in z direction # print abs(int(fp.Angle.Value // 90)) #resolution in z direction # print step zinc = fp.Height.Value/(step-1.0) angleinc = math.radians(fp.Angle.Value)/(step-1.0) spine = Part.makePolygon([(0,0,i*zinc) \ for i in range(step)]) auxspine = Part.makePolygon([(math.cos(i*angleinc),\ math.sin(i*angleinc),i*fp.Height.Value/(step-1)) \ for i in range(step)]) faces=[faceb,faceu] for wire in faceb.Wires: pipeshell=Part.BRepOffsetAPI.MakePipeShell(spine) pipeshell.setSpineSupport(spine) pipeshell.add(wire) # Was before function change # pipeshell.setAuxiliarySpine(auxspine,True,False) if sys.version_info.major < 3: pipeshell.setAuxiliarySpine(auxspine,True,long(0)) else: pipeshell.setAuxiliarySpine(auxspine,True,0) print(pipeshell.getStatus()) assert(pipeshell.isReady()) #fp.Shape=pipeshell.makeSolid() pipeshell.build() faces.extend(pipeshell.shape().Faces) try: fullshell=Part.Shell(faces) solid=Part.Solid(fullshell) if solid.Volume < 0: solid.reverse() assert(solid.Volume >= 0) solids.append(solid) except Part.OCCError: solids.append(Part.Compound(faces)) fp.Shape=Part.Compound(solids)
def shapeGrid(self): poly = [] #polyV = [] for row in self.result: poly.append(Part.makePolygon(row)) for i in range(len(self.result[0])): row = [] for j in range(len(self.result)): row.append(self.result[j][i]) poly.append(Part.makePolygon(row)) c = Part.Compound(poly) return(c)
def execute(self,obj): pl = obj.Placement length = obj.Length.Value width = obj.Width.Value height = obj.Height.Value chamfer = obj.Chamfer.Value dentlength = obj.DentLength.Value dentheight = obj.DentHeight.Value if (length == 0) or (width == 0) or (height == 0): return if (chamfer >= width/2) or (chamfer >= height/2): return import Part p = [] if chamfer > 0: p.append(Vector(0,chamfer,0)) p.append(Vector(0,width-chamfer,0)) p.append(Vector(0,width,chamfer)) p.append(Vector(0,width,height-chamfer)) p.append(Vector(0,width-chamfer,height)) p.append(Vector(0,chamfer,height)) p.append(Vector(0,0,height-chamfer)) p.append(Vector(0,0,chamfer)) else: p.append(Vector(0,0,0)) p.append(Vector(0,width,0)) p.append(Vector(0,width,height)) p.append(Vector(0,0,height)) p.append(p[0]) p = Part.makePolygon(p) f = Part.Face(p) shape = f.extrude(Vector(length,0,0)) if (dentlength > 0) and (dentheight > 0): p = [] p.append(Vector(0,0,0)) p.append(Vector(dentlength,0,0)) p.append(Vector(dentlength,width,0)) p.append(Vector(0,width,0)) p.append(p[0]) p = Part.makePolygon(p) f = Part.Face(p) d1 = f.extrude(Vector(0,0,dentheight)) d2 = d1.copy() d2.translate(Vector(length-dentlength,0,0)) shape = shape.cut(d1) shape = shape.cut(d2) shape = self.processSubShapes(obj,shape,pl) self.applyShape(obj,shape,pl)
def execute(self, fp): scale = fp.Radius/1.90211303259 phy = 1.61803398875 f = list() for i in (-scale,scale): for j in (-scale,scale): k = scale f.append(Part.Face(Part.makePolygon([(-k,0,i*phy), (k,0,i*phy), (0,j*phy,i*1), (-k,0,i*phy)]))) f.append(Part.Face(Part.makePolygon([(0,i*phy,-k), (0,i*phy,k), (j*phy,i*1,0), (0,i*phy,-k)]))) f.append(Part.Face(Part.makePolygon([(i*phy,-k,0), (i*phy,k,0), (i*1,0,j*phy), (i*phy,-k,0)]))) for k in (-scale,scale): f.append(Part.Face(Part.makePolygon([(i*1,0,k*phy), (0,j*phy,k*1), (i*phy,j*1,0), (i*1,0,k*phy)]))) fp.Shape = Part.Solid(Part.Shell(f))
def bague_propu(): """most complicated bague""" # TODO # retreive configuration side = bague_data["side"] thick = bague_data["thick"] length = bague_data["len"] # make bague shape shape = [] # first branch shape.append(Vector(side, -side / 2, 0)) shape.append(Vector(length, -side / 2, 0)) shape.append(Vector(length, side / 2, 0)) shape.append(Vector(side, side / 2, 0)) wire0 = Part.makePolygon(shape) # 2nd and 3rd branches wire1 = wire0.copy() wire1.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 120) wire2 = wire0.copy() wire2.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 240) # union of all branches wire = wire0.fuse(wire1) wire = wire.fuse(wire2) vertexes = [] for edg in wire.Edges: vertexes += edg.Vertexes points = [] for vrt in vertexes: points.append(vrt.Point) points.append(points[0]) # close the wire wire = Part.makePolygon(points) face = Part.Face(wire) # make the volume bagu = face.extrude(Vector(0, 0, thick)) # ring part ring = Part.makeCylinder(bague_propu_data["ring radius"], thick) bagu = bagu.fuse(ring) # dig the hole hole = Part.makeCylinder(bague_propu_data["hole radius"], thick) bagu = bagu.cut(hole) return bagu
def __init__(self, doc, profil, name='bague'): self.data = { 'thick': 10., # mm 'hole radius': 4., # mm 'side': profil['side'] - 2 * profil['thick'], # mm 'len': 60.5, # mm } side = self.data['side'] thick = self.data['thick'] length = self.data['len'] # make bague shape shape = [] # first branch shape.append(Vector(side, -side / 2, 0)) shape.append(Vector(length, -side / 2, 0)) shape.append(Vector(length, side / 2, 0)) shape.append(Vector(side, side / 2, 0)) wire0 = Part.makePolygon(shape) # 2nd and 3rd branches wire1 = wire0.copy() wire1.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 120) wire2 = wire0.copy() wire2.rotate(Vector(0, 0, 0), Vector(0, 0, 1), 240) # union of all branches wire = wire0.fuse(wire1) wire = wire.fuse(wire2) vertexes = [] for edg in wire.Edges: vertexes += edg.Vertexes points = [] for vrt in vertexes: points.append(vrt.Point) points.append(points[0]) # close the wire wire = Part.makePolygon(points) face = Part.Face(wire) # make the volume bague = face.extrude(Vector(0, 0, thick)) # dig the hole hole = Part.makeCylinder(self.data['hole radius'], thick) bague = bague.cut(hole) MecaComponent.__init__(self, doc, bague, name, (0.95, 1., 1.))
def gen_haus0(le,wi,hiall,hi,midx,wx,midy,wy): # le=30 # wi=20 he=hiall he3=hi inle=8 inwi=2 if wx==0: wx=0.0001 if wy==0: wy=0.0001 if midx<0.5: bix=le*midx else: bix=le*(1-midx) if midy<0.5: biy=wi*midy else: biy=wi*(1-midy) list1=viereck(le,wi,0) list2=viereck(le,wi,he) # list3=viereck(le,wi,he3,inle,inwi) list3=viereck(le,wi,he3, le*midx-bix*wx,le-(le*midx+bix*wx), wi*midy-biy*wy,wi-(wi*midy+biy*wy), ) poly1 = Part.makePolygon( list1) poly3 = Part.makePolygon( list3) face1 = Part.Face(poly1) face3 = Part.Face(poly3) faceListe=[face1,face3] for i in range(len(list1)-1): liste3=[list1[i],list1[i+1],list2[i+1],list2[i],list1[i]] poly=Part.makePolygon(liste3) face = Part.Face(poly) faceListe.append(face) for i in range(len(list2)-1): liste3=[list2[i],list2[i+1],list3[i+1],list3[i],list2[i]] poly=Part.makePolygon(liste3) face = Part.Face(poly) faceListe.append(face) myShell = Part.makeShell(faceListe) mySolid = Part.makeSolid(myShell) return mySolid
def genDeckAndWalls(self): '''Returns a compound with the deck and walls of the structure''' #Deck ptDeckBL=self.kpITL.add(Base.Vector(-self.wallTh,0,-self.deckSlope*self.wallTh*self.wallTh)) ptDeckBR=self.kpITR.add(Base.Vector(self.wallTh,0,self.deckSlope*self.wallTh*self.wallTh)) linDeck=Part.makePolygon([self.kpITL,ptDeckBL,self.kpETL,self.kpETR,ptDeckBR,self.kpITR,self.kpITL]) deck=Part.Face(linDeck) #Walls linLeftWall=Part.makePolygon([self.kpIBL,self.kpEBL,ptDeckBL,self.kpITL,self.kpIBL]) leftWall=Part.Face(linLeftWall) linRightWall=Part.makePolygon([self.kpEBR,self.kpIBR,self.kpITR,ptDeckBR,self.kpEBR]) rightWall=Part.Face(linRightWall) retComp=Part.makeCompound([deck,leftWall,rightWall]) return self.placeAndExtrudeShape(retComp)
def execute(self, fp): edges = fp.Edges if edges < 3: edges = 3 length = fp.Length radius = fp.Radius height = fp.Height m=Base.Matrix() m.rotateZ(math.radians(360.0/edges)) # create polygon polygon = [] v=Base.Vector(length,0,0) for i in range(edges): polygon.append(v) v = m.multiply(v) polygon.append(v) wire = Part.makePolygon(polygon) # create circle circ=Part.makeCircle(radius) # Create the face with the polygon as outline and the circle as hole face=Part.Face([wire,Part.Wire(circ)]) # Extrude in z to create the final solid extrude=face.extrude(Base.Vector(0,0,height)) fp.Shape = extrude
def execute(self, obj): debug("* Interpolate : execute *") pts = self.getPoints( obj) if obj.Polygonal: if obj.Periodic: pts.append(pts[0]) poly = Part.makePolygon(pts) if obj.WireOutput: obj.Shape = poly return() else: bs = poly.approximate(1e-8,obj.Tolerance,999,1) else: bs = Part.BSplineCurve() bs.interpolate(Points=pts, PeriodicFlag=obj.Periodic, Tolerance=obj.Tolerance, Parameters=obj.Parameters) if not (len(obj.Tangents) == len(pts) and len(obj.TangentFlags) == len(pts)) or obj.DetectAligned: if obj.Periodic: obj.Tangents = [bs.tangent(p)[0] for p in obj.Parameters[0:-1]] else: obj.Tangents = [bs.tangent(p)[0] for p in obj.Parameters] obj.TangentFlags = [True]*len(pts) if obj.CustomTangents or obj.DetectAligned: if obj.DetectAligned: self.detect_aligned_pts(obj, pts) bs.interpolate(Points=pts, PeriodicFlag=obj.Periodic, Tolerance=obj.Tolerance, Parameters=obj.Parameters, Tangents=obj.Tangents, TangentFlags=obj.TangentFlags) #, Scale=False) obj.Shape = bs.toShape()
def execute(self, obj): pl = obj.Placement p1 = Vector(-obj.Width.Value / 2, -obj.Height.Value / 2, 0) p2 = Vector(obj.Width.Value / 2, -obj.Height.Value / 2, 0) p3 = Vector(obj.Width.Value / 2, (-obj.Height.Value / 2) + obj.FlangeThickness.Value, 0) p4 = Vector(obj.WebThickness.Value / 2, (-obj.Height.Value / 2) + obj.FlangeThickness.Value, 0) p5 = Vector(obj.WebThickness.Value / 2, obj.Height.Value / 2 - obj.FlangeThickness.Value, 0) p6 = Vector(obj.Width.Value / 2, obj.Height.Value / 2 - obj.FlangeThickness.Value, 0) p7 = Vector(obj.Width.Value / 2, obj.Height.Value / 2, 0) p8 = Vector(-obj.Width.Value / 2, obj.Height.Value / 2, 0) p9 = Vector(-obj.Width.Value / 2, obj.Height.Value / 2 - obj.FlangeThickness.Value, 0) p10 = Vector(-obj.WebThickness.Value / 2, obj.Height.Value / 2 - obj.FlangeThickness.Value, 0) p11 = Vector(-obj.WebThickness.Value / 2, (-obj.Height.Value / 2) + obj.FlangeThickness.Value, 0) p12 = Vector(-obj.Width.Value / 2, (-obj.Height.Value / 2) + obj.FlangeThickness.Value, 0) p = Part.makePolygon( [p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p1]) p = Part.Face(p) p.reverse() obj.Shape = p obj.Placement = pl
def projectFace(self,face): "projects a single face on the WP" #print "VRM: projectFace start: ",len(face[0].Vertexes)," verts, ",len(face[0].Edges)," edges" wires = [] if not face[0].Wires: if DEBUG: print "Error: Unable to project face on the WP" return None norm = face[0].normalAt(0,0) for w in face[0].Wires: verts = [] edges = DraftGeomUtils.sortEdges(w.Edges) #print len(edges)," edges after sorting" for e in edges: v = e.Vertexes[0].Point #print v v = self.wp.getLocalCoords(v) verts.append(v) verts.append(verts[0]) if len(verts) > 2: #print "new wire with ",len(verts) wires.append(Part.makePolygon(verts)) try: sh = ArchCommands.makeFace(wires) except: if DEBUG: print "Error: Unable to project face on the WP" return None else: # restoring flipped normals vnorm = self.wp.getLocalCoords(norm) if vnorm.getAngle(sh.normalAt(0,0)) > 1: sh.reverse() #print "VRM: projectFace end: ",len(sh.Vertexes)," verts" return [sh]+face[1:]
def p_polyhedron_action(p) : '''polyhedron_action : polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA faces EQ OSQUARE path_set ESQUARE COMMA keywordargument_list RPAREN SEMICOL | polyhedron LPAREN points EQ OSQUARE points_list_3d ESQUARE COMMA triangles EQ OSQUARE points_list_3d ESQUARE COMMA keywordargument_list RPAREN SEMICOL''' if printverbose: print("Polyhedron Points") v = [] for i in p[6] : if printverbose: print(i) v.append(FreeCAD.Vector(float(i[0]),float(i[1]),float(i[2]))) if printverbose: print(v) print ("Polyhedron "+p[9]) print (p[12]) faces_list = [] mypolyhed = doc.addObject('Part::Feature',p[1]) for i in p[12] : if printverbose: print(i) v2 = FreeCAD.Vector pp =[v2(v[k]) for k in i] # Add first point to end of list to close polygon pp.append(pp[0]) print(pp) w = Part.makePolygon(pp) f = Part.Face(w) #f = make_face(v[int(i[0])],v[int(i[1])],v[int(i[2])]) faces_list.append(f) shell=Part.makeShell(faces_list) solid=Part.Solid(shell).removeSplitter() if solid.Volume < 0: solid.reverse() mypolyhed.Shape=solid p[0] = [mypolyhed]
def Activated(self): proceed = False obj = Gui.Selection.getSelection() if len(obj) > 0: obj = obj[0] if check_glider(obj): proceed = True if proceed: import openglider.plots import Part unwrapper = openglider.plots.PlotMaker(obj.GliderInstance) unwrapper.unwrap() areas = unwrapper.get_all_parts().group_materials() for material_name, draw_area in areas.items(): pattern_doc = FreeCAD.newDocument("plots_{}".format(material_name)) draw_area.rasterize() draw_area.scale(1000) for i, part in enumerate(draw_area.parts): grp = pattern_doc.addObject("App::DocumentObjectGroup", part.name) layer_dict = part.layers for layer in layer_dict: for j, line in enumerate(layer_dict[layer]): obj = FreeCAD.ActiveDocument.addObject("Part::Feature", layer + str(j)) obj.Shape = Part.makePolygon(map(App.Vector, line)) grp.addObject(obj) pattern_doc.recompute()
def makeMesh(doc,activeobject,verts,facets,material,colortable): mfacets = [] if facets: for facet in facets: if len(facet) > 3: vecs = [FreeCAD.Vector(*verts[i-1]) for i in facet] vecs.append(vecs[0]) pol = Part.makePolygon(vecs) try: face = Part.Face(pol) except Part.OCCError: print("Skipping non-planar polygon:",vecs) else: tris = face.tessellate(1) for tri in tris[1]: mfacets.append([tris[0][i] for i in tri]) else: mfacets.append([verts[i-1] for i in facet]) if mfacets: mobj = doc.addObject("Mesh::Feature",activeobject) mobj.Mesh = Mesh.Mesh(mfacets) if material and FreeCAD.GuiUp: if material in colortable: mobj.ViewObject.ShapeColor = colortable[material][0] if colortable[material][1] != None: mobj.ViewObject.Transparency = colortable[material][1]
def execute(self,obj): pl = obj.Placement p1 = Vector(-obj.Width.Value/2,-obj.Height.Value/2,0) p2 = Vector(obj.Width.Value/2,-obj.Height.Value/2,0) p3 = Vector(obj.Width.Value/2,obj.Height.Value/2,0) p4 = Vector(-obj.Width.Value/2,obj.Height.Value/2,0) q1 = Vector(-obj.Width.Value/2+obj.Thickness.Value,-obj.Height.Value/2+obj.Thickness.Value,0) q2 = Vector(obj.Width.Value/2-obj.Thickness.Value,-obj.Height.Value/2+obj.Thickness.Value,0) q3 = Vector(obj.Width.Value/2-obj.Thickness.Value,obj.Height.Value/2-obj.Thickness.Value,0) q4 = Vector(-obj.Width.Value/2+obj.Thickness.Value,obj.Height.Value/2-obj.Thickness.Value,0) p = Part.makePolygon([p1,p2,p3,p4,p1]) q = Part.makePolygon([q1,q2,q3,q4,q1]) r = Part.Face([p,q]) r.reverse() obj.Shape = r obj.Placement = pl
def make_extrusion(self, name, points, invert_order): print 'make_extrusion', name, invert_order wires = [] for section in points: pts = [] if len(section) < 3: print "warning: cross section in make_extrusion() < 3 points" print "length:", len(section) continue if not invert_order: for pt in section: # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) pt = section[0] pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) else: for pt in section: # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) pt = section[0] pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) #pt = section[0] #Base.Vector(pt[0], pt[1], pt[2]) #for pt in reversed(section): # print "%.2f %.2f %.2f" % (pt[0], pt[1], pt[2]) #pts.append( Base.Vector(pt[0], pt[1], pt[2]) ) wire = Part.makePolygon(pts) wires.append(wire) loft = Part.makeLoft(wires, False) return loft
def execute(self, part): data = iso_4014_1979_partial_hex_screw["sizes"][part.size] # the calculations are based on the ACII art picture above, # with the points starting from the far right point, # and ending with the same point to close the polygon y_distance = 0.5 * data["s_max"] angle = math.pi / 3 head_radius = y_distance / math.sin(angle) x_distance = math.cos(angle) * head_radius points = [ Vector(head_radius, 0, 0), Vector(x_distance, y_distance, 0), Vector(-x_distance, y_distance, 0), Vector(-head_radius, 0, 0), Vector(-x_distance, -y_distance, 0), Vector(x_distance, -y_distance, 0), Vector(head_radius, 0, 0), ] # create a polygon and transform it to a face too: hexagon = Part.Face(Part.makePolygon(points)) # just an integer won't work here, must use units: k = data["k_nom"] * Units.MilliMetre head = hexagon.extrude(Vector(0, 0, k)) shaft = Part.makeCylinder( 0.5 * data["ds_max"], part.length + k, Vector(0, 0, 0), Vector(0, 0, 1) ) part.Shape = head.fuse(shaft)
def make_object(self, poly, thickness, pos, nudge): #print pos halfw = thickness * 0.5 norm = Base.Vector(0,thickness,0) object = None for i in range(len(poly)): pts = [] for p in poly.contour(i): pts.append( Base.Vector(p[0]+pos[1], -halfw-nudge+pos[0], p[1]+pos[2]) ) # close the loop pts.append( pts[0] ) #print 'pts:', pts seg = Part.makePolygon( pts ) face = Part.Face(seg) shape = face.extrude(norm) if poly.isHole(i): #print 'hole:', poly.contour(i) if object: object = object.cut(shape) else: #print 'outline:', poly.contour(i) if object: object = object.fuse(shape) else: object = shape return object
def createGeometry(self,fp): if all((fp.Radius1,fp.Radius2,fp.FacesNumber,fp.Height)): import math import FreeCAD,Part #from draftlibs import fcgeo plm = fp.Placement wires=[] faces=[] for ir,r in enumerate((fp.Radius1,fp.Radius2)): angle = (math.pi*2)/fp.FacesNumber pts = [FreeCAD.Vector(r.Value,0,ir*fp.Height.Value)] for i in range(fp.FacesNumber-1): ang = (i+1)*angle pts.append(FreeCAD.Vector(r.Value*math.cos(ang),\ r.Value*math.sin(ang),ir*fp.Height.Value)) pts.append(pts[0]) shape = Part.makePolygon(pts) face = Part.Face(shape) if ir==1: #top face face.reverse() wires.append(shape) faces.append(face) #shellperi=Part.makeRuledSurface(*wires) shellperi=Part.makeLoft(wires) shell=Part.Shell(shellperi.Faces+faces) fp.Shape = Part.Solid(shell) fp.Placement = plm
def __init__(self, doc, name='fin'): # ailerons self.data = { 'len': 365., # mm 'e': 222., # mm 'p': 55., # mm 'm': 255., # mm 'thick': 3., # mm } # use profile shape to make suppressed parts of the skin shape = [] # 1st part shape.append(Vector(0, 0, 0)) shape.append(Vector(0, 0, self.data['len'])) shape.append(Vector(self.data['e'], 0, self.data['len'] - self.data['p'])) shape.append(Vector(self.data['e'], 0, self.data['len'] - self.data['p'] - self.data['m'])) shape.append(Vector(0, 0, 0)) wire = Part.makePolygon(shape) # center it wire.translate(Vector(0, - self.data['thick'] / 2, 0)) face = Part.Face(wire) # make the volume comp = face.extrude(Vector(0, self.data['thick'], 0)) # center it #comp.translate(Vector(0, - self.data['thick'] / 2, 0)) MecaComponent.__init__(self, doc, comp, name, (0.95, 1., 1.))
def makeSquareTool(s, m): # makes a cylinder with an inner square hole, used as cutting tool # create square face msq = Base.Matrix() msq.rotateZ(math.radians(90.0)) polygon = [] vsq = Base.Vector(s / 2.0, s / 2.0, -m * 0.1) for i in range(4): polygon.append(vsq) vsq = msq.multiply(vsq) polygon.append(vsq) square = Part.makePolygon(polygon) square = Part.Face(square) # create circle face circ = Part.makeCircle(s * 3.0, Base.Vector(0.0, 0.0, -m * 0.1)) circ = Part.Face(Part.Wire(circ)) # Create the face with the circle as outline and the square as hole face=circ.cut(square) # Extrude in z to create the final cutting tool exSquare = face.extrude(Base.Vector(0.0, 0.0, m * 1.2)) # Part.show(exHex) return exSquare
def execute(self,obj): pl = obj.Placement length = obj.Length.Value width = obj.Width.Value height = obj.Height.Value base = obj.BeamBase.Value slant = obj.Chamfer.Value if (length == 0) or (width == 0) or (height == 0): return if (slant*2 >= width) or (base*2+slant*2 >= height): return import Part p = [] p.append(Vector(0,0,0)) p.append(Vector(0,0,base)) p.append(Vector(0,slant,base+slant)) p.append(Vector(0,slant,height-(base+slant))) p.append(Vector(0,0,height-base)) p.append(Vector(0,0,height)) p.append(Vector(0,width,height)) p.append(Vector(0,width,height-base)) p.append(Vector(0,width-slant,height-(base+slant))) p.append(Vector(0,width-slant,base+slant)) p.append(Vector(0,width,base)) p.append(Vector(0,width,0)) p.append(p[0]) p = Part.makePolygon(p) f = Part.Face(p) shape = f.extrude(Vector(length,0,0)) shape = self.processSubShapes(obj,shape,pl) self.applyShape(obj,shape,pl)
def getShapeFromMesh(mesh): import Part, MeshPart if mesh.isSolid() and (mesh.countComponents() == 1): # use the best method faces = [] for f in mesh.Facets: p=f.Points+[f.Points[0]] pts = [] for pp in p: pts.append(FreeCAD.Vector(pp[0],pp[1],pp[2])) faces.append(Part.Face(Part.makePolygon(pts))) shell = Part.makeShell(faces) solid = Part.Solid(shell) solid = solid.removeSplitter() return solid faces = [] segments = mesh.getPlanarSegments(0.001) # use rather strict tolerance here for i in segments: if len(i) > 0: wires = MeshPart.wireFromSegment(mesh, i) if wires: faces.append(makeFace(wires)) try: se = Part.makeShell(faces) except: return None else: try: solid = Part.Solid(se) except: return se else: return solid
} def getnameofpolygon(points): avgpt = sum(points, Vector()) * (1.0 / len(points)) closestname = min(((avgpt - Vector(p[0] * 1000, p[1] * 1000)).Length, name) for name, p in patchnamelookups.items())[1] return closestname clw = getemptyobject(doc, "App::DocumentObjectGroup", "UVPolygons") # find the sets of nodes from the coincident constraints gcptsets, gcptnmap = extractcoincidentnodes(cutlinesketch) gcptorders = [ coincidentnodetanges(cutlinesketch, gcptset) for gcptset in gcptsets ] # derive the sequences of (edge, startend) for each contour seqs = extractsequences(gcptorders, gcptnmap) for n, seq in enumerate(seqs): points = sequencetopoints(cutlinesketch, seq, legsampleleng=3.0) if not orientationclockwise(points): closestname = getnameofpolygon(points) ws = createobjectingroup(doc, clw, "Part::Feature", "w%s" % (closestname)) ws.Shape = Part.makePolygon(points + [points[0]]) lam = n / len(seqs) ws.ViewObject.PointColor = (0.5 + lam * 0.5, 1.0 - lam * 0.5, 0.8)
def createStructuralMember(ifcfile, ifcbin, obj): """Creates a structural member if possible. Returns the member""" global structural_nodes, structural_curves structuralMember = None import Draft import Part import ifcopenshell import FreeCAD uid = ifcopenshell.guid.new ownerHistory = ifcfile.by_type("IfcOwnerHistory")[0] structContext = getStructuralContext(ifcfile) # find edges to convert into structural members edges = None if Draft.getType(obj) not in ["Structure"]: # for non structural elements if ALLOW_LINEAR_OBJECTS and obj.isDerivedFrom("Part::Feature"): # for objects created with Part workbench if obj.Shape.Faces: # for objects with faces return None elif not obj.Shape.Edges: # for objects without edges return None else: edges = obj.Shape.Edges else: # for structural elements with nodes nodes = [obj.Placement.multVec(n) for n in obj.Nodes] if len(nodes) > 2: # when there are more then 2 nodes (i.e. for slabs) append closing node to produce closing edge nodes.append(nodes[0]) wire = Part.makePolygon(nodes) edges = wire.Edges if not edges: return None # OBJECT CLASSIFICATION by edge number # Linear elements for edge_number = 1, Surface elements for edge_number > 1 # we don't care about curved edges just now... if len(edges) == 1: # LINEAR OBJECTS: beams, columns # ATM limitations: # - no profile properties are taken into account # - no materials properties are takein into account # - # create geometry verts = [None for _ in range(len(edges)+1)] verts[0] = tuple(edges[0].Vertexes[ 0].Point.multiply(scaling)) verts[1] = tuple(edges[0].Vertexes[-1].Point.multiply(scaling)) cartPnt1 = ifcfile.createIfcCartesianPoint(verts[0]) cartPnt2 = ifcfile.createIfcCartesianPoint(verts[1]) vertPnt1 = ifcfile.createIfcVertexPoint(cartPnt1) vertPnt2 = ifcfile.createIfcVertexPoint(cartPnt2) newEdge = ifcfile.createIfcEdge(vertPnt1, vertPnt2) topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, "Analysis", "Edge", (newEdge,)) prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None, (topologyRep,)) # set local coordinate system localPlacement = ifcbin.createIfcLocalPlacement() localZAxis = ifcbin.createIfcDirection((0, 0, 1)) # create structural member if ifcfile.wrapped_data.schema_name() == "IFC2X3": structuralMember = ifcfile.createIfcStructuralCurveMember( uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER") else: localZAxis = ifcbin.createIfcDirection((0, 0, 1)) structuralMember = ifcfile.createIfcStructuralCurveMember( uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "RIGID_JOINED_MEMBER", localZAxis) elif len(edges) > 1: # SURFACE OBJECTS: slabs (horizontal, vertical, inclined) # ATM limitations: # - mo material properties are taken into account # - walls don't work because they miss a node system # - # creates geometry verts = [None for _ in range(len(edges))] for i, edge in enumerate(edges): verts[i] = tuple(edge.Vertexes[0].Point.multiply(scaling)) cartPnt = ifcfile.createIfcCartesianPoint(verts[i]) vertPnt = ifcfile.createIfcVertexPoint(cartPnt) orientedEdges = [None for _ in range(len(edges))] for i, vert in enumerate(verts): v2Index = (i + 1) if i < len(verts) - 1 else 0 cartPnt1 = ifcfile.createIfcCartesianPoint(vert) cartPnt2 = ifcfile.createIfcCartesianPoint(verts[v2Index]) vertPnt1 = ifcfile.createIfcVertexPoint(cartPnt1) vertPnt2 = ifcfile.createIfcVertexPoint(cartPnt2) edge = ifcfile.createIfcEdge(vertPnt1, vertPnt2) orientedEdges[i] = ifcfile.createIfcOrientedEdge(None, None, edge, True) edgeLoop = ifcfile.createIfcEdgeLoop(tuple(orientedEdges)) # sets local coordinate system localPlacement = ifcbin.createIfcLocalPlacement() # sets face origin to the first vertex point of the planar surface origin = cartPnt2 # find crossVect that is perpendicular to the planar surface vect0 = FreeCAD.Vector(verts[0]) vect1 = FreeCAD.Vector(verts[1]) vectn = FreeCAD.Vector(verts[-1]) vect01 = vect1.sub(vect0) vect0n = vectn.sub(vect0) crossVect = vect01.cross(vect0n) # normalize crossVect normVect = crossVect.normalize() xAxis = ifcfile.createIfcDirection(tuple([vect01.x, vect01.y, vect01.z])) zAxis = ifcfile.createIfcDirection(tuple([normVect.x, normVect.y, normVect.z])) localAxes = ifcfile.createIfcAxis2Placement3D(origin, zAxis, xAxis) plane = ifcfile.createIfcPlane(localAxes) faceBound = ifcfile.createIfcFaceBound(edgeLoop, True) face = ifcfile.createIfcFaceSurface((faceBound,), plane, True) topologyRep = ifcfile.createIfcTopologyRepresentation(structContext, "Analysis", "Face", (face,)) prodDefShape = ifcfile.createIfcProductDefinitionShape(None, None, (topologyRep,)) # sets surface thickness # ATM limitations # - for verical slabs (walls) or inclined slabs (ramps) the thickness is taken from the Height property thickness = float(obj.Height)*scaling # creates structural member structuralMember = ifcfile.createIfcStructuralSurfaceMember( uid(), ownerHistory, obj.Label, None, None, localPlacement, prodDefShape, "SHELL", thickness) # check for existing connection nodes for vert in verts: vertCoord = tuple(vert) if vertCoord in structural_nodes: if structural_nodes[vertCoord]: # there is already another member using this point structPntConn = structural_nodes[vertCoord] else: # there is another member with same point, create a new node connection structPntConn = createStructuralNode(ifcfile, ifcbin, vert) structural_nodes[vertCoord] = structPntConn ifcfile.createIfcRelConnectsStructuralMember( uid(), ownerHistory, None, None, structuralMember, structPntConn, None, None, None, None) else: # just add the point, no other member using it yet structural_nodes[vertCoord] = None # check for existing connection curves for edge in edges: verts12 = tuple([edge.Vertexes[ 0].Point.x, edge.Vertexes[ 0].Point.y, edge.Vertexes[ 0].Point.z, edge.Vertexes[-1].Point.x, edge.Vertexes[-1].Point.y, edge.Vertexes[-1].Point.z]) verts21 = tuple([edge.Vertexes[-1].Point.x, edge.Vertexes[-1].Point.y, edge.Vertexes[-1].Point.z, edge.Vertexes[ 0].Point.x, edge.Vertexes[ 0].Point.y, edge.Vertexes[ 0].Point.z]) verts12_in_curves = verts12 in structural_curves verts21_in_curves = verts21 in structural_curves if verts21_in_curves: verts = verts21 else: verts = verts12 if (verts12_in_curves or verts21_in_curves): if structural_curves[verts]: # there is already another member using this curve strucCrvConn = structural_curves[verts] else: # there is another member with same edge, create a new curve connection strucCrvConn = createStructuralCurve(ifcfile, ifcbin, edge) structural_curves[verts] = strucCrvConn ifcfile.createIfcRelConnectsStructuralMember( uid(), None, None, None, structuralMember, strucCrvConn, None, None, None, None) else: # just add the curve, no other member using it yet structural_curves[verts] = None return structuralMember
def alignTo3Points(self, p1, p2, p3, offset=0): import Part w = Part.makePolygon([p1, p2, p3, p1]) f = Part.Face(w) return self.alignToFace(f, offset)
def make_face(v1, v2, v3): wire = Part.makePolygon([v1, v2, v3, v1]) face = Part.Face(wire) return face
def combineCurves(): #get selected horizontal and vertical geometry (h, v) = Gui.Selection.getSelection() #get list of geometry edges horiz_edge = h.Shape.Edges[0] vert_edge = v.Shape.Edges[0] #get the horizontal curve's first and last parameters fip = horiz_edge.FirstParameter lap = horiz_edge.LastParameter #get the length of the curve and set the step interval horiz_len = horiz_edge.Length step = 3000 #initialize point lists #ptsh is ... ? pts = [] ptsh = [ FreeCAD.Vector(), FreeCAD.Vector(horiz_len, 0, 0), FreeCAD.Vector() ] ptsn = [] ptsc = [] #divide the length by the number of steps, truncating the integer #then add one for the concluding point for the steps, #plus a point for the end of the edge, if the step point falls short point_count = int(horiz_len / float(step)) + 1 if ((point_count - 1) * step) < horiz_len: point_count += 1 #vertial curve as equidistant points at the step interval... vt_seg_pts = vert_edge.discretize(Number=point_count, First=0.00, Last=horiz_len) end_point = vt_seg_pts[point_count - 1] print('Start point: ', vt_seg_pts[0]) print('End point: ', vt_seg_pts[point_count - 1]) #c=FreeCAD.getDocument("stationing").getObject("MyBezierSketch") #pts=c.Shape.Edge1.discretize(20) import numpy as np #this pairs coordinates of like axes in three tuples (x_coords,y_coords,z) vt_pt_seg_axes = np.array(vt_seg_pts).swapaxes(0, 1) #save the x_coords/y_coords coordinate pairs in separate variables x_coords = list(range(0, int(horiz_len) + 1, step)) #if we added two to the point count, then the step interval #won't quite make it to the end... add the length as the last point if len(x_coords) < point_count: x_coords.append(horiz_len) last_pt = len(x_coords) print(x_coords[last_pt - 10:]) y_coords = vt_pt_seg_axes[1] #append the final elevation - see above if (len(y_coords) < point_count): y_coords = np.append(y_coords, end_point.y) print(len(x_coords)) print(len(y_coords)) #interpolation... from scipy import interpolate ff = interpolate.interp1d(x_coords, y_coords, kind='cubic', bounds_error=False, fill_value=0) ll = int(h.Shape.Length) + 1 #create a set of x_coords-values evenly spaced between 0 and ll at the specified step interval xnew = np.arange(0, ll, step) last_element = xnew[len(xnew) - 1] if last_element != h.Shape.Length: xnew = np.append(xnew, h.Shape.Length) #interpolates y_coords values for the specified x_coords values ynew = ff(xnew) # use interpolation function returned by `interp1d` #ynew = np.append(ynew, vert_edge.Curve.parameterAtDistance(horiz_len)) # plt.plot(x_coords, y_coords, 'o', xnew, ynew, '+') # plt.show() #minimum of point_count, and the number of intervals in xnew #anz2=min(point_count,xnew.shape[0]) print('point_count: ', point_count) print('xnew.shape[0]', xnew.shape[0]) #print ("anz2: ", anz2) for i in range(xnew.shape[0]): print(xnew[i], ynew[i]) #x,y coordinate on horizontal #p=horiz_edge.valueAt(fip+step*(lap-fip)/horiz_len*i) #tangent at point t = horiz_edge.tangentAt(fip + step * (lap - fip) / horiz_len * i) #x,y coordinate on horizontal p = horiz_edge.Curve.value(fip + step * (lap - fip) / horiz_len * i) #stationing line interval f = 2 if i % 5 == 0: f = 4 if i % 10 == 0: f = 10 if i % 50 == 0: f = 30 #calculate normal vector at point n = f * t.cross(FreeCAD.Vector(0, 0, 1)) #hp=FreeCAD.Vector(p.x_coords,p.y_coords,hz_seg_pts[i].y_coords) # print i #generate z-coordinate for 3D spline hp = FreeCAD.Vector(p.x, p.y, ynew[i]) pts += [p, p + n, p, p - n, p] ptsn += [p, hp, p] hh = FreeCAD.Vector(xnew[i], ynew[i], 0) vpp = vert_edge.Curve.parameterAtDistance(xnew[i]) #vpp=vert_edge.Curve.parameter(hh) vtt = vert_edge.tangentAt(vpp) vn = f * vtt.cross(FreeCAD.Vector(0, 0, 1)) #ptsh += [hz_seg_pts[i],hz_seg_pts[i]+vn,hz_seg_pts[i]-vn,hz_seg_pts[i]] ptsh += [hh, hh + vn, hh - vn, hh] ptsc += [hp] import Part #stationing along horizontal curve res = App.ActiveDocument.getObject("Wxy") if res == None: res = App.activeDocument().addObject('Part::Feature', 'Wxy') res.Shape = Part.makePolygon(pts) # res = App.ActiveDocument.getObject("Whmap") if res == None: res = App.activeDocument().addObject('Part::Feature', 'Whmap') res.Shape = Part.makePolygon(ptsn) #station along vertical curve res = App.ActiveDocument.getObject("Wh") if res == None: res = App.activeDocument().addObject('Part::Feature', 'Wh') res.Shape = Part.makePolygon(ptsh) res = App.ActiveDocument.getObject("W3D") if res == None: res = App.activeDocument().addObject('Part::Feature', 'W3D') s = Part.BSplineCurve() s.interpolate(ptsc) res.Shape = s.toShape()
def createGeometry(self, obj): import Part, DraftGeomUtils # getting default values height = width = length = 1 if hasattr(obj, "Length"): if obj.Length: length = obj.Length if hasattr(obj, "Width"): if obj.Width: width = obj.Width if hasattr(obj, "Height"): if obj.Height: height = obj.Height # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if hasattr(obj, "Tool"): if obj.Tool: try: base = obj.Tool.Shape.copy().makePipe( obj.Base.Shape.copy()) except: FreeCAD.Console.PrintError( str( translate( "Arch", "Error: The base shape couldn't be extruded along this tool object" ))) return if not base: if obj.Normal == Vector(0, 0, 0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0, 0, 1)) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) base = base.extrude(normal) elif obj.Base.isDerivedFrom("Mesh::Feature"): if obj.Base.Mesh.isSolid(): if obj.Base.Mesh.countComponents() == 1: sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh) if sh.isClosed() and sh.isValid() and sh.Solids: base = sh else: if obj.Normal == Vector(0, 0, 0): normal = Vector(0, 0, 1) else: normal = Vector(obj.Normal) normal = normal.multiply(height) l2 = length / 2 or 0.5 w2 = width / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) base = Part.makePolygon([v1, v2, v3, v4, v1]) base = Part.Face(base) base = base.extrude(normal) base = self.processSubShapes(obj, base) if base: # applying axes pts = self.getAxisPoints(obj) apl = self.getAxisPlacement(obj) if pts: fsh = [] for i in range(len(pts)): if hasattr(obj, "Exclude"): if i in obj.Exclude: continue sh = base.copy() if apl: sh.Placement.Rotation = apl.Rotation sh.translate(pts[i]) fsh.append(sh) obj.Shape = Part.makeCompound(fsh) # finalizing else: if base: if not base.isNull(): if base.isValid() and base.Solids: if base.Volume < 0: base.reverse() if base.Volume < 0: FreeCAD.Console.PrintError( str( translate("Arch", "Couldn't compute a shape"))) return base = base.removeSplitter() obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl
def planarize( layerNum ): #Creates a single Z valued layer covering all previous features ''' planarize function takes the passed FreeCAD function name and finds the distance from that shape to the substrate. It then finds the highest point (top of a feature) and takes that point minus the base of the passed layer which gives the total height of the top object. From here an additional "buffer" is added to those values (so that all features are properly covered - and required for FreeCAD to evaluate properly) to create a total extrusion distance. A layer is then created using the outermost bounds of the FreeCAD document (substrate/outline layer) and the total extrusion distance. The new layer is then trimmed of all objects (not substrate) in the FreeCAD document (anything already deposited). The final object will rest on top of all the other layers as long as there are no gaps within the other layers (these will get filled in with this object). Function is passed the name of the top layer Returns the planarized layer **Currently only designed to create one planarization; however, FreeCAD will automatically append numbers to the name if additional planar layers are called. This can also be updated to use the two global arrays (currently commented out). ''' print("Start planarize") layerObj = FreeCAD.ActiveDocument.getObject(layerNum).Shape belowLayer = layerObj.Edges[0].distToShape( FreeCAD.ActiveDocument.getObject("Substrate").Shape)[0] additionalPlanarizeLevel = 1 #Can change this to add extra thickness to the planarization maxHeight = round(sp.get_highest_point(), 4) objHeight = maxHeight - round( layerObj.Vertexes[0].Point[2], 4) #Returns the max height of just the object being planarizized totalExtrusion = belowLayer + objHeight + additionalPlanarizeLevel #Total value needed to extrude the planar layer outerBounds = list(sp.get_2D_outer_bounds()) outerBounds.append( outerBounds[0] ) #Closes the shape by reconnecting the last vertex to the first vertex for idx, point in enumerate(outerBounds): outerBounds[idx] = list( outerBounds[idx] ) #Changes the tuple values into a list so they can be edited outerBounds[idx].append(0) #Starting Z value of 0 #print(outerBounds) pts = [] for pt in outerBounds: pts.append(FreeCAD.Vector(pt[0], pt[1], pt[2])) planarWire = Part.makePolygon( pts) #Makes a wire out of the outermost bounds planarFace = Part.Face(planarWire) planarExtrusion = planarFace.extrude( Base.Vector(0, 0, totalExtrusion) ) #+.0005)) #Might need to add a small amount, like .0005, here to account for the subtraction done later on cutObj = planarExtrusion.copy() #Used to trim the planar layer for obj in FreeCAD.ActiveDocument.Objects: #Loops all objects if obj.Label != "Substrate": #If FreeCAD label is not substrate #print(obj.Label) #For debugging planarExtrusion = planarExtrusion.cut( obj.Shape ) #Takes the original "block" planar layer and cuts out all features/layers #Part.show(planarExtrusion) #For debugging cutObj.Placement.move( FreeCAD.Vector(0, 0, totalExtrusion) ) #+.0006)) #The .0006 accounts for the -.0005 movement later on and allows for all extra edges to be deleted trimmedPlanar = planarExtrusion.cut( cutObj ) #Trims the top of the planar layer to ensure proper height and being flat planarLayer = FreeCAD.ActiveDocument.addObject("Part::Feature", "myPlanar") planarLayer.Shape = trimmedPlanar print("End planarize") return planarLayer
def run(self): """run(): Runs a nesting operation. Returns a list of lists of shapes, each primary list being one filled container, or None if the operation failed.""" # reset abort mechanism and variables self.running = True self.progress = 0 starttime = datetime.now() # general conformity tests print("Executing conformity tests ... ",end="") if not self.container: print("Empty container. Aborting") return if not self.shapes: print("Empty shapes. Aborting") return if not isinstance(self.container,Part.Face): print("Container is not a face. Aborting") return normal = self.container.normalAt(0,0) for s in self.shapes: if not self.update(): return if len(s.Faces) != 1: print("One of the shapes does not contain exactly one face. Aborting") return # check if all faces correctly oriented (same normal) if s.Faces[0].normalAt(0,0).getAngle(normal) > TOLERANCE: # let pass faces with inverted normal if s.Faces[0].normalAt(0,0).getAngle(normal)-math.pi > TOLERANCE: print("One of the face doesn't have the same orientation as the container. Aborting") return # TODO # allow to use a non-rectangular container # manage margins/paddings # allow to prevent or force specific rotations for a piece # LONG-TERM TODO # add genetic algo to swap pieces, and check if the result is better # track progresses step = 100.0/(len(self.shapes)*len(ROTATIONS)) # store hashCode together with the face so we can change the order # and still identify the original face, so we can calculate a transform afterwards self.indexedfaces = [[shape.hashCode(),shape] for shape in self.shapes] # build a clean copy so we don't touch the original faces = list(self.indexedfaces) # replace shapes by their face faces = [[f[0],f[1].Faces[0]] for f in faces] # order by area faces = sorted(faces,key=lambda face: face[1].Area) # discretize non-linear edges and remove holes nfaces = [] for face in faces: if not self.update(): return nedges = [] allLines = True for edge in face[1].OuterWire.OrderedEdges: if isinstance(edge.Curve,(Part.LineSegment,Part.Line)): nedges.append(edge) else: allLines = False last = edge.Vertexes[0].Point for i in range(DISCRETIZE): s = float(i+1)/DISCRETIZE par = edge.FirstParameter + (edge.LastParameter-edge.FirstParameter)*s new = edge.valueAt(par) nedges.append(Part.LineSegment(last,new).toShape()) last = new f = Part.Face(Part.Wire(nedges)) if not f.isValid(): if allLines: print("Invalid face found in set. Aborting") else: print("Face distretizing failed. Aborting") return nfaces.append([face[0],f]) faces = nfaces # container for sheets with a first, empty sheet sheets = [[]] print("Everything OK (",datetime.now()-starttime,")") # main loop facenumber = 1 facesnumber = len(faces) #print("Vertices per face:",[len(face[1].Vertexes) for face in faces]) while faces: print("Placing piece",facenumber,"/",facesnumber,"Area:",FreeCAD.Units.Quantity(faces[-1][1].Area,FreeCAD.Units.Area).getUserPreferred()[0],": ",end="") face = faces.pop() boc = self.container.BoundBox # this stores the available solutions for each rotation of a piece # contains [sheetnumber,face,xlength] lists, # face being [hascode,transformed face] and xlength # the X size of all boundboxes of placed pieces available = [] # this stores the possible positions on a blank # sheet, in case we need to create a new one initials = [] # this checks if the piece don't fit in the container unfit = True for rotation in ROTATIONS: if not self.update(): return self.progress += step print(rotation,", ",end="") hashcode = face[0] rotface = face[1].copy() if rotation: rotface.rotate(rotface.CenterOfMass,normal,rotation) bof = rotface.BoundBox rotverts = self.order(rotface) #for i,v in enumerate(rotverts): # Draft.makeText([str(i)],point=v) basepoint = rotverts[0] # leftmost point of the rotated face basecorner = boc.getPoint(0) # lower left corner of the container # See if the piece fits in the container dimensions if (bof.XLength < boc.XLength) and (bof.YLength < boc.YLength): unfit = False # Get the fit polygon of the container # that is, the polygon inside which basepoint can # circulate, and the face still be fully inside the container v1 = basecorner.add(basepoint.sub(bof.getPoint(0))) v2 = v1.add(FreeCAD.Vector(0,boc.YLength-bof.YLength,0)) v3 = v2.add(FreeCAD.Vector(boc.XLength-bof.XLength,0,0)) v4 = v3.add(FreeCAD.Vector(0,-(boc.YLength-bof.YLength),0)) binpol = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1])) initials.append([binpol,[hashcode,rotface],basepoint]) # check for available space on each existing sheet for sheetnumber,sheet in enumerate(sheets): # Get the no-fit polygon for each already placed face in # current sheet. That is, a polygon in which basepoint # cannot be, if we want our face to not overlap with the # placed face. # To do this, we "circulate" the face around the placed face if not self.update(): return nofitpol = [] for placed in sheet: pts = [] for placedvert in self.order(placed[1],right=True): fpts = [] for i,rotvert in enumerate(rotverts): if not self.update(): return facecopy = rotface.copy() facecopy.translate(placedvert.sub(rotvert)) # test if all the points of the face are outside the # placed face (except the base point, which is coincident) outside = True faceverts = self.order(facecopy) for vert in faceverts: if (vert.sub(placedvert)).Length > TOLERANCE: if placed[1].isInside(vert,TOLERANCE,True): outside = False break # also need to test for edge intersection, because even # if all vertices are outside, the pieces could still # overlap if outside: for e1 in facecopy.OuterWire.Edges: for e2 in placed[1].OuterWire.Edges: if not self.update(): return if True: # Draft code (SLOW) p = DraftGeomUtils.findIntersection(e1,e2) if p: p = p[0] p1 = e1.Vertexes[0].Point p2 = e1.Vertexes[1].Point p3 = e2.Vertexes[0].Point p4 = e2.Vertexes[1].Point if (p.sub(p1).Length > TOLERANCE) and (p.sub(p2).Length > TOLERANCE) \ and (p.sub(p3).Length > TOLERANCE) and (p.sub(p4).Length > TOLERANCE): outside = False break else: # alt code: using distToShape (EVEN SLOWER!) p = e1.distToShape(e2) if p: if p[0] < TOLERANCE: # allow vertex-to-vertex intersection if (p[2][0][0] != "Vertex") or (p[2][0][3] != "Vertex"): outside = False break if outside: fpts.append([faceverts[0],i]) #Draft.makeText([str(i)],point=faceverts[0]) # reorder available solutions around a same point if needed # ensure they are in the correct order idxs = [p[1] for p in fpts] if (0 in idxs) and (len(faceverts)-1 in idxs): slicepoint = len(fpts) last = len(faceverts) for p in reversed(fpts): if p[1] == last-1: slicepoint -= 1 last -= 1 else: break fpts = fpts[slicepoint:]+fpts[:slicepoint] #print(fpts) pts.extend(fpts) # create the polygon if len(pts) < 3: print("Error calculating a no-fit polygon. Aborting") return pts = [p[0] for p in pts] pol = Part.Face(Part.makePolygon(pts+[pts[0]])) if not pol.isValid(): # fix overlapping edges overlap = True while overlap: overlap = False for i in range(len(pol.OuterWire.Edges)-1): if not self.update(): return v1 = DraftGeomUtils.vec(pol.OuterWire.OrderedEdges[i]) v2 = DraftGeomUtils.vec(pol.OuterWire.OrderedEdges[i+1]) if abs(v1.getAngle(v2)-math.pi) <= TOLERANCE: overlap = True ne = Part.LineSegment(pol.OuterWire.OrderedEdges[i].Vertexes[0].Point, pol.OuterWire.OrderedEdges[i+1].Vertexes[-1].Point).toShape() pol = Part.Face(Part.Wire(pol.OuterWire.OrderedEdges[:i]+[ne]+pol.OuterWire.OrderedEdges[i+2:])) break if not pol.isValid(): # trying basic OCC fix pol.fix(0,0,0) if pol.isValid(): if pol.ShapeType == "Face": pol = Part.Face(pol.OuterWire) # discard possible inner holes elif pol.Faces: # several faces after the fix, keep the biggest one a = 0 ff = None for f in pol.Faces: if f.Area > a: a = f.Area ff = f if ff: pol = ff else: print("Unable to fix invalid no-fit polygon. Aborting") Part.show(pol) return if not pol.isValid(): # none of the fixes worked. Epic fail. print("Invalid no-fit polygon. Aborting") Part.show(pol.OuterWire) for p in sheet: Part.show(p[1]) Part.show(facecopy) #for i,p in enumerate(faceverts): # Draft.makeText([str(i)],point=p) return if pol.isValid(): nofitpol.append(pol) #Part.show(pol) # Union all the no-fit pols into one if len(nofitpol) == 1: nofitpol = nofitpol[0] elif len(nofitpol) > 1: b = nofitpol.pop() for n in nofitpol: if not self.update(): return b = b.fuse(n) nofitpol = b # remove internal edges (discard edges shared by 2 faces) lut = {} for f in fitpol.Faces: for e in f.Edges: h = e.hashCode() if h in lut: lut[h].append(e) else: lut[h] = [e] edges = [e[0] for e in lut.values() if len(e) == 1] try: pol = Part.Face(Part.Wire(edges)) except Exception: # above method can fail sometimes. Try a slower method w = DraftGeomUtils.findWires(edges) if len(w) == 1: if w[0].isClosed(): try: pol = Part.Face(w[0]) except Exception: print("Error merging polygons. Aborting") try: Part.show(Part.Wire(edges)) except Exception: for e in edges: Part.show(e) return # subtract the no-fit polygon from the container's fit polygon # we then have the zone where the face can be placed if nofitpol: fitpol = binpol.cut(nofitpol) else: fitpol = binpol.copy() # check that we have some space on this sheet if (fitpol.Area > 0) and fitpol.Vertexes: # order the fitpol vertexes by smallest X # and try to place the piece, making sure it doesn't # intersect with already placed pieces fitverts = sorted([v.Point for v in fitpol.Vertexes],key=lambda v: v.x) for p in fitverts: if not self.update(): return trface = rotface.copy() trface.translate(p.sub(basepoint)) ok = True for placed in sheet: if ok: for vert in trface.Vertexes: if placed[1].isInside(vert.Point,TOLERANCE,False): ok = False break if ok: for e1 in trface.OuterWire.Edges: for e2 in placed[1].OuterWire.Edges: p = DraftGeomUtils.findIntersection(e1,e2) if p: p = p[0] p1 = e1.Vertexes[0].Point p2 = e1.Vertexes[1].Point p3 = e2.Vertexes[0].Point p4 = e2.Vertexes[1].Point if (p.sub(p1).Length > TOLERANCE) and (p.sub(p2).Length > TOLERANCE) \ and (p.sub(p3).Length > TOLERANCE) and (p.sub(p4).Length > TOLERANCE): ok = False break if not ok: break if ok: rotface = trface break else: print("Couldn't determine location on sheet. Aborting") return # check the X space occupied by this solution bb = rotface.BoundBox for placed in sheet: bb.add(placed[1].BoundBox) available.append([sheetnumber,[hashcode,rotface],bb.XMax,fitpol]) if unfit: print("One face doesn't fit in the container. Aborting") return if available: # order by smallest X size and take the first one available = sorted(available,key=lambda sol: sol[2]) print("Adding piece to sheet",available[0][0]+1) sheets[available[0][0]].append(available[0][1]) #Part.show(available[0][3]) else: # adding to the leftmost vertex of the binpol sheet = [] print("Creating new sheet, adding piece to sheet",len(sheets)) # order initial positions by smallest X size initials = sorted(initials,key=lambda sol: sol[1][1].BoundBox.XLength) hashcode = initials[0][1][0] face = initials[0][1][1] # order binpol vertexes by X coord verts = sorted([v.Point for v in initials[0][0].Vertexes],key=lambda v: v.x) face.translate(verts[0].sub(initials[0][2])) sheet.append([hashcode,face]) sheets.append(sheet) facenumber += 1 print("Run time:",datetime.now()-starttime) self.results.append(sheets) return sheets
def makeStraightStairs(self, obj, edge, numberofsteps=None): "builds a simple, straight staircase from a straight edge" # general data import Part, DraftGeomUtils if not numberofsteps: numberofsteps = obj.NumberOfSteps v = DraftGeomUtils.vec(edge) vLength = DraftVecUtils.scaleTo( v, float(edge.Length) / (numberofsteps - 1)) vLength = Vector(vLength.x, vLength.y, 0) if round(v.z, Draft.precision()) != 0: h = v.z else: h = obj.Height.Value vHeight = Vector(0, 0, float(h) / numberofsteps) vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0, 0, 1)), obj.Width.Value) vBase = edge.Vertexes[0].Point vNose = DraftVecUtils.scaleTo(vLength, -abs(obj.Nosing.Value)) a = math.atan(vHeight.Length / vLength.Length) #print("stair data:",vLength.Length,":",vHeight.Length) # steps for i in range(numberofsteps - 1): p1 = vBase.add((Vector(vLength).multiply(i)).add( Vector(vHeight).multiply(i + 1))) p1 = self.align(p1, obj.Align, vWidth) p1 = p1.add(vNose).add(Vector(0, 0, -abs(obj.TreadThickness.Value))) p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength) p3 = p2.add(vWidth) p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose) step = Part.Face(Part.makePolygon([p1, p2, p3, p4, p1])) if obj.TreadThickness.Value: step = step.extrude(Vector(0, 0, abs(obj.TreadThickness.Value))) self.steps.append(step) else: self.pseudosteps.append(step) # structure lProfile = [] struct = None if obj.Structure == "Massive": if obj.StructureThickness.Value: for i in range(numberofsteps - 1): if not lProfile: lProfile.append(vBase) last = lProfile[-1] if len(lProfile) == 1: last = last.add( Vector(0, 0, -abs(obj.TreadThickness.Value))) lProfile.append(last.add(vHeight)) lProfile.append(lProfile[-1].add(vLength)) resHeight1 = obj.StructureThickness.Value / math.cos(a) lProfile.append(lProfile[-1].add(Vector(0, 0, -resHeight1))) resHeight2 = ((numberofsteps - 1) * vHeight.Length) - ( resHeight1 + obj.TreadThickness.Value) resLength = (vLength.Length / vHeight.Length) * resHeight2 h = DraftVecUtils.scaleTo(vLength, -resLength) lProfile.append(lProfile[-1].add(Vector(h.x, h.y, -resHeight2))) lProfile.append(vBase) #print(lProfile) pol = Part.makePolygon(lProfile) struct = Part.Face(pol) evec = vWidth if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) struct.translate(mvec) evec = DraftVecUtils.scaleTo( evec, evec.Length - (2 * mvec.Length)) struct = struct.extrude(evec) elif obj.Structure in ["One stringer", "Two stringers"]: if obj.StringerWidth.Value and obj.StructureThickness.Value: hyp = math.sqrt(vHeight.Length**2 + vLength.Length**2) l1 = Vector(vLength).multiply(numberofsteps - 1) h1 = Vector(vHeight).multiply(numberofsteps - 1).add( Vector(0, 0, -abs(obj.TreadThickness.Value))) p1 = vBase.add(l1).add(h1) p1 = self.align(p1, obj.Align, vWidth) lProfile.append(p1) h2 = (obj.StructureThickness.Value / vLength.Length) * hyp lProfile.append(lProfile[-1].add(Vector(0, 0, -abs(h2)))) h3 = lProfile[-1].z - vBase.z l3 = (h3 / vHeight.Length) * vLength.Length v3 = DraftVecUtils.scaleTo(vLength, -l3) lProfile.append(lProfile[-1].add(Vector(0, 0, -abs(h3))).add(v3)) l4 = (obj.StructureThickness.Value / vHeight.Length) * hyp v4 = DraftVecUtils.scaleTo(vLength, -l4) lProfile.append(lProfile[-1].add(v4)) lProfile.append(lProfile[0]) #print(lProfile) pol = Part.makePolygon(lProfile) pol = Part.Face(pol) evec = DraftVecUtils.scaleTo(vWidth, obj.StringerWidth.Value) if obj.Structure == "One stringer": if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) else: mvec = DraftVecUtils.scaleTo( vWidth, (vWidth.Length / 2) - obj.StringerWidth.Value / 2) pol.translate(mvec) struct = pol.extrude(evec) elif obj.Structure == "Two stringers": pol2 = pol.copy() if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) pol.translate(mvec) mvec = vWidth.add(mvec.negative()) pol2.translate(mvec) else: pol2.translate(vWidth) s1 = pol.extrude(evec) s2 = pol2.extrude(evec.negative()) struct = Part.makeCompound([s1, s2]) if struct: self.structures.append(struct)
def getCutVolume(cutplane,shapes): """getCutVolume(cutplane,shapes): returns a cut face and a cut volume from the given shapes and the given cutting plane""" if not shapes: return None,None,None import Part if not isinstance(shapes,list): shapes = [shapes] # building boundbox bb = shapes[0].BoundBox for sh in shapes[1:]: bb.add(sh.BoundBox) bb.enlarge(1) # building cutplane space placement = None um = vm = wm = 0 try: if hasattr(cutplane,"Shape"): p = cutplane.Shape.copy().Faces[0] else: p = cutplane.copy().Faces[0] except: FreeCAD.Console.PrintMessage(translate("Arch","Invalid cutplane")) return None,None,None ce = p.CenterOfMass ax = p.normalAt(0,0) u = p.Vertexes[1].Point.sub(p.Vertexes[0].Point).normalize() v = u.cross(ax) if not bb.isCutPlane(ce,ax): FreeCAD.Console.PrintMessage(translate("Arch","No objects are cut by the plane")) return None,None,None else: corners = [FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin), FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMin), FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMin), FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMin), FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMax), FreeCAD.Vector(bb.XMin,bb.YMax,bb.ZMax), FreeCAD.Vector(bb.XMax,bb.YMin,bb.ZMax), FreeCAD.Vector(bb.XMax,bb.YMax,bb.ZMax)] for c in corners: dv = c.sub(ce) um1 = DraftVecUtils.project(dv,u).Length um = max(um,um1) vm1 = DraftVecUtils.project(dv,v).Length vm = max(vm,vm1) wm1 = DraftVecUtils.project(dv,ax).Length wm = max(wm,wm1) vu = DraftVecUtils.scaleTo(u,um) vui = vu.negative() vv = DraftVecUtils.scaleTo(v,vm) vvi = vv.negative() p1 = ce.add(vu.add(vvi)) p2 = ce.add(vu.add(vv)) p3 = ce.add(vui.add(vv)) p4 = ce.add(vui.add(vvi)) cutface = Part.makePolygon([p1,p2,p3,p4,p1]) cutface = Part.Face(cutface) cutnormal = DraftVecUtils.scaleTo(ax,wm) cutvolume = cutface.extrude(cutnormal) cutnormal = cutnormal.negative() invcutvolume = cutface.extrude(cutnormal) return cutface,cutvolume,invcutvolume
def makeSolarDiagram(longitude, latitude, scale=1, complete=False): """makeSolarDiagram(longitude,latitude,[scale,complete]): returns a solar diagram as a pivy node. If complete is True, the 12 months are drawn""" from subprocess import call py3_failed = call(["python3", "-c", "import Pysolar"]) if py3_failed: try: import Pysolar except: print( "Pysolar is not installed. Unable to generate solar diagrams") return None else: from subprocess import check_output from pivy import coin if not scale: return None def toNode(shape): "builds a pivy node from a simple linear shape" from pivy import coin buf = shape.writeInventor(2, 0.01) buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([float(v[0]), float(v[1]), float(v[2])]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) item = coin.SoSeparator() item.addChild(coords) item.addChild(line) return item circles = [] sunpaths = [] hourpaths = [] circlepos = [] hourpos = [] # build the base circle + number positions import Part for i in range(1, 9): circles.append(Part.makeCircle(scale * (i / 8.0))) for ad in range(0, 360, 15): a = math.radians(ad) p1 = FreeCAD.Vector(math.cos(a) * scale, math.sin(a) * scale, 0) p2 = FreeCAD.Vector( math.cos(a) * scale * 0.125, math.sin(a) * scale * 0.125, 0) p3 = FreeCAD.Vector( math.cos(a) * scale * 1.08, math.sin(a) * scale * 1.08, 0) circles.append(Part.LineSegment(p1, p2).toShape()) circlepos.append((ad, p3)) # build the sun curves at solstices and equinoxe year = datetime.datetime.now().year hpts = [[] for i in range(24)] m = [(6, 21), (7, 21), (8, 21), (9, 21), (10, 21), (11, 21), (12, 21)] if complete: m.extend([(1, 21), (2, 21), (3, 21), (4, 21), (5, 21)]) for i, d in enumerate(m): pts = [] for h in range(24): if not py3_failed: dt = "datetime.datetime(%s, %s, %s, %s)" % (year, d[0], d[1], h) alt_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_altitude_fast(%s, %s, %s))'" % ( latitude, longitude, dt) alt = math.radians( float(check_output(alt_call, shell=True).strip())) az_call = "python3 -c 'import datetime,Pysolar; print (Pysolar.solar.get_azimuth(%s, %s, %s))'" % ( latitude, longitude, dt) az = float( re.search('.+$', check_output(az_call, shell=True)).group(0)) else: dt = datetime.datetime(year, d[0], d[1], h) alt = math.radians( Pysolar.solar.GetAltitudeFast(latitude, longitude, dt)) az = Pysolar.solar.GetAzimuth(latitude, longitude, dt) az = -90 + az # pysolar's zero is south if az < 0: az = 360 + az az = math.radians(az) zc = math.sin(alt) * scale ic = math.cos(alt) * scale xc = math.cos(az) * ic yc = math.sin(az) * ic p = FreeCAD.Vector(xc, yc, zc) pts.append(p) hpts[h].append(p) if i in [0, 6]: ep = FreeCAD.Vector(p) ep.multiply(1.08) if ep.z >= 0: if h == 12: if i == 0: h = "SUMMER" else: h = "WINTER" if latitude < 0: if h == "SUMMER": h = "WINTER" else: h = "SUMMER" hourpos.append((h, ep)) if i < 7: sunpaths.append(Part.makePolygon(pts)) for h in hpts: if complete: h.append(h[0]) hourpaths.append(Part.makePolygon(h)) # cut underground lines sz = 2.1 * scale cube = Part.makeBox(sz, sz, sz) cube.translate(FreeCAD.Vector(-sz / 2, -sz / 2, -sz)) sunpaths = [sp.cut(cube) for sp in sunpaths] hourpaths = [hp.cut(cube) for hp in hourpaths] # build nodes ts = 0.005 * scale # text scale mastersep = coin.SoSeparator() circlesep = coin.SoSeparator() numsep = coin.SoSeparator() pathsep = coin.SoSeparator() hoursep = coin.SoSeparator() hournumsep = coin.SoSeparator() mastersep.addChild(circlesep) mastersep.addChild(numsep) mastersep.addChild(pathsep) mastersep.addChild(hoursep) for item in circles: circlesep.addChild(toNode(item)) for item in sunpaths: for w in item.Edges: pathsep.addChild(toNode(w)) for item in hourpaths: for w in item.Edges: hoursep.addChild(toNode(w)) for p in circlepos: text = coin.SoText2() s = p[0] - 90 s = -s if s > 360: s = s - 360 if s < 0: s = 360 + s if s == 0: s = "N" elif s == 90: s = "E" elif s == 180: s = "S" elif s == 270: s = "W" else: s = str(s) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) for p in hourpos: text = coin.SoText2() s = str(p[0]) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) return mastersep
def createShape(obj): '''create the 2D or 3D mapping Shape for a wire and a base face the data are parameters of the obj ''' # print "CreateShape for obj:",obj.Label #pointCount=obj.pointcount #pointCount=50 [uv2x,uv2y,xy2u,xy2v]=[obj.mapobject.Proxy.uv2x,obj.mapobject.Proxy.uv2y,obj.mapobject.Proxy.xy2u,obj.mapobject.Proxy.xy2v] if xy2v==None: print "Kann umkehrung nicht berechnen xy2v nicht vorhanden" return # diese daten vom mapobjekt lesen #+# mpv=0.5 mpu=0.5 u0=0 v0=0 fy=1. fx=1. #+# facenumer aus obj param holen face=obj.face.Shape.Face1 bs=face.Surface # w=obj.wire.Shape.Wires[0] wires=obj.wire.Shape.Wires if len(wires)==0: wires=obj.wire.Shape.Edges ppall=[] pos=FreeCAD.Vector(obj.mapobject.Placement.Base.x,obj.mapobject.Placement.Base.y,0) for i,w in enumerate(wires): # print ("Wire ...",i,pointCount) FreeCAD.w=w for i,ee in enumerate(w.Edges): ct=max(int(round(ee.Length/obj.pointdist)),2) if i == 0: ptsaa= ee.discretize(ct) else: pts=ee.discretize(ct) if pts[-1]==ptsaa[-1]: pts=pts[::-1] ptsaa += pts[1:] pts=[p-pos for p in ptsaa] pts2=[] #refpos geht noch nicht mpv=0. mpu=0. # refpos=bs.value(mpu,mpv) # print ("refpos",mpu,mpv) # print refpos refpos=FreeCAD.Vector(0,0,0) for p in pts: y=fx*(p.x-refpos.x) x=fy*(p.y-refpos.y) #fuer ruled surface !! x=fx*p.y y=fy*p.x u=xy2u(x,y) v=xy2v(x,y) ## su=face.ParameterRange[1] ## sv=face.ParameterRange[3] sua=face.ParameterRange[0] sva=face.ParameterRange[2] sue=face.ParameterRange[1] sve=face.ParameterRange[3] sul=sue-sua svl=sve-sva #sua + svl* #sva + svl* #try: sweep=obj.face.TypeId=='Part::Sweep' #except: sweep=True if obj.mapobject.flipuv23: p2=bs.value(u,v) else: p2=bs.value(sva+u*svl,aua+v*sul) pts2.append(p2) FreeCAD.pts2a=pts2 obj.Shape=Part.makePolygon(pts2)
def execute(self, obj): import Part plm = obj.Placement if obj.Base and (not obj.Tool): if obj.Base.isDerivedFrom("Sketcher::SketchObject"): shape = obj.Base.Shape.copy() if obj.Base.Shape.isClosed(): if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) obj.Shape = shape elif obj.Base and obj.Tool: if hasattr(obj.Base, 'Shape') and hasattr(obj.Tool, 'Shape'): if (not obj.Base.Shape.isNull()) and ( not obj.Tool.Shape.isNull()): sh1 = obj.Base.Shape.copy() sh2 = obj.Tool.Shape.copy() shape = sh1.fuse(sh2) if DraftGeomUtils.isCoplanar(shape.Faces): shape = DraftGeomUtils.concatenate(shape) obj.Shape = shape p = [] for v in shape.Vertexes: p.append(v.Point) if obj.Points != p: obj.Points = p elif obj.Points: if obj.Points[0] == obj.Points[-1]: if not obj.Closed: obj.Closed = True obj.Points.pop() if obj.Closed and (len(obj.Points) > 2): pts = obj.Points if hasattr(obj, "Subdivisions"): if obj.Subdivisions > 0: npts = [] for i in range(len(pts)): p1 = pts[i] npts.append(pts[i]) if i == len(pts) - 1: p2 = pts[0] else: p2 = pts[i + 1] v = p2.sub(p1) v = DraftVecUtils.scaleTo( v, v.Length / (obj.Subdivisions + 1)) for j in range(obj.Subdivisions): npts.append( p1.add(App.Vector(v).multiply(j + 1))) pts = npts shape = Part.makePolygon(pts + [pts[0]]) if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w try: if hasattr(obj, "MakeFace"): if obj.MakeFace: shape = Part.Face(shape) else: shape = Part.Face(shape) except Part.OCCError: pass else: edges = [] pts = obj.Points[1:] lp = obj.Points[0] for p in pts: if not DraftVecUtils.equals(lp, p): if hasattr(obj, "Subdivisions"): if obj.Subdivisions > 0: npts = [] v = p.sub(lp) v = DraftVecUtils.scaleTo( v, v.Length / (obj.Subdivisions + 1)) edges.append( Part.LineSegment(lp, lp.add(v)).toShape()) lv = lp.add(v) for j in range(obj.Subdivisions): edges.append( Part.LineSegment(lv, lv.add(v)).toShape()) lv = lv.add(v) else: edges.append(Part.LineSegment(lp, p).toShape()) else: edges.append(Part.LineSegment(lp, p).toShape()) lp = p try: shape = Part.Wire(edges) except Part.OCCError: print("Error wiring edges") shape = None if "ChamferSize" in obj.PropertiesList: if obj.ChamferSize.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.ChamferSize.Value, chamfer=True) if w: shape = w if "FilletRadius" in obj.PropertiesList: if obj.FilletRadius.Value != 0: w = DraftGeomUtils.filletWire(shape, obj.FilletRadius.Value) if w: shape = w if shape: obj.Shape = shape if hasattr(obj, "Area") and hasattr(shape, "Area"): obj.Area = shape.Area if hasattr(obj, "Length"): obj.Length = shape.Length obj.Placement = plm obj.positionBySupport() self.onChanged(obj, "Placement")
def run_FreeCAD_CurveOffset(self): import Part edge = self.getPinObject("Shape_in") if edge is None: sayW("no shape edge") return Z = FreeCAD.Vector(0, 0, 1) col = [] lastdd = 100 edstart = edge ed = edstart loops = self.getData("loops") for i in range(loops): cs = ed.Curve size = 300 norms = [] if i > 1: #step=self.getData("step")/10 #size=int(round(edstart.Length/step)) #tas=[] say("get distant points size ", size) points = cs.discretize(size + 1) else: deflection = self.getData("deflection") points = cs.discretize(QuasiDeflection=deflection * 0.001) for p in points: v = cs.parameter(p) t = cs.tangent(v)[0] norms += [t.cross(Z)] dd = self.getData("mindd") / 100 if self.getData('flip'): dd = -dd distA = self.getData("distA") pts = [] ptserr = [] if 1: for n, p in zip(norms, points): neup = p + n * dd zp = edstart.distToShape(Part.Vertex(*neup))[1][0][0] if (p - zp).Length > distA * 0.01: #say("ABweichung",(p-zp).Length) #say("p",p) #say("neup",neup) #say("zp",zp) #say(edstart.distToShape(Part.Vertex(*neup))) if i == 0: ptserr += [neup] else: pts += [neup] else: pts += [neup] lp = len(pts) def checkcross(A, B, C, D): ''' schneiden sich die strecken AC und BD innen?''' a = C - A b = B - D c = B - A aa = np.array([[a.x, a.y], [b.x, b.y]]) aa = np.array([[a.x, b.x], [a.y, b.y]]) bb = np.array([c.x, c.y]) x = np.linalg.solve(aa, bb) fa = 0 < x[0] and x[0] < 1 fb = 0 < x[1] and x[1] < 1 return fa and fb def cut(i, j): A = pts[i] B = pts[i + 1] C = pts[j] D = pts[j + 1] return checkcross(A, C, B, D) fehler = [0] for i in range(lp - 2): for j in range(lp - 2): if i >= j: continue if cut(i, j): fehler += [i, j] fehler += [-1] neupol = [] for l in range(int(len(fehler) / 2)): neupol += pts[fehler[2 * l]:fehler[2 * l + 1]] neupol += pts[fehler[-1]:] pts = neupol col = [Part.makePolygon(pts)] FreeCADGui.updateGui() bc = Part.BSplineCurve() bc.buildFromPoles(pts) ed = bc.toShape() if not self.getData('asPolygon'): col = [ed] self.setPinObject("Shape_out", Part.Compound(col)) self.outExec.call() ptsn = bc.discretize(size + 1) dists = [edstart.distToShape(Part.Vertex(*p))[0] for p in ptsn] say("distance expected min max", abs(dd), round(min(dists), 2), round(max(dists), 2))
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 diagonal & thickness side edge vec2 = (p2 - p1) angle1 = vec2.getAngle(vec1) angle = math.degrees(angle1) #print(angle) # Check & correct orientation of diagonal 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 execute(self,obj): tol = 1 # tolerance for alignment. This is only visual, we can keep it low... import math,Part,DraftGeomUtils,ArchCommands if len(obj.Pipes) < 2: return if len(obj.Pipes) > 3: FreeCAD.Console.PrintWarning(translate("Arch","Only the 3 first wires will be connected\n")) if obj.Radius.Value == 0: return wires = [] order = [] for o in obj.Pipes: wires.append(o.Proxy.getWire(o)) if wires[0].Vertexes[0].Point == wires[1].Vertexes[0].Point: order = ["start","start"] point = wires[0].Vertexes[0].Point elif wires[0].Vertexes[0].Point == wires[1].Vertexes[-1].Point: order = ["start","end"] point = wires[0].Vertexes[0].Point elif wires[0].Vertexes[-1].Point == wires[1].Vertexes[-1].Point: order = ["end","end"] point = wires[0].Vertexes[-1].Point elif wires[0].Vertexes[-1].Point == wires[1].Vertexes[0].Point: order = ["end","start"] point = wires[0].Vertexes[-1].Point else: FreeCAD.Console.PrintError(translate("Arch","Common vertex not found\n")) return if order[0] == "start": v1 = wires[0].Vertexes[1].Point.sub(wires[0].Vertexes[0].Point).normalize() else: v1 = wires[0].Vertexes[-2].Point.sub(wires[0].Vertexes[-1].Point).normalize() if order[1] == "start": v2 = wires[1].Vertexes[1].Point.sub(wires[1].Vertexes[0].Point).normalize() else: v2 = wires[1].Vertexes[-2].Point.sub(wires[1].Vertexes[-1].Point).normalize() p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0]) p = Part.Face(p) if len(obj.Pipes) == 2: if obj.ConnectorType != "Corner": obj.ConnectorType = "Corner" if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]: FreeCAD.Console.PrintError(translate("Arch","Pipes are already aligned\n")) return normal = v2.cross(v1) offset = math.tan(math.pi/2-v1.getAngle(v2)/2)*obj.Radius.Value v1.multiply(offset) v2.multiply(offset) self.setOffset(obj.Pipes[0],order[0],offset) self.setOffset(obj.Pipes[1],order[1],offset) # find center perp = v1.cross(normal).normalize() perp.multiply(obj.Radius.Value) center = point.add(v1).add(perp) # move and rotate the profile to the first point delta = point.add(v1)-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,v1) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) sh = p.revolve(center,normal,math.degrees(math.pi-v1.getAngle(v2))) #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))]) else: if obj.ConnectorType != "Tee": obj.ConnectorType = "Tee" if wires[2].Vertexes[0].Point == point: order.append("start") elif wires[0].Vertexes[-1].Point == point: order.append("end") else: FreeCAD.Console.PrintError(translate("Arch","Common vertex not found\n")) if order[2] == "start": v3 = wires[2].Vertexes[1].Point.sub(wires[2].Vertexes[0].Point).normalize() else: v3 = wires[2].Vertexes[-2].Point.sub(wires[2].Vertexes[-1].Point).normalize() if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]: pair = [v1,v2,v3] elif round(v1.getAngle(v3),tol) in [0,round(math.pi,tol)]: pair = [v1,v3,v2] elif round(v2.getAngle(v3),tol) in [0,round(math.pi,tol)]: pair = [v2,v3,v1] else: FreeCAD.Console.PrintError(translate("Arch","At least 2 pipes must aligned\n")) return offset = obj.Radius.Value v1.multiply(offset) v2.multiply(offset) v3.multiply(offset) self.setOffset(obj.Pipes[0],order[0],offset) self.setOffset(obj.Pipes[1],order[1],offset) self.setOffset(obj.Pipes[2],order[2],offset) normal = pair[0].cross(pair[2]) # move and rotate the profile to the first point delta = point.add(pair[0])-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,pair[0]) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) t1 = p.extrude(pair[1].multiply(2)) # move and rotate the profile to the second point delta = point.add(pair[2])-p.CenterOfMass p.translate(delta) vp = DraftGeomUtils.getNormal(p) rot = FreeCAD.Rotation(vp,pair[2]) p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle)) t2 = p.extrude(pair[2].negative().multiply(2)) # create a cut plane cp = Part.makePolygon([point,point.add(pair[0]),point.add(normal),point]) cp = Part.Face(cp) if cp.normalAt(0,0).getAngle(pair[2]) < math.pi/2: cp.reverse() cf, cv, invcv = ArchCommands.getCutVolume(cp,t2) t2 = t2.cut(cv) sh = t1.fuse(t2) obj.Shape = sh
def createGrid(mapobj,upmode=False): '''create a 2D grid or 3D grid (if upmode) for the map obj''' obj=mapobj try: face=obj.faceObject.Shape.Faces[obj.faceNumber] bs=face.Surface except: return Part.Shape() print "createGrid for special faces" print face import numpy as np sf=face.Surface if sf.__class__.__name__ == 'Cone': alpha,beta,hmin,hmax = face.ParameterRange r2=sf.Radius r1=(sf.Apex-sf.Center).Length alpha=r2*np.pi/r1 su=21 sv=21 pts=np.zeros(su*sv*3).reshape(su,sv,3) comp=[] for u in range(su): for v in range(sv): #print (beta-alpha)*u/2 p=FreeCAD.Vector((r1+hmax*v/sv)*np.cos((alpha)*u/su),(r1+hmax*v/sv)*np.sin((alpha)*u/su)) pts[u,v]=p for z in pts: comp += [Part.makePolygon([FreeCAD.Vector(p) for p in z])] pts=pts.swapaxes(0,1) for z in pts: comp += [Part.makePolygon([FreeCAD.Vector(p) for p in z])] #Part.show(Part.Compound(comp)) return Part.Compound(comp) # face=obj.faceObject.Shape.Face1 # mpu=obj.uMapCenter/100 # mpv=obj.vMapCenter/100 mpv=obj.uMapCenter/100 mpu=obj.vMapCenter/100 # skalierung/lage fx=obj.fx fy=obj.fy fz=1.0 comps=[] refpos=bs.value(mpv,mpu) #su=bs.UPeriod() #sv=bs.VPeriod() print "hack DD suu asv" su=face.ParameterRange[1] sv=face.ParameterRange[3] if su>1000: su=face.ParameterRange[1] if sv>1000: sv=face.ParameterRange[3] # mittelpunkt # try: sweep=obj.Faceobject.TypeId=='Part::Sweep' # except: sweep=True sua=face.ParameterRange[0] sva=face.ParameterRange[2] sue=face.ParameterRange[1] sve=face.ParameterRange[3] sul=sue-sua svl=sve-sva #sua + svl* #sva + svl* if not obj.flipuv23: mpu2=sva+mpu*svl mpv2=aza+mpv*sul else: if upmode: mpu2=sua+mpu*sul mpv2=sva+mpv*svl else: mpu2=sva+mpu*svl mpv2=sua+mpv*sul mpu=mpv2 mpv=mpu2 vc=obj.uCount uc=obj.vCount print "isodraw #ll" print (su,sv) print (uc,vc) print face.ParameterRange ptsa=[] ptska=[] ba=bs.uIso(mpu) comps += [ba.toShape()] for v in range(vc+1): pts=[] vm=sva+1.0/vc*v*svl ky=ba.length(vm,mpv) if vm<mpv: ky =-ky bbc=bs.vIso(vm) comps += [bbc.toShape()] ptsk=[] for u in range(uc+1): uv=sua+1.0/uc*u*sul ba=bs.uIso(uv) ky=ba.length(vm,mpv) if vm<mpv: ky =-ky kx=bbc.length(mpu,uv) if uv<mpu: kx =-kx # ptsk.append(bs.value(vm,uv)) ptsk.append(bs.value(uv,vm)) pts.append([kx,ky,0]) #print ("isodraw nknk",uv,vm,bs.value(uv,vm)) ptsa.append(pts) ptska.append(ptsk) #----------------------------------------------- [uv2x,uv2y,xy2u,xy2v]=getmap(mapobj,obj.faceObject) print "hier 3D Methode ccc..oo.............." if obj.mode=='curvature': [uv2x,uv2y,uv2z,xy2u,xy2v]=getmap3(mapobj,obj.faceObject) ptsa=[] for v in range(vc+1): pts=[] z2=0 z=0 for u in range(uc+1): if mapobj.flipuv: uv=sua+1.0/uc*u*sul vv=sva+1.0/vc*v*svl vv2=sva+1.0/uc*u*svl uv2=sua+1.0/vc*v*sul else: vv=sua+1.0/uc*u*sul uv=sva+1.0/vc*v*svl uv2=sva+1.0/uc*u*svl vv2=sua+1.0/vc*v*sul # try: sweep=face.TypeId=='Part::Sweep' # except: sweep=True # # sweep=True if 1 or ( mapobj.flipuv23 and upmode): # print "---------------------------RRRRRRRRRRRRRRRRRRR" # x=uv2x(vv,uv) # y=uv2y(vv,uv) ## uv=sua+1.0/uc*(uc-u)*sul uv=sua+1.0/uc*(u)*sul ## vv=sva+1.0/vc*(vc-v)*svl vv=sva+1.0/vc*(v)*svl x=uv2x(uv,vv) y=uv2y(uv,vv) # x=uv2x(vv,uv) # y=uv2y(vv,uv) else: x=uv2x(uv,vv) y=uv2y(uv,vv) if obj.mode=='curvature': #z=uv2z(uv,vv) # drekt nutzen statt interpolator #z=bs.curvature(vv,uv,"Mean") try: z2=bs.curvature(uv2,vv2,obj.modeCurvature) except: z2=0 if z2<>0:r=round(1.0/z2) else: r='planar' if u>=mapobj.vMin-1 and u<=mapobj.vMax+1 and v>=mapobj.uMin-1 and v<=mapobj.uMax+1: print ("u,v, curvature,radius ",u,v,round(z2,6),r) if abs(z2)>0.001: print ("********** HIGH",u,v,z2,r) z=obj.factorCurvature*z2 else: z=0 #print z # print (x,y,z) pts.append(FreeCAD.Vector(x,y,z)) # if u==5: # print ("aadfdbbw--",uv,vv,z) # print (x,y) ptsa.append(pts) if upmode: print ("Rahmen 3D",obj.uMin,obj.uMax,obj.vMin,obj.vMax) print obj.faceObject.TypeId # try: sweep=obj.faceObject.TypeId=='Part::Sweep' # except: sweep=True # sweep=True if not obj.flipuv23: uMin,uMax,vMin,vMax=obj.uMin,obj.uMax,obj.vMin,obj.vMax else: vMin,vMax,uMin,uMax=obj.uMin,obj.uMax,obj.vMin,obj.vMax relpos=obj.Placement.Base*(-1) comps=[] for pts in ptska[uMin:uMax]: ll=[] for p in pts[vMin:vMax]: pmh=obj.Placement.inverse() vh=FreeCAD.Vector(tuple(p)) th=FreeCAD.Placement() th.Base=vh t2=pmh.multiply(th) vh2=t2.Base ll += [vh2] try: comps += [ Part.makePolygon(ll) ] except: pass ''' comps=[] for pts in ptska[obj.vMin:obj.vMax]: ll=[] for p in pts[obj.uMin:obj.uMax]: pmh=obj.Placement.inverse() vh=FreeCAD.Vector(tuple(p)) th=FreeCAD.Placement() th.Base=vh t2=pmh.multiply(th) vh2=t2.Base ll += [vh2] comps += [ Part.makePolygon(ll) ] ''' ptska=np.array(ptska).swapaxes(0,1) for pts in ptska[vMin:vMax]: ll=[] for p in pts[uMin:uMax]: pmh=obj.Placement.inverse() vh=FreeCAD.Vector(tuple(p)) th=FreeCAD.Placement() th.Base=vh t2=pmh.multiply(th) vh2=t2.Base ll += [vh2] comps += [ Part.makePolygon(ll) ] # markiere zentrum der karte z=bs.value(sua+0.5*sul,sva+0.5*svl) circ=Part.Circle() circ.Radius=10 th=FreeCAD.Placement() th.Base=z t2=pmh.multiply(th) circ.Location=t2.Base th=FreeCAD.Placement() th.Base=bs.normal(sua+0.5*sul,sva+0.5*svl) t2=pmh.multiply(th) circ.Axis=t2.Base if obj.displayCircles: comps += [circ.toShape()] # mapcenter z=bs.value(mpu,mpv) z=bs.value(mpv,mpu) circ=Part.Circle() circ.Radius=20 th=FreeCAD.Placement() th.Base=z t2=pmh.multiply(th) circ.Location=t2.Base th=FreeCAD.Placement() th.Base=bs.normal(mpv,mpu) t2=th.multiply(pmh) # t2=pmh.multiply(th) # diese richtung stimmt noch nicht, deaktivert ## circ.Axis=t2.Base if obj.displayCircles: comps += [circ.toShape()] return Part.Compound(comps) else: # 2d mode comps=[] # markiere zentrum der karte uv=sua+0.5*sul vm=sva+0.5*svl ky=ba.length(vm,mpv) if vm<mpv: ky =-ky kx=bbc.length(mpu,uv) if uv<mpu: kx =-kx if not obj.flipxy: z=FreeCAD.Vector(fy*ky,fx*kx,0) else: z=FreeCAD.Vector(fx*kx,fy*ky,0) circ=Part.Circle() circ.Radius=10 circ.Location=z if obj.displayCircles: comps += [circ.toShape()] z=FreeCAD.Vector(0,0,0) circ=Part.Circle() circ.Radius=20 circ.Location=z if obj.displayCircles: comps += [circ.toShape()] print ("Rahmen 2D",obj.uMin,obj.uMax,obj.vMin,obj.vMax) if obj.flipxy: if 1: for pts in ptsa[obj.uMin:obj.uMax]: try: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[1],fy*p[0],fz*p[2]) for p in pts[obj.vMin:obj.vMax]]) ] except: pass ptsa=np.array(ptsa).swapaxes(0,1) for pts in ptsa[obj.vMin:obj.vMax]: try: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[1],fy*p[0],fz*p[2]) for p in pts[obj.uMin:obj.uMax]]) ] except: pass else : if 1: for pts in ptsa[obj.uMin:obj.uMax]: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[0],fy*p[1],fz*p[2]) for p in pts[obj.vMin:obj.vMax]]) ] ptsa=np.array(ptsa).swapaxes(0,1) for pts in ptsa[obj.vMin:obj.vMax]: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[0],fy*p[1],fz*p[2]) for p in pts[obj.uMin:obj.uMax]]) ] else: for pts in ptsa[obj.vMin:obj.vMax]: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[0],fy*p[1],fz*p[2]) for p in pts[obj.vMin:obj.vMax]]) ] ptsa=np.array(ptsa).swapaxes(0,1) for pts in ptsa[obj.uMin:obj.uMax]: comps += [ Part.makePolygon([FreeCAD.Vector(fx*p[0],fy*p[1],fz*p[2]) for p in pts[obj.uMin:obj.uMax]]) ] return Part.Compound(comps)
def createAll(mode="all",obj=None,dimU=500,dimV=500, ua=10,sizeU=100,va=10,sizeV=100, socketheight=10,saxonyflag=True,rowselector='',center=False,scale=1, createpart=False,createsurface=True ): # obj=App.ActiveDocument.Points print obj.Points.BoundBox.Center # center=False if center: zmin=obj.Points.BoundBox.ZMin -obj.Points.BoundBox.Center.z zmax=obj.Points.BoundBox.ZMax -obj.Points.BoundBox.Center.z else: zmin=obj.Points.BoundBox.ZMin zmax=obj.Points.BoundBox.ZMax p=obj.Points.Points if center: p=np.array(obj.Points.Points)- obj.Points.BoundBox.Center assert dimU*dimV==len(p) # if mode<>"all": # return zmin *=scale zmax *=scale socketheight *= scale p=[pp*scale for pp in p] pa2=np.array(p).reshape(dimU,dimV,3) # pa3=[] # a=0 # for i in range(dimU): # if pa2[i][0][0]<>a: # pa3 += [pa2[i]] # print pa2[i][0][0]-a # # print pa2[i][0] # a= pa2[i][0][0] # andere variante if saxonyflag: pa3=[] pmin=[] pmax=[] for i in range(dimU): if i%4==1: pmin += [pa2[i]] if i%4==3: pmax += [pa2[i]] if i%2==0: pa3 += [pa2[i]] else: p3=p2 pa4=np.array(pa3) pa4.shape if 0: # auswertung der anderen baender pmin=np.array(pmin) print pmin.shape pmax=np.array(pmax) print pmax.shape comp=[] for i in range(124): for j in range(500): if i<4 and j<4: print [pmin[i+1],j,pmax[i,j]] a=FreeCAD.Vector(pmin[i+1,j]) b=FreeCAD.Vector(pmax[i,j]) if a<>b: if b.z<a.z: a,b=b,a comp += [ Part.makePolygon([a,a+(b-a)*10])] print len(comp) Part.show(Part.Compound(comp)) # return if 0: ta=time.time() ss=PointarrayToMesh(pa4[60:70,60:70]) siz=10 tb=time.time() bc=Part.BSplineSurface() bc.interpolate(pa4[100:100+siz,100:100+2*siz]) tc=time.time() Part.show(bc.toShape()) td=time.time() tc-tb td-tc #ss=PointarrayToMesh(pa4) if mode=='mesh': ta=time.time() if 0: ss=PointarrayToMesh(pa4,h=zmax) ss=PointarrayToMesh(pa4,h=zmin) tb=time.time() print "create meshes all", tb-ta ta=time.time() #ss=PointarrayToMesh(pa4) if 1: print ("!",zmax,zmin,socketheight) # ss=PointarrayToMesh(pa4[ua:ua+sizeU,va:va+2*sizeV],h=zmax+socketheight) ss=PointarrayToMesh(pa4[ua:ua+sizeU,va:va+2*sizeV],h=zmin-socketheight) tb=time.time() print "create meshes sub ", tb-ta #return # if not createsurface: return if mode=='part' or mode=='nurbs': #create nurbs face tb=time.time() bs=machFlaeche(pa4[ua:ua+sizeU,va:va+2*sizeV]) tc=time.time() print "create surf 200 x 200 ", tc-tb if 0: tb=time.time() bs=machFlaeche(pa4,degree=3) tc=time.time() print "create surf all ", tc-tb # if not createpart: return if not mode=='part': return #create side faces ff=App.ActiveDocument.ActiveObject be=[] faces=[ff.Shape.Face1] for i,e in enumerate(ff.Shape.Face1.Edges): print e pa=e.Vertexes[0].Point pe=e.Vertexes[-1].Point h=zmin-socketheight pau=FreeCAD.Vector(pa.x,pa.y,h) peu=FreeCAD.Vector(pe.x,pe.y,h) e2=Part.makePolygon([pa,pau]) e3=Part.makePolygon([peu,pe]) e4=Part.makePolygon([pau,peu]) # Part.show(e2) # Part.show(e3) Part.show(e4) App.activeDocument().recompute() eA=App.ActiveDocument.ActiveObject if i%2==0: be += [eA] Part.show(e) App.activeDocument().recompute() eB=App.ActiveDocument.ActiveObject rf=FreeCAD.ActiveDocument.addObject('Part::RuledSurface', 'Ruled Surface') rf.Curve1=(eA,['Edge1']) rf.Curve2=(eB,['Edge1']) App.activeDocument().recompute() faces += [rf.Shape.Face1] # create bottom face rf=FreeCAD.ActiveDocument.addObject('Part::RuledSurface', 'Ruled Surface') rf.Curve1=(be[0],['Edge1']) rf.Curve2=(be[1],['Edge1']) App.activeDocument().recompute() faces += [rf.Shape.Face1] #create shell and solid _=Part.Shell(faces) sh=App.ActiveDocument.addObject('Part::Feature','Shell2') sh.Shape=_.removeSplitter() del _ App.activeDocument().recompute() shell=sh.Shape _=Part.Solid(shell) App.ActiveDocument.addObject('Part::Feature','Solid').Shape=_.removeSplitter() del _ App.activeDocument().recompute() tc=time.time() # toUVMesh(bs) tc-tb
def _build_spline_sections(spline, sketch, interval): """ Generate / regenerate the loft along a spline path """ #reference spline curve object curve = spline.Shape.Curve #return first / last parameters [_a, _b] = spline.Shape.ParameterRange #round the length up and add one length = int(round(_b)) + 1 comps = [] z_up = App.Vector(0, 0, 1) #iterate the range of the length as integers i = 0.0 step = 304.8 * interval sketch_points = [] for vtx in sketch.Shape.Vertexes: sketch_points.append(vtx.Point) is_last_section = False while i <= length: #get the coordinate of the sweep path at the first millimeter origin = curve.value(i) #get the tangent of the sweep path at that coordinate tangent = curve.tangent(i)[0] #calculate the normal against z-up and normalize x_normal = tangent.cross(z_up).normalize() z_normal = tangent.cross(x_normal).normalize() #z-coordinate should always be positive if z_normal.z < 0.0: z_normal = z_normal.negative() poly_points = [] for point in sketch_points: poly_points.append(origin + (point.x * x_normal) + (point.y * z_normal)) poly_points.append(origin) #generate a polygon of the points and save it comps += [Part.makePolygon(poly_points)] i += step if i > length: if not is_last_section: i = length is_last_section = True return comps
def createMeshView(obj, direction=FreeCAD.Vector(0, 0, -1), outeronly=False, largestonly=False): """createMeshView(obj,[direction,outeronly,largestonly]): creates a flat shape that is the projection of the given mesh object in the given direction (default = on the XY plane). If outeronly is True, only the outer contour is taken into consideration, discarding the inner holes. If largestonly is True, only the largest segment of the given mesh will be used.""" import Mesh, math, Part, DraftGeomUtils if not obj.isDerivedFrom("Mesh::Feature"): return mesh = obj.Mesh # 1. Flattening the mesh proj = [] for f in mesh.Facets: nf = [] for v in f.Points: v = FreeCAD.Vector(v) a = v.negative().getAngle(direction) l = math.cos(a) * v.Length p = v.add(FreeCAD.Vector(direction).multiply(l)) p = DraftVecUtils.rounded(p) nf.append(p) proj.append(nf) flatmesh = Mesh.Mesh(proj) # 2. Removing wrong faces facets = [] for f in flatmesh.Facets: if f.Normal.getAngle(direction) < math.pi: facets.append(f) cleanmesh = Mesh.Mesh(facets) #Mesh.show(cleanmesh) # 3. Getting the bigger mesh from the planar segments if largestonly: c = cleanmesh.getSeparateComponents() #print(c) cleanmesh = c[0] segs = cleanmesh.getPlanarSegments(1) meshes = [] for s in segs: f = [cleanmesh.Facets[i] for i in s] meshes.append(Mesh.Mesh(f)) a = 0 for m in meshes: if m.Area > a: boundarymesh = m a = m.Area #Mesh.show(boundarymesh) cleanmesh = boundarymesh # 4. Creating a Part and getting the contour shape = None for f in cleanmesh.Facets: p = Part.makePolygon(f.Points + [f.Points[0]]) #print(p,len(p.Vertexes),p.isClosed()) try: p = Part.Face(p) if shape: shape = shape.fuse(p) else: shape = p except Part.OCCError: pass shape = shape.removeSplitter() # 5. Extracting the largest wire if outeronly: count = 0 largest = None for w in shape.Wires: if len(w.Vertexes) > count: count = len(w.Vertexes) largest = w if largest: try: f = Part.Face(w) except Part.OCCError: print("Unable to produce a face from the outer wire.") else: shape = f return shape
def map3Dgridto2Dgrid(): # 3D Edges auf 2D Edges s0=Gui.Selection.getSelection() base=s0[-1] if hasattr(base,"faceObject"): face=base.faceObject mapobj=base else: face=base mapobj=None s=s0[:-1] if len(s0)==1: s=s0 print s0 polcol=[] for wire in s: print wire.Label [uv2x,uv2y,xy2u,xy2v]=getmap(mapobj,face) # bs=face.Shape.Face1.Surface bs=face.Shape.Faces[base.faceNumber].Surface pts2=[] firstEdge=True n=0 for e in wire.Shape.Edges: #print e n +=1 # if n>6: break # auf 5 millimeter genau if mapobj<>None: dd=mapobj.pointsPerEdge else: dd=int(round(e.Length/5)) dd=30 dd=3 ptsa=e.discretize(dd) #if not firstEdge: # pts=ptsa[1:] #else: pts=ptsa firstEdge=False FreeCAD.ptsaa=pts ptsb=[] for p in pts: # (u,v)=bs.parameter(p) (v,u)=bs.parameter(p) # print "hack A su sv aa bb" # su=face.Shape.Face1.ParameterRange[1] # sv=face.Shape.Face1.ParameterRange[3] # # if su>1000: su=face.ParameterRange[1] # if sv>1000: sv=face.ParameterRange[3] sua=face.ParameterRange[0] sva=face.ParameterRange[2] sue=face.ParameterRange[1] sve=face.ParameterRange[3] sul=sue-sua svl=sve-sva v=(v-sva)/svl u=(u-sua)/sul x=uv2x(u,v) y=uv2y(u,v) if mapobj<>None and mapobj.flipxy: p2=FreeCAD.Vector(y,x,0) else: p2=FreeCAD.Vector(-y,-x,0) # hack richgtung beim Schuh p2=FreeCAD.Vector(y,x,0) ptsb.append(p2) if len(ptsb)>1: try: polcol += [Part.makePolygon(ptsb)] except: print "kann kein polygon bauen" print ptsb #Draft.makeWire(pts2) Part.show(Part.Compound(polcol))
def makeSolarDiagram(longitude, latitude, scale=1, complete=False, tz=None): """makeSolarDiagram(longitude,latitude,[scale,complete,tz]): returns a solar diagram as a pivy node. If complete is True, the 12 months are drawn. Tz is the timezone related to UTC (ex: -3 = UTC-3)""" oldversion = False try: import pysolar except: try: import Pysolar as pysolar except: FreeCAD.Console.PrintError( "The pysolar module was not found. Unable to generate solar diagrams\n" ) return None else: oldversion = True from pivy import coin if not scale: return None if tz: tz = datetime.timezone(datetime.timedelta(hours=-3)) else: tz = datetime.timezone.utc def toNode(shape): "builds a pivy node from a simple linear shape" from pivy import coin buf = shape.writeInventor(2, 0.01) buf = buf.replace("\n", "") pts = re.findall("point \[(.*?)\]", buf)[0] pts = pts.split(",") pc = [] for p in pts: v = p.strip().split() pc.append([float(v[0]), float(v[1]), float(v[2])]) coords = coin.SoCoordinate3() coords.point.setValues(0, len(pc), pc) line = coin.SoLineSet() line.numVertices.setValue(-1) item = coin.SoSeparator() item.addChild(coords) item.addChild(line) return item circles = [] sunpaths = [] hourpaths = [] circlepos = [] hourpos = [] # build the base circle + number positions import Part for i in range(1, 9): circles.append(Part.makeCircle(scale * (i / 8.0))) for ad in range(0, 360, 15): a = math.radians(ad) p1 = FreeCAD.Vector(math.cos(a) * scale, math.sin(a) * scale, 0) p2 = FreeCAD.Vector( math.cos(a) * scale * 0.125, math.sin(a) * scale * 0.125, 0) p3 = FreeCAD.Vector( math.cos(a) * scale * 1.08, math.sin(a) * scale * 1.08, 0) circles.append(Part.LineSegment(p1, p2).toShape()) circlepos.append((ad, p3)) # build the sun curves at solstices and equinoxe year = datetime.datetime.now().year hpts = [[] for i in range(24)] m = [(6, 21), (7, 21), (8, 21), (9, 21), (10, 21), (11, 21), (12, 21)] if complete: m.extend([(1, 21), (2, 21), (3, 21), (4, 21), (5, 21)]) for i, d in enumerate(m): pts = [] for h in range(24): if oldversion: dt = datetime.datetime(year, d[0], d[1], h) alt = math.radians( pysolar.solar.GetAltitudeFast(latitude, longitude, dt)) az = pysolar.solar.GetAzimuth(latitude, longitude, dt) az = -90 + az # pysolar's zero is south, ours is X direction else: dt = datetime.datetime(year, d[0], d[1], h, tzinfo=tz) alt = math.radians( pysolar.solar.get_altitude_fast(latitude, longitude, dt)) az = pysolar.solar.get_azimuth(latitude, longitude, dt) az = 90 + az # pysolar's zero is north, ours is X direction if az < 0: az = 360 + az az = math.radians(az) zc = math.sin(alt) * scale ic = math.cos(alt) * scale xc = math.cos(az) * ic yc = math.sin(az) * ic p = FreeCAD.Vector(xc, yc, zc) pts.append(p) hpts[h].append(p) if i in [0, 6]: ep = FreeCAD.Vector(p) ep.multiply(1.08) if ep.z >= 0: if not oldversion: h = 24 - h # not sure why this is needed now... But it is. if h == 12: if i == 0: h = "SUMMER" else: h = "WINTER" if latitude < 0: if h == "SUMMER": h = "WINTER" else: h = "SUMMER" hourpos.append((h, ep)) if i < 7: sunpaths.append(Part.makePolygon(pts)) for h in hpts: if complete: h.append(h[0]) hourpaths.append(Part.makePolygon(h)) # cut underground lines sz = 2.1 * scale cube = Part.makeBox(sz, sz, sz) cube.translate(FreeCAD.Vector(-sz / 2, -sz / 2, -sz)) sunpaths = [sp.cut(cube) for sp in sunpaths] hourpaths = [hp.cut(cube) for hp in hourpaths] # build nodes ts = 0.005 * scale # text scale mastersep = coin.SoSeparator() circlesep = coin.SoSeparator() numsep = coin.SoSeparator() pathsep = coin.SoSeparator() hoursep = coin.SoSeparator() hournumsep = coin.SoSeparator() mastersep.addChild(circlesep) mastersep.addChild(numsep) mastersep.addChild(pathsep) mastersep.addChild(hoursep) for item in circles: circlesep.addChild(toNode(item)) for item in sunpaths: for w in item.Edges: pathsep.addChild(toNode(w)) for item in hourpaths: for w in item.Edges: hoursep.addChild(toNode(w)) for p in circlepos: text = coin.SoText2() s = p[0] - 90 s = -s if s > 360: s = s - 360 if s < 0: s = 360 + s if s == 0: s = "N" elif s == 90: s = "E" elif s == 180: s = "S" elif s == 270: s = "W" else: s = str(s) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) for p in hourpos: text = coin.SoText2() s = str(p[0]) text.string = s text.justification = coin.SoText2.CENTER coords = coin.SoTransform() coords.translation.setValue([p[1].x, p[1].y, p[1].z]) coords.scaleFactor.setValue([ts, ts, ts]) item = coin.SoSeparator() item.addChild(coords) item.addChild(text) numsep.addChild(item) return mastersep
def createGeometry(self,obj): import Part, DraftGeomUtils # getting default values height = width = length = 1 if hasattr(obj,"Length"): if obj.Length: length = obj.Length if hasattr(obj,"Width"): if obj.Width: width = obj.Width if hasattr(obj,"Height"): if obj.Height: height = obj.Height # creating base shape pl = obj.Placement base = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Normal == Vector(0,0,0): p = FreeCAD.Placement(obj.Base.Placement) normal = p.Rotation.multVec(Vector(0,0,1)) else: normal = Vector(obj.Normal) normal = normal.multiply(height) base = obj.Base.Shape.copy() if base.Solids: pass elif base.Faces: base = base.extrude(normal) elif (len(base.Wires) == 1): if base.Wires[0].isClosed(): base = Part.Face(base.Wires[0]) base = base.extrude(normal) else: if obj.Normal == Vector(0,0,0): normal = Vector(0,0,1) else: normal = Vector(obj.Normal) normal = normal.multiply(height) l2 = length/2 or 0.5 w2 = width/2 or 0.5 v1 = Vector(-l2,-w2,0) v2 = Vector(l2,-w2,0) v3 = Vector(l2,w2,0) v4 = Vector(-l2,w2,0) base = Part.makePolygon([v1,v2,v3,v4,v1]) base = Part.Face(base) base = base.extrude(normal) if base: # applying adds and subs if not base.isNull(): for app in obj.Additions: if hasattr(app,"Shape"): if not app.Shape.isNull(): base = base.fuse(app.Shape) app.ViewObject.hide() # to be removed for hole in obj.Subtractions: if hasattr(hole,"Shape"): if not hole.Shape.isNull(): base = base.cut(hole.Shape) hole.ViewObject.hide() # to be removed pts = self.getAxisPoints(obj) if pts: fsh = [] for p in pts: sh = base.copy() sh.translate(p) fsh.append(sh) obj.Shape = Part.makeCompound(fsh) else: if base: if not base.isNull(): base = base.removeSplitter() obj.Shape = base if not DraftGeomUtils.isNull(pl): obj.Placement = pl
LEidx = int(.1 * xDisc) #chord point index included in LE refinement extradosLine = [] intradosLine = [] LELines = [] TELines = [] print("Creating stations") for i in geom: if i[4] == 'cylinder': extradosPts = profil(float(i[3]), i[4], float(i[5]), "extrados", 1 / 1000.) intradosPts = profil(float(i[3]), i[4], float(i[5]), "intrados", 1 / 1000.) else: extradosPts = profil(float(i[3]), i[4], float(i[5]), "extrados", TEGap) intradosPts = profil(float(i[3]), i[4], float(i[5]), "intrados", TEGap) extradosLineOrig = Part.makePolygon( [Base.Vector(x[0], x[1], float(i[1])) for x in extradosPts]) intradosLineOrig = Part.makePolygon( [Base.Vector(x[0], x[1], float(i[1])) for x in intradosPts]) extradosLineOrig.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), float(i[2]) + pitch - 90) intradosLineOrig.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), float(i[2]) + pitch - 90) extradosPtsInterp = numpy.array(extradosLineOrig.discretize(xDisc)) intradosPtsInterp = numpy.array(intradosLineOrig.discretize(xDisc)) extradosInterp = Part.makePolygon( [Base.Vector(x[0], x[1], x[2]) for x in extradosPtsInterp]) intradosInterp = Part.makePolygon( [Base.Vector(x[0], x[1], x[2]) for x in intradosPtsInterp]) extradosLine.append(extradosInterp) intradosLine.append(intradosInterp) LELines.append(
def alignToSelection(self, offset=0): """Align the plane to a selection if it defines a plane. If the selection uniquely defines a plane it will be used. Parameter --------- offset : float Defaults to zero. A value which will be used to offset the plane in the direction of its `axis`. Returns ------- bool `True` if the operation was successful, and `False` otherwise. It returns `False` if the selection has no elements, or if the object is not derived from `'Part::Feature'` or if the object doesn't have a `Shape`. See Also -------- alignToFace, alignToCurve """ sel_ex = FreeCADGui.Selection.getSelectionEx( FreeCAD.ActiveDocument.Name) if not sel_ex: return False shapes = list() names = list() for obj in sel_ex: # check that the geometric property is a Part.Shape object geom_is_shape = False if isinstance(obj.Object, FreeCAD.GeoFeature): geom = obj.Object.getPropertyOfGeometry() if isinstance(geom, Part.Shape): geom_is_shape = True if not geom_is_shape: FreeCAD.Console.PrintError( translate( "draft", "Object without Part.Shape geometry:'{}'\n".format( obj.ObjectName))) return False if geom.isNull(): FreeCAD.Console.PrintError( translate( "draft", "Object with null Part.Shape geometry:'{}'\n".format( obj.ObjectName))) return False if obj.HasSubObjects: shapes.extend(obj.SubObjects) names.extend( [obj.ObjectName + "." + n for n in obj.SubElementNames]) else: shapes.append(geom) names.append(obj.ObjectName) normal = None for n in range(len(shapes)): if not DraftGeomUtils.is_planar(shapes[n]): FreeCAD.Console.PrintError( translate("draft", "'{}' object is not planar\n".format(names[n]))) return False if not normal: normal = DraftGeomUtils.get_normal(shapes[n]) shape_ref = n # test if all shapes are coplanar if normal: for n in range(len(shapes)): if not DraftGeomUtils.are_coplanar(shapes[shape_ref], shapes[n]): FreeCAD.Console.PrintError( translate( "draft", "{} and {} aren't coplanar\n".format( names[shape_ref], names[n]))) return False else: # suppose all geometries are straight lines or points points = [ vertex.Point for shape in shapes for vertex in shape.Vertexes ] if len(points) >= 3: poly = Part.makePolygon(points) if not DraftGeomUtils.is_planar(poly): FreeCAD.Console.PrintError( translate("draft", "All Shapes must be coplanar\n")) return False normal = DraftGeomUtils.get_normal(poly) else: normal = None if not normal: FreeCAD.Console.PrintError( translate("draft", "Selected Shapes must define a plane\n")) return False # set center of mass ctr_mass = FreeCAD.Vector(0, 0, 0) ctr_pts = FreeCAD.Vector(0, 0, 0) mass = 0 for shape in shapes: if hasattr(shape, "CenterOfMass"): ctr_mass += shape.CenterOfMass * shape.Mass mass += shape.Mass else: ctr_pts += shape.Point if mass > 0: ctr_mass /= mass # all shapes are vertexes else: ctr_mass = ctr_pts / len(shapes) self.alignToPointAndAxis(ctr_mass, normal, offset) return True
def getProfiles(self, obj, noplacement=False): "Returns the base profile(s) of this component, if applicable" wires = [] n, l, w, h = self.getDefaultValues(obj) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: base = obj.Base.Shape.copy() if noplacement: base.Placement = FreeCAD.Placement() if not base.Solids: if base.Faces: return [base] basewires = [] if not base.Wires: if len(base.Edges) == 1: import Part basewires = [Part.Wire(base.Edges)] else: basewires = base.Wires if basewires: import DraftGeomUtils, DraftVecUtils, Part for wire in basewires: e = wire.Edges[0] if isinstance(e.Curve, Part.Circle): dvec = e.Vertexes[0].Point.sub( e.Curve.Center) else: dvec = DraftGeomUtils.vec( wire.Edges[0]).cross(n) if not DraftVecUtils.isNull(dvec): dvec.normalize() sh = None if hasattr(obj, "Align"): if obj.Align == "Left": dvec.multiply(w) if hasattr(obj, "Offset"): if obj.Offset.Value: dvec2 = DraftVecUtils.scaleTo( dvec, obj.Offset.Value) wire = DraftGeomUtils.offsetWire( wire, dvec2) w2 = DraftGeomUtils.offsetWire( wire, dvec) w1 = Part.Wire( DraftGeomUtils.sortEdges( wire.Edges)) sh = DraftGeomUtils.bind(w1, w2) elif obj.Align == "Right": dvec.multiply(w) dvec = dvec.negative() if hasattr(obj, "Offset"): if obj.Offset.Value: dvec2 = DraftVecUtils.scaleTo( dvec, obj.Offset.Value) wire = DraftGeomUtils.offsetWire( wire, dvec2) w2 = DraftGeomUtils.offsetWire( wire, dvec) w1 = Part.Wire( DraftGeomUtils.sortEdges( wire.Edges)) sh = DraftGeomUtils.bind(w1, w2) elif obj.Align == "Center": dvec.multiply(w / 2) w1 = DraftGeomUtils.offsetWire( wire, dvec) dvec = dvec.negative() w2 = DraftGeomUtils.offsetWire( wire, dvec) sh = DraftGeomUtils.bind(w1, w2) if sh: wires.append(sh) else: wires.append(wire) else: if (Draft.getType(obj) == "Structure") and (l > h): if noplacement: h2 = h / 2 or 0.5 w2 = w / 2 or 0.5 v1 = Vector(-h2, -w2, 0) v2 = Vector(h2, -w2, 0) v3 = Vector(h2, w2, 0) v4 = Vector(-h2, w2, 0) else: h2 = h / 2 or 0.5 w2 = w / 2 or 0.5 v1 = Vector(0, -w2, -h2) v2 = Vector(0, -w2, h2) v3 = Vector(0, w2, h2) v4 = Vector(0, w2, -h2) else: l2 = l / 2 or 0.5 w2 = w / 2 or 0.5 v1 = Vector(-l2, -w2, 0) v2 = Vector(l2, -w2, 0) v3 = Vector(l2, w2, 0) v4 = Vector(-l2, w2, 0) import Part base = Part.makePolygon([v1, v2, v3, v4, v1]) return [base] return wires
def makePolygon(cls, listOfVertices, forConstruction=False): # convert list of tuples into Vectors. w = Wire(FreeCADPart.makePolygon([i.wrapped for i in listOfVertices])) w.forConstruction = forConstruction return w
def helix2(points): # гвинтова лінія з відхиленнями pts = [(x, y, z) for t, x, y, z in points] h = Part.makePolygon(pts) return h
def runB(): ''' testcase for a expression baes mountain profile ''' import numpy as np print "WARNING:this is a testcase only" # hard coded test data kl = App.ActiveDocument.subedge kr = App.ActiveDocument.subedge001 kali = kl.Shape.Edge1.Curve.getPoles() kare = kr.Shape.Edge1.Curve.getPoles() lena = len(kali) l0 = (kali[0] - kare[0]).Length scales = [(kali[i] - kare[i]).Length / l0 for i in range(lena)] rots = [0.0] + [(kali[i] - kare[i]).normalize().cross( (kali[0] - kare[0]).normalize()).dot(FreeCAD.Vector(0, 0, 1)) for i in range(1, lena)] rots = np.arcsin(rots) apts = [] for i in range(lena): yy = (kare[0] - kali[0]) * scales[i] polyp = [ FreeCAD.Vector(), FreeCAD.Vector(0, 0, 115), FreeCAD.Vector(0, 0, 130), ((kare[0] - kali[0]) * 0.3 + FreeCAD.Vector(0, 0, 200)) * scales[i], ((kare[0] - kali[0]) * 0.3 + FreeCAD.Vector(0, 0, 200)) * scales[i] + FreeCAD.Vector(40, 0, 0), ((kare[0] - kali[0]) * 0.3 + FreeCAD.Vector(0, 0, 200)) * scales[i] + FreeCAD.Vector(80, 0, 0), yy + FreeCAD.Vector(0, 0, 50), yy + FreeCAD.Vector(0, 0, 25), yy + FreeCAD.Vector(), ] pol = Part.makePolygon(polyp) if 1: # display the control points polygons res = App.ActiveDocument.addObject("Part::Spline", "aa" + str(i) + "__") res.Shape = pol res.Placement = FreeCAD.Placement( kali[i], FreeCAD.Rotation()).multiply( FreeCAD.Placement( FreeCAD.Vector(), FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), -180.0 * rots[i] / np.pi))) # print kali[i] # print rots[i] # print scales[i] pts = [v.Point for v in res.Shape.Vertexes] apts += [pts] machFlaeche(np.array(apts)) # display the controlpoint curves bpts = np.array(apts).swapaxes(0, 1) for l in bpts: machkurve(l)
def makeStraightLanding(self, obj, edge, numberofsteps=None): "builds a landing from a straight edge" # general data if not numberofsteps: numberofsteps = obj.NumberOfSteps import Part, DraftGeomUtils v = DraftGeomUtils.vec(edge) vLength = Vector(v.x, v.y, 0) vWidth = vWidth = DraftVecUtils.scaleTo(vLength.cross(Vector(0, 0, 1)), obj.Width.Value) vBase = edge.Vertexes[0].Point vNose = DraftVecUtils.scaleTo(vLength, -abs(obj.Nosing.Value)) h = obj.Height.Value l = obj.Length.Value if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): l = obj.Base.Shape.Length if obj.Base.Shape.BoundBox.ZLength: h = obj.Base.Shape.BoundBox.ZLength fLength = float(l - obj.Width.Value) / (numberofsteps - 2) fHeight = float(h) / numberofsteps a = math.atan(fHeight / fLength) print("landing data:", fLength, ":", fHeight) # step p1 = self.align(vBase, obj.Align, vWidth) p1 = p1.add(vNose).add(Vector(0, 0, -abs(obj.TreadThickness.Value))) p2 = p1.add(DraftVecUtils.neg(vNose)).add(vLength) p3 = p2.add(vWidth) p4 = p3.add(DraftVecUtils.neg(vLength)).add(vNose) step = Part.Face(Part.makePolygon([p1, p2, p3, p4, p1])) if obj.TreadThickness.Value: step = step.extrude(Vector(0, 0, abs(obj.TreadThickness.Value))) self.steps.append(step) else: self.pseudosteps.append(step) # structure lProfile = [] struct = None p7 = None p1 = p1.add(DraftVecUtils.neg(vNose)) p2 = p1.add(Vector(0, 0, -fHeight)).add( Vector(0, 0, -obj.StructureThickness.Value / math.cos(a))) resheight = p1.sub(p2).Length - obj.StructureThickness.Value reslength = resheight / math.tan(a) p3 = p2.add(DraftVecUtils.scaleTo(vLength, reslength)).add( Vector(0, 0, resheight)) p6 = p1.add(vLength) if obj.TreadThickness.Value: p7 = p6.add(Vector(0, 0, obj.TreadThickness.Value)) reslength = fLength + ( obj.StructureThickness.Value / math.sin(a) - (fHeight - obj.TreadThickness.Value) / math.tan(a)) if p7: p5 = p7.add(DraftVecUtils.scaleTo(vLength, reslength)) else: p5 = p6.add(DraftVecUtils.scaleTo(vLength, reslength)) resheight = obj.StructureThickness.Value + obj.TreadThickness.Value reslength = resheight / math.tan(a) p4 = p5.add(DraftVecUtils.scaleTo(vLength, -reslength)).add( Vector(0, 0, -resheight)) if obj.Structure == "Massive": if obj.StructureThickness.Value: if p7: struct = Part.Face( Part.makePolygon([p1, p2, p3, p4, p5, p7, p6, p1])) else: struct = Part.Face( Part.makePolygon([p1, p2, p3, p4, p5, p6, p1])) evec = vWidth if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) struct.translate(mvec) evec = DraftVecUtils.scaleTo( evec, evec.Length - (2 * mvec.Length)) struct = struct.extrude(evec) elif obj.Structure in ["One stringer", "Two stringers"]: if obj.StringerWidth.Value and obj.StructureThickness.Value: p1b = p1.add(Vector(0, 0, -fHeight)) reslength = fHeight / math.tan(a) p1c = p1.add(DraftVecUtils.scaleTo(vLength, reslength)) p5b = None p5c = None if obj.TreadThickness.Value: reslength = obj.StructureThickness.Value / math.sin(a) p5b = p5.add(DraftVecUtils.scaleTo(vLength, -reslength)) reslength = obj.TreadThickness.Value / math.tan(a) p5c = p5b.add(DraftVecUtils.scaleTo( vLength, -reslength)).add( Vector(0, 0, -obj.TreadThickness.Value)) pol = Part.Face( Part.makePolygon( [p1c, p1b, p2, p3, p4, p5, p5b, p5c, p1c])) else: pol = Part.Face( Part.makePolygon([p1c, p1b, p2, p3, p4, p5, p1c])) evec = DraftVecUtils.scaleTo(vWidth, obj.StringerWidth.Value) if obj.Structure == "One stringer": if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) else: mvec = DraftVecUtils.scaleTo( vWidth, (vWidth.Length / 2) - obj.StringerWidth.Value / 2) pol.translate(mvec) struct = pol.extrude(evec) elif obj.Structure == "Two stringers": pol2 = pol.copy() if obj.StructureOffset.Value: mvec = DraftVecUtils.scaleTo(vWidth, obj.StructureOffset.Value) pol.translate(mvec) mvec = vWidth.add(mvec.negative()) pol2.translate(mvec) else: pol2.translate(vWidth) s1 = pol.extrude(evec) s2 = pol2.extrude(evec.negative()) struct = Part.makeCompound([s1, s2]) if struct: self.structures.append(struct)