def makeFlatFace(mobile=[], fixed=[], vert=False): import Part import DraftVecUtils import DraftGeomUtils if not fixed: pol = Part.makePolygon(mobile + [mobile[0]]) pol = DraftGeomUtils.flattenWire(pol) return Part.Face(pol) elif len(fixed) == 3: tempf = Part.Face(Part.makePolygon(fixed + [fixed[0]])) v4 = mobile[0].add( DraftVecUtils.project(tempf.CenterOfMass.sub(mobile[0]), tempf.normalAt(0, 0))) pol = Part.makePolygon([fixed[0], fixed[1], v4, fixed[2], fixed[0]]) pol = DraftGeomUtils.flattenWire(pol) return Part.Face(pol) elif len(fixed) == 2: tp = DraftGeomUtils.findMidpoint( Part.LineSegment(mobile[0], mobile[1]).toShape()) tempf = Part.Face(Part.makePolygon(fixed + [tp, fixed[0]])) v4 = mobile[0].add( DraftVecUtils.project(tempf.CenterOfMass.sub(mobile[0]), tempf.normalAt(0, 0))) v5 = mobile[1].add( DraftVecUtils.project(tempf.CenterOfMass.sub(mobile[1]), tempf.normalAt(0, 0))) if vert: pol = Part.makePolygon([fixed[0], v4, v5, fixed[1], fixed[0]]) else: pol = Part.makePolygon(fixed + [v4, v5, fixed[0]]) pol = DraftGeomUtils.flattenWire(pol) return Part.Face(pol)
def export(exportList, filename): "called when freecad exports a file" faces = [] edges = [] # getting faces and edges for ob in exportList: if ob.Shape.Faces: for f in ob.Shape.Faces: faces.append(f) else: for e in ob.Shape.Edges: edges.append(e) if not (edges or faces): print "oca: found no data to export" return # writing file oca = pythonopen(filename, 'wb') oca.write("#oca file generated from FreeCAD\r\n") oca.write("# edges\r\n") count = 1 for e in edges: if DraftGeomUtils.geomType(e) == "Line": oca.write("L" + str(count) + "=") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) oca.write("\r\n") elif DraftGeomUtils.geomType(e) == "Circle": if (len(e.Vertexes) > 1): oca.write("C" + str(count) + "=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: oca.write("C" + str(count) + "= ") oca.write(writepoint(e.Curve.Center)) oca.write(" ") oca.write(str(e.Curve.Radius)) oca.write("\r\n") count += 1 oca.write("# faces\r\n") for f in faces: oca.write("A" + str(count) + "=S(POL") for v in f.Vertexes: oca.write(" ") oca.write(writepoint(v.Point)) oca.write(" ") oca.write(writepoint(f.Vertexes[0].Point)) oca.write(")\r\n") count += 1 # closing oca.close() FreeCAD.Console.PrintMessage("successfully exported " + filename)
def export(exportList, filename): "called when freecad exports a file" faces = [] edges = [] # getting faces and edges for ob in exportList: if ob.Shape.Faces: for f in ob.Shape.Faces: faces.append(f) else: for e in ob.Shape.Edges: edges.append(e) if not (edges or faces): print "oca: found no data to export" return # writing file oca = pythonopen(filename, "wb") oca.write("#oca file generated from FreeCAD\r\n") oca.write("# edges\r\n") count = 1 for e in edges: if isinstance(e.Curve, Part.Line): oca.write("L" + str(count) + "=") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) oca.write("\r\n") elif isinstance(e.Curve, Part.Circle): if len(e.Vertexes) > 1: oca.write("C" + str(count) + "=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: oca.write("C" + str(count) + "= ") oca.write(writepoint(e.Curve.Center)) oca.write(" ") oca.write(str(e.Curve.Radius)) oca.write("\r\n") count += 1 oca.write("# faces\r\n") for f in faces: oca.write("A" + str(count) + "=S(POL") for v in f.Vertexes: oca.write(" ") oca.write(writepoint(v.Point)) oca.write(" ") oca.write(writepoint(f.Vertexes[0].Point)) oca.write(")\r\n") count += 1 # closing oca.close() FreeCAD.Console.PrintMessage("successfully exported " + filename)
def snapToMidpoint(self,shape): "returns a list of midpoints snap locations" snaps = [] if self.isEnabled("midpoint"): if isinstance(shape,Part.Edge): mp = DraftGeomUtils.findMidpoint(shape) if mp: snaps.append([mp,'midpoint',mp]) return snaps
def snapToMidpoint(self, shape): "returns a list of midpoints snap locations" snaps = [] if self.isEnabled("midpoint"): if isinstance(shape, Part.Edge): mp = DraftGeomUtils.findMidpoint(shape) if mp: snaps.append([mp, 'midpoint', mp]) return snaps
def execute(self, obj): if self.clone(obj): return import Part, math, DraftGeomUtils pl = obj.Placement #self.baseface = None base = None w = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: base = obj.Base.Shape #pl = obj.Base.Placement else: if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = Part.__sortEdges__(w.Edges) l = len(edges) for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for i in range(l): self.calcEdgeGeometry(edges, i) for i in range(l): self.calcDraftEdges(i) for i in range(l): self.calcEave(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): self.getRoofPaneProject(i) profilCurrent = self.findProfil(i) midpoint = DraftGeomUtils.findMidpoint( profilCurrent["edge"]) ptsPaneProject = profilCurrent["points"] lp = len(ptsPaneProject) if lp != 0: ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for p in range(lp): edge = Part.makeLine(ptsPaneProject[p], ptsPaneProject[p + 1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profilCurrent["thickness"] / (math.cos( math.radians(profilCurrent["angle"]))) overhangV = profilCurrent["overhang"] * math.tan( math.radians(profilCurrent["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude( FreeCAD.Vector( 0, 0, profilCurrent["height"] + 1000000.0)) f.translate( FreeCAD.Vector(0.0, 0.0, -2 * overhangV)) ptsPaneProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector( profilCurrent["run"], profilCurrent["height"] + thicknessV, 0.0), FreeCAD.Vector(-profilCurrent["overhang"], -overhangV + thicknessV, 0.0) ] self.shps.append( self.createProfilShape(ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## subVolume shape ptsSubVolumeProfil = [ FreeCAD.Vector(-profilCurrent["overhang"], -overhangV, 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"], 0.0), FreeCAD.Vector(profilCurrent["run"], profilCurrent["height"] + 900000.0, 0.0), FreeCAD.Vector(-profilCurrent["overhang"], profilCurrent["height"] + 900000.0, 0.0) ] self.subVolshps.append( self.createProfilShape(ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) base = self.processSubShapes(obj, base) self.applyShape(obj, base, pl) elif base: base = self.processSubShapes(obj, base) self.applyShape(obj, base, pl) else: FreeCAD.Console.PrintMessage( translate("Arch", "Unable to create a roof"))
def execute(self, obj): if self.clone(obj): return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return pl = obj.Placement if obj.Base.Shape.Solids: obj.Shape = obj.Base.Shape.copy() if not pl.isNull(): obj.Placement = obj.Shape.Placement.multiply(pl) else: if not obj.Profile: return if not obj.Profile.isDerivedFrom("Part::Part2DObject"): return if not obj.Profile.Shape: return if not obj.Profile.Shape.Wires: return if not obj.Profile.Shape.Faces: for w in obj.Profile.Shape.Wires: if not w.isClosed(): return import DraftGeomUtils, Part, math baseprofile = obj.Profile.Shape.copy() if not baseprofile.Faces: f = [] for w in baseprofile.Wires: f.append(Part.Face(w)) if len(f) == 1: baseprofile = f[0] else: baseprofile = Part.makeCompound(f) shapes = [] normal = DraftGeomUtils.getNormal(obj.Base.Shape) #for wire in obj.Base.Shape.Wires: for e in obj.Base.Shape.Edges: #e = wire.Edges[0] bvec = DraftGeomUtils.vec(e) bpoint = e.Vertexes[0].Point profile = baseprofile.copy() #basepoint = profile.Placement.Base if hasattr(obj, "BasePoint"): edges = DraftGeomUtils.sortEdges(profile.Edges) basepointliste = [profile.CenterOfMass] for edge in edges: basepointliste.append( DraftGeomUtils.findMidpoint(edge)) basepointliste.append(edge.Vertexes[-1].Point) try: basepoint = basepointliste[obj.BasePoint] except IndexError: FreeCAD.Console.PrintMessage( translate( "Arch", "Crossing point not found in profile.\n")) basepoint = basepointliste[0] else: basepoint = profile.CenterOfMass profile.translate(bpoint.sub(basepoint)) if obj.Align: axis = profile.Placement.Rotation.multVec( FreeCAD.Vector(0, 0, 1)) angle = bvec.getAngle(axis) if round(angle, Draft.precision()) != 0: if round(angle, Draft.precision()) != round( math.pi, Draft.precision()): rotaxis = axis.cross(bvec) profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle)) if obj.Rotation: profile.rotate( DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation) #profile = wire.makePipeShell([profile],True,False,2) TODO buggy profile = profile.extrude(bvec) if obj.Offset: if not DraftVecUtils.isNull(obj.Offset): profile.translate(obj.Offset) shapes.append(profile) if shapes: obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def execute(self,obj): if self.clone(obj): return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return pl = obj.Placement if obj.Base.Shape.Solids: obj.Shape = obj.Base.Shape.copy() if not pl.isNull(): obj.Placement = obj.Shape.Placement.multiply(pl) else: if not obj.Profile: return if not obj.Profile.isDerivedFrom("Part::Part2DObject"): return if not obj.Profile.Shape: return if not obj.Profile.Shape.Wires: return if not obj.Profile.Shape.Faces: for w in obj.Profile.Shape.Wires: if not w.isClosed(): return import DraftGeomUtils, Part, math baseprofile = obj.Profile.Shape.copy() if hasattr(obj,"ProfilePlacement"): if not obj.ProfilePlacement.isNull(): baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement) if not baseprofile.Faces: f = [] for w in baseprofile.Wires: f.append(Part.Face(w)) if len(f) == 1: baseprofile = f[0] else: baseprofile = Part.makeCompound(f) shapes = [] normal = DraftGeomUtils.getNormal(obj.Base.Shape) #for wire in obj.Base.Shape.Wires: edges = obj.Base.Shape.Edges if hasattr(obj,"Edges"): if obj.Edges == "Vertical edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,1,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] elif obj.Edges == "Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] elif obj.Edges == "Top Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] edges = sorted(edges,key=lambda x: x.CenterOfMass.z,reverse=True) z = edges[0].CenterOfMass.z edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001] elif obj.Edges == "Bottom Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] edges = sorted(edges,key=lambda x: x.CenterOfMass.z) z = edges[0].CenterOfMass.z edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001] for e in edges: #e = wire.Edges[0] bvec = DraftGeomUtils.vec(e) bpoint = e.Vertexes[0].Point profile = baseprofile.copy() #basepoint = profile.Placement.Base if hasattr(obj,"BasePoint"): edges = Part.__sortEdges__(profile.Edges) basepointliste = [profile.CenterOfMass] for edge in edges: basepointliste.append(DraftGeomUtils.findMidpoint(edge)) basepointliste.append(edge.Vertexes[-1].Point) try: basepoint = basepointliste[obj.BasePoint] except IndexError: FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n")) basepoint = basepointliste[0] else : basepoint = profile.CenterOfMass profile.translate(bpoint.sub(basepoint)) if obj.Align: axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1)) angle = bvec.getAngle(axis) if round(angle,Draft.precision()) != 0: if round(angle,Draft.precision()) != round(math.pi,Draft.precision()): rotaxis = axis.cross(bvec) profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle)) if obj.Rotation: profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation) #profile = wire.makePipeShell([profile],True,False,2) TODO buggy profile = profile.extrude(bvec) if obj.Offset: if not DraftVecUtils.isNull(obj.Offset): profile.translate(obj.Offset) shapes.append(profile) if shapes: if hasattr(obj,"Fuse"): if obj.Fuse: if len(shapes) > 1: s = shapes[0].multiFuse(shapes[1:]) s = s.removeSplitter() obj.Shape = s obj.Placement = pl return obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def execute(self, obj): if self.clone(obj): return pl = obj.Placement #self.baseface = None self.flip = False if hasattr(obj, "Flip"): if obj.Flip: self.flip = True base = None baseWire = None if obj.Base: if hasattr(obj.Base, "Shape"): if obj.Base.Shape.Solids: base = obj.Base.Shape #pl = obj.Base.Placement else: if (obj.Base.Shape.Faces and obj.Face): baseWire = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: baseWire = obj.Base.Shape.Wires[0] if baseWire: if baseWire.isClosed(): self.profilsDico = [] self.shps = [] self.subVolShps = [] heights = [] edges = Part.__sortEdges__(baseWire.Edges) if self.flip: edges = self.flipEdges(edges) ln = len(edges) obj.Angles = adjust_list_len(obj.Angles, ln, obj.Angles[0]) obj.Runs = adjust_list_len(obj.Runs, ln, obj.Runs[0]) obj.IdRel = adjust_list_len(obj.IdRel, ln, obj.IdRel[0]) obj.Thickness = adjust_list_len(obj.Thickness, ln, obj.Thickness[0]) obj.Overhang = adjust_list_len(obj.Overhang, ln, obj.Overhang[0]) for i in range(ln): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(ln): self.calcEdgeGeometry(i, edges[i]) for i in range(ln): self.calcApex( i, ln) # after calcEdgeGeometry as it uses vec data for i in range(ln): self.calcMissingData( i, ln ) # after calcApex so it can use recalculated heights for i in range(ln): self.calcDraftEdges(i) for i in range(ln): self.calcEave(i) for profil in self.profilsDico: heights.append(profil["height"]) obj.Heights = heights for i in range(ln): self.getRoofPaneProject(i) profilCurr = self.profilsDico[i] ptsPaneProject = profilCurr["points"] if len(ptsPaneProject) == 0: continue face = face_from_points(ptsPaneProject) if face: diag = face.BoundBox.DiagonalLength midpoint = DraftGeomUtils.findMidpoint( profilCurr["edge"]) thicknessV = profilCurr["thickness"] / (math.cos( math.radians(profilCurr["angle"]))) overhangV = profilCurr["overhang"] * math.tan( math.radians(profilCurr["angle"])) sol = face.extrude( Vector(0.0, 0.0, profilCurr["height"] + 1000000.0)) sol.translate(Vector(0.0, 0.0, -2.0 * overhangV)) ## baseVolume shape ptsPaneProfil = [ Vector(-profilCurr["overhang"], -overhangV, 0.0), Vector(profilCurr["run"], profilCurr["height"], 0.0), Vector(profilCurr["run"], profilCurr["height"] + thicknessV, 0.0), Vector(-profilCurr["overhang"], -overhangV + thicknessV, 0.0) ] self.shps.append( self.createProfilShape(ptsPaneProfil, midpoint, profilCurr["rot"], profilCurr["vec"], profilCurr["run"], diag, sol)) ## subVolume shape ptsSubVolProfil = [ Vector(-profilCurr["overhang"], -overhangV, 0.0), Vector(profilCurr["run"], profilCurr["height"], 0.0), Vector(profilCurr["run"], profilCurr["height"] + 900000.0, 0.0), Vector(-profilCurr["overhang"], profilCurr["height"] + 900000.0, 0.0) ] self.subVolShps.append( self.createProfilShape(ptsSubVolProfil, midpoint, profilCurr["rot"], profilCurr["vec"], profilCurr["run"], diag, sol)) if len( self.shps ) == 0: # occurs if all segments have angle=90 or run=0. # create a flat roof using the eavePtLst outline: ptsPaneProject = [] for i in range(ln): ptsPaneProject.append( self.profilsDico[i]["eavePtLst"][0]) face = face_from_points(ptsPaneProject) if face: thk = max( 1.0, self.profilsDico[0]["thickness"] ) # FreeCAD will crash when extruding with a null vector here self.shps = [face.extrude(Vector(0.0, 0.0, thk))] self.subVolShps = [ face.extrude(Vector(0.0, 0.0, 1000000.0)) ] ## baseVolume base = self.shps.pop() for s in self.shps: base = base.fuse(s) base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl, allownosolid=True) ## subVolume self.sub = self.subVolShps.pop() for s in self.subVolShps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl elif base: base = self.processSubShapes(obj, base, pl) self.applyShape(obj, base, pl, allownosolid=True) else: FreeCAD.Console.PrintMessage( translate("Arch", "Unable to create a roof"))
def execute(self,obj): import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base and obj.Angles: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face-1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient "+str(l)+" aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): edgesForward = edges[:] edgesForward.append(edges[0]) ptsPaneProject=[] profil0 =self.profilsDico[i-1] profil1 =self.profilsDico[i] if i == l-1: profil2 =self.profilsDico[0] else: profil2 =self.profilsDico[i+1] vec0 = edges[i-1].Vertexes[-1].Point.sub(edges[i-1].Vertexes[0].Point) vec1 = edges[i].Vertexes[-1].Point.sub(edges[i].Vertexes[0].Point) vec2 = edgesForward[i+1].Vertexes[-1].Point.sub(edgesForward[i+1].Vertexes[0].Point) rotEdge0 = math.degrees(DraftVecUtils.angle(vec0)) rotEdge1 = math.degrees(DraftVecUtils.angle(vec1)) rotEdge2 = math.degrees(DraftVecUtils.angle(vec2)) edgeEave0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["overhang"]).negative()) edgeEave1 = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,profil1["overhang"]).negative()) edgeEave2 = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,profil2["overhang"]).negative()) pt0Eave1 = DraftGeomUtils.findIntersection(edgeEave0,edgeEave1,infinite1=True,infinite2=True,) pt1Eave1 = DraftGeomUtils.findIntersection(edgeEave1,edgeEave2,infinite1=True,infinite2=True,) edgeEave1 = DraftGeomUtils.edg(FreeCAD.Vector(pt0Eave1[0]),FreeCAD.Vector(pt1Eave1[0])) edgeRidge0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["run"])) edgeRidge1 = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,profil1["run"])) edgeRidge2 = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,profil2["run"])) midpoint = DraftGeomUtils.findMidpoint(edges[i]) pt0Edge1 = edges[i].Vertexes[0].Point pt1Edge1 = edges[i].Vertexes[-1].Point print("Analyse profil " + str(i)) if profil1["angle"] != 90.: if profil2["angle"] == 90. : print("situation a droite : pignon") ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) point = DraftGeomUtils.findIntersection(edgeRidge1,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(point[0])) elif profil1["height"] == profil2["height"] : print("situation a droite : ht1 = ht2") ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) elif profil1["height"] > profil2["height"]: print("situation a droite : ht1 > ht2") dec = profil2["height"]/math.tan(math.radians(profil1["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge2,edgeRidge2OnPane,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [edgeRidge1.Edges[0],], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) elif profil1["height"] < profil2["height"]: print("situation a droite : ht1 < ht2") dec = profil1["height"]/math.tan(math.radians(profil2["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset(edgesForward[i+1],self.getPerpendicular(vec2,rotEdge2,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2OnPane,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave1: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection(edgeHip,edgeEave2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge2,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) else: print("Cas de figure non pris en charge") if profil0["angle"] == 90. : print("situation a gauche : pignon") point = DraftGeomUtils.findIntersection(edgeRidge1,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(point[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil0["height"] == profil1["height"]: print("situation a gauche : ht1 = ht0") edgeRidge0 = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,profil0["run"])) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge1,edgeRidge0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] > profil0["height"]: print("situation a gauche : ht1 > ht0") dec = profil0["height"]/math.tan(math.radians(profil1["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset(edges[i],self.getPerpendicular(vec1,rotEdge1,dec)) ptInter1 = DraftGeomUtils.findIntersection(edgeRidge0OnPane,edgeRidge0,infinite1=True,infinite2=True,) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInter1[0]),pt0Edge1) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular(ptInter2, [edgeRidge1.Edges[0],], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges)) ptsPaneProject.append(FreeCAD.Vector(ptInter1[0])) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] < profil0["height"]: print("situation a gauche : ht1 < ht0") dec = profil1["height"]/math.tan(math.radians(profil0["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset(edges[i-1],self.getPerpendicular(vec0,rotEdge0,dec)) ptInterRidges = DraftGeomUtils.findIntersection(edgeRidge0OnPane,edgeRidge1,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg(FreeCAD.Vector(ptInterRidges[0]),pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection(edgeHip,edgeEave1,infinite1=True,infinite2=False,) if ptInterHipEave3: ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection(edgeHip,edgeEave0,infinite1=True,infinite2=True,) ptsPaneProject.append(FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append(FreeCAD.Vector(pt0Eave1[0])) else: print("Cas de figure non pris en charge") ptsPaneProject = DraftVecUtils.removeDoubles(ptsPaneProject) print("ptsPaneProject",ptsPaneProject) print("Fin Analyse profil " + str(i)) self.profilsDico[i]["points"] = ptsPaneProject lp = len(ptsPaneProject) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for i in range(lp): edge = Part.makeLine(ptsPaneProject[i],ptsPaneProject[i+1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profil1["thickness"]/(math.cos(math.radians(profil1["angle"]))) overhangV = profil1["overhang"]*math.tan(math.radians(profil1["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude(FreeCAD.Vector(0,0,profil1["height"]+2*thicknessV+2*overhangV)) f.translate(FreeCAD.Vector(0.0,0.0,-2*overhangV)) ptsPaneProfil=[FreeCAD.Vector(-profil1["overhang"],-overhangV,0.0),FreeCAD.Vector(profil1["run"],profil1["height"],0.0),FreeCAD.Vector(profil1["run"],profil1["height"]+thicknessV,0.0),FreeCAD.Vector(-profil1["overhang"],-overhangV+thicknessV,0.0)] self.createProfilShape (ptsPaneProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil=[FreeCAD.Vector(-profil1["overhang"],-overhangV,0.0),FreeCAD.Vector(profil1["run"],profil1["height"],0.0),FreeCAD.Vector(profil1["run"],profil1["height"]+10000,0.0),FreeCAD.Vector(0.0,profil1["height"]+10000,0.0)] self.createProfilShape (ptsSubVolumeProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.subVolshps, f) else: #TODO PIGNON pass ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj,base) if base: if not base.isNull(): obj.Shape = base
def export(exportList, filename): """Export the OCA file with a given list of objects. The objects must be edges or faces, in order to be processed and exported. Parameters ---------- exportList : list List of document objects to export. filename : str Path to the new file. Returns ------- None If `exportList` doesn't have shapes to export. """ faces = [] edges = [] # getting faces and edges for ob in exportList: if ob.Shape.Faces: for f in ob.Shape.Faces: faces.append(f) else: for e in ob.Shape.Edges: edges.append(e) if not (edges or faces): FCC.PrintMessage( translate("importOCA", "OCA: found no data to export") + "\n") return # writing file oca = pythonopen(filename, 'w') oca.write("#oca file generated from FreeCAD\r\n") oca.write("# edges\r\n") count = 1 for e in edges: if DraftGeomUtils.geomType(e) == "Line": oca.write("L" + str(count) + "=") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) oca.write("\r\n") elif DraftGeomUtils.geomType(e) == "Circle": if len(e.Vertexes) > 1: oca.write("C" + str(count) + "=ARC ") oca.write(writepoint(e.Vertexes[0].Point)) oca.write(" ") oca.write(writepoint(DraftGeomUtils.findMidpoint(e))) oca.write(" ") oca.write(writepoint(e.Vertexes[-1].Point)) else: oca.write("C" + str(count) + "= ") oca.write(writepoint(e.Curve.Center)) oca.write(" ") oca.write(str(e.Curve.Radius)) oca.write("\r\n") count += 1 oca.write("# faces\r\n") for f in faces: oca.write("A" + str(count) + "=S(POL") for v in f.Vertexes: oca.write(" ") oca.write(writepoint(v.Point)) oca.write(" ") oca.write(writepoint(f.Vertexes[0].Point)) oca.write(")\r\n") count += 1 # closing oca.close() FCC.PrintMessage( translate("importOCA", "successfully exported") + " " + filename + "\n")
def getEdgesAngleSVG( edge1: Part.Edge, edge2: Part.Edge, arc_radius: float, view_plane: WorkingPlane.Plane, font_family: str, font_size: Union[float, str], bent_angle_exclude_list: Tuple[float, ...] = (90, 180), stroke_width: Union[float, str] = 0.2, stroke_color: str = "black", ) -> ElementTree.Element: """Returns svg representation for angle between two edges by drawing an arc of given radius and adding angle text svg. It returns empty svg if edges doesn't intersect when extended infinitely. Parameters ---------- edge1: Part.Edge The first edge to get its angle dimension svg with edge2. edge2: The second edge to get its angle dimension svg with edge1. arc_radius: float The radius of dimension arc. view_plane: WorkingPlane.Plane The view plane acting as svg plane. font_family: str The font-family of angle dimension. font_size: float or str The font-size of angle dimension. bent_angle_exclude_list: tuple of float, optional If angle between two edges is present in bent_angle_exclude_list, then empty svg element will be returned. Default is (90, 180) stroke_width: float or str, optional The stroke-width of arc svg. Default is 0.2 stroke_color: str, optional The stroke color of arc svg. Default is "black". Returns ------- ElementTree.Element The generated edges angle dimension svg. """ intersection = DraftGeomUtils.findIntersection(edge1, edge2, True, True) if not intersection: return ElementTree.Element("g") else: intersection = intersection[0] p1 = max( DraftGeomUtils.getVerts(edge1), key=lambda x: x.distanceToPoint(intersection), ) p2 = max( DraftGeomUtils.getVerts(edge2), key=lambda x: x.distanceToPoint(intersection), ) angle = round( math.degrees( abs(DraftVecUtils.angle(p2.sub(intersection), p1.sub(intersection))))) if angle in bent_angle_exclude_list: return ElementTree.Element("g") arc_p1 = intersection.add(arc_radius * p2.sub(intersection).normalize()) arc_p2 = intersection.add(arc_radius * p1.sub(intersection).normalize()) arc_edge = DraftGeomUtils.arcFrom2Pts(arc_p1, arc_p2, intersection) arc_svg = getRoundEdgeSVG(arc_edge, view_plane, stroke_width, stroke_color) arc_mid_point = DraftGeomUtils.findMidpoint(arc_edge) proj_intersection = getProjectionToSVGPlane(intersection, view_plane) proj_mid_point = getProjectionToSVGPlane(arc_mid_point, view_plane) if round(proj_intersection.x) < round(proj_mid_point.x): text_anchor = "start" elif round(proj_intersection.x) > round(proj_mid_point.x): text_anchor = "end" else: text_anchor = "middle" if round(proj_intersection.y) < round(proj_mid_point.y): text_y = proj_mid_point.y + font_size elif round(proj_intersection.y) > round(proj_mid_point.y): text_y = proj_mid_point.y else: text_y = proj_mid_point.y + font_size / 2 angle_text_svg = getSVGTextElement( "{}°".format(angle), proj_mid_point.x, text_y, font_family, font_size, text_anchor, ) bent_angle_svg = ElementTree.Element("g") bent_angle_svg.extend([arc_svg, angle_text_svg]) return bent_angle_svg
def execute(self,obj): import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base: if not obj.Angles: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: base = obj.Base.Shape.copy() else: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face-1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient "+str(l)+" aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for i in range(l): self.calcEdgeGeometry(edges, i) for i in range(l): self.calcDraftEdges(i) for i in range(l): self.calcEave(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): self.getRoofPaneProject(i) profilCurrent = self.findProfil(i) midpoint = DraftGeomUtils.findMidpoint(profilCurrent["edge"]) ptsPaneProject = profilCurrent["points"] lp = len(ptsPaneProject) if lp != 0: #print FreeCAD.Vector(ptsPaneProject[0]) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for p in range(lp): edge = Part.makeLine(ptsPaneProject[p],ptsPaneProject[p+1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profilCurrent["thickness"]/(math.cos(math.radians(profilCurrent["angle"]))) overhangV = profilCurrent["overhang"]*math.tan(math.radians(profilCurrent["angle"])) if wire.isClosed(): f = Part.Face(wire) #Part.show(f) f = f.extrude(FreeCAD.Vector(0,0,profilCurrent["height"]+2*thicknessV+2*overhangV)) f.translate(FreeCAD.Vector(0.0,0.0,-2*overhangV)) ptsPaneProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+thicknessV,0.0),FreeCAD.Vector(-profilCurrent["overhang"],-overhangV+thicknessV,0.0)] self.createProfilShape (ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+10000,0.0),FreeCAD.Vector(0.0,profilCurrent["height"]+10000,0.0)] self.createProfilShape (ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, self.subVolshps, f) ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj,base) if base: if not base.isNull(): obj.Shape = base
def execute(self, obj): import Part, math, DraftGeomUtils pl = obj.Placement self.baseface = None base = None if obj.Base and obj.Angles: w = None if obj.Base.isDerivedFrom("Part::Feature"): if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face - 1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = DraftGeomUtils.sortEdges(w.Edges) l = len(edges) print("le contour contient " + str(l) + " aretes") for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): edgesForward = edges[:] edgesForward.append(edges[0]) ptsPaneProject = [] profil0 = self.profilsDico[i - 1] profil1 = self.profilsDico[i] if i == l - 1: profil2 = self.profilsDico[0] else: profil2 = self.profilsDico[i + 1] vec0 = edges[i - 1].Vertexes[-1].Point.sub( edges[i - 1].Vertexes[0].Point) vec1 = edges[i].Vertexes[-1].Point.sub( edges[i].Vertexes[0].Point) vec2 = edgesForward[i + 1].Vertexes[-1].Point.sub( edgesForward[i + 1].Vertexes[0].Point) rotEdge0 = math.degrees(DraftVecUtils.angle(vec0)) rotEdge1 = math.degrees(DraftVecUtils.angle(vec1)) rotEdge2 = math.degrees(DraftVecUtils.angle(vec2)) edgeEave0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular( vec0, rotEdge0, profil0["overhang"]).negative()) edgeEave1 = DraftGeomUtils.offset( edges[i], self.getPerpendicular( vec1, rotEdge1, profil1["overhang"]).negative()) edgeEave2 = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular( vec2, rotEdge2, profil2["overhang"]).negative()) pt0Eave1 = DraftGeomUtils.findIntersection( edgeEave0, edgeEave1, infinite1=True, infinite2=True, ) pt1Eave1 = DraftGeomUtils.findIntersection( edgeEave1, edgeEave2, infinite1=True, infinite2=True, ) edgeEave1 = DraftGeomUtils.edg( FreeCAD.Vector(pt0Eave1[0]), FreeCAD.Vector(pt1Eave1[0])) edgeRidge0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular(vec0, rotEdge0, profil0["run"])) edgeRidge1 = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, profil1["run"])) edgeRidge2 = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular(vec2, rotEdge2, profil2["run"])) midpoint = DraftGeomUtils.findMidpoint(edges[i]) pt0Edge1 = edges[i].Vertexes[0].Point pt1Edge1 = edges[i].Vertexes[-1].Point print("Analyse profil " + str(i)) if profil1["angle"] != 90.: if profil2["angle"] == 90.: print("situation a droite : pignon") ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) point = DraftGeomUtils.findIntersection( edgeRidge1, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append(FreeCAD.Vector(point[0])) elif profil1["height"] == profil2["height"]: print("situation a droite : ht1 = ht2") ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) elif profil1["height"] > profil2["height"]: print("situation a droite : ht1 > ht2") dec = profil2["height"] / math.tan( math.radians(profil1["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge2, edgeRidge2OnPane, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular( ptInter2, [ edgeRidge1.Edges[0], ], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges)) elif profil1["height"] < profil2["height"]: print("situation a droite : ht1 < ht2") dec = profil1["height"] / math.tan( math.radians(profil2["angle"])) edgeRidge2OnPane = DraftGeomUtils.offset( edgesForward[i + 1], self.getPerpendicular(vec2, rotEdge2, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2OnPane, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt1Edge1) ptInterHipEave1 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave1: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave1[0])) else: ptInterHipEave2 = DraftGeomUtils.findIntersection( edgeHip, edgeEave2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(pt1Eave1[0])) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave2[0])) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge2, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) else: print("Cas de figure non pris en charge") if profil0["angle"] == 90.: print("situation a gauche : pignon") point = DraftGeomUtils.findIntersection( edgeRidge1, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append(FreeCAD.Vector(point[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil0["height"] == profil1["height"]: print("situation a gauche : ht1 = ht0") edgeRidge0 = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular( vec0, rotEdge0, profil0["run"])) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge1, edgeRidge0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] > profil0["height"]: print("situation a gauche : ht1 > ht0") dec = profil0["height"] / math.tan( math.radians(profil1["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset( edges[i], self.getPerpendicular(vec1, rotEdge1, dec)) ptInter1 = DraftGeomUtils.findIntersection( edgeRidge0OnPane, edgeRidge0, infinite1=True, infinite2=True, ) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInter1[0]), pt0Edge1) ptInter2 = edgeHip.Vertexes[0].Point vecInterRidges = DraftGeomUtils.findPerpendicular( ptInter2, [ edgeRidge1.Edges[0], ], force=0) ptInterRidges = ptInter2.add(vecInterRidges[0]) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges)) ptsPaneProject.append( FreeCAD.Vector(ptInter1[0])) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) elif profil1["height"] < profil0["height"]: print("situation a gauche : ht1 < ht0") dec = profil1["height"] / math.tan( math.radians(profil0["angle"])) edgeRidge0OnPane = DraftGeomUtils.offset( edges[i - 1], self.getPerpendicular(vec0, rotEdge0, dec)) ptInterRidges = DraftGeomUtils.findIntersection( edgeRidge0OnPane, edgeRidge1, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterRidges[0])) edgeHip = DraftGeomUtils.edg( FreeCAD.Vector(ptInterRidges[0]), pt0Edge1) ptInterHipEave3 = DraftGeomUtils.findIntersection( edgeHip, edgeEave1, infinite1=True, infinite2=False, ) if ptInterHipEave3: ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave3[0])) else: ptInterHipEave4 = DraftGeomUtils.findIntersection( edgeHip, edgeEave0, infinite1=True, infinite2=True, ) ptsPaneProject.append( FreeCAD.Vector(ptInterHipEave4[0])) ptsPaneProject.append( FreeCAD.Vector(pt0Eave1[0])) else: print("Cas de figure non pris en charge") ptsPaneProject = DraftVecUtils.removeDoubles( ptsPaneProject) print("ptsPaneProject", ptsPaneProject) print("Fin Analyse profil " + str(i)) self.profilsDico[i]["points"] = ptsPaneProject lp = len(ptsPaneProject) ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for i in range(lp): edge = Part.makeLine(ptsPaneProject[i], ptsPaneProject[i + 1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profil1["thickness"] / (math.cos( math.radians(profil1["angle"]))) overhangV = profil1["overhang"] * math.tan( math.radians(profil1["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude( FreeCAD.Vector( 0, 0, profil1["height"] + 2 * thicknessV + 2 * overhangV)) f.translate( FreeCAD.Vector(0.0, 0.0, -2 * overhangV)) ptsPaneProfil = [ FreeCAD.Vector(-profil1["overhang"], -overhangV, 0.0), FreeCAD.Vector(profil1["run"], profil1["height"], 0.0), FreeCAD.Vector(profil1["run"], profil1["height"] + thicknessV, 0.0), FreeCAD.Vector(-profil1["overhang"], -overhangV + thicknessV, 0.0) ] self.createProfilShape(ptsPaneProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.shps, f) ## subVolume shape ptsSubVolumeProfil = [ FreeCAD.Vector(-profil1["overhang"], -overhangV, 0.0), FreeCAD.Vector(profil1["run"], profil1["height"], 0.0), FreeCAD.Vector(profil1["run"], profil1["height"] + 10000, 0.0), FreeCAD.Vector(0.0, profil1["height"] + 10000, 0.0) ] self.createProfilShape(ptsSubVolumeProfil, midpoint, rotEdge1, vec1, profil1["run"], d, self.subVolshps, f) else: #TODO PIGNON pass ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = Part.makeCompound(self.shps) if not base.isNull(): if not DraftGeomUtils.isNull(pl): base.Placement = pl base = self.processSubShapes(obj, base) if base: if not base.isNull(): obj.Shape = base
def execute(self,obj): if self.clone(obj): return import Part, math, DraftGeomUtils pl = obj.Placement #self.baseface = None base = None w = None if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape.Solids: base = obj.Base.Shape #pl = obj.Base.Placement else: if (obj.Base.Shape.Faces and obj.Face): w = obj.Base.Shape.Faces[obj.Face-1].Wires[0] elif obj.Base.Shape.Wires: w = obj.Base.Shape.Wires[0] if w: if w.isClosed(): self.profilsDico = [] self.shps = [] self.subVolshps = [] heights = [] edges = Part.__sortEdges__(w.Edges) l = len(edges) for i in range(l): self.makeRoofProfilsDic(i, obj.Angles[i], obj.Runs[i], obj.IdRel[i], obj.Overhang[i], obj.Thickness[i]) for i in range(l): self.calcMissingData(i) for i in range(l): self.calcEdgeGeometry(edges, i) for i in range(l): self.calcDraftEdges(i) for i in range(l): self.calcEave(i) for p in self.profilsDico: heights.append(p["height"]) obj.Heights = heights for i in range(l): self.getRoofPaneProject(i) profilCurrent = self.findProfil(i) midpoint = DraftGeomUtils.findMidpoint(profilCurrent["edge"]) ptsPaneProject = profilCurrent["points"] lp = len(ptsPaneProject) if lp != 0: ptsPaneProject.append(ptsPaneProject[0]) edgesWire = [] for p in range(lp): edge = Part.makeLine(ptsPaneProject[p],ptsPaneProject[p+1]) edgesWire.append(edge) wire = Part.Wire(edgesWire) d = wire.BoundBox.DiagonalLength thicknessV = profilCurrent["thickness"]/(math.cos(math.radians(profilCurrent["angle"]))) overhangV = profilCurrent["overhang"]*math.tan(math.radians(profilCurrent["angle"])) if wire.isClosed(): f = Part.Face(wire) f = f.extrude(FreeCAD.Vector(0,0,profilCurrent["height"]+1000000.0)) f.translate(FreeCAD.Vector(0.0,0.0,-2*overhangV)) ptsPaneProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+thicknessV,0.0),FreeCAD.Vector(-profilCurrent["overhang"],-overhangV+thicknessV,0.0)] self.shps.append(self.createProfilShape(ptsPaneProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## subVolume shape ptsSubVolumeProfil=[FreeCAD.Vector(-profilCurrent["overhang"],-overhangV,0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"],0.0),FreeCAD.Vector(profilCurrent["run"],profilCurrent["height"]+900000.0,0.0),FreeCAD.Vector(-profilCurrent["overhang"],profilCurrent["height"]+900000.0,0.0)] self.subVolshps.append(self.createProfilShape(ptsSubVolumeProfil, midpoint, profilCurrent["rot"], profilCurrent["vec"], profilCurrent["run"], d, f)) ## SubVolume self.sub = self.subVolshps.pop() for s in self.subVolshps: self.sub = self.sub.fuse(s) self.sub = self.sub.removeSplitter() if not self.sub.isNull(): if not DraftGeomUtils.isNull(pl): self.sub.Placement = pl ## BaseVolume base = self.shps.pop() for s in self.shps : base = base.fuse(s) base = self.processSubShapes(obj,base) self.applyShape(obj,base,pl,allownosolid=True) elif base : base = self.processSubShapes(obj,base) self.applyShape(obj,base,pl,allownosolid=True) else: FreeCAD.Console.PrintMessage(translate("Arch","Unable to create a roof"))
def execute(self,obj): if self.clone(obj): return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return pl = obj.Placement if obj.Base.Shape.Solids: obj.Shape = obj.Base.Shape.copy() if not pl.isNull(): obj.Placement = obj.Shape.Placement.multiply(pl) else: if not obj.Profile: return if not obj.Profile.isDerivedFrom("Part::Part2DObject"): return if not obj.Profile.Shape: return if not obj.Profile.Shape.Wires: return if not obj.Profile.Shape.Faces: for w in obj.Profile.Shape.Wires: if not w.isClosed(): return import DraftGeomUtils, Part, math baseprofile = obj.Profile.Shape.copy() if hasattr(obj,"ProfilePlacement"): if not obj.ProfilePlacement.isNull(): baseprofile.Placement = obj.ProfilePlacement.multiply(baseprofile.Placement) if not baseprofile.Faces: f = [] for w in baseprofile.Wires: f.append(Part.Face(w)) if len(f) == 1: baseprofile = f[0] else: baseprofile = Part.makeCompound(f) shapes = [] normal = DraftGeomUtils.getNormal(obj.Base.Shape) #for wire in obj.Base.Shape.Wires: edges = obj.Base.Shape.Edges if hasattr(obj,"Edges"): if obj.Edges == "Vertical edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(0,1,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] elif obj.Edges == "Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] elif obj.Edges == "Top Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] edges = sorted(edges,key=lambda x: x.CenterOfMass.z,reverse=True) z = edges[0].CenterOfMass.z edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001] elif obj.Edges == "Bottom Horizontal edges": rv = obj.Base.Placement.Rotation.multVec(FreeCAD.Vector(1,0,0)) edges = [e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)),4) in [0,3.1416]] edges = sorted(edges,key=lambda x: x.CenterOfMass.z) z = edges[0].CenterOfMass.z edges = [e for e in edges if abs(e.CenterOfMass.z-z) < 0.00001] for e in edges: #e = wire.Edges[0] bvec = DraftGeomUtils.vec(e) bpoint = e.Vertexes[0].Point profile = baseprofile.copy() #basepoint = profile.Placement.Base if hasattr(obj,"BasePoint"): edges = Part.__sortEdges__(profile.Edges) basepointliste = [profile.CenterOfMass] for edge in edges: basepointliste.append(DraftGeomUtils.findMidpoint(edge)) basepointliste.append(edge.Vertexes[-1].Point) try: basepoint = basepointliste[obj.BasePoint] except IndexError: FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.")+"\n") basepoint = basepointliste[0] else : basepoint = profile.CenterOfMass profile.translate(bpoint.sub(basepoint)) if obj.Align: axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1)) angle = bvec.getAngle(axis) if round(angle,Draft.precision()) != 0: if round(angle,Draft.precision()) != round(math.pi,Draft.precision()): rotaxis = axis.cross(bvec) profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle)) if obj.Rotation: profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation) #profile = wire.makePipeShell([profile],True,False,2) TODO buggy profile = profile.extrude(bvec) if obj.Offset: if not DraftVecUtils.isNull(obj.Offset): profile.translate(obj.Offset) shapes.append(profile) if shapes: if hasattr(obj,"Fuse"): if obj.Fuse: if len(shapes) > 1: s = shapes[0].multiFuse(shapes[1:]) s = s.removeSplitter() obj.Shape = s obj.Placement = pl return obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def execute(self,obj): if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return pl = obj.Placement if obj.Base.Shape.Solids: obj.Shape = obj.Base.Shape.copy() if not pl.isNull(): obj.Placement = obj.Shape.Placement.multiply(pl) else: if not obj.Profile: return if not obj.Profile.isDerivedFrom("Part::Part2DObject"): return if not obj.Profile.Shape: return if not obj.Profile.Shape.Wires: return if not obj.Profile.Shape.Faces: for w in obj.Profile.Shape.Wires: if not w.isClosed(): return import DraftGeomUtils, Part, math baseprofile = obj.Profile.Shape.copy() if not baseprofile.Faces: f = [] for w in baseprofile.Wires: f.append(Part.Face(w)) if len(f) == 1: baseprofile = f[0] else: baseprofile = Part.makeCompound(f) shapes = [] normal = DraftGeomUtils.getNormal(obj.Base.Shape) #for wire in obj.Base.Shape.Wires: for e in obj.Base.Shape.Edges: #e = wire.Edges[0] bvec = DraftGeomUtils.vec(e) bpoint = e.Vertexes[0].Point profile = baseprofile.copy() #basepoint = profile.Placement.Base if hasattr(obj,"BasePoint"): edges = DraftGeomUtils.sortEdges(profile.Edges) basepointliste = [profile.CenterOfMass] for edge in edges: basepointliste.append(DraftGeomUtils.findMidpoint(edge)) basepointliste.append(edge.Vertexes[-1].Point) try: basepoint = basepointliste[obj.BasePoint] except IndexError: FreeCAD.Console.PrintMessage(translate("Arch","Crossing point not found in profile.\n")) basepoint = basepointliste[0] else : basepoint = profile.CenterOfMass profile.translate(bpoint.sub(basepoint)) if obj.Align: axis = profile.Placement.Rotation.multVec(FreeCAD.Vector(0,0,1)) angle = bvec.getAngle(axis) if round(angle,Draft.precision()) != 0: if round(angle,Draft.precision()) != round(math.pi,Draft.precision()): rotaxis = axis.cross(bvec) profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(rotaxis), math.degrees(angle)) if obj.Rotation: profile.rotate(DraftVecUtils.tup(bpoint), DraftVecUtils.tup(FreeCAD.Vector(bvec).normalize()), obj.Rotation) #profile = wire.makePipeShell([profile],True,False,2) TODO buggy profile = profile.extrude(bvec) if obj.Offset: if not DraftVecUtils.isNull(obj.Offset): profile.translate(obj.Offset) shapes.append(profile) if shapes: obj.Shape = Part.makeCompound(shapes) obj.Placement = pl
def updateData(self, obj, prop): if hasattr(self, "arc"): from pivy import coin import Part, DraftGeomUtils import DraftGui arcsegs = 24 # calculate the arc data if DraftVecUtils.isNull(obj.Normal): norm = App.Vector(0, 0, 1) else: norm = obj.Normal radius = (obj.Dimline.sub(obj.Center)).Length self.circle = Part.makeCircle(radius, obj.Center, norm, obj.FirstAngle.Value, obj.LastAngle.Value) self.p2 = self.circle.Vertexes[0].Point self.p3 = self.circle.Vertexes[-1].Point mp = DraftGeomUtils.findMidpoint(self.circle.Edges[0]) ray = mp.sub(obj.Center) # set text value if obj.LastAngle.Value > obj.FirstAngle.Value: a = obj.LastAngle.Value - obj.FirstAngle.Value else: a = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value su = True if hasattr(obj.ViewObject, "ShowUnit"): su = obj.ViewObject.ShowUnit if hasattr(obj.ViewObject, "Decimals"): self.string = DraftGui.displayExternal(a, obj.ViewObject.Decimals, 'Angle', su) else: self.string = DraftGui.displayExternal(a, None, 'Angle', su) if obj.ViewObject.Override: self.string = obj.ViewObject.Override.replace("$dim",\ self.string) self.text.string = self.text3d.string = utils.string_encode_coin( self.string) # check display mode try: m = obj.ViewObject.DisplayMode except: # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet) m = ["2D", "3D"][utils.get_param("dimstyle", 0)] # set the arc if m == "3D": # calculate the spacing of the text spacing = (len(self.string) * obj.ViewObject.FontSize.Value) / 8.0 pts1 = [] cut = None pts2 = [] for i in range(arcsegs + 1): p = self.circle.valueAt(self.circle.FirstParameter + ( (self.circle.LastParameter - self.circle.FirstParameter) / arcsegs) * i) if (p.sub(mp)).Length <= spacing: if cut is None: cut = i else: if cut is None: pts1.append([p.x, p.y, p.z]) else: pts2.append([p.x, p.y, p.z]) self.coords.point.setValues(pts1 + pts2) i1 = len(pts1) i2 = i1 + len(pts2) self.arc.coordIndex.setValues( 0, len(pts1) + len(pts2) + 1, list(range(len(pts1))) + [-1] + list(range(i1, i2))) if (len(pts1) >= 3) and (len(pts2) >= 3): self.circle1 = Part.Arc( App.Vector(pts1[0][0], pts1[0][1], pts1[0][2]), App.Vector(pts1[1][0], pts1[1][1], pts1[1][2]), App.Vector(pts1[-1][0], pts1[-1][1], pts1[-1][2])).toShape() self.circle2 = Part.Arc( App.Vector(pts2[0][0], pts2[0][1], pts2[0][2]), App.Vector(pts2[1][0], pts2[1][1], pts2[1][2]), App.Vector(pts2[-1][0], pts2[-1][1], pts2[-1][2])).toShape() else: pts = [] for i in range(arcsegs + 1): p = self.circle.valueAt(self.circle.FirstParameter + ( (self.circle.LastParameter - self.circle.FirstParameter) / arcsegs) * i) pts.append([p.x, p.y, p.z]) self.coords.point.setValues(pts) self.arc.coordIndex.setValues(0, arcsegs + 1, list(range(arcsegs + 1))) # set the arrow coords and rotation self.trans1.translation.setValue((self.p2.x, self.p2.y, self.p2.z)) self.coord1.point.setValue((self.p2.x, self.p2.y, self.p2.z)) self.trans2.translation.setValue((self.p3.x, self.p3.y, self.p3.z)) self.coord2.point.setValue((self.p3.x, self.p3.y, self.p3.z)) # calculate small chords to make arrows look better arrowlength = 4 * obj.ViewObject.ArrowSize.Value u1 = (self.circle.valueAt(self.circle.FirstParameter + arrowlength) ).sub(self.circle.valueAt( self.circle.FirstParameter)).normalize() u2 = (self.circle.valueAt(self.circle.LastParameter)).sub( self.circle.valueAt(self.circle.LastParameter - arrowlength)).normalize() if hasattr(obj.ViewObject, "FlipArrows"): if obj.ViewObject.FlipArrows: u1 = u1.negative() u2 = u2.negative() w2 = self.circle.Curve.Axis w1 = w2.negative() v1 = w1.cross(u1) v2 = w2.cross(u2) q1 = App.Placement(DraftVecUtils.getPlaneRotation(u1, v1, w1)).Rotation.Q q2 = App.Placement(DraftVecUtils.getPlaneRotation(u2, v2, w2)).Rotation.Q self.trans1.rotation.setValue((q1[0], q1[1], q1[2], q1[3])) self.trans2.rotation.setValue((q2[0], q2[1], q2[2], q2[3])) # setting text pos & rot self.tbase = mp if hasattr(obj.ViewObject, "TextPosition"): if not DraftVecUtils.isNull(obj.ViewObject.TextPosition): self.tbase = obj.ViewObject.TextPosition u3 = ray.cross(norm).normalize() v3 = norm.cross(u3) r = App.Placement(DraftVecUtils.getPlaneRotation(u3, v3, norm)).Rotation offset = r.multVec(App.Vector(0, 1, 0)) if hasattr(obj.ViewObject, "TextSpacing"): offset = DraftVecUtils.scaleTo( offset, obj.ViewObject.TextSpacing.Value) else: offset = DraftVecUtils.scaleTo(offset, 0.05) if m == "3D": offset = offset.negative() self.tbase = self.tbase.add(offset) q = r.Q self.textpos.translation.setValue( [self.tbase.x, self.tbase.y, self.tbase.z]) self.textpos.rotation = coin.SbRotation(q[0], q[1], q[2], q[3]) # set the angle property if round(obj.Angle, utils.precision()) != round( a, utils.precision()): obj.Angle = a
def execute(self, obj): if self.clone(obj): return if not obj.Base: return if not obj.Base.Shape: return if not obj.Base.Shape.Wires: return pl = obj.Placement if obj.Base.Shape.Solids: obj.Shape = obj.Base.Shape.copy() if not pl.isNull(): obj.Placement = obj.Shape.Placement.multiply(pl) else: if not obj.Profile: return if not obj.Profile.Shape: return if obj.Profile.Shape.findPlane() is None: return if not obj.Profile.Shape.Wires: return if not obj.Profile.Shape.Faces: for w in obj.Profile.Shape.Wires: if not w.isClosed(): return import DraftGeomUtils, Part, math baseprofile = obj.Profile.Shape.copy() if hasattr(obj, "ProfilePlacement"): if not obj.ProfilePlacement.isNull(): baseprofile.Placement = obj.ProfilePlacement.multiply( baseprofile.Placement) if not baseprofile.Faces: f = [] for w in baseprofile.Wires: f.append(Part.Face(w)) if len(f) == 1: baseprofile = f[0] else: baseprofile = Part.makeCompound(f) shapes = [] normal = DraftGeomUtils.getNormal(obj.Base.Shape) edges = obj.Base.Shape.Edges if hasattr(obj, "Edges"): if obj.Edges == "Vertical edges": rv = obj.Base.Placement.Rotation.multVec( FreeCAD.Vector(0, 1, 0)) edges = [ e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4) in [0, 3.1416] ] elif obj.Edges == "Horizontal edges": rv = obj.Base.Placement.Rotation.multVec( FreeCAD.Vector(1, 0, 0)) edges = [ e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4) in [0, 3.1416] ] elif obj.Edges == "Top Horizontal edges": rv = obj.Base.Placement.Rotation.multVec( FreeCAD.Vector(1, 0, 0)) edges = [ e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4) in [0, 3.1416] ] edges = sorted(edges, key=lambda x: x.CenterOfMass.z, reverse=True) z = edges[0].CenterOfMass.z edges = [ e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001 ] elif obj.Edges == "Bottom Horizontal edges": rv = obj.Base.Placement.Rotation.multVec( FreeCAD.Vector(1, 0, 0)) edges = [ e for e in edges if round(rv.getAngle(e.tangentAt(e.FirstParameter)), 4) in [0, 3.1416] ] edges = sorted(edges, key=lambda x: x.CenterOfMass.z) z = edges[0].CenterOfMass.z edges = [ e for e in edges if abs(e.CenterOfMass.z - z) < 0.00001 ] for e in edges: bvec = DraftGeomUtils.vec(e) bpoint = e.Vertexes[0].Point profile = baseprofile.copy() rot = None # New rotation. # Supplying FreeCAD.Rotation() with two parallel vectors and # a null vector may seem strange, but the function is perfectly # able to handle this. Its algorithm will use default axes in # such cases. if obj.Align: if normal is None: rot = FreeCAD.Rotation(FreeCAD.Vector(), bvec, bvec, "ZYX") else: rot = FreeCAD.Rotation(FreeCAD.Vector(), normal, bvec, "ZYX") profile.Placement.Rotation = rot if hasattr(obj, "BasePoint"): edges = Part.__sortEdges__(profile.Edges) basepointliste = [profile.Placement.Base] for edge in edges: basepointliste.append( DraftGeomUtils.findMidpoint(edge)) basepointliste.append(edge.Vertexes[-1].Point) try: basepoint = basepointliste[obj.BasePoint] except IndexError: FreeCAD.Console.PrintMessage( translate("Arch", "Crossing point not found in profile.") + "\n") basepoint = basepointliste[0] else: basepoint = profile.Placement.Base delta = bpoint.sub(basepoint) # Translation vector. if obj.Offset and (not DraftVecUtils.isNull(obj.Offset)): if rot is None: delta = delta + obj.Offset else: delta = delta + rot.multVec(obj.Offset) profile.translate(delta) if obj.Rotation: profile.rotate(bpoint, bvec, obj.Rotation) # profile = wire.makePipeShell([profile], True, False, 2) TODO buggy profile = profile.extrude(bvec) shapes.append(profile) if shapes: if hasattr(obj, "Fuse"): if obj.Fuse: if len(shapes) > 1: s = shapes[0].multiFuse(shapes[1:]) s = s.removeSplitter() obj.Shape = s obj.Placement = pl return obj.Shape = Part.makeCompound(shapes) obj.Placement = pl