def runCommand(cmd,RaiseError=True):
    """Run a command and raise error if exited with error."""
    GD.message("Running command: %s" % cmd)
    sta,out = commands.getstatusoutput(cmd)
    if sta != 0 and RaiseError:
        raise RuntimeError, "Error while executing command:\n  %s" % cmd
    return sta,out
def detect():
    """Check if we have calpy and if so, add its path to sys.path."""

    global calpy_path
    
    calpy = utils.hasExternal('calpy')
    if not calpy:
        return
    
    GD.message("You have calpy version %s" % calpy)
    path = ''
    calpy = calpy.split('-')[0]  # trim the version trailer
    if utils.checkVersion('calpy','0.3.4-rev3',external=True) >= 0:
        sta,out = utils.runCommand('calpy --whereami')
        if not sta:
            path = os.path.dirname(out)
            GD.debug("I found calpy in %s" % path)
    if not path:
        trypaths = [ '/usr/local/lib', '/usr/local' ]
        for p in trypaths:
            path = '%s/calpy-%s' % (p,calpy)
            if os.path.exists(path):
                GD.debug('path exists: %s' % path)
                break
            else:
                GD.debug('path does not exist: %s' % path)
                path = ''
    if path:
        GD.message("I found calpy in '%s'" % path)
        sys.path.append(path)

    calpy_path = path
def read_Formex(fn):
    GD.message("Reading file %s" % fn)
    t = timer.Timer()
    F = Formex.read(fn)
    nelems, nplex = F.f.shape[0:2]
    GD.message("Read %d elems of plexitude %d in %s seconds" % (nelems, nplex, t.seconds()))
    return F
def readSelection(select=True,draw=True,multi=True):
    """Read a Surface (or list) from asked file name(s).

    If select is True (default), this becomes the current selection.
    If select and draw are True (default), the selection is drawn.
    """
    types = [ 'Surface Files (*.gts *.stl *.off *.neu *.smesh)', 'All Files (*)' ]
    fn = askFilename(GD.cfg['workdir'],types,exist=True,multi=multi)
    if not multi:
        fn = [ fn ]
    if fn:
        chdir(fn[0])
        names = map(utils.projectName,fn)
        GD.gui.setBusy()
        surfaces = map(read_Surface,fn)
        for i,S in enumerate(surfaces):
            S.setProp(i)
        GD.gui.setBusy(False)
        export(dict(zip(names,surfaces)))
        if select:
            GD.message("Set selection to %s" % str(names))
            selection.set(names)
            if draw:
                if max([named(s).nfaces() for s in selection]) < 100000 or ack("""
This is a large model and drawing could take quite some time.
You should consider coarsening the model before drawing it.
Shall I proceed with the drawing now?
"""):
                    selection.draw()
    return fn
def create_tetgen_volume():
    """Generate a volume tetraeder mesh inside an stl surface."""
    types = [ 'STL/OFF Files (*.stl *.off)', 'All Files (*)' ]
    fn = askFilename(GD.cfg['workdir'],types,exist=True,multi=False)
    if os.path.exists(fn):
        sta,out = utils.runCommand('tetgen -z %s' % fn)
        GD.message(out)
def congratulations(name,version,typ='module'):
    """Report a detected module/program."""
    if GD.options.debug:
        if version:
            GD.message("Congratulations! You have %s (%s)" % (name,version))
        else:
            GD.message("ALAS! I could not find %s '%s' on your system" % (typ,name))
Exemple #7
0
def remove_triangles(elems,remove):
    """Remove triangles from a surface mesh.

    elems is a (nelems,3) integer array of triangles.
    remove is a (nremove,3) integer array of triangles to remove.
    
    Returns a (nelems-nremove,3) integer array with the triangles of
    nelems where the triangles of remove have been removed.
    """
    print elems,remove
    GD.message("Removing %s out of %s triangles" % (remove.shape[0],elems.shape[0]))
    magic = elems.max()+1

    mag1 = magic_numbers(elems,magic)
    mag2 = magic_numbers(remove,magic)

    mag1.sort()
    mag2.sort()

    nelems = mag1.shape[0]

    pos = mag1.searchsorted(mag2)
    mag1[pos] = -1
    mag1 = mag1[mag1 >= 0]

    elems = demagic(mag1,magic)
    GD.message("Actually removed %s triangles, leaving %s" % (nelems-mag1.shape[0],elems.shape[0]))

    return elems
    def printSettings(self):
        for i,v in enumerate(self.all):
            GD.message("""
## VIEWPORTS ##
Viewport %s;  Active:%s;  Current:%s;  Settings:
%s
""" % (i,v in self.active, v == self.current, v.settings))
def clip_surface():
    """Clip the stl model."""
    if not check_surface():
        return
    itemlist = [['axis',0],['begin',0.0],['end',1.0],['nodes','any']]
    res,accept = widgets.inputDialog(itemlist,'Clipping Parameters').getResult()
    if accept:
        updateGUI()
        nodes,elems = PF['old_surface'] = PF['surface']
        F = Formex(nodes[elems])
        bb = F.bbox()
        GD.message("Original bbox: %s" % bb) 
        xmi = bb[0][0]
        xma = bb[1][0]
        dx = xma-xmi
        axis = int(res[0][1])
        xc1 = xmi + float(res[1][1]) * dx
        xc2 = xmi + float(res[2][1]) * dx
        nodid = res[3][1]
        print nodid
        clear()
        draw(F,color='yellow')
        w = F.test(nodes='any',dir=axis,min=xc1,max=xc2)
        F = F.clip(w)
        draw(F,clor='red')
def read_surface(types=['stl/off','stl','off','neu','smesh','gts'],show=True):
    """Read STL model from file fn.

    If no file is given, one is asked.
    The file fn should exist and contain a valid STL model.
    The STL model is stored in the Formex F.
    The workdir and project name are set from the filename.
    The Formex is stored under the project basename.
    The model is displayed.
    """
    if type(types) == str:
        types = [ types ]
    types = map(utils.fileDescription,types)
    fn = askFilename(GD.cfg['workdir'],types,exist=True)
    if fn:
        chdir(fn)
        set_project(utils.projectName(fn))
        GD.message("Reading file %s" % fn)
        GD.gui.setBusy()
        t = timer.Timer()
        nodes,elems =stl.readSurface(fn)
        GD.message("Time to import stl: %s seconds" % t.seconds())
        GD.gui.setBusy(False)
        set_surface(nodes,elems)
        if show:
            show_surface(view='front')
        if ack('Convert to Formex?'):
            name = toFormex()
            # This is convenient for the user
            if name:
                formex_menu.setSelection(name)
                #formex_menu.drawSelection()
    return fn
def checkExternal(name,command=None,answer=None):
    """Check if the named external command is available on the system.

    name is the generic command name,
    command is the command as it will be executed to check its operation,
    answer is a regular expression to match positive answers from the command.
    answer should contain at least one group. In case of a match, the
    contents of the match will be stored in the GD.external dict
    with name as the key. If the result does not match the specified answer,
    an empty value is inserted.

    Usually, command will contain an option to display the version, and
    the answer re contains a group to select the version string from
    the result.

    As a convenience, we provide a list of predeclared external commands,
    that can be checked by their name alone.
    """
    if command is None or answer is None:
        cmd,ans = known_externals.get(name,(name,'(.+)\n'))
        if command is None:
            command = cmd
        if answer is None:
            answer = ans
    m = re.match(answer,commands.getoutput(command))
    if m:
        value = m.group(1)
        GD.message("Congratulations! You have %s (%s)" % (name,value))
    else:
        value = ''
    GD.external[name] = value
    return value
 def printBbox(self):
     """Print the bbox of the current selection."""
     objects = self.check()
     for n,o in zip(self.names,objects):
         GD.message("Object %s has bbox %s" % (n,o.bbox()))
     if len(self.names) > 1:
         GD.message("Overal bbox is %s" % bbox(objects))
 def selectStepInc(self):
     res = askItems([('Step',self.DB.step,'select',self.DB.res.keys())])
     if res:
         step = int(res['Step'])
         res = askItems([('Increment',None,'select',self.DB.res[step].keys())])
         if res:
             inc = int(res['Increment'])
     GD.message("Step %s; Increment %s;" % (step,inc))
     self.DB.setStepInc(step,inc)
Exemple #14
0
def breakpt(msg=None):
    """Set a breakpoint where the script can be halted on pressing a button.

    If an argument is specified, it will be written to the message board.
    """
    if exitrequested:
        if msg is not None:
            GD.message(msg)
        raise Exit
def closeProject():
    global the_project,the_project_saved
    if not (the_project_saved or the_project is None):
        GD.message("Closing project %s" % the_project.filename)
        GD .message("Project contents: %s" % the_project.keys())
        the_project.save()
        GD.PF = {}
        GD.PF.update(the_project)
        GD.gui.setcurproj('None')
    the_project = None
def show_volume():
    """Display the volume model."""
    if PF['volume'] is None:
        return
    nodes,elems = PF['volume']
    F = Formex(nodes[elems])
    GD.message("BBOX = %s" % F.bbox())
    clear()
    draw(F,color='random',eltype='tet')
    PF['vol_model'] = F
def show_shrinked():
    """Display the surface model in shrinked mode.

    This is based on the stl model.
    """
    if check_stl():
        F = PF['stl_model']
        GD.message("BBOX = %s" % F.bbox())
        clear()
        draw(F.shrink(0.8),color=PF['stl_color'])
def export_stl():
    """Export an stl model stored in Formex F in Abaqus .inp format."""
    global project,F
    if ack("Creating nodes and elements.\nFor a large model, this could take quite some time!"):
        GD.app.processEvents()
        GD.message("Creating nodes and elements.")
        nodes,elems = F.feModel()
        nnodes = nodes.shape[0]
        nelems = elems.shape[0]
        GD.message("There are %d unique nodes and %d triangle elements in the model." % (nnodes,nelems))
        stl_abq.abq_export(project+'.inp',nodes,elems,'S3',"Created by stl_examples.py")
def writeSelection():
    """Writes the currently selected Formex to .formex file."""
    F = selection.check(single=True)
    if F:
        name = selection.names[0]
        fn = askFilename(GD.cfg['workdir'],file="%s.formex" % name,
                         filter=['(*.formex)','*'],exist=False)
        if fn:
            GD.message("Writing Formex '%s' to file '%s'" % (name,fn))
            chdir(fn)
            F.write(fn)
def showBboxB():
    """Draw the bbox on the current selection."""
    global bboxB
    FL = selection.check()
    if FL:
        bb = bbox(FL)
        GD.message("Bbox of selection: %s" % bb)
        nx = array([4,4,4])
        bboxB = actors.CoordPlaneActor(nx=nx,ox=bb[0],dx=(bb[1]-bb[0])/nx)
        GD.canvas.addActor(bboxB)
        GD.canvas.update()
def write_surface(types=['surface','gts','stl','off','neu','smesh']):
    F = selection.check(single=True)
    if F:
        if type(types) == str:
            types = [ types ]
        types = map(utils.fileDescription,types)
        fn = askFilename(GD.cfg['workdir'],types,exist=False)
        if fn:
            GD.message("Exporting surface model to %s" % fn)
            GD.gui.setBusy()
            F.write(fn)   
            GD.gui.setBusy(False)
 def postABQ(self,fn=None):
     """Translate an Abaqus .fil file in a postproc script."""
     types = [ 'Abaqus results file (*.fil)' ]
     fn = askFilename(GD.cfg['workdir'],types,exist=True)
     if fn:
         chdir(fn)
         name,ext = os.path.splitext(fn)
         post = name+'.post'
         cmd = "%s/lib/postabq %s > %s" % (GD.cfg['pyformexdir'],fn,post)
         sta,out = utils.runCommand(cmd)
         if sta:
             GD.message(out)
    def drawGL(self,mode,color=None,alpha=None):
        """Draw the surface."""
        print "SURFACE.DRAWGL"
        if mode.endswith('wire'):
            self.drawGL(mode[:-4],color=color)
            self.drawGL('wireframe',color=asarray(black))
            return

        if alpha is None:
            alpha = self.alpha           

        if color == None:
            color = self.color

##                 if mode == 'wireframe':
##                     # adapt color array to edgeselect
##                     color = concatenate([self.color,self.color,self.color],axis=-1)
##                     color = color.reshape((-1,2))[self.edgeselect]
        
        if color is None:  # no color
            pass
        
        elif color.dtype.kind == 'f' and color.ndim == 1:  # single color
            GL.glColor(append(color,alpha))
            color = None

        elif color.dtype.kind == 'i': # color index
            color = self.colormap[color]

        else: # a full color array : use as is
            pass

        #print "SURFACE COLOR = %s" % str(color)

        if self.linewidth is not None:
            GL.glLineWidth(self.linewidth)

        t = timer.Timer()
        if mode=='wireframe' :
            #print color.shape
            #print self.edges.shape
            #print self.faces.shape
            rev = reverseIndex(self.faces)
            if color is not None:
                color = color[rev[:,-1]]
            drawLineElems(self.coords,self.edges,color)
        else:
            self.refresh()
            drawTriangleElems(self.coords,self.elems,mode,color,alpha)
        GD.message("Drawing time: %s seconds" % t.seconds())
 def refine(self,max_edges=None,min_cost=None,
            log=False, verbose=False):
     """Refine the surface using gtsrefine."""
     if max_edges is None and min_cost is None:
         max_edges = self.nedges() * 2
     cmd = 'gtsrefine'
     if max_edges:
         cmd += ' -n %d' % max_edges
     if min_cost:
         cmd += ' -c %d' % min_cost
     if log:
         cmd += ' -L'
     if verbose:
         cmd += ' -v'
     tmp = tempfile.mktemp('.gts')
     tmp1 = tempfile.mktemp('.gts')
     GD.message("Writing temp file %s" % tmp)
     self.write(tmp,'gts')
     GD.message("Refining with command\n %s" % cmd)
     cmd += ' < %s > %s' % (tmp,tmp1)
     sta,out = runCommand(cmd)
     os.remove(tmp)
     if sta or verbose:
         GD.message(out)
     GD.message("Reading refined model from %s" % tmp1)
     self.__init__(*read_gts(tmp1))        
     os.remove(tmp1)
def breakpt(msg=None):
    """Set a breakpoint where the script can be halted on a signal.

    If an argument is specified, it will be written to the message board.

    The exitrequested signal is usually emitted by pressing a button in the GUI.
    In nongui mode the stopatbreakpt function can be called from another thread.
    """
    global exitrequested
    if exitrequested:
        if msg is not None:
            GD.message(msg)
        exitrequested = False # reset for next time
        raise Exit
Exemple #26
0
def pick(mode='actor',single=False,front=False,func=None):
    """Enter interactive picking mode and return selection.

    See viewport.py for more details.
    This function differs in that it provides default highlighting
    during the picking operation.
    """
    GD.message("Select %s" % mode)
    selection_buttons = widgets.ButtonBox('Selection:',['Cancel','OK'],[GD.canvas.cancel_selection,GD.canvas.accept_selection])
    GD.gui.statusbar.addWidget(selection_buttons)
    if func is None:
        func = highlight_funcs.get(mode,None)
    sel = GD.canvas.pick(mode,single,front,func) 
    GD.gui.statusbar.removeWidget(selection_buttons)
    return sel
def fill_holes():
    global F,oldF
    fn = project + '.stl'
    fn1 = project + '-closed.stl'
    if os.path.exists(fn):
        sta,out = commands.getstatusoutput('admesh %s -f -a %s' % (fn,fn1))
        GD.message(out)
        if sta == 0:
            clear()
            linewidth(1)
            draw(F,color='yellow',view='front')
            oldF = F
            linewidth(2)
            GD.gui.setBusy()
            stl.readSurface(fn1)
            GD.gui.setBusy(False)
Exemple #28
0
def chdir(fn):
    """Change the current pyFormex working directory.

    If fn is a directory name, the current directory is set to fn.
    If fn is a file name, the current directory is set to the directory
    holding fn.
    In either case, the current dirctory is stored in GD.cfg['workdir']
    for persistence between pyFormex invocations.
    
    If fn does not exist, nothing is done.
    """
    if os.path.exists:
        if not os.path.isdir(fn):
            fn = os.path.dirname(fn)
        os.chdir(fn)
        GD.cfg['workdir'] = fn
        GD.message("Your current workdir is %s" % os.getcwd())
def read_surface(fn='',types=['stl/off','stl','off','neu','smesh','gts'],convert=None,show=True):
    """Read STL model from file fn.

    If no file is given, one is asked.
    The file fn should exist and contain a valid surface model.
    
    The STL model is stored in the Formex F.
    The workdir and project name are set from the filename.
    The Formex is stored under the project basename.
    The model is displayed.

    If convert == True, the model is converted to a Formex.
    If convert == False, it will not be converted.
    The default is to ask the user.
    """
    if not (fn and os.path.exists(fn)):
        if type(types) == str:
            types = [ types ]
        types = map(utils.fileDescription,types)
        fn = askFilename(GD.cfg['workdir'],types,exist=True)
    if fn:
        chdir(fn)
        set_project(utils.projectName(fn))
        GD.message("Reading file %s" % fn)
        GD.gui.setBusy()
        t = timer.Timer()
        nodes,elems =stl.readSurface(fn)
        GD.message("Time to import surface: %s seconds" % t.seconds())
        GD.gui.setBusy(False)
        set_surface(nodes,elems)
        if show:
            show_surface(view='front')
        if convert is None:
            convert = ack('Convert to Formex?')
        if convert:
            GD.debug("GOING")
            name = toFormex(PF.get('project',''))
            # This is convenient for the user
            if name:
                formex_menu.setSelection(name)
                if show:
                    formex_menu.drawSelection()
        else:
            pass
        
    return fn
def partitionSelection():
    """Partition the selection."""
    F = checkSelection(single=True)
    if not F:
        return

    name = selection[0]
    GD.message("Partitioning Formex '%s'" % name)
    cuts = partition.partition(F)
    GD.message("Subsequent cutting planes: %s" % cuts)
    if ack("Save cutting plane data?"):
        types = ["Text Files (*.txt)", "All Files (*)"]
        fn = askFilename(GD.cfg["workdir"], types, exist=False)
        if fn:
            chdir(fn)
            fil = file(fn, "w")
            fil.write("%s\n" % cuts)
            fil.close()