Пример #1
0
    def Activated(self, name=translate("draft", "Fillet")):
        DraftTools.Creator.Activated(self, name)
        if not self.doc:
            FCC.PrintWarning(translate("draft", "No active document") + "\n")
            return
        if self.ui:
            self.rad = 100
            self.chamfer = False
            self.delete = False
            label = translate("draft", "Fillet radius")
            tooltip = translate("draft", "Radius of fillet")

            # Call the Task panel for a radius
            # The graphical widgets are defined in DraftGui
            self.ui.taskUi(title=name, icon="Draft_Fillet")
            self.ui.radiusUi()
            self.ui.sourceCmd = self
            self.ui.labelRadius.setText(label)
            self.ui.radiusValue.setToolTip(tooltip)
            self.ui.setRadiusValue(self.rad, "Length")
            self.ui.check_delete = self.ui._checkbox("isdelete",
                                                     self.ui.layout,
                                                     checked=self.delete)
            self.ui.check_delete.setText(
                translate("draft", "Delete original objects"))
            self.ui.check_delete.show()
            self.ui.check_chamfer = self.ui._checkbox("ischamfer",
                                                      self.ui.layout,
                                                      checked=self.chamfer)
            self.ui.check_chamfer.setText(translate("draft", "Create chamfer"))
            self.ui.check_chamfer.show()

            QtCore.QObject.connect(self.ui.check_delete,
                                   QtCore.SIGNAL("stateChanged(int)"),
                                   self.set_delete)
            QtCore.QObject.connect(self.ui.check_chamfer,
                                   QtCore.SIGNAL("stateChanged(int)"),
                                   self.set_chamfer)
            self.linetrack = trackers.lineTracker(dotted=True)
            self.arctrack = trackers.arcTracker()
            # self.call = self.view.addEventCallback("SoEvent", self.action)
            FCC.PrintMessage(translate("draft", "Enter radius") + "\n")
Пример #2
0
 def _handleSimulation(self):
     self._simulation("Coordinate System", "Cartesian 3D")
     self._simulation("Coordinate Mapping", (1, 2, 3))
     if self.unit_schema == Units.Scheme.SI2:
         self._simulation("Coordinate Scaling", 0.001)
         Console.PrintMessage(
             "'Coordinate Scaling = Real 0.001' was inserted into the solver input file.\n"
         )
     self._simulation("Simulation Type", "Steady state")
     self._simulation("Steady State Max Iterations", 1)
     self._simulation("Output Intervals", 1)
     self._simulation("Timestepping Method", "BDF")
     self._simulation("BDF Order", 1)
     self._simulation("Use Mesh Names", True)
     self._simulation(
         "Steady State Max Iterations",
         self.solver.SteadyStateMaxIterations)
     self._simulation(
         "Steady State Min Iterations",
         self.solver.SteadyStateMinIterations)
Пример #3
0
 def _writeMesh(self):
     mesh = self._getSingleMember("Fem::FemMeshObject")
     unvPath = os.path.join(self.directory, "mesh.unv")
     groups = []
     groups.extend(self._builder.getBodyNames())
     groups.extend(self._builder.getBoundaryNames())
     self._exportToUnv(groups, mesh, unvPath)
     if self.testmode:
         Console.PrintMessage(
             "Solver Elmer testmode, ElmerGrid will not be used. "
             "It might not be installed.\n")
     else:
         binary = settings.get_binary("ElmerGrid")
         if binary is None:
             raise WriteError("Could not find ElmerGrid binary.")
         args = [
             binary, _ELMERGRID_IFORMAT, _ELMERGRID_OFORMAT, unvPath,
             "-out", self.directory
         ]
         subprocess.call(args, stdout=subprocess.DEVNULL)
Пример #4
0
    def __init__(self):
        Console.PrintMessage("BodyRenderer\n")

        self.width = None
        self.depth = None
        self.height = None

        self.hole_style = None
        self.holes_offset = None

        self.doc = None
        self.brick = None

        self.top_datum_plane = None
        self.top_inside_datum_plane = None
        self.front_inside_datum_plane = None
        self.back_inside_datum_plane = None
        self.left_inside_datum_plane = None
        self.right_inside_datum_plane = None
        self.xy_plane = None
Пример #5
0
    def _render_tubes_or_sticks(self, body_pad_sketch):
        Console.PrintMessage("_render_tubes_or_sticks()\n")

        tubes = self.depth > 1 and self.width > 1
        tube_ribs = tubes and self.height > 1 and (self.depth > 2
                                                   or self.width > 2)
        sticks = not tubes and (self.depth > 1 or self.width > 1)
        stick_ribs = sticks and self.height > 1 and not self.hole_style == HoleStyle.HOLE

        if tube_ribs:
            self._render_tube_ribs()

        if tubes:
            self._render_tubes(body_pad_sketch)

        if stick_ribs:
            self._render_stick_ribs()

        if sticks:
            self._render_sticks(body_pad_sketch)
Пример #6
0
def findStartPoint(op, feat_num, cut_region_tp, cut_region_tp_polytree,
                   helixRadius, toolRadius, scale_factor):
    #searching for biggest area to cut, by decremental offseting from target cut_region

    #start offset is max x or y size of the stock/2
    maxLen = max(op.stock.Shape.BoundBox.XLength,
                 op.stock.Shape.BoundBox.YLength)
    starting_offset = maxLen * scale_factor / 2

    #try with some reasonable step
    step = toolRadius / 4

    while starting_offset >= helixRadius:
        of.Clear()
        of.AddPaths(cut_region_tp, pyclipper.JT_ROUND,
                    pyclipper.ET_CLOSEDPOLYGON)
        offsetPaths = of.Execute(-(starting_offset))
        #showPath(op,offsetPaths,scale_factor)
        for path in offsetPaths:
            #find center
            pt = GeomUtils.centroid(path)
            #showTool("STP", pt, scale_factor, (1,0,1))
            if not isOutsideCutRegion(pt, cut_region_tp_polytree):
                of.Clear()
                of.AddPath([pt, [pt[0] + 1, pt[1]]], pyclipper.JT_ROUND,
                           pyclipper.ET_OPENROUND)
                cleared_helix = of.Execute(helixRadius + toolRadius)
                Console.PrintMessage(
                    "Start point: %f,%f\n" %
                    (1.0 * pt[0] / scale_factor, 1.0 * pt[1] / scale_factor))
                return cleared_helix, pt
            # sceneClearPaths("STP")
            # sceneDrawPath("STP", path, scale_factor, (1, 0, 1))
            # messageBox("Continue")

        starting_offset = starting_offset - step

    Console.PrintError("Unable to find starting point (for path no:%d)!\n" %
                       feat_num)
    #sceneClearPaths("STP")
    return None, None
Пример #7
0
 def get_dimension(self):
     # Dimension
     # known_element_dimensions = ["From Shape", "1D", "2D", "3D"]
     # if not given, Gmsh uses the highest available.
     # A use case for not "From Shape" would be a surface (2D) mesh of a solid
     if self.dimension == "From Shape":
         shty = self.part_obj.Shape.ShapeType
         if shty == "Solid" or shty == "CompSolid":
             # print("Found: " + shty)
             self.dimension = "3"
         elif shty == "Face" or shty == "Shell":
             # print("Found: " + shty)
             self.dimension = "2"
         elif shty == "Edge" or shty == "Wire":
             # print("Found: " + shty)
             self.dimension = "1"
         elif shty == "Vertex":
             # print("Found: " + shty)
             Console.PrintError("You can not mesh a Vertex.\n")
             self.dimension = "0"
         elif shty == "Compound":
             # print("  Found a " + shty)
             Console.PrintLog(
                 "  Found a Compound. Since it could contain"
                 "any kind of shape dimension 3 is used.\n"
             )
             self.dimension = "3"  # dimension 3 works for 2D and 1d shapes as well
         else:
             self.dimension = "0"
             Console.PrintError(
                 "Could not retrieve Dimension from shape type. Please choose dimension.\n"
             )
     elif self.dimension == "3D":
         self.dimension = "3"
     elif self.dimension == "2D":
         self.dimension = "2"
     elif self.dimension == "1D":
         self.dimension = "1"
     else:
         Console.PrintError("Error in dimension\n")
     Console.PrintMessage("  ElementDimension: " + self.dimension + "\n")
Пример #8
0
 def onOK(self):
     if self.mirroredPartName != '':
         # the mirrored object's name
         symPartName = self.mirroredPartName.text()
         symObjName = self.selObj.Label + '_mirrored'
         linkObjName = self.selObj.Label + '_link'
         # create Part
         symPart = App.ActiveDocument.addObject('App::Part', symPartName)
         # add an LCS at the root of the Part, and attach it to the 'Origin'
         lcs = symPart.newObject('PartDesign::CoordinateSystem',
                                 'LCS_' + symPart.Name)
         lcs.Support = [(symPart.Origin.OriginFeatures[0], '')]
         lcs.MapMode = 'ObjectXY'
         lcs.MapReversed = False
         # if there is a Parts group, put the symmetrical part there
         partsGroup = Asm4.getPartsGroup()
         if partsGroup:
             partsGroup.addObject(symPart)
         # create a link to the original
         link = symPart.newObject('App::Link', linkObjName)
         link.LinkedObject = self.selObj
         link.Label = linkObjName
         link.Visibility = False
         # create the mirrored object
         symObj = symPart.newObject('Part::Mirroring', symObjName)
         symObj.Source = link
         # set the symmetry plane
         if self.symPlane.currentText() == 'X-Y':
             symObj.Normal = App.Vector(0, 0, 1)
         elif self.symPlane.currentText() == 'X-Z':
             symObj.Normal = App.Vector(0, 1, 0)
         elif self.symPlane.currentText() == 'Y-Z':
             symObj.Normal = App.Vector(1, 0, 0)
         else:
             FCC.PrintMessage(
                 "ERROR : You shouldn't see this message from mirrorPartCmd()\n"
             )
         # recompute
         symPart.recompute()
         App.ActiveDocument.recompute()
     self.UI.close()
Пример #9
0
 def onDatumClicked( self ):
     # clear the selection in the GUI window
     Gui.Selection.clearSelection()
     # keep the fastener selected
     Gui.Selection.addSelection( self.activeDoc.Name, 'Model', self.selectedFastener.Name+'.')
     # LCS in the parent
     if self.attLCSlist.selectedItems():
         #a_LCS = self.attLCSlist.selectedItems()[0].text()
         a_LCS = self.attLCStable[ self.attLCSlist.currentRow() ].Name
         # get the part where the selected LCS is
         #a_Part = self.parentList.currentText()
         a_Part = self.parentTable[ self.parentList.currentIndex() ]
         # parent assembly and sister part need a different treatment
         if a_Part == 'Parent Assembly':
             linkDot = ''
         else:
             linkDot = a_Part+'.'
         Gui.Selection.addSelection( self.activeDoc.Name, 'Model', linkDot+a_LCS+'.')
         FCC.PrintMessage("selection: "+ linkDot+a_LCS+'.' +"\n")
     # show the resulting placement
     self.onApply()
Пример #10
0
    def _add_vertical_sketch_segment(geometries, constraints, length,
                                     ver_vec_start, ver_vec_end, reverse):
        Console.PrintMessage("_add_vertical_sketch_segment({},{})\n".format(
            length, reverse))

        segment_count = len(geometries)

        geometries.append(Part.LineSegment(ver_vec_start, ver_vec_end))
        constraints.append(Sketcher.Constraint("Vertical", segment_count))
        if segment_count > 0:
            constraints.append(
                Sketcher.Constraint("Coincident", segment_count - 1,
                                    SKETCH_GEOMETRY_VERTEX_END_INDEX,
                                    segment_count,
                                    SKETCH_GEOMETRY_VERTEX_START_INDEX))
        constraints.append(
            Sketcher.Constraint("DistanceY", segment_count,
                                SKETCH_GEOMETRY_VERTEX_START_INDEX,
                                segment_count,
                                SKETCH_GEOMETRY_VERTEX_END_INDEX,
                                (-1 if reverse else 1) * length))
Пример #11
0
    def get_tmp_file_paths(self, param_working_dir=None, create=False):
        self.working_dir = ""
        # try to use given working dir
        if param_working_dir is not None:
            self.working_dir = param_working_dir
            if femutils.check_working_dir(self.working_dir) is not True:
                if create is True:
                    Console.PrintMessage(
                        "Dir given as parameter \'{}\' doesn't exist, "
                        "but parameter to create it is set to True. "
                        "Dir will be created.\n".format(self.working_dir))
                    from os import mkdir
                    mkdir(param_working_dir)
                else:
                    Console.PrintError(
                        "Dir given as parameter \'{}\' doesn't exist "
                        "and create parameter is set to False.\n".format(
                            self.working_dir))
                    self.working_dir = femutils.get_pref_working_dir(
                        self.mesh_obj)
                    Console.PrintMessage(
                        "Dir \'{}\' will be used instead.\n".format(
                            self.working_dir))
        else:
            self.working_dir = femutils.get_pref_working_dir(self.mesh_obj)

        # check working_dir exist, if not use a tmp dir and inform the user
        if femutils.check_working_dir(self.working_dir) is not True:
            Console.PrintError(
                "Dir \'{}\' doesn't exist or cannot be created.\n".format(
                    self.working_dir))
            self.working_dir = femutils.get_temp_dir(self.mesh_obj)
            Console.PrintMessage("Dir \'{}\' will be used instead.\n".format(
                self.working_dir))

        # file paths
        _geometry_name = self.part_obj.Name + "_Geometry"
        self.mesh_name = self.part_obj.Name + "_Mesh"
        from os.path import join
        self.temp_file_geometry = join(self.working_dir, _geometry_name +
                                       ".brep")  # geometry file
        self.temp_file_mesh = join(self.working_dir,
                                   self.mesh_name + ".unv")  # mesh file
        self.temp_file_geo = join(self.working_dir,
                                  "shape2mesh.geo")  # Gmsh input file
        Console.PrintMessage("  " + self.temp_file_geometry + "\n")
        Console.PrintMessage("  " + self.temp_file_mesh + "\n")
        Console.PrintMessage("  " + self.temp_file_geo + "\n")
Пример #12
0
def gettranslation(data):
    """Retrieve a translation (move) vector from `data`.

    Parameters
    ----------
    data : list
        Different types of data.

    Returns
    -------
    Base::Vector3
        A vector with X, Y, or Z displacement, or (0, 0, 0).
    """
    FCC.PrintMessage("found translation %s \n" % data)
    if data[0] == "Z":
        return Vector(0, 0, float(data[1]))
    elif data[0] == "Y":
        return Vector(0, float(data[1]), 0)
    elif data[0] == "X":
        return Vector(float(data[1]), 0, 0)
    return Vector(0, 0, 0)
Пример #13
0
    def _exportToUnv(self, groups, mesh, meshPath):
        unvGmshFd, unvGmshPath = tempfile.mkstemp(suffix=".unv")
        brepFd, brepPath = tempfile.mkstemp(suffix=".brep")
        geoFd, geoPath = tempfile.mkstemp(suffix=".geo")
        os.close(brepFd)
        os.close(geoFd)
        os.close(unvGmshFd)

        tools = gmshtools.GmshTools(mesh)
        tools.group_elements = {g: [g] for g in groups}
        tools.group_nodes_export = False
        tools.ele_length_map = {}
        tools.temp_file_geometry = brepPath
        tools.temp_file_geo = geoPath
        tools.temp_file_mesh = unvGmshPath

        tools.get_dimension()
        tools.get_region_data()
        tools.get_boundary_layer_data()
        tools.write_part_file()
        tools.write_geo()
        if self.testmode:
            Console.PrintMessage(
                "Solver Elmer testmode, Gmsh will not be used. "
                "It might not be installed.\n")
            import shutil
            shutil.copyfile(geoPath,
                            os.path.join(self.directory, "group_mesh.geo"))
        else:
            tools.get_gmsh_command()
            tools.run_gmsh_with_geo()

            ioMesh = Fem.FemMesh()
            ioMesh.read(unvGmshPath)
            ioMesh.write(meshPath)

        os.remove(brepPath)
        os.remove(geoPath)
        os.remove(unvGmshPath)
Пример #14
0
def getline(data):
    """Turns an OCA line definition into a FreeCAD Part.Edge.

    Parameters
    ----------
    data : list
        Different types of data.

    Returns
    -------
    Part.Edge
        An edge object from the points in `data`.
    """
    FCC.PrintMessage("found line %s \n" % data)
    verts = []
    for p in range(len(data)):
        if data[p] == "P":
            verts.append(getpoint(data[p:p + 4]))
        elif data[p][0] == "P":
            verts.append(getpoint([data[p]]))
    L = Part.LineSegment(verts[0], verts[1])
    return L.toShape()
Пример #15
0
    def addSelection(self, doc, obj, sub, pnt):  # Selection object
        # Since both 3D view clicks and manual tree selection gets into the same callback
        # we will determine by clicked coordinates, for manual tree selections the coordinates are (0,0,0)
        FCC.PrintMessage('Clicked on :' + obj + '@' + sub + '\n')
        if pnt != (0, 0, 0):
            # 3D view click
            # Get linked object name that handles sub-sub-assembly
            #subObjName = Asm4.getLinkedObjectName(doc, obj, sub)
            objList = App.getDocument(doc).getObject(obj).getSubObjectList(sub)
            # Build the name of the selected sub-object for multiple sub-assembly levels
            subObjName = ''
            for subObj in objList:
                if subObj.TypeId == 'App::Link':
                    subObjName = subObjName + subObj.Name + '.'

            if subObjName != '':
                # set the selection to the selected object
                Gui.Selection.clearSelection()
                Gui.Selection.addSelection(doc, obj, subObjName)
                # set the selected object drop-down to this object
                global taskUI
                link = App.ActiveDocument.getObject(subObjName[0:-1])
                #FCC.PrintMessage('LinkedObject = '+link.LinkedObject.Name+'\n')
                # try to find this link in the parents
                parent_found = False
                parent_index = 1
                for item in taskUI.parentTable[1:]:
                    if item.Name == link.Name:
                        parent_found = True
                        break
                    else:
                        parent_index = parent_index + 1
                if not parent_found:
                    parent_index = 0
                taskUI.parentList.setCurrentIndex(parent_index)
            # select the Parent Assembly
            else:
                taskUI.parentList.setCurrentIndex(1)
Пример #16
0
def convertToDwg(dxffilename, dwgfilename):
    """Convert a DXF file to a DWG file.

    If the converter is found it is used, otherwise the conversion fails.

    Parameters
    ----------
    dxffilename : str
        The input DXF file
    dwgfilename : str
        The output DWG file

    Returns
    -------
    str
        The same `dwgfilename` file path.
    """
    import os, subprocess

    import shutil
    if shutil.which("dxf2dwg"):
        proc = subprocess.Popen(
            ("dxf2dwg", dxffilename, "-y", "-o", dwgfilename))
        proc.communicate()
        return dwgfilename

    teigha = getTeighaConverter()
    if teigha:
        indir = os.path.dirname(dxffilename)
        outdir = os.path.dirname(dwgfilename)
        basename = os.path.basename(dxffilename)
        cmdline = ('"%s" "%s" "%s" "ACAD2000" "DWG" "0" "1" "%s"' %
                   (teigha, indir, outdir, basename))
        FCC.PrintMessage(
            translate("ImportDWG", "Converting:") + " " + cmdline + "\n")
        subprocess.call(cmdline, shell=True)  # os.system(cmdline)
        return dwgfilename
    return None
Пример #17
0
    def render(self, context):
        Console.PrintMessage("render\n")

        self.doc = context.doc
        self.brick = context.brick

        self.width = context.width
        self.depth = context.depth
        self.style = context.side_studs_style
        self.front = context.side_studs_front
        self.back = context.side_studs_back
        self.left = context.side_studs_left
        self.right = context.side_studs_right

        self.front_datum_plane = context.front_datum_plane
        self.back_datum_plane = context.back_datum_plane
        self.left_datum_plane = context.left_datum_plane
        self.right_datum_plane = context.right_datum_plane

        if self.front:
            self._render_side_studs_outside("front", self.front_datum_plane, self.width, True)
            if self.style == SideStudStyle.HOLE:
                self._render_side_studs_inside("front", self.front_datum_plane, self.width, False)

        if self.back:
            self._render_side_studs_outside("back", self.back_datum_plane, self.width, False)
            if self.style == SideStudStyle.HOLE:
                self._render_side_studs_inside("back", self.back_datum_plane, self.width, True)

        if self.left:
            self._render_side_studs_outside("left", self.left_datum_plane, self.depth, False)
            if self.style == SideStudStyle.HOLE:
                self._render_side_studs_inside("left", self.left_datum_plane, self.depth, True)

        if self.right:
            self._render_side_studs_outside("right", self.right_datum_plane, self.depth, True)
            if self.style == SideStudStyle.HOLE:
                self._render_side_studs_inside("right", self.right_datum_plane, self.depth, False)
Пример #18
0
def getpoint(data):
    """Turn an OCA point definition into a FreeCAD.Vector.

    Parameters
    ----------
    data : list
        Different types of data.

    Returns
    -------
    Base::Vector3
        A vector with the data arranged, depending on the contents of `data`.
    """
    FCC.PrintMessage("found point %s \n" % data)
    if len(data) == 3:
        return Vector(float(data[0]), float(data[1]), float(data[2]))
    elif (data[0] == "P") and (len(data) == 4):
        return Vector(float(data[1]), float(data[2]), float(data[3]))
    elif (data[0][0] == "P") and (len(data[0]) > 1):
        if len(data) == 1:
            return objects[data[0]]
        else:
            if data[1][0] == "R":
                return objects[data[0]].add(objects[data[1]])
            elif data[1][0] == "C":
                # Error: DraftGeomUtils.findProjection()
                # doesn't exist
                return DraftGeomUtils.findProjection(objects[data[0]],
                                                     objects[data[1]])
    elif data[0][0] == "C":
        if objects[data[0]]:
            p1 = objects[data[0]].Curve.Position
            if len(data) == 1:
                return p1
            else:
                if data[1][0] == "L":
                    L = objects[data[1]]
                    return p1.add(DraftGeomUtils.vec(L))
Пример #19
0
def getarea(data):
    """Turn an OCA area definition into a FreeCAD Part.Wire.

    Parameters
    ----------
    data : list
        Different types of data.

    Returns
    -------
    Part.Wire
        A wire object from the points in `data`.
    """
    FCC.PrintMessage("found area %s \n" % data)
    if data[0] == "S":
        if data[1] == "POL":
            pts = data[2:]
            verts = []
            for p in pts:
                if p[0] == "P":
                    verts.append(getpoint([p]))
            w = Part.makePolygon(verts)
            return w
Пример #20
0
def _extract_edges(objs):
    """Extract the edges from the given objects (Draft lines or Edges).

    objs : list of Draft Lines or Part.Edges
        The list of edges from which to create the fillet.
    """
    o1, o2 = objs
    if hasattr(o1, "PropertiesList"):
        if "Proxy" in o1.PropertiesList:
            if hasattr(o1.Proxy, "Type"):
                if o1.Proxy.Type in ("Wire", "Fillet"):
                    e1 = o1.Shape.Edges[0]
        elif "Shape" in o1.PropertiesList:
            if o1.Shape.ShapeType in ("Wire", "Edge"):
                e1 = o1.Shape
    elif hasattr(o1, "ShapeType"):
        if o1.ShapeType in "Edge":
            e1 = o1

    if hasattr(o1, "Label"):
        FCC.PrintMessage("o1: " + o1.Label)
    else:
        FCC.PrintMessage("o1: 1")
    FCC.PrintMessage(", length: " + str(e1.Length) + "\n")

    if hasattr(o2, "PropertiesList"):
        if "Proxy" in o2.PropertiesList:
            if hasattr(o2.Proxy, "Type"):
                if o2.Proxy.Type in ("Wire", "Fillet"):
                    e2 = o2.Shape.Edges[0]
        elif "Shape" in o2.PropertiesList:
            if o2.Shape.ShapeType in ("Wire", "Edge"):
                e2 = o2.Shape
    elif hasattr(o2, "ShapeType"):
        if o2.ShapeType in "Edge":
            e2 = o2

    if hasattr(o2, "Label"):
        FCC.PrintMessage("o2: " + o2.Label)
    else:
        FCC.PrintMessage("o2: 2")
    FCC.PrintMessage(", length: " + str(e2.Length) + "\n")

    return e1, e2
def add_heated_beds_and_spool_holder_rods_to_cut_list(cut_list_table_rows,
                                                      num_z_axes, document):
    frame = retrieve_frame_from_document(document)
    if frame is None:
        Console.PrintMessage(
            'Frame must be added to document to calculate length of heated bed rods and spool holder rod.\n'
        )
        return cut_list_table_rows
    frame_size = frame.Size.Value
    rod_length_equal_to_frame_length = convert_value_to_quantity_and_format(
        frame_size)
    one_inch = 25.4

    # 2 heated bed rods per pair of Z axes
    num_heated_bed_rods = (num_z_axes / 2) * 2
    log_warning_if_odd_number_of_z_axes(num_z_axes, num_heated_bed_rods)
    if num_heated_bed_rods > 0:
        cut_list_table_rows = cut_list_table_rows + [
            {
                'quantity': num_heated_bed_rods,
                'description': 'Heated Bed Rod',
                'length': rod_length_equal_to_frame_length
            }
        ]
    return cut_list_table_rows + [{
        'quantity': '1',
        'description': 'Spool Holder Rod',
        'length': rod_length_equal_to_frame_length
    }, {
        'quantity':
        '2',
        'description':
        'Spool Holder Rod',
        'length':
        convert_value_to_quantity_and_format(frame_size - one_inch)
    }]
Пример #22
0
 def setupObject(self, obj):
     FCC.PrintMessage('Triggered by setupObject() in VariantLink\n')
     obj.LinkedObject = obj.SourceObject
Пример #23
0
 def __init__(self):
     FCC.PrintMessage('Initialising ...\n')
     self.Object = None
Пример #24
0
 def onLostLinkToObject(self, obj):
     FCC.PrintMessage('Triggered onLostLinkToObject() in VariantLink\n')
     obj.LinkedObject = obj.SourceObject
     return
Пример #25
0
def read_frd_result(frd_input):
    Console.PrintMessage(
        "Read ccx results from frd file: {}\n".format(frd_input))
    inout_nodes = []
    inout_nodes_file = frd_input.rsplit(".", 1)[0] + "_inout_nodes.txt"
    if os.path.exists(inout_nodes_file):
        Console.PrintMessage(
            "Read special 1DFlow nodes data form: {}\n".format(
                inout_nodes_file))
        f = pyopen(inout_nodes_file, "r")
        lines = f.readlines()
        for line in lines:
            a = line.split(",")
            inout_nodes.append(a)
        f.close()
        Console.PrintMessage("{}\n".format(inout_nodes))
    frd_file = pyopen(frd_input, "r")
    nodes = {}
    elements_hexa8 = {}
    elements_penta6 = {}
    elements_tetra4 = {}
    elements_tetra10 = {}
    elements_penta15 = {}
    elements_hexa20 = {}
    elements_tria3 = {}
    elements_tria6 = {}
    elements_quad4 = {}
    elements_quad8 = {}
    elements_seg2 = {}
    elements_seg3 = {}
    results = []
    mode_results = {}
    mode_results["number"] = float("NaN")
    mode_results["time"] = float("NaN")
    mode_disp = {}
    mode_stress = {}
    mode_strain = {}
    mode_peeq = {}
    mode_temp = {}
    mode_massflow = {}
    mode_networkpressure = {}

    nodes_found = False
    elements_found = False
    mode_time_found = False
    mode_disp_found = False
    mode_stress_found = False
    mode_strain_found = False
    mode_peeq_found = False
    mode_temp_found = False
    mode_massflow_found = False
    mode_networkpressure_found = False
    end_of_section_found = False
    end_of_frd_data_found = False
    input_continues = False
    mode_eigen_changed = False
    mode_time_changed = False

    eigenmode = 0
    eigentemp = 0
    elem = -1
    elemType = 0
    timestep = 0
    timetemp = 0

    for line in frd_file:

        # Check if we found nodes section
        if line[4:6] == "2C":
            nodes_found = True
        if nodes_found and (line[1:3] == "-1"):
            # we found a nodes line, lets extract the node and coordinate data
            elem = int(line[4:13])
            nodes_x = float(line[13:25])
            nodes_y = float(line[25:37])
            nodes_z = float(line[37:49])
            nodes[elem] = FreeCAD.Vector(nodes_x, nodes_y, nodes_z)

        # Check if we found elements section
        if line[4:6] == "3C":
            elements_found = True
        if elements_found and (line[1:3] == "-1"):
            # we found a first element line, lets extract element number
            elem = int(line[4:13])
            elemType = int(line[14:18])
        if elements_found and (line[1:3] == "-2"):
            # we found a second element line, lets extract the elements
            # node order fits with node order in writeAbaqus() in FemMesh.cpp
            if elemType == 1:
                # C3D8 CalculiX --> hexa8 FreeCAD
                # N6, N7, N8, N5, N2, N3, N4, N1
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                elements_hexa8[elem] = (nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1)
            elif elemType == 2:
                # C3D6 Calculix --> penta6 FreeCAD
                # N5, N6, N4, N2, N3, N1
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                elements_penta6[elem] = (nd5, nd6, nd4, nd2, nd3, nd1)
            elif elemType == 3:
                # C3D4 Calculix --> tetra4 FreeCAD
                # N2, N1, N3, N4
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                elements_tetra4[elem] = (nd2, nd1, nd3, nd4)
            elif elemType == 4 and input_continues is False:
                # first line
                # C3D20 Calculix --> hexa20 FreeCAD
                # N6, N7, N8, N5, N2, N3, N4, N1, N14, N15
                # N16, N13, N10, N11, N12, N9, N18, N19, N20, N17
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                input_continues = True
            elif elemType == 4 and input_continues is True:
                # second line
                nd11 = int(line[3:13])
                nd12 = int(line[13:23])
                nd13 = int(line[23:33])
                nd14 = int(line[33:43])
                nd15 = int(line[43:53])
                nd16 = int(line[53:63])
                nd17 = int(line[63:73])
                nd18 = int(line[73:83])
                nd19 = int(line[83:93])
                nd20 = int(line[93:103])
                input_continues = False
                """
                CalculiX uses a different node order in
                input file *.inp and result file *.frd for hexa20 (C3D20)
                according to Guido (the developer of ccx):
                see note in in first line of cgx manuel part element types
                ccx (and thus the *.inp) follows the ABAQUS convention
                documented in the ccx-documentation
                cgx (and thus the *.frd) follows the FAM2 convention
                documented in the cgx-documentation
                FAM32 is from the company FEGS limited
                maybe this company does not exist any more
                elements_hexa20[elem] = (
                    nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1, nd14, nd15,
                    nd16, nd13, nd10, nd11, nd12, nd9, nd18, nd19, nd20, nd17
                )
                elements_hexa20[elem] = (
                    nd6, nd7, nd8, nd5, nd2, nd3, nd4, nd1, nd14, nd15,
                    nd16, nd13, nd18, nd19, nd20, nd17, nd10, nd11, nd12, nd9
                )
                hexa20 import works with the following frd file node assignment
                """
                elements_hexa20[elem] = (nd8, nd5, nd6, nd7, nd4, nd1, nd2,
                                         nd3, nd20, nd17, nd18, nd19, nd12,
                                         nd9, nd10, nd11, nd16, nd13, nd14,
                                         nd15)
            elif elemType == 5 and input_continues is False:
                # first line
                # C3D15 Calculix --> penta15 FreeCAD
                # N5, N6, N4, N2, N3, N1, N11, N12, N10, N8, N9, N7, N14, N15, N13
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                input_continues = True
            elif elemType == 5 and input_continues is True:
                # second line
                nd11 = int(line[3:13])
                nd12 = int(line[13:23])
                nd13 = int(line[23:33])
                nd14 = int(line[33:43])
                nd15 = int(line[43:53])
                input_continues = False
                """
                CalculiX uses a different node order in
                input file *.inp and result file *.frd for penta15 (C3D15)
                see notes at hexa20
                elements_penta15[elem] = (
                    nd5, nd6, nd4, nd2, nd3, nd1, nd11, nd12, nd10, nd8,
                    nd9, nd7, nd14, nd15, nd13
                )  # order of the *.inp file
                """
                elements_penta15[elem] = (nd5, nd6, nd4, nd2, nd3, nd1, nd14,
                                          nd15, nd13, nd8, nd9, nd7, nd11,
                                          nd12, nd10)
            elif elemType == 6:
                # C3D10 Calculix --> tetra10 FreeCAD
                # N2, N1, N3, N4, N5, N7, N6, N9, N8, N10
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                nd9 = int(line[83:93])
                nd10 = int(line[93:103])
                elements_tetra10[elem] = (nd2, nd1, nd3, nd4, nd5, nd7, nd6,
                                          nd9, nd8, nd10)
            elif elemType == 7:
                # S3 Calculix --> tria3 FreeCAD
                # N1, N2, N3
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                elements_tria3[elem] = (nd1, nd2, nd3)
            elif elemType == 8:
                # S6 CalculiX --> tria6 FreeCAD
                # N1, N2, N3, N4, N5, N6
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                elements_tria6[elem] = (nd1, nd2, nd3, nd4, nd5, nd6)
            elif elemType == 9:
                # S4 CalculiX --> quad4 FreeCAD
                # N1, N2, N3, N4
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                elements_quad4[elem] = (nd1, nd2, nd3, nd4)
            elif elemType == 10:
                # S8 CalculiX --> quad8 FreeCAD
                # N1, N2, N3, N4, N5, N6, N7, N8
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                nd4 = int(line[33:43])
                nd5 = int(line[43:53])
                nd6 = int(line[53:63])
                nd7 = int(line[63:73])
                nd8 = int(line[73:83])
                elements_quad8[elem] = (nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8)
            elif elemType == 11:
                # B31 CalculiX --> seg2 FreeCAD
                # N1, N2
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                elements_seg2[elem] = (nd1, nd2)
            elif elemType == 12:
                # B32 CalculiX --> seg3 FreeCAD
                # Also D element element number
                # CalculiX uses a different node order in
                # input file *.inp and result file *.frd for seg3 (B32)
                # see notes at hexa20
                # N1, N2 ,N3
                nd1 = int(line[3:13])
                nd2 = int(line[13:23])
                nd3 = int(line[23:33])
                if inout_nodes:
                    for i in range(len(inout_nodes)):
                        if nd1 == int(inout_nodes[i][1]):
                            # fluid inlet node numbering
                            elements_seg3[elem] = (int(inout_nodes[i][2]), nd3,
                                                   nd1)
                        elif nd3 == int(inout_nodes[i][1]):
                            # fluid outlet node numbering
                            elements_seg3[elem] = (nd1, int(inout_nodes[i][2]),
                                                   nd3)
                else:
                    # normal node numbering for D, B32 elements
                    elements_seg3[elem] = (nd1, nd2, nd3)

        # Check if we found new eigenmode line
        if line[5:10] == "PMODE":
            eigentemp = int(line[30:36])
            if eigentemp > eigenmode:
                eigenmode = eigentemp
                mode_eigen_changed = True

        # Check if we found new time step
        if line[4:10] == "1PSTEP":
            mode_time_found = True
        if mode_time_found and (line[2:7] == "100CL"):
            # we found the new time step line
            # !!! be careful here, there is timetemp and timestep!
            # TODO: use more differ names
            timetemp = float(line[13:25])
            if timetemp > timestep:
                timestep = timetemp
                mode_time_changed = True

        # Check if we found displacement section
        if line[5:9] == "DISP":
            mode_disp_found = True
        if mode_disp_found and (line[1:3] == "-1"):
            # we found a displacement line
            elem = int(line[4:13])
            mode_disp_x = float(line[13:25])
            mode_disp_y = float(line[25:37])
            mode_disp_z = float(line[37:49])
            mode_disp[elem] = FreeCAD.Vector(mode_disp_x, mode_disp_y,
                                             mode_disp_z)

        # Check if we found stress section
        if line[5:11] == "STRESS":
            mode_stress_found = True
        if mode_stress_found and (line[1:3] == "-1"):
            # we found a stress line
            elem = int(line[4:13])
            stress_1 = float(line[13:25])
            stress_2 = float(line[25:37])
            stress_3 = float(line[37:49])
            stress_4 = float(line[49:61])
            stress_5 = float(line[61:73])
            stress_6 = float(line[73:85])
            # CalculiX frd files: (Sxx, Syy, Szz, Sxy, Syz, Szx)
            # FreeCAD:            (Sxx, Syy, Szz, Sxy, Sxz, Syz)
            # thus exchange the last two entries
            mode_stress[elem] = (stress_1, stress_2, stress_3, stress_4,
                                 stress_6, stress_5)

        # Check if we found strain section
        if line[5:13] == "TOSTRAIN":
            mode_strain_found = True
        if mode_strain_found and (line[1:3] == "-1"):
            # we found a strain line in the frd file
            elem = int(line[4:13])
            strain_1 = float(line[13:25])
            strain_2 = float(line[25:37])
            strain_3 = float(line[37:49])
            strain_4 = float(line[49:61])
            strain_5 = float(line[61:73])
            strain_6 = float(line[73:85])
            # CalculiX frd files: (Exx, Eyy, Ezz, Exy, Eyz, Ezx)
            # FreeCAD:            (Exx, Eyy, Ezz, Exy, Exz, Eyz)
            # thus exchange the last two entries
            mode_strain[elem] = (strain_1, strain_2, strain_3, strain_4,
                                 strain_6, strain_5)

        # Check if we found an equivalent plastic strain section
        if line[5:7] == "PE":
            mode_peeq_found = True
        if mode_peeq_found and (line[1:3] == "-1"):
            # we found an equivalent plastic strain line
            elem = int(line[4:13])
            peeq = float(line[13:25])
            mode_peeq[elem] = (peeq)

        # Check if we found a temperature section
        if line[5:11] == "NDTEMP":
            mode_temp_found = True
        if mode_temp_found and (line[1:3] == "-1"):
            # we found a temperature line
            elem = int(line[4:13])
            temperature = float(line[13:25])
            mode_temp[elem] = (temperature)

        # Check if we found a mass flow section
        if line[5:11] == "MAFLOW":
            mode_massflow_found = True
        if mode_massflow_found and (line[1:3] == "-1"):
            # we found a mass flow line
            elem = int(line[4:13])
            massflow = float(line[13:25])
            mode_massflow[elem] = (massflow * 1000
                                   )  # convert units to kg/s from t/s
            if inout_nodes:
                for i in range(len(inout_nodes)):
                    if elem == int(inout_nodes[i][1]):
                        node = int(inout_nodes[i][2])
                        # convert units to kg/s from t/s
                        mode_massflow[node] = (massflow * 1000)

        # Check if we found a network pressure section
        if line[5:11] == "STPRES":
            mode_networkpressure_found = True
        if mode_networkpressure_found and (line[1:3] == "-1"):
            # we found a network pressure line
            elem = int(line[4:13])
            networkpressure = float(line[13:25])
            mode_networkpressure[elem] = (networkpressure)
            if inout_nodes:
                for i in range(len(inout_nodes)):
                    if elem == int(inout_nodes[i][1]):
                        node = int(inout_nodes[i][2])
                        mode_networkpressure[node] = (networkpressure)

        # Check if we found the end of a section
        if line[1:3] == "-3":
            end_of_section_found = True

            if nodes_found:
                nodes_found = False
                node_element_section = True

            if elements_found:
                elements_found = False
                node_element_section = True

            if mode_disp_found:
                mode_results["disp"] = mode_disp
                mode_disp = {}
                mode_disp_found = False
                node_element_section = False

            if mode_stress_found:
                mode_results["stress"] = mode_stress
                mode_stress = {}
                mode_stress_found = False
                node_element_section = False

            if mode_strain_found:
                mode_results["strain"] = mode_strain

                mode_strain = {}
                mode_strain_found = False
                node_element_section = False

            if mode_peeq_found:
                mode_results["peeq"] = mode_peeq
                mode_peeq = {}
                mode_peeq_found = False
                node_element_section = False

            if mode_temp_found:
                mode_results["temp"] = mode_temp
                mode_temp = {}
                mode_temp_found = False
                node_element_section = False

            if mode_massflow_found:
                mode_results["mflow"] = mode_massflow
                mode_massflow = {}
                mode_massflow_found = False
                node_element_section = False

            if mode_networkpressure_found:
                mode_results["npressure"] = mode_networkpressure
                mode_networkpressure_found = False
                mode_networkpressure = {}
                node_element_section = False
            """
            print("---- End of Section --> Mode_Results may be changed ----")
            for key in sorted(mode_results.keys()):
                if key is "number" or key is "time":
                    print(key + " --> " + str(mode_results[key]))
                else:
                    print(key + " --> " + str(len(mode_results[key])))
            print("----Mode_Results----\n")
            """

        # Check if we found the end of frd data
        if line[1:5] == "9999":
            end_of_frd_data_found = True

        if (mode_eigen_changed or mode_time_changed or end_of_frd_data_found) \
                and end_of_section_found \
                and not node_element_section:
            """
            print("\n\n----Append mode_results to results")
            print(line)
            for key in sorted(mode_results.keys()):
                if key is "number" or key is "time":
                    print(key + " --> " + str(mode_results[key]))
                else:
                    print(key + " --> " + str(len(mode_results[key])))
            print("----Append Mode_Results----\n")
            """

            # append mode_results to results and reset mode_result
            results.append(mode_results)
            mode_results = {}
            # https://forum.freecadweb.org/viewtopic.php?f=18&t=32649&start=10#p274686
            mode_results["number"] = float("NaN")
            mode_results["time"] = float("NaN")
            end_of_section_found = False

        # on changed --> write changed values in mode_result
        # will be the first to do on an empty mode_result
        if mode_eigen_changed:
            mode_results["number"] = eigenmode
            mode_eigen_changed = False

        if mode_time_changed:
            mode_results["time"] = timestep
            # mode_results["time"] = 0  # Don't return time if static  # Why?
            mode_time_found = False
            mode_time_changed = False

        # here we are in the indent of loop for every line in frd file
        # do not add a print here :-)

    # close frd file if loop over all lines is finished
    frd_file.close()
    """
    # debug prints and checks with the read data
    print("\n\n----RESULTS values begin----")
    print(len(results))
    # print("\n")
    # print(results)
    print("----RESULTS values end----\n\n")
    """

    if not inout_nodes:
        if results:
            if "mflow" in results[0] or "npressure" in results[0]:
                Console.PrintError(
                    "We have mflow or npressure, but no inout_nodes file.\n")
    if not nodes:
        Console.PrintError("FEM: No nodes found in Frd file.\n")

    return {
        "Nodes": nodes,
        "Seg2Elem": elements_seg2,
        "Seg3Elem": elements_seg3,
        "Tria3Elem": elements_tria3,
        "Tria6Elem": elements_tria6,
        "Quad4Elem": elements_quad4,
        "Quad8Elem": elements_quad8,
        "Tetra4Elem": elements_tetra4,
        "Tetra10Elem": elements_tetra10,
        "Hexa8Elem": elements_hexa8,
        "Hexa20Elem": elements_hexa20,
        "Penta6Elem": elements_penta6,
        "Penta15Elem": elements_penta15,
        "Results": results
    }
Пример #26
0
 def Activated(self):
     # check that the Fasteners WB has been loaded before:
     if not 'FSChangeParams' in Gui.listCommands():
         Gui.activateWorkbench('FastenersWorkbench')
         Gui.activateWorkbench('Assembly4Workbench')
     # if something is selected
     container = None
     fsClass = self.FSclass
     fsType = None
     selObj = None
     if len(Gui.Selection.getSelection()) == 1:
         selObj = Gui.Selection.getSelection()[0]
         # if it's a container, we'll put it there
         if selObj.TypeId == 'App::Part':
             container = selObj
         # if a fastener is selected, we duplicate it
         elif isFastener(selObj):
             try:
                 fs = screwTables[selObj.type][0]
                 if fs in ['Screw', 'Nut', 'Washer']:
                     fsClass = fs
                     fsType = selObj.type
                     container = selObj.getParentGeoFeatureGroup()
             except:
                 FCC.PrintMessage(
                     "Selected object doesn't seem to be a valid fastener, ignoring\n"
                 )
     # create the fastener
     newFastener = App.ActiveDocument.addObject("Part::FeaturePython",
                                                fsClass)
     # if a previous fastener was selected, we match its parameters
     if fsType:
         FS.FSScrewObject(newFastener, fsType, None)
         newFastener.recompute()
         newFastener.diameter = selObj.diameter
         newFastener.recompute()
         if hasattr(newFastener, 'length'):
             try:
                 newFastener.length = selObj.length
             except:
                 FCC.PrintMessage("Length \"" + selObj.length +
                                  "\" is not available, ignoring\n")
     # we create a new fastener as asked
     else:
         if fsClass == 'Screw':
             FS.FSScrewObject(newFastener, 'ISO7045', None)
         elif fsClass == 'Nut':
             FS.FSScrewObject(newFastener, 'ISO4032', None)
         elif fsClass == 'Washer':
             FS.FSScrewObject(newFastener, 'ISO7089', None)
         elif fsClass == 'ThreadedRod':
             FS.FSThreadedRodObject(newFastener, None)
     # make the Proxy and stuff
     newFastener.Label = newFastener.Proxy.itemText
     FS.FSViewProviderTree(newFastener.ViewObject)
     # if a container was selected, put it there
     if container:
         container.addObject(newFastener)
     # apply custom Asm4 colours:
     try:
         newFastener.ViewObject.ShapeColor = self.FScolor[fsClass]
     except:
         FCC.PrintMessage("unknown fastener type \"" + str(fsClass) +
                          "\", ignoring\n")
     # add AttachmentEngine
     # oooops, no, creates problems because it creates an AttachmentOffset property that collides with Asm4
     # newFastener.addExtension("Part::AttachExtensionPython")
     # ... and select it
     newFastener.recompute()
     Gui.Selection.clearSelection()
     Gui.Selection.addSelection(newFastener)
Пример #27
0
    def __init__(self):
        # self.base = QtGui.QWidget()
        # self.form = self.base
        self.form = QtGui.QWidget()
        self.form.setWindowIcon(QtGui.QIcon(iconFile))
        self.form.setWindowTitle('Attach a Fastener in the assembly')

        # get the current active document to avoid errors if user changes tab
        self.activeDoc = App.activeDocument()
        # the parent (top-level) assembly is the App::Part called Model (hard-coded)
        self.rootAssembly = Asm4.getAssembly()
        # has been checked before calling
        self.selectedFastener = getSelectionFS()

        # check where the fastener was attached to
        (self.old_Parent, separator,
         self.old_parentLCS) = self.selectedFastener.AttachedTo.partition('#')
        # get and store the Placement's current ExpressionEngine:
        self.old_EE = Asm4.placementEE(self.selectedFastener.ExpressionEngine)
        if hasattr(self.selectedFastener, 'AttachmentOffset'):
            self.old_AO = self.selectedFastener.AttachmentOffset
        else:
            self.old_AO = None

        # Now we can draw the UI
        self.drawUI()
        self.initUI()
        # now self.parentList and self.parentTable are available

        # find all the linked parts in the assembly
        for obj in self.activeDoc.findObjects("App::Link"):
            if self.rootAssembly.getObject(obj.Name) is not None and hasattr(
                    obj.LinkedObject, 'isDerivedFrom'):
                linkedObj = obj.LinkedObject
                FCC.PrintMessage("found link to " + linkedObj.Name)
                if linkedObj.isDerivedFrom(
                        'App::Part') or linkedObj.isDerivedFrom(
                            'PartDesign::Body'):
                    # add to the object table holding the objects ...
                    self.parentTable.append(obj)
                    # ... and add to the drop-down combo box with the assembly tree's parts
                    objIcon = linkedObj.ViewObject.Icon
                    objText = Asm4.labelName(obj)
                    self.parentList.addItem(objIcon, objText, obj)

        # decode the old ExpressionEngine
        # if the decode is unsuccessful, old_Expression is set to False
        # and old_attPart and old_attLCS are set to 'None'
        old_Parent = ''
        old_parentPart = ''
        old_parentLCS = ''
        if self.old_EE and self.old_Parent:
            (old_Parent, old_parentPart,
             old_parentLCS) = self.splitExpressionFastener(
                 self.old_EE, self.old_Parent)

        # find the oldPart in the part list...
        parent_index = 1
        if old_Parent == 'Parent Assembly':
            parent_found = True
        else:
            parent_found = False
            for item in self.parentTable[1:]:
                if item.Name == old_Parent:
                    parent_found = True
                    break
                else:
                    parent_index += 1
        if not parent_found:
            parent_index = 0
        self.parentList.setCurrentIndex(parent_index)
        # this should have triggered self.getPartLCS() to fill the LCS list

        # find the oldLCS in the list of LCS of the linked part...
        lcs_found = []
        lcs_found = self.attLCSlist.findItems(old_parentLCS,
                                              QtCore.Qt.MatchExactly)
        # may-be it was renamed, see if we can find it as (name)
        if not lcs_found:
            lcs_found = self.attLCSlist.findItems('(' + old_parentLCS + ')',
                                                  QtCore.Qt.MatchContains)
        if lcs_found:
            # ... and select it
            self.attLCSlist.setCurrentItem(lcs_found[0])

        Gui.Selection.addObserver(self, 0)
Пример #28
0
def get_z88_element_type(
    femmesh,
    femelement_table=None
):
    import femmesh.meshtools as FemMeshTools
    if not femmesh:
        Console.PrintError("Error: No femmesh.\n")
    if not femelement_table:
        Console.PrintError("The femelement_table need to be calculated.\n")
        femelement_table = FemMeshTools.get_femelement_table(femmesh)
    # in some cases lowest key in femelement_table is not [1]
    for elem in sorted(femelement_table):
        elem_length = len(femelement_table[elem])
        Console.PrintLog("Node count of first element: {}\n".format(elem_length))
        break  # break after the first elem
    if FemMeshTools.is_solid_femmesh(femmesh):
        if femmesh.TetraCount == femmesh.VolumeCount:
            if elem_length == 4:
                return 17
            elif elem_length == 10:
                return 16
            else:
                Console.PrintMessage("Tetra with neither 4 nor 10 nodes.\n")
        elif femmesh.HexaCount == femmesh.VolumeCount:
            if elem_length == 8:
                return 1
            elif elem_length == 20:
                return 10
            else:
                Console.PrintError("Hexa with neither 8 nor 20 nodes.\n")
                return 0
        else:
            Console.PrintError("no tetra, no hexa or Mixed Volume Elements.\n")
    elif FemMeshTools.is_face_femmesh(femmesh):
        if femmesh.TriangleCount == femmesh.FaceCount:
            if elem_length == 3:
                Console.PrintError("tria3mesh, not supported by Z88.\n")
                return 0
            elif elem_length == 6:
                return 24
            else:
                Console.PrintError("Tria with neither 3 nor 6 nodes.\n")
                return 0
        elif femmesh.QuadrangleCount == femmesh.FaceCount:
            if elem_length == 4:
                Console.PrintError("quad4mesh, not supported by Z88.\n")
                return 0
            elif elem_length == 8:
                return 23
            else:
                Console.PrintError("Quad with neither 4 nor 8 nodes.\n")
                return 0
        else:
            Console.PrintError("no tria, no quad\n")
            return 0
    elif FemMeshTools.is_edge_femmesh(femmesh):
        Console.PrintMessage("Edge femmesh will be exported as 3D truss element nr 4.\n")
        return 4
    else:
        Console.PrintError("Neither edge nor face nor solid femmesh.\n")
        return 0
    return 0
Пример #29
0
def importFrd(filename, analysis=None, result_name_prefix=""):
    from . import importToolsFem
    import ObjectsFem

    if analysis:
        doc = analysis.Document
    else:
        doc = FreeCAD.ActiveDocument

    m = read_frd_result(filename)
    result_mesh_object = None
    res_obj = None

    if len(m["Nodes"]) > 0:
        mesh = importToolsFem.make_femmesh(m)
        result_mesh_object = ObjectsFem.makeMeshResult(doc, "ResultMesh")
        result_mesh_object.FemMesh = mesh
        res_mesh_is_compacted = False
        nodenumbers_for_compacted_mesh = []

        number_of_increments = len(m["Results"])
        Console.PrintLog("Increments: " + str(number_of_increments) + "\n")
        if len(m["Results"]) > 0:
            for result_set in m["Results"]:
                if "number" in result_set:
                    eigenmode_number = result_set["number"]
                else:
                    eigenmode_number = 0
                step_time = result_set["time"]
                step_time = round(step_time, 2)
                if eigenmode_number > 0:
                    results_name = ("{}Mode{}_Results".format(
                        result_name_prefix, eigenmode_number))
                elif number_of_increments > 1:
                    results_name = ("{}Time{}_Results".format(
                        result_name_prefix, step_time))
                else:
                    results_name = ("{}Results".format(result_name_prefix))

                res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
                res_obj.Mesh = result_mesh_object
                res_obj = importToolsFem.fill_femresult_mechanical(
                    res_obj, result_set)
                if analysis:
                    analysis.addObject(res_obj)

                # complementary result object calculations
                import femresult.resulttools as restools
                import femtools.femutils as femutils
                if not res_obj.MassFlowRate:
                    # information 1:
                    # only compact result if not Flow 1D results
                    # compact result object, workaround for bug 2873
                    # https://www.freecadweb.org/tracker/view.php?id=2873
                    # information 2:
                    # if the result data has multiple result sets there will be multiple result objs
                    # they all will use one mesh obj
                    # on the first res obj fill the mesh obj will be compacted, thus
                    # it does not need to be compacted on further result sets
                    # but NodeNumbers need to be compacted for every result set (res object fill)
                    # example frd file: https://forum.freecadweb.org/viewtopic.php?t=32649#p274291
                    if res_mesh_is_compacted is False:
                        # first result set, compact FemMesh and NodeNumbers
                        res_obj = restools.compact_result(res_obj)
                        res_mesh_is_compacted = True
                        nodenumbers_for_compacted_mesh = res_obj.NodeNumbers
                    else:
                        # all other result sets, do not compact FemMesh, only set NodeNumbers
                        res_obj.NodeNumbers = nodenumbers_for_compacted_mesh

                # fill DisplacementLengths
                res_obj = restools.add_disp_apps(res_obj)
                # fill vonMises
                res_obj = restools.add_von_mises(res_obj)
                if res_obj.getParentGroup():
                    has_reinforced_mat = False
                    for obj in res_obj.getParentGroup().Group:
                        if obj.isDerivedFrom("App::MaterialObjectPython") \
                                and femutils.is_of_type(obj, "Fem::MaterialReinforced"):
                            has_reinforced_mat = True
                            restools.add_principal_stress_reinforced(res_obj)
                            break
                    if has_reinforced_mat is False:
                        # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                        res_obj = restools.add_principal_stress_std(res_obj)
                else:
                    # if a pure frd file was opened no analysis and thus no parent group
                    # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear
                    res_obj = restools.add_principal_stress_std(res_obj)
                # fill Stats
                res_obj = restools.fill_femresult_stats(res_obj)

        else:
            error_message = (
                "Nodes, but no results found in frd file. "
                "It means there only is a mesh but no results in frd file. "
                "Usually this happens for: \n"
                "- analysis type 'NOANALYSIS'\n"
                "- if CalculiX returned no results "
                "(happens on nonpositive jacobian determinant in at least one element)\n"
                "- just no frd results where requestet in input file "
                "(neither 'node file' nor 'el file' in output section')\n")
            Console.PrintMessage(error_message)

        # create a result obj, even if we have no results but a result mesh in frd file
        # see error message above for more information
        if not res_obj:
            if result_name_prefix:
                results_name = ("{}_Results".format(result_name_prefix))
            else:
                results_name = ("Results".format(result_name_prefix))
            res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
            res_obj.Mesh = result_mesh_object
            # TODO, node numbers in result obj could be set
            if analysis:
                analysis.addObject(res_obj)

        if FreeCAD.GuiUp:
            if analysis:
                import FemGui
                FemGui.setActiveAnalysis(analysis)
            doc.recompute()

    else:
        Console.PrintError(
            "Problem on frd file import. No nodes found in frd file.\n")
        # None will be returned
        # or would it be better to raise an exception if there are not even nodes in frd file

    return res_obj
Пример #30
0
def read_fenics_mesh_xml(xmlfilename):
    """
        Returns element dictionary to be evaluated by make_femmesh later
    """

    Fenics_to_FreeCAD_dict = {
        "triangle": "tria3",
        "tetrahedron": "tetra4",
        "hexahedron": "hexa8",
        "interval": "seg2",
        "quadrilateral": "quad4",
    }

    def read_mesh_block(mesh_block):
        """
            Reading mesh block from XML file.
            The mesh block only contains cells and vertices.
        """
        dim = int(mesh_block.get("dim"))
        cell_type = mesh_block.get("celltype")

        vertex_size = 0

        Console.PrintLog("Mesh dimension: %d\n" % (dim, ))
        Console.PrintLog("Mesh cell type: %s\n" % (cell_type, ))

        # every cell type contains a dict with key=dimension and value=number

        cells_parts_dim = {
            "point": {
                0: 1
            },
            "interval": {
                0: 2,
                1: 1
            },
            "triangle": {
                0: 3,
                1: 3,
                2: 1
            },
            "tetrahedron": {
                0: 4,
                1: 6,
                2: 4,
                3: 1
            },
            "quadrilateral": {
                0: 4,
                1: 4,
                2: 1
            },
            "hexahedron": {
                0: 8,
                1: 12,
                2: 6,
                3: 1
            }
        }

        find_vertices = mesh_block.find("vertices")
        find_cells = mesh_block.find("cells")

        nodes_dict = {}
        cell_dict = {}

        if find_vertices is None:
            Console.PrintWarning("No vertices found!\n")
        else:
            vertex_size = int(find_vertices.attrib.get("size"))
            Console.PrintLog("Reading %d vertices\n" % (vertex_size, ))

            for vertex in find_vertices:
                ind = int(vertex.get("index"))

                if vertex.tag.lower() == "vertex":
                    [node_x, node_y, node_z] = [
                        float(vertex.get(coord, 0.))
                        for coord in ["x", "y", "z"]
                    ]

                    nodes_dict[ind + 1] = FreeCAD.Vector(
                        node_x, node_y, node_z)
                    # increase node index by one, since fenics starts at 0, FreeCAD at 1
                    # print("%d %f %f %f" % (ind, node_x, node_y, node_z))
                else:
                    Console.PrintWarning("found strange vertex tag: %s\n" %
                                         (vertex.tag, ))

        if find_cells is None:
            Console.PrintWarning("No cells found!\n")
        else:
            Console.PrintLog("Reading %d cells\n" %
                             (int(find_cells.attrib.get("size")), ))
            for cell in find_cells:
                ind = int(cell.get("index"))

                if cell.tag.lower() != cell_type.lower():
                    Console.PrintWarning(
                        "Strange mismatch between cell type {} and cell tag {}\n"
                        .format(cell_type, cell.tag.lower()))
                num_vertices = cells_parts_dim[cell_type][0]

                vtupel = tuple([
                    int(cell.get("v" + str(vnum))) + 1
                    for vnum in range(num_vertices)
                ])
                # generate "v0", "v1", ... from dimension lookup table
                # increase numbers by one to match FC numbering convention

                cell_dict[ind + 1] = vtupel

                # valtupel = tuple([ind] + list(vtupel))
                # print(("%d " + ("%d "*len(vtupel))) % valtupel)

        return (nodes_dict, cell_dict, cell_type, dim)

    def generate_lower_dimensional_structures(nodes, cell_dict, cell_type,
                                              dim):
        def correct_volume_det(element_dict):
            """
                Checks whether the cell elements
                all have the same volume (<0?)
                sign (is necessary to avoid negative
                Jacobian errors).
                Works only with tet4 and tri3 elements at the moment
            """
            if dim == 3:
                for (ind, tet) in list(element_dict["tetra4"].items()):
                    v0 = nodes[tet[0]]
                    v1 = nodes[tet[1]]
                    v2 = nodes[tet[2]]
                    v3 = nodes[tet[3]]
                    a = v1 - v0
                    b = v2 - v0
                    c = v3 - v0
                    if a.dot(b.cross(c)) > 0:
                        element_dict["tetra4"][ind] = (tet[1], tet[0], tet[2],
                                                       tet[3])
            if dim == 2:
                nz = FreeCAD.Vector(0., 0., 1.)
                for (ind, tria) in list(element_dict["tria3"].items()):
                    v0 = nodes[tria[0]]
                    v1 = nodes[tria[1]]
                    v2 = nodes[tria[2]]
                    a = v1 - v0
                    b = v2 - v0
                    if nz.dot(a.cross(b)) < 0:
                        element_dict["tria3"][ind] = (tria[1], tria[0],
                                                      tria[2])

        element_dict = {}
        element_counter = {}

        # TODO: remove upper level lookup
        for (key, val) in list(Fenics_to_FreeCAD_dict.items()):
            element_dict[val] = {}
            element_counter[
                key] = 0  # count every distinct element and sub element type

        def addtupletodict(di, tpl, counter):
            sortedtpl = tuple(sorted(tpl))
            if di.get(sortedtpl) is None:
                di[sortedtpl] = counter
                counter += 1
            return counter

        def invertdict(dic):
            invdic = {}
            for (key, it) in list(dic.items()):
                invdic[it] = key
            return invdic

        num_vert_dict = {
            "interval": 2,
            "triangle": 3,
            "tetrahedron": 4,
            "hexahedron": 8,
            "quadrilateral": 4
        }
        lower_dims_dict = {
            "interval": [],
            "triangle": ["interval"],
            "tetrahedron": ["triangle", "interval"],
            "hexahedron": ["quadrilateral", "interval"],
            "quadrilateral": ["interval"]
        }

        # generate cell list from file
        # read vertex list from cells
        # generate lower dimensional objects in mesh from cell

        for (cell_index, cell) in list(cell_dict.items()):
            cell_lower_dims = lower_dims_dict[cell_type]
            element_counter[cell_type] += 1
            element_dict[Fenics_to_FreeCAD_dict[cell_type]][
                cell] = element_counter[cell_type]
            for ld in cell_lower_dims:
                for vertextuple in itertools.combinations(
                        cell, num_vert_dict[ld]):
                    element_counter[ld] = addtupletodict(
                        element_dict[Fenics_to_FreeCAD_dict[ld]], vertextuple,
                        element_counter[ld])

        length_counter = len(nodes)  # maintain distinct counting values
        # print("nodes")
        # print("len & len counter", length_counter)
        for (key, val_dict) in list(element_dict.items()):
            # to ensure distinct indices for FreeCAD
            # print("key: ", key)
            for (vkey, it) in list(val_dict.items()):
                val_dict[
                    vkey] = it + length_counter  # maintain distinct element numbers
            len_val_dict = len(val_dict)
            if len_val_dict > 0:
                length_counter += len_val_dict + 1  # only if preceding list is not empty
            # print("len: ", len_val_dict)
            # print("lencounter: ", length_counter)
            # inverse of the dict (dict[key] = val -> dict[val] = key)
            element_dict[key] = invertdict(val_dict)

        correct_volume_det(element_dict)  # corrects negative determinants

        return element_dict  # returns complete element dictionary

    nodes = {}
    element_dict = {}
    # TODO: remove two times initialization
    for val in list(Fenics_to_FreeCAD_dict.values()):
        element_dict[val] = {}

    tree = ET.parse(xmlfilename)
    root = tree.getroot()

    if root.tag.lower() != "dolfin":
        Console.PrintWarning("Strange root tag, should be dolfin!\n")

    find_mesh = root.find("mesh")
    if find_mesh is not None:  # these are consistency checks of the XML structure
        Console.PrintMessage("Mesh found\n")
        (nodes, cells_dict, cell_type, dim) = read_mesh_block(find_mesh)
        element_dict = generate_lower_dimensional_structures(
            nodes, cells_dict, cell_type, dim)
        Console.PrintMessage("Show min max element dict")
        for (elm, numbers) in list(element_dict.items()):
            lst = sorted(list(numbers.items()), key=lambda x: x[0])
            if lst != []:
                Console.PrintWarning(elm, " min: ", lst[0], " max: ", lst[-1],
                                     "\n")
    else:
        Console.PrintError("No mesh found")

    if root.find("data") is not None:
        Console.PrintLog("Internal mesh data found\n")

    return {
        "Nodes": nodes,
        "Seg2Elem": element_dict["seg2"],
        "Seg3Elem": {},
        "Tria3Elem": element_dict["tria3"],
        "Tria6Elem": {},
        "Quad4Elem": element_dict["quad4"],
        "Quad8Elem": {},
        "Tetra4Elem": element_dict["tetra4"],
        "Tetra10Elem": {},
        "Hexa8Elem": {},
        "Hexa20Elem": {},
        "Penta6Elem": {},
        "Penta15Elem": {}
    }