예제 #1
0
def write_stl_file(a_shape,
                   filename,
                   mode="ascii",
                   linear_deflection=0.9,
                   angular_deflection=0.5):
    """ export the shape to a STL file
    Be careful, the shape first need to be explicitely meshed using BRepMesh_IncrementalMesh
    a_shape: the topods_shape to export
    filename: the filename
    mode: optional, "ascii" by default. Can either be "binary"
    linear_deflection: optional, default to 0.001. Lower, more occurate mesh
    angular_deflection: optional, default to 0.5. Lower, more accurate_mesh
    """
    assert not a_shape.IsNull()
    assert mode in ["ascii", "binary"]
    if os.path.isfile(filename):
        print("Warning: %s file already exists and will be replaced" %
              filename)
    # first mesh the shape
    mesh = BRepMesh_IncrementalMesh(a_shape, linear_deflection, False,
                                    angular_deflection, True)
    #mesh.SetDeflection(0.05)
    mesh.Perform()
    assert mesh.IsDone()

    stl_exporter = StlAPI_Writer()
    if mode == "ascii":
        stl_exporter.SetASCIIMode(True)
    else:  # binary, just set the ASCII flag to False
        stl_exporter.SetASCIIMode(False)
    stl_exporter.Write(a_shape, filename)

    assert os.path.isfile(filename)
예제 #2
0
def write_2_stl(occtopology, stl_filepath, linear_deflection = 0.8, angle_deflection = 0.5):
    """
    This function writes a 3D model into STL format.
 
    Parameters
    ----------
    occtopology : OCCtopology
        Geometries to be written into STL.
        OCCtopology includes: OCCshape, OCCcompound, OCCcompsolid, OCCsolid, OCCshell, OCCface, OCCwire, OCCedge, OCCvertex 
        
    stl_filepath : str
        The file path of the STL file. 
        
    mesh_incremental_float : float, optional
        Default = 0.8.
        
    Returns
    -------
    None : None
        The geometries are written to a STL file.
    """       
    from OCC.StlAPI import StlAPI_Writer
    from OCC.BRepMesh import BRepMesh_IncrementalMesh
    from OCC.TopoDS import TopoDS_Shape
    # Export to STL
    stl_writer = StlAPI_Writer()
    stl_writer.SetASCIIMode(True)
    occtopology = TopoDS_Shape(occtopology)
    mesh = BRepMesh_IncrementalMesh(occtopology, linear_deflection, True, angle_deflection, True)
    assert mesh.IsDone()
        
    stl_writer.Write(occtopology,stl_filepath)
예제 #3
0
    def export(self, event):
        """ Export the current model to stl """
        from OCC.StlAPI import StlAPI_Writer
        from OCC.BRepMesh import BRepMesh_IncrementalMesh
        #: TODO: All parts
        options = event.parameters.get('options')
        if not isinstance(options, ExportOptions):
            return False

        exporter = StlAPI_Writer()
        exporter.SetASCIIMode(not options.binary)

        #: Make a compound of compounds (if needed)
        compound = TopoDS_Compound()
        builder = BRep_Builder()
        builder.MakeCompound(compound)
        for part in self.parts:
            #: Must mesh the shape first
            if isinstance(part, Part):
                builder.Add(compound, part.proxy.shape)
            else:
                builder.Add(compound, part.proxy.shape.Shape())

        #: Build the mesh
        mesh = BRepMesh_IncrementalMesh(compound, options.linear_deflection,
                                        options.relative,
                                        options.angular_deflection)
        mesh.Perform()
        if not mesh.IsDone():
            raise ExportError("Failed to create the mesh")

        exporter.Write(compound, options.path)
예제 #4
0
    def exportStl(self, fileName, precision=1e-5):

        mesh = BRepMesh_IncrementalMesh(self.wrapped, precision, True)
        mesh.Perform()

        writer = StlAPI_Writer()

        return writer.Write(self.wrapped, fileName)
예제 #5
0
 def write_file(self):
     r"""Write file"""
     mesh = BRepMesh_IncrementalMesh(
         self._shape, self._line_deflection, self._is_relative,
         self._angular_deflection, self._in_parallel)
     mesh.Perform()
     stl_writer = StlAPI.StlAPI_Writer()
     stl_writer.SetASCIIMode(self._ascii_mode)
     stl_writer.Write(self._shape, self._filename)
     logger.info("Wrote STL file")
예제 #6
0
    def export(self):
        """ Export a DeclaraCAD model from an enaml file to an STL based on the
        given options.
        
        Parameters
        ----------
        options: declaracad.occ.plugin.ExportOptions
        
        """
        from OCC.BRep import BRep_Builder
        from OCC.BRepMesh import BRepMesh_IncrementalMesh
        from OCC.StlAPI import StlAPI_Writer
        from OCC.TopoDS import TopoDS_Compound
        
        # Make a compound of compounds (if needed)
        compound = TopoDS_Compound()
        builder = BRep_Builder()
        builder.MakeCompound(compound)
        
        # Load the enaml model file
        parts = load_model(self.filename)
        
        for part in parts:
            # Render the part from the declaration
            shape = part.render()
            
            # Must mesh the shape firsts
            if hasattr(shape, 'Shape'):
                builder.Add(compound, shape.Shape())
            else:
                builder.Add(compound, shape)

        #: Build the mesh
        exporter = StlAPI_Writer()
        exporter.SetASCIIMode(not self.binary)
        mesh = BRepMesh_IncrementalMesh(
            compound,
            self.linear_deflection,
            self.relative,
            self.angular_deflection
        )
        mesh.Perform()
        if not mesh.IsDone():
            raise RuntimeError("Failed to create the mesh")
        
        exporter.Write(compound, self.path)
            
        if not os.path.exists(self.path):
            raise RuntimeError("Failed to write shape")
예제 #7
0
    def build_bounding_box(self,
                           shape,
                           tol=1e-6,
                           triangulate=False,
                           triangulate_tol=1e-1):
        """
        Builds a bounding box around the given shape. All parameters are set to
        match the computed box, the deformed FFD points are reset.

        :param shape: the shape to compute the bounding box.
        :type shape: TopoDS_Shape or its subclass
        :param float tol: tolerance of the computed bounding box.
        :param bool triangulate: if True, shape is triangulated before the
            bouning box creation.
        :param float triangulate_tol: tolerance of triangulation (size of
            created triangles).

        .. note::

            Every UV-Surface has to be rectangular. When a solid is created
            surfaces are trimmed. The trimmed part, however, is still saved
            inside a file. It is just *invisible* when drawn in a program.
        """
        bbox = Bnd_Box()
        bbox.SetGap(tol)
        if triangulate:
            BRepMesh_IncrementalMesh(shape, triangulate_tol)
        brepbndlib_Add(shape, bbox, triangulate)
        xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
        min_xyz = np.array([xmin, ymin, zmin])
        max_xyz = np.array([xmax, ymax, zmax])

        self.origin_box = min_xyz
        self.lenght_box = max_xyz - min_xyz
        self.reset_deformation()
def occ_triangle_mesh(event=None):
    #
    # Mesh the shape
    #
    BRepMesh_IncrementalMesh(aShape, 0.1)
    builder = BRep_Builder()
    Comp = TopoDS_Compound()
    builder.MakeCompound(Comp)

    ex = TopExp_Explorer(aShape, TopAbs_FACE)
    while ex.More():
        F = topods_Face(ex.Current())
        L = TopLoc_Location()
        facing = (BRep_Tool().Triangulation(F, L)).GetObject()
        tab = facing.Nodes()
        tri = facing.Triangles()
        for i in range(1, facing.NbTriangles() + 1):
            trian = tri.Value(i)
            #print trian
            index1, index2, index3 = trian.Get()
            for j in range(1, 4):
                if j == 1:
                    M = index1
                    N = index2
                elif j == 2:
                    N = index3
                elif j == 3:
                    M = index2
                ME = BRepBuilderAPI_MakeEdge(tab.Value(M), tab.Value(N))
                if ME.IsDone():
                    builder.Add(Comp, ME.Edge())
        ex.Next()
    display.DisplayShape(Comp, update=True)
예제 #9
0
파일: params.py 프로젝트: zjvskobe/PyGeM
    def _calculate_bb_dimension(shape,
                                tol=1e-6,
                                triangulate=False,
                                triangulate_tol=1e-1):
        """ Calculate dimensions (minima and maxima) of a box bounding the

		:param TopoDS_Shape shape: or a subclass such as TopoDS_Face the shape
			to compute the bounding box from
		:param float tol: tolerance of the computed bounding box
		:param bool triangulate: Should shape be triangulated before the
			boudning box is created.

			If ``True`` only the dimensions of the bb will take into account
			every part of the shape (also not *visible*)

			If ``False`` only the *visible* part is taken into account

			\*See :meth:`~params.FFDParameters.build_bounding_box`
		:param float triangulate_tol: tolerance of triangulation (size of
				created triangles)
		:return: coordinates of minima and maxima along XYZ
		:rtype: tuple
		"""
        bbox = Bnd_Box()
        bbox.SetGap(tol)
        if triangulate:
            BRepMesh_IncrementalMesh(shape, triangulate_tol)
        brepbndlib_Add(shape, bbox, triangulate)
        xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
        xyz_min = np.array([xmin, ymin, zmin])
        xyz_max = np.array([xmax, ymax, zmax])
        return xyz_min, xyz_max
예제 #10
0
    def _fromTopoDS(cls, shape, tol=TOL, optimal=False):
        '''
        Constructs a bounnding box from a TopoDS_Shape
        '''
        bbox = Bnd_Box()
        bbox.SetGap(tol)
        if optimal:
            raise NotImplementedError
            # brepbndlib_AddOptimal(shape, bbox) #this is 'exact' but expensive - not yet wrapped by PythonOCC
        else:
            mesh = BRepMesh_IncrementalMesh(shape, TOL, True)
            mesh.Perform()
            # this is adds +margin but is faster
            brepbndlib_Add(shape, bbox, True)

        return cls(bbox)
예제 #11
0
def simple_mesh(occshape, mesh_incremental_float=0.8):
    #TODO: figure out why is it that some surfaces do not work
    occshape = TopoDS_Shape(occshape)
    bt = BRep_Tool()
    BRepMesh_IncrementalMesh(occshape, mesh_incremental_float)
    occshape_face_list = fetch.geom_explorer(occshape, "face")
    occface_list = []
    for occshape_face in occshape_face_list:
        location = TopLoc_Location()
        #occshape_face = modify.fix_face(occshape_face)
        facing = bt.Triangulation(occshape_face, location).GetObject()
        if facing:
            tab = facing.Nodes()
            tri = facing.Triangles()
            for i in range(1, facing.NbTriangles() + 1):
                trian = tri.Value(i)
                index1, index2, index3 = trian.Get()
                #print index1, index2, index3
                pypt1 = fetch.occpt2pypt(tab.Value(index1))
                pypt2 = fetch.occpt2pypt(tab.Value(index2))
                pypt3 = fetch.occpt2pypt(tab.Value(index3))
                #print pypt1, pypt2, pypt3
                occface = make_polygon([pypt1, pypt2, pypt3])
                occface_list.append(occface)
    return occface_list
예제 #12
0
파일: step2stl.py 프로젝트: amramsey/MMTMM
def write_stl(shape, filename, df=0.1):
    from OCC.StlAPI import StlAPI_Writer
    import os

    directory = os.path.split(__name__)[0]
    stl_output_dir = os.path.abspath(directory)
    assert os.path.isdir(stl_output_dir)

    stl_file = os.path.join(stl_output_dir, filename)

    stl_writer = StlAPI_Writer()
    stl_writer.SetASCIIMode(False)

    from OCC.BRepMesh import BRepMesh_IncrementalMesh
    mesh = BRepMesh_IncrementalMesh(shape, df)
    mesh.Perform()
    assert mesh.IsDone()

    stl_writer.Write(shape, stl_file)
    assert os.path.isfile(stl_file)
예제 #13
0
def analyze_file(filename):
    step_reader = STEPControl_Reader()
    status = step_reader.ReadFile(str(filename))
    result = None

    if status == IFSelect_RetDone:  # check status
        number_of_roots = step_reader.NbRootsForTransfer()
        ok = False
        i = 1

        while i <= number_of_roots and not ok:
            ok = step_reader.TransferRoot(i)
            i += 1

        if (not ok):
            return {
                'error': 'Failed to find a suitable root for the STEP file'
            }

        number_of_shapes = step_reader.NbShapes()

        if (number_of_shapes > 1):
            return {'error': 'Cannot handle more than one shape in a file'}

        aResShape = step_reader.Shape(1)

        # bounding box
        bbox = Bnd_Box()
        deflection = 0.01
        BRepMesh_IncrementalMesh(aResShape, deflection)

        brepbndlib_Add(aResShape, bbox)
        xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()

        bounding_box = calculate_bnd_box(bbox)

        result = {
            'x0': bounding_box['x_min'],
            'x1': bounding_box['x_max'],
            'y0': bounding_box['y_min'],
            'y1': bounding_box['y_max'],
            'z0': bounding_box['z_min'],
            'z1': bounding_box['z_max'],
            'length': bounding_box['x_length'],
            'width': bounding_box['z_length'],
            'height': bounding_box['y_length'],
            'volume': calculate_volume(aResShape)
        }

    else:
        result = {'error': 'Cannot read file'}

    return result
예제 #14
0
def get_boundingbox(shape, tol=1e-6, use_mesh=True):
    """ return the bounding box of the TopoDS_Shape `shape`
    Parameters
    ----------
    shape : TopoDS_Shape or a subclass such as TopoDS_Face
        the shape to compute the bounding box from
    tol: float
        tolerance of the computed boundingbox
    use_mesh : bool
        a flag that tells whether or not the shape has first to be meshed before the bbox
        computation. This produces more accurate results
    """
    bbox = Bnd_Box()
    bbox.SetGap(tol)
    if use_mesh:
        mesh = BRepMesh_IncrementalMesh()
        mesh.SetParallel(True)
        mesh.SetShape(shape)
        mesh.Perform()
        if not mesh.IsDone():
            raise AssertionError("Mesh not done.")
    brepbndlib_Add(shape, bbox, use_mesh)

    xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
    return xmin, ymin, zmin, xmax, ymax, zmax, xmax - xmin, ymax - ymin, zmax - zmin
예제 #15
0
def topods_shape_reader(shape, deflection=0.001):

    from OCC.StlAPI import StlAPI_Writer
    from OCC.BRepMesh import BRepMesh_IncrementalMesh

    import vtk

    stl_writer = StlAPI_Writer()

    with tmpfile(suffix='.stl') as tmpf:
        mesh = BRepMesh_IncrementalMesh(shape, deflection)
        mesh.Perform()
        assert mesh.IsDone()
        stl_writer.SetASCIIMode(False)
        stl_writer.Write(shape, tmpf[1])
        tmpf[0].flush()

        reader = vtk.vtkSTLReader()
        reader.SetFileName(tmpf[1])
        reader.Update()

        return reader
예제 #16
0
def simple_mesh():
    #
    # Create the shape
    #
    shape = BRepPrimAPI_MakeBox(200, 200, 200).Shape()
    theBox = BRepPrimAPI_MakeBox(200, 60, 60).Shape()
    theSphere = BRepPrimAPI_MakeSphere(gp_Pnt(100, 20, 20), 80).Shape()
    shape = BRepAlgoAPI_Fuse(theSphere, theBox).Shape()
    #
    # Mesh the shape
    #
    BRepMesh_IncrementalMesh(shape, 0.8)
    builder = BRep_Builder()
    comp = TopoDS_Compound()
    builder.MakeCompound(comp)

    bt = BRep_Tool()
    ex = TopExp_Explorer(shape, TopAbs_FACE)
    while ex.More():
        face = topods_Face(ex.Current())
        location = TopLoc_Location()
        facing = (bt.Triangulation(face, location)).GetObject()
        tab = facing.Nodes()
        tri = facing.Triangles()
        for i in range(1, facing.NbTriangles()+1):
            trian = tri.Value(i)
            index1, index2, index3 = trian.Get()
            for j in range(1, 4):
                if j == 1:
                    m = index1
                    n = index2
                elif j == 2:
                    n = index3
                elif j == 3:
                    m = index2
                me = BRepBuilderAPI_MakeEdge(tab.Value(m), tab.Value(n))
                if me.IsDone():
                    builder.Add(comp, me.Edge())
        ex.Next()
    display.EraseAll()
    display.DisplayShape(shape)
    display.DisplayShape(comp, update=True)
def makeIncrementalMesh(shape, lindefl=0.1, angdefl=.07):
    """ Make mesh using BRepMesh_IncrementalMesh 
    
     BRepMesh_IncrementalMesh was found to have some issues with the
     transitions radius (basically turning it into a chamfer instead,
     getting rid of the actual curvature), so SMESH was then explored.

     lindefl = Linear Deflection Setting
     angdefl = Angular Deflection Setting
    """

    try:
        mesh = BRepMesh_IncrementalMesh(diffuser.Shape(), lindefl, True,
                                        angdefl, False)
    except:
        print('Mesh failed')
    else:
        if args.v >= 1:
            print(f'\nDiffuser shape has been meshed.')
    return mesh
예제 #18
0
def discretize(shape, tol):
    """This method discretizes the OpenCascade shape.

    :param shape: Shape to discretize
    :type shape:
    :return: discretized face; profile coordinates; id of the surface the\
    coordinates belong to
    :rtype: OCC.TopoDS.TopoDS_Compound; numpy.ndarray; numpy.ndarray
    """
    BRepMesh_IncrementalMesh(shape, tol, False, 5)
    builder = BRep_Builder()
    comp = TopoDS_Compound()
    builder.MakeCompound(comp)

    bt = BRep_Tool()
    ex = TopExp_Explorer(shape, TopAbs_EDGE)
    edge_coords = np.zeros([0, 3])
    edge_ids = np.zeros([0], dtype=int)
    edge_id = 0
    while ex.More():
        edge = topods_Edge(ex.Current())
        location = TopLoc_Location()
        edging = (bt.Polygon3D(edge, location)).GetObject()
        tab = edging.Nodes()
        for i in range(1, edging.NbNodes() + 1):
            p = tab.Value(i)
            edge_coords = np.append(edge_coords,
                                    [[p.X(), p.Y(), p.Z()]],
                                    axis=0)
            edge_ids = np.append(edge_ids, edge_id)
            mv = BRepBuilderAPI_MakeVertex(p)
            if mv.IsDone():
                builder.Add(comp, mv.Vertex())
        edge_id += 1
        ex.Next()

    edge_coords = np.round(edge_coords, 8)
    return edge_coords, edge_ids
예제 #19
0
    def __init__(self, shape):
        from OCC.BRep import BRep_Tool
        from OCC.BRepMesh import BRepMesh_IncrementalMesh
        from OCC.TopAbs import TopAbs_FACE, TopAbs_VERTEX
        from OCC.TopExp import TopExp_Explorer
        from OCC.TopLoc import TopLoc_Location
        from OCC.TopoDS import topods_Face, topods_Vertex, TopoDS_Iterator

        vertices = []  # a (nested) list of vec3
        triangles = []  # a (flat) list of integers
        normals = []
        uv = []

        # Mesh the shape
        linDeflection = 0.8
        BRepMesh_IncrementalMesh(shape, linDeflection)
        bt = BRep_Tool()

        # Explore the faces of the shape
        # each face is triangulated, we need to collect all the parts
        expFac = TopExp_Explorer(shape, TopAbs_FACE)
        while expFac.More():
            face = topods_Face(expFac.Current())
            location = TopLoc_Location()
            facing = (bt.Triangulation(face, location)).GetObject()
            try:
                tri = facing.Triangles()
                nTri = facing.NbTriangles()
                ver = facing.Nodes()
            except:
                tri = None
                nTri = None
                ver = None
            # store origin of the face's local coordinates
            transf = face.Location().Transformation()

            # iterate over triangles and store indices of vertices defining each triangle
            # OCC uses one-based indexing
            for i in range(1, nTri + 1):
                # each triangle is defined by three points
                # each point is defined by its index in the list of vertices
                index1, index2, index3 = tri.Value(i).Get()
                indices = [index1, index2, index3]

                # python uses zero-based indexing
                # for each vertex of a triangle, check whether it is already known
                # then store it (or not) and update the index
                for idx in [0, 1, 2]:
                    # read global coordinates of each point
                    vec3 = [
                        ver.Value(indices[idx]).Transformed(transf).X(),
                        ver.Value(indices[idx]).Transformed(transf).Y(),
                        ver.Value(indices[idx]).Transformed(transf).Z()
                    ]
                    if vec3 not in vertices:
                        vertices.append(vec3)
                    indices[idx] = vertices.index(vec3)
                triangles.extend(indices)
            expFac.Next()

        self.shape = shape
        self.vertices = vertices
        self.triangles = triangles
        self.normals = normals
        self.uv = uv
예제 #20
0
##GNU Lesser General Public License for more details.
##
##You should have received a copy of the GNU Lesser General Public License
##along with pythonOCC.  If not, see <http://www.gnu.org/licenses/>.

import os
from OCC.StlAPI import StlAPI_Writer
from OCC.BRepPrimAPI import BRepPrimAPI_MakeTorus
from OCC.BRepMesh import BRepMesh_IncrementalMesh

# first, create the shape
my_torus = BRepPrimAPI_MakeTorus(20., 10.).Shape()
# then mesh it. This mesh is used by the STL exporter
# Note : if the mesh is not performed, the STL exporter
# won't do nothing
mesh = BRepMesh_IncrementalMesh(my_torus, 0.9)
mesh.Perform()
assert mesh.IsDone()

# set the directory where to output the
directory = os.path.split(__name__)[0]
stl_output_dir = os.path.abspath(os.path.join(directory, "models"))

# make sure the path exists otherwise OCE get confused
assert os.path.isdir(stl_output_dir)
stl_low_resolution_file = os.path.join(stl_output_dir,
                                       "torus_low_resolution.stl")
stl_exporter = StlAPI_Writer()
stl_exporter.SetASCIIMode(True)  # change to False if you need binary export
stl_exporter.Write(my_torus, stl_low_resolution_file)
# make sure the program was created
def Mesh(shape):
    mesh = BRepMesh_IncrementalMesh(shape, 0.6)
    mesh.Perform()
예제 #22
0
def analyze_file(filename):
    step_reader = STEPControl_Reader()
    status = step_reader.ReadFile(filename)
    result = None

    if status == IFSelect_RetDone:  # check status
        number_of_roots = step_reader.NbRootsForTransfer()
        ok = False
        i = 1

        while i <= number_of_roots and not ok:
            ok = step_reader.TransferRoot(i)
            i += 1

        if (not ok):
            return {
                'error': 'Failed to find a suitable root for the STEP file'
            }

        number_of_shapes = step_reader.NbShapes()

        if (number_of_shapes > 1):
            return {'error': 'Cannot handle more than one shape in a file'}

        aResShape = step_reader.Shape(1)

        # Units
        length = TColStd_SequenceOfAsciiString()
        angles = TColStd_SequenceOfAsciiString()
        solid_angles = TColStd_SequenceOfAsciiString()
        step_reader.FileUnits(length, angles, solid_angles)

        # bounding box
        bbox = Bnd_Box()
        deflection = 0.01
        BRepMesh_IncrementalMesh(aResShape, deflection)

        brepbndlib_Add(aResShape, bbox)
        xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()

        bounding_box = calculate_bnd_box(bbox)

        bounding_cylinder = calculate_bounding_cylinder(
            aResShape, bounding_box)

        result = {
            'bounding_box_volume': bounding_box['volume'],
            'bounding_box_x_length': bounding_box['x_length'],
            'bounding_box_y_length': bounding_box['y_length'],
            'bounding_box_z_length': bounding_box['z_length'],
            'mesh_volume': calculate_volume(aResShape),
            'mesh_surface_area': None,
            'cylinder_volume': bounding_cylinder['cylinder_volume'],
            'cylinder_diameter': bounding_cylinder['radius'] * 2,
            'cylinder_length': bounding_cylinder['height'],
            'convex_hull_volume': None,
            'euler_number': None,
            'units': length.First().ToCString().lower()
        }

    else:
        result = {'error': 'Cannot read file'}

    return result