Beispiel #1
0
    def execute(self, obj):
        # please, don't override. Override derivedExecute instead.

        plms = self.derivedExecute(obj)

        if plms is not None:
            if plms == "suppress":
                return
            obj.NumElements = len(plms)
            shapes = []
            markerSize = obj.MarkerSize
            if markerSize < DistConfusion:
                markerSize = getMarkerSizeEstimate(plms)
            marker = lattice2Markers.getPlacementMarker(
                scale=markerSize, markerID=obj.MarkerShape)

            bExposing = False
            if obj.ExposePlacement:
                if len(plms) == 1:
                    bExposing = True
                else:
                    lattice2Executer.warning(
                        obj,
                        "Multiple placements are being fed, can't expose placements. Placement property will be forced to zero."
                    )
                    obj.Placement = App.Placement()

            if bExposing:
                obj.Shape = shallowCopy(marker)
                obj.Placement = plms[0]
            else:
                for plm in plms:
                    sh = shallowCopy(marker)
                    sh.Placement = plm
                    shapes.append(sh)

                if len(shapes) == 0:
                    obj.Shape = lattice2Markers.getNullShapeShape(markerSize)
                    raise ValueError('Lattice object is null')

                sh = Part.makeCompound(shapes)
                sh.Placement = obj.Placement
                obj.Shape = sh

            if obj.isLattice == 'Auto-Off':
                obj.isLattice = 'Auto-On'

        else:
            # DerivedExecute didn't return anything. Thus we assume it
            # has assigned the shape, and thus we don't do anything.
            # Moreover, we assume that it is no longer a lattice object, so:
            if obj.isLattice == 'Auto-On':
                obj.isLattice = 'Auto-Off'

            if obj.ExposePlacement:
                if obj.Shape.ShapeType == "Compound":
                    children = obj.Shape.childShapes()
                    if len(children) == 1:
                        obj.Placement = children[0].Placement
                        obj.Shape = children[0]
                    else:
                        obj.Placement = App.Placement()
                else:
                    #nothing to do - FreeCAD will take care to make obj.Placement and obj.Shape.Placement synchronized.
                    pass
        return
    def __init__(self, obj, label, node1, node2):
        
        x = node1.position_X
        y = node1.position_Y
        z = node1.position_Z 
     
        obj.addExtension("App::GroupExtensionPython", self)  
        #Create scripted object:
        obj.addProperty("App::PropertyString","label","In line joint","label",1).label = label
        obj.addProperty("App::PropertyString","joint","In line joint","joint",1).joint = 'prismatic'
        obj.addProperty("App::PropertyString","node 1","In line joint","node 1",1).node_1 = node1.label
        obj.addProperty("App::PropertyString","node 2","In line joint","node 2",1).node_2 = node2.label
            #Absolute position at the node 1 position, only for animation, not for MBDyn sumulation:  
        obj.addProperty("App::PropertyDistance","position X","Initial absolute position","position X",1).position_X = x
        obj.addProperty("App::PropertyDistance","position Y","Initial absolute position","position Y",1).position_Y = y
        obj.addProperty("App::PropertyDistance","position Z","Initial absolute position","position Z",1).position_Z = z

        obj.addProperty("App::PropertyString","animate","Animation","animate").animate = 'false'
        obj.addProperty("App::PropertyString","frame","Animation","frame").frame = 'local'
        obj.addProperty("App::PropertyString","structural dummy","Animation","structural dummy").structural_dummy = '2'
        obj.addProperty("App::PropertyString","force vector multiplier","Animation","force vector multiplier").force_vector_multiplier = '1'

        obj.Proxy = self
        
        length = FreeCAD.ActiveDocument.getObjectsByLabel("x: structural: " + node1.label)[0].Length.Value # Calculate the body characteristic length. Will be used to size the arrows that represent the node.
        p1 = FreeCAD.Vector(0, 0, 0)
        #Add x vector of the coordinate system:
        p2 = FreeCAD.Vector(length, 0, 0)
        l = Draft.makeLine(p1, p2)
        l.Label = 'x: joint: '+ label            
        l.ViewObject.LineColor = (1.00,0.00,0.00)
        l.ViewObject.PointColor = (1.00,0.00,0.00)
        l.Placement=FreeCAD.Placement(FreeCAD.Vector(x,y,z), FreeCAD.Rotation(FreeCAD.Vector(0,0,1),0), FreeCAD.Vector(0,0,0))
        l.ViewObject.EndArrow = True
        l.ViewObject.ArrowType = u"Arrow"
        l.ViewObject.LineWidth = 1.00
        l.ViewObject.PointSize = 1.00
        l.ViewObject.ArrowSize = str(length/15)+' mm'
        l.ViewObject.Selectable = False
        #Add y vector of the coordinate system:
        p2 = FreeCAD.Vector(0, length, 0)
        l = Draft.makeLine(p1, p2)
        l.Label = 'y: joint: '+ label            
        l.ViewObject.LineColor = (0.00,1.00,0.00)
        l.ViewObject.PointColor = (0.00,1.00,0.00)
        l.Placement=FreeCAD.Placement(FreeCAD.Vector(x,y,z), FreeCAD.Rotation(FreeCAD.Vector(0,0,1),0), FreeCAD.Vector(0,0,0))
        l.ViewObject.EndArrow = True
        l.ViewObject.ArrowType = u"Arrow"
        l.ViewObject.LineWidth = 1.00
        l.ViewObject.PointSize = 1.00
        l.ViewObject.ArrowSize = str(length/15)+' mm' 
        l.ViewObject.Selectable = False
        #Add z vector of the coordinate system:
        p2 = FreeCAD.Vector(0, 0, length)
        l = Draft.makeLine(p1, p2)
        l.Label = 'z: joint: '+ label
        l.ViewObject.ArrowType = u"Arrow"            
        l.ViewObject.LineColor = (0.00,0.00,1.00)
        l.ViewObject.PointColor = (0.00,0.00,1.00)
        l.Placement=FreeCAD.Placement(FreeCAD.Vector(x,y,z), FreeCAD.Rotation(FreeCAD.Vector(0,0,1),0), FreeCAD.Vector(0,0,0))
        l.ViewObject.EndArrow = True        
        l.ViewObject.LineWidth = 1.00
        l.ViewObject.PointSize = 1.00
        l.ViewObject.ArrowSize = str(length/15)+' mm' 
        l.ViewObject.Selectable = False             
        #Add the vector to visualize reaction forces
        Llength = FreeCAD.Units.Quantity(FreeCAD.ActiveDocument.getObjectsByLabel("X")[0].End[0]/4,FreeCAD.Units.Unit('mm'))
        p1 = FreeCAD.Vector(x, y, z)
        p2 = FreeCAD.Vector(x+Llength, y+Llength, z+Llength)         
        d = Draft.makeLine(p1, p2)
        d.ViewObject.LineColor = (1.00,0.00,0.00)
        d.ViewObject.PointColor = (1.00,0.00,0.00)  
        d.ViewObject.LineWidth = 1.00
        d.ViewObject.PointSize = 1.00
        d.ViewObject.EndArrow = True
        d.ViewObject.ArrowType = u"Arrow"
        d.ViewObject.ArrowSize = str(Llength/75)#+' mm'
        d.ViewObject.Selectable = False
        d.Label = "jf: "+ label 
        
        FreeCAD.ActiveDocument.recompute()
Beispiel #3
0
    def updateData(self, obj, prop):
        if hasattr(self,"arc"):
            from pivy import coin
            import Part, DraftGeomUtils
            import DraftGui
            arcsegs = 24

            # calculate the arc data
            if DraftVecUtils.isNull(obj.Normal):
                norm = App.Vector(0,0,1)
            else:
                norm = obj.Normal
            radius = (obj.Dimline.sub(obj.Center)).Length
            self.circle = Part.makeCircle(radius,obj.Center,norm,obj.FirstAngle.Value,obj.LastAngle.Value)
            self.p2 = self.circle.Vertexes[0].Point
            self.p3 = self.circle.Vertexes[-1].Point
            mp = DraftGeomUtils.findMidpoint(self.circle.Edges[0])
            ray = mp.sub(obj.Center)

            # set text value
            if obj.LastAngle.Value > obj.FirstAngle.Value:
                a = obj.LastAngle.Value - obj.FirstAngle.Value
            else:
                a = (360 - obj.FirstAngle.Value) + obj.LastAngle.Value
            su = True
            if hasattr(obj.ViewObject,"ShowUnit"):
                su = obj.ViewObject.ShowUnit
            if hasattr(obj.ViewObject,"Decimals"):
                self.string = DraftGui.displayExternal(a,obj.ViewObject.Decimals,'Angle',su)
            else:
                self.string = DraftGui.displayExternal(a,None,'Angle',su)
            if obj.ViewObject.Override:
                self.string = obj.ViewObject.Override.replace("$dim",\
                    self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(self.string)

            # check display mode
            try:
                m = obj.ViewObject.DisplayMode
            except: # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D","3D"][utils.get_param("dimstyle",0)]

            # set the arc
            if m == "3D":
                # calculate the spacing of the text
                spacing = (len(self.string)*obj.ViewObject.FontSize.Value)/8.0
                pts1 = []
                cut = None
                pts2 = []
                for i in range(arcsegs+1):
                    p = self.circle.valueAt(self.circle.FirstParameter+((self.circle.LastParameter-self.circle.FirstParameter)/arcsegs)*i)
                    if (p.sub(mp)).Length <= spacing:
                        if cut is None:
                            cut = i
                    else:
                        if cut is None:
                            pts1.append([p.x,p.y,p.z])
                        else:
                            pts2.append([p.x,p.y,p.z])
                self.coords.point.setValues(pts1+pts2)
                i1 = len(pts1)
                i2 = i1+len(pts2)
                self.arc.coordIndex.setValues(0,len(pts1)+len(pts2)+1,list(range(len(pts1)))+[-1]+list(range(i1,i2)))
                if (len(pts1) >= 3) and (len(pts2) >= 3):
                    self.circle1 = Part.Arc(App.Vector(pts1[0][0],pts1[0][1],pts1[0][2]),App.Vector(pts1[1][0],pts1[1][1],pts1[1][2]),App.Vector(pts1[-1][0],pts1[-1][1],pts1[-1][2])).toShape()
                    self.circle2 = Part.Arc(App.Vector(pts2[0][0],pts2[0][1],pts2[0][2]),App.Vector(pts2[1][0],pts2[1][1],pts2[1][2]),App.Vector(pts2[-1][0],pts2[-1][1],pts2[-1][2])).toShape()
            else:
                pts = []
                for i in range(arcsegs+1):
                    p = self.circle.valueAt(self.circle.FirstParameter+((self.circle.LastParameter-self.circle.FirstParameter)/arcsegs)*i)
                    pts.append([p.x,p.y,p.z])
                self.coords.point.setValues(pts)
                self.arc.coordIndex.setValues(0,arcsegs+1,list(range(arcsegs+1)))

            # set the arrow coords and rotation
            self.trans1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.coord1.point.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.trans2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
            self.coord2.point.setValue((self.p3.x,self.p3.y,self.p3.z))
            # calculate small chords to make arrows look better
            arrowlength = 4*obj.ViewObject.ArrowSize.Value
            u1 = (self.circle.valueAt(self.circle.FirstParameter+arrowlength)).sub(self.circle.valueAt(self.circle.FirstParameter)).normalize()
            u2 = (self.circle.valueAt(self.circle.LastParameter)).sub(self.circle.valueAt(self.circle.LastParameter-arrowlength)).normalize()
            if hasattr(obj.ViewObject,"FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u1 = u1.negative()
                    u2 = u2.negative()
            w2 = self.circle.Curve.Axis
            w1 = w2.negative()
            v1 = w1.cross(u1)
            v2 = w2.cross(u2)
            q1 = App.Placement(DraftVecUtils.getPlaneRotation(u1,v1,w1)).Rotation.Q
            q2 = App.Placement(DraftVecUtils.getPlaneRotation(u2,v2,w2)).Rotation.Q
            self.trans1.rotation.setValue((q1[0],q1[1],q1[2],q1[3]))
            self.trans2.rotation.setValue((q2[0],q2[1],q2[2],q2[3]))

            # setting text pos & rot
            self.tbase = mp
            if hasattr(obj.ViewObject,"TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition

            u3 = ray.cross(norm).normalize()
            v3 = norm.cross(u3)
            r = App.Placement(DraftVecUtils.getPlaneRotation(u3,v3,norm)).Rotation
            offset = r.multVec(App.Vector(0,1,0))

            if hasattr(obj.ViewObject,"TextSpacing"):
                offset = DraftVecUtils.scaleTo(offset,obj.ViewObject.TextSpacing.Value)
            else:
                offset = DraftVecUtils.scaleTo(offset,0.05)
            if m == "3D":
                offset = offset.negative()
            self.tbase = self.tbase.add(offset)
            q = r.Q
            self.textpos.translation.setValue([self.tbase.x,self.tbase.y,self.tbase.z])
            self.textpos.rotation = coin.SbRotation(q[0],q[1],q[2],q[3])

            # set the angle property
            if round(obj.Angle,utils.precision()) != round(a,utils.precision()):
                obj.Angle = a
    def addtofreecad(self, doc=None, fcpar=None):
        def center(obj, x, y, z):
            obj.Placement = FreeCAD.Placement(\
               FreeCAD.Vector(-x/2.0,-y/2.0,-z/2.0),\
               FreeCAD.Rotation(0,0,0,1))

        import FreeCAD, Part
        if not doc:
            doc = FreeCAD.newDocument()
        namel = self.name.lower()
        multifeature = {
            'union': "Part::MultiFuse",
            'imp_union': "Part::MultiFuse",
            'intersection': "Part::MultiCommon"
        }
        if namel in multifeature:
            if len(self.children) > 1:
                obj = doc.addObject(multifeature[namel], namel)
                subobjs = [
                    child.addtofreecad(doc, obj) for child in self.children
                ]
                obj.Shapes = subobjs
                for subobj in subobjs:
                    subobj.ViewObject.hide()
            elif len(self.children) == 1:
                obj = self.children[0].addtofreecad(doc, fcpar or True)
            else:
                obj = fcpar
        elif namel == 'difference':
            if len(self.children) == 1:
                obj = self.children[0].addtofreecad(doc, fcpar or True)
            else:
                obj = doc.addObject("Part::Cut", namel)
                base = self.children[0].addtofreecad(doc, obj)

                if len(self.children) == 2:
                    tool = self.children[1].addtofreecad(doc, obj)
                else:
                    tool = Node(name='imp_union',\
                        children=self.children[1:]).addtofreecad(doc,obj)
                obj.Base = base
                obj.Tool = tool
                base.ViewObject.hide()
                tool.ViewObject.hide()
        elif namel == 'cube':
            obj = doc.addObject('Part::Box', namel)
            x, y, z = self.arguments['size']
            obj.Length = x
            obj.Width = y
            obj.Height = z
            if self.arguments['center']:
                center(obj, x, y, z)
        elif namel == 'sphere':
            obj = doc.addObject("Part::Sphere", namel)
            obj.Radius = self.arguments['r']
        elif namel == 'cylinder':
            h = self.arguments['h']
            r1, r2 = self.arguments['r1'], self.arguments['r2']
            if '$fn' in self.arguments and self.arguments['$fn'] > 2 \
            and self.arguments['$fn']<=Node.fnmin: # polygonal
                if r1 == r2:  # prismatic
                    obj = doc.addObject("Part::Prism", "prism")
                    obj.Polygon = int(self.arguments['$fn'])
                    obj.Length = r1
                    obj.Height = h
                    if self.arguments['center']:
                        center(obj, 0, 0, h)
                    base.ViewObject.hide()
                elif True:  #use Frustum Feature with makeRuledSurface
                    obj = doc.addObject("Part::FeaturePython", 'frustum')
                    Frustum(obj, r1, r2, int(self.arguments['$fn']), h)
                    ViewProviderTree(obj.ViewObject)
                    if self.arguments['center']:
                        center(obj, 0, 0, h)
                else:  #Use Part::Loft and GetWire Feature
                    obj = doc.addObject('Part::Loft', 'frustum')
                    import Draft
                    p1 = Draft.makePolygon(int(self.arguments['$fn']), r1)
                    p2 = Draft.makePolygon(int(self.arguments['$fn']), r2)
                    if self.arguments['center']:
                        p1.Placement = FreeCAD.Placement(\
                        FreeCAD.Vector(0.0,0.0,-h/2.0),FreeCAD.Rotation())
                        p2.Placement = FreeCAD.Placement(\
                        FreeCAD.Vector(0.0,0.0,h/2.0),FreeCAD.Rotation())
                    else:
                        p2.Placement = FreeCAD.Placement(\
                        FreeCAD.Vector(0.0,0.0,h),FreeCAD.Rotation())
                    w1 = doc.addObject("Part::FeaturePython", 'polygonwire1')
                    w2 = doc.addObject("Part::FeaturePython", 'polygonwire2')
                    GetWire(w1, p1)
                    GetWire(w2, p2)
                    ViewProviderTree(w1.ViewObject)
                    ViewProviderTree(w2.ViewObject)
                    obj.Sections = [w1, w2]
                    obj.Solid = True
                    obj.Ruled = True
                    p1.ViewObject.hide()
                    p2.ViewObject.hide()
                    w1.ViewObject.hide()
                    w2.ViewObject.hide()
            else:
                if r1 == r2:
                    obj = doc.addObject("Part::Cylinder", namel)
                    obj.Height = h
                    obj.Radius = r1
                else:
                    obj = doc.addObject("Part::Cone", 'cone')
                    obj.Height = h
                    obj.Radius1, obj.Radius2 = r1, r2
                if self.arguments['center']:
                    center(obj, 0, 0, h)
        elif namel == 'polyhedron':
            obj = doc.addObject("Part::Feature", namel)
            points = self.arguments['points']
            faces = self.arguments['triangles']
            shell=Part.Shell([Part.Face(Part.makePolygon(\
                    [tuple(points[pointindex]) for pointindex in \
                    (face+face[0:1])])) for face in faces])
            #            obj.Shape=Part.Solid(shell).removeSplitter()
            solid = Part.Solid(shell).removeSplitter()
            if solid.Volume < 0:
                #                solid.complement()
                solid.reverse()
            obj.Shape = solid  #.removeSplitter()

        elif namel == 'polygon':
            obj = doc.addObject("Part::Feature", namel)
            points = self.arguments['points']
            paths = self.arguments.get('paths')
            if not paths:
                faces = [
                    Part.Face(
                        Part.makePolygon([(x, y, 0)
                                          for x, y in points + points[0:1]]))
                ]
            else:
                faces= [Part.Face(Part.makePolygon([(points[pointindex][0],points[pointindex][1],0) for \
                    pointindex in (path+path[0:1])])) for path in paths]
            obj.Shape = subtractfaces(faces)
        elif namel == 'square':
            obj = doc.addObject("Part::Plane", namel)
            x, y = self.arguments['size']
            obj.Length = x
            obj.Width = y
            if self.arguments['center']:
                center(obj, x, y, 0)
        elif namel == 'circle':
            r = self.arguments['r']
            import Draft
            if '$fn' in self.arguments and self.arguments['$fn'] != 0 \
            and self.arguments['$fn']<=Node.fnmin:
                obj = Draft.makePolygon(int(self.arguments['$fn']), r)
            else:
                obj = Draft.makeCircle(r)  # create a Face
                #obj = doc.addObject("Part::Circle",namel);obj.Radius = r
        elif namel == 'color':
            if len(self.children) == 1:
                obj = self.children[0].addtofreecad(doc, fcpar or True)
            else:
                obj = Node(name='imp_union',\
                        children=self.children).addtofreecad(doc,fcpar or True)
            obj.ViewObject.ShapeColor = tuple(
                [float(p) for p in self.arguments[:3]])  #RGB
            transp = 100 - int(math.floor(100 * self.arguments[3]))  #Alpha
            obj.ViewObject.Transparency = transp
        elif namel == 'multmatrix':
            assert (len(self.children) > 0)
            m1l = [round(f, 12) for f in sum(self.arguments, [])
                   ]  #Thats the original matrix
            m1 = FreeCAD.Matrix(*tuple(m1l))  #Thats the original matrix
            if isspecialorthogonalpython(fcsubmatrix(
                    m1)):  #a Placement can represent the transformation
                if len(self.children) == 1:
                    obj = self.children[0].addtofreecad(doc, fcpar or True)
                else:
                    obj = Node(name='imp_union',\
                            children=self.children).addtofreecad(doc,fcpar or True)
                    #FreeCAD.Console.PrintMessage('obj %s\nmat %s/n' % (obj.Placement,m1))
                obj.Placement = FreeCAD.Placement(m1).multiply(obj.Placement)
            else:  #we need to apply the matrix transformation to the Shape using a custom PythonFeature
                obj = doc.addObject("Part::FeaturePython", namel)
                if len(self.children) == 1:
                    child = self.children[0].addtofreecad(doc, obj)
                else:
                    child = Node(name='imp_union',\
                            children=self.children).addtofreecad(doc,obj)
                MatrixTransform(
                    obj, m1, child)  #This object is not mutable from the GUI
                ViewProviderTree(obj.ViewObject)
        #elif namel == 'import': pass #Custom Feature
        elif namel == 'linear_extrude':
            height = self.arguments['height']
            twist = self.arguments.get('twist')
            if not twist:
                obj = doc.addObject("Part::Extrusion", namel)
            else:  #twist
                obj = doc.addObject("Part::FeaturePython", 'twist_extrude')
            if len(self.children) == 0:
                base = Node('import', self.arguments).addtofreecad(doc, obj)
            elif len(self.children) == 1:
                base = self.children[0].addtofreecad(doc, obj)
            else:
                base = Node(name='imp_union',\
                            children=self.children).addtofreecad(doc,obj)
            if False and base.isDerivedFrom('Part::MultiFuse'):
                #does not solve all the problems
                newobj = doc.addObject("Part::FeaturePython", 'refine')
                RefineShape(newobj, base)
                ViewProviderTree(newobj.ViewObject)
                base.ViewObject.hide()
                base = newobj
            if not twist:
                obj.Base = base
                obj.Dir = (0, 0, height)
            else:  #twist
                Twist(obj, base, height, -twist)
                ViewProviderTree(obj.ViewObject)
            if self.arguments['center']:
                center(obj, 0, 0, height)
            base.ViewObject.hide()

        elif namel == 'rotate_extrude':
            obj = doc.addObject("Part::Revolution", namel)
            if len(self.children) == 0:
                base = Node('import', self.arguments).addtofreecad(doc, obj)
            elif len(self.children) == 1:
                base = self.children[0].addtofreecad(doc, obj)
            else:
                base = Node(name='imp_union',\
                            children=self.children).addtofreecad(doc,obj)
            if False and base.isDerivedFrom('Part::MultiFuse'):
                #creates 'Axe and meridian are confused' Errors
                newobj = doc.addObject("Part::FeaturePython", 'refine')
                RefineShape(newobj, base)
                ViewProviderTree(newobj.ViewObject)
                base.ViewObject.hide()
                base = newobj
            obj.Source = base
            obj.Axis = (0.00, 1.00, 0.00)
            obj.Base = (0.00, 0.00, 0.00)
            obj.Angle = 360.00
            base.ViewObject.hide()
            obj.Placement = FreeCAD.Placement(FreeCAD.Vector(),
                                              FreeCAD.Rotation(0, 0, 90))
        elif namel == 'projection':
            if self.arguments['cut']:
                planename = 'xy_plane_used_for_project_cut'
                obj = doc.addObject('Part::MultiCommon', 'projection_cut')
                plane = doc.getObject(planename)
                if not plane:
                    plane = doc.addObject("Part::Plane", planename)
                    plane.Length = Node.planedim * 2
                    plane.Width = Node.planedim * 2
                    plane.Placement = FreeCAD.Placement(FreeCAD.Vector(\
                    -Node.planedim,-Node.planedim,0),FreeCAD.Rotation(0,0,0,1))
                #plane.ViewObject.hide()
                subobjs = [
                    child.addtofreecad(doc, obj) for child in self.children
                ]
                subobjs.append(plane)
                obj.Shapes = subobjs
                for subobj in subobjs:
                    subobj.ViewObject.hide()
            else:
                #Do a proper projection
                raise (NotImplementedError)
        elif namel == 'import':
            filename = self.arguments.get('file')
            scale = self.arguments.get('scale')
            origin = self.arguments.get('origin')
            if filename:
                import os
                docname = os.path.split(filename)[1]
                objname, extension = docname.split('.', 1)
                if not os.path.isabs(filename):
                    try:
                        global lastimportpath
                        filename = os.path.join(lastimportpath, filename)
                    except:
                        raise  #no path given
                # Check for a mesh fileformat support by the Mesh mddule
                if extension.lower() in reverseimporttypes()['Mesh']:
                    import Mesh
                    mesh1 = doc.getObject(objname)  #reuse imported object
                    if not mesh1:
                        Mesh.insert(filename)
                        mesh1 = doc.getObject(objname)
                    mesh1.ViewObject.hide()
                    sh = Part.Shape()
                    sh.makeShapeFromMesh(mesh1.Mesh.Topology, 0.1)
                    solid = Part.Solid(sh)
                    obj = doc.addObject("Part::FeaturePython",
                                        'import_%s_%s' % (extension, objname))
                    #obj=doc.addObject('Part::Feature',)
                    ImportObject(
                        obj, mesh1)  #This object is not mutable from the GUI
                    ViewProviderTree(obj.ViewObject)
                    solid = solid.removeSplitter()
                    if solid.Volume < 0:
                        #sh.reverse()
                        #sh = sh.copy()
                        solid.complement()
                    obj.Shape = solid  #.removeSplitter()
                elif extension in ['dxf']:
                    layera = self.arguments.get('layer')
                    featname = 'import_dxf_%s_%s' % (objname, layera)
                    # reusing an allready imported object does not work if the
                    #shape in not yet calculated
                    import importDXF
                    global dxfcache
                    layers = dxfcache.get(id(doc), [])
                    if layers:
                        try:
                            groupobj = [
                                go for go in layers
                                if (not layera) or go.Label == layera
                            ]
                        except:
                            groupobj = None
                    else:
                        groupobj = None
                    if not groupobj:
                        groupname = objname
                        layers = importDXF.processdxf(
                            doc, filename) or importDXF.layers
                        dxfcache[id(doc)] = layers[:]
                        for l in layers:
                            for o in l.Group:
                                o.ViewObject.hide()
                            l.ViewObject.hide()
                        groupobj = [
                            go for go in layers
                            if (not layera) or go.Label == layera
                        ]
                    edges = []
                    for shapeobj in groupobj[0].Group:
                        edges.extend(shapeobj.Shape.Edges)
                    try:
                        f = edgestofaces(edges)
                    except:
                        FreeCAD.Console.PrintError(\
 'processing of dxf import faild\nPlease rework \'%s\' manualy\n' % layera)
                        f = Part.Shape()  #empty Shape
                    obj = doc.addObject("Part::FeaturePython",
                                        'import_dxf_%s_%s' % (objname, layera))
                    #obj=doc.addObject('Part::Feature',)
                    ImportObject(
                        obj,
                        groupobj[0])  #This object is not mutable from the GUI
                    ViewProviderTree(obj.ViewObject)
                    obj.Shape = f

                else:
                    FreeCAD.Console.ErrorMessage(\
                            'Filetype of %s not supported\n' % (filename))
                    raise (NotImplementedError)
                if obj:  #handle origin and scale
                    if scale is not None and scale != 1:
                        if origin is not None and any([c != 0
                                                       for c in origin]):
                            raise (NotImplementedError
                                   )  # order of transformations unkown
                        child = obj
                        m1 = FreeCAD.Matrix()
                        m1.scale(scale, scale, scale)
                        obj = doc.addObject("Part::FeaturePython",
                                            'scale_import')
                        MatrixTransform(
                            obj, m1,
                            child)  #This object is not mutable from the GUI
                        ViewProviderTree(obj.ViewObject)
                    elif origin is not None and any([c != 0 for c in origin]):
                        placement = FreeCAD.Placement(
                            FreeCAD.Vector(*[-c for c in origin]),
                            FreeCAD.Rotation())
                        obj.Placement = placement.multiply(obj.Placement)
                else:
                    FreeCAD.Console.ErrorMessage('Import of %s failed\n' %
                                                 (filename))

        elif namel == 'minkowski':
            childrennames = [child.name.lower() for child in self.children]
            if len(self.children) == 2 and \
                childrennames.count('cube')==1 and \
                (childrennames.count('sphere') + \
                childrennames.count('cylinder')) == 1:
                if self.children[0].name.lower() == 'cube':
                    cube = self.children[0]
                    roundobj = self.children[1]
                elif self.children[1].name.lower() == 'cube':
                    cube = self.children[1]
                    roundobj = self.children[0]
                roundobjname = roundobj.name.lower()
                issphere = roundobjname == 'sphere'
                cubeobj = doc.addObject('Part::Box', 'roundedcube')
                x, y, z = cube.arguments['size']
                r=roundobj.arguments.get('r') or \
                        roundobj.arguments.get('r1')
                cubeobj.Length = x + 2 * r
                cubeobj.Width = y + 2 * r
                cubeobj.Height = z + 2 * r * issphere
                obj = doc.addObject("Part::Fillet",
                                    "%s_%s" % (namel, roundobjname))
                obj.Base = cubeobj
                cubeobj.ViewObject.hide()
                if issphere:
                    obj.Edges = [(i, r, r) for i in range(1, 13)]
                else:  #cylinder
                    obj.Edges = [(i, r, r) for i in [1, 3, 5, 7]]
                if cube.arguments['center']:
                    center(cubeobj, x + 2 * r, y + 2 * r, z + 2 * r * issphere)
                else:  #htandle a rotated cylinder
                    #OffsetShape
                    raise (NotImplementedError)
            elif childrennames.count('sphere') == 1:
                sphereindex = childrennames.index('sphere')
                sphere = self.children[sphereindex]
                offset = sphere.arguments['r']
                nonsphere=self.children[0:sphereindex]+\
                        self.sphere[sphereindex+1:]
                obj = doc.addObject("Part::FeaturePython", 'Offset')
                if len(nonsphere) == 1:
                    child = nonsphere[0].addtofreecad(doc, obj)
                else:
                    child = Node(name='imp_union',\
                        children=nonsphere).addtofreecad(doc,obj)
                OffsetShape(obj, child, offset)
                ViewProviderTree(obj.ViewObject)
            elif False:
                raise (NotImplementedError)
                pass  # handle rotated cylinders and select edges that
                #radius = radius0 * m1.multiply(FreeCAD.Vector(0,0,1)).dot(edge.Curve.tangent(0)[0])
            else:
                raise (NotImplementedError)
        elif namel == 'surface':
            obj = doc.addObject("Part::Feature", namel)  #include filename?
            obj.Shape, xoff, yoff = makeSurfaceVolume(self.arguments['file'])
            if self.arguments['center']:
                center(obj, xoff, yoff, 0.0)
            return obj
            #import os
            #scadstr = 'surface(file = "%s", center = %s );' % \
            #    (self.arguments['file'], 'true' if self.arguments['center'] else 'false')
            #docname=os.path.split(self.arguments['file'])[1]
            #objname,extension = docname.split('.',1)
            #obj = openscadmesh(doc,scadstr,objname)

        elif namel in ['glide', 'hull']:
            raise (NotImplementedError)
        elif namel in ['render', 'subdiv'] or True:
            lenchld = len(self.children)
            if lenchld == 1:
                FreeCAD.Console.PrintMessage('Not recognized %s\n' % (self))
                obj = self.children[0].addtofreecad(doc, fcpar)
            elif lenchld > 1:
                obj = Node(name='imp_union',\
                        children=self.children).addtofreecad(doc,fcpar or True)
            else:
                obj = doc.addObject("Part::Feature", 'Not_Impl_%s' % namel)
        if fcpar == True:  #We are the last real object, our parent is not rendered.
            return obj

        if fcpar:
            try:
                obj.ViewObject.hide()
            except:
                raise
            if True:  #never refine the Shape, as it itroduces crashes
                return obj
            else:  #refine Shape
                import Draft
                if obj.Type =='Part::Extrusion' and obj.Base.Type == 'Part::Part2DObjectPython' and \
                    isinstance(obj.Base.Proxy,Draft._Polygon) or \
                    (not obj.isDerivedFrom('Part::Extrusion') and \
                    not obj.isDerivedFrom('Part::Boolean') and \
                    not obj.isDerivedFrom('Part::Cut') and \
                    not obj.isDerivedFrom('Part::MultiCommon') and \
                    not obj.isDerivedFrom('Part::MultiFuse') and \
                    not obj.isDerivedFrom('Part::Revolution') ) \
                    or (obj.isDerivedFrom('Part::FeaturePython') and isinstance(obj.Proxy,RefineShape)):
                    return obj
                else:
                    newobj = doc.addObject("Part::FeaturePython", 'refine')
                    RefineShape(newobj, obj)
                    ViewProviderTree(newobj.ViewObject)
                    obj.ViewObject.hide()
                    return newobj

        else:
            doc.recompute()
Beispiel #5
0
def p_multmatrix_action(p):
    'multmatrix_action : multmatrix LPAREN matrix RPAREN OBRACE block_list EBRACE'
    if printverbose: print("MultMatrix")
    transform_matrix = FreeCAD.Matrix()
    if printverbose: print("Multmatrix")
    if printverbose: print(p[3])
    m1l=sum(p[3],[])
    if any('x' in me for me in m1l): #hexfloats
        m1l=[float.fromhex(me) for me in m1l]
        matrixisrounded=False
    elif max((len(me) for me in m1l)) >= 14: #might have double precision
        m1l=[float(me) for me in m1l] # assume precise output
        m1l=[(0 if (abs(me) < 1e-15) else me) for me in m1l]
        matrixisrounded=False
    else: #trucanted numbers
        m1l=[round(float(me),12) for me in m1l] #round
        matrixisrounded=True
    transform_matrix = FreeCAD.Matrix(*tuple(m1l))
    if printverbose: print(transform_matrix)
    if printverbose: print("Apply Multmatrix")
#   If more than one object on the stack for multmatrix fuse first
    if (len(p[6]) == 0) :
        part = placeholder('group',[],'{}')
    elif (len(p[6]) > 1) :
        part = fuse(p[6],"Matrix Union")
    else :
        part = p[6][0]
    if (isspecialorthogonalpython(fcsubmatrix(transform_matrix))) :
        if printverbose: print("special orthogonal")
        if matrixisrounded:
            if printverbose: print("rotation rounded")
            plm=FreeCAD.Placement(transform_matrix)
            plm=FreeCAD.Placement(plm.Base,roundrotation(plm.Rotation))
            part.Placement=plm.multiply(part.Placement)
        else:
            part.Placement=FreeCAD.Placement(transform_matrix).multiply(\
                    part.Placement)
        new_part = part
    elif isrotoinversionpython(fcsubmatrix(transform_matrix)):
        if printverbose: print("orthogonal and inversion")
        cmat,axisvec = decomposerotoinversion(transform_matrix)
        new_part=doc.addObject("Part::Mirroring",'mirr_%s'%part.Name)
        new_part.Source=part
        new_part.Normal=axisvec
        if matrixisrounded:
            if printverbose: print("rotation rounded")
            plm=FreeCAD.Placement(cmat)
            new_part.Placement=FreeCAD.Placement(plm.Base,roundrotation(plm.Rotation))
        else:
            new_part.Placement=FreeCAD.Placement(cmat)
        new_part.Label="mirrored %s" % part.Label
        if gui:
            part.ViewObject.hide()
    elif FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
        GetBool('useMultmatrixFeature'):
        from OpenSCADFeatures import MatrixTransform
        new_part=doc.addObject("Part::FeaturePython",'Matrix Deformation')
        MatrixTransform(new_part,transform_matrix,part)
        if gui:
            if FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/OpenSCAD").\
                GetBool('useViewProviderTree'):
                from OpenSCADFeatures import ViewProviderTree
                ViewProviderTree(new_part.ViewObject)
            else:
                new_part.ViewObject.Proxy = 0
            part.ViewObject.hide()
    else :
        if printverbose: print("Transform Geometry")
#       Need to recompute to stop transformGeometry causing a crash        
        doc.recompute()
        new_part = doc.addObject("Part::Feature","Matrix Deformation")
      #  new_part.Shape = part.Base.Shape.transformGeometry(transform_matrix)
        new_part.Shape = part.Shape.transformGeometry(transform_matrix) 
        if gui:
            part.ViewObject.hide()
    if False :  
#   Does not fix problemfile or beltTighener although later is closer       
        newobj=doc.addObject("Part::FeaturePython",'RefineMultMatrix')
        RefineShape(newobj,new_part)
        if gui:
            newobj.ViewObject.Proxy = 0
            new_part.ViewObject.hide()   
        p[0] = [newobj]
    else :
        p[0] = [new_part]
    if printverbose: print("Multmatrix applied")
Beispiel #6
0
    def execute(self, obj):

        "constructs the shape of the stairs"

        if self.clone(obj):
            return

        import Part
        self.steps = []
        self.pseudosteps = []
        self.structures = []
        pl = obj.Placement
        landings = 0

        base = None

        if obj.Base:
            if hasattr(obj.Base, "Shape"):
                if obj.Base.Shape:
                    if obj.Base.Shape.Solids:
                        base = obj.Base.Shape.copy()

        if (not base) and obj.Width.Value and obj.Height.Value and (
                obj.NumberOfSteps > 1):
            if obj.Base:
                if not obj.Base.isDerivedFrom("Part::Feature"):
                    return
                if obj.Base.Shape.Solids:
                    obj.Shape = obj.Base.Shape.copy()
                    obj.Placement = FreeCAD.Placement(
                        obj.Base.Placement).multiply(pl)
                    obj.TreadDepth = 0.0
                    obj.RiserHeight = 0.0
                    return
                if not obj.Base.Shape.Edges:
                    return
                if obj.Base.Shape.Faces:
                    return
                if (len(obj.Base.Shape.Edges) == 1):
                    edge = obj.Base.Shape.Edges[0]
                    if isinstance(edge.Curve, (Part.LineSegment, Part.Line)):
                        if obj.Landings == "At center":
                            landings = 1
                            self.makeStraightStairsWithLanding(obj, edge)
                        else:
                            self.makeStraightStairs(obj, edge)
                    else:
                        if obj.Landings == "At center":
                            landings = 1
                            self.makeCurvedStairsWithLandings(obj, edge)
                        else:
                            self.makeCurvedStairs(obj, edge)
            else:
                if not obj.Length.Value:
                    return
                edge = Part.LineSegment(Vector(0, 0, 0),
                                        Vector(obj.Length.Value, 0,
                                               0)).toShape()
                if obj.Landings == "At center":
                    landings = 1
                    self.makeStraightStairsWithLanding(obj, edge)
                else:
                    self.makeStraightStairs(obj, edge)

        if self.structures or self.steps:
            base = Part.makeCompound(self.structures + self.steps)
        elif self.pseudosteps:
            shape = Part.makeCompound(self.pseudosteps)
            obj.Shape = shape
            obj.Placement = pl
            return

        base = self.processSubShapes(obj, base, pl)
        if base:
            if not base.isNull():
                obj.Shape = base
                obj.Placement = pl

        # compute step data
        if obj.NumberOfSteps > 1:
            l = obj.Length.Value
            h = obj.Height.Value
            if obj.Base:
                if obj.Base.isDerivedFrom("Part::Feature"):
                    l = obj.Base.Shape.Length
                    if obj.Base.Shape.BoundBox.ZLength:
                        h = obj.Base.Shape.BoundBox.ZLength
            if obj.LandingDepth:
                obj.TreadDepth = float(l -
                                       (landings * obj.LandingDepth.Value)) / (
                                           obj.NumberOfSteps - (1 + landings))
            else:
                obj.TreadDepth = float(l - (landings * obj.Width.Value)) / (
                    obj.NumberOfSteps - (1 + landings))
            obj.RiserHeight = float(h) / obj.NumberOfSteps
            obj.BlondelRatio = obj.RiserHeight.Value * 2 + obj.TreadDepth.Value
Beispiel #7
0
def calculate_placement(globalRotation,
                        edge,
                        offset,
                        RefPt,
                        xlate,
                        align,
                        normal=None,
                        mode='Original',
                        overrideNormal=False):
    """Orient shape to a local coordinate system (tangent, normal, binormal).

    Orient shape at parameter offset, normally length.

    http://en.wikipedia.org/wiki/Euler_angles (previous version)
    http://en.wikipedia.org/wiki/Quaternions
    """
    # Start with a null Placement so the translation goes to the right place.
    # Then apply the global orientation.
    placement = App.Placement()
    placement.Rotation = globalRotation

    placement.move(RefPt + xlate)
    if not align:
        return placement

    nullv = App.Vector(0, 0, 0)
    defNormal = App.Vector(0.0, 0.0, 1.0)
    if normal:
        defNormal = normal

    try:
        t = edge.tangentAt(get_parameter_from_v0(edge, offset))
        t.normalize()
    except Exception:
        _wrn(_tr("Cannot calculate path tangent. Copy not aligned."))
        return placement

    if mode in ('Original', 'Tangent'):
        if normal is None:
            n = defNormal
        else:
            n = normal
            n.normalize()

        try:
            b = t.cross(n)
            b.normalize()
        except Exception:
            # weird special case, tangent and normal parallel
            b = nullv
            _wrn(_tr("Tangent and normal are parallel. Copy not aligned."))
            return placement

        if overrideNormal:
            priority = "XZY"
            newRot = App.Rotation(t, b, n, priority)  # t/x, b/y, n/z
        else:
            # must follow X, try to follow Z, Y is what it is
            priority = "XZY"
            newRot = App.Rotation(t, n, b, priority)

    elif mode == 'Frenet':
        try:
            n = edge.normalAt(get_parameter_from_v0(edge, offset))
            n.normalize()
        except App.Base.FreeCADError:  # no/infinite normals here
            n = defNormal
            _msg(_tr("Cannot calculate path normal, using default."))

        try:
            b = t.cross(n)
            b.normalize()
        except Exception:
            b = nullv
            _wrn(_tr("Cannot calculate path binormal. Copy not aligned."))
            return placement

        priority = "XZY"
        newRot = App.Rotation(t, n, b, priority)  # t/x, n/y, b/z
    else:
        _msg(_tr("AlignMode {} is not implemented".format(mode)))
        return placement

    # Have valid tangent, normal, binormal
    newGRot = newRot.multiply(globalRotation)

    placement.Rotation = newGRot
    return placement
Beispiel #8
0
            self.tooltip = tooltip

    def GetCommands(self):
        return tuple(self.cmdlist)

    def GetResources(self):
        return { 'MenuText': self.menu, 'ToolTip': self.tooltip }



"""
    +-----------------------------------------------+
    |         the 3 base rotation Placements        |
    +-----------------------------------------------+
"""
rotX = App.Placement( App.Vector(0,0,0), App.Rotation( App.Vector(1,0,0), 90. ) )
rotY = App.Placement( App.Vector(0,0,0), App.Rotation( App.Vector(0,1,0), 90. ) )
rotZ = App.Placement( App.Vector(0,0,0), App.Rotation( App.Vector(0,0,1), 90. ) )




"""
    +-----------------------------------------------+
    |         returns the object Label (Name)       |
    +-----------------------------------------------+
"""


# Label (Name)
def labelName( obj ):
Beispiel #9
0
def getSVG(section,
           allOn=False,
           renderMode="Wireframe",
           showHidden=False,
           showFill=False,
           scale=1,
           linewidth=1,
           fontsize=1,
           techdraw=False,
           rotation=0):
    """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 Part, 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 and Draft objects
    spaces = []
    nonspaces = []
    drafts = []
    windows = []
    cutface = None
    for o in objs:
        if Draft.getType(o) == "Space":
            spaces.append(o)
        elif Draft.getType(o) in ["Dimension", "Annotation"]:
            drafts.append(o)
        elif o.isDerivedFrom("Part::Part2DObject"):
            drafts.append(o)
        else:
            nonspaces.append(o)
        if Draft.getType(o) == "Window":
            windows.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 in ["Solid", 1]:
        # 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, cutface, cutvolume, invcutvolume = getCutShapes(
            objs, section, showHidden)
        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))
                        # temporarily disabling fill patterns
                        f = Draft.getSVG(s,
                                         direction=direction.negative(),
                                         linewidth=0,
                                         fillstyle="#aaaaaa",
                                         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
    scaledlinewidth = linewidth / scale
    st = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch").GetFloat(
            "CutLineThickness", 2)
    yt = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch").GetFloat(
            "SymbolLineThickness", 0.6)
    da = FreeCAD.ParamGet(
        "User parameter:BaseApp/Preferences/Mod/Arch").GetString(
            "archHiddenPattern", "30,10")
    da = da.replace(" ", "")
    svg = svg.replace('LWPlaceholder', str(scaledlinewidth) + 'px')
    svg = svg.replace('SWPlaceholder', str(scaledlinewidth * st) + 'px')
    svg = svg.replace('DAPlaceholder', str(da))
    if drafts:
        if not techdraw:
            svg += '<g transform="scale(1,-1)">'
        for d in drafts:
            svg += Draft.getSVG(d,
                                scale=scale,
                                linewidth=linewidth * yt,
                                fontsize=fontsize,
                                direction=direction,
                                techdraw=techdraw,
                                rotation=rotation)
        if not techdraw:
            svg += '</g>'
    # filter out spaces not cut by the section plane
    if cutface and spaces:
        spaces = [
            s for s in spaces if s.Shape.BoundBox.intersect(cutface.BoundBox)
        ]
    if spaces:
        if not techdraw:
            svg += '<g transform="scale(1,-1)">'
        for s in spaces:
            svg += Draft.getSVG(s,
                                scale=scale,
                                linewidth=linewidth * yt,
                                fontsize=fontsize,
                                direction=direction,
                                techdraw=techdraw,
                                rotation=rotation)
        if not techdraw:
            svg += '</g>'
    # add additional edge symbols from windows
    if cutface and windows:
        cutwindows = [
            w.Name for w in windows
            if w.Shape.BoundBox.intersect(cutface.BoundBox)
        ]
    if windows:
        sh = []
        for w in windows:
            if not hasattr(w.Proxy, "sshapes"):
                w.Proxy.execute(w)
            if hasattr(w.Proxy, "sshapes"):
                if w.Proxy.sshapes and (w.Name in cutwindows):
                    c = Part.makeCompound(w.Proxy.sshapes)
                    c.Placement = w.Placement
                    sh.append(c)
            # buggy for now...
            #if hasattr(w.Proxy,"vshapes"):
            #    if w.Proxy.vshapes:
            #        c = Part.makeCompound(w.Proxy.vshapes)
            #        c.Placement = w.Placement
            #        sh.append(c)
        if sh:
            if not techdraw:
                svg += '<g transform="scale(1,-1)">'
            for s in sh:
                svg += Draft.getSVG(s,
                                    scale=scale,
                                    linewidth=linewidth * yt,
                                    fontsize=fontsize,
                                    fillstyle="none",
                                    direction=direction,
                                    techdraw=techdraw,
                                    rotation=rotation)
            if not techdraw:
                svg += '</g>'

    #print "complete node:",svg
    return svg
Beispiel #10
0
def createAnnotation(annotation, doc, ifcscale, preferences):
    """creates an annotation object"""

    anno = None
    if annotation.is_a("IfcGrid"):
        axes = []
        uvwaxes = ()
        if annotation.UAxes:
            uvwaxes = annotation.UAxes
        if annotation.VAxes:
            uvwaxes = uvwaxes + annotation.VAxes
        if annotation.WAxes:
            uvwaxes = uvwaxes + annotation.WAxes
        for axis in uvwaxes:
            if axis.AxisCurve:
                sh = get2DShape(axis.AxisCurve, ifcscale)
                if sh and (len(sh[0].Vertexes)
                           == 2):  # currently only straight axes are supported
                    sh = sh[0]
                    l = sh.Length
                    pl = FreeCAD.Placement()
                    pl.Base = sh.Vertexes[0].Point
                    pl.Rotation = FreeCAD.Rotation(
                        FreeCAD.Vector(0, 1, 0),
                        sh.Vertexes[-1].Point.sub(sh.Vertexes[0].Point))
                    o = Arch.makeAxis(1, l)
                    o.Length = l
                    o.Placement = pl
                    o.CustomNumber = axis.AxisTag
                    axes.append(o)
        if axes:
            name = "Grid"
            grid_placement = None
            if annotation.Name:
                name = annotation.Name
                if six.PY2:
                    name = name.encode("utf8")
            if annotation.ObjectPlacement:
                # https://forum.freecadweb.org/viewtopic.php?f=39&t=40027
                grid_placement = getPlacement(annotation.ObjectPlacement,
                                              scaling=1)
            if preferences['PREFIX_NUMBERS']:
                name = "ID" + str(aid) + " " + name
            anno = Arch.makeAxisSystem(axes, name)
            if grid_placement:
                anno.Placement = grid_placement
        print(" axis")
    else:
        name = "Annotation"
        if annotation.Name:
            name = annotation.Name
            if six.PY2:
                name = name.encode("utf8")
        if "annotation" not in name.lower():
            name = "Annotation " + name
        if preferences['PREFIX_NUMBERS']: name = "ID" + str(aid) + " " + name
        shapes2d = []
        for rep in annotation.Representation.Representations:
            if rep.RepresentationIdentifier in [
                    "Annotation", "FootPrint", "Axis"
            ]:
                sh = get2DShape(rep, ifcscale)
                if sh in doc.Objects:
                    # dirty hack: get2DShape might return an object directly if non-shape based (texts for ex)
                    anno = sh
                else:
                    shapes2d.extend(sh)
        if shapes2d:
            import Part
            sh = Part.makeCompound(shapes2d)
            #if preferences['DEBUG']: print(" shape")
            anno = doc.addObject("Part::Feature", name)
            anno.Shape = sh
            p = getPlacement(annotation.ObjectPlacement, ifcscale)
            if p:  # and annotation.is_a("IfcAnnotation"):
                anno.Placement = p
        #else:
        #if preferences['DEBUG']: print(" no shape")

    return anno
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
Beispiel #12
0
    def execute(self, obj):
        # When operating on the object, it is to be treated as a lattice object. If False, treat as a regular shape.'''
        if hasattr(obj, "isLattice"):
            if 'On' in obj.isLattice:
                print(
                    obj.Name +
                    " A generic shape is expected, but an array of placements was supplied. It will be treated as a generic shape.\n"
                )

        rst = []  # variable to receive the final list of shapes
        shps = obj.Base.Shape.childShapes()
        if obj.FilterType == 'bypass':
            rst = shps
        elif obj.FilterType == 'specific items':
            rst = []
            flags = [False] * len(shps)
            ranges = obj.items.split(';')
            for r in ranges:
                r_v = r.split(':')
                if len(r_v) == 1:
                    i = int(r_v[0])
                    rst.append(shps[i])
                    flags[i] = True
                elif len(r_v) == 2 or len(r_v) == 3:
                    if len(r_v) == 2:
                        r_v.append(
                            ""
                        )  # fix issue #1: instead of checking length here and there, simply add the missing field =) (DeepSOIC)
                    ifrom = None if len(r_v[0].strip()) == 0 else int(r_v[0])
                    ito = None if len(r_v[1].strip()) == 0 else int(r_v[1])
                    istep = None if len(r_v[2].strip()) == 0 else int(r_v[2])
                    rst = rst + shps[ifrom:ito:istep]
                    for b in flags[ifrom:ito:istep]:
                        b = True
                else:
                    raise ValueError('index range cannot be parsed:' + r)
            if obj.Invert:
                rst = []
                for i in xrange(0, len(shps)):
                    if not flags[i]:
                        rst.append(shps[i])
        elif obj.FilterType == 'collision-pass':
            stencil = obj.Stencil.Shape
            for s in shps:
                d = s.distToShape(stencil)
                if bool(d[0] < DistConfusion) ^ bool(obj.Invert):
                    rst.append(s)
        elif obj.FilterType == 'window-volume' or obj.FilterType == 'window-area' or obj.FilterType == 'window-length' or obj.FilterType == 'window-distance':
            vals = [0.0] * len(shps)
            for i in xrange(0, len(shps)):
                if obj.FilterType == 'window-volume':
                    vals[i] = shps[i].Volume
                elif obj.FilterType == 'window-area':
                    vals[i] = shps[i].Area
                elif obj.FilterType == 'window-length':
                    vals[i] = shps[i].Length
                elif obj.FilterType == 'window-distance':
                    vals[i] = shps[i].distToShape(obj.Stencil.Shape)[0]

            maxval = max(vals)
            if obj.Stencil:
                if obj.FilterType == 'window-volume':
                    maxval = obj.Stencil.Shape.Volume
                elif obj.FilterType == 'window-area':
                    maxval = obj.Stencil.Shape.Area
                elif obj.FilterType == 'window-length':
                    maxval = obj.Stencil.Shape.Length
            if obj.OverrideMaxVal:
                maxval = obj.OverrideMaxVal

            valFrom = obj.WindowFrom / 100.0 * maxval
            valTo = obj.WindowTo / 100.0 * maxval

            for i in xrange(0, len(shps)):
                if bool(vals[i] >= valFrom and vals[i] <= valTo) ^ obj.Invert:
                    rst.append(shps[i])
        else:
            raise ValueError('Filter mode not implemented:' + obj.FilterType)

        if len(rst) == 0:
            scale = 1.0
            if not obj.Base.Shape.isNull():
                scale = obj.Base.Shape.BoundBox.DiagonalLength / math.sqrt(
                    3) / math.sqrt(len(shps))
            if scale < DistConfusion * 100:
                scale = 1.0
            print(scale)
            obj.Shape = getNullShapeShape(scale)
            raise ValueError(
                'Nothing passes through the filter'
            )  # Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing.

        if len(rst) > 1:
            obj.Shape = Part.makeCompound(rst)
        else:  # don't make compound of one shape, output it directly
            sh = rst[0]
            sh.transformShape(sh.Placement.toMatrix(),
                              True)  # True = make copy
            sh.Placement = FreeCAD.Placement()
            obj.Shape = sh

        return
Beispiel #13
0
def _create_objects(doc=None,
                    font_file="/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
                    ):
    """Create the objects of the test file.

    Parameters
    ----------
    doc: App::Document, optional
        It defaults to `None`, which then defaults to the current
        active document, or creates a new document.
    """
    if not doc:
        doc = App.activeDocument()
    if not doc:
        doc = App.newDocument()

    # Line, wire, and fillet
    _msg(16 * "-")
    _msg("Line")
    Draft.make_line(Vector(0, 0, 0), Vector(500, 500, 0))
    t_xpos = -50
    t_ypos = -200
    _set_text(["Line"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Wire")
    Draft.make_wire(
        [Vector(500, 0, 0),
         Vector(1000, 500, 0),
         Vector(1000, 1000, 0)])
    t_xpos += 500
    _set_text(["Wire"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Fillet")
    line_h_1 = Draft.make_line(Vector(1500, 0, 0), Vector(1500, 500, 0))
    line_h_2 = Draft.make_line(Vector(1500, 500, 0), Vector(2000, 500, 0))
    if App.GuiUp:
        line_h_1.ViewObject.DrawStyle = "Dotted"
        line_h_2.ViewObject.DrawStyle = "Dotted"
    doc.recompute()

    Draft.make_fillet([line_h_1, line_h_2], 400)
    t_xpos += 900
    _set_text(["Fillet"], Vector(t_xpos, t_ypos, 0))

    # Circle, arc, arc by 3 points
    _msg(16 * "-")
    _msg("Circle")
    circle = Draft.make_circle(350)
    circle.Placement.Base = Vector(2500, 500, 0)
    t_xpos += 1050
    _set_text(["Circle"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Circular arc")
    arc = Draft.make_circle(350, startangle=0, endangle=100)
    arc.Placement.Base = Vector(3200, 500, 0)
    t_xpos += 800
    _set_text(["Circular arc"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Circular arc 3 points")
    Draft.make_arc_3points(
        [Vector(4600, 0, 0),
         Vector(4600, 800, 0),
         Vector(4000, 1000, 0)])
    t_xpos += 600
    _set_text(["Circular arc 3 points"], Vector(t_xpos, t_ypos, 0))

    # Ellipse, polygon, rectangle
    _msg(16 * "-")
    _msg("Ellipse")
    ellipse = Draft.make_ellipse(500, 300)
    ellipse.Placement.Base = Vector(5500, 250, 0)
    t_xpos += 1600
    _set_text(["Ellipse"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Polygon")
    polygon = Draft.make_polygon(5, 250)
    polygon.Placement.Base = Vector(6500, 500, 0)
    t_xpos += 950
    _set_text(["Polygon"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Rectangle")
    rectangle = Draft.make_rectangle(500, 1000, 0)
    rectangle.Placement.Base = Vector(7000, 0, 0)
    t_xpos += 650
    _set_text(["Rectangle"], Vector(t_xpos, t_ypos, 0))

    # Text
    _msg(16 * "-")
    _msg("Text")
    text = Draft.make_text(["Testing", "text"], Vector(7700, 500, 0))
    if App.GuiUp:
        text.ViewObject.FontSize = 100
    t_xpos += 700
    _set_text(["Text"], Vector(t_xpos, t_ypos, 0))

    # Linear dimension
    _msg(16 * "-")
    _msg("Linear dimension")
    line = Draft.make_wire([Vector(8700, 200, 0), Vector(8700, 1200, 0)])

    dimension = Draft.make_linear_dimension(Vector(8600, 200, 0),
                                            Vector(8600, 1000, 0),
                                            Vector(8400, 750, 0))
    if App.GuiUp:
        dimension.ViewObject.ArrowSize = 15
        dimension.ViewObject.ExtLines = 1000
        dimension.ViewObject.ExtOvershoot = 100
        dimension.ViewObject.DimOvershoot = 50
        dimension.ViewObject.FontSize = 100
        dimension.ViewObject.ShowUnit = False
    doc.recompute()

    dim_obj = Draft.make_linear_dimension_obj(line, 1, 2, Vector(9000, 750, 0))
    if App.GuiUp:
        dim_obj.ViewObject.ArrowSize = 15
        dim_obj.ViewObject.ArrowType = "Arrow"
        dim_obj.ViewObject.ExtLines = 100
        dim_obj.ViewObject.ExtOvershoot = 100
        dim_obj.ViewObject.DimOvershoot = 50
        dim_obj.ViewObject.FontSize = 100
        dim_obj.ViewObject.ShowUnit = False

    t_xpos += 680
    _set_text(["Dimension"], Vector(t_xpos, t_ypos, 0))

    # Radius and diameter dimension
    _msg(16 * "-")
    _msg("Radius and diameter dimension")
    arc_h = Draft.make_circle(500, startangle=0, endangle=90)
    arc_h.Placement.Base = Vector(9500, 0, 0)
    doc.recompute()

    dimension_r = Draft.make_radial_dimension_obj(arc_h, 1, "radius",
                                                  Vector(9750, 200, 0))
    if App.GuiUp:
        dimension_r.ViewObject.ArrowSize = 15
        dimension_r.ViewObject.FontSize = 100
        dimension_r.ViewObject.ShowUnit = False

    arc_h2 = Draft.make_circle(450, startangle=-120, endangle=80)
    arc_h2.Placement.Base = Vector(10000, 1000, 0)
    doc.recompute()

    dimension_d = Draft.make_radial_dimension_obj(arc_h2, 1, "diameter",
                                                  Vector(10750, 900, 0))
    if App.GuiUp:
        dimension_d.ViewObject.ArrowSize = 15
        dimension_d.ViewObject.FontSize = 100
        dimension_d.ViewObject.ShowUnit = False
    t_xpos += 950
    _set_text(["Radius dimension", "Diameter dimension"],
              Vector(t_xpos, t_ypos, 0))

    # Angular dimension
    _msg(16 * "-")
    _msg("Angular dimension")
    Draft.make_line(Vector(10500, 300, 0), Vector(11500, 1000, 0))
    Draft.make_line(Vector(10500, 300, 0), Vector(11500, 0, 0))
    angle1 = -20
    angle2 = 40
    dimension_a = Draft.make_angular_dimension(Vector(10500, 300, 0),
                                               [angle1, angle2],
                                               Vector(11500, 300, 0))
    if App.GuiUp:
        dimension_a.ViewObject.ArrowSize = 15
        dimension_a.ViewObject.FontSize = 100
    t_xpos += 1700
    _set_text(["Angle dimension"], Vector(t_xpos, t_ypos, 0))

    # BSpline
    _msg(16 * "-")
    _msg("BSpline")
    Draft.make_bspline([
        Vector(12500, 0, 0),
        Vector(12500, 500, 0),
        Vector(13000, 500, 0),
        Vector(13000, 1000, 0)
    ])
    t_xpos += 1500
    _set_text(["BSpline"], Vector(t_xpos, t_ypos, 0))

    # Point
    _msg(16 * "-")
    _msg("Point")
    point = Draft.make_point(13500, 500, 0)
    if App.GuiUp:
        point.ViewObject.PointSize = 10
    t_xpos += 900
    _set_text(["Point"], Vector(t_xpos, t_ypos, 0))

    # Shapestring
    _msg(16 * "-")
    _msg("Shapestring")
    try:
        shape_string = Draft.make_shapestring("Testing", font_file, 100)
        shape_string.Placement.Base = Vector(14000, 500)
    except Exception:
        _wrn("Shapestring could not be created")
        _wrn("Possible cause: the font file may not exist")
        _wrn(font_file)
        rect = Draft.make_rectangle(500, 100)
        rect.Placement.Base = Vector(14000, 500)
    t_xpos += 600
    _set_text(["Shapestring"], Vector(t_xpos, t_ypos, 0))

    # Facebinder
    _msg(16 * "-")
    _msg("Facebinder")
    box = doc.addObject("Part::Box", "Cube")
    box.Length = 200
    box.Width = 500
    box.Height = 100
    box.Placement.Base = Vector(15000, 0, 0)
    if App.GuiUp:
        box.ViewObject.Visibility = False

    facebinder = Draft.make_facebinder([(box, ("Face1", "Face3", "Face6"))])
    facebinder.Extrusion = 10
    t_xpos += 780
    _set_text(["Facebinder"], Vector(t_xpos, t_ypos, 0))

    # Cubic bezier curve, n-degree bezier curve
    _msg(16 * "-")
    _msg("Cubic bezier")
    Draft.make_bezcurve([
        Vector(15500, 0, 0),
        Vector(15578, 485, 0),
        Vector(15879, 154, 0),
        Vector(15975, 400, 0),
        Vector(16070, 668, 0),
        Vector(16423, 925, 0),
        Vector(16500, 500, 0)
    ],
                        degree=3)
    t_xpos += 680
    _set_text(["Cubic bezier"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("N-degree bezier")
    Draft.make_bezcurve([
        Vector(16500, 0, 0),
        Vector(17000, 500, 0),
        Vector(17500, 500, 0),
        Vector(17500, 1000, 0),
        Vector(17000, 1000, 0),
        Vector(17063, 1256, 0),
        Vector(17732, 1227, 0),
        Vector(17790, 720, 0),
        Vector(17702, 242, 0)
    ])
    t_xpos += 1200
    _set_text(["n-Bezier"], Vector(t_xpos, t_ypos, 0))

    # Label
    _msg(16 * "-")
    _msg("Label")
    place = App.Placement(Vector(18500, 500, 0), App.Rotation())
    label = Draft.make_label(target_point=Vector(18000, 0, 0),
                             placement=place,
                             custom_text="Example label",
                             distance=-250)
    label.Text = "Testing"
    if App.GuiUp:
        label.ViewObject.ArrowSize = 15
        label.ViewObject.TextSize = 100
    doc.recompute()
    t_xpos += 1200
    _set_text(["Label"], Vector(t_xpos, t_ypos, 0))

    # Orthogonal array and orthogonal link array
    _msg(16 * "-")
    _msg("Orthogonal array")
    rect_h = Draft.make_rectangle(500, 500)
    rect_h.Placement.Base = Vector(1500, 2500, 0)
    if App.GuiUp:
        rect_h.ViewObject.Visibility = False

    Draft.make_ortho_array(rect_h,
                           Vector(600, 0, 0),
                           Vector(0, 600, 0),
                           Vector(0, 0, 0),
                           3,
                           2,
                           1,
                           use_link=False)
    t_xpos = 1700
    t_ypos = 2200
    _set_text(["Array"], Vector(t_xpos, t_ypos, 0))

    rect_h_2 = Draft.make_rectangle(500, 100)
    rect_h_2.Placement.Base = Vector(1500, 5000, 0)
    if App.GuiUp:
        rect_h_2.ViewObject.Visibility = False

    _msg(16 * "-")
    _msg("Orthogonal link array")
    Draft.make_ortho_array(rect_h_2,
                           Vector(800, 0, 0),
                           Vector(0, 500, 0),
                           Vector(0, 0, 0),
                           2,
                           4,
                           1,
                           use_link=True)
    t_ypos += 2600
    _set_text(["Link array"], Vector(t_xpos, t_ypos, 0))

    # Polar array and polar link array
    _msg(16 * "-")
    _msg("Polar array")
    wire_h = Draft.make_wire([
        Vector(5500, 3000, 0),
        Vector(6000, 3500, 0),
        Vector(6000, 3200, 0),
        Vector(5800, 3200, 0)
    ])
    if App.GuiUp:
        wire_h.ViewObject.Visibility = False

    Draft.make_polar_array(wire_h,
                           8,
                           200,
                           Vector(5000, 3000, 0),
                           use_link=False)

    t_xpos = 4600
    t_ypos = 2200
    _set_text(["Polar array"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Polar link array")
    wire_h_2 = Draft.make_wire([
        Vector(5500, 6000, 0),
        Vector(6000, 6000, 0),
        Vector(5800, 5700, 0),
        Vector(5800, 5750, 0)
    ])
    if App.GuiUp:
        wire_h_2.ViewObject.Visibility = False

    Draft.make_polar_array(wire_h_2,
                           8,
                           200,
                           Vector(5000, 6000, 0),
                           use_link=True)
    t_ypos += 3200
    _set_text(["Polar link array"], Vector(t_xpos, t_ypos, 0))

    # Circular array and circular link array
    _msg(16 * "-")
    _msg("Circular array")
    poly_h = Draft.make_polygon(5, 200)
    poly_h.Placement.Base = Vector(8000, 3000, 0)
    if App.GuiUp:
        poly_h.ViewObject.Visibility = False

    Draft.make_circular_array(poly_h,
                              500,
                              600,
                              3,
                              1,
                              Vector(0, 0, 1),
                              Vector(0, 0, 0),
                              use_link=False)
    t_xpos = 7700
    t_ypos = 1700
    _set_text(["Circular array"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Circular link array")
    poly_h_2 = Draft.make_polygon(6, 150)
    poly_h_2.Placement.Base = Vector(8000, 6250, 0)
    if App.GuiUp:
        poly_h_2.ViewObject.Visibility = False

    Draft.make_circular_array(poly_h_2,
                              550,
                              450,
                              3,
                              1,
                              Vector(0, 0, 1),
                              Vector(0, 0, 0),
                              use_link=True)
    t_ypos += 3100
    _set_text(["Circular link array"], Vector(t_xpos, t_ypos, 0))

    # Path array and path link array
    _msg(16 * "-")
    _msg("Path array")
    poly_h = Draft.make_polygon(3, 250)
    poly_h.Placement.Base = Vector(10000, 3000, 0)
    if App.GuiUp:
        poly_h.ViewObject.Visibility = False

    bspline_path = Draft.make_bspline([
        Vector(10500, 2500, 0),
        Vector(11000, 3000, 0),
        Vector(11500, 3200, 0),
        Vector(12000, 4000, 0)
    ])

    Draft.make_path_array(poly_h, bspline_path, 5, use_link=False)
    t_xpos = 10400
    t_ypos = 2200
    _set_text(["Path array"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Path link array")
    poly_h_2 = Draft.make_polygon(4, 200)
    poly_h_2.Placement.Base = Vector(10000, 5000, 0)
    if App.GuiUp:
        poly_h_2.ViewObject.Visibility = False

    bspline_path_2 = Draft.make_bspline([
        Vector(10500, 4500, 0),
        Vector(11000, 6800, 0),
        Vector(11500, 6000, 0),
        Vector(12000, 5200, 0)
    ])

    Draft.make_path_array(poly_h_2, bspline_path_2, 6, use_link=True)
    t_ypos += 2000
    _set_text(["Path link array"], Vector(t_xpos, t_ypos, 0))

    # Point array
    _msg(16 * "-")
    _msg("Point array")
    poly_h = Draft.make_polygon(3, 250)
    poly_h.Placement.Base = Vector(12500, 2500, 0)

    point_1 = Draft.make_point(13000, 3000, 0)
    point_2 = Draft.make_point(13000, 3500, 0)
    point_3 = Draft.make_point(14000, 2500, 0)
    point_4 = Draft.make_point(14000, 3000, 0)

    add_list, delete_list = Draft.upgrade([point_1, point_2, point_3, point_4])
    compound = add_list[0]
    if App.GuiUp:
        compound.ViewObject.PointSize = 5

    Draft.make_point_array(poly_h, compound)
    t_xpos = 13000
    t_ypos = 2200
    _set_text(["Point array"], Vector(t_xpos, t_ypos, 0))

    # Clone and mirror
    _msg(16 * "-")
    _msg("Clone")
    wire_h = Draft.make_wire([
        Vector(15000, 2500, 0),
        Vector(15200, 3000, 0),
        Vector(15500, 2500, 0),
        Vector(15200, 2300, 0)
    ])

    Draft.make_clone(wire_h, Vector(0, 1000, 0))
    t_xpos = 15000
    t_ypos = 2100
    _set_text(["Clone"], Vector(t_xpos, t_ypos, 0))

    _msg(16 * "-")
    _msg("Mirror")
    wire_h = Draft.make_wire([
        Vector(17000, 2500, 0),
        Vector(16500, 4000, 0),
        Vector(16000, 2700, 0),
        Vector(16500, 2500, 0),
        Vector(16700, 2700, 0)
    ])

    Draft.mirror(wire_h, Vector(17100, 2000, 0), Vector(17100, 4000, 0))
    t_xpos = 17000
    t_ypos = 2200
    _set_text(["Mirror"], Vector(t_xpos, t_ypos, 0))
    doc.recompute()
Beispiel #14
0
    def onBeforeChange(self, obj, prop):

        if prop == "Placement":
            self.oldPlacement = FreeCAD.Placement(obj.Placement)
Beispiel #15
0
    def execute(self, obj):
        "creates the panel shape"

        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        # base tests
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if not obj.Base.Mesh.isSolid():
                    return
        else:
            if obj.Length.Value:
                length = obj.Length.Value
            else:
                return
            if obj.Width.Value:
                width = obj.Width.Value
            else:
                return
        if obj.Thickness.Value:
            thickness = obj.Thickness.Value
        else:
            if not obj.Base:
                return
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if not obj.Base.Shape.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        baseprofile = None
        if obj.Base:
            base = obj.Base.Shape.copy()
            if not base.Solids:
                p = FreeCAD.Placement(obj.Base.Placement)
                if base.Faces:
                    baseprofile = base
                    normal = baseprofile.Faces[0].normalAt(
                        0, 0).multiply(thickness)
                    base = base.extrude(normal)
                elif base.Wires:
                    closed = True
                    for w in base.Wires:
                        if not w.isClosed():
                            closed = False
                    if closed:
                        baseprofile = ArchCommands.makeFace(base.Wires)
                        normal = baseprofile.normalAt(0, 0).multiply(thickness)
                        base = baseprofile.extrude(normal)
                elif obj.Base.isDerivedFrom("Mesh::Feature"):
                    if obj.Base.Mesh.isSolid():
                        if obj.Base.Mesh.countComponents() == 1:
                            sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                            if sh.isClosed() and sh.isValid() and sh.Solids:
                                base = sh
        else:
            normal = Vector(0, 0, 1).multiply(thickness)
            l2 = length / 2 or 0.5
            w2 = width / 2 or 0.5
            v1 = Vector(-l2, -w2, 0)
            v2 = Vector(l2, -w2, 0)
            v3 = Vector(l2, w2, 0)
            v4 = Vector(-l2, w2, 0)
            base = Part.makePolygon([v1, v2, v3, v4, v1])
            baseprofile = Part.Face(base)
            base = baseprofile.extrude(normal)

        if hasattr(obj, "Area"):
            if baseprofile:
                obj.Area = baseprofile.Area

        if hasattr(obj, "WaveLength"):
            if baseprofile and obj.WaveLength.Value and obj.WaveHeight.Value:
                # corrugated element
                bb = baseprofile.BoundBox
                bb.enlarge(bb.DiagonalLength)
                p1 = Vector(bb.getPoint(0).x, bb.getPoint(0).y, bb.Center.z)
                if obj.WaveType == "Curved":
                    p2 = p1.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    p3 = p2.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    e1 = Part.Arc(p1, p2, p3).toShape()
                    p4 = p3.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               -obj.WaveHeight.Value))
                    p5 = p4.add(
                        Vector(obj.WaveLength.Value / 2, 0,
                               obj.WaveHeight.Value))
                    e2 = Part.Arc(p3, p4, p5).toShape()
                else:
                    if obj.WaveHeight.Value < obj.WaveLength.Value:
                        p2 = p1.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p4 = p3.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3, p4])
                        p5 = p4.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   -obj.WaveHeight.Value))
                        p6 = p5.add(
                            Vector(
                                obj.WaveLength.Value -
                                2 * obj.WaveHeight.Value, 0, 0))
                        p7 = p6.add(
                            Vector(obj.WaveHeight.Value, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p4, p5, p6, p7])
                    else:
                        p2 = p1.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        p3 = p2.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        e1 = Part.makePolygon([p1, p2, p3])
                        p4 = p3.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   -obj.WaveHeight.Value))
                        p5 = p4.add(
                            Vector(obj.WaveLength.Value / 2, 0,
                                   obj.WaveHeight.Value))
                        e2 = Part.makePolygon([p3, p4, p5])
                edges = [e1, e2]
                for i in range(int(bb.XLength / (obj.WaveLength.Value * 2))):
                    e1 = e1.copy()
                    e1.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    e2 = e2.copy()
                    e2.translate(Vector(obj.WaveLength.Value * 2, 0, 0))
                    edges.extend([e1, e2])
                basewire = Part.Wire(edges)
                baseface = basewire.extrude(Vector(0, bb.YLength, 0))
                base = baseface.extrude(Vector(0, 0, thickness))
                rot = FreeCAD.Rotation(FreeCAD.Vector(0, 0, 1), normal)
                base.rotate(bb.Center, rot.Axis, math.degrees(rot.Angle))
                if obj.WaveDirection.Value:
                    base.rotate(bb.Center, normal, obj.WaveDirection.Value)
                n1 = normal.negative().normalize().multiply(
                    obj.WaveHeight.Value * 2)
                self.vol = baseprofile.copy()
                self.vol.translate(n1)
                self.vol = self.vol.extrude(n1.negative().multiply(2))
                base = self.vol.common(base)
                base = base.removeSplitter()
                if not base:
                    FreeCAD.Console.PrintError(
                        transpate("Arch", "Error computing shape of ") +
                        obj.Label + "\n")
                    return False

        if base and (obj.Sheets > 1) and normal and thickness:
            bases = [base]
            for i in range(1, obj.Sheets):
                n = FreeCAD.Vector(normal).normalize().multiply(i * thickness)
                b = base.copy()
                b.translate(n)
                bases.append(b)
            base = Part.makeCompound(bases)

        if base and normal and hasattr(obj, "Offset"):
            if obj.Offset.Value:
                v = DraftVecUtils.scaleTo(normal, obj.Offset.Value)
                base.translate(v)

        # process subshapes
        base = self.processSubShapes(obj, base, pl)

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(
                            translate("Arch", "Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Beispiel #16
0
 def onChanged(self, vobj, prop):
     if prop == "LineColor":
         l = vobj.LineColor
         self.mat1.diffuseColor.setValue([l[0], l[1], l[2]])
         self.mat2.diffuseColor.setValue([l[0], l[1], l[2]])
     elif prop == "Transparency":
         if hasattr(vobj, "Transparency"):
             self.mat2.transparency.setValue(vobj.Transparency / 100.0)
     elif prop in ["DisplayLength", "DisplayHeight", "ArrowSize"]:
         if hasattr(vobj, "DisplayLength"):
             ld = vobj.DisplayLength.Value / 2
             hd = vobj.DisplayHeight.Value / 2
         elif hasattr(vobj, "DisplaySize"):
             # old objects
             ld = vobj.DisplaySize.Value / 2
             hd = vobj.DisplaySize.Value / 2
         else:
             ld = 1
             hd = 1
         verts = []
         fverts = []
         for v in [[-ld, -hd], [ld, -hd], [ld, hd], [-ld, hd]]:
             if hasattr(vobj, "ArrowSize"):
                 l1 = vobj.ArrowSize.Value if vobj.ArrowSize.Value > 0 else 0.1
             else:
                 l1 = 0.1
             l2 = l1 / 3
             pl = FreeCAD.Placement(vobj.Object.Placement)
             p1 = pl.multVec(Vector(v[0], v[1], 0))
             p2 = pl.multVec(Vector(v[0], v[1], -l1))
             p3 = pl.multVec(Vector(v[0] - l2, v[1], -l1 + l2))
             p4 = pl.multVec(Vector(v[0] + l2, v[1], -l1 + l2))
             p5 = pl.multVec(Vector(v[0], v[1] - l2, -l1 + l2))
             p6 = pl.multVec(Vector(v[0], v[1] + l2, -l1 + l2))
             verts.extend([[p1.x, p1.y, p1.z], [p2.x, p2.y, p2.z]])
             fverts.append([p1.x, p1.y, p1.z])
             verts.extend([[p2.x, p2.y, p2.z], [p3.x, p3.y, p3.z],
                           [p4.x, p4.y, p4.z], [p2.x, p2.y, p2.z]])
             verts.extend([[p2.x, p2.y, p2.z], [p5.x, p5.y, p5.z],
                           [p6.x, p6.y, p6.z], [p2.x, p2.y, p2.z]])
         verts.extend(fverts + [fverts[0]])
         self.lcoords.point.setValues(verts)
         self.fcoords.point.setValues(fverts)
     elif prop == "LineWidth":
         self.drawstyle.lineWidth = vobj.LineWidth
     elif prop == "CutView":
         if hasattr(vobj,
                    "CutView") and FreeCADGui.ActiveDocument.ActiveView:
             sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
             if vobj.CutView:
                 if self.clip:
                     sg.removeChild(self.clip)
                     self.clip = None
                 for o in Draft.getGroupContents(vobj.Object.Objects,
                                                 walls=True):
                     if hasattr(o.ViewObject, "Lighting"):
                         o.ViewObject.Lighting = "One side"
                 self.clip = coin.SoClipPlane()
                 self.clip.on.setValue(True)
                 norm = vobj.Object.Proxy.getNormal(vobj.Object)
                 mp = vobj.Object.Shape.CenterOfMass
                 mp = DraftVecUtils.project(mp, norm)
                 dist = mp.Length  #- 0.1 # to not clip exactly on the section object
                 norm = norm.negative()
                 if mp.getAngle(norm) > 1:
                     dist += 1
                     dist = -dist
                 else:
                     dist -= 0.1
                 plane = coin.SbPlane(coin.SbVec3f(norm.x, norm.y, norm.z),
                                      dist)
                 self.clip.plane.setValue(plane)
                 sg.insertChild(self.clip, 0)
             else:
                 if self.clip:
                     sg.removeChild(self.clip)
                     self.clip = None
     return
Beispiel #17
0
def make_text(string, placement=None, screen=False):
    """Create a Text object containing the given list of strings.

    The current color and text height and font specified in preferences
    are used.

    Parameters
    ----------
    string: str, or list of str
        String to display on screen.
        If it is a list, each element in the list represents a new text line.

    placement: Base::Placement, Base::Vector3, or Base::Rotation, optional
        It defaults to `None`.
        If it is provided, it is the placement of the new text.
        The input could be a full placement, just a vector indicating
        the translation, or just a rotation.

    screen: bool, optional
        It defaults to `False`, in which case the text is placed in 3D space
        oriented like any other object, on top of a given plane,
        by the default the XY plane.
        If it is `True`, the text will always face perpendicularly
        to the camera direction, that is, it will be flat on the screen.

    Returns
    -------
    App::FeaturePython
        A scripted object of type `'Text'`.
        This object does not have a `Shape` attribute, as the text is created
        on screen by Coin (pivy).

    None
        If there is a problem it will return `None`.
    """
    _name = "make_text"
    utils.print_header(_name, "Text")

    found, doc = utils.find_doc(App.activeDocument())
    if not found:
        _err(translate("draft", "No active document. Aborting."))
        return None

    _msg("string: {}".format(string))
    try:
        utils.type_check([(string, (str, list))], name=_name)
    except TypeError:
        _err(
            translate(
                "draft",
                "Wrong input: must be a list of strings or a single string."))
        return None

    if (type(string) is list
            and not all(isinstance(element, str) for element in string)):
        _err(
            translate(
                "draft",
                "Wrong input: must be a list of strings or a single string."))
        return None

    _msg("placement: {}".format(placement))
    if not placement:
        placement = App.Placement()
    try:
        utils.type_check([(placement,
                           (App.Placement, App.Vector, App.Rotation))],
                         name=_name)
    except TypeError:
        _err(
            translate(
                "draft",
                "Wrong input: must be a placement, a vector, or a rotation."))
        return None

    # Convert the vector or rotation to a full placement
    if isinstance(placement, App.Vector):
        placement = App.Placement(placement, App.Rotation())
    elif isinstance(placement, App.Rotation):
        placement = App.Placement(App.Vector(), placement)

    new_obj = doc.addObject("App::FeaturePython", "Text")
    Text(new_obj)
    new_obj.Text = string
    new_obj.Placement = placement

    if App.GuiUp:
        ViewProviderText(new_obj.ViewObject)

        h = utils.get_param("textheight", 2)

        new_obj.ViewObject.DisplayMode = "3D text"
        if screen:
            _msg("screen: {}".format(screen))
            new_obj.ViewObject.DisplayMode = "2D text"
            h = h * 10

        new_obj.ViewObject.FontSize = h
        new_obj.ViewObject.FontName = utils.get_param("textfont", "")
        new_obj.ViewObject.LineSpacing = 1

        gui_utils.format_object(new_obj)
        gui_utils.select(new_obj)

    return new_obj
Beispiel #18
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
Beispiel #19
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
Beispiel #20
0
    def processSubShapes(self, obj, base, placement=None):
        "Adds additions and subtractions to a base shape"
        import Draft, Part
        #print("Processing subshapes of ",obj.Label, " : ",obj.Additions)

        if placement:
            if placement.isNull():
                placement = None
            else:
                placement = FreeCAD.Placement(placement)
                placement = placement.inverse()

        # treat additions
        for o in obj.Additions:

            if not base:
                if o.isDerivedFrom("Part::Feature"):
                    base = o.Shape
            else:
                if base.isNull():
                    if o.isDerivedFrom("Part::Feature"):
                        base = o.Shape
                else:
                    # special case, both walls with coinciding endpoints
                    import ArchWall
                    js = ArchWall.mergeShapes(o, obj)
                    if js:
                        add = js.cut(base)
                        if placement:
                            add.Placement = add.Placement.multiply(placement)
                        base = base.fuse(add)

                    elif (Draft.getType(o) == "Window") or (Draft.isClone(
                            o, "Window", True)):
                        if hasattr(o.Proxy, "getSubVolume"):
                            f = o.Proxy.getSubVolume(o)
                            if f:
                                if base.Solids and f.Solids:
                                    if placement:
                                        f.Placement = f.Placement.multiply(
                                            placement)
                                    base = base.cut(f)

                    elif o.isDerivedFrom("Part::Feature"):
                        if o.Shape:
                            if not o.Shape.isNull():
                                if o.Shape.Solids:
                                    s = o.Shape.copy()
                                    if placement:
                                        s.Placement = s.Placement.multiply(
                                            placement)
                                    if base:
                                        if base.Solids:
                                            try:
                                                base = base.fuse(s)
                                            except Part.OCCError:
                                                print(
                                                    "Arch: unable to fuse object ",
                                                    obj.Name, " with ", o.Name)
                                    else:
                                        base = s

        # treat subtractions
        for o in obj.Subtractions:

            if base:
                if base.isNull():
                    base = None

            if base:
                if (Draft.getType(o) == "Window") or (Draft.isClone(
                        o, "Window", True)):
                    # windows can be additions or subtractions, treated the same way
                    f = o.Proxy.getSubVolume(o)
                    if f:
                        if base.Solids and f.Solids:
                            if placement:
                                f.Placement = f.Placement.multiply(placement)
                            base = base.cut(f)

                elif (Draft.getType(o) == "Roof") or (Draft.isClone(o,
                                                                    "Roof")):
                    # roofs define their own special subtraction volume
                    f = o.Proxy.getSubVolume(o)
                    if f:
                        if base.Solids and f.Solids:
                            base = base.cut(f)

                elif o.isDerivedFrom("Part::Feature"):
                    if o.Shape:
                        if not o.Shape.isNull():
                            if o.Shape.Solids and base.Solids:
                                s = o.Shape.copy()
                                if placement:
                                    s.Placement = s.Placement.multiply(
                                        placement)
                                try:
                                    base = base.cut(s)
                                except Part.OCCError:
                                    print("Arch: unable to cut object ",
                                          o.Name, " from ", obj.Name)
        return base
    def loadStockSettings(self):
        stock = PathPreferences.defaultStockTemplate()
        index = -1
        if stock:
            attrs = json.loads(stock)
            if attrs.get('version') and 1 == int(attrs['version']):
                stockType = attrs.get('create')
                if stockType == PathStock.StockType.FromBase:
                    index = 2
                elif stockType == PathStock.StockType.CreateBox:
                    index = 0
                elif stockType == PathStock.StockType.CreateCylinder:
                    index = 1
                else:
                    index = -1
        if -1 == index:
            attrs = {}
            self.form.stockGroup.setChecked(False)
        else:
            self.form.stockGroup.setChecked(True)
            self.form.stock.setCurrentIndex(index)

        # this either sets the default value or the value from the template for each field
        self.form.stockExtXneg.setText(attrs.get('xneg', '1 mm'))
        self.form.stockExtXpos.setText(attrs.get('xpos', '1 mm'))
        self.form.stockExtYneg.setText(attrs.get('yneg', '1 mm'))
        self.form.stockExtYpos.setText(attrs.get('ypos', '1 mm'))
        self.form.stockExtZneg.setText(attrs.get('zneg', '1 mm'))
        self.form.stockExtZpos.setText(attrs.get('zpos', '1 mm'))
        self.form.stockBoxLength.setText(attrs.get('length', '10 mm'))
        self.form.stockBoxWidth.setText(attrs.get('width', '10 mm'))
        self.form.stockBoxHeight.setText(attrs.get('height', '10 mm'))
        self.form.stockCylinderRadius.setText(attrs.get('radius', '5 mm'))
        self.form.stockCylinderHeight.setText(attrs.get('height', '10 mm'))

        posX = attrs.get('posX')
        posY = attrs.get('posY')
        posZ = attrs.get('posZ')
        rotX = attrs.get('rotX')
        rotY = attrs.get('rotY')
        rotZ = attrs.get('rotZ')
        rotW = attrs.get('rotW')
        if posX is not None and posY is not None and posZ is not None and rotX is not None and rotY is not None and rotZ is not None and rotW is not None:
            pos = FreeCAD.Vector(float(posX), float(posY), float(posZ))
            rot = FreeCAD.Rotation(float(rotX), float(rotY), float(rotZ),
                                   float(rotW))
            placement = FreeCAD.Placement(pos, rot)
            self.form.stockPlacementGroup.setChecked(True)
        else:
            placement = FreeCAD.Placement()
            self.form.stockPlacementGroup.setChecked(False)

        self.form.stockAngle.setText(
            FreeCAD.Units.Quantity("%f rad" %
                                   placement.Rotation.Angle).UserString)
        self.form.stockAxisX.setValue(placement.Rotation.Axis.x)
        self.form.stockAxisY.setValue(placement.Rotation.Axis.y)
        self.form.stockAxisZ.setValue(placement.Rotation.Axis.z)
        self.form.stockPositionX.setText(
            FreeCAD.Units.Quantity(placement.Base.x,
                                   FreeCAD.Units.Length).UserString)
        self.form.stockPositionY.setText(
            FreeCAD.Units.Quantity(placement.Base.y,
                                   FreeCAD.Units.Length).UserString)
        self.form.stockPositionZ.setText(
            FreeCAD.Units.Quantity(placement.Base.z,
                                   FreeCAD.Units.Length).UserString)

        self.setupStock(index)
        self.form.stock.currentIndexChanged.connect(self.setupStock)
def platonicsolid(solid='cube',
                  name=None,
                  clearall=False,
                  vertexpolygon=False,
                  cloud=False,
                  solidoutline=False,
                  solidobject=True,
                  outerradius=None,
                  edgelength=None):
    platonic_solid = platonic_solids[solid]

    if name == None:
        name = solid

    doc = FreeCAD.activeDocument()

    if clearall:
        clearobjects(doc)

    #print(doc.supportedTypes())
    radius = platonic_solid['radius']

    if outerradius:
        factor = outerradius / radius
        print(f"Outerradius: {outerradius}")
    elif edgelength:
        factor = edgelength / platonic_solid['edgelength']

    print(f"Factor: {factor} = {factor/platonic_solid['radius']} * R")
    print(f"Edge length: {platonic_solid['edgelength']}")
    if vertexpolygon:
        p = Part.makePolygon(
            [normalize(x, factor) for x in platonic_solid['vertices']])
        solidwire(doc,
                  p,
                  name=f"{name}_vertices",
                  radius=factor * platonic_solid['edgelength'] / 20)

    platonic_solid['edges'] = []
    if cloud:
        spheres = []
        for i, vertex in enumerate(platonic_solid['vertices']):
            s = doc.addObject("Part::Sphere", f"{name}_sphere{i}")
            s.Radius = 0.2
            p = FreeCAD.Placement()
            p.Base = FreeCAD.Vector(
                normalize((vertex[0], vertex[1], vertex[2]), factor))
            s.Placement = p
            s.Visibility = False
            spheres.append(s)

        spherefusion = doc.addObject("Part::MultiFuse", f"{name}_cloud")
        spherefusion.Shapes = spheres

    facelist = []
    solidfaces = []
    for i, face in enumerate(platonic_solid['faces']):
        edgelist = []
        verts = platonic_solid['vertices']
        prev = None
        for v in face:
            if prev is not None:
                edge = Part.makeLine(normalize(verts[prev], factor),
                                     normalize(verts[v], factor))
                edgelist.append(edge)
            prev = v
        edge = Part.makeLine(normalize(verts[prev], factor),
                             normalize(verts[face[0]], factor))
        edgelist.append(edge)
        wire = Part.Wire(edgelist)
        if solidoutline:
            solidfaces.append(
                solidwire(doc,
                          wire,
                          f"{name}_face{i}",
                          radius=factor * platonic_solid['edgelength'] / 20))
        face = Part.Face(wire)
        facelist.append(face)

    if solidoutline:
        solidfacefusion = doc.addObject("Part::MultiFuse",
                                        f"{name}_solidfaces")
        solidfacefusion.Shapes = solidfaces

    if solidobject:
        shell = Part.makeShell(facelist)
        solid = doc.addObject("Part::Feature", name)
        solid.Shape = Part.makeSolid(shell)
Beispiel #23
0
 def Activated(self):
     import expandplacements
     for selobj in FreeCADGui.Selection.getSelectionEx():
         expandplacements.expandplacements(selobj.Object,
                                           FreeCAD.Placement())
     FreeCAD.ActiveDocument.recompute()
Beispiel #24
0
    def execute(self,obj):
        "creates the panel shape"
        
        if self.clone(obj):
            return

        import Part, DraftGeomUtils

        # base tests
        if obj.Base:
            if obj.Base.isDerivedFrom("Part::Feature"):
                if obj.Base.Shape.isNull():
                    return
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if not obj.Base.Mesh.isSolid():
                    return
        else:
            if obj.Length.Value:
                length = obj.Length.Value
            else:
                return
            if obj.Width.Value:
                width = obj.Width.Value
            else:
                return
        if obj.Thickness.Value:
            thickness = obj.Thickness.Value
        else:
            if not obj.Base:
                return
            elif obj.Base.isDerivedFrom("Part::Feature"):
                if not obj.Base.Solids:
                    return

        # creating base shape
        pl = obj.Placement
        base = None
        normal = None
        if obj.Base:
            p = FreeCAD.Placement(obj.Base.Placement)
            normal = p.Rotation.multVec(Vector(0,0,1))
            normal = normal.multiply(thickness)
            base = obj.Base.Shape.copy()
            if base.Solids:
                pass
            elif base.Faces:
                self.BaseProfile = base
                self.ExtrusionVector = normal
                base = base.extrude(normal)
            elif base.Wires:
                closed = True
                for w in base.Wires:
                    if not w.isClosed():
                        closed = False
                if closed:
                    base = ArchCommands.makeFace(base.Wires)
                    self.BaseProfile = base
                    self.ExtrusionVector = normal
                    base = base.extrude(normal)
            elif obj.Base.isDerivedFrom("Mesh::Feature"):
                if obj.Base.Mesh.isSolid():
                    if obj.Base.Mesh.countComponents() == 1:
                        sh = ArchCommands.getShapeFromMesh(obj.Base.Mesh)
                        if sh.isClosed() and sh.isValid() and sh.Solids:
                            base = sh
        else:
            normal = Vector(0,0,1).multiply(thickness)
            self.ExtrusionVector = normal
            l2 = length/2 or 0.5
            w2 = width/2 or 0.5
            v1 = Vector(-l2,-w2,0)
            v2 = Vector(l2,-w2,0)
            v3 = Vector(l2,w2,0)
            v4 = Vector(-l2,w2,0)
            base = Part.makePolygon([v1,v2,v3,v4,v1])
            base = Part.Face(base)
            self.BaseProfile = base
            base = base.extrude(self.ExtrusionVector)

        if base and (obj.Sheets > 1) and normal and thickness:
            bases = [base]
            for i in range(1,obj.Sheets):
                n = FreeCAD.Vector(normal).normalize().multiply(i*thickness)
                b = base.copy()
                b.translate(n)
                bases.append(b)
            base = Part.makeCompound(bases)

        if base and normal and hasattr(obj,"Offset"):
            if obj.Offset.Value:
                v = DraftVecUtils.scaleTo(normal,obj.Offset.Value)
                base.translate(v)

        # process subshapes
        base = self.processSubShapes(obj,base,pl)

        # applying
        if base:
            if not base.isNull():
                if base.isValid() and base.Solids:
                    if base.Volume < 0:
                        base.reverse()
                    if base.Volume < 0:
                        FreeCAD.Console.PrintError(translate("Arch","Couldn't compute a shape"))
                        return
                    base = base.removeSplitter()
                    obj.Shape = base
                    if not pl.isNull():
                        obj.Placement = pl
Beispiel #25
0
def center(obj,x,y,z):
    obj.Placement = FreeCAD.Placement(\
        FreeCAD.Vector(-x/2.0,-y/2.0,-z/2.0),\
        FreeCAD.Rotation(0,0,0,1))
 def getRotation(self):
     "returns a placement describing the working plane orientation ONLY"
     m = DraftVecUtils.getPlaneRotation(self.u, self.v, self.axis)
     return FreeCAD.Placement(m)
Beispiel #27
0
    def updateData(self, obj, prop):
        """called when the base object is changed"""
        import DraftGui
        if prop in ["Start","End","Dimline","Direction"]:

            if obj.Start == obj.End:
                return

            if not hasattr(self,"node"):
                return

            import Part, DraftGeomUtils
            from pivy import coin

            # calculate the 4 points
            self.p1 = obj.Start
            self.p4 = obj.End
            base = None
            if hasattr(obj,"Direction"):
                if not DraftVecUtils.isNull(obj.Direction):
                    v2 = self.p1.sub(obj.Dimline)
                    v3 = self.p4.sub(obj.Dimline)
                    v2 = DraftVecUtils.project(v2,obj.Direction)
                    v3 = DraftVecUtils.project(v3,obj.Direction)
                    self.p2 = obj.Dimline.add(v2)
                    self.p3 = obj.Dimline.add(v3)
                    if DraftVecUtils.equals(self.p2,self.p3):
                        base = None
                        proj = None
                    else:
                        base = Part.LineSegment(self.p2,self.p3).toShape()
                        proj = DraftGeomUtils.findDistance(self.p1,base)
                        if proj:
                            proj = proj.negative()
            if not base:
                if DraftVecUtils.equals(self.p1,self.p4):
                    base = None
                    proj = None
                else:
                    base = Part.LineSegment(self.p1,self.p4).toShape()
                    proj = DraftGeomUtils.findDistance(obj.Dimline,base)
                if proj:
                    self.p2 = self.p1.add(proj.negative())
                    self.p3 = self.p4.add(proj.negative())
                else:
                    self.p2 = self.p1
                    self.p3 = self.p4
            if proj:
                if hasattr(obj.ViewObject,"ExtLines") and hasattr(obj.ViewObject,"ScaleMultiplier"):
                    dmax = obj.ViewObject.ExtLines.Value * obj.ViewObject.ScaleMultiplier
                    if dmax and (proj.Length > dmax):
                        if (dmax > 0):
                            self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,dmax))
                            self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,dmax))
                        else:
                            rest = proj.Length + dmax
                            self.p1 = self.p2.add(DraftVecUtils.scaleTo(proj,rest))
                            self.p4 = self.p3.add(DraftVecUtils.scaleTo(proj,rest))
            else:
                proj = (self.p3.sub(self.p2)).cross(App.Vector(0,0,1))

            # calculate the arrows positions
            self.trans1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.coord1.point.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.trans2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
            self.coord2.point.setValue((self.p3.x,self.p3.y,self.p3.z))

            # calculate dimension and extension lines overshoots positions
            self.transDimOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.transDimOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))
            self.transExtOvershoot1.translation.setValue((self.p2.x,self.p2.y,self.p2.z))
            self.transExtOvershoot2.translation.setValue((self.p3.x,self.p3.y,self.p3.z))

            # calculate the text position and orientation
            if hasattr(obj,"Normal"):
                if DraftVecUtils.isNull(obj.Normal):
                    if proj:
                        norm = (self.p3.sub(self.p2).cross(proj)).negative()
                    else:
                        norm = App.Vector(0,0,1)
                else:
                    norm = App.Vector(obj.Normal)
            else:
                if proj:
                    norm = (self.p3.sub(self.p2).cross(proj)).negative()
                else:
                    norm = App.Vector(0,0,1)
            if not DraftVecUtils.isNull(norm):
                norm.normalize()
            u = self.p3.sub(self.p2)
            u.normalize()
            v1 = norm.cross(u)
            rot1 = App.Placement(DraftVecUtils.getPlaneRotation(u,v1,norm)).Rotation.Q
            self.transDimOvershoot1.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
            self.transDimOvershoot2.rotation.setValue((rot1[0],rot1[1],rot1[2],rot1[3]))
            if hasattr(obj.ViewObject,"FlipArrows"):
                if obj.ViewObject.FlipArrows:
                    u = u.negative()
            v2 = norm.cross(u)
            rot2 = App.Placement(DraftVecUtils.getPlaneRotation(u,v2,norm)).Rotation.Q
            self.trans1.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
            self.trans2.rotation.setValue((rot2[0],rot2[1],rot2[2],rot2[3]))
            if self.p1 != self.p2:
                u3 = self.p1.sub(self.p2)
                u3.normalize()
                v3 = norm.cross(u3)
                rot3 = App.Placement(DraftVecUtils.getPlaneRotation(u3,v3,norm)).Rotation.Q
                self.transExtOvershoot1.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
                self.transExtOvershoot2.rotation.setValue((rot3[0],rot3[1],rot3[2],rot3[3]))
            if hasattr(obj.ViewObject,"TextSpacing") and hasattr(obj.ViewObject,"ScaleMultiplier"):
                ts = obj.ViewObject.TextSpacing.Value * obj.ViewObject.ScaleMultiplier
                offset = DraftVecUtils.scaleTo(v1,ts)
            else:
                offset = DraftVecUtils.scaleTo(v1,0.05)
            rott = rot1
            if hasattr(obj.ViewObject,"FlipText"):
                if obj.ViewObject.FlipText:
                    rott = App.Rotation(*rott).multiply(App.Rotation(norm,180)).Q
                    offset = offset.negative()
            # setting text
            try:
                m = obj.ViewObject.DisplayMode
            except: # swallow all exceptions here since it always fails on first run (Displaymode enum no set yet)
                m = ["2D","3D"][utils.get_param("dimstyle",0)]
            if m == "3D":
                offset = offset.negative()
            self.tbase = (self.p2.add((self.p3.sub(self.p2).multiply(0.5)))).add(offset)
            if hasattr(obj.ViewObject,"TextPosition"):
                if not DraftVecUtils.isNull(obj.ViewObject.TextPosition):
                    self.tbase = obj.ViewObject.TextPosition
            self.textpos.translation.setValue([self.tbase.x,self.tbase.y,self.tbase.z])
            self.textpos.rotation = coin.SbRotation(rott[0],rott[1],rott[2],rott[3])
            su = True
            if hasattr(obj.ViewObject,"ShowUnit"):
                su = obj.ViewObject.ShowUnit
            # set text value
            l = self.p3.sub(self.p2).Length
            unit = None
            if hasattr(obj.ViewObject,"UnitOverride"):
                unit = obj.ViewObject.UnitOverride
            # special representation if "Building US" scheme
            if App.ParamGet("User parameter:BaseApp/Preferences/Units").GetInt("UserSchema",0) == 5:
                s = App.Units.Quantity(l,App.Units.Length).UserString
                self.string = s.replace("' ","'- ")
                self.string = s.replace("+"," ")
            elif hasattr(obj.ViewObject,"Decimals"):
                self.string = DraftGui.displayExternal(l,obj.ViewObject.Decimals,'Length',su,unit)
            else:
                self.string = DraftGui.displayExternal(l,None,'Length',su,unit)
            if hasattr(obj.ViewObject,"Override"):
                if obj.ViewObject.Override:
                    self.string = obj.ViewObject.Override.replace("$dim",\
                            self.string)
            self.text.string = self.text3d.string = utils.string_encode_coin(self.string)

            # set the lines
            if m == "3D":
                # calculate the spacing of the text
                textsize = (len(self.string)*obj.ViewObject.FontSize.Value)/4.0
                spacing = ((self.p3.sub(self.p2)).Length/2.0) - textsize
                self.p2a = self.p2.add(DraftVecUtils.scaleTo(self.p3.sub(self.p2),spacing))
                self.p2b = self.p3.add(DraftVecUtils.scaleTo(self.p2.sub(self.p3),spacing))
                self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
                                             [self.p2.x,self.p2.y,self.p2.z],
                                             [self.p2a.x,self.p2a.y,self.p2a.z],
                                             [self.p2b.x,self.p2b.y,self.p2b.z],
                                             [self.p3.x,self.p3.y,self.p3.z],
                                             [self.p4.x,self.p4.y,self.p4.z]])
                #self.line.numVertices.setValues([3,3])
                self.line.coordIndex.setValues(0,7,(0,1,2,-1,3,4,5))
            else:
                self.coords.point.setValues([[self.p1.x,self.p1.y,self.p1.z],
                                             [self.p2.x,self.p2.y,self.p2.z],
                                             [self.p3.x,self.p3.y,self.p3.z],
                                             [self.p4.x,self.p4.y,self.p4.z]])
                #self.line.numVertices.setValue(4)
                self.line.coordIndex.setValues(0,4,(0,1,2,3))
 def setFromPlacement(self, pl):
     "sets the working plane from a placement (rotaton ONLY)"
     rot = FreeCAD.Placement(pl).Rotation
     self.u = rot.multVec(FreeCAD.Vector(1, 0, 0))
     self.v = rot.multVec(FreeCAD.Vector(0, 1, 0))
     self.axis = rot.multVec(FreeCAD.Vector(0, 0, 1))
Beispiel #29
0
def createFromProperties(propsets, ifcfile, parametrics):
    """
    Creates a FreeCAD parametric object from a set of properties.
    """

    obj = None
    sets = []
    appset = None
    guiset = None
    for pset in propsets.keys():
        if ifcfile[pset].Name == "FreeCADPropertySet":
            appset = {}
            for pid in propsets[pset]:
                p = ifcfile[pid]
                appset[p.Name] = p.NominalValue.wrappedValue
        elif ifcfile[pset].Name == "FreeCADGuiPropertySet":
            guiset = {}
            for pid in propsets[pset]:
                p = ifcfile[pid]
                guiset[p.Name] = p.NominalValue.wrappedValue
    if appset:
        oname = None
        otype = None
        if "FreeCADType" in appset.keys():
            if "FreeCADName" in appset.keys():
                obj = FreeCAD.ActiveDocument.addObject(appset["FreeCADType"],
                                                       appset["FreeCADName"])
                if "FreeCADAppObject" in appset:
                    mod, cla = appset["FreeCADAppObject"].split(".")
                    if "'" in mod:
                        mod = mod.split("'")[-1]
                    if "'" in cla:
                        cla = cla.split("'")[0]
                    import importlib
                    mod = importlib.import_module(mod)
                    getattr(mod, cla)(obj)
                sets.append(("App", appset))
                if FreeCAD.GuiUp:
                    if guiset:
                        if "FreeCADGuiObject" in guiset:
                            mod, cla = guiset["FreeCADGuiObject"].split(".")
                            if "'" in mod:
                                mod = mod.split("'")[-1]
                            if "'" in cla:
                                cla = cla.split("'")[0]
                            import importlib
                            mod = importlib.import_module(mod)
                            getattr(mod, cla)(obj.ViewObject)
                        sets.append(("Gui", guiset))
    if obj and sets:
        for realm, pset in sets:
            if realm == "App":
                target = obj
            else:
                target = obj.ViewObject
            for key, val in pset.items():
                if key.startswith("FreeCAD_") or key.startswith("FreeCADGui_"):
                    name = key.split("_")[1]
                    if name in target.PropertiesList:
                        if not target.getEditorMode(name):
                            ptype = target.getTypeIdOfProperty(name)
                            if ptype in [
                                    "App::PropertyString",
                                    "App::PropertyEnumeration",
                                    "App::PropertyInteger",
                                    "App::PropertyFloat"
                            ]:
                                setattr(target, name, val)
                            elif ptype in [
                                    "App::PropertyLength",
                                    "App::PropertyDistance"
                            ]:
                                setattr(target, name, val * 1000)
                            elif ptype == "App::PropertyBool":
                                if val in [".T.", True]:
                                    setattr(target, name, True)
                                else:
                                    setattr(target, name, False)
                            elif ptype == "App::PropertyVector":
                                setattr(
                                    target, name,
                                    FreeCAD.Vector([
                                        float(s) for s in val.split("(")
                                        [1].strip(")").split(",")
                                    ]))
                            elif ptype == "App::PropertyArea":
                                setattr(target, name, val * 1000000)
                            elif ptype == "App::PropertyPlacement":
                                data = val.split("[")[1].strip("]").split("(")
                                data = [
                                    data[1].split(")")[0], data[2].strip(")")
                                ]
                                v = FreeCAD.Vector(
                                    [float(s) for s in data[0].split(",")])
                                r = FreeCAD.Rotation(
                                    *[float(s) for s in data[1].split(",")])
                                setattr(target, name, FreeCAD.Placement(v, r))
                            elif ptype == "App::PropertyLink":
                                link = val.split("_")[1]
                                parametrics.append([target, name, link])
                            else:
                                print("Unhandled FreeCAD property:", name,
                                      " of type:", ptype)
    return obj, parametrics
Beispiel #30
0
    def onChanged(self, vobj, prop):
        """Execute when a view property is changed."""
        super(ViewProviderLabel, self).onChanged(vobj, prop)

        if prop == "ScaleMultiplier":
            if not hasattr(vobj, "ScaleMultiplier"):
                return
            if hasattr(vobj, "TextSize") and hasattr(vobj, "TextAlignment"):
                self.update_label(vobj)
            if hasattr(vobj, "ArrowSize"):
                s = vobj.ArrowSize.Value * vobj.ScaleMultiplier
                if s:
                    self.arrowpos.scaleFactor.setValue((s, s, s))
        elif prop == "LineColor":
            if hasattr(vobj, "LineColor"):
                l = vobj.LineColor
                self.matline.diffuseColor.setValue([l[0], l[1], l[2]])
        elif prop == "TextColor":
            if hasattr(vobj, "TextColor"):
                l = vobj.TextColor
                self.mattext.diffuseColor.setValue([l[0], l[1], l[2]])
        elif prop == "LineWidth":
            if hasattr(vobj, "LineWidth"):
                self.drawstyle.lineWidth = vobj.LineWidth
        elif (prop == "TextFont"):
            if hasattr(vobj, "TextFont"):
                self.font.name = vobj.TextFont.encode("utf8")
        elif prop in ["TextSize", "TextAlignment"] and hasattr(
                vobj, "ScaleMultiplier"):
            if hasattr(vobj, "TextSize") and hasattr(vobj, "TextAlignment"):
                self.update_label(vobj)
        elif prop == "Line":
            if hasattr(vobj, "Line"):
                if vobj.Line:
                    self.lineswitch.whichChild = 0
                else:
                    self.lineswitch.whichChild = -1
        elif prop == "ArrowType":
            if hasattr(vobj, "ArrowType"):
                if len(vobj.Object.Points) > 1:
                    if hasattr(self, "symbol"):
                        if self.arrow.findChild(self.symbol) != -1:
                            self.arrow.removeChild(self.symbol)
                    s = utils.ARROW_TYPES.index(vobj.ArrowType)
                    self.symbol = gui_utils.dim_symbol(s)
                    self.arrow.addChild(self.symbol)
                    self.arrowpos.translation.setValue(vobj.Object.Points[-1])
                    v1 = vobj.Object.Points[-2].sub(vobj.Object.Points[-1])
                    if not DraftVecUtils.isNull(v1):
                        v1.normalize()
                        v2 = App.Vector(0, 0, 1)
                        if round(v2.getAngle(v1), 4) in [0, round(math.pi, 4)]:
                            v2 = App.Vector(0, 1, 0)
                        v3 = v1.cross(v2).negative()
                        q = App.Placement(
                            DraftVecUtils.getPlaneRotation(v1, v3,
                                                           v2)).Rotation.Q
                        self.arrowpos.rotation.setValue(
                            (q[0], q[1], q[2], q[3]))
        elif prop == "ArrowSize":
            if hasattr(vobj, "ArrowSize") and hasattr(vobj, "ScaleMultiplier"):
                s = vobj.ArrowSize.Value * vobj.ScaleMultiplier
                if s:
                    self.arrowpos.scaleFactor.setValue((s, s, s))
        elif prop == "Frame":
            if hasattr(vobj, "Frame"):
                self.frame.coordIndex.deleteValues(0)
                if vobj.Frame == "Rectangle":
                    tsize = self.getTextSize(vobj)
                    pts = []
                    base = vobj.Object.Placement.Base.sub(
                        App.Vector(
                            self.textpos.translation.getValue().getValue()))
                    pts.append(base.add(App.Vector(0, tsize[1] * 3, 0)))
                    pts.append(pts[-1].add(App.Vector(-tsize[0] * 6, 0, 0)))
                    pts.append(pts[-1].add(App.Vector(0, -tsize[1] * 6, 0)))
                    pts.append(pts[-1].add(App.Vector(tsize[0] * 6, 0, 0)))
                    pts.append(pts[0])
                    self.fcoords.point.setValues(pts)
                    self.frame.coordIndex.setValues(0, len(pts),
                                                    range(len(pts)))