1*37da2899SCharles.Forsythimplement Readstrokes; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsyth# 4*37da2899SCharles.Forsyth# read structures from stroke classifier files 5*37da2899SCharles.Forsyth# 6*37da2899SCharles.Forsyth 7*37da2899SCharles.Forsythinclude "sys.m"; 8*37da2899SCharles.Forsyth sys: Sys; 9*37da2899SCharles.Forsyth 10*37da2899SCharles.Forsythinclude "bufio.m"; 11*37da2899SCharles.Forsyth bufio: Bufio; 12*37da2899SCharles.Forsyth Iobuf: import bufio; 13*37da2899SCharles.Forsyth 14*37da2899SCharles.Forsythinclude "strokes.m"; 15*37da2899SCharles.Forsyth strokes: Strokes; 16*37da2899SCharles.Forsyth Classifier, Penpoint, Stroke, Region: import strokes; 17*37da2899SCharles.Forsyth buildstrokes: Buildstrokes; 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsythinit(s: Strokes) 20*37da2899SCharles.Forsyth{ 21*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 22*37da2899SCharles.Forsyth bufio = load Bufio Bufio->PATH; 23*37da2899SCharles.Forsyth strokes = s; 24*37da2899SCharles.Forsyth} 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsythgetint(fp: ref Iobuf): (int, int) 27*37da2899SCharles.Forsyth{ 28*37da2899SCharles.Forsyth while((c := fp.getc()) == ' ' || c == '\t' || c == '\n') 29*37da2899SCharles.Forsyth ; 30*37da2899SCharles.Forsyth if(c < 0) 31*37da2899SCharles.Forsyth return (c, 0); 32*37da2899SCharles.Forsyth sign := 1; 33*37da2899SCharles.Forsyth if(c == '-') 34*37da2899SCharles.Forsyth sign = -1; 35*37da2899SCharles.Forsyth else if(c == '+') 36*37da2899SCharles.Forsyth ; 37*37da2899SCharles.Forsyth else 38*37da2899SCharles.Forsyth fp.ungetc(); 39*37da2899SCharles.Forsyth rc := 0; 40*37da2899SCharles.Forsyth n := 0; 41*37da2899SCharles.Forsyth while((c = fp.getc()) >= '0' && c <= '9'){ 42*37da2899SCharles.Forsyth n = n*10 + (c-'0'); 43*37da2899SCharles.Forsyth rc = 1; 44*37da2899SCharles.Forsyth } 45*37da2899SCharles.Forsyth return (rc, n*sign); 46*37da2899SCharles.Forsyth} 47*37da2899SCharles.Forsyth 48*37da2899SCharles.Forsythgetstr(fp: ref Iobuf): (int, string) 49*37da2899SCharles.Forsyth{ 50*37da2899SCharles.Forsyth while((c := fp.getc()) == ' ' || c == '\t' || c == '\n') 51*37da2899SCharles.Forsyth ; 52*37da2899SCharles.Forsyth if(c < 0) 53*37da2899SCharles.Forsyth return (c, nil); 54*37da2899SCharles.Forsyth fp.ungetc(); 55*37da2899SCharles.Forsyth s := ""; 56*37da2899SCharles.Forsyth while((c = fp.getc()) != ' ' && c != '\t' && c != '\n') 57*37da2899SCharles.Forsyth s[len s] = c; 58*37da2899SCharles.Forsyth return (0, s); 59*37da2899SCharles.Forsyth} 60*37da2899SCharles.Forsyth 61*37da2899SCharles.Forsythgetpoint(fp: ref Iobuf): (int, Penpoint) 62*37da2899SCharles.Forsyth{ 63*37da2899SCharles.Forsyth (okx, x) := getint(fp); 64*37da2899SCharles.Forsyth (oky, y) := getint(fp); 65*37da2899SCharles.Forsyth if(okx <= 0 || oky <= 0) 66*37da2899SCharles.Forsyth return (-1, (0,0,0)); 67*37da2899SCharles.Forsyth return (0, (x,y,0)); 68*37da2899SCharles.Forsyth} 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsythgetpoints(fp: ref Iobuf): ref Stroke 71*37da2899SCharles.Forsyth{ 72*37da2899SCharles.Forsyth (ok, npts) := getint(fp); 73*37da2899SCharles.Forsyth if(ok <= 0 || npts < 0 || npts > 4000) 74*37da2899SCharles.Forsyth return nil; 75*37da2899SCharles.Forsyth pts := array[npts] of Penpoint; 76*37da2899SCharles.Forsyth for(i := 0; i < npts; i++){ 77*37da2899SCharles.Forsyth (ok, pts[i]) = getpoint(fp); 78*37da2899SCharles.Forsyth if(ok < 0) 79*37da2899SCharles.Forsyth return nil; 80*37da2899SCharles.Forsyth } 81*37da2899SCharles.Forsyth return ref Stroke(npts, pts, 0, 0); 82*37da2899SCharles.Forsyth} 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsythread_classifier_points(fp: ref Iobuf, nclass: int): (int, array of string, array of list of ref Stroke) 85*37da2899SCharles.Forsyth{ 86*37da2899SCharles.Forsyth names := array[nclass] of string; 87*37da2899SCharles.Forsyth examples := array[nclass] of list of ref Stroke; 88*37da2899SCharles.Forsyth for(k := 0; k < nclass; k++){ 89*37da2899SCharles.Forsyth # read class name and number of examples 90*37da2899SCharles.Forsyth (ok, nex) := getint(fp); 91*37da2899SCharles.Forsyth if(ok <= 0) 92*37da2899SCharles.Forsyth return (-1, nil, nil); 93*37da2899SCharles.Forsyth (ok, names[k]) = getstr(fp); 94*37da2899SCharles.Forsyth if(ok < 0) 95*37da2899SCharles.Forsyth return (ok, nil, nil); 96*37da2899SCharles.Forsyth 97*37da2899SCharles.Forsyth # read examples 98*37da2899SCharles.Forsyth for(i := 0; i < nex; i++){ 99*37da2899SCharles.Forsyth pts := getpoints(fp); 100*37da2899SCharles.Forsyth if(pts == nil) 101*37da2899SCharles.Forsyth return (-1, nil, nil); 102*37da2899SCharles.Forsyth examples[k] = pts :: examples[k]; 103*37da2899SCharles.Forsyth } 104*37da2899SCharles.Forsyth } 105*37da2899SCharles.Forsyth return (0, names, examples); 106*37da2899SCharles.Forsyth} 107*37da2899SCharles.Forsyth 108*37da2899SCharles.Forsyth# 109*37da2899SCharles.Forsyth# read a classifier, using its digest if that exists 110*37da2899SCharles.Forsyth# 111*37da2899SCharles.Forsythread_classifier(file: string, build: int, needex: int): (string, ref Classifier) 112*37da2899SCharles.Forsyth{ 113*37da2899SCharles.Forsyth rc := ref Classifier; 114*37da2899SCharles.Forsyth l := len file; 115*37da2899SCharles.Forsyth digestfile: string; 116*37da2899SCharles.Forsyth if(l >= 4 && file[l-4:]==".clx") 117*37da2899SCharles.Forsyth digestfile = file; 118*37da2899SCharles.Forsyth else if(!needex && l >= 3 && file[l-3:]==".cl") 119*37da2899SCharles.Forsyth digestfile = file[0:l-3]+".clx"; # try the digest file first 120*37da2899SCharles.Forsyth err: string; 121*37da2899SCharles.Forsyth if(digestfile != nil){ 122*37da2899SCharles.Forsyth fd := sys->open(digestfile, Sys->OREAD); 123*37da2899SCharles.Forsyth if(fd != nil){ 124*37da2899SCharles.Forsyth (err, rc.cnames, rc.dompts) = read_digest(fd); 125*37da2899SCharles.Forsyth rc.nclasses = len rc.cnames; 126*37da2899SCharles.Forsyth if(rc.cnames == nil) 127*37da2899SCharles.Forsyth err = "empty digest file"; 128*37da2899SCharles.Forsyth if(err == nil) 129*37da2899SCharles.Forsyth return (nil, rc); 130*37da2899SCharles.Forsyth }else 131*37da2899SCharles.Forsyth err = sys->sprint("%r"); 132*37da2899SCharles.Forsyth if(!build) 133*37da2899SCharles.Forsyth return (sys->sprint("digest file: %s", err), nil); 134*37da2899SCharles.Forsyth } 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth if(buildstrokes == nil){ 137*37da2899SCharles.Forsyth buildstrokes = load Buildstrokes Buildstrokes->PATH; 138*37da2899SCharles.Forsyth if(buildstrokes == nil) 139*37da2899SCharles.Forsyth return (sys->sprint("module %s: %r", Buildstrokes->PATH), nil); 140*37da2899SCharles.Forsyth buildstrokes->init(strokes); 141*37da2899SCharles.Forsyth } 142*37da2899SCharles.Forsyth 143*37da2899SCharles.Forsyth fd := sys->open(file, Sys->OREAD); 144*37da2899SCharles.Forsyth if(fd == nil) 145*37da2899SCharles.Forsyth return (sys->sprint("%r"), nil); 146*37da2899SCharles.Forsyth (emsg, cnames, examples) := read_examples(fd); 147*37da2899SCharles.Forsyth if(emsg != nil) 148*37da2899SCharles.Forsyth return (emsg, nil); 149*37da2899SCharles.Forsyth rc.nclasses = len cnames; 150*37da2899SCharles.Forsyth (err, rc.canonex, rc.dompts) = buildstrokes->canonical_example(rc.nclasses, cnames, examples); 151*37da2899SCharles.Forsyth if(err != nil) 152*37da2899SCharles.Forsyth return ("failed to calculate canonical examples", nil); 153*37da2899SCharles.Forsyth rc.cnames = cnames; 154*37da2899SCharles.Forsyth if(needex) 155*37da2899SCharles.Forsyth rc.examples = examples; 156*37da2899SCharles.Forsyth 157*37da2899SCharles.Forsyth return (nil, rc); 158*37da2899SCharles.Forsyth} 159*37da2899SCharles.Forsyth 160*37da2899SCharles.Forsythread_examples(fd: ref Sys->FD): (string, array of string, array of list of ref Strokes->Stroke) 161*37da2899SCharles.Forsyth{ 162*37da2899SCharles.Forsyth fp := bufio->fopen(fd, Bufio->OREAD); 163*37da2899SCharles.Forsyth (ok, nclasses) := getint(fp); 164*37da2899SCharles.Forsyth if(ok <= 0) 165*37da2899SCharles.Forsyth return ("missing number of classes", nil, nil); 166*37da2899SCharles.Forsyth (okc, cnames, examples) := read_classifier_points(fp, nclasses); 167*37da2899SCharles.Forsyth if(okc < 0) 168*37da2899SCharles.Forsyth return ("couldn't read examples", nil, nil); 169*37da2899SCharles.Forsyth return (nil, cnames, examples); 170*37da2899SCharles.Forsyth} 171*37da2899SCharles.Forsyth 172*37da2899SCharles.Forsyth# 173*37da2899SCharles.Forsyth# attempt to read the digest of a classifier, 174*37da2899SCharles.Forsyth# and return its contents if successful; 175*37da2899SCharles.Forsyth# return a diagnostic if not 176*37da2899SCharles.Forsyth# 177*37da2899SCharles.Forsythread_digest(fd: ref Sys->FD): (string, array of string, array of ref Stroke) 178*37da2899SCharles.Forsyth{ 179*37da2899SCharles.Forsyth # Read-in the name and dominant points for each class. 180*37da2899SCharles.Forsyth fp := bufio->fopen(fd, Bufio->OREAD); 181*37da2899SCharles.Forsyth cnames := array[32] of string; 182*37da2899SCharles.Forsyth dompts := array[32] of ref Stroke; 183*37da2899SCharles.Forsyth for(nclasses := 0;; nclasses++){ 184*37da2899SCharles.Forsyth if(nclasses >= len cnames){ 185*37da2899SCharles.Forsyth a := array[nclasses+32] of string; 186*37da2899SCharles.Forsyth a[0:] = cnames; 187*37da2899SCharles.Forsyth cnames = a; 188*37da2899SCharles.Forsyth b := array[nclasses+32] of ref Stroke; 189*37da2899SCharles.Forsyth b[0:] = dompts; 190*37da2899SCharles.Forsyth dompts = b; 191*37da2899SCharles.Forsyth } 192*37da2899SCharles.Forsyth (okn, class) := getstr(fp); 193*37da2899SCharles.Forsyth if(okn == Bufio->EOF) 194*37da2899SCharles.Forsyth break; 195*37da2899SCharles.Forsyth if(class == nil) 196*37da2899SCharles.Forsyth return ("expected class name", nil, nil); 197*37da2899SCharles.Forsyth cnames[nclasses] = class; 198*37da2899SCharles.Forsyth dpts := getpoints(fp); 199*37da2899SCharles.Forsyth if(dpts == nil) 200*37da2899SCharles.Forsyth return ("bad points list", nil, nil); 201*37da2899SCharles.Forsyth strokes->compute_chain_code(dpts); 202*37da2899SCharles.Forsyth dompts[nclasses] = dpts; 203*37da2899SCharles.Forsyth } 204*37da2899SCharles.Forsyth return (nil, cnames[0:nclasses], dompts[0:nclasses]); 205*37da2899SCharles.Forsyth} 206