Пример #1
0
 def change_label_name(self, uid, name):
     """Change the name of component with uid."""
     entry, _ = uid.split('.')
     entry_parts = entry.split(':')
     if len(entry_parts) == 4:  # first label at root
         j = 1
         k = None
     elif len(entry_parts) == 5:  # part is a component of label at root
         j = int(entry_parts[3])  # number of label at root
         k = int(entry_parts[4])  # component number
     shape_tool = XCAFDoc_DocumentTool_ShapeTool(self.doc.Main())
     color_tool = XCAFDoc_DocumentTool_ColorTool(self.doc.Main())
     labels = TDF_LabelSequence()  # labels at root of self.doc
     shape_tool.GetShapes(labels)
     label = labels.Value(j)
     comps = TDF_LabelSequence()  # Components of root_label
     subchilds = False
     is_assy = shape_tool.GetComponents(label, comps, subchilds)
     target_label = comps.Value(k)
     self.setLabelName(target_label, name)
     shape_tool.UpdateAssemblies()
     print(f"Name {name} set for part with uid = {uid}.")
     self.parse_doc()
Пример #2
0
class StepAnalyzer():
    """A class that analyzes the structure of an OCAF document."""
    def __init__(self, document=None, filename=None):
        """Supply one or the other: document or STEP filename."""

        self.uid = 1
        self.indent = 0
        self.output = ""
        self.fname = filename
        if filename:
            self.doc = self.read_file(filename)
        elif document:
            self.doc = document
            self.shape_tool = XCAFDoc_DocumentTool_ShapeTool(self.doc.Main())
        else:
            print("Supply one or the other: document or STEP filename.")

    def read_file(self, fname):
        """Read STEP file and return <TDocStd_Document>."""

        # Create the application, empty document and shape_tool
        doc = TDocStd_Document(TCollection_ExtendedString("STEP"))
        app = XCAFApp_Application_GetApplication()
        app.NewDocument(TCollection_ExtendedString("MDTV-XCAF"), doc)
        self.shape_tool = XCAFDoc_DocumentTool_ShapeTool(doc.Main())
        self.shape_tool.SetAutoNaming(True)

        # Read file and return populated doc
        step_reader = STEPCAFControl_Reader()
        step_reader.SetColorMode(True)
        step_reader.SetLayerMode(True)
        step_reader.SetNameMode(True)
        step_reader.SetMatMode(True)
        status = step_reader.ReadFile(fname)
        if status == IFSelect_RetDone:
            step_reader.Transfer(doc)
        return doc

    def dump(self):
        """Return assembly structure in indented outline form.

        Format of lines:
        Component Name [entry] => Referred Label Name [entry]
        Components are shown indented w/r/t line above."""

        if self.fname:
            self.output += f"Assembly structure of file: {self.fname}\n\n"
        else:
            self.output += "Assembly structure of doc:\n\n"
        self.indent = 0

        # Find root label of step doc
        labels = TDF_LabelSequence()
        self.shape_tool.GetShapes(labels)
        nbr = labels.Length()
        rootlabel = labels.Value(1)  # First label at root

        # Get information from root label
        name = rootlabel.GetLabelName()
        entry = rootlabel.EntryDumpToString()
        is_assy = self.shape_tool.IsAssembly(rootlabel)
        if is_assy:
            # If 1st label at root holds an assembly, it is the Top Assy.
            # Through this label, the entire assembly is accessible.
            # There is no need to explicitly examine other labels at root.
            self.output += f"{self.uid}\t[{entry}] {name}\t"
            self.uid += 1
            self.indent += 2
            top_comps = TDF_LabelSequence()  # Components of Top Assy
            subchilds = False
            is_assy = self.shape_tool.GetComponents(rootlabel, top_comps,
                                                    subchilds)
            self.output += f"Number of labels at root = {nbr}\n"
            if top_comps.Length():
                self.find_components(top_comps)
        return self.output

    def find_components(self, comps):
        """Discover components from comps (LabelSequence) of an assembly.

        Components of an assembly are, by definition, references which refer
        to either a shape or another assembly. Components are essentially
        'instances' of the referred shape or assembly, and carry a location
        vector specifing the location of the referred shape or assembly.
        """
        for j in range(comps.Length()):
            c_label = comps.Value(j + 1)  # component label <class 'TDF_Label'>
            c_name = c_label.GetLabelName()
            c_entry = c_label.EntryDumpToString()
            ref_label = TDF_Label()  # label of referred shape (or assembly)
            is_ref = self.shape_tool.GetReferredShape(c_label, ref_label)
            if is_ref:  # just in case all components are not references
                ref_entry = ref_label.EntryDumpToString()
                ref_name = ref_label.GetLabelName()
                indent = "\t" * self.indent
                self.output += f"{self.uid}{indent}[{c_entry}] {c_name}"
                self.output += f" => [{ref_entry}] {ref_name}\n"
                self.uid += 1
                if self.shape_tool.IsAssembly(ref_label):
                    self.indent += 1
                    ref_comps = TDF_LabelSequence()  # Components of Assy
                    subchilds = False
                    _ = self.shape_tool.GetComponents(ref_label, ref_comps,
                                                      subchilds)
                    if ref_comps.Length():
                        self.find_components(ref_comps)

        self.indent -= 1
Пример #3
0
    def parse_doc(self):
        """Generate new part_dict & label_dict.

        part_dict (dict of dicts) is used primarily for 3D display
        part_dict = {uid: {'shape': ,
                            'name': ,
                            'color': ,
                            'loc': }}
        label_dict (dict of dicts) is used primarily for tree view display
        label_dict = {uid:   {'entry': ,
                            'name': ,
                            'parent_uid': ,
                            'ref_entry': ,
                            'is_assy': }}
        """

        # Initialize dictionaries & list
        self._share_dict = {'0:1:1': 0}  # {entry: ser_nbr}
        self.part_dict = {}
        self.label_dict = {}
        # Temporary use during unpacking
        self.parent_uid_stack = []  # uid of parent (topmost first)
        self.assy_entry_stack = ['0:1:1']  # [entries of containing assemblies]
        self.assy_loc_stack = []  # applicable <TopLoc_Location> locations

        shape_tool = XCAFDoc_DocumentTool_ShapeTool(self.doc.Main())
        color_tool = XCAFDoc_DocumentTool_ColorTool(self.doc.Main())

        # Find root label of self.doc
        labels = TDF_LabelSequence()
        shape_tool.GetShapes(labels)
        root_label = labels.Value(1)  # First label at root
        nbr = labels.Length()  # number of labels at root
        logger.debug('Number of labels at doc root : %i', nbr)
        # Get root label information
        # The first label at root holds an assembly, it is the Top Assy.
        # Through this label, the entire assembly is accessible.
        # There is no need to explicitly examine other labels at root.
        root_name = root_label.GetLabelName()
        root_entry = root_label.EntryDumpToString()
        root_uid = self.get_uid_from_entry(root_entry)
        loc = shape_tool.GetLocation(root_label)  # <TopLoc_Location>
        self.assy_loc_stack.append(loc)
        self.assy_entry_stack.append(root_entry)
        self.label_dict = {
            root_uid: {
                'entry': root_entry,
                'name': root_name,
                'parent_uid': None,
                'ref_entry': None,
                'is_assy': True
            }
        }
        self.parent_uid_stack.append(root_uid)
        top_comps = TDF_LabelSequence()  # Components of Top Assy
        subchilds = False
        is_assy = shape_tool.GetComponents(root_label, top_comps, subchilds)
        if top_comps.Length():  # if is_assy:
            logger.debug("")
            logger.debug("Parsing components of label entry %s)", root_entry)
            self.parse_components(top_comps, shape_tool, color_tool)
        else:
            print("Something is wrong.")
Пример #4
0
    def read_file(self):
        """Build self.tree (treelib.Tree()) containing CAD data read from a step file.

        Each node of self.tree contains the following:
        (Name, UID, ParentUID, {Data}) where the Data keys are:
        'a' (isAssy?), 'l' (TopLoc_Location), 'c' (Quantity_Color), 's' (TopoDS_Shape)
        """
        logger.info("Reading STEP file")
        doc = TDocStd_Document(TCollection_ExtendedString("STEP"))

        # Create the application
        app = XCAFApp_Application_GetApplication()
        app.NewDocument(TCollection_ExtendedString("MDTV-CAF"), doc)

        # Get root shapes
        shape_tool = XCAFDoc_DocumentTool_ShapeTool(doc.Main())
        shape_tool.SetAutoNaming(True)
        self.color_tool = XCAFDoc_DocumentTool_ColorTool(doc.Main())
        layer_tool = XCAFDoc_DocumentTool_LayerTool(doc.Main())
        l_materials = XCAFDoc_DocumentTool_MaterialTool(doc.Main())

        step_reader = STEPCAFControl_Reader()
        step_reader.SetColorMode(True)
        step_reader.SetLayerMode(True)
        step_reader.SetNameMode(True)
        step_reader.SetMatMode(True)

        status = step_reader.ReadFile(self.filename)
        if status == IFSelect_RetDone:
            logger.info("Transfer doc to STEPCAFControl_Reader")
            step_reader.Transfer(doc)

        # Test round trip by writing doc back to another file.
        logger.info("Doing a 'short-circuit' Round Trip test")
        doctype = type(doc)  # <class 'OCC.Core.TDocStd.TDocStd_Document'>
        logger.info(f"Writing {doctype} back to another STEP file")
        self.testRTStep(doc)

        # Save doc to file (for educational purposes) (not working yet)
        logger.debug("Saving doc to file")
        savefilename = TCollection_ExtendedString('../doc.txt')
        app.SaveAs(doc, savefilename)

        labels = TDF_LabelSequence()
        color_labels = TDF_LabelSequence()

        shape_tool.GetShapes(labels)
        self.shape_tool = shape_tool
        logger.info('Number of labels at root : %i' % labels.Length())
        try:
            label = labels.Value(1)  # First label at root
        except RuntimeError:
            return
        name = self.getName(label)
        logger.info('Name of root label: %s' % name)
        isAssy = shape_tool.IsAssembly(label)
        logger.info("First label at root holds an assembly? %s" % isAssy)
        if isAssy:
            # If first label at root holds an assembly, it is the Top Assembly.
            # Through this label, the entire assembly is accessible.
            # No need to examine other labels at root explicitly.
            topLoc = TopLoc_Location()
            topLoc = shape_tool.GetLocation(label)
            self.assyLocStack.append(topLoc)
            entry = label.EntryDumpToString()
            logger.debug("Entry: %s" % entry)
            logger.debug("Top assy name: %s" % name)
            # Create root node for top assy
            newAssyUID = self.getNewUID()
            self.tree.create_node(name, newAssyUID, None, {
                'a': True,
                'l': None,
                'c': None,
                's': None
            })
            self.assyUidStack.append(newAssyUID)
            topComps = TDF_LabelSequence()  # Components of Top Assy
            subchilds = False
            isAssy = shape_tool.GetComponents(label, topComps, subchilds)
            logger.debug("Is Assembly? %s" % isAssy)
            logger.debug("Number of components: %s" % topComps.Length())
            logger.debug("Is Reference? %s" % shape_tool.IsReference(label))
            if topComps.Length():
                self.findComponents(label, topComps)
        else:
            # Labels at root can hold solids or compounds (which are 'crude' assemblies)
            # Either way, we will need to create a root node in self.tree
            newAssyUID = self.getNewUID()
            self.tree.create_node(os.path.basename(self.filename), newAssyUID,
                                  None, {
                                      'a': True,
                                      'l': None,
                                      'c': None,
                                      's': None
                                  })
            self.assyUidStack = [newAssyUID]
            for j in range(labels.Length()):
                label = labels.Value(j + 1)
                name = self.getName(label)
                isAssy = shape_tool.IsAssembly(label)
                logger.debug("Label %i is assembly?: %s" % (j + 1, isAssy))
                shape = shape_tool.GetShape(label)
                color = self.getColor(shape)
                isSimpleShape = self.shape_tool.IsSimpleShape(label)
                logger.debug("Is Simple Shape? %s" % isSimpleShape)
                shapeType = shape.ShapeType()
                logger.debug("The shape type is: %i" % shapeType)
                if shapeType == 0:
                    logger.debug(
                        "The shape type is OCC.Core.TopAbs.TopAbs_COMPOUND")
                    topo = TopologyExplorer(shape)
                    #topo = aocutils.topology.Topo(shape)
                    logger.debug("Nb of compounds : %i" %
                                 topo.number_of_compounds())
                    logger.debug("Nb of solids : %i" % topo.number_of_solids())
                    logger.debug("Nb of shells : %i" % topo.number_of_shells())
                    newAssyUID = self.getNewUID()
                    for i, solid in enumerate(topo.solids()):
                        name = "P%s" % str(i + 1)
                        self.tree.create_node(name, self.getNewUID(),
                                              self.assyUidStack[-1], {
                                                  'a': False,
                                                  'l': None,
                                                  'c': color,
                                                  's': solid
                                              })
                elif shapeType == 2:
                    logger.debug(
                        "The shape type is OCC.Core.TopAbs.TopAbs_SOLID")
                    self.tree.create_node(name, self.getNewUID(),
                                          self.assyUidStack[-1], {
                                              'a': False,
                                              'l': None,
                                              'c': color,
                                              's': shape
                                          })
                elif shapeType == 3:
                    logger.debug(
                        "The shape type is OCC.Core.TopAbs.TopAbs_SHELL")
                    self.tree.create_node(name, self.getNewUID(),
                                          self.assyUidStack[-1], {
                                              'a': False,
                                              'l': None,
                                              'c': color,
                                              's': shape
                                          })
        return True