def spliner(): """Slice the surface to a sequence of cross sections.""" import olist from plugins.curve import BezierSpline S = selection.check(single=True) if not S: return res = askItems([_I('Direction',[1.,0.,0.]), _I('# slices',20), _I('remove_invalid',False), ],caption = 'Define the slicing planes') if res: axis = res['Direction'] nslices = res['# slices'] remove_cruft = res['remove_invalid'] pf.GUI.setBusy(True) slices = S.slice(dir=axis,nplanes=nslices) pf.GUI.setBusy(False) print([ s.nelems() for s in slices ]) split = [ s.splitProp() for s in slices if s.nelems() > 0 ] split = olist.flatten(split) hasnan = [ isnan(s.coords).any() for s in split ] print(hasnan) print(sum(hasnan)) #print [s.closed for s in split] export({'%s/split' % selection[0]:split}) draw(split,color='blue',bbox='last',view=None) splines = [ BezierSpline(s.coords[s.elems[:,0]],closed=True) for s in split ] draw(splines,color='red',bbox='last',view=None) export({'%s/splines' % selection[0]:splines})
def colorByFront(): S = selection.check(single=True) if S: res = askItems( [ _I("front type", choices=["node", "edge"]), _I("number of colors", -1), _I("front width", 1), _I("start at", 0), _I("first prop", 0), ] ) pf.app.processEvents() if res: selection.remember() t = timer.Timer() ftype = res["front type"] nwidth = res["front width"] nsteps = nwidth * res["number of colors"] startat = res["start at"] firstprop = res["first prop"] if ftype == "node": p = S.walkNodeFront(nsteps=nsteps, startat=startat) else: p = S.walkEdgeFront(nsteps=nsteps, startat=startat) S.setProp(p / nwidth + firstprop) print ("Colored in %s parts (%s seconds)" % (S.prop.max() + 1, t.seconds())) selection.draw()
def sendMail(): import sendmail sender = pf.cfg['mail/sender'] if not sender: warning("You have to configure your email settings first") return res = askItems([ _I('sender',sender,text="From:",readonly=True), _I('to','',text="To:"), _I('cc','',text="Cc:"), _I('subject','',text="Subject:"), _I('text','',itemtype='text',text="Message:"), ]) if not res: return msg = sendmail.message(**res) print(msg) to = res['to'].split(',') cc = res['cc'].split(',') sendmail.sendmail(message=msg,sender=res['sender'],to=to+cc) print("Mail has been sent to %s" % to) if cc: print(" with copy to %s" % cc)
def translateSelection(): """Translate the selection in axes direction.""" FL = selection.check() modes = ['Axis direction','General direction'] if FL: res = askItems( [ _I('mode',choices=modes), _I('axis',0), _I('direction',[1.,0.,0.],itemtype='point'), _I('distance',1.0), ], enablers=[ ('mode',modes[0],'axis'), ('mode',modes[1],'direction'), ], caption = 'Translation Parameters', ) if res: mode = res['mode'] if mode[0] == 'A': dir = res['axis'] else: dir = res['direction'] dist = res['distance'] selection.remember(True) selection.changeValues([F.translate(dir,dist) for F in FL]) selection.drawChanges()
def fillBorders(): _data_ = _name_+'fillBorders_data' S = showBorder() try: B = named('border') except: return if B: props = [ b.prop[0] for b in B ] dia = Dialog([ _I('Fill which borders',itemtype='radio',choices=['All','One']), _I('Filling method',itemtype='radio',choices=['radial','border']), _I('merge',False,text='Merge fills into current surface'), ]) if _data_ in pf.PF: dia.updateData(pf.PF[_data_]) res = dia.getResults() if res: pf.PF[_data_] = res if res['Fill which borders'] == 'One': B = B[:1] fills = [ fillBorder(b,method=res['Filling method']).setProp(i+1) for i,b in enumerate(B) ] if res['merge']: name = selection.names[0] S = named(name) for f in fills: S += f export({name:S}) selection.draw() else: draw(fills) export(dict([('fill-%s'%i,f) for i,f in enumerate(fills)]))
def boolean(): """Boolean operation on two surfaces. op is one of '+' : union, '-' : difference, '*' : interesection """ surfs = listAll(clas=TriSurface) if len(surfs) == 0: warning("You currently have no exported surfaces!") return ops = ['+ (Union)','- (Difference)','* (Intersection)'] res = askItems([_I('surface 1',choices=surfs), _I('surface 2',choices=surfs), _I('operation',choices=ops), _I('check self intersection',False), _I('verbose',False), ],'Boolean Operation') if res: SA = pf.PF[res['surface 1']] SB = pf.PF[res['surface 2']] SC = SA.boolean(SB,op=res['operation'].strip()[0], check=res['check self intersection'], verbose=res['verbose']) export({'__auto__':SC}) selection.set('__auto__') selection.draw()
def sendMail(): import sendmail sender = pf.cfg['mail/sender'] if not sender: warning("You have to configure your email settings first") return res = askItems([ _I('sender',sender,text="From:",readonly=True), _I('to','',text="To:"), _I('cc','',text="Cc:"), _I('subject','',text="Subject:"), _I('text','',itemtype='text',text="Message:"), ]) if not res: return msg = sendmail.message(**res) print msg to = res['to'].split(',') cc = res['cc'].split(',') sendmail.sendmail(message=msg,sender=res['sender'],to=to+cc) print "Mail has been sent to %s" % to if cc: print " with copy to %s" % cc
def colorByFront(): S = selection.check(single=True) if S: res = askItems([_I('front type',choices=['node','edge']), _I('number of colors',-1), _I('front width',1), _I('start at',0), _I('first prop',0), ]) pf.app.processEvents() if res: selection.remember() t = timer.Timer() ftype = res['front type'] nwidth = res['front width'] nsteps = nwidth * res['number of colors'] startat = res['start at'] firstprop = res['first prop'] if ftype == 'node': p = S.walkNodeFront(nsteps=nsteps,startat=startat) else: p = S.walkEdgeFront(nsteps=nsteps,startat=startat) S.setProp(p/nwidth + firstprop) print("Colored in %s parts (%s seconds)" % (S.prop.max()+1,t.seconds())) selection.draw()
def trim_surface(): check_surface() res = askItems([_I("Number of trim rounds", 1), _I("Minimum number of border edges", 1)]) n = int(res["Number of trim rounds"]) nb = int(res["Minimum number of border edges"]) print ("Initial number of elements: %s" % elems.shape[0]) for i in range(n): elems = trim_border(elems, nodes, nb) print ("Number of elements after border removal: %s" % elems.shape[0])
def createSphere(): res = askItems([_I("name", "__auto__"), _I("grade", 4)]) if res: name = res["name"] level = max(1, res["grade"]) S = Sphere(level, verbose=True, filename=name + ".gts") export({name: S}) selection.set([name]) selection.draw()
def cutSelectionByPlanes(): """Cut the selection with one or more planes, which are already created.""" S = selection.check(single=True) if not S: return planes = listAll(clas=Plane) if len(planes) == 0: warning("You have to define some planes first.") return res1 = widgets.ListSelection(planes, caption="Known %sobjects" % selection.object_type(), sort=True).getResult() if res1: res2 = askItems( [ _I("Tolerance", 0.0), _I("Color by", "side", itemtype="radio", choices=["side", "element type"]), _I("Side", "both", itemtype="radio", choices=["positive", "negative", "both"]), ], caption="Cutting parameters", ) if res2: planes = map(named, res1) p = [plane.P for plane in planes] n = [plane.n for plane in planes] atol = res2["Tolerance"] color = res2["Color by"] side = res2["Side"] if color == "element type": newprops = [1, 2, 2, 3, 4, 5, 6] else: newprops = None if side == "both": Spos, Sneg = S.toFormex().cutWithPlane(p, n, newprops=newprops, side=side, atol=atol) elif side == "positive": Spos = S.toFormex().cutWithPlane(p, n, newprops=newprops, side=side, atol=atol) Sneg = Formex() elif side == "negative": Sneg = S.toFormex().cutWithPlane(p, n, newprops=newprops, side=side, atol=atol) Spos = Formex() if Spos.nelems() != 0: Spos = TriSurface(Spos) if color == "side": Spos.setProp(2) else: Spos = None if Sneg.nelems() != 0: Sneg = TriSurface(Sneg) if color == "side": Sneg.setProp(3) else: Sneg = None name = selection.names[0] export({name + "/pos": Spos}) export({name + "/neg": Sneg}) selection.set([name + "/pos", name + "/neg"] + res1) selection.draw()
def translateSelection(): """Translate the selection.""" FL = selection.check() if FL: res = askItems([_I("direction", 0), _I("distance", "1.0")], caption="Translation Parameters") if res: dir = res["direction"] dist = res["distance"] selection.remember(True) selection.changeValues([F.translate(dir, dist) for F in FL]) selection.drawChanges()
def createSphere(): res = askItems([_I('name','__auto__'), _I('ndiv',8,min=1), ]) if res: name = res['name'] ndiv = res['ndiv'] S = simple.sphere(ndiv) export({name:S}) selection.set([name]) selection.draw()
def createSphere(): res = askItems([_I('name','__auto__'), _I('grade',4), ]) if res: name = res['name'] level = max(1,res['grade']) S = Sphere(level,verbose=True,filename=name+'.gts') export({name:S}) selection.set([name]) selection.draw()
def convertMesh(): """Transform the element type of the selected meshes. """ if not selection.check(): selection.ask() narrow_selection(Mesh) if not selection.names: return meshes = [ named(n) for n in selection.names ] eltypes = set([ m.eltype.name() for m in meshes if m.eltype is not None]) print "eltypes in selected meshes: %s" % eltypes if len(eltypes) > 1: warning("I can only convert meshes with the same element type\nPlease narrow your selection before trying conversion.") return if len(eltypes) == 1: fromtype = elementType(eltypes.pop()) choices = ["%s -> %s" % (fromtype,to) for to in fromtype.conversions.keys()] if len(choices) == 0: warning("Sorry, can not convert a %s mesh"%fromtype) return res = askItems([ _I('_conversion',itemtype='vradio',text='Conversion Type',choices=choices), _I('_compact',True), _I('_merge',itemtype='hradio',text="Merge Meshes",choices=['None','Each','All']), ]) if res: globals().update(res) print "Selected conversion %s" % _conversion totype = _conversion.split()[-1] names = [ "%s_converted" % n for n in selection.names ] meshes = [ m.convert(totype) for m in meshes ] if _merge == 'Each': meshes = [ m.fuse() for m in meshes ] elif _merge == 'All': print _merge coords,elems = mergeMeshes(meshes) print elems ## names = [ "_merged_mesh_%s" % e.nplex() for e in elems ] ## meshes = [ Mesh(coords,e,eltype=meshes[0].eltype) for e in elems ] ## print meshes[0].elems meshes = [ Mesh(coords,e,m.prop,m.eltype) for e,m in zip(elems,meshes) ] if _compact: print "compacting meshes" meshes = [ m.compact() for m in meshes ] export2(names,meshes) selection.set(names) clear() selection.draw()
def createGrid(): res = askItems([_I("name", "__auto__"), _I("nx", 3), _I("ny", 3), _I("b", 1), _I("h", 1)]) if res: globals().update(res) # name = res['name'] # nx = res['nx'] # ny = res['ny'] # b = S = TriSurface(simple.rectangle(nx, ny, b, h, diag="d")) export({name: S}) selection.set([name]) selection.draw()
def refine(): S = selection.check(single=True) if S: res = askItems([_I("max_edges", -1), _I("min_cost", -1.0), _I("log", False), _I("verbose", False)]) if res: selection.remember() if res["max_edges"] <= 0: res["max_edges"] = None if res["min_cost"] <= 0: res["min_cost"] = None S = S.refine(**res) selection.changeValues([S]) selection.drawChanges()
def fillBorder(): showBorder() B = named('border') if B: res = askItems([ _I('Fill how many',itemtype='radio',choices=['All','One']), _I('Filling method',itemtype='radio',choices=['radial','border']), ]) if res['Fill how many'] == 'One': B = B[:1] fills = [ surfaceInsideBorder(b,method=res['Filling method']).setProp(i+1) for i,b in enumerate(B) ] draw(fills) export(dict([('fill-%s'%i,f) for i,f in enumerate(fills)]))
def translateSelection(): """Translate the selection.""" FL = selection.check() if FL: res = askItems([_I('direction',0), _I('distance','1.0'), ],caption = 'Translation Parameters') if res: dir = res['direction'] dist = res['distance'] selection.remember(True) selection.changeValues([F.translate(dir,dist) for F in FL]) selection.drawChanges()
def showFeatureEdges(): S = selection.check(single=True) if S: selection.draw() res = askItems([ _I('angle',60.), _I('ontop',False), ]) pf.app.processEvents() if res: p = S.featureEdges(angle=res['angle']) M = Mesh(S.coords,S.edges[p]) draw(M,color='red',linewidth=3,bbox='last',nolight=True,ontop=res['ontop'])
def partitionByAngle(): S = selection.check(single=True) if S: res = askItems([_I('angle',60.), _I('firstprop',1), #_I('startat',0) ]) pf.app.processEvents() if res: selection.remember() t = timer.Timer() S.prop = S.partitionByAngle(**res) print("Partitioned in %s parts (%s seconds)" % (S.prop.max()+1,t.seconds())) selection.draw()
def showStatisticsDialog(): global _stat_dia if _stat_dia: _close_stats_dia() dispmodes = ['On Domain','Histogram','Cumulative Histogram'] keys = SelectableStatsValues.keys() _stat_dia = widgets.InputDialog( caption='Surface Statistics',items=[ _I('Value',itemtype='vradio',choices=keys), _I('neighbours',text='Curvature Neighbourhood',value=1), _I('curval',text='Curvature Value',itemtype='vradio',choices=CurvatureValues), _I('clip',itemtype='hradio',choices=['None','Top','Bottom','Both']), _I('Clip Mode',itemtype='hradio',choices=['Range','Percentile']), _G('Clip Values',checkable=True,items=[ _I('Top',1.0), _I('Bottom',0.0), ], ), _I('Cumulative Distribution',False), ], actions=[ ('Close',_close_stats_dia), ('Distribution',_show_dist), ('Show on domain',_show_domain)], default='Show on domain' ) _stat_dia.show()
def slicer(): """Slice the surface to a sequence of cross sections.""" S = selection.check(single=True) if not S: return res = askItems([_I("Direction", [1.0, 0.0, 0.0]), _I("# slices", 20)], caption="Define the slicing planes") if res: axis = res["Direction"] nslices = res["# slices"] pf.GUI.setBusy(True) t = timer.Timer() slices = S.slice(dir=axis, nplanes=nslices) print "Sliced in %s seconds" % t.seconds() pf.GUI.setBusy(False) print [s.nelems() for s in slices]
def refine(): S = selection.check(single=True) if S: res = askItems([_I('max_edges',-1), _I('min_cost',-1.0), ]) if res: selection.remember() if res['max_edges'] <= 0: res['max_edges'] = None if res['min_cost'] <= 0: res['min_cost'] = None S=S.refine(**res) selection.changeValues([S]) selection.drawChanges()
def intersectWithPlane(): """Intersect the selection with a plane.""" FL = selection.check() if not FL: return res = askItems( [_I("Name suffix", "intersect"), _I("Point", (0.0, 0.0, 0.0)), _I("Normal", (1.0, 0.0, 0.0))], caption="Define the cutting plane", ) if res: suffix = res["Name suffix"] P = res["Point"] N = res["Normal"] M = [S.intersectionWithPlane(P, N) for S in FL] draw(M, color="red") export(dict([("%s/%s" % (n, suffix), m) for (n, m) in zip(selection, M)]))
def fillBorder(): showBorder() B = named("border") props = [b.prop[0] for b in B] if B: res = askItems( [ _I("Fill which borders", itemtype="radio", choices=["All", "One"]), _I("Filling method", itemtype="radio", choices=["radial", "border"]), ] ) if res["Fill which borders"] == "One": B = B[:1] fills = [surfaceInsideBorder(b, method=res["Filling method"]).setProp(i + 1) for i, b in enumerate(B)] draw(fills) export(dict([("fill-%s" % i, f) for i, f in enumerate(fills)]))
def show_nodes(): n = 0 data = askItems([_I("node number", n)]) n = int(data["node number"]) if n > 0: nodes, elems = PF["surface"] print ("Node %s = %s", (n, nodes[n]))
def intersectWithPlane(): """Intersect the selection with a plane.""" FL = selection.check() if not FL: return res = askItems([_I('Name suffix','intersect'), _I('Point',(0.0,0.0,0.0)), _I('Normal',(1.0,0.0,0.0)), ],caption = 'Define the cutting plane') if res: suffix = res['Name suffix'] P = res['Point'] N = res['Normal'] M = [ S.intersectionWithPlane(P,N) for S in FL ] draw(M,color='red') export(dict([('%s/%s' % (n,suffix), m) for (n,m) in zip(selection,M)]))
def show_nodes(): n = 0 data = askItems([_I('node number',n), ]) n = int(data['node number']) if n > 0: nodes,elems = PF['surface'] print("Node %s = %s",(n,nodes[n]))
def createCube(): res = askItems([_I("name", "__auto__")]) if res: name = res["name"] S = Cube() export({name: S}) selection.set([name]) selection.draw()
def createGrid(): res = askItems([_I('name','__auto__'), _I('nx',3), _I('ny',3), _I('b',1), _I('h',1), ]) if res: globals().update(res) #name = res['name'] #nx = res['nx'] #ny = res['ny'] #b = S = TriSurface(simple.rectangle(nx,ny,b,h,diag='d')) export({name:S}) selection.set([name]) selection.draw()
def export_selection(): if selection is None: warning("You need to pick something first.") return sel = getCollection(selection) if len(sel) == 0: warning("Nothing to export!") return options = ['List','Single items'] default = options[0] if len(sel) == 1: default = options[1] res = askItems([ _I('Export with name',''), _I('Export as',default,itemtype='radio',choices=options), ]) if res: name = res['Export with name'] opt = res['Export as'][0] if opt == 'L': export({name:sel}) elif opt == 'S': export(dict([ (name+"-%s"%i,v) for i,v in enumerate(sel)]))
def edit_point(pt): x,y,z = pt dia = None def close(): dia.close() def accept(): dia.acceptData() res = dia.results return [ res[i] for i in 'xyz' ] dia = widgets.InputDialog( items = [_I(x=x,y=y,z=z),] ) dia.show()
def showCameraTool(): global dialog cam = pf.canvas.camera settings = getCameraSettings(cam) settings['near'] = cam.near / cam.dist settings['far'] = cam.far / cam.dist dialog = Dialog( store=settings, items=[ _I('focus', text='Focus', itemtype='point', tooltip='The point where the camera is looking at.'), _I('dist', text='Distance', tooltip='The distance of the camera to the focus point.'), _I('fovy', text='Field of View', tooltip='The vertical opening angle of the camera lens.'), _I('aspect', text='Aspect ratio', tooltip= 'The ratio of the vertical over the horizontal lens opening angles.' ), # _I('area',text='Visible area',tooltip='Relative part of the camera area that is visible in the viewport.'), _I('near', text='Near clipping plane', itemtype='fslider', func=setNear, tooltip='Distance of the near clipping plane to the camera.'), _I('far', 100, text='Far clipping plane', itemtype='fslider', func=setFar, tooltip='Distance of the far clipping plane to the camera.'), ], actions=[ ('Close', close), # ('Apply',apply), ], default='Close', ) dialog.show() cam.modelview_callback = updateSettings
def showImage3D(): clear() im,res = selectImage([_I('pixel cell',choices=['dot','quad'])]) if im: drawImage3D(im,pixel=res['pixel cell'])
def selectImage(extra_items=[]): """Open a dialog to read an image file. """ global image from gui.widgets import ImageView from plugins.imagearray import resizeImage # some default values filename = getcfg('datadir')+'/butterfly.png' w,h = 200,200 image = None # the loaded image diag = None # the image dialog # construct the image previewer widget viewer = ImageView(filename,maxheight=h) def select_image(fn): """Helper function to load and preview image""" fn = askImageFile(fn) if fn: viewer.showImage(fn) load_image(fn) return fn def load_image(fn): """Helper function to load the image and set its size in the dialog""" global image image = resizeImage(fn) if image.isNull(): warning("Could not load image '%s'" % fn) return None w,h = image.width(),image.height() print("size = %sx%s" % (w,h)) diag = currentDialog() if diag: diag.updateData({'nx':w,'ny':h}) maxsiz = 40000. if w*h > maxsiz: scale = sqrt(maxsiz/w/h) w = int(w*scale) h = int(h*scale) return w,h res = askItems([ _I('filename',filename,text='Image file',itemtype='button',func=select_image), _I('viewer',viewer,itemtype='widget'), # the image previewing widget _I('nx',w,text='width'), _I('ny',h,text='height'), ] + extra_items) if not res: return None if image is None: print("Loading image") load_image(filename) image = resizeImage(image,res['nx'],res['ny']) return image,res