#!/usr/bin/env python # -*- coding: iso-8859-15 -*- #-------------------------------python------------------------pykig.py--# # # # Da Python a Kig # # # #--Maurizio Paolini-Daniele Zambelli-----------------------------2005---# # # (licenza GPL) version="0.2.11" ##### # Type constant ##### TI=type(0) TF=type(0.) TS=type("") TT=type((0, 0)) ##### # Constants: Point Style, Line Style, defaults values... ##### PS=("Round", "RoundEmpty", "Rectangular", "RectangularEmpty", "Cross") LS=("SolidLine", "DashLine", "DashDotLine", "DashDotDotLine", "DotLine") KIGTRUE="true" KIGFALSE="false" DEFWIDTH=-1 DEFCOLOR="#0000ff" DEFNAME="none" PROPERTY_INI="Property which" OBJECT_INI="Object type" PROPERTY_END="Property" OBJECT_END="Object" DICT=(("&","&"), ("<","<"), (">",">"), ("à","à"), ("è","è"), ("ì","ì"), ("ò","ò"), ("ù","ù"), ("é","é")) # # this is a trick to allow definitions like "p=Point(0,0,HIDDEN)" # HIDDEN=KIGFALSE VISIBLE=KIGTRUE ##### # Validation parameters ##### def parameter(val, defval): if val==None: return defval else: return val def validshown(shown): if shown==KIGTRUE or shown==KIGFALSE: return shown def validwidth(width): if type(width)==TI: return width def validpointstyle(ps): if ps in PS: return ps def validname(name): if type(name)==TS: return name def validlinestyle(ls): if ls in LS: return ls def validcolor(color): if type(color)==TS: return color ##### # if as function ##### def rif(condition, val1, val2): """Return val1 if condition is True else return val2.""" if condition: return val1 else: return val2 ##### # Force some Python variables as kig variables ##### def kig_double(val): tp=type(val) if tp==TI or tp==TF: return Double(val) else: return val def kig_int(val): tp=type(val) if tp==TI: return Int(val) else: return val def kig_string(val): tp=type(val) if tp==TS: return String(val) else: return val def kig_point(val): tp=type(val) if tp==TT: x, y = val return Point(x, y, internal=True) else: return val def kig_relpoint(obj, displ): x, y = displ return RelativePoint(x, y, obj, internal=True) ##### # base classes ##### ##### # Classe KigDocument ##### class KigDocument(object): """ Classe che produce il documento kig. genealogia: KigDocument <- object attributi di classe: attributi: axes grid outfilename outfile callkig of viewkig hierarchy internal width pointstyle name linestyle shown color metodi: viewappend hierarchyappend setcallkig setof str_open close noaxes nogrid hideobjects showobjects setwidth setpointstyle setname setlinestyle setshown setcolor setinternal """ def __init__(self, outfilename, callkig=True, of=False): # print "KigDocument.__init__()" self.axes = "1" self.grid = "1" self.outfilename=outfilename self.callkig=callkig self.of=of try: self.outfile = open(outfilename, 'w') except IOError, value: # print >> sys.stderr, outfilename, 'unwritable' print >> sys.stderr, value sys.exit(2) # KigOut._kigdocument=self KigDOP._kd=self KigView._kd=self self.viewkig=[] self.hierarchy=[] # Defaults values self.internal=False self.width=DEFWIDTH self.pointstyle=PS[0] self.name=DEFNAME self.linestyle=LS[0] self.shown=VISIBLE self.color=DEFCOLOR def viewappend(self, e): self.viewkig.append(e) def hierarchyappend(self, e): self.hierarchy.append(e) def setcallkig(v): self.callkig=v def setof(v): self.of=v def str_open(self): return """ Euclidean """ % (self.axes, self.grid) def close(self): try: self.outfile.write(self.str_open()) self.outfile.writelines(self.hierarchy) self.outfile.write(" \n \n") for f in self.viewkig: self.outfile.write(f.str_view()) self.outfile.write(" \n\n") if self.outfile != sys.stdout: self.outfile.close() except IOError, value: print >> sys.stderr, value sys.exit(2) try: if self.callkig: err = os.system('kig --nofork ' + self.outfilename) except Exception, value: print >> sys.stderr, value if not self.of: os.system('rm ' + self.outfilename) def noaxes(self): self.axes="0" def nogrid(self): self.grid="0" def hideobjects(self): self.shown=HIDDEN def showobjects(self): self.shown=VISIBLE def setwidth(self, w): self.width=w def setpointstyle(self, ps): self.pointstyle=ps def setname(self, n): self.name=n def setlinestyle(self, ls): self.linestyle=ls def setshown(self, s): self.shown=s def setcolor(self, c): self.color=c def setinternal(self, v): self.internal=v ##### # Classe KigDOP ##### #class KigDOP(KigOut): class KigDOP(object): """Classe da cui deriva ogni elemento che ha un id: Data, Object, Property. genealogia: kigDOP <- object attributo di classe: id-counter attributi: id type metodi: getid str_hierarchy """ _kd=None _id_counter=0 def __init__(self, type): KigDOP._id_counter+=1 self.id=KigDOP._id_counter self._type=type # self.getkigdocument().hierarchyappend(self.str_hierarchy()) KigDOP._kd.hierarchyappend(self.str_hierarchy()) def getid(self): return str(self.id) def str_hierarchy(self): pass ##### # Classe KigView ##### #class KigView(KigOut): class KigView(object): """ Classe con i dati di visualizzazione genealogia: KigView <- object attributi di classe: _kd attributi: shown width style color name pointstyle metodi: str_view show hide """ _kd=None def __init__(self, object, shown, name, width, pointstyle, linestyle, color): self.object=object self.shown = parameter(shown, KigView._kd.shown) self.width = parameter(width, KigView._kd.width) self.pointstyle = parameter(pointstyle, KigView._kd.pointstyle) self.linestyle = parameter(linestyle, KigView._kd.linestyle) self.color = parameter(color, KigView._kd.color) self.name = parameter(name, KigView._kd.name) KigView._kd.viewappend(self) def str_view(self): """Produce la stringa che viene scritta sotto . esempio: """ return ' \n' %\ (self.width, self.pointstyle, self.name, self.linestyle, self.shown, self.color, self.object.getid()) ##### # Classe Data ##### class Data(KigDOP): """ Classe da cui deriva ogni elemento Data genealogia: Data <- KigDOP <- object attributi: val metodi: str_hierarchy """ def __init__(self, type, val): self.val=val KigDOP.__init__(self, type) def str_hierarchy(self): """Produce la stringa che viene scritta sotto . esempio: 0.1 """ return ' %s\n' % \ (self._type, self.getid(), self.val) ##### # Classe PropObj ##### class PropObj(KigDOP): """ Classe da cui deriva ogni elemento visibile genealogia: PropObj <- KigDOP <- object attributi di classe: attributi: prop objvec view metodi: str_hierarchy showname(self, n) show(self) hide(self) setwidth(self, width) setcolor(self, color) setlinestyle(self, linestyle) setpointstyle(self, pointstyle) setname(self, n) setshown(self, s) getwidth(self) getcolor(self) getlinestyle(self) getpointstyle(self) """ def __init__(self, prop, type, objvec, shown, name, internal, width, pointstyle, linestyle, color): self.prop=prop self.objvec=objvec self.n_lb=None KigDOP.__init__(self, type) internal=parameter(internal, KigDOP._kd.internal) if internal: self.view = None else: # Qui si assume che, se viene dato un nome ad un oggetto, # si voglia anche visualizzare questo nome if name: n_id=self.showname(name, shown, width, pointstyle, linestyle, color) else: n_id=None self.view = KigView(self, shown, n_id, width, pointstyle, linestyle, color) def str_hierarchy(self): """Produce la stringa che viene scritta sotto . esempio: oppure: """ retstring = ' <%s="%s" id="%s" >' %\ ((self.prop and PROPERTY_INI or OBJECT_INI), self._type, self.getid()) for p in self.objvec: retstring = retstring + '\n ' % p.getid() retstring = retstring + '\n \n' % (self.prop and PROPERTY_END or OBJECT_END) return retstring def showname(self, name, shown, width, pointstyle, linestyle, color): n=String(name) self.n_lb=Label(self, (0, 0), n, 0, shown, None, False, width, pointstyle, linestyle, color) return n.getid() def show(self): if self.view: self.view.shown=None def hide(self): if self.view: self.view.shown=KIGFALSE def setwidth(self, width): self.view.width=width def setcolor(self, color): self.view.color=color def setlinestyle(self, linestyle): if linestyle in LS: self.view.linestyle=linestyle def setpointstyle(self, pointstyle): if pointstyle in PS: self.view.pointstyle=pointstyle def type(self): return Type(self) def setname(self, n): v=self.view v.name=self.showname(n, v.shown, v.width, v.pointstyle, v.linestyle, v.color) def setshown(self, s): self.view.shown=s ##### # Classe Property ##### class Property(PropObj): """ Classe da cui deriva ogni elemento Property genealogia: Property <- PropObj <- KigDOP <- object """ def __init__(self, type, parent, shown, name, internal, width, pointstyle, linestyle, color): PropObj.__init__(self, True, type, (parent,), shown, name, internal, width, pointstyle, linestyle, color) # print shown ##### # Classe Object ##### class Object(PropObj): """ Classe da cui deriva ogni elemento Oggetto genealogia: Object <- PropObj <- KigDOP <- object """ def __init__(self, type, objvec, shown, name, internal, width, pointstyle, linestyle, color): PropObj.__init__(self, False, type, objvec, shown, name, internal, width, pointstyle, linestyle, color) ##### # Data ##### data=(\ ("Int", "int", "val"), ("Double", "double", "val"), ("String", "string", "convstr(val)"), ) def convstr(s): for o, n in DICT: s=s.replace(o, n) return s def databuild(nomeclasse, nomekig, v="val"): """Create string with a Data class definition.""" return """class %s(Data): def __init__(self, val): Data.__init__(self, "%s", %s) """ % (nomeclasse, nomekig, v) for d in data: p1, p2, p3 = d exec databuild(p1, p2, p3) ##### # Objects ##### """Da aggiungere: ("ConvexHall", "ConvexHall", "polygon,", "(polygon,),"), ("EllipseByFocusFocusPoint", "EllipseBFFP", "p1, p2, p3,", "(p1, p2, p3,),"), ("HyperbolaByFocusFocusPoint", "HyperbolaBFFP", "p1, p2, p3,", "(p1, p2, p3,),"), (ConicsBy5Points", "ConicB5P", "p1, p2, p3, p4, p5,", "(p1, p2, p3, p4, p5),"), ("ParabolaBy3Points", "ParabolaBTP", "p1, p2, p3,", "(p1, p2, p3,),"), ("CocCurve", "CocCurve", "line, point,", "(line, point,),"), """ objects=(\ ###### Points class ("Point", "FixedPoint", "x, y,", "(kig_double(x), kig_double(y)),"), ("ConstrainedPoint", "ConstrainedPoint", "t, curve,", "(kig_double(t), curve),"), ("RelativePoint", "RelativePoint", "x, y, p,", "(kig_double(x), kig_double(y), p),"), ###### segments, rays, lines ("Line", "LineAB", "p1, p2,", "(p1, p2),"), ("Segment", "SegmentAB", "p1, p2,", "(p1, p2),"), ("Ray", "RayAB", "p1, p2,", "(p1, p2),"), ("Orthogonal", "LinePerpend", "line, point,", "(line, point,),"), ("Parallel", "LineParallel", "line, point,", "(line, point,),"), ###### Circles, arcs, ... ("Circle", "CircleBCP", "center, point,", "(center, point,),"), ("CircleByCenterRadius", "CircleBPR", "center, radius,", "(center, radius,),"), ("CircleBy3Points", "CircleBTP", "p1, p2, p3,", "(p1, p2, p3,),"), ("ArcBy3Points", "ArcBTP", "p1, p2, p3,", "(p1, p2, p3,),"), ("ArcByCenterPointAngle", "ArcBCPA", "center, point, angle,", "(center, point, angle),"), ###### Conics... ("ParabolaByDirectrixFocus", "ParabolaBDP", "line, point,", "(line, point,),"), ("VerticalCubic", "VerticalCubicB4P", "p1, p2, p3, p4,", "(p1, p2, p3, p4),"), ("ConicArc", "ConicArcBTPC", "p1, p2, p3, center,", "(p1, p2, p3, center),"), ##### # intersections. The only standard object is the intersection # of two lines, which always gives one single point ##### ("LineLineIntersection", "LineLineIntersection", "l1, l2,", "(l1, l2),"), ##### # Classe CircleCircleIntersection e ConicLineIntersection # l'intero "which" puo' assumere i valori 1 o -1 per indicare quale # delle due intersezioni si desidera ottenere # si potrebbe mettere un controllo... ##### ("CircleCircleIntersection", "CircleCircleIntersection", "c1, c2, witch,", "(c1, c2, Int(witch),),"), ("ConicLineIntersection", "ConicLineIntersection", "conic, line, witch,", "(conic, line, Int(witch),),"), ###### Classe Triangle ("Triangle", "TriangleB3P", "p1, p2, p3,", "(p1, p2, p3),"), ###### Classe Polygon (the only argument is a points vect) ("Polygon", "PolygonBNP", "pvec,", "pvec,"), ###### Classe PolygonBCV # Poligono regolare dati il centro e un vertice; il terzo argomento # e' un intero contenente il numero di lati ("PolygonBCV", "PoligonBCV", "center, vertex, n,", "(center, vertex, Int(n)),"), ##### Classe PolygonVertex (poligono, intero >= 0) ("PolygonVertex", "PolygonVertex", "polygon, i,", "(polygon, Int(i)),"), ##### Classe PolygonSide (poligono, intero >= 0) ("PolygonSide", "PolygonSide", "polygon, i,", "(polygon, Int(i)),"), ###### vector, angle,... ("Vector", "Vector", "p1, p2,", "(p1, p2),"), ("Angle", "Angle", "p1, v, p2,", "(p1, v, p2),"), ###### Transformations ("Translate", "Translation", "obj, vector,", "(obj, vector),"), ("CentralSymmetry", "PointReflection", "obj, center,", "(obj, center),"), ("AxialSymmetry", "LineReflection", "obj, center,", "(obj, center),"), ("Rotate", "Rotation", "obj, center, angle,", "(obj, center, angle),"), ("Scale", "ScalingOverCenter", "obj, center, segment,", "(obj, center, segment),"), ("Scale2", "ScalingOverCenter2", "obj, center, s1, s2,", "(obj, center, s1, s2),"), ("InvertPoint", "InvertPoint", "point, circle,", "(point, circle),"), ("CircularInversion", "CircularInversion", "objecttoinvert, circle,", "(objecttoinvert, circle),"), ("InvertLine", "InvertLine", "line, circle,", "(line, circle),"), ("InvertCircle", "InvertCircle", "circletoinvert, circle,", "(circletoinvert, circle),"), ("InvertArc", "InvertArc", "arctoinvert, circle,", "(arctoinvert, circle),"), ("InvertSegment", "InvertSegment", "segment, circle,", "(segment, circle),"), ###### Text, Label, ... ("Text", "Label", "point, string, boxed=0,", "(Int(boxed), kig_point(point), kig_string(string)),"), ("Label", "Label", "obj, displ, string, boxed=0,", "(Int(boxed),kig_relpoint(obj, displ),kig_string(string)),"), ("VarText", "Label", "point, string, vars, boxed=0,", "(Int(boxed), kig_point(point), \ kig_string(string))+tuple(vars),"), ("VarLabel", "Label", "obj, displ, string, vars, boxed=0,", "(Int(boxed), kig_relpoint(obj, displ), \ kig_string(string))+tuple(vars),"), ###### Python scripting... we need some work here... ("PythonScript", "PythonExecuteType", "script, argvec,", '(Object("PythonCompileType", (kig_string(script),), shown,\ name, internal, width, pointstyle, linestyle,\ color),)+tuple(argvec),'), ) def objectbuild(nameclass, namekig, params, objparams): """Create string with a Object class definition.""" return """class %s(Object): def __init__(self, %s shown=None, name=None, internal=None, width=None, pointstyle=None, linestyle=None, color=None): Object.__init__(self, "%s", %s shown, name, internal, width, pointstyle, linestyle, color) """ % (nameclass, params, namekig, objparams) for o in objects: p1, p2, p3, p4 = o exec objectbuild(p1, p2, p3, p4) ##### # Propertys ##### property=(\ ("Type", "base-object-type", "o,", "o,"), ("Coordinate", "coordinate", "point,", "point,"), ("XCoord", "coordinate-x", "point,", "point,"), ("YCoord", "coordinate-y", "point,", "point,"), ("MidPoints", "mid-point", "a, b,", "Segment(a, b, internal=True),"), ("MidPoint", "mid-point", "segment,", "segment,"), ("EndPointA", "end-point-A", "segment,", "segment,"), ("EndPointB", "end-point-B", "segment,", "segment,"), ("Length", "length", "segment,", "segment,"), ("Equation", "equation", "segment,", "segment,"), ("Slope", "slope", "segment,", "segment,"), ("NumOfSides", "polygon-number-of-sides", "poly,", "poly,"), ("Perimeter", "polygon-perimeter", "poly,", "poly,"), ("Surface", "polygon-surface", "poly,", "poly,"), ("CenterOfMass", "polygon-center-of-mass", "poly,", "poly,"), ("WindingNumber", "polygon-winding-number", "poly,", "poly,"), ("Radius", "radius", "circle,", "circle,"), ("Center", "center", "circle,", "circle,"), ("Bisector", "angle-bisector", "angle,", "angle,"), ("Support", "support", "object,", "object,"), ) def propertybuild(nameclass, namekig, params, objparams): """Create string with a Property class definition.""" return """class %s(Property): def __init__(self, %s shown=None, name=None, internal=False, width=None, pointstyle=None, linestyle=None, color=None): Property.__init__(self, "%s", %s shown, name, internal, width, pointstyle, linestyle, color) """ % (nameclass, params, namekig, objparams) for p in property: p1, p2, p3, p4 = p exec propertybuild(p1, p2, p3, p4) ##### # Start of properties definitions as Object's metod ##### # da sistemare! points =(Point, ConstrainedPoint, RelativePoint, PolygonVertex) lines=(Segment, Ray, Vector, InvertLine) segments=(Segment, Vector, PolygonSide, InvertSegment) circles =(Circle, CircleBy3Points, CircularInversion, ArcBy3Points, ArcByCenterPointAngle, InvertCircle) polygons=(Polygon, PolygonBCV, Triangle) angles =(Angle,) supp = circles+lines methods=(\ ("coordinate", "coordinate", points), ("coordinate-x", "xcoord", points), ("coordinate-y", "ycoord", points), ("mid-point", "midpoint", segments), ("end-point-A", "endpointA", segments), ("end-point-B", "endpointB", segments), ("length", "length", segments), ("equation", "equation", lines), ("slope", "slope", lines), ("polygon-number-of-sides", "numofsides", polygons), ("polygon-perimeter", "perimeter", polygons), ("polygon-surface", "surface", polygons), ("polygon-center-of-mass", "centerofmass", polygons), ("polygon-winding-number", "windingnumber", polygons), ("center", "center", polygons), ("center", "center", circles), ("angle-bisector", "bisector", angles), ("support", "support", supp), ) def methodsbuild(namekig): """Create string with a method class definition.""" return """def method(self,shown=None, name=None, internal=False, width=None, pointstyle=None, linestyle=None, color=None): return Property("%s", self, shown, name, internal, width, pointstyle, linestyle, color) """ % (namekig, ) for p in methods: p1, p2, cl = p exec methodsbuild(p1) for c in cl: setattr(c, p2, method) ##### # Usage ##### def usage(codexit): print >> sys.stderr, """ usage: pykig.py [options...] file ... Options: -h, --help Show this text. -o --output output no call Kig -v, --version output version -n, --nokig no call Kig examples: $ pykig.py my_file.kpy $ pykig.py -o output_file.kig my_file.kpy $ ... """ sys.exit(codexit) ##### # Main body ##### import sys, traceback, os #from math import * # for user's programs import math # for user's programs import getopt import atexit def prog(): try: _opts, _args = getopt.getopt(sys.argv[1:], "hvno:",\ ["help", "version", "nokig", "output="]) except getopt.GetoptError: print "GetoptError" usage(2) _callKig=True _of=False for _opt, _arg in _opts: if _opt in ("-h", "--help"): usage(0) if _opt in ("-v", "--version"): print "version:", version sys.exit(0) if _opt in ("-n", "--nokig"): _callKig=False elif _opt in ("-o", "--output"): _outfilename=_arg _of=True _callKig=False # se c'è il file di output, non viene chiamato Kig if len(_args)==0: _infilename=raw_input("Nome del file di input: ") if not _infilename: print "No Input filename" usage(2) elif len(_args)==1: _infilename=_args[0] else: print "No infilename" usage(2) try: _infile = open(_infilename, 'r') except: print >> sys.stderr, _infilename, 'unreadable' sys.exit(2) if _of: if _outfilename=="-": _n, _e = os.path.splitext(_infilename) _outfilename=_n+'.kig' else: _outfilename="/tmp/pykig" + str(os.getpid()) + ".kig" global kigdocument kigdocument=KigDocument(_outfilename, _callKig, _of) kd=kigdocument try: execfile(_infilename, globals()) except: print >> sys.stderr, 'syntax error in', _infilename _info = sys.exc_info() # vorrei stampare il traceback... traceback.print_exc() sys.exit(3) kigdocument.close() if _infile != sys.stdin: _infile.close() def lib(): _outfilename="/tmp/pykig" + str(os.getpid()) + ".kig" global kigdocument kigdocument=KigDocument(_outfilename) kd=kigdocument atexit.register(kigdocument.close) if __name__ == "__main__": prog() else: lib()