Esempio n. 1
0
 def getArea(self,obj):
     "returns the horizontal area at the center of the space"
     import Part,DraftGeomUtils
     if not hasattr(obj.Shape,"CenterOfMass"):
         return 0
     try:
         pl = Part.makePlane(1,1)
         pl.translate(obj.Shape.CenterOfMass)
         sh = obj.Shape.copy()
         cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
         e = sh.section(cutplane)
         e = Part.__sortEdges__(e.Edges)
         w = Part.Wire(e)
         f = Part.Face(w)
     except Part.OCCError:
         return 0
     else:
         if hasattr(obj,"PerimeterLength"):
             if w.Length != obj.PerimeterLength.Value:
                 obj.PerimeterLength = w.Length
         if hasattr(obj,"VerticalArea"):
             a = 0
             for f in sh.Faces:
                 ang = f.normalAt(0,0).getAngle(FreeCAD.Vector(0,0,1))
                 if (ang > 1.57) and (ang < 1.571):
                     a += f.Area
                 if a != obj.VerticalArea.Value:
                     obj.VerticalArea = a
         #print "area of ",obj.Label," : ",f.Area
         return f.Area
 def execute(self, obj):
     #print("TimberMachiningCut Start Execute")
     face = obj.Face
     faceObject = face[0]
     faceNumber = int(face[1][0][4:]) - 1
     face = faceObject.Shape.Faces[faceNumber]
     structure = obj.Structure
     cutVolume = ArchCommands.getCutVolume(face, structure.Shape)
     machining = cutVolume[2].common(beam.Shape)
     obj.Shape = machining
Esempio n. 3
0
 def previewCutVolume(self, i):
     cutVolume = ArchCommands.getCutVolume(FreeCADGui.Selection.getSelectionEx()[1].SubObjects[0], FreeCADGui.Selection.getSelectionEx()[0].Object.Shape)
     FreeCAD.ActiveDocument.removeObject(self.previewObj.Name)
     self.previewObj = FreeCAD.ActiveDocument.addObject("Part::Feature", "PreviewCutVolume")
     self.previewObj.ViewObject.ShapeColor = (1.00,0.00,0.00)
     self.previewObj.ViewObject.Transparency = 75
     if i == 1:
         cutVolume = cutVolume[1]
     else:
         cutVolume = cutVolume[2]
     if cutVolume:
         self.previewObj.Shape = cutVolume
def cutComponentwithPlane(archObject, cutPlane, sideFace):
    """cut object from a plan define by a face, Behind = 0 , front = 1"""
    cutVolume = ArchCommands.getCutVolume(cutPlane, archObject.Object.Shape)
    if sideFace == 0:
        cutVolume = cutVolume[2]
    else:
        cutVolume = cutVolume[1]
    if cutVolume:
        obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "CutVolume")
        obj.Shape = cutVolume
        # add substraction component to Arch object
        return ArchCommands.removeComponents(obj,archObject.Object)
 def getArea(self,obj):
     "returns the horizontal area at the center of the space"
     import Part,DraftGeomUtils
     try:
         pl = Part.makePlane(1,1)
         sh = obj.Shape.copy()
         cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
         e = sh.section(cutplane)
         e = DraftGeomUtils.sortEdges(e.Edges)
         w = Part.Wire(e)
         f = Part.Face(w)
         return round(f.Area,Draft.getParam("dimPrecision",6))
     except:
         return 0
Esempio n. 6
0
 def getArea(self,obj):
     "returns the horizontal area at the center of the space"
     import Part,DraftGeomUtils
     try:
         pl = Part.makePlane(1,1)
         pl.translate(obj.Shape.CenterOfMass)
         sh = obj.Shape.copy()
         cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
         e = sh.section(cutplane)
         e = DraftGeomUtils.sortEdges(e.Edges)
         w = Part.Wire(e)
         f = Part.Face(w)
         return f.Area
     except:
         return 0
Esempio n. 7
0
def cutComponentwithPlane(archObject, cutPlane, sideFace):
    """cut object from a plan define by a face, Behind = 0 , front = 1"""
    cutVolume = ArchCommands.getCutVolume(cutPlane, archObject.Object.Shape)
    if sideFace == 0:
        cutVolume = cutVolume[2]
    else:
        cutVolume = cutVolume[1]
    if cutVolume:
        obj = FreeCAD.ActiveDocument.addObject("Part::Feature", "CutVolume")
        obj.Shape = cutVolume
        obj.ViewObject.ShapeColor = (1.00, 0.00, 0.00)
        obj.ViewObject.Transparency = 75
        if "Additions" in archObject.Object.PropertiesList:
            return ArchCommands.removeComponents(obj, archObject.Object)
        else:
            cutObj = FreeCAD.ActiveDocument.addObject("Part::Cut", "CutPlane")
            cutObj.Base = archObject.Object
            cutObj.Tool = obj
            return cutObj
Esempio n. 8
0
def getCutShapes(objs, section, showHidden):
    import Part, DraftGeomUtils
    shapes = []
    hshapes = []
    sshapes = []
    for o in objs:
        if o.isDerivedFrom("Part::Feature"):
            if o.Shape.isNull():
                pass
            elif section.OnlySolids:
                if o.Shape.isValid():
                    shapes.extend(o.Shape.Solids)
                else:
                    print section.Label, ": Skipping invalid object:", o.Label
            else:
                shapes.append(o.Shape)
    cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
        section.Shape.copy(), shapes)
    if cutvolume:
        nsh = []
        for sh in shapes:
            for sol in sh.Solids:
                if sol.Volume < 0:
                    sol.reverse()
                c = sol.cut(cutvolume)
                s = sol.section(cutface)
                try:
                    wires = DraftGeomUtils.findWires(s.Edges)
                    for w in wires:
                        f = Part.Face(w)
                        sshapes.append(f)
                    #s = Part.Wire(s.Edges)
                    #s = Part.Face(s)
                except Part.OCCError:
                    #print "ArchDrawingView: unable to get a face"
                    sshapes.append(s)
                nsh.extend(c.Solids)
                #sshapes.append(s)
                if showHidden:
                    c = sol.cut(invcutvolume)
                    hshapes.append(c)
        shapes = nsh
    return shapes, hshapes, sshapes, cutface, cutvolume, invcutvolume
Esempio n. 9
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")
Esempio n. 10
0
def cutComponentwithPlane(archObject, cutPlane, sideFace):
    """cut object from a plan define by a face, Behind = 0 , front = 1"""
    cutVolume = ArchCommands.getCutVolume(cutPlane, archObject.Object.Shape)
    if sideFace == 0:
        cutVolume = cutVolume[2]
    else:
        cutVolume = cutVolume[1]
    if cutVolume:
        obj = FreeCAD.ActiveDocument.addObject("Part::Feature", str(translate("Arch","CutVolume")))
        obj.Shape = cutVolume
        obj.ViewObject.ShapeColor = (1.00,0.00,0.00)
        obj.ViewObject.Transparency = 75
        if "Additions" in archObject.Object.PropertiesList:
            return ArchCommands.removeComponents(obj,archObject.Object)
        else:
            cutObj = FreeCAD.ActiveDocument.addObject("Part::Cut", str(translate("Arch","CutPlane")))
            cutObj.Base = archObject.Object
            cutObj.Tool = obj
            return cutObj
def getCutShapes(objs,section,showHidden):

    import Part,DraftGeomUtils
    shapes = []
    hshapes = []
    sshapes = []
    for o in objs:
        if o.isDerivedFrom("Part::Feature"):
            if o.Shape.isNull():
                pass
            elif section.OnlySolids:
                if o.Shape.isValid():
                    shapes.extend(o.Shape.Solids)
                else:
                    print(section.Label,": Skipping invalid object:",o.Label)
            else:
                shapes.append(o.Shape)
    cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes)
    if cutvolume:
        nsh = []
        for sh in shapes:
            for sol in sh.Solids:
                if sol.Volume < 0:
                    sol.reverse()
                c = sol.cut(cutvolume)
                s = sol.section(cutface)
                try:
                    wires = DraftGeomUtils.findWires(s.Edges)
                    for w in wires:
                        f = Part.Face(w)
                        sshapes.append(f)
                    #s = Part.Wire(s.Edges)
                    #s = Part.Face(s)
                except Part.OCCError:
                    #print "ArchDrawingView: unable to get a face"
                    sshapes.append(s)
                nsh.extend(c.Solids)
                #sshapes.append(s)
                if showHidden:
                    c = sol.cut(invcutvolume)
                    hshapes.append(c)
        shapes = nsh
    return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume
Esempio n. 12
0
    def getFootprint(self,obj):

        "returns a face that represents the footprint of this space"

        import Part,DraftGeomUtils
        if not hasattr(obj.Shape,"CenterOfMass"):
            return None
        try:
            pl = Part.makePlane(1,1)
            pl.translate(obj.Shape.CenterOfMass)
            sh = obj.Shape.copy()
            cutplane,v1,v2 = ArchCommands.getCutVolume(pl,sh)
            e = sh.section(cutplane)
            e = Part.__sortEdges__(e.Edges)
            w = Part.Wire(e)
            dv = FreeCAD.Vector(obj.Shape.CenterOfMass.x,obj.Shape.CenterOfMass.y,obj.Shape.BoundBox.ZMin)
            dv = dv.sub(obj.Shape.CenterOfMass)
            w.translate(dv)
            return Part.Face(w)
        except Part.OCCError:
            return None
Esempio n. 13
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"
Esempio n. 14
0
    def execute(self, obj):

        tol = 1  # tolerance for alignment. This is only visual, we can keep it low...
        ptol = 0.001  # tolerance for coincident points

        import math, Part, DraftGeomUtils, ArchCommands
        if len(obj.Pipes) < 2:
            return
        if len(obj.Pipes) > 3:
            FreeCAD.Console.PrintWarning(
                translate("Arch", "Only the 3 first wires will be connected") +
                "\n")
        if obj.Radius.Value == 0:
            return
        wires = []
        order = []
        for o in obj.Pipes:
            wires.append(o.Proxy.getWire(o))
        if wires[0].Vertexes[0].Point.sub(
                wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["start", "start"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[0].Point.sub(
                wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["start", "end"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[-1].Point.sub(
                wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["end", "end"]
            point = wires[0].Vertexes[-1].Point
        elif wires[0].Vertexes[-1].Point.sub(
                wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["end", "start"]
            point = wires[0].Vertexes[-1].Point
        else:
            FreeCAD.Console.PrintError(
                translate("Arch", "Common vertex not found") + "\n")
            return
        if order[0] == "start":
            v1 = wires[0].Vertexes[1].Point.sub(
                wires[0].Vertexes[0].Point).normalize()
        else:
            v1 = wires[0].Vertexes[-2].Point.sub(
                wires[0].Vertexes[-1].Point).normalize()
        if order[1] == "start":
            v2 = wires[1].Vertexes[1].Point.sub(
                wires[1].Vertexes[0].Point).normalize()
        else:
            v2 = wires[1].Vertexes[-2].Point.sub(
                wires[1].Vertexes[-1].Point).normalize()
        p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0])
        p = Part.Face(p)
        if len(obj.Pipes) == 2:
            if obj.ConnectorType != "Corner":
                obj.ConnectorType = "Corner"
            if round(v1.getAngle(v2), tol) in [0, round(math.pi, tol)]:
                FreeCAD.Console.PrintError(
                    translate("Arch", "Pipes are already aligned") + "\n")
                return
            normal = v2.cross(v1)
            offset = math.tan(math.pi / 2 -
                              v1.getAngle(v2) / 2) * obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            self.setOffset(obj.Pipes[0], order[0], offset)
            self.setOffset(obj.Pipes[1], order[1], offset)
            # find center
            perp = v1.cross(normal).normalize()
            perp.multiply(obj.Radius.Value)
            center = point.add(v1).add(perp)
            # move and rotate the profile to the first point
            delta = point.add(v1) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, v1)
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            sh = p.revolve(center, normal,
                           math.degrees(math.pi - v1.getAngle(v2)))
            #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))])
        else:
            if obj.ConnectorType != "Tee":
                obj.ConnectorType = "Tee"
            if wires[2].Vertexes[0].Point == point:
                order.append("start")
            elif wires[0].Vertexes[-1].Point == point:
                order.append("end")
            else:
                FreeCAD.Console.PrintError(
                    translate("Arch", "Common vertex not found") + "\n")
            if order[2] == "start":
                v3 = wires[2].Vertexes[1].Point.sub(
                    wires[2].Vertexes[0].Point).normalize()
            else:
                v3 = wires[2].Vertexes[-2].Point.sub(
                    wires[2].Vertexes[-1].Point).normalize()
            if round(v1.getAngle(v2), tol) in [0, round(math.pi, tol)]:
                pair = [v1, v2, v3]
            elif round(v1.getAngle(v3), tol) in [0, round(math.pi, tol)]:
                pair = [v1, v3, v2]
            elif round(v2.getAngle(v3), tol) in [0, round(math.pi, tol)]:
                pair = [v2, v3, v1]
            else:
                FreeCAD.Console.PrintError(
                    translate("Arch", "At least 2 pipes must align") + "\n")
                return
            offset = obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            v3.multiply(offset)
            self.setOffset(obj.Pipes[0], order[0], offset)
            self.setOffset(obj.Pipes[1], order[1], offset)
            self.setOffset(obj.Pipes[2], order[2], offset)
            normal = pair[0].cross(pair[2])
            # move and rotate the profile to the first point
            delta = point.add(pair[0]) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, pair[0])
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            t1 = p.extrude(pair[1].multiply(2))
            # move and rotate the profile to the second point
            delta = point.add(pair[2]) - p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp, pair[2])
            p.rotate(p.CenterOfMass, rot.Axis, math.degrees(rot.Angle))
            t2 = p.extrude(pair[2].negative().multiply(2))
            # create a cut plane
            cp = Part.makePolygon(
                [point, point.add(pair[0]),
                 point.add(normal), point])
            cp = Part.Face(cp)
            if cp.normalAt(0, 0).getAngle(pair[2]) < math.pi / 2:
                cp.reverse()
            cf, cv, invcv = ArchCommands.getCutVolume(cp, t2)
            t2 = t2.cut(cv)
            sh = t1.fuse(t2)
        obj.Shape = sh
Esempio n. 15
0
    def updateSVG(self, obj,join=False):
        "encapsulates a svg fragment into a transformation node"
        import Part, DraftGeomUtils
        if hasattr(obj,"Source"):
            if obj.Source:
                if obj.Source.Objects:
                    objs = Draft.getGroupContents(obj.Source.Objects)
                    objs = Draft.removeHidden(objs)
                    svg = ''

                    # generating SVG
                    linewidth = obj.LineWidth/obj.Scale        
                    if obj.RenderingMode == "Solid":
                        # render using the Arch Vector Renderer                        
                        import ArchVRM
                        render = ArchVRM.Renderer()
                        render.setWorkingPlane(obj.Source.Placement)
                        render.addObjects(Draft.getGroupContents(objs,walls=True))
                        render.cut(obj.Source.Shape)
                        svg += render.getViewSVG(linewidth=linewidth)
                        svg += render.getSectionSVG(linewidth=linewidth*2)
                        # print render.info()
                        
                    else:
                        # render using the Drawing module
                        import Drawing, Part
                        shapes = []
                        p = FreeCAD.Placement(obj.Source.Placement)
                        direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
                        for o in objs:
                            if o.isDerivedFrom("Part::Feature"):
                                shapes.extend(o.Shape.Solids)
                        cutface,cutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
                        if cutvolume:
                            nsh = []
                            for sh in shapes:
                                for sol in sh.Solids:
                                    c = sol.cut(cutvolume)
                                    nsh.append(c)
                            shapes = nsh
                        base = Part.makeCompound(shapes)
                        #if shapes:
                        #    base = shapes.pop().copy()
                        #for sh in shapes:
                        #    try:
                        #        base = base.fuse(sh)
                        #    except:
                        #        print "unable to fuse, passing..."
                        svgf = Drawing.projectToSVG(base,direction)
                        if svgf:
                            svgf = svgf.replace('stroke-width="0.35"','stroke-width="' + str(linewidth) + 'px"')
                            svgf = svgf.replace('stroke-width="1"','stroke-width="' + str(linewidth) + 'px"')
                            svgf = svgf.replace('stroke-width:0.01','stroke-width:' + str(linewidth) + 'px')
                        svg += svgf

                    result = ''
                    result += '<g id="' + obj.Name + '"'
                    result += ' transform="'
                    result += 'rotate('+str(obj.Rotation)+','+str(obj.X)+','+str(obj.Y)+') '
                    result += 'translate('+str(obj.X)+','+str(obj.Y)+') '
                    result += 'scale('+str(obj.Scale)+','+str(-obj.Scale)+')'
                    result += '">\n'
                    result += svg
                    result += '</g>\n'
                    # print "complete node:",result
                    return result
        return ''
Esempio n. 16
0
    def getShape(self, obj):
        "computes a shape from a base shape and/or bounday faces"
        import Part
        shape = None
        faces = []

        #print "starting compute"
        # 1: if we have a base shape, we use it

        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Solids:
                    shape = obj.Base.Shape.Solids[0].copy()
                    shape = shape.removeSplitter()

        # 2: if not, add all bounding boxes of considered objects and build a first shape
        if shape:
            #print "got shape from base object"
            bb = shape.BoundBox
        else:
            bb = None
            for b in obj.Boundaries:
                if b[0].isDerivedFrom("Part::Feature"):
                    if not bb:
                        bb = b[0].Shape.BoundBox
                    else:
                        bb.add(b[0].Shape.BoundBox)
            if not bb:
                return
            shape = Part.makeBox(bb.XLength, bb.YLength, bb.ZLength,
                                 FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin))
            #print "created shape from boundbox"

        # 3: identifing boundary faces
        goodfaces = []
        for b in obj.Boundaries:
            if b[0].isDerivedFrom("Part::Feature"):
                if "Face" in b[1]:
                    fn = int(b[1][4:]) - 1
                    faces.append(b[0].Shape.Faces[fn])
                    #print "adding face ",fn," of object ",b[0].Name

        #print "total: ", len(faces), " faces"

        # 4: get cutvolumes from faces
        cutvolumes = []
        for f in faces:
            f = f.copy()
            f.reverse()
            cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
                f, shape)
            if cutvolume:
                #print "generated 1 cutvolume"
                cutvolumes.append(cutvolume.copy())
                #Part.show(cutvolume)
        for v in cutvolumes:
            #print "cutting"
            shape = shape.cut(v)

        # 5: get the final shape
        if shape:
            if shape.Solids:
                #print "setting objects shape"
                shape = shape.Solids[0]
                obj.Shape = shape
                return

        print "Arch: error computing space boundary"
Esempio n. 17
0
    def getShape(self,obj):

        "computes a shape from a base shape and/or bounday faces"
        import Part
        shape = None
        faces = []

        pl = obj.Placement

        #print("starting compute")
        # 1: if we have a base shape, we use it

        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Solids:
                    shape = obj.Base.Shape.copy()
                    shape = shape.removeSplitter()

        # 2: if not, add all bounding boxes of considered objects and build a first shape
        if shape:
            #print("got shape from base object")
            bb = shape.BoundBox
        else:
            bb = None
            for b in obj.Boundaries:
                if b[0].isDerivedFrom("Part::Feature"):
                    if not bb:
                        bb = b[0].Shape.BoundBox
                    else:
                        bb.add(b[0].Shape.BoundBox)
            if not bb:
                return
            shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin))
            #print("created shape from boundbox")

        # 3: identifying boundary faces
        goodfaces = []
        for b in obj.Boundaries:
                if b[0].isDerivedFrom("Part::Feature"):
                    for sub in b[1]:
                        if "Face" in sub:
                            fn = int(sub[4:])-1
                            faces.append(b[0].Shape.Faces[fn])
                            #print("adding face ",fn," of object ",b[0].Name)

        #print("total: ", len(faces), " faces")

        # 4: get cutvolumes from faces
        cutvolumes = []
        for f in faces:
            f = f.copy()
            f.reverse()
            cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape)
            if cutvolume:
                #print("generated 1 cutvolume")
                cutvolumes.append(cutvolume.copy())
                #Part.show(cutvolume)
        for v in cutvolumes:
            #print("cutting")
            shape = shape.cut(v)

        # 5: get the final shape
        if shape:
            if shape.Solids:
                #print("setting objects shape")
                shape = shape.Solids[0]
                obj.Shape = shape
                #pl = pl.multiply(obj.Placement)
                obj.Placement = pl
                if hasattr(obj.Area,"Value"):
                    a = self.getArea(obj)
                    if obj.Area.Value != a:
                        obj.Area = a
                return

        print("Arch: error computing space boundary")
Esempio n. 18
0
    def execute(self,obj):
        
        tol = 1 # tolerance for alignment. This is only visual, we can keep it low...
        ptol = 0.001 # tolerance for coincident points

        import math,Part,DraftGeomUtils,ArchCommands
        if len(obj.Pipes) < 2:
            return
        if len(obj.Pipes) > 3:
            FreeCAD.Console.PrintWarning(translate("Arch","Only the 3 first wires will be connected")+"\n")
        if obj.Radius.Value == 0:
            return
        wires = []
        order = []
        for o in obj.Pipes:
            wires.append(o.Proxy.getWire(o))
        if wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["start","start"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[0].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["start","end"]
            point = wires[0].Vertexes[0].Point
        elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[-1].Point).Length <= ptol:
            order = ["end","end"]
            point = wires[0].Vertexes[-1].Point
        elif wires[0].Vertexes[-1].Point.sub(wires[1].Vertexes[0].Point).Length <= ptol:
            order = ["end","start"]
            point = wires[0].Vertexes[-1].Point
        else:
            FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n")
            return
        if order[0] == "start":
            v1 = wires[0].Vertexes[1].Point.sub(wires[0].Vertexes[0].Point).normalize()
        else:
            v1 = wires[0].Vertexes[-2].Point.sub(wires[0].Vertexes[-1].Point).normalize()
        if order[1] == "start":
            v2 = wires[1].Vertexes[1].Point.sub(wires[1].Vertexes[0].Point).normalize()
        else:
            v2 = wires[1].Vertexes[-2].Point.sub(wires[1].Vertexes[-1].Point).normalize()
        p = obj.Pipes[0].Proxy.getProfile(obj.Pipes[0])
        p = Part.Face(p)
        if len(obj.Pipes) == 2:
            if obj.ConnectorType != "Corner":
                obj.ConnectorType = "Corner"
            if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]:
                FreeCAD.Console.PrintError(translate("Arch","Pipes are already aligned")+"\n")
                return
            normal = v2.cross(v1)
            offset = math.tan(math.pi/2-v1.getAngle(v2)/2)*obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            self.setOffset(obj.Pipes[0],order[0],offset)
            self.setOffset(obj.Pipes[1],order[1],offset)
            # find center
            perp = v1.cross(normal).normalize()
            perp.multiply(obj.Radius.Value)
            center = point.add(v1).add(perp)
            # move and rotate the profile to the first point
            delta = point.add(v1)-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,v1)
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            sh = p.revolve(center,normal,math.degrees(math.pi-v1.getAngle(v2)))
            #sh = Part.makeCompound([sh]+[Part.Vertex(point),Part.Vertex(point.add(v1)),Part.Vertex(center),Part.Vertex(point.add(v2))])
        else:
            if obj.ConnectorType != "Tee":
                obj.ConnectorType = "Tee"
            if wires[2].Vertexes[0].Point == point:
                order.append("start")
            elif wires[0].Vertexes[-1].Point == point:
                order.append("end")
            else:
                FreeCAD.Console.PrintError(translate("Arch","Common vertex not found")+"\n")
            if order[2] == "start":
                v3 = wires[2].Vertexes[1].Point.sub(wires[2].Vertexes[0].Point).normalize()
            else:
                v3 = wires[2].Vertexes[-2].Point.sub(wires[2].Vertexes[-1].Point).normalize()
            if round(v1.getAngle(v2),tol) in [0,round(math.pi,tol)]:
                pair = [v1,v2,v3]
            elif round(v1.getAngle(v3),tol) in [0,round(math.pi,tol)]:
                pair = [v1,v3,v2]
            elif round(v2.getAngle(v3),tol) in [0,round(math.pi,tol)]:
                pair = [v2,v3,v1]
            else:
                FreeCAD.Console.PrintError(translate("Arch","At least 2 pipes must aligned")+"\n")
                return
            offset = obj.Radius.Value
            v1.multiply(offset)
            v2.multiply(offset)
            v3.multiply(offset)
            self.setOffset(obj.Pipes[0],order[0],offset)
            self.setOffset(obj.Pipes[1],order[1],offset)
            self.setOffset(obj.Pipes[2],order[2],offset)
            normal = pair[0].cross(pair[2])
            # move and rotate the profile to the first point
            delta = point.add(pair[0])-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,pair[0])
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            t1 = p.extrude(pair[1].multiply(2))
            # move and rotate the profile to the second point
            delta = point.add(pair[2])-p.CenterOfMass
            p.translate(delta)
            vp = DraftGeomUtils.getNormal(p)
            rot = FreeCAD.Rotation(vp,pair[2])
            p.rotate(p.CenterOfMass,rot.Axis,math.degrees(rot.Angle))
            t2 = p.extrude(pair[2].negative().multiply(2))
            # create a cut plane
            cp = Part.makePolygon([point,point.add(pair[0]),point.add(normal),point])
            cp = Part.Face(cp)
            if cp.normalAt(0,0).getAngle(pair[2]) < math.pi/2:
                cp.reverse()
            cf, cv, invcv = ArchCommands.getCutVolume(cp,t2)
            t2 = t2.cut(cv)
            sh = t1.fuse(t2)
        obj.Shape = sh
Esempio n. 19
0
def getCutShapes(objs, section, showHidden, groupSshapesByObject=False):

    import Part, DraftGeomUtils
    shapes = []
    hshapes = []
    sshapes = []
    objectShapes = []
    objectSshapes = []
    for o in objs:
        if o.isDerivedFrom("Part::Feature"):
            if o.Shape.isNull():
                pass
            elif section.OnlySolids:
                if o.Shape.isValid():
                    solids = []
                    solids.extend(o.Shape.Solids)

                    shapes.extend(solids)

                    objectShapes.append((o, solids))
                else:
                    print(section.Label, ": Skipping invalid object:", o.Label)
            else:
                shapes.append(o.Shape)
                objectShapes.append((o, [o.Shape]))
    cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
        section.Shape.copy(), shapes)
    if cutvolume:
        for o, shapeList in objectShapes:
            tmpSshapes = []
            for sh in shapeList:
                for sol in sh.Solids:
                    if sol.Volume < 0:
                        sol.reverse()
                    c = sol.cut(cutvolume)
                    s = sol.section(cutface)
                    try:
                        wires = DraftGeomUtils.findWires(s.Edges)
                        for w in wires:
                            f = Part.Face(w)
                            tmpSshapes.append(f)
                        #s = Part.Wire(s.Edges)
                        #s = Part.Face(s)
                    except Part.OCCError:
                        #print "ArchDrawingView: unable to get a face"
                        tmpSshapes.append(s)
                    shapes.extend(c.Solids)
                    #sshapes.append(s)
                    if showHidden:
                        c = sol.cut(invcutvolume)
                        hshapes.append(c)

            if len(tmpSshapes) > 0:
                sshapes.extend(tmpSshapes)

                if groupSshapesByObject:
                    objectSshapes.append((o, tmpSshapes))

    if groupSshapesByObject:
        return shapes, hshapes, sshapes, cutface, cutvolume, invcutvolume, objectSshapes
    else:
        return shapes, hshapes, sshapes, cutface, cutvolume, invcutvolume
Esempio n. 20
0
    def onChanged(self, obj, prop):
        if prop in ["Source", "RenderingMode", "ShowCut"]:
            import Part, DraftGeomUtils
            if hasattr(obj, "Source"):
                if obj.Source:
                    if obj.Source.Objects:
                        objs = Draft.getGroupContents(obj.Source.Objects,
                                                      walls=True,
                                                      addgroups=True)
                        objs = Draft.removeHidden(objs)
                        # separate spaces
                        self.spaces = []
                        os = []
                        for o in objs:
                            if Draft.getType(o) == "Space":
                                self.spaces.append(o)
                            else:
                                os.append(o)
                        objs = os
                        self.svg = ''
                        fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
                        fillpattern += ' x="0" y="0" width="10" height="10">'
                        fillpattern += '<g>'
                        fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>'

                        # generating SVG
                        if obj.RenderingMode == "Solid":
                            # render using the Arch Vector Renderer
                            import ArchVRM, WorkingPlane
                            wp = WorkingPlane.plane()
                            wp.setFromPlacement(obj.Source.Placement)
                            #wp.inverse()
                            render = ArchVRM.Renderer()
                            render.setWorkingPlane(wp)
                            render.addObjects(objs)
                            if hasattr(obj, "ShowCut"):
                                render.cut(obj.Source.Shape, obj.ShowCut)
                            else:
                                render.cut(obj.Source.Shape)
                            self.svg += '<g transform="scale(1,-1)">\n'
                            self.svg += render.getViewSVG(
                                linewidth="LWPlaceholder")
                            self.svg += fillpattern
                            self.svg += render.getSectionSVG(
                                linewidth="SWPlaceholder",
                                fillpattern="sectionfill")
                            if hasattr(obj, "ShowCut"):
                                if obj.ShowCut:
                                    self.svg += render.getHiddenSVG(
                                        linewidth="LWPlaceholder")
                            self.svg += '</g>\n'
                            # print render.info()

                        else:
                            # render using the Drawing module
                            import Drawing, Part
                            shapes = []
                            hshapes = []
                            sshapes = []
                            p = FreeCAD.Placement(obj.Source.Placement)
                            self.direction = p.Rotation.multVec(
                                FreeCAD.Vector(0, 0, 1))
                            for o in objs:
                                if o.isDerivedFrom("Part::Feature"):
                                    if o.Shape.isNull():
                                        pass
                                        #FreeCAD.Console.PrintWarning(translate("Arch","Skipping empty object: ")+o.Name)
                                    elif o.Shape.isValid():
                                        if hasattr(obj.Source, "OnlySolids"):
                                            if obj.Source.OnlySolids:
                                                shapes.extend(o.Shape.Solids)
                                            else:
                                                shapes.append(o.Shape)
                                        else:
                                            shapes.extend(o.Shape.Solids)
                                    else:
                                        FreeCAD.Console.PrintWarning(
                                            translate(
                                                "Arch",
                                                "Skipping invalid object: ") +
                                            o.Name)
                            cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
                                obj.Source.Shape.copy(), shapes)
                            if cutvolume:
                                nsh = []
                                for sh in shapes:
                                    for sol in sh.Solids:
                                        if sol.Volume < 0:
                                            sol.reverse()
                                        c = sol.cut(cutvolume)
                                        s = sol.section(cutface)
                                        try:
                                            wires = DraftGeomUtils.findWires(
                                                s.Edges)
                                            for w in wires:
                                                f = Part.Face(w)
                                                sshapes.append(f)
                                            #s = Part.Wire(s.Edges)
                                            #s = Part.Face(s)
                                        except Part.OCCError:
                                            #print "ArchDrawingView: unable to get a face"
                                            sshapes.append(s)
                                        nsh.extend(c.Solids)
                                        #sshapes.append(s)
                                        if hasattr(obj, "ShowCut"):
                                            if obj.ShowCut:
                                                c = sol.cut(invcutvolume)
                                                hshapes.append(c)
                                shapes = nsh
                            if shapes:
                                self.shapes = shapes
                                self.baseshape = Part.makeCompound(shapes)
                                svgf = Drawing.projectToSVG(
                                    self.baseshape, self.direction)
                                if svgf:
                                    svgf = svgf.replace(
                                        'stroke-width="0.35"',
                                        'stroke-width="LWPlaceholder"')
                                    svgf = svgf.replace(
                                        'stroke-width="1"',
                                        'stroke-width="LWPlaceholder"')
                                    svgf = svgf.replace(
                                        'stroke-width:0.01',
                                        'stroke-width:LWPlaceholder')
                                    self.svg += svgf
                            if hshapes:
                                hshapes = Part.makeCompound(hshapes)
                                self.hiddenshape = hshapes
                                svgh = Drawing.projectToSVG(
                                    hshapes, self.direction)
                                if svgh:
                                    svgh = svgh.replace(
                                        'stroke-width="0.35"',
                                        'stroke-width="LWPlaceholder"')
                                    svgh = svgh.replace(
                                        'stroke-width="1"',
                                        'stroke-width="LWPlaceholder"')
                                    svgh = svgh.replace(
                                        'stroke-width:0.01',
                                        'stroke-width:LWPlaceholder')
                                    svgh = svgh.replace(
                                        'fill="none"',
                                        'fill="none"\nstroke-dasharray="DAPlaceholder"'
                                    )
                                    self.svg += svgh
                            if sshapes:
                                svgs = ""
                                if hasattr(obj, "ShowFill"):
                                    if obj.ShowFill:
                                        svgs += fillpattern
                                        svgs += '<g transform="rotate(180)">\n'
                                        for s in sshapes:
                                            if s.Edges:
                                                f = Draft.getSVG(
                                                    s,
                                                    direction=self.direction.
                                                    negative(),
                                                    linewidth=0,
                                                    fillstyle="sectionfill",
                                                    color=(0, 0, 0))
                                                svgs += f
                                        svgs += "</g>\n"
                                sshapes = Part.makeCompound(sshapes)
                                self.sectionshape = sshapes
                                svgs += Drawing.projectToSVG(
                                    sshapes, self.direction)
                                if svgs:
                                    svgs = svgs.replace(
                                        'stroke-width="0.35"',
                                        'stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace(
                                        'stroke-width="1"',
                                        'stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace(
                                        'stroke-width:0.01',
                                        'stroke-width:SWPlaceholder')
                                    svgs = svgs.replace(
                                        'stroke-width="0.35 px"',
                                        'stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace(
                                        'stroke-width:0.35',
                                        'stroke-width:SWPlaceholder')
                                    self.svg += svgs
Esempio n. 21
0
def getSVG(section,allOn=False,renderMode="Wireframe",showHidden=False,showFill=False,scale=1,linewidth=1,fontsize=1):
    """getSVG(section,[allOn,renderMode,showHidden,showFill,scale,linewidth,fontsize]) : 
    returns an SVG fragment from an Arch section plane. If
    allOn is True, all cut objects are shown, regardless if they are visible or not.
    renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If
    showHidden is True, the hidden geometry above the section plane is shown in dashed line.
    If showFill is True, the cut areas get filled with a pattern"""

    if not section.Objects:
        return
    import DraftGeomUtils
    p = FreeCAD.Placement(section.Placement)
    direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
    objs = Draft.getGroupContents(section.Objects,walls=True,addgroups=True)
    if not allOn:
            objs = Draft.removeHidden(objs)
    # separate spaces
    spaces = []
    nonspaces = []
    for o in objs:
        if Draft.getType(o) == "Space":
            spaces.append(o)
        else:
            nonspaces.append(o)
    objs = nonspaces
    svg = ''
    fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
    fillpattern += ' x="0" y="0" width="10" height="10">'
    fillpattern += '<g>'
    fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>'

    # generating SVG
    if renderMode == "Solid":
        # render using the Arch Vector Renderer
        import ArchVRM, WorkingPlane
        wp = WorkingPlane.plane()
        wp.setFromPlacement(section.Placement)
        #wp.inverse()
        render = ArchVRM.Renderer()
        render.setWorkingPlane(wp)
        render.addObjects(objs)
        if showHidden:
            render.cut(section.Shape,showHidden)
        else:
            render.cut(section.Shape)
        svg += '<g transform="scale(1,-1)">\n'
        svg += render.getViewSVG(linewidth="LWPlaceholder")
        svg += fillpattern
        svg += render.getSectionSVG(linewidth="SWPlaceholder",fillpattern="sectionfill")
        if showHidden:
            svg += render.getHiddenSVG(linewidth="LWPlaceholder")
        svg += '</g>\n'
        # print render.info()

    else:
        # render using the Drawing module
        import Drawing, Part
        shapes = []
        hshapes = []
        sshapes = []
        for o in objs:
            if o.isDerivedFrom("Part::Feature"):
                if o.Shape.isNull():
                    pass
                elif o.Shape.isValid():
                    if section.OnlySolids:
                        shapes.extend(o.Shape.Solids)
                    else:
                        shapes.append(o.Shape)
                else:
                    print section.Label,": Skipping invalid object:",o.Label
        cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes)
        if cutvolume:
            nsh = []
            for sh in shapes:
                for sol in sh.Solids:
                    if sol.Volume < 0:
                        sol.reverse()
                    c = sol.cut(cutvolume)
                    s = sol.section(cutface)
                    try:
                        wires = DraftGeomUtils.findWires(s.Edges)
                        for w in wires:
                            f = Part.Face(w)
                            sshapes.append(f)
                        #s = Part.Wire(s.Edges)
                        #s = Part.Face(s)
                    except Part.OCCError:
                        #print "ArchDrawingView: unable to get a face"
                        sshapes.append(s)
                    nsh.extend(c.Solids)
                    #sshapes.append(s)
                    if showHidden:
                        c = sol.cut(invcutvolume)
                        hshapes.append(c)
            shapes = nsh
        if shapes:
            baseshape = Part.makeCompound(shapes)
            svgf = Drawing.projectToSVG(baseshape,direction)
            if svgf:
                svgf = svgf.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                svgf = svgf.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                svgf = svgf.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                svg += svgf
        if hshapes:
            hshapes = Part.makeCompound(hshapes)
            svgh = Drawing.projectToSVG(hshapes,direction)
            if svgh:
                svgh = svgh.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                svgh = svgh.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                svgh = svgh.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                svgh = svgh.replace('fill="none"','fill="none"\nstroke-dasharray="DAPlaceholder"')
                svg += svgh
        if sshapes:
            svgs = ""
            if showFill:
                svgs += fillpattern
                svgs += '<g transform="rotate(180)">\n'
                for s in sshapes:
                    if s.Edges:
                        f = Draft.getSVG(s,direction=direction.negative(),linewidth=0,fillstyle="sectionfill",color=(0,0,0))
                        svgs += f
                svgs += "</g>\n"
            sshapes = Part.makeCompound(sshapes)
            svgs += Drawing.projectToSVG(sshapes,direction)
            if svgs:
                svgs = svgs.replace('stroke-width="0.35"','stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width="1"','stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width:0.01','stroke-width:SWPlaceholder')
                svgs = svgs.replace('stroke-width="0.35 px"','stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width:0.35','stroke-width:SWPlaceholder')
                svg += svgs

    linewidth = linewidth/scale
    st = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetFloat("CutLineThickness",2)
    da = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Arch").GetString("archHiddenPattern","30,10")
    da = da.replace(" ","")
    svg = svg.replace('LWPlaceholder', str(linewidth) + 'px')
    svg = svg.replace('SWPlaceholder', str(linewidth*st) + 'px')
    svg = svg.replace('DAPlaceholder', str(da))
    if spaces and round(direction.getAngle(FreeCAD.Vector(0,0,1)),Draft.precision()) in [0,round(math.pi,Draft.precision())]:
        svg += '<g transform="scale(1,-1)">'
        for s in spaces:
            svg += Draft.getSVG(s,scale=scale,fontsize=fontsize,direction=direction)
        svg += '</g>'
    # print "complete node:",svg
    return svg
def getCutShapes(objs,section,showHidden,groupSshapesByObject=False):

    import Part,DraftGeomUtils
    shapes = []
    hshapes = []
    sshapes = []
    objectShapes = []
    objectSshapes = []
    for o in objs:
        if o.isDerivedFrom("Part::Feature"):
            if o.Shape.isNull():
                pass
            elif section.OnlySolids:
                if o.Shape.isValid():
                    solids = []
                    solids.extend(o.Shape.Solids)

                    shapes.extend(solids)

                    objectShapes.append((o, solids))
                else:
                    print(section.Label,": Skipping invalid object:",o.Label)
            else:
                shapes.append(o.Shape)
                objectShapes.append((o, [o.Shape]))
    clip = False
    if hasattr(section, "Clip"):
        clip = section.Clip
    cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(section.Shape.copy(),shapes,clip)
    shapes =[]
    if cutvolume:
        for o, shapeList in objectShapes:
            tmpSshapes = []
            for sh in shapeList:
                for sol in sh.Solids:
                    if sol.Volume < 0:
                        sol.reverse()
                    c = sol.cut(cutvolume)
                    s = sol.section(cutface)
                    try:
                        wires = DraftGeomUtils.findWires(s.Edges)
                        for w in wires:
                            f = Part.Face(w)
                            tmpSshapes.append(f)
                        #s = Part.Wire(s.Edges)
                        #s = Part.Face(s)
                    except Part.OCCError:
                        #print "ArchDrawingView: unable to get a face"
                        tmpSshapes.append(s)
                    shapes.extend(c.Solids)
                    #sshapes.append(s)
                    if showHidden:
                        c = sol.cut(invcutvolume)
                        hshapes.append(c)

            if len(tmpSshapes) > 0:
                sshapes.extend(tmpSshapes)

                if groupSshapesByObject:
                    objectSshapes.append((o, tmpSshapes))

    if groupSshapesByObject:
        return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume,objectSshapes
    else:
        return shapes,hshapes,sshapes,cutface,cutvolume,invcutvolume
Esempio n. 23
0
    def buildSVG(self, obj,join=False):
        "creates a svg representation"
        import Part, DraftGeomUtils
        if hasattr(obj,"Source"):
            if obj.Source:
                if obj.Source.Objects:
                    objs = Draft.getGroupContents(obj.Source.Objects,walls=True)
                    objs = Draft.removeHidden(objs)
                    self.svg = ''

                    # generating SVG
                    if obj.RenderingMode == "Solid":
                        # render using the Arch Vector Renderer                        
                        import ArchVRM
                        render = ArchVRM.Renderer()
                        render.setWorkingPlane(obj.Source.Placement)
                        render.addObjects(objs)
                        if hasattr(obj,"ShowCut"):
                            render.cut(obj.Source.Shape,obj.ShowCut)
                        else:
                            render.cut(obj.Source.Shape)
                        self.svg += render.getViewSVG(linewidth="LWPlaceholder")
                        self.svg += render.getSectionSVG(linewidth="SWPLaceholder")
                        if hasattr(obj,"ShowCut"):
                            if obj.ShowCut:
                                self.svg += render.getHiddenSVG(linewidth="LWPlaceholder")
                        # print render.info()
                        
                    else:
                        # render using the Drawing module
                        import Drawing, Part
                        shapes = []
                        hshapes = []
                        sshapes = []
                        p = FreeCAD.Placement(obj.Source.Placement)
                        self.direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
                        for o in objs:
                            if o.isDerivedFrom("Part::Feature"):
                                if o.Shape.isNull():
                                    pass
                                    #FreeCAD.Console.PrintWarning(translate("Arch","Skipping empty object: ")+o.Name)
                                elif o.Shape.isValid():
                                    shapes.extend(o.Shape.Solids)
                                else:
                                    FreeCAD.Console.PrintWarning(translate("Arch","Skipping invalid object: ")+o.Name)
                        cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
                        if cutvolume:
                            nsh = []
                            for sh in shapes:
                                for sol in sh.Solids:
                                    if sol.Volume < 0:
                                        sol.reverse()
                                    c = sol.cut(cutvolume)
                                    s = sol.section(cutface)
                                    nsh.extend(c.Solids)
                                    sshapes.append(s)
                                    if hasattr(obj,"ShowCut"):
                                        if obj.ShowCut:
                                            c = sol.cut(invcutvolume)
                                            hshapes.append(c)
                            shapes = nsh
                        if shapes:
                            self.shapes = shapes
                            self.baseshape = Part.makeCompound(shapes)
                            svgf = Drawing.projectToSVG(self.baseshape,self.direction)
                            if svgf:
                                svgf = svgf.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                                svgf = svgf.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                                svgf = svgf.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                                self.svg += svgf
                        if hshapes:
                            hshapes = Part.makeCompound(hshapes)
                            svgh = Drawing.projectToSVG(hshapes,self.direction)
                            if svgh:
                                svgh = svgh.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                                svgh = svgh.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                                svgh = svgh.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                                svgh = svgh.replace('fill="none"','fill="none"\nstroke-dasharray="0.09,0.05"')                              
                                self.svg += svgh
                        if sshapes:
                            edges = []
                            for s in sshapes:
                                edges.extend(s.Edges)
                            wires = DraftGeomUtils.findWires(edges)
                            faces = []
                            for w in wires:
                                if (w.ShapeType == "Wire") and w.isClosed():
                                    faces.append(Part.Face(w))
                            sshapes = Part.makeCompound(faces)
                            svgs = Drawing.projectToSVG(sshapes,self.direction)
                            if svgs:
                                svgs = svgs.replace('stroke-width="0.35"','stroke-width="SWPlaceholder"')
                                svgs = svgs.replace('stroke-width="1"','stroke-width="SWPlaceholder"')
                                svgs = svgs.replace('stroke-width:0.01','stroke-width:SWPlaceholder')
                                self.svg += svgs
    def getShape(self,obj):
        "computes a shape from a base shape and/or bounday faces"
        import Part
        shape = None
        faces = []
        
        #print "starting compute"
        # 1: if we have a base shape, we use it
        
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.Solids:
                    shape = obj.Base.Shape.Solids[0].copy()

        # 2: if not, add all bounding boxes of considered objects and build a first shape
        if shape:
            #print "got shape from base object"
            bb = shape.BoundBox
        else:
            bb = None
            for b in obj.Boundaries:
                if b[0].isDerivedFrom("Part::Feature"):
                    if not bb:
                        bb = b[0].Shape.BoundBox
                    else:
                        bb.add(b[0].Shape.BoundBox)
            if not bb:
                return
            shape = Part.makeBox(bb.XLength,bb.YLength,bb.ZLength,FreeCAD.Vector(bb.XMin,bb.YMin,bb.ZMin))
            #print "created shape from boundbox"
        
        # 3: identifing boundary faces
        goodfaces = []
        for b in obj.Boundaries:
                if b[0].isDerivedFrom("Part::Feature"):
                    if "Face" in b[1]:
                        fn = int(b[1][4:])-1
                        faces.append(b[0].Shape.Faces[fn])
                        #print "adding face ",fn," of object ",b[0].Name

        #print "total: ", len(faces), " faces"
        
        # 4: get cutvolumes from faces
        cutvolumes = []
        for f in faces:
            f = f.copy()
            f.reverse()
            cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(f,shape)
            if cutvolume:
                #print "generated 1 cutvolume"
                cutvolumes.append(cutvolume.copy())
                #Part.show(cutvolume)
        for v in cutvolumes:
            #print "cutting"
            shape = shape.cut(v)
            
        # 5: get the final shape
        if shape:
            if shape.Solids:
                #print "setting objects shape"
                shape = shape.Solids[0]
                obj.Shape = shape
                return
                
        print "Arch: error computing space boundary"
Esempio n. 25
0
    def getShape(self, obj):

        "computes a shape from a base shape and/or boundary faces"
        import Part
        shape = None
        faces = []

        pl = obj.Placement

        #print("starting compute")

        # 1: if we have a base shape, we use it
        if obj.Base:
            if hasattr(obj.Base, 'Shape'):
                if obj.Base.Shape.Solids:
                    shape = obj.Base.Shape.copy()
                    shape = shape.removeSplitter()

        # 2: if not, add all bounding boxes of considered objects and build a first shape
        if shape:
            #print("got shape from base object")
            bb = shape.BoundBox
        else:
            bb = None
            for b in obj.Boundaries:
                if hasattr(b[0], 'Shape'):
                    if not bb:
                        bb = b[0].Shape.BoundBox
                    else:
                        bb.add(b[0].Shape.BoundBox)
            if not bb:
                # compute area even if we are not calculating the shape
                if obj.Shape and obj.Shape.Solids:
                    if hasattr(obj.Area, "Value"):
                        a = self.getArea(obj)
                        if obj.Area.Value != a:
                            obj.Area = a
                return
            shape = Part.makeBox(bb.XLength, bb.YLength, bb.ZLength,
                                 FreeCAD.Vector(bb.XMin, bb.YMin, bb.ZMin))
            #print("created shape from boundbox")

        # 3: identifying boundary faces
        goodfaces = []
        for b in obj.Boundaries:
            if hasattr(b[0], 'Shape'):
                for sub in b[1]:
                    if "Face" in sub:
                        fn = int(sub[4:]) - 1
                        faces.append(b[0].Shape.Faces[fn])
                        #print("adding face ",fn," of object ",b[0].Name)

        #print("total: ", len(faces), " faces")

        # 4: get cutvolumes from faces
        cutvolumes = []
        for f in faces:
            f = f.copy()
            f.reverse()
            cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
                f, shape)
            if cutvolume:
                #print("generated 1 cutvolume")
                cutvolumes.append(cutvolume.copy())
                #Part.show(cutvolume)
        for v in cutvolumes:
            #print("cutting")
            shape = shape.cut(v)

        # 5: get the final shape
        if shape:
            if shape.Solids:
                #print("setting objects shape")
                shape = shape.Solids[0]
                self.applyShape(obj, shape, pl)
                if hasattr(obj.Area, "Value"):
                    a = self.getArea(obj)
                    if obj.Area.Value != a:
                        obj.Area = a
                return

        print("Arch: error computing space boundary for", obj.Label)
Esempio n. 26
0
    def onChanged(self, obj, prop):
        if prop in ["Source","RenderingMode","ShowCut"]:
            import Part, DraftGeomUtils
            if hasattr(obj,"Source"):
                if obj.Source:
                    if obj.Source.Objects:
                        objs = Draft.getGroupContents(obj.Source.Objects,walls=True)
                        objs = Draft.removeHidden(objs)
                        # separate spaces
                        self.spaces = []
                        os = []
                        for o in objs:
                            if Draft.getType(o) == "Space":
                                self.spaces.append(o)
                            else:
                                os.append(o)
                        objs = os
                        self.svg = ''
                        fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
                        fillpattern += ' x="0" y="0" width="10" height="10">'
                        fillpattern += '<g>'
                        fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>'

                        # generating SVG
                        if obj.RenderingMode == "Solid":
                            # render using the Arch Vector Renderer
                            import ArchVRM, WorkingPlane
                            wp = WorkingPlane.plane()
                            wp.setFromPlacement(obj.Source.Placement)
                            wp.inverse()
                            render = ArchVRM.Renderer()
                            render.setWorkingPlane(wp)
                            render.addObjects(objs)
                            if hasattr(obj,"ShowCut"):
                                render.cut(obj.Source.Shape,obj.ShowCut)
                            else:
                                render.cut(obj.Source.Shape)
                            self.svg += render.getViewSVG(linewidth="LWPlaceholder")
                            self.svg += fillpattern
                            self.svg += render.getSectionSVG(linewidth="SWPlaceholder",fillpattern="sectionfill")
                            if hasattr(obj,"ShowCut"):
                                if obj.ShowCut:
                                    self.svg += render.getHiddenSVG(linewidth="LWPlaceholder")
                            # print render.info()

                        else:
                            # render using the Drawing module
                            import Drawing, Part
                            shapes = []
                            hshapes = []
                            sshapes = []
                            p = FreeCAD.Placement(obj.Source.Placement)
                            self.direction = p.Rotation.multVec(FreeCAD.Vector(0,0,1))
                            for o in objs:
                                if o.isDerivedFrom("Part::Feature"):
                                    if o.Shape.isNull():
                                        pass
                                        #FreeCAD.Console.PrintWarning(translate("Arch","Skipping empty object: ")+o.Name)
                                    elif o.Shape.isValid():
                                        if hasattr(obj.Source,"OnlySolids"):
                                            if obj.Source.OnlySolids:
                                                shapes.extend(o.Shape.Solids)
                                            else:
                                                shapes.append(o.Shape)
                                        else:
                                            shapes.extend(o.Shape.Solids)
                                    else:
                                        FreeCAD.Console.PrintWarning(translate("Arch","Skipping invalid object: ")+o.Name)
                            cutface,cutvolume,invcutvolume = ArchCommands.getCutVolume(obj.Source.Shape.copy(),shapes)
                            if cutvolume:
                                nsh = []
                                for sh in shapes:
                                    for sol in sh.Solids:
                                        if sol.Volume < 0:
                                            sol.reverse()
                                        c = sol.cut(cutvolume)
                                        s = sol.section(cutface)
                                        try:
                                            wires = DraftGeomUtils.findWires(s.Edges)
                                            for w in wires:
                                                f = Part.Face(w)
                                                sshapes.append(f)
                                            #s = Part.Wire(s.Edges)
                                            #s = Part.Face(s)
                                        except Part.OCCError:
                                            #print "ArchDrawingView: unable to get a face"
                                            sshapes.append(s)
                                        nsh.extend(c.Solids)
                                        #sshapes.append(s)
                                        if hasattr(obj,"ShowCut"):
                                            if obj.ShowCut:
                                                c = sol.cut(invcutvolume)
                                                hshapes.append(c)
                                shapes = nsh
                            if shapes:
                                self.shapes = shapes
                                self.baseshape = Part.makeCompound(shapes)
                                svgf = Drawing.projectToSVG(self.baseshape,self.direction)
                                if svgf:
                                    svgf = svgf.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                                    svgf = svgf.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                                    svgf = svgf.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                                    self.svg += svgf
                            if hshapes:
                                hshapes = Part.makeCompound(hshapes)
                                self.hiddenshape = hshapes
                                svgh = Drawing.projectToSVG(hshapes,self.direction)
                                if svgh:
                                    svgh = svgh.replace('stroke-width="0.35"','stroke-width="LWPlaceholder"')
                                    svgh = svgh.replace('stroke-width="1"','stroke-width="LWPlaceholder"')
                                    svgh = svgh.replace('stroke-width:0.01','stroke-width:LWPlaceholder')
                                    svgh = svgh.replace('fill="none"','fill="none"\nstroke-dasharray="DAPlaceholder"')
                                    self.svg += svgh
                            if sshapes:
                                svgs = ""
                                if hasattr(obj,"ShowFill"):
                                    if obj.ShowFill:
                                        svgs += fillpattern
                                        svgs += '<g transform="rotate(180)">\n'
                                        for s in sshapes:
                                            if s.Edges:
                                                f = Draft.getSVG(s,direction=self.direction.negative(),linewidth=0,fillstyle="sectionfill",color=(0,0,0))
                                                svgs += f
                                        svgs += "</g>\n"
                                sshapes = Part.makeCompound(sshapes)
                                self.sectionshape = sshapes
                                svgs += Drawing.projectToSVG(sshapes,self.direction)
                                if svgs:
                                    svgs = svgs.replace('stroke-width="0.35"','stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace('stroke-width="1"','stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace('stroke-width:0.01','stroke-width:SWPlaceholder')
                                    svgs = svgs.replace('stroke-width="0.35 px"','stroke-width="SWPlaceholder"')
                                    svgs = svgs.replace('stroke-width:0.35','stroke-width:SWPlaceholder')
                                    self.svg += svgs
Esempio n. 27
0
def getSVG(section,
           allOn=False,
           renderMode="Wireframe",
           showHidden=False,
           showFill=False,
           scale=1,
           linewidth=1,
           fontsize=1):
    """getSVG(section,[allOn,renderMode,showHidden,showFill,scale,linewidth,fontsize]) : 
    returns an SVG fragment from an Arch section plane. If
    allOn is True, all cut objects are shown, regardless if they are visible or not.
    renderMode can be Wireframe (default) or Solid to use the Arch solid renderer. If
    showHidden is True, the hidden geometry above the section plane is shown in dashed line.
    If showFill is True, the cut areas get filled with a pattern"""

    if not section.Objects:
        return
    import DraftGeomUtils
    p = FreeCAD.Placement(section.Placement)
    direction = p.Rotation.multVec(FreeCAD.Vector(0, 0, 1))
    objs = Draft.getGroupContents(section.Objects, walls=True, addgroups=True)
    if not allOn:
        objs = Draft.removeHidden(objs)
    # separate spaces
    spaces = []
    nonspaces = []
    for o in objs:
        if Draft.getType(o) == "Space":
            spaces.append(o)
        else:
            nonspaces.append(o)
    objs = nonspaces
    svg = ''
    fillpattern = '<pattern id="sectionfill" patternUnits="userSpaceOnUse" patternTransform="matrix(5,0,0,5,0,0)"'
    fillpattern += ' x="0" y="0" width="10" height="10">'
    fillpattern += '<g>'
    fillpattern += '<rect width="10" height="10" style="stroke:none; fill:#ffffff" /><path style="stroke:#000000; stroke-width:1" d="M0,0 l10,10" /></g></pattern>'

    # generating SVG
    if renderMode == "Solid":
        # render using the Arch Vector Renderer
        import ArchVRM, WorkingPlane
        wp = WorkingPlane.plane()
        wp.setFromPlacement(section.Placement)
        #wp.inverse()
        render = ArchVRM.Renderer()
        render.setWorkingPlane(wp)
        render.addObjects(objs)
        if showHidden:
            render.cut(section.Shape, showHidden)
        else:
            render.cut(section.Shape)
        svg += '<g transform="scale(1,-1)">\n'
        svg += render.getViewSVG(linewidth="LWPlaceholder")
        svg += fillpattern
        svg += render.getSectionSVG(linewidth="SWPlaceholder",
                                    fillpattern="sectionfill")
        if showHidden:
            svg += render.getHiddenSVG(linewidth="LWPlaceholder")
        svg += '</g>\n'
        # print render.info()

    else:
        # render using the Drawing module
        import Drawing, Part
        shapes = []
        hshapes = []
        sshapes = []
        for o in objs:
            if o.isDerivedFrom("Part::Feature"):
                if o.Shape.isNull():
                    pass
                elif o.Shape.isValid():
                    if section.OnlySolids:
                        shapes.extend(o.Shape.Solids)
                    else:
                        shapes.append(o.Shape)
                else:
                    print section.Label, ": Skipping invalid object:", o.Label
        cutface, cutvolume, invcutvolume = ArchCommands.getCutVolume(
            section.Shape.copy(), shapes)
        if cutvolume:
            nsh = []
            for sh in shapes:
                for sol in sh.Solids:
                    if sol.Volume < 0:
                        sol.reverse()
                    c = sol.cut(cutvolume)
                    s = sol.section(cutface)
                    try:
                        wires = DraftGeomUtils.findWires(s.Edges)
                        for w in wires:
                            f = Part.Face(w)
                            sshapes.append(f)
                        #s = Part.Wire(s.Edges)
                        #s = Part.Face(s)
                    except Part.OCCError:
                        #print "ArchDrawingView: unable to get a face"
                        sshapes.append(s)
                    nsh.extend(c.Solids)
                    #sshapes.append(s)
                    if showHidden:
                        c = sol.cut(invcutvolume)
                        hshapes.append(c)
            shapes = nsh
        if shapes:
            baseshape = Part.makeCompound(shapes)
            svgf = Drawing.projectToSVG(baseshape, direction)
            if svgf:
                svgf = svgf.replace('stroke-width="0.35"',
                                    'stroke-width="LWPlaceholder"')
                svgf = svgf.replace('stroke-width="1"',
                                    'stroke-width="LWPlaceholder"')
                svgf = svgf.replace('stroke-width:0.01',
                                    'stroke-width:LWPlaceholder')
                svg += svgf
        if hshapes:
            hshapes = Part.makeCompound(hshapes)
            svgh = Drawing.projectToSVG(hshapes, direction)
            if svgh:
                svgh = svgh.replace('stroke-width="0.35"',
                                    'stroke-width="LWPlaceholder"')
                svgh = svgh.replace('stroke-width="1"',
                                    'stroke-width="LWPlaceholder"')
                svgh = svgh.replace('stroke-width:0.01',
                                    'stroke-width:LWPlaceholder')
                svgh = svgh.replace(
                    'fill="none"',
                    'fill="none"\nstroke-dasharray="DAPlaceholder"')
                svg += svgh
        if sshapes:
            svgs = ""
            if showFill:
                svgs += fillpattern
                svgs += '<g transform="rotate(180)">\n'
                for s in sshapes:
                    if s.Edges:
                        f = Draft.getSVG(s,
                                         direction=direction.negative(),
                                         linewidth=0,
                                         fillstyle="sectionfill",
                                         color=(0, 0, 0))
                        svgs += f
                svgs += "</g>\n"
            sshapes = Part.makeCompound(sshapes)
            svgs += Drawing.projectToSVG(sshapes, direction)
            if svgs:
                svgs = svgs.replace('stroke-width="0.35"',
                                    'stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width="1"',
                                    'stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width:0.01',
                                    'stroke-width:SWPlaceholder')
                svgs = svgs.replace('stroke-width="0.35 px"',
                                    'stroke-width="SWPlaceholder"')
                svgs = svgs.replace('stroke-width:0.35',
                                    'stroke-width:SWPlaceholder')
                svg += svgs

    linewidth = linewidth / scale
    st = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch").GetFloat(
            "CutLineThickness", 2)
    da = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch").GetString(
            "archHiddenPattern", "30,10")
    da = da.replace(" ", "")
    svg = svg.replace('LWPlaceholder', str(linewidth) + 'px')
    svg = svg.replace('SWPlaceholder', str(linewidth * st) + 'px')
    svg = svg.replace('DAPlaceholder', str(da))
    if spaces and round(
            direction.getAngle(FreeCAD.Vector(0, 0, 1)),
            Draft.precision()) in [0, round(math.pi, Draft.precision())]:
        svg += '<g transform="scale(1,-1)">'
        for s in spaces:
            svg += Draft.getSVG(s,
                                scale=scale,
                                fontsize=fontsize,
                                direction=direction)
        svg += '</g>'
    # print "complete node:",svg
    return svg