示例#1
0
    def doCut(self, cutplane, hidden, clip, clipDepth, shapes):
        objectShapes = []
        sections = []
        faces = []

        shps = []

        # self.reorient()
        # self.filterWrongOrientedFaces()

        for sh in shapes:
            shps.append(sh[0])

        cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
            cutplane, shps, clip=clip)
        planeNormal = self.wp.getNormal()
        planeNormal.normalize()

        if not cutvolume:
            cutface = cutplane
            cutnormal = cutplane.normalAt(0.5, 0.5)
            cutvolume = cutplane.extrude(cutnormal)
            cutnormal = cutnormal.negative()
            invcutvolume = cutplane.extrude(cutnormal)

        if DEBUG:
            print('cutface: %s, cutvolume: %s, invcutvolume: %s' %
                  (cutface, cutvolume, invcutvolume))

        if cutface and cutvolume:
            for sh in shapes:
                for sol in sh[0].Solids:
                    c = sol.cut(cutvolume)
                    objectShapes.append([c]+sh[1:])

                    for f in c.Faces:
                        faceData = FaceData(f, sh[1], sh[2])
                        faceData = self.projectFace(faceData)
                        # TODO: Create temporary face list and filter duplicate faces
                        # Do isCoplanar check later on, when duplicate faces are removed

                        if faceData.correctlyOriented(planeNormal):
                            if DraftGeomUtils.isCoplanar([f, cutface]):
                                sections.append(faceData)
                            else:
                                faces.append(faceData)

                    if hidden:
                        c = sol.cut(invcutvolume)
                        # self.projectEdge(e)
                        self.hiddenEdges.extend(c.Edges)

        if clipDepth > 0:
            faces = [f for f in faces if self.isInRange(
                f.originalFace, clipDepth)]

        return CutResult(objectShapes, sections, faces, cutvolume, cutface)
 def cut(self, cutplane, hidden=False):
     "Cuts through the shapes with a given cut plane and builds section faces"
     if DEBUG: print "\n\n======> Starting cut\n\n"
     if self.iscut:
         return
     if not self.shapes:
         if DEBUG: print "No objects to make sections"
     else:
         fill = (1.0, 1.0, 1.0, 1.0)
         shps = []
         for sh in self.shapes:
             shps.append(sh[0])
         cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
             cutplane, shps)
         if cutface and cutvolume:
             shapes = []
             faces = []
             sections = []
             for sh in self.shapes:
                 for sol in sh[0].Solids:
                     c = sol.cut(cutvolume)
                     shapes.append([c] + sh[1:])
                     for f in c.Faces:
                         faces.append([f] + sh[1:])
                         print "iscoplanar:", f.Vertexes[
                             0].Point, f.normalAt(
                                 0, 0
                             ), cutface.Vertexes[0].Point, cutface.normalAt(
                                 0, 0)
                         if DraftGeomUtils.isCoplanar([f, cutface]):
                             print "COPLANAR"
                             sections.append([f, fill])
                     if hidden:
                         c = sol.cut(invcutvolume)
                         self.hiddenEdges.extend(c.Edges)
             self.shapes = shapes
             self.faces = faces
             self.sections = sections
             if DEBUG:
                 print "Built ", len(self.sections), " sections, ", len(
                     self.faces), " faces retained"
             self.iscut = True
             self.oriented = False
             self.trimmed = False
             self.sorted = False
             self.joined = False
     if DEBUG: print "\n\n======> Finished cut\n\n"
示例#3
0
def fuse(object1, object2):
    """fuse(oject1, object2)
    
    Returns an object made from the union of the 2 given objects. 
    If the objects are coplanar, a special Draft Wire is used, otherwise we use
    a standard Part fuse.
    
    """
    if not App.ActiveDocument:
        App.Console.PrintError("No active document. Aborting\n")
        return
    import Part
    import DraftGeomUtils
    # testing if we have holes:
    holes = False
    fshape = object1.Shape.fuse(object2.Shape)
    fshape = fshape.removeSplitter()
    for f in fshape.Faces:
        if len(f.Wires) > 1:
            holes = True
    if DraftGeomUtils.isCoplanar(object1.Shape.fuse(
            object2.Shape).Faces) and not holes:
        obj = App.ActiveDocument.addObject("Part::Part2DObjectPython",
                                           "Fusion")
        Wire(obj)
        if App.GuiUp:
            ViewProviderWire(obj.ViewObject)
        obj.Base = object1
        obj.Tool = object2
    elif holes:
        # temporary hack, since Part::Fuse objects don't remove splitters
        obj = App.ActiveDocument.addObject("Part::Feature", "Fusion")
        obj.Shape = fshape
    else:
        obj = App.ActiveDocument.addObject("Part::Fuse", "Fusion")
        obj.Base = object1
        obj.Tool = object2
    if App.GuiUp:
        object1.ViewObject.Visibility = False
        object2.ViewObject.Visibility = False
        gui_utils.format_object(obj, object1)
        gui_utils.select(obj)

    return obj
示例#4
0
 def joinFaces(objectslist):
     """makes one big face from selected objects, if possible"""
     faces = []
     for obj in objectslist:
         faces.extend(obj.Shape.Faces)
     u = faces.pop(0)
     for f in faces:
         u = u.fuse(f)
     if DraftGeomUtils.isCoplanar(faces):
         u = DraftGeomUtils.concatenate(u)
         if not DraftGeomUtils.hasCurves(u):
             # several coplanar and non-curved faces: they can become a Draft wire
             newobj = makeWire(u.Wires[0],closed=True,face=True)
         else:
             # if not possible, we do a non-parametric union
             newobj = App.ActiveDocument.addObject("Part::Feature","Union")
             newobj.Shape = u
         addList.append(newobj)
         deleteList.extend(objectslist)
         return newobj
     return None
示例#5
0
 def cut(self,cutplane,hidden=False):
     "Cuts through the shapes with a given cut plane and builds section faces"
     if DEBUG: print "\n\n======> Starting cut\n\n"
     if self.iscut:
         return
     if not self.shapes:
         if DEBUG: print "No objects to make sections"
     else:
         fill = (1.0,1.0,1.0,1.0)
         shps = []
         for sh in self.shapes:
             shps.append(sh[0])
         cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(cutplane,shps)
         if cutface and cutvolume:
             shapes = []
             faces = []
             sections = []
             for sh in self.shapes:
                 for sol in sh[0].Solids:
                     c = sol.cut(cutvolume)
                     shapes.append([c]+sh[1:])
                     for f in c.Faces:
                         faces.append([f]+sh[1:])
                         print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
                         if DraftGeomUtils.isCoplanar([f,cutface]):
                             print "COPLANAR"
                             sections.append([f,fill])
                     if hidden:
                         c = sol.cut(invcutvolume)
                         self.hiddenEdges.extend(c.Edges)
             self.shapes = shapes
             self.faces = faces
             self.sections = sections
             if DEBUG: print "Built ",len(self.sections)," sections, ", len(self.faces), " faces retained"
             self.iscut = True
             self.oriented = False
             self.trimmed = False
             self.sorted = False
             self.joined = False
     if DEBUG: print "\n\n======> Finished cut\n\n"
示例#6
0
    def getProfiles(self, obj, noplacement=False):
        "Returns the base profile(s) of this component, if applicable"
        wires = []
        if Draft.getType(obj) == "Precast":
            return wires
        n, l, w, h = self.getDefaultValues(obj)
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Extrusion"):
                if obj.Base.Base:
                    base = obj.Base.Base.Shape.copy()
                    #if noplacement:
                    #    base.Placement = FreeCAD.Placement()
                    return [base]
            elif 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:
                            import DraftGeomUtils
                            if not DraftGeomUtils.isCoplanar(base.Faces):
                                return []
                            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(
                                            Part.__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(
                                            Part.__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)
        elif Draft.getType(obj) in ["Wall", "Structure"]:
            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
示例#7
0
    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
示例#8
0
文件: wire.py 项目: zikpuppy/FreeCAD
    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")
示例#9
0
    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
示例#10
0
    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::Extrusion"):
                if obj.Base.Base:
                    base = obj.Base.Base.Shape.copy()
                    if noplacement:
                        base.Placement = FreeCAD.Placement()
                    return [base]
            elif 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:
                            import DraftGeomUtils
                            if not DraftGeomUtils.isCoplanar(base.Faces):
                                return []
                            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(Part.__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(Part.__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)
        elif Draft.getType(obj) in ["Wall","Structure"]:
            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
示例#11
0
 def getExtrusionData(self,obj):
     """returns (shape,extrusion vector,placement) or None"""
     import Part,DraftGeomUtils
     data = ArchComponent.Component.getExtrusionData(self,obj)
     if data:
         return data
     length  = obj.Length.Value
     width = obj.Width.Value
     height = obj.Height.Value
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/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 = 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)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
示例#12
0
 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) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     if obj.Normal == Vector(0,0,0):
         normal = Vector(0,0,1)
     else:
         normal = Vector(obj.Normal)
     base = None
     placement = None
     basewires = None
     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 obj.Base.Shape.Wires:
                     basewires = obj.Base.Shape.Wires
                 elif len(obj.Base.Shape.Edges) == 1:
                     basewires = [Part.Wire(obj.Base.Shape.Edges)]
                 if basewires and width:
                     baseface = None
                     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(normal)
                         if not DraftVecUtils.isNull(dvec):
                             dvec.normalize()
                         sh = None
                         if obj.Align == "Left":
                             dvec.multiply(width)
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 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.multiply(width)
                             dvec = dvec.negative()
                             if obj.Offset.Value:
                                 dvec2 = DraftVecUtils.scaleTo(dvec,obj.Offset.Value)
                                 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":
                             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:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                     if baseface:
                         base,placement = self.rebase(baseface)
     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
示例#13
0
 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
     normal = None
     if not height:
         for p in obj.InList:
             if Draft.getType(p) == "Floor":
                 if p.Height.Value:
                     height = p.Height.Value
     base = None
     placement = None
     if obj.Base:
         if obj.Base.isDerivedFrom("Part::Feature"):
             if obj.Base.Shape:
                 if obj.Base.Shape.Solids:
                     return None
                 elif obj.Base.Shape.Faces:
                     if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                         return None
                     else:
                         base,placement = self.rebase(obj.Base.Shape)
                         normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                 elif obj.Base.Shape.Wires:
                     baseface = None
                     if hasattr(obj,"FaceMaker"):
                         if obj.FaceMaker != "None":
                             try:
                                 baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                             except:
                                 FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                 return None
                             if len(baseface.Faces) > 1:
                                 baseface = baseface.Faces[0]
                             normal = baseface.normalAt(0,0)
                     if not baseface:
                         for w in obj.Base.Shape.Wires:
                             w.fix(0.1,0,1) # fixes self-intersecting wires
                             f = Part.Face(w)
                             if baseface:
                                 baseface = baseface.fuse(f)
                             else:
                                 baseface = f
                                 normal = f.normalAt(0,0)
                     base,placement = self.rebase(baseface)
                 elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                     # closed edge
                     w = Part.Wire(obj.Base.Shape.Edges[0])
                     baseface = Part.Face(w)
                     base,placement = self.rebase(baseface)
     elif length and width and height:
         if (length > height) and (obj.Role != "Slab"):
             h2 = height/2 or 0.5
             w2 = width/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 = 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)
         import Part
         baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
         base,placement = self.rebase(baseface)
     if base and placement:
         if obj.Normal == Vector(0,0,0):
             if not normal:
                 normal = Vector(0,0,1)
         else:
             normal = Vector(obj.Normal)
         if (length > height) and (obj.Role != "Slab"):
             extrusion = normal.multiply(length)
         else:
             extrusion = normal.multiply(height)
         return (base,extrusion,placement)
     return None
示例#14
0
    def cut(self,cutplane):
        "Cuts through the shapes with a given cut plane and builds section faces"
        if DEBUG: print "\n\n======> Starting cut\n\n"
        if self.iscut:
            return
        if not self.shapes:
            if DEBUG: print "No objects to make sections"
        else:
            fill = (1.0,1.0,1.0,1.0)
            placement = FreeCAD.Placement(cutplane.Placement)

            # building boundbox
            bb = self.shapes[0][0].BoundBox 
            for sh in self.shapes[1:]:
                bb.add(sh[0].BoundBox)
            bb.enlarge(1)
            um = vm = wm = 0
            if not bb.isCutPlane(placement.Base,self.wp.axis):
                if DEBUG: print "No objects are cut by the plane"
            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(placement.Base)
                    um1 = DraftVecUtils.project(dv,self.wp.u).Length
                    um = max(um,um1)
                    vm1 = DraftVecUtils.project(dv,self.wp.v).Length
                    vm = max(vm,vm1)
                    wm1 = DraftVecUtils.project(dv,self.wp.axis).Length
                    wm = max(wm,wm1)
                p1 = FreeCAD.Vector(-um,vm,0)
                p2 = FreeCAD.Vector(um,vm,0)
                p3 = FreeCAD.Vector(um,-vm,0)
                p4 = FreeCAD.Vector(-um,-vm,0)
                cutface = Part.makePolygon([p1,p2,p3,p4,p1])
                cutface = Part.Face(cutface)
                cutface.Placement = placement
                cutnormal = DraftVecUtils.scaleTo(self.wp.axis,wm)
                cutvolume = cutface.extrude(cutnormal)
                shapes = []
                faces = []
                sections = []
                for sh in self.shapes:
                    for sol in sh[0].Solids:
                        c = sol.cut(cutvolume)
                        shapes.append([c]+sh[1:])
                        for f in c.Faces:
                            faces.append([f]+sh[1:])
                            print "iscoplanar:",f.Vertexes[0].Point,f.normalAt(0,0),cutface.Vertexes[0].Point,cutface.normalAt(0,0)
                            if DraftGeomUtils.isCoplanar([f,cutface]):
                                print "COPLANAR"
                                sections.append([f,fill])
                self.shapes = shapes
                self.faces = faces
                self.sections = sections
                if DEBUG: print "Built ",len(self.sections)," sections, ", len(self.faces), " faces retained"
                self.iscut = True
                self.oriented = False
                self.trimmed = False
                self.sorted = False
                self.joined = False
        if DEBUG: print "\n\n======> Finished cut\n\n"
示例#15
0
    def getExtrusionData(self,obj):

        """returns (shape,extrusion vector,placement) or None"""

        if hasattr(obj,"IfcRole"):
            role = obj.IfcRole
        else:
            role = obj.Role
        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
        normal = None
        if not height:
            for p in obj.InList:
                if Draft.getType(p) in ["Floor","BuildingPart"]:
                    if p.Height.Value:
                        height = p.Height.Value
        base = None
        placement = None
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        return None
                    elif obj.Base.Shape.Faces:
                        if not DraftGeomUtils.isCoplanar(obj.Base.Shape.Faces):
                            return None
                        else:
                            base,placement = self.rebase(obj.Base.Shape)
                            normal = obj.Base.Shape.Faces[0].normalAt(0,0)
                            normal = placement.inverse().Rotation.multVec(normal)
                    elif obj.Base.Shape.Wires:
                        baseface = None
                        if hasattr(obj,"FaceMaker"):
                            if obj.FaceMaker != "None":
                                try:
                                    baseface = Part.makeFace(obj.Base.Shape.Wires,"Part::FaceMaker"+str(obj.FaceMaker))
                                except:
                                    FreeCAD.Console.PrintError(translate("Arch","Facemaker returned an error")+"\n")
                                    return None
                                if len(baseface.Faces) > 1:
                                    baseface = baseface.Faces[0]
                                normal = baseface.normalAt(0,0)
                        if not baseface:
                            for w in obj.Base.Shape.Wires:
                                if not w.isClosed():
                                    p0 = w.OrderedVertexes[0].Point
                                    p1 = w.OrderedVertexes[-1].Point
                                    if p0 != p1:
                                        e = Part.Line(p0,p1).toShape()
                                        w.add(e)
                                w.fix(0.1,0,1) # fixes self-intersecting wires
                                f = Part.Face(w)
                                if baseface:
                                    baseface = baseface.fuse(f)
                                else:
                                    baseface = f
                                    normal = f.normalAt(0,0)
                        base,placement = self.rebase(baseface)
                        normal = placement.inverse().Rotation.multVec(normal)
                    elif (len(obj.Base.Shape.Edges) == 1) and (len(obj.Base.Shape.Vertexes) == 1):
                        # closed edge
                        w = Part.Wire(obj.Base.Shape.Edges[0])
                        baseface = Part.Face(w)
                        base,placement = self.rebase(baseface)
        elif length and width and height:
            if (length > height) and (role != "Slab"):
                h2 = height/2 or 0.5
                w2 = width/2 or 0.5
                v1 = Vector(0,-w2,-h2)
                v4 = Vector(0,-w2,h2)
                v3 = Vector(0,w2,h2)
                v2 = Vector(0,w2,-h2)
            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)
            import Part
            baseface = Part.Face(Part.makePolygon([v1,v2,v3,v4,v1]))
            base,placement = self.rebase(baseface)
        if base and placement:
            if obj.Normal.Length:
                normal = Vector(obj.Normal)
                normal = placement.inverse().Rotation.multVec(normal)
            if not normal:
                normal = Vector(0,0,1)
            if not normal.Length:
                normal = Vector(0,0,1)
            extrusion = normal
            if (length > height) and (role != "Slab"):
                if length:
                    extrusion = normal.multiply(length)
            else:
                if height:
                    extrusion = normal.multiply(height)
            return (base,extrusion,placement)
        return None