def mergeWires(list_of_edges_wires, flag_single = False, split_connections = []): edges = [] for sh in list_of_edges_wires: edges.extend(sh.Edges) if flag_single: return Part.Wire(edges) else: groups = splitIntoGroupsBySharing(edges, lambda(sh): sh.Vertexes, split_connections) return Part.makeCompound([Part.Wire(Part.getSortedClusters(group)[0]) for group in groups])
def mergeWires(list_of_edges_wires, flag_single=False, split_connections=[]): edges = [] for sh in list_of_edges_wires: edges.extend(sh.Edges) if flag_single: return Part.Wire(edges) else: groups = splitIntoGroupsBySharing(edges, lambda sh: sh.Vertexes, split_connections) return Part.makeCompound( [Part.Wire(Part.getSortedClusters(group)[0]) for group in groups])
def draftify(objectslist, makeblock=False, delete=True): """draftify(objectslist,[makeblock],[delete]) Turn each object of the given list (objectslist can also be a single object) into a Draft parametric wire. TODO: support more objects Parameters ---------- objectslist : makeblock : bool If makeblock is True, multiple objects will be grouped in a block. delete : bool If delete = False, old objects are not deleted """ import Part import DraftGeomUtils if not isinstance(objectslist, list): objectslist = [objectslist] newobjlist = [] for obj in objectslist: if hasattr(obj, 'Shape'): for cluster in Part.getSortedClusters(obj.Shape.Edges): w = Part.Wire(cluster) if DraftGeomUtils.hasCurves(w): if (len(w.Edges) == 1) and (DraftGeomUtils.geomType( w.Edges[0]) == "Circle"): nobj = makeCircle(w.Edges[0]) else: nobj = App.ActiveDocument.addObject( "Part::Feature", obj.Name) nobj.Shape = w else: nobj = makeWire(w) newobjlist.append(nobj) gui_utils.format_object(nobj, obj) # sketches are always in wireframe mode. In Draft we don't like that! if App.GuiUp: nobj.ViewObject.DisplayMode = "Flat Lines" if delete: App.ActiveDocument.removeObject(obj.Name) if makeblock: return makeBlock(newobjlist) else: if len(newobjlist) == 1: return newobjlist[0] return newobjlist
def getExtrusionData(self,obj): """returns (shape,extrusion vector,placement) or None""" import Part,DraftGeomUtils data = ArchComponent.Component.getExtrusionData(self,obj) if data: if not isinstance(data[0],list): # multifuses not considered here return data length = obj.Length.Value width = obj.Width.Value height = obj.Height.Value if not height: for p in obj.InList: if Draft.getType(p) in ["Floor","BuildingPart"]: if p.Height.Value: height = p.Height.Value if not height: return None if obj.Normal == Vector(0,0,0): normal = Vector(0,0,1) else: normal = Vector(obj.Normal) base = None placement = None self.basewires = None # build wall layers layers = [] if hasattr(obj,"Material"): if obj.Material: if hasattr(obj.Material,"Materials"): varwidth = 0 restwidth = width - sum(obj.Material.Thicknesses) if restwidth > 0: varwidth = [t for t in obj.Material.Thicknesses if t == 0] if varwidth: varwidth = restwidth/len(varwidth) for t in obj.Material.Thicknesses: if t: layers.append(t) elif varwidth: layers.append(varwidth) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: if obj.Base.Shape.Solids: return None elif obj.Face > 0: if len(obj.Base.Shape.Faces) >= obj.Face: face = obj.Base.Shape.Faces[obj.Face-1] # this wall is based on a specific face of its base object normal = face.normalAt(0,0) if normal.getAngle(Vector(0,0,1)) > math.pi/4: normal.multiply(width) base = face.extrude(normal) if obj.Align == "Center": base.translate(normal.negative().multiply(0.5)) elif obj.Align == "Right": base.translate(normal.negative()) else: normal.multiply(height) base = face.extrude(normal) base,placement = self.rebase(base) return (base,normal,placement) elif obj.Base.Shape.Faces: if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces): return None else: base,placement = self.rebase(obj.Base.Shape) elif len(obj.Base.Shape.Edges) == 1: self.basewires = [Part.Wire(obj.Base.Shape.Edges)] else: # self.basewires = obj.Base.Shape.Wires self.basewires = [] for cluster in Part.getSortedClusters(obj.Base.Shape.Edges): for c in Part.sortEdges(cluster): self.basewires.append(Part.Wire(c)) if self.basewires and width: if (len(self.basewires) == 1) and layers: self.basewires = [self.basewires[0] for l in layers] layeroffset = 0 baseface = None for i,wire in enumerate(self.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(normal) if not DraftVecUtils.isNull(dvec): dvec.normalize() sh = None if obj.Align == "Left": off = obj.Offset.Value if layers: off = off+layeroffset dvec.multiply(layers[i]) layeroffset += layers[i] else: dvec.multiply(width) if off: dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Right": dvec = dvec.negative() off = obj.Offset.Value if layers: off = off+layeroffset dvec.multiply(layers[i]) layeroffset += layers[i] else: dvec.multiply(width) if off: dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Center": if layers: off = width/2-layeroffset d1 = Vector(dvec).multiply(off) w1 = DraftGeomUtils.offsetWire(wire,d1) layeroffset += layers[i] off = width/2-layeroffset d1 = Vector(dvec).multiply(off) w2 = DraftGeomUtils.offsetWire(wire,d1) else: dvec.multiply(width/2) w1 = DraftGeomUtils.offsetWire(wire,dvec) dvec = dvec.negative() w2 = DraftGeomUtils.offsetWire(wire,dvec) sh = DraftGeomUtils.bind(w1,w2) if sh: sh.fix(0.1,0,1) # fixes self-intersecting wires f = Part.Face(sh) if baseface: if layers: baseface.append(f) else: baseface = baseface.fuse(f) # baseface = baseface.removeSplitter() s = DraftGeomUtils.removeSplitter(baseface) if s: baseface = s else: if layers: baseface = [f] else: baseface = f if baseface: base,placement = self.rebase(baseface) else: if layers: totalwidth = sum(layers) offset = 0 base = [] for l in layers: l2 = length/2 or 0.5 w1 = -totalwidth/2 + offset w2 = w1 + l v1 = Vector(-l2,w1,0) v2 = Vector(l2,w1,0) v3 = Vector(l2,w2,0) v4 = Vector(-l2,w2,0) base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))) offset += l else: 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.Face(Part.makePolygon([v1,v2,v3,v4,v1])) placement = FreeCAD.Placement() if base and placement: extrusion = normal.multiply(height) return (base,extrusion,placement) return None
def getExtrusionData(self,obj): """returns (shape,extrusion vector,placement) or None""" import Part,DraftGeomUtils data = ArchComponent.Component.getExtrusionData(self,obj) if data: if not isinstance(data[0],list): # multifuses not considered here return data length = obj.Length.Value width = obj.Width.Value height = obj.Height.Value if not height: for p in obj.InList: if Draft.getType(p) in ["Floor","BuildingPart"]: if p.Height.Value: height = p.Height.Value if not height: return None if obj.Normal == Vector(0,0,0): normal = Vector(0,0,1) else: normal = Vector(obj.Normal) base = None placement = None self.basewires = None # build wall layers layers = [] if hasattr(obj,"Material"): if obj.Material: if hasattr(obj.Material,"Materials"): varwidth = 0 restwidth = width - sum(obj.Material.Thicknesses) if restwidth > 0: varwidth = [t for t in obj.Material.Thicknesses if t == 0] if varwidth: varwidth = restwidth/len(varwidth) for t in obj.Material.Thicknesses: if t: layers.append(t) elif varwidth: layers.append(varwidth) if obj.Base: if obj.Base.isDerivedFrom("Part::Feature"): if obj.Base.Shape: if obj.Base.Shape.Solids: return None elif obj.Face > 0: if len(obj.Base.Shape.Faces) >= obj.Face: face = obj.Base.Shape.Faces[obj.Face-1] # this wall is based on a specific face of its base object if obj.Normal != Vector(0,0,0): normal = face.normalAt(0,0) if normal.getAngle(Vector(0,0,1)) > math.pi/4: normal.multiply(width) base = face.extrude(normal) if obj.Align == "Center": base.translate(normal.negative().multiply(0.5)) elif obj.Align == "Right": base.translate(normal.negative()) else: normal.multiply(height) base = face.extrude(normal) base,placement = self.rebase(base) return (base,normal,placement) elif obj.Base.Shape.Faces: if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces): return None else: base,placement = self.rebase(obj.Base.Shape) elif len(obj.Base.Shape.Edges) == 1: self.basewires = [Part.Wire(obj.Base.Shape.Edges)] else: # self.basewires = obj.Base.Shape.Wires self.basewires = [] for cluster in Part.getSortedClusters(obj.Base.Shape.Edges): for c in Part.sortEdges(cluster): self.basewires.append(Part.Wire(c)) if self.basewires and width: if (len(self.basewires) == 1) and layers: self.basewires = [self.basewires[0] for l in layers] layeroffset = 0 baseface = None for i,wire in enumerate(self.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(normal) if not DraftVecUtils.isNull(dvec): dvec.normalize() sh = None if obj.Align == "Left": off = obj.Offset.Value if layers: off = off+layeroffset dvec.multiply(layers[i]) layeroffset += layers[i] else: dvec.multiply(width) if off: dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Right": dvec = dvec.negative() off = obj.Offset.Value if layers: off = off+layeroffset dvec.multiply(layers[i]) layeroffset += layers[i] else: dvec.multiply(width) if off: dvec2 = DraftVecUtils.scaleTo(dvec,off) wire = DraftGeomUtils.offsetWire(wire,dvec2) w2 = DraftGeomUtils.offsetWire(wire,dvec) w1 = Part.Wire(Part.__sortEdges__(wire.Edges)) sh = DraftGeomUtils.bind(w1,w2) elif obj.Align == "Center": if layers: off = width/2-layeroffset d1 = Vector(dvec).multiply(off) w1 = DraftGeomUtils.offsetWire(wire,d1) layeroffset += layers[i] off = width/2-layeroffset d1 = Vector(dvec).multiply(off) w2 = DraftGeomUtils.offsetWire(wire,d1) else: dvec.multiply(width/2) w1 = DraftGeomUtils.offsetWire(wire,dvec) dvec = dvec.negative() w2 = DraftGeomUtils.offsetWire(wire,dvec) sh = DraftGeomUtils.bind(w1,w2) if sh: sh.fix(0.1,0,1) # fixes self-intersecting wires f = Part.Face(sh) if baseface: if layers: baseface.append(f) else: baseface = baseface.fuse(f) # baseface = baseface.removeSplitter() s = DraftGeomUtils.removeSplitter(baseface) if s: baseface = s else: if layers: baseface = [f] else: baseface = f if baseface: base,placement = self.rebase(baseface) else: if layers: totalwidth = sum(layers) offset = 0 base = [] for l in layers: l2 = length/2 or 0.5 w1 = -totalwidth/2 + offset w2 = w1 + l v1 = Vector(-l2,w1,0) v2 = Vector(l2,w1,0) v3 = Vector(l2,w2,0) v4 = Vector(-l2,w2,0) base.append(Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))) offset += l else: 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.Face(Part.makePolygon([v1,v2,v3,v4,v1])) placement = FreeCAD.Placement() if base and placement: extrusion = normal.multiply(height) if placement.Rotation.Angle > 0: extrusion = placement.inverse().Rotation.multVec(extrusion) return (base,extrusion,placement) return None