diff options
author | Karl Berry <karl@freefriends.org> | 2016-04-07 16:52:56 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-04-07 16:52:56 +0000 |
commit | e1e1d6fa3224440612d3ad6595c413f88d552702 (patch) | |
tree | eaa3301c9fecd1d01baa642b2e483fee4430bcee /Master/texmf-dist/asymptote | |
parent | 0eefec13710bb4d6aff6838a6efc463912506ee9 (diff) |
asymptote 2.37
git-svn-id: svn://tug.org/texlive/trunk@40303 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/asymptote')
26 files changed, 981 insertions, 718 deletions
diff --git a/Master/texmf-dist/asymptote/GUI/CubicBezier.py b/Master/texmf-dist/asymptote/GUI/CubicBezier.py index 6455b700a79..2eb62577b0a 100755 --- a/Master/texmf-dist/asymptote/GUI/CubicBezier.py +++ b/Master/texmf-dist/asymptote/GUI/CubicBezier.py @@ -82,16 +82,19 @@ if __name__ == '__main__': pointList = makeBezier((-80,0),(-150,40),(150,120),(80,0),0.5) from timeit import Timer t = Timer('makeBezier((-80,0),(-40,-40),(40,120),(80,0),1)','from __main__ import makeBezier') - print pointList - print len(pointList) + print (pointList) + print (len(pointList)) iterations = 1000 time = t.timeit(iterations) - print "%d iterations took %f seconds (%f ms for each)."%(iterations,time,1000.0*time/iterations) + print ("{:d} iterations took {:f} seconds ({:f} ms for each).".format(iterations,time,1000.0*time/iterations)) points = [] for point in pointList: points.append(point[0]) points.append(-point[1]) - from Tkinter import * + if sys.version_info >= (3, 0): + from tkinter import * + else: + from Tkinter import * root = Tk() canv = Canvas(root,scrollregion=(-100,-100,100,100)) canv.pack() diff --git a/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py b/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py index f4a247a411d..779d0330a81 100755 --- a/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py +++ b/Master/texmf-dist/asymptote/GUI/UndoRedoStack.py @@ -13,10 +13,10 @@ class action: self.act = act self.inv = inv def undo(self): - #print "Undo:",self + #print ("Undo:",self) self.inv() def redo(self): - #print "Redo:",self + #print ("Redo:",self) self.act() def __str__(self): return "A generic action" @@ -33,7 +33,7 @@ class actionStack: def add(self,action): self.undoStack.append(action) - #print "Added",action + #print ("Added",action) self.redoStack = [] def undo(self): @@ -54,13 +54,13 @@ class actionStack: op.undo() self.redoStack.append(op) elif op is endActionGroup: - raise Exception,"endActionGroup without previous beginActionGroup" + raise Exception("endActionGroup without previous beginActionGroup") else: self.redoStack.append(op) op.undo() - #print "undid",op + #print ("undid",op) else: - pass #print "nothing to undo" + pass #print ("nothing to undo") def redo(self): if len(self.redoStack) > 0: @@ -80,13 +80,13 @@ class actionStack: op.redo() self.undoStack.append(op) elif op is endActionGroup: - raise Exception,"endActionGroup without previous beginActionGroup" + raise Exception("endActionGroup without previous beginActionGroup") else: self.undoStack.append(op) op.redo() - #print "redid",op + #print ("redid",op) else: - pass #print "nothing to redo" + pass #print ("nothing to redo") def setCommitLevel(self): self.commitLevel = len(self.undoStack) @@ -105,9 +105,9 @@ class actionStack: if __name__=='__main__': import sys def opq(): - print "action1" + print ("action1") def unopq(): - print "inverse1" + print ("inverse1") q = action(opq,unopq) w = action(lambda:sys.stdout.write("action2\n"),lambda:sys.stdout.write("inverse2\n")) e = action(lambda:sys.stdout.write("action3\n"),lambda:sys.stdout.write("inverse3\n")) diff --git a/Master/texmf-dist/asymptote/GUI/xasy.py b/Master/texmf-dist/asymptote/GUI/xasy.py index ffca16a1e2d..f160404c19a 100755 --- a/Master/texmf-dist/asymptote/GUI/xasy.py +++ b/Master/texmf-dist/asymptote/GUI/xasy.py @@ -10,8 +10,11 @@ ############################################################################ import getopt,sys,signal -from Tkinter import * import xasyMainWin +if sys.version_info >= (3, 0): + from tkinter import * +else: + from Tkinter import * signal.signal(signal.SIGINT,signal.SIG_IGN) @@ -22,11 +25,11 @@ try: if(len(opts)>=1): mag = float(opts[0][1]) except: - print "Invalid arguments." - print "Usage: xasy.py [-x magnification] [filename]" + print ("Invalid arguments.") + print ("Usage: xasy.py [-x magnification] [filename]") sys.exit(1) if(mag <= 0.0): - print "Magnification must be positive." + print ("Magnification must be positive.") sys.exit(1) if(len(args)>=1): app = xasyMainWin.xasyMainWin(root,args[0],mag) diff --git a/Master/texmf-dist/asymptote/GUI/xasy2asy.py b/Master/texmf-dist/asymptote/GUI/xasy2asy.py index 3a2c1bcbe7b..06c0dbd7f54 100755 --- a/Master/texmf-dist/asymptote/GUI/xasy2asy.py +++ b/Master/texmf-dist/asymptote/GUI/xasy2asy.py @@ -12,10 +12,15 @@ import sys,os,signal,threading from subprocess import * from string import * import xasyOptions -import Queue -from Tkinter import * from tempfile import mkdtemp +if sys.version_info >= (3, 0): + from tkinter import * + import queue +else: + from Tkinter import * + import Queue as queue + # PIL support is now mandatory due to rotations try: from PIL import ImageTk @@ -50,14 +55,21 @@ def startQuickAsy(): AsyTempDir=mkdtemp(prefix="asy_")+os.sep if sys.platform[:3] == 'win': quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q", - "-o"+AsyTempDir,"-inpipe=0","-outpipe=2"],stdin=PIPE,stderr=PIPE) + "-o"+AsyTempDir,"-inpipe=0","-outpipe=2"],stdin=PIPE, + stderr=PIPE,universal_newlines=True) fout=quickAsy.stdin fin=quickAsy.stderr else: (rx,wx) = os.pipe() (ra,wa) = os.pipe() + if sys.version_info >= (3, 4): + os.set_inheritable(rx, True) + os.set_inheritable(wx, True) + os.set_inheritable(ra, True) + os.set_inheritable(wa, True) quickAsy=Popen([xasyOptions.options['asyPath'],"-noV","-multiline","-q", - "-o"+AsyTempDir,"-inpipe="+str(rx),"-outpipe="+str(wa)]) + "-o"+AsyTempDir,"-inpipe="+str(rx),"-outpipe="+str(wa)], + close_fds=False) fout=os.fdopen(wx,'w') fin=os.fdopen(ra,'r') if quickAsy.returncode != None: @@ -111,7 +123,7 @@ class asyTransform: self.x,self.y,self.xx,self.xy,self.yx,self.yy = initTuple self.deleted = delete else: - raise Exception,"Illegal initializer for asyTransform" + raise Exception("Illegal initializer for asyTransform") def getCode(self): """Obtain the asy code that represents this transform""" @@ -135,7 +147,7 @@ class asyTransform: elif len(other) == 2: return ((self.t[0]+self.t[2]*other[0]+self.t[3]*other[1]),(self.t[1]+self.t[4]*other[0]+self.t[5]*other[1])) else: - raise Exception, "Illegal multiplier of %s"%str(type(other)) + raise Exception("Illegal multiplier of {:s}".format(str(type(other)))) elif isinstance(other,asyTransform): result = asyTransform((0,0,0,0,0,0)) result.x = self.x+self.xx*other.x+self.xy*other.y @@ -147,7 +159,7 @@ class asyTransform: result.t = (result.x,result.y,result.xx,result.xy,result.yx,result.yy) return result else: - raise Exception, "Illegal multiplier of %s"%str(type(other)) + raise Exception("Illegal multiplier of {:s}".format(str(type(other)))) def identity(): return asyTransform((0,0,1,0,0,1)) @@ -181,7 +193,7 @@ class asyPen(asyObj): def updateCode(self,mag=1.0): """Generate the pen's code""" - self.asyCode = "rgb(%g,%g,%g)"%self.color+"+"+str(self.width) + self.asyCode = "rgb({:g},{:g},{:g})+{:s}".format(self.color[0], self.color[1], self.color[2],str(self.width)) if len(self.options) > 0: self.asyCode += "+"+self.options @@ -226,23 +238,7 @@ class asyPen(asyObj): def tkColor(self): """Return the tk version of the pen's color""" self.computeColor() - r,g,b = self.color - r,g,b = int(256*r),int(256*g),int(256*b) - if r == 256: - r = 255 - if g == 256: - g = 255 - if b == 256: - b = 255 - r,g,b = map(hex,(r,g,b)) - r,g,b = r[2:],g[2:],b[2:] - if len(r) < 2: - r += '0' - if len(g) < 2: - g += '0' - if len(b) < 2: - b += '0' - return'#'+r+g+b + return '#{}'.format("".join(["{:02x}".format(min(int(256*a),255)) for a in self.color])) class asyPath(asyObj): """A python wrapper for an asymptote path""" @@ -353,7 +349,7 @@ class asyPath(asyObj): line=fin.readline() line=line.replace("\n","") pathStrLines.append(line) - oneLiner = "".join(split(join(pathStrLines))) + oneLiner = "".join(pathStrLines).replace(" ", "") splitList = oneLiner.split("..") nodes = [a for a in splitList if a.find("controls")==-1] self.nodeSet = [] @@ -437,7 +433,7 @@ class xasyItem: def asyfy(self,mag=1.0): self.removeFromCanvas() self.imageList = [] - self.imageHandleQueue = Queue.Queue() + self.imageHandleQueue = queue.Queue() worker = threading.Thread(target=self.asyfyThread,args=(mag,)) worker.start() item = self.imageHandleQueue.get() @@ -461,23 +457,22 @@ class xasyItem: fout.write("reset;\n") fout.write("initXasyMode();\n") fout.write("atexit(null);\n") - global console for line in self.getCode().splitlines(): fout.write(line+"\n"); - fout.write("deconstruct(%f);\n"%mag) + fout.write("deconstruct({:f});\n".format(mag)) fout.flush() - format = "png" - maxargs = int(split(fin.readline())[0]) + maxargs = int(fin.readline().split()[0]) boxes=[] batch=0 n=0 text = fin.readline() - template=AsyTempDir+"%d_%d.%s" + # template=AsyTempDir+"%d_%d.%s" + fileformat = "png" def render(): for i in range(len(boxes)): - l,b,r,t = [float(a) for a in split(boxes[i])] - name=template%(batch,i+1,format) - self.imageHandleQueue.put((name,format,(l,b,r,t),i)) + l,b,r,t = [float(a) for a in boxes[i].split()] + name="{:s}{:d}_{:d}.{:s}".format(AsyTempDir,batch,i+1,fileformat) + self.imageHandleQueue.put((name,fileformat,(l,b,r,t),i)) while text != "Done\n" and text != "Error\n": boxes.append(text) text = fin.readline() @@ -595,14 +590,14 @@ class xasyShape(xasyDrawnItem): def __str__(self): """Create a string describing this shape""" - return "xasyShape code:%s"%("\n\t".join(self.getCode().splitlines())) + return "xasyShape code:{:s}".format("\n\t".join(self.getCode().splitlines())) class xasyFilledShape(xasyShape): """A filled shape drawn on the GUI""" def __init__(self,path,pen=asyPen(),transform=identity()): """Initialize this shape with a path, pen, and transform""" if path.nodeSet[-1] != 'cycle': - raise Exception,"Filled paths must be cyclic" + raise Exception("Filled paths must be cyclic") xasyShape.__init__(self,path,pen,transform) def updateCode(self,mag=1.0): @@ -661,7 +656,7 @@ class xasyFilledShape(xasyShape): def __str__(self): """Return a string describing this shape""" - return "xasyFilledShape code:%s"%("\n\t".join(self.getCode().splitlines())) + return "xasyFilledShape code:{:s}".format("\n\t".join(self.getCode().splitlines())) class xasyText(xasyItem): """Text created by the GUI""" @@ -690,11 +685,11 @@ class xasyText(xasyItem): if self.onCanvas == None: self.onCanvas = canvas elif self.onCanvas != canvas: - raise Exception,"Error: item cannot be added to more than one canvas" + raise Exception("Error: item cannot be added to more than one canvas") self.asyfy(mag) def __str__(self): - return "xasyText code:%s"%("\n\t".join(self.getCode().splitlines())) + return "xasyText code:{:s}".format("\n\t".join(self.getCode().splitlines())) class xasyScript(xasyItem): """A set of images create from asymptote code. It is always deconstructed.""" @@ -718,7 +713,7 @@ class xasyScript(xasyItem): for xform in self.transform: if not isFirst: self.asyCode+=",\n" - self.asyCode += "indexedTransform(%d,%s)"%(count,str(xform)) + self.asyCode += "indexedTransform({:d},{:s})".format(count,str(xform)) isFirst = False count += 1 self.asyCode += ");\n" @@ -754,7 +749,7 @@ class xasyScript(xasyItem): if self.onCanvas == None: self.onCanvas = canvas elif self.onCanvas != canvas: - raise Exception,"Error: item cannot be added to more than one canvas" + raise Exception("Error: item cannot be added to more than one canvas") self.asyfy(mag) def __str__(self): diff --git a/Master/texmf-dist/asymptote/GUI/xasyActions.py b/Master/texmf-dist/asymptote/GUI/xasyActions.py index 38aae1d5c7e..95411c5d9a4 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyActions.py +++ b/Master/texmf-dist/asymptote/GUI/xasyActions.py @@ -9,9 +9,13 @@ # ########################################################################### import math +import sys import UndoRedoStack import xasy2asy -from Tkinter import * +if sys.version_info >= (3, 0): + from tkinter import * +else: + from Tkinter import * class translationAction(UndoRedoStack.action): def __init__(self,owner,itemList,indexList,translation): diff --git a/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py b/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py index 998ee4c7c25..75ddeafa2d2 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py +++ b/Master/texmf-dist/asymptote/GUI/xasyBezierEditor.py @@ -10,11 +10,16 @@ # ########################################################################### -from Tkinter import * import math +import sys from CubicBezier import * import xasy2asy +if sys.version_info >= (3, 0): + from tkinter import * +else: + from Tkinter import * + class node: def __init__(self,precontrol,node,postcontrol,uid,isTied = True): self.node = node diff --git a/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py b/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py index d09196a41be..8f3de4034fe 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py +++ b/Master/texmf-dist/asymptote/GUI/xasyCodeEditor.py @@ -15,7 +15,6 @@ from tempfile import mkstemp from os import remove from os import fdopen from os import path -from string import split import xasyOptions def getText(text=""): @@ -26,7 +25,7 @@ def getText(text=""): tempf.close() try: cmdpath,cmd = path.split(path.expandvars(xasyOptions.options['externalEditor'])) - split_cmd = split(cmd) + split_cmd = cmd.split() cmdpart = [path.join(cmdpath,split_cmd[0])] argpart = split_cmd[1:]+[temp[1]] arglist = cmdpart+argpart @@ -45,4 +44,4 @@ def getText(text=""): if __name__ == '__main__': #run a test - print getText("Here is some text to edit") + print (getText("Here is some text to edit")) diff --git a/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py b/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py index 7415be205c4..217835bdbb0 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py +++ b/Master/texmf-dist/asymptote/GUI/xasyColorPicker.py @@ -10,8 +10,15 @@ # ############################################################################ -from Tkinter import * -import tkColorChooser +import sys + +if sys.version_info >= (3, 0): + from tkinter import * + from tkinter import colorchooser +else: + from Tkinter import * + import tkColorChooser as colorchooser + asyColors = { "black":(0,0,0), "white":(1,1,1), "gray":(0.5,0.5,0.5), @@ -145,28 +152,13 @@ def makeRGBfromTkColor(tkColor): b /= 255.0 return (r,g,b) -def RGBreal255((r,g,b)): +def RGBreal255(rgb): """Convert an RGB color from 0-1 to 0-255""" - a,b,c = (256*r,256*g,256*b) - if a == 256: - a = 255 - if b == 256: - b = 255 - if c == 256: - c = 255 - return map(int,(a,b,c)) + return [min(int(256*a),255) for a in rgb] -def RGB255hex((r,g,b)): +def RGB255hex(rgb): """Make a color in the form #rrggbb in hex from r,g,b in 0-255""" - rs,gs,bs = map(hex,(r,g,b)) - rs,gs,bs = rs[2:],gs[2:],bs[2:] - if len(rs) < 2: - rs += '0' - if len(gs) < 2: - gs += '0' - if len(bs) < 2: - bs += '0' - return '#'+rs+gs+bs + return "#{}".format("".join(["{:02x}".format(a) for a in rgb])) class xasyColorDlg(Toplevel): """A dialog for choosing an asymptote color. It displays the usual asy presets and allows custom rgb colors""" @@ -216,8 +208,8 @@ class xasyColorDlg(Toplevel): """Close the dialog forcibly""" self.destroy() def getCustom(self): - """Request a custom RGB color using a tkColorChooser""" - result=tkColorChooser.askcolor(initialcolor=RGB255hex(RGBreal255(self.color)),title="Custom Color",parent=self) + """Request a custom RGB color using a colorchooser""" + result=colorchooser.askcolor(initialcolor=RGB255hex(RGBreal255(self.color)),title="Custom Color",parent=self) if result != (None,None): self.setColor((result[0][0]/255.0,result[0][1]/255.0,result[0][2]/255.0)) def cancel(self): @@ -235,7 +227,7 @@ class xasyColorDlg(Toplevel): """Use this method to prompt for a color. It returns the new color or the old color if the user cancelled the operation. e.g: - print xasyColorDlg(Tk()).getColor((1,1,0)) + print (xasyColorDlg(Tk()).getColor((1,1,0))) """ self.setColor(initialColor) self.oldColor = initialColor diff --git a/Master/texmf-dist/asymptote/GUI/xasyFile.py b/Master/texmf-dist/asymptote/GUI/xasyFile.py index 890f1ad3eef..7516fc7d3b5 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyFile.py +++ b/Master/texmf-dist/asymptote/GUI/xasyFile.py @@ -28,7 +28,7 @@ def parseFile(inFile): #lines = [line for line in lines.splitlines() if not line.startswith("//")] result = [] if lines[0] != "initXasyMode();": - raise xasyFileError,"Invalid file format: First line must be \"initXasyMode();\"" + raise xasyFileError("Invalid file format: First line must be \"initXasyMode();\"") lines.pop(0) lineCount = 2 lineNum = len(lines) @@ -37,14 +37,14 @@ def parseFile(inFile): lines.pop(0) if not line.isspace() and len(line)>0: try: - #print "Line %d: %s"%(lineCount,line), + #print ("Line {:d}: {:s}".format(lineCount,line)) lineResult = parseLine(line.strip(),lines) except: - raise xasyParseError,"Parsing error: line %d in %s\n%s"%(lineCount,inFile.name,line) + raise xasyParseError("Parsing error: line {:d} in {:s}\n{:s}".format(lineCount,inFile.name,line)) if lineResult != None: result.append(lineResult) - #print "\tproduced: %s"%str(lineResult) + #print ("\tproduced: {:s}".format(str(lineResult))) lineCount += lineNum-len(lines) lineNum = len(lines) return result @@ -105,7 +105,7 @@ def parseTransformExpression(line): global pendingTransforms stackCmd = line[len(transformPrefix)+1:line.find("(")] if line[-2:] != ");": - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") args = line[line.find("(")+1:-2] if stackCmd == "push": t = asyTransform(eval(args)) @@ -113,19 +113,19 @@ def parseTransformExpression(line): elif stackCmd == "add": parseIndexedTransforms(args) else: - raise xasyParseError,"Invalid transform stack command." + raise xasyParseError("Invalid transform stack command.") return None def parseLabel(line): """Parse an asy Label statement, returning an xasyText item""" if not (line.startswith("Label(") and line.endswith(",align=SE)")): - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") args = line[6:-1] loc2 = args.rfind(",align=SE") loc1 = args.rfind(",",0,loc2-1) loc = args.rfind(",(",0,loc1-1) if loc < 2: - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") text = args[1:loc-1] location = eval(args[loc+1:args.find("),",loc)+1]) pen = args[loc:loc2] @@ -143,7 +143,7 @@ def parseLabelCommand(line): e.g.: label(Label("Hello world!",(0,0),rgb(0,0,0)+0.5,align=SE)); """ if line[-2:] != ");": - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") arguments = line[6:-2] return parseLabel(arguments) @@ -155,7 +155,7 @@ def parseDrawCommand(line): e.g.: draw((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1),rgb(1,0,1)+1.5); """ if line[-2:] != ");": - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") args = line[5:-2] loc = args.rfind(",rgb") path = args[:loc] @@ -171,7 +171,7 @@ def parseFillCommand(line): e.g.: fill((0,0)..controls(0.33,0.33)and(0.66,0.66)..(1,1)..controls(0.66,0)and(0.33,0)..cycle,rgb(1,0,1)+1.5); """ if line[-2:] != ");": - raise xasyParseError,"Invalid syntax" + raise xasyParseError("Invalid syntax") args = line[5:-2] loc = args.rfind(",rgb") path = args[:loc] @@ -197,13 +197,13 @@ def parsePen(pen): options = "" return asyPen(color,width,options) except: - raise xasyParseError,"Invalid pen" + raise xasyParseError("Invalid pen") def parsePathExpression(expr): """Parse an asy path returning an asyPath()""" result = asyPath() expr = "".join(expr.split()) - #print expr + #print (expr) if expr.find("controls") != -1: #parse a path with control points tokens = expr.split("..") @@ -211,18 +211,18 @@ def parsePathExpression(expr): for a in range(len(nodes)): if nodes[a] != "cycle": nodes[a] = eval(nodes[a]) - controls = [map(eval,a.replace("controls","").split("and")) for a in tokens if a.startswith("controls")] + controls = [[eval(b) for b in a.replace("controls", "").split("and")] for a in tokens if a.startswith("controls")] result.initFromControls(nodes, controls) else: #parse a path without control points tokens = re.split(r"(::|--|\.\.)",expr) linkSet = re.findall("::|--|\.\.",expr) nodeSet = [a for a in tokens if not re.match(r"::|--|\.\.",a)] - #print nodeSet + #print (nodeSet) for a in range(len(nodeSet)): if nodeSet[a] != "cycle": nodeSet[a] = eval(nodeSet[a]) - #print nodeSet + #print (nodeSet) result.initFromNodeList(nodeSet, linkSet) return result @@ -250,7 +250,7 @@ def parseLine(line,lines): return parseFillCommand(takeUntilSemicolon(line,lines)) elif line.startswith("exitXasyMode();"): return None - raise Exception,"Could not parse the line" + raise Exception("Could not parse the line") fileHeader = """initXasyMode(); // This file was generated by xasy. It may be edited manually, however, a strict @@ -280,28 +280,28 @@ if __name__ == '__main__': name = "../../xasyTest.asy" f = open(name,"rt") except: - print "Could not open file." + print ("Could not open file.") asy.quit() sys.exit(1) fileItems = [] try: fileItems = parseFile(f) - res = map(str,fileItems) - print "----------------------------------" - print "Objects in %s"%f.name - print "----------------------------------" + res = [str(a) for a in fileItems] + print ("----------------------------------") + print ("Objects in {:s}".format(f.name)) + print ("----------------------------------") for a in res: - print a - print "----------------------------------" - print "successful parse" + print (a) + print ("----------------------------------") + print ("successful parse") f.close() except: f.close() - print "parse failed" + print ("parse failed") raise - print "making a file" + print ("making a file") f = open("testfile.asy","wt") saveFile(f,fileItems) f.close() diff --git a/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py b/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py index 3afecfd349c..7f07d5748d7 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py +++ b/Master/texmf-dist/asymptote/GUI/xasyGUIIcons.py @@ -53,11 +53,11 @@ iconB64 = { def createGIF(key): """Create a gif file from the data in the iconB64 list of icons""" if key not in iconB64.keys(): - print "Error: %s not found in icon list."%key - print "Available icons:",iconB64.keys() + print ("Error: {:s} not found in icon list.".format(key)) + print ("Available icons:",iconB64.keys()) else: - print "Generating %s.gif"%key - open("%s.gif"%key,"w").write(base64.decodestring(iconB64[key])) + print ("Generating {:s}.gif".format(key)) + open("{:s}.gif".format(key),"w").write(base64.decodestring(iconB64[key])) def createGIFs(): """Create the files for all the icons in iconB64""" @@ -69,24 +69,24 @@ def createStrFromGif(gifFile): return base64.encodestring(gifFile.read()) if __name__=='__main__': - print "Testing the xasyGUIIcons module." - print "Generating all the GIFs:" + print ("Testing the xasyGUIIcons module.") + print ("Generating all the GIFs:") createGIFs() - print "Checking consistency of all icons in iconB64" + print ("Checking consistency of all icons in iconB64") allpassed = True for icon in iconB64.keys(): - print ("Checking %s"%icon), - if createStrFromGif(open("%s.gif"%icon,"rb")) == iconB64[icon]: - print "\tPassed." + print ("Checking {:s}".format(icon)) + if createStrFromGif(open("{:s}.gif".format(icon),"rb")) == iconB64[icon]: + print ("\tPassed.") else: - print "\tFailed." + print ("\tFailed.") allpassed= False if allpassed: - print "All files succeeded." + print ("All files succeeded.") s = raw_input("Delete generated files? (y/n)") if s == "y": for name in iconB64.keys(): - print "Deleting %s.gif"%name, + print ("Deleting {:s}.gif".format(name)) os.unlink(name+".gif") - print "\tdone" - print "Done" + print ("\tdone") + print ("Done") diff --git a/Master/texmf-dist/asymptote/GUI/xasyMainWin.py b/Master/texmf-dist/asymptote/GUI/xasyMainWin.py index 657d24ba81b..b0549e72f9c 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyMainWin.py +++ b/Master/texmf-dist/asymptote/GUI/xasyMainWin.py @@ -11,15 +11,23 @@ ########################################################################### import os +import sys from string import * import subprocess import math import copy -from Tkinter import * -import tkMessageBox -import tkFileDialog -import tkSimpleDialog +if sys.version_info >= (3, 0): + # python3 + from tkinter import * + from tkinter import filedialog, messagebox, simpledialog +else: + # python2 + # from Tkinter import * + import tkFileDialog as filedialog + import tkMessageBox as messagebox + import tkSimpleDialog as simpledialog + import threading import time @@ -56,12 +64,9 @@ class xasyMainWin: self.bindGlobalEvents() self.createWidgets() self.resetGUI() - if sys.platform[:3] == "win": - site="http://effbot.org/downloads/PIL-1.1.7.win32-py2.7.exe" - else: - site="http://effbot.org/downloads/Imaging-1.1.7.tar.gz" + site="" if not PILAvailable: - tkMessageBox.showerror("Failed Dependencies","An error occurred loading the required PIL library. Please install "+site) + messagebox.showerror("Failed Dependencies","An error occurred loading the required PIL library. Please install Pillow from http://pypi.python.org/pypi/Pillow") self.parent.destroy() sys.exit(1) if file != None: @@ -449,12 +454,12 @@ class xasyMainWin: #test the asyProcess startQuickAsy() if not quickAsyRunning(): - if tkMessageBox.askyesno("Xasy Error","Asymptote could not be executed.\r\nTry to find Asymptote automatically?"): + if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nTry to find Asymptote automatically?"): xasyOptions.setAsyPathFromWindowsRegistry() xasyOptions.save() startQuickAsy() while not quickAsyRunning(): - if tkMessageBox.askyesno("Xasy Error","Asymptote could not be executed.\r\nEdit settings?"): + if messagebox.askyesno("Xasy Error","Asymptote could not be executed.\r\nEdit settings?"): xasyOptionsDialog.xasyOptionsDlg(self.parent) xasyOptions.save() startQuickAsy() @@ -466,7 +471,7 @@ class xasyMainWin: self.mainCanvas.delete("grid") if not self.gridVisible: return - left,top,right,bottom = map(int,self.mainCanvas.cget("scrollregion").split()) + left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()] gridyspace = int(self.magnification*self.gridyspace) gridxspace = int(self.magnification*self.gridxspace) if gridxspace >= 3 and gridyspace >= 3: @@ -484,7 +489,7 @@ class xasyMainWin: self.mainCanvas.delete("axes") if not self.axesVisible: return - left,top,right,bottom = map(int,self.mainCanvas.cget("scrollregion").split()) + left,top,right,bottom = [int(float(a)) for a in self.mainCanvas.cget("scrollregion").split()] self.mainCanvas.create_line(0,top,0,bottom,tags=("axes","yaxis"),fill=self.axiscolor) self.mainCanvas.create_line(left,0,right,0,tags=("axes","xaxis"),fill=self.axiscolor) axisxspace = int(self.magnification*self.axisxspace) @@ -513,12 +518,12 @@ class xasyMainWin: w,h = self.mainCanvas.winfo_width(),self.mainCanvas.winfo_height() if right-left < w: extraw = w-(right-left) - right += extraw/2 - left -= extraw/2 + right += extraw//2 + left -= extraw//2 if bottom-top < h: extrah = h-(bottom-top) - bottom += extrah/2 - top -= extrah/2 + bottom += extrah//2 + top -= extrah//2 self.mainCanvas.config(scrollregion=(left,top,right,bottom)) #self.mainCanvas.xview(MOVETO,float(split(self.mainCanvas["scrollregion"])[0])) #self.mainCanvas.yview(MOVETO,float(split(self.mainCanvas["scrollregion"])[1])) @@ -549,7 +554,7 @@ class xasyMainWin: self.bindEvents(item.IDTag) def canQuit(self,force=False): - #print "Quitting" + #print ("Quitting") if not force and not self.testOrAcquireLock(): return try: @@ -557,10 +562,10 @@ class xasyMainWin: except: pass if self.undoRedoStack.changesMade(): - result = tkMessageBox._show("xasy","File has been modified.\nSave changes?",icon=tkMessageBox.QUESTION,type=tkMessageBox.YESNOCANCEL) - if str(result) == tkMessageBox.CANCEL: + result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL) + if str(result) == messagebox.CANCEL: return - elif result == tkMessageBox.YES: + elif result == messagebox.YES: self.fileSaveCmd() try: os.rmdir(getAsyTempDir()) @@ -595,19 +600,19 @@ class xasyMainWin: self.fileItems = xasyFile.parseFile(f) f.close() except IOError: - tkMessageBox.showerror("File Opening Failed.","File could not be opened.") + messagebox.showerror("File Opening Failed.","File could not be opened.") self.fileItems = [] except: self.fileItems = [] self.autoMakeScript = True - if self.autoMakeScript or tkMessageBox.askyesno("Error Opening File", "File was not recognized as an xasy file.\nLoad as a script item?"): + if self.autoMakeScript or messagebox.askyesno("Error Opening File", "File was not recognized as an xasy file.\nLoad as a script item?"): try: item = xasyScript(self.mainCanvas) f.seek(0) item.setScript(f.read()) self.addItemToFile(item) except: - tkMessageBox.showerror("File Opening Failed.","Could not load as a script item.") + messagebox.showerror("File Opening Failed.","Could not load as a script item.") self.fileItems = [] self.populateCanvasWithItems() self.populatePropertyList() @@ -663,12 +668,12 @@ class xasyMainWin: if(not self.testOrAcquireLock()): return self.releaseLock() - #print "Create New File" + #print ("Create New File") if self.undoRedoStack.changesMade(): - result = tkMessageBox._show("xasy","File has been modified.\nSave changes?",icon=tkMessageBox.QUESTION,type=tkMessageBox.YESNOCANCEL) - if str(result) == tkMessageBox.CANCEL: + result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL) + if str(result) == messagebox.CANCEL: return - elif result == tkMessageBox.YES: + elif result == messagebox.YES: self.fileSaveCmd() self.resetGUI() @@ -676,25 +681,25 @@ class xasyMainWin: if(not self.testOrAcquireLock()): return self.releaseLock() - #print "Open a file" + #print ("Open a file") if self.undoRedoStack.changesMade(): - result = tkMessageBox._show("xasy","File has been modified.\nSave changes?",icon=tkMessageBox.QUESTION,type=tkMessageBox.YESNOCANCEL) - if str(result) == tkMessageBox.CANCEL: + result = messagebox._show("xasy","File has been modified.\nSave changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL) + if str(result) == messagebox.CANCEL: return - elif result == tkMessageBox.YES: + elif result == messagebox.YES: self.fileSaveCmd() - filename=tkFileDialog.askopenfilename(filetypes=[("asy files","*.asy"),("All files","*")],title="Open File",parent=self.parent) + filename=filedialog.askopenfilename(filetypes=[("asy files","*.asy"),("All files","*")],title="Open File",parent=self.parent) if type(filename) != type((0,)) and filename != None and filename != '': self.filename = filename self.openFile(self.filename) def fileSaveCmd(self): - #print "Save current file" + #print ("Save current file") if(not self.testOrAcquireLock()): return self.releaseLock() if self.filename == None: - filename=tkFileDialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File") + filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File") if type(filename) != type((0,)) and filename != None and filename != '': self.filename = filename if self.filename != None: @@ -704,8 +709,8 @@ class xasyMainWin: if(not self.testOrAcquireLock()): return self.releaseLock() - #print "Save current file as" - filename=tkFileDialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File") + #print ("Save current file as") + filename=filedialog.asksaveasfilename(defaultextension=".asy",filetypes=[("asy files","*.asy")],initialfile="newDrawing.asy",parent=self.parent,title="Save File") if type(filename) != type((0,)) and filename != None and filename != '': self.filename = filename self.saveFile(self.filename) @@ -731,20 +736,20 @@ class xasyMainWin: return self.releaseLock() if inFile == None: - if tkMessageBox.askyesno("xasy","File has not been saved.\nSave?"): + if messagebox.askyesno("xasy","File has not been saved.\nSave?"): self.fileSaveAsCmd() inFile = self.filename else: return elif self.undoRedoStack.changesMade(): - choice = tkMessageBox._show("xasy","File has been modified.\nOnly saved changes can be exported.\nDo you want to save changes?",icon=tkMessageBox.QUESTION,type=tkMessageBox.YESNOCANCEL) + choice = messagebox._show("xasy","File has been modified.\nOnly saved changes can be exported.\nDo you want to save changes?",icon=messagebox.QUESTION,type=messagebox.YESNOCANCEL) choice = str(choice) - if choice != tkMessageBox.YES: + if choice != messagebox.YES: return else: self.fileSaveCmd() name = os.path.splitext(os.path.basename(self.filename))[0]+'.'+outFormat - outfilename = tkFileDialog.asksaveasfilename(defaultextension = '.'+outFormat,filetypes=[(outFormat+" files","*."+outFormat)],initialfile=name,parent=self.parent,title="Choose output file") + outfilename = filedialog.asksaveasfilename(defaultextension = '.'+outFormat,filetypes=[(outFormat+" files","*."+outFormat)],initialfile=name,parent=self.parent,title="Choose output file") if type(outfilename)==type((0,)) or not outfilename or outfilename == '': return fullname = os.path.abspath(outfilename) @@ -753,13 +758,13 @@ class xasyMainWin: saver = subprocess.Popen(command,stdin=PIPE,stdout=PIPE,stderr=PIPE) saver.wait() if saver.returncode != 0: - tkMessageBox.showerror("Export Error","Export Error:\n"+saver.stdout.read()+saver.stderr.read()) + messagebox.showerror("Export Error","Export Error:\n"+saver.stdout.read()+saver.stderr.read()) self.status.config(text="Error exporting file") else: self.status.config(text="File exported successfully") def fileExitCmd(self): - #print "Exit xasy" + #print ("Exit xasy") self.canQuit() def editUndoCmd(self): @@ -779,14 +784,14 @@ class xasyMainWin: self.releaseLock() def helpHelpCmd(self): - print "Get help on xasy" + print ("Get help on xasy") def helpAsyDocCmd(self): - #print "Open documentation about Asymptote" + #print ("Open documentation about Asymptote") asyExecute("help;\n") def helpAboutCmd(self): - tkMessageBox.showinfo("About xasy","A graphical interface for Asymptote "+xasyVersion) + messagebox.showinfo("About xasy","A graphical interface for Asymptote "+xasyVersion) def updateSelectedButton(self,newB): if(not self.testOrAcquireLock()): @@ -847,8 +852,8 @@ class xasyMainWin: self.unbindGlobalEvents() try: self.getNewText("// enter your code here") - except Exception, e: - tkMessageBox.showerror('xasy Error',e.message) + except Exception as e: + messagebox.showerror('xasy Error',e.message) else: self.addItemToFile(xasyScript(self.mainCanvas)) text = self.newText @@ -963,7 +968,7 @@ class xasyMainWin: self.setSelection(item.IDTag) def propSelect(self,event): - items = map(int, self.propList.curselection()) + items = [int(a) for a in self.propList.curselection()] if len(items)>0: try: self.selectItem(self.fileItems[len(self.fileItems)-items[0]-1]) @@ -979,7 +984,7 @@ class xasyMainWin: else: if item.IDTag == ID: return item - raise Exception,"Illegal operation: Item with matching ID could not be found." + raise Exception("Illegal operation: Item with matching ID could not be found.") def findItemImageIndex(self,item,ID): count = 0 @@ -988,7 +993,7 @@ class xasyMainWin: return count else: count += 1 - raise Exception,"Illegal operation: Image with matching ID could not be found." + raise Exception("Illegal operation: Image with matching ID could not be found.") return None def raiseSomething(self,item,force=False): @@ -1057,9 +1062,9 @@ class xasyMainWin: return asyTransform((shift[0],shift[1],rotMat[0],rotMat[1],rotMat[2],rotMat[3])) def rotateSomething(self,ID,theta,origin,specificItem=None,specificIndex=None): - #print "Rotating by",theta*180.0/math.pi,"around",origin + #print ("Rotating by {} around {}".format(theta*180.0/math.pi,origin)) rotMat = self.makeRotationMatrix(theta,(origin[0]/self.magnification,origin[1]/self.magnification)) - #print rotMat + #print (rotMat) if ID == -1: item = specificItem else: @@ -1098,9 +1103,9 @@ class xasyMainWin: p3 = rotMat2*(oldBbox[2],-oldBbox[1]) newTopLeft = (min(p0[0],p1[0],p2[0],p3[0]),-max(p0[1],p1[1],p2[1],p3[1]))#switch back to screen coords shift = (newTopLeft[0]-oldBbox[0],newTopLeft[1]-oldBbox[3]) - #print theta*180.0/math.pi,origin,oldBbox,newTopLeft,shift - #print item.imageList[index].originalImage.size - #print item.imageList[index].image.size + #print (theta*180.0/math.pi,origin,oldBbox,newTopLeft,shift) + #print (item.imageList[index].originalImage.size) + #print (item.imageList[index].image.size) #print self.mainCanvas.coords(ID,oldBbox[0]+shift[0],oldBbox[3]+shift[1]) else: @@ -1179,8 +1184,8 @@ class xasyMainWin: oldText = item.script try: self.getNewText(oldText) - except Exception,e: - tkMessageBox.showerror('xasy Error',e.message) + except Exception as e: + messagebox.showerror('xasy Error',e.message) else: if self.newText != oldText: self.undoRedoStack.add(editScriptAction(self,item,self.newText,oldText)) @@ -1189,7 +1194,7 @@ class xasyMainWin: self.bindItemEvents(item) self.bindGlobalEvents() elif isinstance(item,xasyText): - theText = tkSimpleDialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue=item.label.text,parent=self.parent) + theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue=item.label.text,parent=self.parent) if theText != None and theText != "": self.undoRedoStack.add(editLabelTextAction(self,item,theText,item.label.text)) item.label.text = theText @@ -1264,7 +1269,7 @@ class xasyMainWin: self.setSelection(CURRENT) def itemToggleSelect(self,event): - #print "control click" + #print ("control click") x0,y0 = self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y) x = x0/self.magnification y = y0/self.magnification @@ -1356,7 +1361,7 @@ class xasyMainWin: elif self.selectedButton == self.toolFillEllipButton: pass elif self.selectedButton == self.toolTextButton: - theText = tkSimpleDialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue="",parent=self.parent) + theText = simpledialog.askstring(title="Xasy - Text",prompt="Enter text to display:",initialvalue="",parent=self.parent) if theText != None and theText != "": theItem = xasyText(theText,(x,-y),asyPen(self.penColor,self.penWidth,self.penOptions)) theItem.drawOnCanvas(self.mainCanvas,self.magnification) @@ -1431,7 +1436,7 @@ class xasyMainWin: self.releaseLock() def canvLeftDown(self,event): - #print "Left Mouse Down" + #print ("Left Mouse Down") self.selectDragStart = (self.mainCanvas.canvasx(event.x),self.mainCanvas.canvasy(event.y)) theBbox = self.mainCanvas.bbox("selectedItem") if theBbox != None: @@ -1449,7 +1454,7 @@ class xasyMainWin: self.startDraw(event) def canvLeftUp(self,event): - #print "Left Mouse Up" + #print ("Left Mouse Up") # if we're busy, ignore it if not self.testOrAcquireLock(): return @@ -1543,11 +1548,11 @@ class xasyMainWin: def canvRightDown(self,event): pass - #print "Right Mouse Down" + #print ("Right Mouse Down") def canvRightUp(self,event): pass - #print "Right Mouse Up" + #print ("Right Mouse Up") def configEvt(self,event): self.updateCanvasSize() @@ -1573,7 +1578,7 @@ class xasyMainWin: self.itemEdit(self.itemPopupMenu.item) def popupViewCode(self): - tkMessageBox.showinfo("Item Code",self.itemPopupMenu.item.getCode()) + messagebox.showinfo("Item Code",self.itemPopupMenu.item.getCode()) def popupClearTransform(self): self.undoRedoStack.add(clearItemTransformsAction(self,self.itemPopupMenu.item,copy.deepcopy(self.itemPopupMenu.item.transform))) diff --git a/Master/texmf-dist/asymptote/GUI/xasyOptions.py b/Master/texmf-dist/asymptote/GUI/xasyOptions.py index 17d58d760e5..927490b77aa 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyOptions.py +++ b/Master/texmf-dist/asymptote/GUI/xasyOptions.py @@ -81,16 +81,16 @@ def load(): try: os.makedirs(thedir) except: - raise Exception,"Could not create configuration folder" + raise Exception("Could not create configuration folder") if not os.path.isdir(thedir): - raise Exception,"Configuration folder path does not point to a folder" + raise Exception("Configuration folder path does not point to a folder") setDefaults() try: f = open(fileName,"rb") newOptions = pickle.load(f) for key in options.keys(): if type(newOptions[key]) != type(options[key]): - raise Exception,"Bad type for entry in xasy settings" + raise Exception("Bad type for entry in xasy settings") options = newOptions except: setDefaults() @@ -103,24 +103,24 @@ def save(): pickle.dump(options,f) f.close() except: - raise Exception,"Error saving preferences" + raise Exception("Error saving preferences") load() if __name__=='__main__': - print settingsFileLocation() - print "Current content" + print (settingsFileLocation()) + print ("Current content") load() - print "Setting defaults" + print ("Setting defaults") setDefaults() save() load() options['showAxes'] = options['showGrid'] = False save() - print "Set to False" + print ("Set to False") load() options['showAxes'] = options['showGrid'] = True save() - print "Set to True" + print ("Set to True") load() - print options + print (options) diff --git a/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py b/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py index c3162e8673b..271070ea457 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py +++ b/Master/texmf-dist/asymptote/GUI/xasyOptionsDialog.py @@ -10,20 +10,26 @@ # ########################################################################### -from Tkinter import * -import xasyOptions -import tkSimpleDialog -import xasyColorPicker -import tkMessageBox -import tkFileDialog -import tkColorChooser import os import sys +import xasyOptions +import xasyColorPicker -class xasyOptionsDlg(tkSimpleDialog.Dialog): +if sys.version_info >= (3, 0): + from tkinter import * + from tkinter import simpledialog, messagebox, filedialog +else: + # python2 + from Tkinter import * + import tkSimpleDialog as simpledialog + import tkMessageBox as messagebox + import tkFileDialog as filedialog + # import tkColorChooser as colorchooser + +class xasyOptionsDlg(simpledialog.Dialog): """A dialog to interact with users about their preferred settings""" def __init__(self,master=None): - tkSimpleDialog.Dialog.__init__(self,master,"xasy Options") + simpledialog.Dialog.__init__(self,master,"xasy Options") def body(self,master): optFrame = Frame(master) @@ -116,9 +122,9 @@ class xasyOptionsDlg(tkSimpleDialog.Dialog): def findEEPath(self): if sys.platform[:3] == 'win': #for windows, wince, win32, etc - file=tkFileDialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Choose External Editor",parent=self) + file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Choose External Editor",parent=self) else: - file=tkFileDialog.askopenfile(filetypes=[("All files","*")],title="Choose External Editor",parent=self) + file=filedialog.askopenfile(filetypes=[("All files","*")],title="Choose External Editor",parent=self) if file != None: name = os.path.abspath(file.name) file.close() @@ -128,9 +134,9 @@ class xasyOptionsDlg(tkSimpleDialog.Dialog): def findAsyPath(self): if sys.platform[:3] == 'win': #for windows, wince, win32, etc - file=tkFileDialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Find Asymptote Executable",parent=self) + file=filedialog.askopenfile(filetypes=[("Programs","*.exe"),("All files","*")],title="Find Asymptote Executable",parent=self) else: - file=tkFileDialog.askopenfile(filetypes=[("All files","*")],title="Find Asymptote Executable",parent=self) + file=filedialog.askopenfile(filetypes=[("All files","*")],title="Find Asymptote Executable",parent=self) if file != None: name = os.path.abspath(file.name) file.close() @@ -183,13 +189,13 @@ class xasyOptionsDlg(tkSimpleDialog.Dialog): #validate the color hexdigits = '0123456789abcdef' if not self.validateAColor(self.pc): - tkMessageBox.showerror("xasy Options","Invalid pen color.\r\n"+self.pc,parent=self) + messagebox.showerror("xasy Options","Invalid pen color.\r\n"+self.pc,parent=self) return False #validate the width try: test = float(self.pw.get()) except: - tkMessageBox.showerror("xasy Options","Pen width must be a number.",parent=self) + messagebox.showerror("xasy Options","Pen width must be a number.",parent=self) return False #validate the options @@ -200,7 +206,7 @@ class xasyOptionsDlg(tkSimpleDialog.Dialog): test = int(self.axs.get()) test = int(self.ays.get()) except: - tkMessageBox.showerror("xasy Options","Axes' x- and y-spacing must be numbers.",parent=self) + messagebox.showerror("xasy Options","Axes' x- and y-spacing must be numbers.",parent=self) return False #validate the grid spacing @@ -208,15 +214,15 @@ class xasyOptionsDlg(tkSimpleDialog.Dialog): test = int(self.gxs.get()) test = int(self.gys.get()) except: - tkMessageBox.showerror("xasy Options","Grid's x- and y-spacing must be numbers.",parent=self) + messagebox.showerror("xasy Options","Grid's x- and y-spacing must be numbers.",parent=self) return False if not self.validateAColor(self.ac): - tkMessageBox.showerror("xasy Options","Invalid axis color.\r\n"+self.ac,parent=self) + messagebox.showerror("xasy Options","Invalid axis color.\r\n"+self.ac,parent=self) return False if not self.validateAColor(self.gc): - tkMessageBox.showerror("xasy Options","Invalid grid color.\r\n"+self.gc,parent=self) + messagebox.showerror("xasy Options","Invalid grid color.\r\n"+self.gc,parent=self) return False return True @@ -225,4 +231,4 @@ if __name__ == '__main__': root = Tk() xasyOptions.load() d = xasyOptionsDlg(root) - print d.result + print (d.result) diff --git a/Master/texmf-dist/asymptote/GUI/xasyVersion.py b/Master/texmf-dist/asymptote/GUI/xasyVersion.py index 4d81598bbd8..83cd6c96fa7 100755 --- a/Master/texmf-dist/asymptote/GUI/xasyVersion.py +++ b/Master/texmf-dist/asymptote/GUI/xasyVersion.py @@ -1,2 +1,2 @@ #!/usr/bin/env python -xasyVersion = "2.35" +xasyVersion = "2.37" diff --git a/Master/texmf-dist/asymptote/animation.asy b/Master/texmf-dist/asymptote/animation.asy index 57e13ab6e03..270adce713a 100644 --- a/Master/texmf-dist/asymptote/animation.asy +++ b/Master/texmf-dist/asymptote/animation.asy @@ -139,6 +139,7 @@ struct animation { string pdf(enclosure enclosure=NoBox, real delay=animationdelay, string options="", bool keep=settings.keep, bool multipage=true) { + settings.twice=true; if(settings.inlinetex) multipage=true; if(!global) multipage=false; if(!pdflatex()) diff --git a/Master/texmf-dist/asymptote/asy-keywords.el b/Master/texmf-dist/asymptote/asy-keywords.el index 60e35207d61..2b6e9e561d4 100644 --- a/Master/texmf-dist/asymptote/asy-keywords.el +++ b/Master/texmf-dist/asymptote/asy-keywords.el @@ -2,7 +2,7 @@ ;; This file is automatically generated by asy-list.pl. ;; Changes will be overwritten. ;; -(defvar asy-keywords-version "2.35") +(defvar asy-keywords-version "2.37") (defvar asy-keyword-name '( and controls tension atleast curl if else while for do return break continue struct typedef new access import unravel from include quote static public private restricted this explicit true false null cycle newframe operator )) @@ -11,7 +11,7 @@ and controls tension atleast curl if else while for do return break continue str Braid FitResult Label Legend Solution TreeNode abscissa arc arrowhead binarytree binarytreeNode block bool bool3 bounds bqe circle conic coord coordsys cputime ellipse evaluatedpoint file filltype frame grid3 guide horner hsv hyperbola indexedTransform int inversion key light line linefit marginT marker mass object pair parabola patch path path3 pen picture point position positionedvector projection real revolution scaleT scientific segment side slice solution splitface string surface tensionSpecifier ticklocate ticksgridT tickvalues transform transformation tree triangle trilinear triple vector vertex void )) (defvar asy-function-name '( -AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _image _labelpath _projection _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply applytranspose approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asydir asyfigure asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVertexO drawVertexOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawline drawpixel drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endScript endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitXasyMode exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedTransform indexedfigure initXasyMode initdefaults input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate locatefile location log log10 log1p logaxiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural needshipout newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa none norm normalout normalvideo notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY seconds section sector seek seekeof segment segmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys startScript stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zero3 zlimits zpart ztick ztick3 ztrans )) +AND Arc ArcArrow ArcArrows Arrow Arrows AtA Automatic AvantGarde B03 B13 B23 B33 BBox BWRainbow BWRainbow2 Bar Bars BeginArcArrow BeginArrow BeginBar BeginDotMargin BeginMargin BeginPenMargin Blank Bookman Bottom BottomTop Bounds Break Broken BrokenLog CLZ CTZ Ceil Circle CircleBarIntervalMarker Cos Courier CrossIntervalMarker DOSendl DOSnewl DefaultFormat DefaultLogFormat Degrees Dir DotMargin DotMargins Dotted Draw Drawline Embed EndArcArrow EndArrow EndBar EndDotMargin EndMargin EndPenMargin Fill FillDraw Floor Format Full Gaussian Gaussrand Gaussrandpair Gradient Grayscale Helvetica Hermite HookHead InOutTicks InTicks Jn Label Landscape Left LeftRight LeftTicks Legend Linear Log LogFormat Margin Margins Mark MidArcArrow MidArrow NOT NewCenturySchoolBook NoBox NoMargin NoModifier NoTicks NoTicks3 NoZero NoZeroFormat None OR OmitFormat OmitTick OmitTickInterval OmitTickIntervals OutTicks Ox Oy Palatino PaletteTicks Pen PenMargin PenMargins Pentype Portrait RadialShade RadialShadeDraw Rainbow Range Relative Right RightTicks Rotate Round SQR Scale ScaleX ScaleY ScaleZ Seascape Shift Sin Slant Spline StickIntervalMarker Straight Symbol Tan TeXify Ticks Ticks3 TildeIntervalMarker TimesRoman Top TrueMargin UnFill UpsideDown Wheel X XEquals XOR XY XYEquals XYZero XYgrid XZEquals XZZero XZero XZgrid Y YEquals YXgrid YZ YZEquals YZZero YZero YZgrid Yn Z ZX ZXgrid ZYgrid ZapfChancery ZapfDingbats _begingroup3 _cputime _draw _eval _findroot _image _labelpath _projection _strokepath _texpath aCos aSin aTan abort abs accel acos acosh acot acsc activatequote add addArrow addMargins addSaveFunction addpenarc addpenline addseg adjust alias align all altitude angabscissa angle angledegrees angpoint animate annotate anticomplementary antipedal apply approximate arc arcarrowsize arccircle arcdir arcfromcenter arcfromfocus arclength arcnodesnumber arcpoint arcsubtended arcsubtendedcenter arctime arctopath array arrow arrow2 arrowbase arrowbasepoints arrowsize ascii asec asin asinh ask assert asy asycode asydir asyfigure asyfilecode asyinclude asywrite atan atan2 atanh atbreakpoint atexit attach attract atupdate autoformat autoscale autoscale3 axes axes3 axialshade axis axiscoverage azimuth babel background bangles bar barmarksize barsize basealign baseline bbox beep begin beginclip begingroup beginpoint between bevel bezier bezierP bezierPP bezierPPP bezulate bibliography bibliographystyle binarytree binarytreeNode binomial bins bisector bisectorpoint bispline blend blockconnector box bqe brace breakpoint breakpoints brick buildRestoreDefaults buildRestoreThunk buildcycle bulletcolor byte calculateScaling canonical canonicalcartesiansystem cartesiansystem case1 case2 case3 cbrt cd ceil center centerToFocus centroid cevian change2 changecoordsys checkSegment check_fpt_zero checkconditionlength checker checkincreasing checklengths checkposition checkpt checkptincube checktriangle choose circle circlebarframe circlemarkradius circlenodesnumber circumcenter circumcircle clamped clear clip clipdraw close cmyk code colatitude collect collinear color colorless colors colorspace comma compassmark complement complementary concat concurrent cone conic conicnodesnumber conictype conj connect containmentTree contains contour contour3 controlSpecifier convert coordinates coordsys copy copyPairOrTriple cos cosh cot countIntersections cputime crop cropcode cross crossframe crosshatch crossmarksize csc cubicroots curabscissa curlSpecifier curpoint currentarrow currentexitfunction currentmomarrow currentpolarconicroutine curve cut cutafter cutbefore cyclic cylinder deactivatequote debugger deconstruct defaultdir defaultformat defaultpen defined degenerate degrees delete deletepreamble determinant diagonal diamond diffdiv dir dirSpecifier dirtime display distance divisors do_overpaint dot dotframe dotsize downcase draw drawAll drawDoubleLine drawFermion drawGhost drawGluon drawMomArrow drawPRCcylinder drawPRCdisk drawPRCsphere drawPRCtube drawPhoton drawScalar drawVertex drawVertexBox drawVertexBoxO drawVertexBoxX drawVertexO drawVertexOX drawVertexTriangle drawVertexTriangleO drawVertexX drawarrow drawarrow2 drawbeziertriangle drawline drawpixel drawtick duplicate elle ellipse ellipsenodesnumber embed embed3 embedplayer empty enclose end endScript endclip endgroup endgroup3 endl endpoint endpoints eof eol equation equations erase erasestep erf erfc error errorbar errorbars eval excenter excircle exit exitXasyMode exitfunction exp expfactors expi expm1 exradius extend extension extouch fabs factorial fermat fft fhorner figure file filecode fill filldraw filloutside fillrule filltype find findroot finite finiteDifferenceJacobian firstcut firstframe fit fit2 fixedscaling floor flush fmdefaults fmod focusToCenter font fontcommand fontsize foot format frac frequency fromCenter fromFocus fspline functionshade gamma generate_random_backtrace generateticks gergonne getc getint getpair getreal getstring gettriple gluon gouraudshade graph graphic graphicscale gray grestore grid grid3 gsave halfbox hatch hdiffdiv hermite hex histogram history hline hprojection hsv hyperbola hyperbolanodesnumber hyperlink hypot identity image implicitsurface incenter incentral incircle increasing incrementposition indexedTransform indexedfigure initXasyMode initdefaults input inradius insert inside insphere integrate interactive interior interp interpolate intersect intersection intersectionpoint intersectionpoints intersections intouch inverse inversion invisible is3D isDuplicate isnan isogonal isogonalconjugate isotomic isotomicconjugate isparabola italic item jobname key kurtosis kurtosisexcess label labelaxis labelmargin labelpath labels labeltick labelx labelx3 labely labely3 labelz labelz3 lastcut latex latitude latticeshade layer layout ldexp leastsquares legend legenditem length lexorder lift light limits line linear linecap lineinversion linejoin linemargin lineskip linetype linewidth link list lm_enorm lm_evaluate_default lm_lmdif lm_lmpar lm_minimize lm_print_default lm_print_quiet lm_qrfac lm_qrsolv locale locate locatefile location log log10 log1p logaxiscoverage longitude lookup make3dgrid makeNode makecircle makedraw makepen maketriangle map margin markangle markangleradius markanglespace markarc marker markinterval marknodes markrightangle markthin markuniform mass masscenter massformat math max max3 maxAfterTransform maxbezier maxbound maxcoords maxlength maxratio maxtimes mean medial median midpoint min min3 minAfterTransform minbezier minbound minipage minratio mintimes miterlimit mktemp momArrowPath momarrowsize monotonic multifigure nGrad nativeformat natural needshipout newl newpage newslide newton newtree nextframe nextnormal nextpage nib nodabscissa none norm normalout normalvideo notaknot nowarn numberpage nurb object offset onpath opacity opposite orient orientation origin orthic orthocentercenter outformat outline outname outprefix output overloadedMessage overwrite pack pad pairs palette parabola parabolanodesnumber parallel parallelogram partialsum patchwithnormals path path3 pathbetween pathinface pattern pause pdf pedal periodic perp perpendicular perpendicularmark phantom phi1 phi2 phi3 photon piecewisestraight point polar polarconicroutine polargraph polygon postcontrol postscript pow10 ppoint prc prc0 prconly precision precontrol prepend printBytecode print_random_addresses progress project projection projecttospan projecttospan_findcoeffs purge pwhermite quadpatches quadrant quadraticroots quantize quarticroots quotient radialshade radians radicalcenter radicalline radius rand randompath rd readline realmult realquarticroots rectangle rectangular rectify reflect relabscissa relative relativedistance reldir relpoint reltime remainder remark removeDuplicates rename replace report resetdefaultpen restore restoredefaults reverse reversevideo rf rfind rgb rgba rgbint rms rotate rotateO rotation round roundbox roundedpath roundrectangle samecoordsys sameside sample save savedefaults saveline scale scale3 scaleO scaleT scaleless scientific search searchtree sec secondaryX secondaryY seconds section sector seek seekeof segment segmentlimits sequence setpens sgn sgnd sharpangle sharpdegrees shift shiftless shipout shipout3 show simeq simpson sin sinh size size3 skewness skip slant sleep slice slope slopefield solve solveBVP sort sourceline sphere split sqrt square srand standardizecoordsys startScript stdev step stickframe stickmarksize stickmarkspace stop straight straightness string stripdirectory stripextension stripfile stripsuffix strokepath subdivide subitem subpath substr sum surface symmedial symmedian system tab tableau tan tangent tangential tangents tanh tell tensionSpecifier tensorshade tex texcolor texify texpath texpreamble texreset texshipout texsize textpath thick thin tick tickMax tickMax3 tickMin tickMin3 ticklabelshift ticklocate tildeframe tildemarksize tile tiling time times title titlepage topbox transform transformation transpose trembleFuzz triangle triangleAbc triangleabc triangletoquads trianglewithnormals triangulate tricoef tridiagonal trilinear trim truepoint tube uncycle unfill uniform unique unit unitrand unitsize unityroot unstraighten upcase updatefunction uperiodic upscale uptodate usepackage usersetting usetypescript usleep value variance variancebiased vbox vector vectorfield verbatim view vline vperiodic vprojection warn warning windingnumber write xaxis xaxis3 xaxis3At xaxisAt xequals xlimits xpart xscale xscaleO xtick xtick3 xtrans yaxis yaxis3 yaxis3At yaxisAt yequals ylimits ypart yscale yscaleO ytick ytick3 ytrans zaxis3 zaxis3At zero zero3 zlimits zpart ztick ztick3 ztrans )) (defvar asy-variable-name '( -AliceBlue Align Allow AntiqueWhite Apricot Aqua Aquamarine Aspect Azure BeginPoint Beige Bisque Bittersweet Black BlanchedAlmond Blue BlueGreen BlueViolet Both Break BrickRed Brown BurlyWood BurntOrange CCW CW CadetBlue CarnationPink Center Centered Cerulean Chartreuse Chocolate Coeff Coral CornflowerBlue Cornsilk Crimson Crop Cyan Dandelion DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DefaultHead DimGray DodgerBlue Dotted Down Draw E ENE EPS ESE E_Euler E_PC E_RK2 E_RK3BS Emerald EndPoint Euler Fill FillDraw FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HookHead Horizontal HotPink I IgnoreAspect IndianRed Indigo Ivory JOIN_IN JOIN_OUT JungleGreen Khaki LM_DWARF LM_MACHEP LM_SQRT_DWARF LM_SQRT_GIANT LM_USERTOL Label Lavender LavenderBlush LawnGreen Left LeftJustified LeftSide LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linear Linen Log Logarithmic Magenta Mahogany Mark MarkFill MarkPath Maroon Max MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed Melon MidPoint MidnightBlue Min MintCream MistyRose Moccasin Move MoveQuiet Mulberry N NE NNE NNW NULL_VERTEX NW NavajoWhite Navy NavyBlue NoAlign NoCrop NoFill NoSide OldLace Olive OliveDrab OliveGreen Orange OrangeRed Orchid Ox Oy PC PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip Peach PeachPuff Periwinkle Peru PineGreen Pink Plum PowderBlue ProcessBlue Purple RK2 RK3 RK3BS RK4 RK5 RK5DP RK5F RawSienna Red RedOrange RedViolet Rhodamine Right RightJustified RightSide RosyBrown RoyalBlue RoyalPurple RubineRed S SE SSE SSW SW SaddleBrown Salmon SandyBrown SeaGreen Seashell Sepia Sienna Silver SimpleHead SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Suppress SuppressQuiet Tan TeXHead Teal TealBlue Thistle Ticksize Tomato Turquoise UnFill Up VERSION Value Vertical Violet VioletRed W WNW WSW Wheat White WhiteSmoke WildStrawberry XHIGH XLOW XYAlign YAlign YHIGH YLOW Yellow YellowGreen YellowOrange ZHIGH ZLOW addpenarc addpenline align allowstepping angularsystem animationdelay appendsuffix arcarrowangle arcarrowfactor arrow2sizelimit arrowangle arrowbarb arrowdir arrowfactor arrowhookfactor arrowlength arrowsizelimit arrowtexfactor authorpen axis axiscoverage axislabelfactor background backgroundcolor backgroundpen barfactor barmarksizefactor basealign baselinetemplate bernstein beveljoin bigvertexpen bigvertexsize black blue bm bottom bp bracedefaultratio braceinnerangle bracemidangle braceouterangle brown bullet byfoci byvertices camerafactor chartreuse circlemarkradiusfactor circlenodesnumberfactor circleprecision circlescale cm codefile codepen codeskip colorPen coloredNodes coloredSegments conditionlength conicnodesfactor count cputimeformat crossmarksizefactor currentcoordsys currentlight currentpatterns currentpen currentpicture currentposition currentprojection curvilinearsystem cuttings cyan darkblue darkbrown darkcyan darkgray darkgreen darkgrey darkmagenta darkolive darkred dashdotted dashed datepen dateskip debuggerlines debugging deepblue deepcyan deepgray deepgreen deepgrey deepmagenta deepred default defaultControl defaultS defaultbackpen defaultcoordsys defaultexcursion defaultfilename defaultformat defaultmassformat defaultpen defaultseparator diagnostics differentlengths dot dotfactor dotframe dotted doublelinepen doublelinespacing down duplicateFuzz ellipsenodesnumberfactor eps epsgeo epsilon evenodd expansionfactor extendcap fermionpen figureborder figuremattpen file3 firstnode firststep foregroundcolor fuchsia fuzz gapfactor ghostpen gluonamplitude gluonpen gluonratio gray green grey hatchepsilon havepagenumber heavyblue heavycyan heavygray heavygreen heavygrey heavymagenta heavyred hline hwratio hyperbolanodesnumberfactor identity4 ignore inXasyMode inch inches includegraphicscommand inf infinity institutionpen intMax intMin invert invisible itempen itemskip itemstep labelmargin landscape lastnode left legendhskip legendlinelength legendmargin legendmarkersize legendmaxrelativewidth legendvskip lightblue lightcyan lightgray lightgreen lightgrey lightmagenta lightolive lightred lightyellow linemargin lm_infmsg lm_shortmsg longdashdotted longdashed magenta magneticRadius mantissaBits markangleradius markangleradiusfactor markanglespace markanglespacefactor maxrefinements mediumblue mediumcyan mediumgray mediumgreen mediumgrey mediummagenta mediumred mediumyellow middle minDistDefault minblockheight minblockwidth mincirclediameter minipagemargin minipagewidth minvertexangle miterjoin mm momarrowfactor momarrowlength momarrowmargin momarrowoffset momarrowpen monoPen morepoints nCircle newbulletcolor ngraph nil nmesh nobasealign nodeMarginDefault nodesystem nomarker nopoint noprimary nullpath nullpen numarray ocgindex oldbulletcolor olive orange origin overpaint page pageheight pagemargin pagenumberalign pagenumberpen pagenumberposition pagewidth paleblue palecyan palegray palegreen palegrey palemagenta palered paleyellow parabolanodesnumberfactor perpfactor phi photonamplitude photonpen photonratio pi pink plain plain_bounds plain_scaling plus preamblenodes pt purple r3 r4a r4b randMax realDigits realEpsilon realMax realMin red relativesystem reverse right roundcap roundjoin royalblue salmon saveFunctions scalarpen sequencereal settings shipped signedtrailingzero solid springgreen sqrtEpsilon squarecap squarepen startposition stdin stdout stepfactor stepfraction steppagenumberpen stepping stickframe stickmarksizefactor stickmarkspacefactor swap textpen ticksize tildeframe tildemarksizefactor tinv titlealign titlepagepen titlepageposition titlepen titleskip top trailingzero treeLevelStep treeMinNodeWidth treeNodeStep trembleAngle trembleFrequency trembleRandom undefined unitcircle unitsquare up urlpen urlskip version vertexpen vertexsize viewportmargin viewportsize vline white wye xformStack yellow ylabelwidth zerotickfuzz zerowinding )) +AliceBlue Align Allow AntiqueWhite Apricot Aqua Aquamarine Aspect Azure BeginPoint Beige Bisque Bittersweet Black BlanchedAlmond Blue BlueGreen BlueViolet Both Break BrickRed Brown BurlyWood BurntOrange CCW CW CadetBlue CarnationPink Center Centered Cerulean Chartreuse Chocolate Coeff Coral CornflowerBlue Cornsilk Crimson Crop Cyan Dandelion DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DefaultHead DimGray DodgerBlue Dotted Down Draw E ENE EPS ESE E_Euler E_PC E_RK2 E_RK3BS Emerald EndPoint Euler Fill FillDraw FireBrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HookHead Horizontal HotPink I IgnoreAspect IndianRed Indigo Ivory JOIN_IN JOIN_OUT JungleGreen Khaki LM_DWARF LM_MACHEP LM_SQRT_DWARF LM_SQRT_GIANT LM_USERTOL Label Lavender LavenderBlush LawnGreen Left LeftJustified LeftSide LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGreen LightGrey LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linear Linen Log Logarithmic Magenta Mahogany Mark MarkFill MarkPath Maroon Max MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed Melon MidPoint MidnightBlue Min MintCream MistyRose Moccasin Move MoveQuiet Mulberry N NE NNE NNW NULL_VERTEX NW NavajoWhite Navy NavyBlue NoAlign NoCrop NoFill NoSide OldLace Olive OliveDrab OliveGreen Orange OrangeRed Orchid Ox Oy PC PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip Peach PeachPuff Periwinkle Peru PineGreen Pink Plum PowderBlue ProcessBlue Purple RK2 RK3 RK3BS RK4 RK5 RK5DP RK5F RawSienna Red RedOrange RedViolet Rhodamine Right RightJustified RightSide RosyBrown RoyalBlue RoyalPurple RubineRed S SE SSE SSW SW SaddleBrown Salmon SandyBrown SeaGreen Seashell Sepia Sienna Silver SimpleHead SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Suppress SuppressQuiet Tan TeXHead Teal TealBlue Thistle Ticksize Tomato Turquoise UnFill Up VERSION Value Vertical Violet VioletRed W WNW WSW Wheat White WhiteSmoke WildStrawberry XHIGH XLOW XYAlign YAlign YHIGH YLOW Yellow YellowGreen YellowOrange ZHIGH ZLOW addpenarc addpenline align allowstepping angularsystem animationdelay appendsuffix arcarrowangle arcarrowfactor arrow2sizelimit arrowangle arrowbarb arrowdir arrowfactor arrowhookfactor arrowlength arrowsizelimit arrowtexfactor authorpen axis axiscoverage axislabelfactor background backgroundcolor backgroundpen barfactor barmarksizefactor basealign baselinetemplate bernstein beveljoin bigvertexpen bigvertexsize black blue bm bottom bp bracedefaultratio braceinnerangle bracemidangle braceouterangle brown bullet byfoci byvertices camerafactor chartreuse circlemarkradiusfactor circlenodesnumberfactor circleprecision circlescale cm codefile codepen codeskip colorPen coloredNodes coloredSegments conditionlength conicnodesfactor count cputimeformat crossmarksizefactor currentcoordsys currentlight currentpatterns currentpen currentpicture currentposition currentprojection curvilinearsystem cuttings cyan darkblue darkbrown darkcyan darkgray darkgreen darkgrey darkmagenta darkolive darkred dashdotted dashed datepen dateskip debuggerlines debugging deepblue deepcyan deepgray deepgreen deepgrey deepmagenta deepred default defaultControl defaultS defaultbackpen defaultcoordsys defaultexcursion defaultfilename defaultformat defaultmassformat defaultpen defaultseparator diagnostics differentlengths dot dotfactor dotframe dotted doublelinepen doublelinespacing down duplicateFuzz ellipsenodesnumberfactor eps epsgeo epsilon evenodd expansionfactor extendcap fermionpen figureborder figuremattpen file3 firstnode firststep foregroundcolor fuchsia fuzz gapfactor ghostpen gluonamplitude gluonpen gluonratio gray green grey hatchepsilon havepagenumber heavyblue heavycyan heavygray heavygreen heavygrey heavymagenta heavyred hline hwratio hyperbolanodesnumberfactor identity4 ignore inXasyMode inch inches includegraphicscommand inf infinity institutionpen intMax intMin invert invisible itempen itemskip itemstep labelmargin landscape lastnode left legendhskip legendlinelength legendmargin legendmarkersize legendmaxrelativewidth legendvskip lightblue lightcyan lightgray lightgreen lightgrey lightmagenta lightolive lightred lightyellow linemargin lm_infmsg lm_shortmsg longdashdotted longdashed magenta magneticRadius mantissaBits markangleradius markangleradiusfactor markanglespace markanglespacefactor maxrefinements mediumblue mediumcyan mediumgray mediumgreen mediumgrey mediummagenta mediumred mediumyellow middle minDistDefault minblockheight minblockwidth mincirclediameter minipagemargin minipagewidth minvertexangle miterjoin mm momarrowfactor momarrowlength momarrowmargin momarrowoffset momarrowpen monoPen morepoints nCircle nan newbulletcolor ngraph nil nmesh nobasealign nodeMarginDefault nodesystem nomarker nopoint noprimary nullpath nullpen numarray ocgindex oldbulletcolor olive orange origin overpaint page pageheight pagemargin pagenumberalign pagenumberpen pagenumberposition pagewidth paleblue palecyan palegray palegreen palegrey palemagenta palered paleyellow parabolanodesnumberfactor perpfactor phi photonamplitude photonpen photonratio pi pink plain plain_bounds plain_scaling plus preamblenodes pt purple r3 r4a r4b randMax realDigits realEpsilon realMax realMin red relativesystem reverse right roundcap roundjoin royalblue salmon saveFunctions scalarpen sequencereal settings shipped signedtrailingzero solid spinner springgreen sqrtEpsilon squarecap squarepen startposition stdin stdout stepfactor stepfraction steppagenumberpen stepping stickframe stickmarksizefactor stickmarkspacefactor swap textpen ticksize tildeframe tildemarksizefactor tinv titlealign titlepagepen titlepageposition titlepen titleskip top trailingzero treeLevelStep treeMinNodeWidth treeNodeStep trembleAngle trembleFrequency trembleRandom undefined unitcircle unitsquare up urlpen urlskip version vertexpen vertexsize viewportmargin viewportsize vline white wye xformStack yellow ylabelwidth zerotickfuzz zerowinding )) diff --git a/Master/texmf-dist/asymptote/asy-mode.el b/Master/texmf-dist/asymptote/asy-mode.el index 7ccdfdf1197..c1960e23035 100644 --- a/Master/texmf-dist/asymptote/asy-mode.el +++ b/Master/texmf-dist/asymptote/asy-mode.el @@ -1,10 +1,15 @@ -;;; asy-mode.el +;;; asy-mode.el --- Major mode for editing Asymptote source code. ;; Copyright (C) 2006-8 + ;; Author: Philippe IVALDI 20 August 2006 -;; http://www.piprime.fr/ -;; Modified by: John Bowman -;; +;; Maintainer: John Bowman +;; URL: https://github.com/vectorgraphics/asymptote +;; Version: 1.6 +;; Keywords: language, mode + +;;; License: + ;; This program is free software ; you can redistribute it and/or modify ;; it under the terms of the GNU Lesser General Public License as published by ;; the Free Software Foundation ; either version 3 of the License, or @@ -19,7 +24,9 @@ ;; along with this program ; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -;; Emacs mode for editing Asymptote source code. +;;; Commentary + +;; Major mode for editing Asymptote source code. ;; INSTALLATION: ;; Place this file (asy-mode.el) and asy-keywords.el in your Emacs load path. @@ -43,6 +50,8 @@ ;; ;; See also paragraph II of the documentation below to automate asy-insinuate-latex. +;;; Code: + (defvar asy-mode-version "1.6") ;;;###autoload @@ -754,7 +763,7 @@ You should remove the line " (int-to-string (line-number-at-pos))))))) ;; Functions and 'advises' to restrict 'font-lock-unfontify-region' ;; and 'font-lock-fontify-syntactically-region' within lasy-mode - ;; Special thanks to Olivier Ramaré for his help. + ;; Special thanks to Olivier Ramaré for his help. (when (and (fboundp 'font-lock-add-keywords) (> emacs-major-version 21)) (defun lasy-mode-at-pos (pos &optional interior strictly) "If point at POS is in an asy environment return the list (start end)." @@ -1160,7 +1169,7 @@ See `asy-insinuate-latex'." (defvar lasy-run-tex nil) (defun lasy-asydef() - "Return the content between the tags \begin{asydef} and \end{asydef}." + "Return the content between the tags \\begin{asydef} and \\end{asydef}." (save-excursion (if (re-search-backward "\\\\begin{asydef}" 0 t) (buffer-substring @@ -1588,3 +1597,4 @@ If optional argument Force is t then force compilation." (define-key asy-mode-map (kbd "<C-M-S-return>") 'asy-master-tex-view-ps2pdf-f) (provide `asy-mode) +;;; asy-mode.el ends here diff --git a/Master/texmf-dist/asymptote/bezulate.asy b/Master/texmf-dist/asymptote/bezulate.asy index 60be8cb7045..38d35718d4a 100644 --- a/Master/texmf-dist/asymptote/bezulate.asy +++ b/Master/texmf-dist/asymptote/bezulate.asy @@ -2,7 +2,7 @@ private real fuzz=sqrtEpsilon; real duplicateFuzz=1e-3; // Work around font errors. -real maxrefinements=7; +real maxrefinements=10; private real[][] intersections(pair a, pair b, path p) { @@ -248,7 +248,8 @@ path subdivide(path p) path q; int l=length(p); for(int i=0; i < l; ++i) - q=q&subpath(p,i,i+0.5)&subpath(p,i+0.5,i+1); + q=q&(straight(p,i) ? subpath(p,i,i+1) : + subpath(p,i,i+0.5)&subpath(p,i+0.5,i+1)); return cyclic(p) ? q&cycle : q; } diff --git a/Master/texmf-dist/asymptote/contour3.asy b/Master/texmf-dist/asymptote/contour3.asy index 3d925be684e..4977a351bf2 100644 --- a/Master/texmf-dist/asymptote/contour3.asy +++ b/Master/texmf-dist/asymptote/contour3.asy @@ -473,9 +473,7 @@ surface surface(vertex[][] g) surface s=surface(g.length); for(int i=0; i < g.length; ++i) { vertex[] cur=g[i]; - s.s[i]=patch(new triple[] {cur[0].v,cur[0].v,cur[1].v,cur[2].v}, - normals=new triple[] {cur[0].normal,cur[0].normal, - cur[1].normal,cur[2].normal}); + s.s[i]=patch(cur[0].v--cur[1].v--cur[2].v--cycle); } return s; } diff --git a/Master/texmf-dist/asymptote/embed.asy b/Master/texmf-dist/asymptote/embed.asy index 588ad79c283..88495f12128 100644 --- a/Master/texmf-dist/asymptote/embed.asy +++ b/Master/texmf-dist/asymptote/embed.asy @@ -2,11 +2,6 @@ if(latex()) { usepackage("hyperref"); texpreamble("\hypersetup{"+settings.hyperrefOptions+"}"); usepackage("media9","bigfiles"); - texpreamble("\newif\ifplaybutton"); - texpreamble("\count255=\the\catcode`\@\makeatletter% -\@ifpackagelater{media9}{2013/11/15}{}{\playbuttontrue}% -\catcode`\@=\the\count255 -%"); } // For documentation of the options see @@ -19,11 +14,7 @@ string embedplayer(string name, string text="", string options="", if(width != 0) options += ",width="+(string) (width/pt)+"pt"; if(height != 0) options += ",height="+(string) (height/pt)+"pt"; return "% -\ifplaybutton% -\includemedia["+options+"]{"+text+"}{"+name+"}% -\else% -\includemedia[noplaybutton,"+options+"]{"+text+"}{"+name+"}% -\fi"; +\includemedia[noplaybutton,"+options+"]{"+text+"}{"+name+"}"; } // Embed media in pdf file diff --git a/Master/texmf-dist/asymptote/math.asy b/Master/texmf-dist/asymptote/math.asy index 47044a75df1..9d10e2b7794 100644 --- a/Master/texmf-dist/asymptote/math.asy +++ b/Master/texmf-dist/asymptote/math.asy @@ -423,3 +423,29 @@ pair[][] fft(pair[][] a, int sign=1) } return transpose(A); } + +// Given a matrix A with independent columns, return +// the unique vector y minimizing |Ay - b|^2 (the L2 norm). +// If the columns of A are not linearly independent, +// throw an error (if warn == true) or return an empty array +// (if warn == false). +real[] leastsquares(real[][] A, real[] b, bool warn=true) +{ + real[] solution=solve(AtA(A),b*A,warn=false); + if (solution.length == 0 && warn) + abort("Cannot compute least-squares approximation for " + + "a matrix with linearly dependent columns."); + return solution; +} + +// Namespace +struct rootfinder_settings { + static real roottolerance = 1e-4; +} + +real findroot(real f(real), real a, real b, + real tolerance=rootfinder_settings.roottolerance, + real fa=f(a), real fb=f(b)) +{ + return _findroot(f,a,b,tolerance,fa,fb); +} diff --git a/Master/texmf-dist/asymptote/plain_strings.asy b/Master/texmf-dist/asymptote/plain_strings.asy index f4c856e8ad9..a88e3863416 100644 --- a/Master/texmf-dist/asymptote/plain_strings.asy +++ b/Master/texmf-dist/asymptote/plain_strings.asy @@ -179,6 +179,11 @@ string graphic(string name, string options="") return "\externalfigure["+name+"]["+options+"]"; } +string graphicscale(real x) +{ + return string(settings.tex == "context" ? 1000*x : x); +} + string minipage(string s, real width=100bp) { if(latex()) @@ -223,4 +228,25 @@ string phantom(string s) return settings.tex != "none" ? "\phantom{"+s+"}" : ""; } +string[] spinner=new string[] {'|','/','-','\\'}; +spinner.cyclic=true; + +void progress(bool3 init=default) +{ + static int count=-1; + static int lastseconds=-1; + if(init == true) { + lastseconds=0; + write(stdout,' ',flush); + } else + if(init == default) { + int seconds=seconds(); + if(seconds > lastseconds) { + lastseconds=seconds; + write(stdout,'\b'+spinner[++count],flush); + } + } else + write(stdout,'\b',flush); +} + restricted int ocgindex=0; diff --git a/Master/texmf-dist/asymptote/smoothcontour3.asy b/Master/texmf-dist/asymptote/smoothcontour3.asy index 216f3269d92..4fe26654283 100644 --- a/Master/texmf-dist/asymptote/smoothcontour3.asy +++ b/Master/texmf-dist/asymptote/smoothcontour3.asy @@ -19,69 +19,7 @@ import graph_settings; // for nmesh import three; - -/***********************************************/ -/******** LINEAR ALGEBRA ROUTINES **************/ -/******** LEAST-SQUARES **************/ -/***********************************************/ - -// Apply a matrix to a vector. -real[] apply(real[][] matrix, real[] v) { - real[] ans = new real[matrix.length]; - for (int r = 0; r < matrix.length; ++r) { - ans[r] = 0; - for (int c = 0; c < v.length; ++c) { - ans[r] += matrix[r][c] * v[c]; - } - } - return ans; -} - -// Apply the transpose of a matrix to a vector, -// without actually forming the transpose. -real[] applytranspose(real[][] matrix, real[] v) { - real[] ans = new real[matrix[0].length]; - for (int r = 0; r < ans.length; ++r) ans[r] = 0; - for (int c = 0; c < matrix.length; ++c) { - for (int r = 0; r < ans.length; ++r) { - ans[r] += matrix[c][r] * v[c]; - } - } - return ans; -} - -// For a matrix A, returns the matrix product -// (A transposed) * A. -// The transpose of A is never actually formed. -real[][] AtA(real[][] matrix) { - real[][] toreturn = new real[matrix[0].length][matrix[0].length]; - for (int i = 0; i < toreturn.length; ++i) { - for (int j = 0; j < toreturn.length; ++j) { - toreturn [i][j] = 0; - } - } - for (int k = 0; k < matrix.length; ++k) { - for (int i = 0; i < toreturn.length; ++i) { - for (int j = 0; j < toreturn.length; ++j) { - toreturn[i][j] += matrix[k][i] * matrix[k][j]; - } - } - } - return toreturn; -} - -// Assuming A is a matrix with independent columns, returns -// the unique vector y minimizing |Ay - b|^2 (the L2 norm). -// If the columns of A are not linearly independent, -// throws an error (if warn == true) or returns an empty array -// (if warn == false). -real[] leastsquares(real[][] A, real[] b, bool warn = true) { - real[] solution = solve(AtA(A), applytranspose(A, b), warn=false); - if (solution.length == 0 && warn) - abort("Cannot compute least-squares approximation for " + - "a matrix with linearly dependent columns."); - return solution; -} +import math; /***********************************************/ /******** CREATING BEZIER PATCHES **************/ @@ -126,7 +64,7 @@ function[] bernstein = new function[] {B03, B13, B23, B33}; // the specified boundary path. However, the entries in the array // remain intact. patch patchwithnormals(path3 external, triple[] u0normals, triple[] u1normals, - triple[] v0normals, triple[] v1normals) + triple[] v0normals, triple[] v1normals) { assert(cyclic(external)); assert(length(external) == 4); @@ -275,8 +213,8 @@ patch patchwithnormals(path3 external, triple[] u0normals, triple[] u1normals, real[] solution = leastsquares(matrix, rightvector, warn=false); if (solution.length == 0) { // if the matrix was singular - write("Warning: unable to solve matrix for specifying normals " - + "on bezier patch. Using standard method."); + write("Warning: unable to solve matrix for specifying edge normals " + + "on bezier patch. Using coons patch."); return patch(external); } @@ -284,22 +222,95 @@ patch patchwithnormals(path3 external, triple[] u0normals, triple[] u1normals, for (int j = 1; j <= 2; ++j) { int position = 3 * (2 * (i-1) + (j-1)); controlpoints[i][j] = (solution[position], - solution[position+1], - solution[position+2]); + solution[position+1], + solution[position+2]); } } return patch(controlpoints); } -// A wrapper for the previous function when the normal direction +// This function attempts to produce a Bezier triangle +// with the specified boundary path and normal directions at the +// edge midpoints. The bezier triangle should be normal to +// n1 at point(external, 0.5), +// normal to n2 at point(external, 1.5), and +// normal to n3 at point(external, 2.5). +// The actual normal (as computed by the patch.normal() function) +// may be parallel to the specified normal, antiparallel, or +// even zero. +// +// A small amount of deviation is allowed in order to stabilize +// the algorithm (by keeping the mixed partials at the corners from +// growing too large). +patch trianglewithnormals(path3 external, triple n1, + triple n2, triple n3) { + assert(cyclic(external)); + assert(length(external) == 3); + // Use the formal symbols a3, a2b, abc, etc. to denote the control points, + // following the Wikipedia article on Bezier triangles. + triple a3 = point(external, 0), a2b = postcontrol(external, 0), + ab2 = precontrol(external, 1), b3 = point(external, 1), + b2c = postcontrol(external, 1), bc2 = precontrol(external, 2), + c3 = point(external, 2), ac2 = postcontrol(external, 2), + a2c = precontrol(external, 0); + + // Use orthogonal projection to ensure that the normal vectors are + // actually normal to the boundary path. + triple tangent = dir(external, 0.5); + n1 -= dot(n1,tangent)*tangent; + n1 = unit(n1); + + tangent = dir(external, 1.5); + n2 -= dot(n2,tangent)*tangent; + n2 = unit(n2); + + tangent = dir(external, 2.5); + n3 -= dot(n3,tangent)*tangent; + n3 = unit(n3); + + real wild = 2 * wildnessweight; + real[][] matrix = { {n1.x, n1.y, n1.z}, + {n2.x, n2.y, n2.z}, + {n3.x, n3.y, n3.z}, + { wild, 0, 0}, + { 0, wild, 0}, + { 0, 0, wild} }; + real[] rightvector = + { dot(n1, (a3 + 3a2b + 3ab2 + b3 - 2a2c - 2b2c)) / 4, + dot(n2, (b3 + 3b2c + 3bc2 + c3 - 2ab2 - 2ac2)) / 4, + dot(n3, (c3 + 3ac2 + 3a2c + a3 - 2bc2 - 2a2b)) / 4 }; + + // The inner control point that minimizes the sum of squares of + // the mixed partials on the corners. + triple tameinnercontrol = + ((a2b + a2c - a3) + (ab2 + b2c - b3) + (ac2 + bc2 - c3)) / 3; + rightvector.append(wild * new real[] + {tameinnercontrol.x, tameinnercontrol.y, tameinnercontrol.z}); + real[] solution = leastsquares(matrix, rightvector, warn=false); + if (solution.length == 0) { // if the matrix was singular + write("Warning: unable to solve matrix for specifying edge normals " + + "on bezier triangle. Using coons triangle."); + return patch(external); + } + triple innercontrol = (solution[0], solution[1], solution[2]); + return patch(external, innercontrol); +} + +// A wrapper for the previous functions when the normal direction // is given as a function of direction. The wrapper can also // accommodate cyclic boundary paths of between one and four // segments, although the results are best by far when there -// are four segments. +// are three or four segments. patch patchwithnormals(path3 external, triple normalat(triple)) { assert(cyclic(external)); assert(1 <= length(external) && length(external) <= 4); + if (length(external) == 3) { + triple n1 = normalat(point(external, 0.5)); + triple n2 = normalat(point(external, 1.5)); + triple n3 = normalat(point(external, 2.5)); + return trianglewithnormals(external, n1, n2, n3); + } while (length(external) < 4) external = external -- cycle; triple[] u0normals = new triple[3]; triple[] u1normals = new triple[3]; @@ -315,82 +326,6 @@ patch patchwithnormals(path3 external, triple normalat(triple)) { } /***********************************************/ -/*********** ROOT-FINDER UTILITY ***************/ -/***********************************************/ - -// Namespace -struct rootfinder_settings { - static real roottolerance = 1e-4; -} - -// Find a root for the specified continuous (but not -// necessarily differentiable) function. Whatever -// value t is returned, it is guaranteed that either -// t is within tolerance of a sign change, or -// abs(f(t)) <= 0.1 tolerance. -// An error is thrown if fa and fb are both positive -// or both negative. -// -// In the current implementation, binary search is interleaved -// with a modified version of linear interpolation. -real findroot(real f(real), real a, real b, - real tolerance = rootfinder_settings.roottolerance, - real fa = f(a), real fb = f(b)) -{ - if (fa == 0) return a; - if (fb == 0) return b; - real g(real); - if (fa < 0) { - assert(fb > 0); - g = f; - } else { - assert(fb < 0); - fa = -fa; - fb = -fb; - g = new real(real t) { return -f(t); }; - } - - real t = a; - real ft = fa; - - while (b - a > tolerance && abs(ft) > 0.1*tolerance) { - t = a + (b - a) / 2; - ft = g(t); - if (ft == 0) return t; - else if (ft > 0) { - b = t; - fb = ft; - } else if (ft < 0) { - a = t; - fa = ft; - } - - // linear interpolation - t = a - (b - a) / (fb - fa) * fa; - - // If the interpolated value is close to one edge of - // the interval, move it farther away from the edge in - // an effort to catch the root in the middle. - if (t - a < (b-a)/8) t = a + 2*(t-a); - else if (b - t < (b-a)/8) t = b - 2*(b-t); - - assert(t >= a && t <= b); - - ft = g(t); - if (ft == 0) return t; - else if (ft > 0) { - b = t; - fb = ft; - } else if (ft < 0) { - a = t; - fa = ft; - } - - } - return a - (b - a) / (fb - fa) * fa; -} - -/***********************************************/ /********* DUAL CUBE GRAPH UTILITY *************/ /***********************************************/ @@ -466,8 +401,8 @@ struct int_to_intset { void add(int key, int value) { for (int i = 0; i < keys.length; ++i) { if (keys[i] == key) { - values[i].add(value); - return; + values[i].add(value); + return; } } keys.push(key); @@ -561,9 +496,9 @@ int[] makecircle(edge[] edges) { if (adjacentvertices.length != 2) return null; for (int v : adjacentvertices) { if (v != lastvertex) { - lastvertex = currentvertex; - currentvertex = v; - break; + lastvertex = currentvertex; + currentvertex = v; + break; } } } while (currentvertex != startvertex); @@ -597,9 +532,10 @@ string operator cast(positionedvector vv) { // The angle, in degrees, between two vectors. real angledegrees(triple a, triple b) { - real lengthprod = abs(a) * abs(b); + real dotprod = dot(a,b); + real lengthprod = max(abs(a) * abs(b), abs(dotprod)); if (lengthprod == 0) return 0; - return aCos(dot(a,b) / lengthprod); + return aCos(dotprod / lengthprod); } // A path (single curved segment) between two points. At each point @@ -622,10 +558,10 @@ path3 pathbetween(positionedvector v1, positionedvector v2) { // the span of v1 and v2. If v1 and v2 are dependent, returns an empty array // (if warn==false) or throws an error (if warn==true). real[] projecttospan_findcoeffs(triple toproject, triple v1, triple v2, - bool warn=false) { + bool warn=false) { real[][] matrix = {{v1.x, v2.x}, - {v1.y, v2.y}, - {v1.z, v2.z}}; + {v1.y, v2.y}, + {v1.z, v2.z}}; real[] desiredanswer = {toproject.x, toproject.y, toproject.z}; return leastsquares(matrix, desiredanswer, warn=warn); } @@ -635,7 +571,7 @@ real[] projecttospan_findcoeffs(triple toproject, triple v1, triple v2, // a >= mincoeff and b >= mincoeff. If v1 and v2 are linearly dependent, // return a random (positive) linear combination. triple projecttospan(triple toproject, triple v1, triple v2, - real mincoeff = 0.05) { + real mincoeff = 0.05) { real[] coeffs = projecttospan_findcoeffs(toproject, v1, v2, warn=false); real a, b; if (coeffs.length == 0) { @@ -701,25 +637,25 @@ path3 bisector(path3 edgecycle, int[] savevertices) { int opposite = i + 3; triple vec = unit(point(edgecycle, opposite) - point(edgecycle, i)); real[] coeffsbegin = projecttospan_findcoeffs(vec, forwarddirections[i], - backwarddirections[i]); + backwarddirections[i]); if (coeffsbegin.length == 0) continue; coeffsbegin[0] = max(coeffsbegin[0], mincoeff); coeffsbegin[1] = max(coeffsbegin[1], mincoeff); real[] coeffsend = projecttospan_findcoeffs(-vec, forwarddirections[opposite], - backwarddirections[opposite]); + backwarddirections[opposite]); if (coeffsend.length == 0) continue; coeffsend[0] = max(coeffsend[0], mincoeff); coeffsend[1] = max(coeffsend[1], mincoeff); real goodness = angles[i] * angles[opposite] * coeffsbegin[0] * coeffsend[0] - * coeffsbegin[1] * coeffsend[1]; + * coeffsbegin[1] * coeffsend[1]; if (goodness > maxgoodness) { maxgoodness = goodness; directionout = coeffsbegin[0] * forwarddirections[i] + - coeffsbegin[1] * backwarddirections[i]; + coeffsbegin[1] * backwarddirections[i]; directionin = -(coeffsend[0] * forwarddirections[opposite] + - coeffsend[1] * backwarddirections[opposite]); + coeffsend[1] * backwarddirections[opposite]); chosenindex = i; } } @@ -738,7 +674,7 @@ path3 bisector(path3 edgecycle, int[] savevertices) { // A path between two specified points (with specified normals) that lies // within a specified face of a rectangular solid. path3 pathinface(positionedvector v1, positionedvector v2, - triple facenorm, triple edge1normout, triple edge2normout) + triple facenorm, triple edge1normout, triple edge2normout) { triple dir1 = cross(v1.direction, facenorm); real dotprod = dot(dir1, edge1normout); @@ -769,15 +705,16 @@ triple normalout(int face) { // A path between two specified points (with specified normals) that lies // within a specified face of a rectangular solid. path3 pathinface(positionedvector v1, positionedvector v2, - int face, int edge1face, int edge2face) { + int face, int edge1face, int edge2face) { return pathinface(v1, v2, normalout(face), normalout(edge1face), - normalout(edge2face)); + normalout(edge2face)); } /***********************************************/ /******** DRAWING IMPLICIT SURFACES ************/ /***********************************************/ +// DEPRECATED // Quadrilateralization: // Produce a surface (array of *nondegenerate* Bezier patches) with a // specified three-segment boundary. The surface should approximate the @@ -787,11 +724,12 @@ path3 pathinface(positionedvector v1, positionedvector v2, // specified rectangular region, returns a length-zero array. // // Dividing a triangle into smaller quadrilaterals this way is opposite -// the usual trend in mathematics. However, the pathwithnormals algorithm -// does a poor job of choosing a good surface when the boundary path does +// the usual trend in mathematics. However, *before the introduction of bezier +// triangles,* the pathwithnormals algorithm +// did a poor job of choosing a good surface when the boundary path did // not consist of four positive-length segments. patch[] triangletoquads(path3 external, real f(triple), triple grad(triple), - triple a, triple b) { + triple a, triple b) { static real epsilon = 1e-3; assert(length(external) == 3); assert(cyclic(external)); @@ -867,6 +805,65 @@ patch[] triangletoquads(path3 external, real f(triple), triple grad(triple), patchwithnormals(quad2, grad)}; } +// Attempts to fill the path external (which should by a cyclic path consisting of +// three segments) with bezier triangle(s). Returns an empty array if it fails. +// +// In more detail: A single bezier triangle is computed using trianglewithnormals. The normals of +// the resulting triangle at the midpoint of each edge are computed. If any of these normals +// is in the negative f direction, the external triangle is subdivided into four external triangles +// and the same procedure is applied to each. If one or more of them has an incorrectly oriented +// edge normal, the function gives up and returns an empty array. +// +// Thus, the returned array consists of 0, 1, or 4 bezier triangles; no other array lengths +// are possible. +// +// This function assumes that the path orientation is consistent with f (and its gradient) +// -- i.e., that +// at a corner, (tangent in) x (tangent out) is in the positive f direction. +patch[] maketriangle(path3 external, real f(triple), + triple grad(triple), bool allowsubdivide = true) { + assert(cyclic(external)); + assert(length(external) == 3); + triple m1 = point(external, 0.5); + triple n1 = unit(grad(m1)); + triple m2 = point(external, 1.5); + triple n2 = unit(grad(m2)); + triple m3 = point(external, 2.5); + triple n3 = unit(grad(m3)); + patch beziertriangle = trianglewithnormals(external, n1, n2, n3); + if (dot(n1, beziertriangle.normal(0.5, 0)) >= 0 && + dot(n2, beziertriangle.normal(0.5, 0.5)) >= 0 && + dot(n3, beziertriangle.normal(0, 0.5)) >= 0) + return new patch[] {beziertriangle}; + + if (!allowsubdivide) return new patch[0]; + + positionedvector m1 = positionedvector(m1, n1); + positionedvector m2 = positionedvector(m2, n2); + positionedvector m3 = positionedvector(m3, n3); + path3 p12 = pathbetween(m1, m2); + path3 p23 = pathbetween(m2, m3); + path3 p31 = pathbetween(m3, m1); + patch[] triangles = maketriangle(p12 & p23 & p31 & cycle, f, grad=grad, + allowsubdivide=false); + if (triangles.length < 1) return new patch[0]; + + triangles.append(maketriangle(subpath(external, -0.5, 0.5) & reverse(p31) & cycle, + f, grad=grad, allowsubdivide=false)); + if (triangles.length < 2) return new patch[0]; + + triangles.append(maketriangle(subpath(external, 0.5, 1.5) & reverse(p12) & cycle, + f, grad=grad, allowsubdivide=false)); + if (triangles.length < 3) return new patch[0]; + + triangles.append(maketriangle(subpath(external, 1.5, 2.5) & reverse(p23) & cycle, + f, grad=grad, allowsubdivide=false)); + if (triangles.length < 4) return new patch[0]; + + return triangles; +} + + // Returns true if the point is "nonsingular" (in the sense that the magnitude // of the gradient is not too small) AND very close to the zero locus of f // (assuming f is locally linear). @@ -891,14 +888,14 @@ bool checkptincube(triple pt, triple a, triple b) { if (zmin > zmax) { real t = zmax; zmax=zmin; zmin=t; } return ((xmin <= pt.x) && (pt.x <= xmax) && - (ymin <= pt.y) && (pt.y <= ymax) && - (zmin <= pt.z) && (pt.z <= zmax)); + (ymin <= pt.y) && (pt.y <= ymax) && + (zmin <= pt.z) && (pt.z <= zmax)); } // A convenience function for combining the previous two tests. bool checkpt(triple testpt, real f(triple), triple grad(triple), - triple a, triple b) { + triple a, triple b) { return checkptincube(testpt, a, b) && check_fpt_zero(testpt, f, grad); } @@ -910,8 +907,8 @@ bool checkpt(triple testpt, real f(triple), triple grad(triple), // array, which merely indicates that the boundary cycle is too small // to be worth filling in. patch[] quadpatches(path3 edgecycle, positionedvector[] corners, - real f(triple), triple grad(triple), - triple a, triple b) { + real f(triple), triple grad(triple), + triple a, triple b, bool usetriangles) { assert(corners.cyclic); // The tolerance for considering two points "essentially identical." @@ -924,8 +921,8 @@ patch[] quadpatches(path3 edgecycle, positionedvector[] corners, if (corners.length == 2) return new patch[0]; corners.delete(i); edgecycle = subpath(edgecycle, 0, i) - & subpath(edgecycle, i+1, length(edgecycle)) - & cycle; + & subpath(edgecycle, i+1, length(edgecycle)) + & cycle; --i; assert(length(edgecycle) == corners.length); } @@ -937,9 +934,9 @@ patch[] quadpatches(path3 edgecycle, positionedvector[] corners, if (corners.length == 2) { // If the area is too small, just ignore it; otherwise, subdivide. real area0 = abs(cross(-dir(edgecycle, 0, sign=-1, normalize=false), - dir(edgecycle, 0, sign=1, normalize=false))); + dir(edgecycle, 0, sign=1, normalize=false))); real area1 = abs(cross(-dir(edgecycle, 1, sign=-1, normalize=false), - dir(edgecycle, 1, sign=1, normalize=false))); + dir(edgecycle, 1, sign=1, normalize=false))); if (area0 < areatolerance && area1 < areatolerance) return new patch[0]; else return null; } @@ -947,13 +944,14 @@ patch[] quadpatches(path3 edgecycle, positionedvector[] corners, for (int i = 0; i < length(edgecycle); ++i) { if (angledegrees(dir(edgecycle,i,sign=1), - dir(edgecycle,i+1,sign=-1)) > 80) { + dir(edgecycle,i+1,sign=-1)) > 80) { return null; } } if (length(edgecycle) == 3) { - patch[] toreturn = triangletoquads(edgecycle, f, grad, a, b); + patch[] toreturn = usetriangles ? maketriangle(edgecycle, f, grad) + : triangletoquads(edgecycle, f, grad, a, b); if (toreturn.length == 0) return null; else return toreturn; } @@ -974,8 +972,9 @@ patch[] quadpatches(path3 edgecycle, positionedvector[] corners, & reverse(middleguide) & cycle; if (length(edgecycle) == 5) { path3 secondpatch = middleguide - & subpath(edgecycle, bisectorindices[1], 5+bisectorindices[0]) & cycle; - toreturn = triangletoquads(secondpatch, f, grad, a, b); + & subpath(edgecycle, bisectorindices[1], 5+bisectorindices[0]) & cycle; + toreturn = usetriangles ? maketriangle(secondpatch, f, grad) + : triangletoquads(secondpatch, f, grad, a, b); if (toreturn.length == 0) return null; toreturn.push(patchwithnormals(firstpatch, grad)); } else { @@ -984,7 +983,7 @@ patch[] quadpatches(path3 edgecycle, positionedvector[] corners, & subpath(edgecycle, bisectorindices[1], 6+bisectorindices[0]) & cycle; toreturn = new patch[] {patchwithnormals(firstpatch, grad), - patchwithnormals(secondpatch, grad)}; + patchwithnormals(secondpatch, grad)}; } return toreturn; } @@ -995,8 +994,8 @@ vectorfunction nGrad(real f(triple)) { static real epsilon = 1e-3; return new triple(triple v) { return ( (f(v + epsilon*X) - f(v - epsilon*X)) / (2 epsilon), - (f(v + epsilon*Y) - f(v - epsilon*Y)) / (2 epsilon), - (f(v + epsilon*Z) - f(v - epsilon*Z)) / (2 epsilon) ); + (f(v + epsilon*Y) - f(v - epsilon*Y)) / (2 epsilon), + (f(v + epsilon*Z) - f(v - epsilon*Z)) / (2 epsilon) ); }; } @@ -1015,18 +1014,18 @@ triple operator cast(evaluatedpoint p) { return p.pt; } // Compute the values of a function at every vertex of an nx by ny by nz // array of rectangular solids. evaluatedpoint[][][] make3dgrid(triple a, triple b, int nx, int ny, int nz, - real f(triple), bool allowzero = false) + real f(triple), bool allowzero = false) { evaluatedpoint[][][] toreturn = new evaluatedpoint[nx+1][ny+1][nz+1]; for (int i = 0; i <= nx; ++i) { for (int j = 0; j <= ny; ++j) { for (int k = 0; k <= nz; ++k) { - triple pt = (interp(a.x, b.x, i/nx), - interp(a.y, b.y, j/ny), - interp(a.z, b.z, k/nz)); - real value = f(pt); - if (value == 0 && !allowzero) value = 1e-5; - toreturn[i][j][k] = evaluatedpoint(pt, value); + triple pt = (interp(a.x, b.x, i/nx), + interp(a.y, b.y, j/ny), + interp(a.z, b.z, k/nz)); + real value = f(pt); + if (value == 0 && !allowzero) value = 1e-5; + toreturn[i][j][k] = evaluatedpoint(pt, value); } } } @@ -1045,8 +1044,8 @@ T[][] slice(T[][] a, int start1, int end1, int start2, int end2) { return toreturn; } T[][][] slice(T[][][] a, int start1, int end1, - int start2, int end2, - int start3, int end3) { + int start2, int end2, + int start3, int end3) { T[][][] toreturn = new T[end1-start1][][]; for (int i = start1; i < end1; ++i) { toreturn[i-start1] = slice(a[i], start2, end2, start3, end3); @@ -1062,8 +1061,8 @@ T[][] slice(T[][] a, int start1, int end1, int start2, int end2) { return toreturn; } T[][][] slice(T[][][] a, int start1, int end1, - int start2, int end2, - int start3, int end3) { + int start2, int end2, + int start3, int end3) { T[][][] toreturn = new T[end1-start1][][]; for (int i = start1; i < end1; ++i) { toreturn[i-start1] = slice(a[i], start2, end2, start3, end3); @@ -1083,73 +1082,74 @@ struct gridwithzeros { triple grad(triple); real f(triple); int maxdepth; + bool usetriangles; // Populate the edges with zeros that have a sign change and are not already // populated. void fillzeros() { for (int j = 0; j < ny+1; ++j) { for (int k = 0; k < nz+1; ++k) { - real y = corners[0][j][k].pt.y; - real z = corners[0][j][k].pt.z; - real f_along_x(real t) { return f((t, y, z)); } - for (int i = 0; i < nx; ++i) { - if (xdirzeros[i][j][k] != null) continue; - evaluatedpoint start = corners[i][j][k]; - evaluatedpoint end = corners[i+1][j][k]; - if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) - xdirzeros[i][j][k] = null; - else { - triple root = (0,y,z); - root += X * findroot(f_along_x, start.pt.x, end.pt.x, - fa=start.value, fb=end.value); - triple normal = grad(root); - xdirzeros[i][j][k] = positionedvector(root, normal); - } - } + real y = corners[0][j][k].pt.y; + real z = corners[0][j][k].pt.z; + real f_along_x(real t) { return f((t, y, z)); } + for (int i = 0; i < nx; ++i) { + if (xdirzeros[i][j][k] != null) continue; + evaluatedpoint start = corners[i][j][k]; + evaluatedpoint end = corners[i+1][j][k]; + if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) + xdirzeros[i][j][k] = null; + else { + triple root = (0,y,z); + root += X * findroot(f_along_x, start.pt.x, end.pt.x, + fa=start.value, fb=end.value); + triple normal = grad(root); + xdirzeros[i][j][k] = positionedvector(root, normal); + } + } } } for (int i = 0; i < nx+1; ++i) { for (int k = 0; k < nz+1; ++k) { - real x = corners[i][0][k].pt.x; - real z = corners[i][0][k].pt.z; - real f_along_y(real t) { return f((x, t, z)); } - for (int j = 0; j < ny; ++j) { - if (ydirzeros[i][j][k] != null) continue; - evaluatedpoint start = corners[i][j][k]; - evaluatedpoint end = corners[i][j+1][k]; - if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) - ydirzeros[i][j][k] = null; - else { - triple root = (x,0,z); - root += Y * findroot(f_along_y, start.pt.y, end.pt.y, - fa=start.value, fb=end.value); - triple normal = grad(root); - ydirzeros[i][j][k] = positionedvector(root, normal); - } - } + real x = corners[i][0][k].pt.x; + real z = corners[i][0][k].pt.z; + real f_along_y(real t) { return f((x, t, z)); } + for (int j = 0; j < ny; ++j) { + if (ydirzeros[i][j][k] != null) continue; + evaluatedpoint start = corners[i][j][k]; + evaluatedpoint end = corners[i][j+1][k]; + if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) + ydirzeros[i][j][k] = null; + else { + triple root = (x,0,z); + root += Y * findroot(f_along_y, start.pt.y, end.pt.y, + fa=start.value, fb=end.value); + triple normal = grad(root); + ydirzeros[i][j][k] = positionedvector(root, normal); + } + } } } for (int i = 0; i < nx+1; ++i) { for (int j = 0; j < ny+1; ++j) { - real x = corners[i][j][0].pt.x; - real y = corners[i][j][0].pt.y; - real f_along_z(real t) { return f((x, y, t)); } - for (int k = 0; k < nz; ++k) { - if (zdirzeros[i][j][k] != null) continue; - evaluatedpoint start = corners[i][j][k]; - evaluatedpoint end = corners[i][j][k+1]; - if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) - zdirzeros[i][j][k] = null; - else { - triple root = (x,y,0); - root += Z * findroot(f_along_z, start.pt.z, end.pt.z, - fa=start.value, fb=end.value); - triple normal = grad(root); - zdirzeros[i][j][k] = positionedvector(root, normal); - } - } + real x = corners[i][j][0].pt.x; + real y = corners[i][j][0].pt.y; + real f_along_z(real t) { return f((x, y, t)); } + for (int k = 0; k < nz; ++k) { + if (zdirzeros[i][j][k] != null) continue; + evaluatedpoint start = corners[i][j][k]; + evaluatedpoint end = corners[i][j][k+1]; + if ((start.value > 0 && end.value > 0) || (start.value < 0 && end.value < 0)) + zdirzeros[i][j][k] = null; + else { + triple root = (x,y,0); + root += Z * findroot(f_along_z, start.pt.z, end.pt.z, + fa=start.value, fb=end.value); + triple normal = grad(root); + zdirzeros[i][j][k] = positionedvector(root, normal); + } + } } } } @@ -1159,14 +1159,15 @@ struct gridwithzeros { // maximum subdivision depth. When a cube at maxdepth cannot be resolved to // patches, it is left empty. void operator init(int nx, int ny, int nz, - real f(triple), triple a, triple b, - int maxdepth = 6) { + real f(triple), triple a, triple b, + int maxdepth = 6, bool usetriangles) { this.nx = nx; this.ny = ny; this.nz = nz; grad = nGrad(f); this.f = f; this.maxdepth = maxdepth; + this.usetriangles = usetriangles; corners = make3dgrid(a, b, nx, ny, nz, f); xdirzeros = new positionedvector[nx][ny+1][nz+1]; ydirzeros = new positionedvector[nx+1][ny][nz+1]; @@ -1174,11 +1175,11 @@ struct gridwithzeros { for (int i = 0; i <= nx; ++i) { for (int j = 0; j <= ny; ++j) { - for (int k = 0; k <= nz; ++k) { - if (i < nx) xdirzeros[i][j][k] = null; - if (j < ny) ydirzeros[i][j][k] = null; - if (k < nz) zdirzeros[i][j][k] = null; - } + for (int k = 0; k <= nz; ++k) { + if (i < nx) xdirzeros[i][j][k] = null; + if (j < ny) ydirzeros[i][j][k] = null; + if (k < nz) zdirzeros[i][j][k] = null; + } } } @@ -1206,18 +1207,18 @@ struct gridwithzeros { corners = new evaluatedpoint[nx+1][ny+1][nz+1]; for (int i = 0; i <= nx; ++i) { for (int j = 0; j <= ny; ++j) { - for (int k = 0; k <= nz; ++k) { - if (i % 2 == 0 && j % 2 == 0 && k % 2 == 0) { - corners[i][j][k] = oldcorners[quotient(i,2)][quotient(j,2)][quotient(k,2)]; - } else { - triple pt = (interp(a.x, b.x, i/nx), - interp(a.y, b.y, j/ny), - interp(a.z, b.z, k/nz)); - real value = f(pt); - if (value == 0) value = 1e-5; - corners[i][j][k] = evaluatedpoint(pt, value); - } - } + for (int k = 0; k <= nz; ++k) { + if (i % 2 == 0 && j % 2 == 0 && k % 2 == 0) { + corners[i][j][k] = oldcorners[quotient(i,2)][quotient(j,2)][quotient(k,2)]; + } else { + triple pt = (interp(a.x, b.x, i/nx), + interp(a.y, b.y, j/ny), + interp(a.z, b.z, k/nz)); + real value = f(pt); + if (value == 0) value = 1e-5; + corners[i][j][k] = evaluatedpoint(pt, value); + } + } } } @@ -1225,23 +1226,23 @@ struct gridwithzeros { xdirzeros = new positionedvector[nx][ny+1][nz+1]; for (int i = 0; i < nx; ++i) { for (int j = 0; j < ny + 1; ++j) { - for (int k = 0; k < nz + 1; ++k) { - if (j % 2 != 0 || k % 2 != 0) { - xdirzeros[i][j][k] = null; - } else { - positionedvector zero = oldxdir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; - if (zero == null) { - xdirzeros[i][j][k] = null; - continue; - } - real x = zero.position.x; - if (x > interp(a.x, b.x, i/nx) && x < interp(a.x, b.x, (i+1)/nx)) { - xdirzeros[i][j][k] = zero; - } else { - xdirzeros[i][j][k] = null; - } - } - } + for (int k = 0; k < nz + 1; ++k) { + if (j % 2 != 0 || k % 2 != 0) { + xdirzeros[i][j][k] = null; + } else { + positionedvector zero = oldxdir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; + if (zero == null) { + xdirzeros[i][j][k] = null; + continue; + } + real x = zero.position.x; + if (x > interp(a.x, b.x, i/nx) && x < interp(a.x, b.x, (i+1)/nx)) { + xdirzeros[i][j][k] = zero; + } else { + xdirzeros[i][j][k] = null; + } + } + } } } @@ -1249,23 +1250,23 @@ struct gridwithzeros { ydirzeros = new positionedvector[nx+1][ny][nz+1]; for (int i = 0; i < nx+1; ++i) { for (int j = 0; j < ny; ++j) { - for (int k = 0; k < nz + 1; ++k) { - if (i % 2 != 0 || k % 2 != 0) { - ydirzeros[i][j][k] = null; - } else { - positionedvector zero = oldydir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; - if (zero == null) { - ydirzeros[i][j][k] = null; - continue; - } - real y = zero.position.y; - if (y > interp(a.y, b.y, j/ny) && y < interp(a.y, b.y, (j+1)/ny)) { - ydirzeros[i][j][k] = zero; - } else { - ydirzeros[i][j][k] = null; - } - } - } + for (int k = 0; k < nz + 1; ++k) { + if (i % 2 != 0 || k % 2 != 0) { + ydirzeros[i][j][k] = null; + } else { + positionedvector zero = oldydir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; + if (zero == null) { + ydirzeros[i][j][k] = null; + continue; + } + real y = zero.position.y; + if (y > interp(a.y, b.y, j/ny) && y < interp(a.y, b.y, (j+1)/ny)) { + ydirzeros[i][j][k] = zero; + } else { + ydirzeros[i][j][k] = null; + } + } + } } } @@ -1273,23 +1274,23 @@ struct gridwithzeros { zdirzeros = new positionedvector[nx+1][ny+1][nz]; for (int i = 0; i < nx + 1; ++i) { for (int j = 0; j < ny + 1; ++j) { - for (int k = 0; k < nz; ++k) { - if (i % 2 != 0 || j % 2 != 0) { - zdirzeros[i][j][k] = null; - } else { - positionedvector zero = oldzdir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; - if (zero == null) { - zdirzeros[i][j][k] = null; - continue; - } - real z = zero.position.z; - if (z > interp(a.z, b.z, k/nz) && z < interp(a.z, b.z, (k+1)/nz)) { - zdirzeros[i][j][k] = zero; - } else { - zdirzeros[i][j][k] = null; - } - } - } + for (int k = 0; k < nz; ++k) { + if (i % 2 != 0 || j % 2 != 0) { + zdirzeros[i][j][k] = null; + } else { + positionedvector zero = oldzdir[quotient(i,2)][quotient(j,2)][quotient(k,2)]; + if (zero == null) { + zdirzeros[i][j][k] = null; + continue; + } + real z = zero.position.z; + if (z > interp(a.z, b.z, k/nz) && z < interp(a.z, b.z, (k+1)/nz)) { + zdirzeros[i][j][k] = zero; + } else { + zdirzeros[i][j][k] = null; + } + } + } } } @@ -1316,14 +1317,14 @@ struct gridwithzeros { void pushifnonnull(positionedvector v) { if (v != null) { - zeroedges.push(edge(currentface, nextface)); - zeros.push(v); + zeroedges.push(edge(currentface, nextface)); + zeros.push(v); } } positionedvector findzero(int face1, int face2) { edge e = edge(face1, face2); for (int i = 0; i < zeroedges.length; ++i) { - if (zeroedges[i] == e) return zeros[i]; + if (zeroedges[i] == e) return zeros[i]; } return null; } @@ -1365,7 +1366,7 @@ struct gridwithzeros { patch[] subdividecube() { if (!subdivide()) { - return new patch[0]; + return new patch[0]; } return draw(reportactive); } @@ -1386,19 +1387,31 @@ struct gridwithzeros { path3 edgecycle; for (int i = 0; i < faceorder.length; ++i) { path3 currentpath = pathinface(patchcorners[i], patchcorners[i+1], - faceorder[i+1], faceorder[i], - faceorder[i+2]); + faceorder[i+1], faceorder[i], + faceorder[i+2]); triple testpoint = point(currentpath, 0.5); if (!checkpt(testpoint, f, grad, corners[0][0][0], corners[1][1][1])) { - return subdividecube(); + return subdividecube(); } edgecycle = edgecycle & currentpath; } edgecycle = edgecycle & cycle; + + { // Ensure the outward normals are pointing in the same direction as the gradient. + triple tangentin = patchcorners[0].position - precontrol(edgecycle, 0); + triple tangentout = postcontrol(edgecycle, 0) - patchcorners[0].position; + triple normal = cross(tangentin, tangentout); + if (dot(normal, patchcorners[0].direction) < 0) { + edgecycle = reverse(edgecycle); + patchcorners = patchcorners[-sequence(patchcorners.length)]; + patchcorners.cyclic = true; + } + } + patch[] toreturn = quadpatches(edgecycle, patchcorners, f, grad, - corners[0][0][0], corners[1][1][1]); + corners[0][0][0], corners[1][1][1], usetriangles); if (alias(toreturn, null)) return subdividecube(); return toreturn; } @@ -1413,6 +1426,7 @@ struct gridwithzeros { cube.ny = 1; cube.nz = 1; cube.maxdepth = maxdepth; + cube.usetriangles = usetriangles; cube.corners = slice(corners,i,i+2,j,j+2,k,k+2); cube.xdirzeros = slice(xdirzeros,i,i+1,j,j+2,k,k+2); cube.ydirzeros = slice(ydirzeros,i,i+2,j,j+1,k,k+2); @@ -1434,6 +1448,7 @@ struct gridwithzeros { // grid will subdivide all the way to maxdepth if necessary to find points // on the surface. draw = new patch[](bool[] reportactive = null) { + if (alias(reportactive, null)) progress(true); // A list of all the patches not already drawn but known // to contain part of the surface. This "queue" is // actually implemented as stack for simplicity, since @@ -1444,49 +1459,49 @@ struct gridwithzeros { bool[][][] enqueued = new bool[nx][ny][nz]; for (int i = 0; i < enqueued.length; ++i) { for (int j = 0; j < enqueued[i].length; ++j) { - for (int k = 0; k < enqueued[i][j].length; ++k) { - enqueued[i][j][k] = false; - } + for (int k = 0; k < enqueued[i][j].length; ++k) { + enqueued[i][j][k] = false; + } } } void enqueue(int i, int j, int k) { if (i >= 0 && i < nx - && j >= 0 && j < ny - && k >= 0 && k < nz - && !enqueued[i][j][k]) { - queue.push((i,j,k)); - enqueued[i][j][k] = true; + && j >= 0 && j < ny + && k >= 0 && k < nz + && !enqueued[i][j][k]) { + queue.push((i,j,k)); + enqueued[i][j][k] = true; } if (!alias(reportactive, null)) { - if (i < 0) reportactive[XLOW] = true; - if (i >= nx) reportactive[XHIGH] = true; - if (j < 0) reportactive[YLOW] = true; - if (j >= ny) reportactive[YHIGH] = true; - if (k < 0) reportactive[ZLOW] = true; - if (k >= nz) reportactive[ZHIGH] = true; + if (i < 0) reportactive[XLOW] = true; + if (i >= nx) reportactive[XHIGH] = true; + if (j < 0) reportactive[YLOW] = true; + if (j >= ny) reportactive[YHIGH] = true; + if (k < 0) reportactive[ZLOW] = true; + if (k >= nz) reportactive[ZHIGH] = true; } } for (int i = 0; i < nx+1; ++i) { for (int j = 0; j < ny+1; ++j) { - for (int k = 0; k < nz+1; ++k) { - if (i < nx && xdirzeros[i][j][k] != null) { - for (int jj = j-1; jj <= j; ++jj) - for (int kk = k-1; kk <= k; ++kk) - enqueue(i, jj, kk); - } - if (j < ny && ydirzeros[i][j][k] != null) { - for (int ii = i-1; ii <= i; ++ii) - for (int kk = k-1; kk <= k; ++kk) - enqueue(ii, j, kk); - } - if (k < nz && zdirzeros[i][j][k] != null) { - for (int ii = i-1; ii <= i; ++ii) - for (int jj = j-1; jj <= j; ++jj) - enqueue(ii, jj, k); - } - } + for (int k = 0; k < nz+1; ++k) { + if (i < nx && xdirzeros[i][j][k] != null) { + for (int jj = j-1; jj <= j; ++jj) + for (int kk = k-1; kk <= k; ++kk) + enqueue(i, jj, kk); + } + if (j < ny && ydirzeros[i][j][k] != null) { + for (int ii = i-1; ii <= i; ++ii) + for (int kk = k-1; kk <= k; ++kk) + enqueue(ii, j, kk); + } + if (k < nz && zdirzeros[i][j][k] != null) { + for (int ii = i-1; ii <= i; ++ii) + for (int jj = j-1; jj <= j; ++jj) + enqueue(ii, jj, k); + } + } } } @@ -1510,9 +1525,9 @@ struct gridwithzeros { if (reportface[ZLOW]) enqueue(i,j,k-1); if (reportface[ZHIGH]) enqueue(i,j,k+1); surface.append(toappend); - if (settings.verbose > 1 && alias(reportactive, null)) write(stdout, '.'); + if (alias(reportactive, null)) progress(); } - if (settings.verbose > 1 && alias(reportactive, null)) write(stdout, '\n'); + if (alias(reportactive, null)) progress(false); return surface; }; } @@ -1540,22 +1555,25 @@ struct gridwithzeros { // maxdepth - the maximum depth to which the algorithm will subdivide in // an effort to find patches that closely approximate the true surface. surface implicitsurface(real f(triple) = null, real ff(real,real,real) = null, - triple a, triple b, - int n = nmesh, - bool keyword overlapedges = false, - int keyword nx=n, int keyword ny=n, - int keyword nz=n, - int keyword maxdepth = 8) { + triple a, triple b, + int n = nmesh, + bool keyword overlapedges = false, + int keyword nx=n, int keyword ny=n, + int keyword nz=n, + int keyword maxdepth = 8, + bool keyword usetriangles=true) { if (f == null && ff == null) abort("implicitsurface called without specifying a function."); if (f != null && ff != null) abort("Only specify one function when calling implicitsurface."); if (f == null) f = new real(triple w) { return ff(w.x, w.y, w.z); }; - gridwithzeros grid = gridwithzeros(nx, ny, nz, f, a, b, maxdepth=maxdepth); + gridwithzeros grid = gridwithzeros(nx, ny, nz, f, a, b, maxdepth=maxdepth, + usetriangles=usetriangles); patch[] patches = grid.draw(); if (overlapedges) { for (int i = 0; i < patches.length; ++i) { - triple center = patches[i].point(1/2,1/2); + triple center = (patches[i].triangular ? + patches[i].point(1/3, 1/3) : patches[i].point(1/2,1/2)); patches[i] = shift(center) * scale3(1.01) * shift(-center) * patches[i]; } } diff --git a/Master/texmf-dist/asymptote/three_surface.asy b/Master/texmf-dist/asymptote/three_surface.asy index f2f21eb826c..c6d439e9fb0 100644 --- a/Master/texmf-dist/asymptote/three_surface.asy +++ b/Master/texmf-dist/asymptote/three_surface.asy @@ -9,12 +9,21 @@ string meshname(string name) {return name+" mesh";} private real Fuzz=10.0*realEpsilon; private real nineth=1/9; +// Return the default Coons interior control point for a Bezier triangle +// based on the cyclic path3 external. +triple coons3(path3 external) { + return 0.25*(precontrol(external,0)+postcontrol(external,0)+ + precontrol(external,1)+postcontrol(external,1)+ + precontrol(external,2)+postcontrol(external,2))- + (point(external,0)+point(external,1)+point(external,2))/6; +} + struct patch { triple[][] P; - triple[] normals; // Optionally specify 4 normal vectors at the corners. pen[] colors; // Optionally specify 4 corner colors. bool straight; // Patch is based on a piecewise straight external path. bool3 planar; // Patch is planar. + bool triangular; // Patch is a Bezier triangle. path3 external() { return straight ? P[0][0]--P[3][0]--P[3][3]--P[0][3]--cycle : @@ -24,22 +33,44 @@ struct patch { P[0][3]..controls P[0][2] and P[0][1]..cycle; } + path3 externaltriangular() { + return + P[0][0]..controls P[1][0] and P[2][0].. + P[3][0]..controls P[3][1] and P[3][2].. + P[3][3]..controls P[2][2] and P[1][1]..cycle; + } + triple[] internal() { return new triple[] {P[1][1],P[2][1],P[2][2],P[1][2]}; } + triple[] internaltriangular() { + return new triple[] {P[2][1]}; + } + triple cornermean() { return 0.25*(P[0][0]+P[0][3]+P[3][0]+P[3][3]); } + triple cornermeantriangular() { + return (P[0][0]+P[3][0]+P[3][3])/3; + } + triple[] corners() {return new triple[] {P[0][0],P[3][0],P[3][3],P[0][3]};} + triple[] cornerstriangular() {return new triple[] {P[0][0],P[3][0],P[3][3]};} real[] map(real f(triple)) { return new real[] {f(P[0][0]),f(P[3][0]),f(P[3][3]),f(P[0][3])}; } + real[] maptriangular(real f(triple)) { + return new real[] {f(P[0][0]),f(P[3][0]),f(P[3][3])}; + } + triple Bu(int j, real u) {return bezier(P[0][j],P[1][j],P[2][j],P[3][j],u);} - triple BuP(int j, real u) {return bezierP(P[0][j],P[1][j],P[2][j],P[3][j],u);} + triple BuP(int j, real u) { + return bezierP(P[0][j],P[1][j],P[2][j],P[3][j],u); + } triple BuPP(int j, real u) { return bezierPP(P[0][j],P[1][j],P[2][j],P[3][j],u); } @@ -53,7 +84,9 @@ struct patch { } triple Bv(int i, real v) {return bezier(P[i][0],P[i][1],P[i][2],P[i][3],v);} - triple BvP(int i, real v) {return bezierP(P[i][0],P[i][1],P[i][2],P[i][3],v);} + triple BvP(int i, real v) { + return bezierP(P[i][0],P[i][1],P[i][2],P[i][3],v); + } triple BvPP(int i, real v) { return bezierPP(P[i][0],P[i][1],P[i][2],P[i][3],v); } @@ -131,13 +164,96 @@ struct patch { return abs(n) > epsilon ? n : normal0(0,1,epsilon); } + triple pointtriangular(real u, real v) { + real w=1-u-v; + return w^2*(w*P[0][0]+3*(u*P[1][0]+v*P[1][1]))+ + u^2*(3*(w*P[2][0]+v*P[3][1])+u*P[3][0])+ + 6*u*v*w*P[2][1]+v^2*(3*(w*P[2][2]+u*P[3][2])+v*P[3][3]); + } + + triple bu(real u, real v) { + // Compute one-third of the directional derivative of a Bezier triangle + // in the u direction at (u,v). + real w=1-u-v; + return -w^2*P[0][0]+w*(w-2*u)*P[1][0]-2*w*v*P[1][1]+u*(2*w-u)*P[2][0]+ + 2*v*(w-u)*P[2][1]-v^2*P[2][2]+u^2*P[3][0]+2*u*v*P[3][1]+v^2*P[3][2]; + } + + triple buu(real u, real v) { + // Compute one-sixth of the second directional derivative of a Bezier + // triangle in the u direction at (u,v). + real w=1-u-v; + return w*P[0][0]+(u-2*w)*P[1][0]+v*P[1][1]+(w-2*u)*P[2][0]-2*v*P[2][1]+ + u*P[3][0]+v*P[3][1]; + } + + triple buuu() { + // Compute one-sixth of the third directional derivative of a Bezier + // triangle in the u direction at (u,v). + return -P[0][0]+3*P[1][0]-3*P[2][0]+P[3][0]; + } + + triple bv(real u, real v) { + // Compute one-third of the directional derivative of a Bezier triangle + // in the v direction at (u,v). + real w=1-u-v; + return -w^2*P[0][0]-2*u*w*P[1][0]+w*(w-2*v)*P[1][1]-u^2*P[2][0]+ + 2*u*(w-v)*P[2][1]+v*(2*w-v)*P[2][2]+u*u*P[3][1]+2*u*v*P[3][2]+ + v^2*P[3][3]; + } + + triple bvv(real u, real v) { + // Compute one-sixth of the second directional derivative of a Bezier + // triangle in the v direction at (u,v). + real w=1-u-v; + return w*P[0][0]+u*P[1][0]+(v-2*w)*P[1][1]-2*u*P[2][1]+(w-2*v)*P[2][2]+ + u*P[3][2]+v*P[3][3]; + } + + triple bvvv() { + // Compute one-sixth of the third directional derivative of a Bezier + // triangle in the v direction at (u,v). + return -P[0][0]+3*P[1][1]-3*P[2][2]+P[3][3]; + } + + // compute normal vectors for a degenerate Bezier triangle + private triple normaltriangular0(real u, real v, real epsilon) { + triple n=9*(cross(buu(u,v),bv(u,v))+ + cross(bu(u,v),bvv(u,v))); + return abs(n) > epsilon ? n : + 9*cross(buu(u,v),bvv(u,v))+ + 3*(cross(buuu(),bv(u,v))+cross(bu(u,v),bvvv())+ + cross(buuu(),bvv(u,v))+cross(buu(u,v),bvvv()))+ + cross(buuu(),bvvv()); + } + + // Compute the normal of a Bezier triangle at (u,v) + triple normaltriangular(real u, real v) { + triple n=9*cross(bu(u,v),bv(u,v)); + real epsilon=fuzz*change2(P); + return (abs(n) > epsilon) ? n : normal0(u,v,epsilon); + } + + triple normal00triangular() { + triple n=9*cross(P[1][0]-P[0][0],P[1][1]-P[0][0]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normaltriangular0(0,0,epsilon); + } + + triple normal10triangular() { + triple n=9*cross(P[3][0]-P[2][0],P[3][1]-P[2][0]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normaltriangular0(1,0,epsilon); + } + + triple normal01triangular() { + triple n=9*cross(P[3][2]-P[2][2],P[3][3]-P[2][2]); + real epsilon=fuzz*change2(P); + return abs(n) > epsilon ? n : normaltriangular0(0,1,epsilon); + } + pen[] colors(material m, light light=currentlight) { bool nocolors=colors.length == 0; - if(normals.length > 0) - return new pen[] {color(normals[0],nocolors ? m : colors[0],light), - color(normals[1],nocolors ? m : colors[1],light), - color(normals[2],nocolors ? m : colors[2],light), - color(normals[3],nocolors ? m : colors[3],light)}; if(planar) { triple normal=normal(0.5,0.5); return new pen[] {color(normal,nocolors ? m : colors[0],light), @@ -151,12 +267,40 @@ struct patch { color(normal01(),nocolors ? m : colors[3],light)}; } + pen[] colorstriangular(material m, light light=currentlight) { + bool nocolors=colors.length == 0; + if(planar) { + triple normal=normal(1/3,1/3); + return new pen[] {color(normal,nocolors ? m : colors[0],light), + color(normal,nocolors ? m : colors[1],light), + color(normal,nocolors ? m : colors[2],light)}; + } + return new pen[] {color(normal00(),nocolors ? m : colors[0],light), + color(normal10(),nocolors ? m : colors[1],light), + color(normal01(),nocolors ? m : colors[2],light)}; + } + triple min3,max3; bool havemin3,havemax3; void init() { havemin3=false; havemax3=false; + if(triangular) { + external=externaltriangular; + internal=internaltriangular; + cornermean=cornermeantriangular; + corners=cornerstriangular; + map=maptriangular; + point=pointtriangular; + normal=normaltriangular; + normal00=normal00triangular; + normal10=normal10triangular; + normal01=normal01triangular; + colors=colorstriangular; + uequals=new path3(real u) {return nullpath3;}; + vequals=new path3(real u) {return nullpath3;}; + } } triple min(triple bound=P[0][0]) { @@ -191,63 +335,81 @@ struct patch { return minratio(Q,d*bound)/d; // d is negative } - void operator init(triple[][] P, triple[] normals=new triple[], + void operator init(triple[][] P, pen[] colors=new pen[], bool straight=false, - bool3 planar=default, bool copy=true) { - init(); + bool3 planar=default, bool triangular=false, + bool copy=true) { this.P=copy ? copy(P) : P; - if(normals.length != 0) - this.normals=copy(normals); if(colors.length != 0) this.colors=copy(colors); - this.planar=planar; this.straight=straight; + this.planar=planar; + this.triangular=triangular; + init(); } void operator init(pair[][] P, triple plane(pair)=XYplane, - bool straight=false) { + bool straight=false, bool triangular=false) { triple[][] Q=new triple[4][]; for(int i=0; i < 4; ++i) { pair[] Pi=P[i]; Q[i]=sequence(new triple(int j) {return plane(Pi[j]);},4); } - operator init(Q,straight); - planar=true; + operator init(Q,straight,planar=true,triangular); } void operator init(patch s) { - operator init(s.P,s.normals,s.colors,s.straight); - } + operator init(s.P,s.colors,s.straight,s.planar,s.triangular); + } - // A constructor for a convex cyclic path3 of length <= 4 with optional - // arrays of 4 internal points, corner normals, and pens. - void operator init(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], + // A constructor for a cyclic path3 of length 3 with a specified + // internal point, corner normals, and pens (rendered as a Bezier triangle). + void operator init(path3 external, triple internal, pen[] colors=new pen[], bool3 planar=default) { + triangular=true; + this.planar=planar; init(); + if(colors.length != 0) + this.colors=copy(colors); + + P=new triple[][] { + {point(external,0)}, + {postcontrol(external,0),precontrol(external,0)}, + {precontrol(external,1),internal,postcontrol(external,2)}, + {point(external,1),postcontrol(external,1),precontrol(external,2), + point(external,2)} + }; + } + // A constructor for a convex cyclic path3 of length <= 4 with optional + // arrays of internal points (4 for a Bezier patch, 1 for a Bezier + // triangle), and pens. + void operator init(path3 external, triple[] internal=new triple[], + pen[] colors=new pen[], bool3 planar=default) { if(internal.length == 0 && planar == default) this.planar=normal(external) != O; else this.planar=planar; int L=length(external); + + if(L == 3) { + operator init(external,internal.length == 1 ? internal[0] : + coons3(external),colors,this.planar); + straight=piecewisestraight(external); + return; + } + if(L > 4 || !cyclic(external)) abort("cyclic path3 of length <= 4 expected"); if(L == 1) { external=external--cycle--cycle--cycle; if(colors.length > 0) colors.append(array(3,colors[0])); - if(normals.length > 0) normals.append(array(3,normals[0])); } else if(L == 2) { external=external--cycle--cycle; if(colors.length > 0) colors.append(array(2,colors[0])); - if(normals.length > 0) normals.append(array(2,normals[0])); - } else if(L == 3) { - external=external--cycle; - if(colors.length > 0) colors.push(colors[0]); - if(normals.length > 0) normals.push(normals[0]); } - if(normals.length != 0) - this.normals=copy(normals); + + init(); if(colors.length != 0) this.colors=copy(colors); @@ -261,7 +423,7 @@ struct patch { +3*(precontrol(external,j-1)+ postcontrol(external,j+1)) -point(external,j+2)); - } else straight=false; + } P=new triple[][] { {point(external,0),precontrol(external,0),postcontrol(external,3), @@ -275,16 +437,13 @@ struct patch { // A constructor for a convex quadrilateral. void operator init(triple[] external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { init(); if(internal.length == 0 && planar == default) this.planar=normal(external) != O; else this.planar=planar; - if(normals.length != 0) - this.normals=copy(normals); if(colors.length != 0) this.colors=copy(colors); @@ -313,41 +472,46 @@ struct patch { patch operator * (transform3 t, patch s) { patch S; - S.P=new triple[4][4]; - for(int i=0; i < 4; ++i) { + S.P=new triple[s.P.length][]; + for(int i=0; i < s.P.length; ++i) { triple[] si=s.P[i]; triple[] Si=S.P[i]; - for(int j=0; j < 4; ++j) + for(int j=0; j < si.length; ++j) Si[j]=t*si[j]; } - if(s.normals.length > 0) { - transform3 t0=shiftless(t); - t0=determinant(t0) == 0 ? identity4 : transpose(inverse(t0)); - for(int i=0; i < s.normals.length; ++i) - S.normals[i]=t0*s.normals[i]; - } - S.colors=copy(s.colors); S.planar=s.planar; S.straight=s.straight; + S.triangular=s.triangular; + S.init(); return S; } patch reverse(patch s) { + assert(!s.triangular); patch S; S.P=transpose(s.P); - if(s.normals.length > 0) - S.normals= - new triple[] {s.normals[0],s.normals[3],s.normals[2],s.normals[1]}; - if(s.colors.length > 0) + if(s.colors.length > 0) S.colors=new pen[] {s.colors[0],s.colors[3],s.colors[2],s.colors[1]}; - S.planar=s.planar; S.straight=s.straight; + S.planar=s.planar; return S; } +// Return a degenerate tensor patch representation of a Bezier triangle. +patch tensor(patch s) { + if(!s.triangular) return patch(s); + triple[][] P=s.P; + return patch(new triple[][] {{P[0][0],P[0][0],P[0][0],P[0][0]}, + {P[1][0],P[1][0]*2/3+P[1][1]/3,P[1][0]/3+P[1][1]*2/3,P[1][1]}, + {P[2][0],P[2][0]/3+P[2][1]*2/3,P[2][1]*2/3+P[2][2]/3,P[2][2]}, + {P[3][0],P[3][1],P[3][2],P[3][3]}}, + s.colors.length > 0 ? new pen[] {s.colors[0],s.colors[1],s.colors[2],s.colors[0]} : new pen[], + s.straight,s.planar,false,false); +} + // Return the tensor product patch control points corresponding to path p // and points internal. pair[][] tensor(path p, pair[] internal) @@ -589,7 +753,7 @@ path[] regularize(path p, bool checkboundary=true) struct surface { patch[] s; - int index[][]; + int index[][];// Position of patch corresponding to major U,V parameter in s. bool vcyclic; bool empty() { @@ -612,11 +776,11 @@ struct surface { this.vcyclic=s.vcyclic; } - void operator init(triple[][][] P, triple[][] normals=new triple[][], - pen[][] colors=new pen[][], bool3 planar=default) { + void operator init(triple[][][] P, pen[][] colors=new pen[][], + bool3 planar=default, bool triangular=false) { s=sequence(new patch(int i) { - return patch(P[i],normals.length == 0 ? new triple[] : normals[i], - colors.length == 0 ? new pen[] : colors[i],planar); + return patch(P[i],colors.length == 0 ? new pen[] : colors[i],planar, + triangular); },P.length); } @@ -698,11 +862,16 @@ struct surface { return ucyclic() ? g&cycle : g; } - // A constructor for a possibly nonconvex simple cyclic path in a given plane. + // A constructor for a possibly nonconvex simple cyclic path in a given + // plane. void operator init(path p, triple plane(pair)=XYplane) { - bool straight=piecewisestraight(p); - for(path g : regularize(p)) - s.push(patch(coons(g),plane,straight)); + for(path g : regularize(p)) { + if(length(g) == 3) { + path3 G=path3(g,plane); + s.push(patch(G,coons3(G),planar=true)); + } else + s.push(patch(coons(g),plane,piecewisestraight(g))); + } } void operator init(explicit path[] g, triple plane(pair)=XYplane) { @@ -712,19 +881,17 @@ struct surface { // A general surface constructor for both planar and nonplanar 3D paths. void construct(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { int L=length(external); if(!cyclic(external)) abort("cyclic path expected"); if(L <= 3 && piecewisestraight(external)) { - s.push(patch(external,internal,normals,colors,planar=true)); + s.push(patch(external,internal,colors,planar)); return; } // Construct a surface from a possibly nonconvex planar cyclic path3. - if(planar != false && internal.length == 0 && normals.length == 0 && - colors.length == 0) { + if(planar != false && internal.length == 0 && colors.length == 0) { triple n=normal(external); if(n != O) { transform3 T=align(n); @@ -737,7 +904,7 @@ struct surface { } if(L <= 4 || internal.length > 0) { - s.push(patch(external,internal,normals,colors,planar)); + s.push(patch(external,internal,colors,planar)); return; } @@ -746,40 +913,33 @@ struct surface { pen[] p; triple[] n; bool nocolors=colors.length == 0; - bool nonormals=normals.length == 0; triple center; for(int i=0; i < L; ++i) center += point(external,i); center *= factor; if(!nocolors) p=new pen[] {mean(colors)}; - if(!nonormals) - n=new triple[] {factor*sum(normals)}; // Use triangles for nonplanar surfaces. int step=normal(external) == O ? 1 : 2; int i=0; int end; while((end=i+step) < L) { s.push(patch(subpath(external,i,end)--center--cycle, - nonormals ? n : concat(normals[i:end+1],n), nocolors ? p : concat(colors[i:end+1],p),planar)); i=end; } s.push(patch(subpath(external,i,L)--center--cycle, - nonormals ? n : concat(normals[i:],normals[0:1],n), nocolors ? p : concat(colors[i:],colors[0:1],p),planar)); } void operator init(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[], pen[] colors=new pen[], - bool3 planar=default) { + pen[] colors=new pen[], bool3 planar=default) { s=new patch[]; - construct(external,internal,normals,colors,planar); + construct(external,internal,colors,planar); } void operator init(explicit path3[] external, triple[][] internal=new triple[][], - triple[][] normals=new triple[][], pen[][] colors=new pen[][], bool3 planar=default) { s=new patch[]; if(planar == true) {// Assume all path3 elements share a common normal. @@ -801,14 +961,12 @@ struct surface { for(int i=0; i < external.length; ++i) construct(external[i], internal.length == 0 ? new triple[] : internal[i], - normals.length == 0 ? new triple[] : normals[i], colors.length == 0 ? new pen[] : colors[i],planar); } void push(path3 external, triple[] internal=new triple[], - triple[] normals=new triple[] ,pen[] colors=new pen[], - bool3 planar=default) { - s.push(patch(external,internal,normals,colors,planar)); + pen[] colors=new pen[], bool3 planar=default) { + s.push(patch(external,internal,colors,planar)); } // Construct the surface of rotation generated by rotating g @@ -1111,7 +1269,7 @@ triple[][] subpatch(triple[][] P, pair a, pair b) patch subpatch(patch s, pair a, pair b) { assert(a.x >= 0 && a.y >= 0 && b.x <= 1 && b.y <= 1 && - a.x < b.x && a.y < b.y); + a.x < b.x && a.y < b.y && !s.triangular); return patch(subpatch(s.P,a,b),s.straight,s.planar); } @@ -1244,8 +1402,14 @@ void draw3D(frame f, int type=0, patch s, triple center=O, material m, if(prc()) PRCshininess=PRCshininess(m.shininess); - draw(f,s.P,center,s.straight,m.p,m.opacity,m.shininess,PRCshininess, - s.planar ? s.normal(0.5,0.5) : O,s.colors,interaction.type,prc); + if(s.triangular) + drawbeziertriangle(f,s.P,center,s.straight && s.planar,m.p, + m.opacity,m.shininess,PRCshininess,s.colors, + interaction.type); + else + draw(f,s.P,center,s.straight && s.planar,m.p,m.opacity,m.shininess, + PRCshininess,s.planar ? s.normal(0.5,0.5) : O,s.colors, + interaction.type,prc); } // Draw triangles on a frame. @@ -1337,11 +1501,13 @@ void draw(picture pic=currentpicture, triple[] v, int[][] vi, pic.addPoint(v[viij]); } -void drawPRCsphere(frame f, transform3 t=identity4, bool half=false, material m, - light light=currentlight, render render=defaultrender) +void drawPRCsphere(frame f, transform3 t=identity4, bool half=false, + material m, light light=currentlight, + render render=defaultrender) { m=material(m,light); - drawPRCsphere(f,t,half,m.p,m.opacity,PRCshininess(m.shininess),render.sphere); + drawPRCsphere(f,t,half,m.p,m.opacity,PRCshininess(m.shininess), + render.sphere); } void drawPRCcylinder(frame f, transform3 t=identity4, material m, @@ -1368,9 +1534,15 @@ void drawPRCtube(frame f, path3 center, path3 g, material m, void tensorshade(transform t=identity(), frame f, patch s, material m, light light=currentlight, projection P) { + + pen[] p; + if(s.triangular) { + p=s.colorstriangular(m,light); + p.push(p[0]); + s=tensor(s); + } else p=s.colors(m,light); tensorshade(f,box(t*s.min(P),t*s.max(P)),m.diffuse(), - s.colors(m,light),t*project(s.external(),P,1), - t*project(s.internal(),P)); + p,t*project(s.external(),P,1),t*project(s.internal(),P)); } restricted pen[] nullpens={nullpen}; @@ -1397,7 +1569,7 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, real[][] depth=new real[s.s.length][]; for(int i=0; i < depth.length; ++i) - depth[i]=new real[] {abs(camera-s.s[i].cornermean()),i}; + depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i}; depth=sort(depth); @@ -1414,18 +1586,19 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, for(int p=depth.length-1; p >= 0; --p) { real[] a=depth[p]; int k=round(a[1]); + patch S=s.s[k]; pen meshpen=meshpen[k]; - if(!invisible(meshpen)) { + if(!invisible(meshpen) && !S.triangular) { if(group) begingroup3(f,meshname(name),render); meshpen=modifiers+meshpen; real step=nu == 0 ? 0 : 1/nu; for(int i=0; i <= nu; ++i) - draw(f,s.s[k].uequals(i*step),meshpen,meshlight,partname(i,render), + draw(f,S.uequals(i*step),meshpen,meshlight,partname(i,render), render); step=nv == 0 ? 0 : 1/nv; for(int j=0; j <= nv; ++j) - draw(f,s.s[k].vequals(j*step),meshpen,meshlight,partname(j,render), + draw(f,S.vequals(j*step),meshpen,meshlight,partname(j,render), render); if(group) endgroup3(f); @@ -1444,7 +1617,7 @@ void draw(transform t=identity(), frame f, surface s, int nu=1, int nv=1, real[][] depth=new real[s.s.length][]; for(int i=0; i < depth.length; ++i) - depth[i]=new real[] {abs(camera-s.s[i].cornermean()),i}; + depth[i]=new real[] {dot(P.normal,camera-s.s[i].cornermean()),i}; depth=sort(depth); @@ -1507,8 +1680,9 @@ void draw(picture pic=currentpicture, surface s, int nu=1, int nv=1, pen modifiers; if(is3D()) modifiers=thin()+squarecap; for(int k=0; k < s.s.length; ++k) { + patch S=s.s[k]; pen meshpen=meshpen[k]; - if(!invisible(meshpen)) { + if(!invisible(meshpen) && !S.triangular) { meshpen=modifiers+meshpen; real step=nu == 0 ? 0 : 1/nu; for(int i=0; i <= nu; ++i) diff --git a/Master/texmf-dist/asymptote/three_tube.asy b/Master/texmf-dist/asymptote/three_tube.asy index bbbd5a65633..25bb9385ec8 100644 --- a/Master/texmf-dist/asymptote/three_tube.asy +++ b/Master/texmf-dist/asymptote/three_tube.asy @@ -176,18 +176,24 @@ bool uperiodic(real[][] a) { int m=a[0].length; real[] a0=a[0]; real[] a1=a[n-1]; - real epsilon=sqrtEpsilon*norm(a); - for(int j=0; j < m; ++j) + for(int j=0; j < m; ++j) { + real norm=0; + for(int i=0; i < n; ++i) + norm=max(norm,abs(a[i][j])); + real epsilon=sqrtEpsilon*norm; if(abs(a0[j]-a1[j]) > epsilon) return false; + } return true; } bool vperiodic(real[][] a) { int n=a.length; if(n == 0) return false; int m=a[0].length-1; - real epsilon=sqrtEpsilon*norm(a); - for(int i=0; i < n; ++i) - if(abs(a[i][0]-a[i][m]) > epsilon) return false; + for(int i=0; i < n; ++i) { + real[] ai=a[i]; + real epsilon=sqrtEpsilon*norm(ai); + if(abs(ai[0]-ai[m]) > epsilon) return false; + } return true; } diff --git a/Master/texmf-dist/asymptote/version.asy b/Master/texmf-dist/asymptote/version.asy index 1801d9842da..7cd9bd7a245 100644 --- a/Master/texmf-dist/asymptote/version.asy +++ b/Master/texmf-dist/asymptote/version.asy @@ -1 +1 @@ -string VERSION="2.35"; +string VERSION="2.37"; |