home *** CD-ROM | disk | FTP | other *** search
- // ┌───────┐
- // ─────────>│ AVNER │
- // ─────────>│ BEN │──────> Software Engineering Method
- // └───────┘
- // 10 Dov-Hoz st. Tel-Aviv 63416 Israel tel. 972-3-221535
-
- // The Screen NAVigator, ver 1.10 April 1990
- // Copyright (c) 1989 by Avner Ben
- // Snav is not, and never was, free software.
- // for conditions for use refer to file "copyrigh.txt"
-
- // The Screen Navigator is an object-oriented device-independent
- // character-graphics driver package, written in the C++ language,
- // distributed in the form of C++ source code.
- // For further information refer to the documentation files.
-
- // The user may not omit this text, from the beginning of the file, to
- // the line of asterisks below.
-
- /***************************************************************************/
-
- // package nucleus part 4 - source code.
- // This file defines specific "shape" objects, inheriting the generic "shape"
- // defined in snav2. The shape object in snav differs from other
- // implementations using the same word, in being an abstract, defined by
- // directions of pen motion and sizes, independent of screen position.
- // defined are a "tracing" shape that initilizes automatically, given a
- // screen image to trace, and the archetypal regular shape "oblong".
- // For example of more specific regular shapes, refer to demo-3.
-
- // History:
- /////// snav v1.1
- // 13.3.90-7.3.90 avner ben:
-
- // * sperated from snav2 * debugged append_stroke of tracing * debugged
- // oblong constructor * added clear to oblong * used pendn feature of curve
- // instead of offset * fixed weight recording bug in first stroke * added
- // color recording *
-
- // Site history (of this copy):
- // __.__.__ ____________ : __________________.
-
- #ifndef SNAV3_C
- #define SNAV3_C
- #endif
-
- #include "snav2.hpp"
-
- /*********************** pattern recognition **************************/
-
- tracing :: ~tracing()
- {
- if (stmark) {
- landmark *next=stmark->next;
- for (; stmark; stmark=next) {
- next=stmark->next;
- delete stmark;
- }
- }
- }
-
- tracing :: tracing(panel *scr, point_pos *cursor) : shape(NULL,"trace"),
- start(*cursor)
- { // "probe constructor"
- /////////////// experimental code! //////////////
-
- stmark=NULL;
- point_pos pt(*cursor);
- // beginning and end of scan are complicated, in an attempt to
- // preserve arcs of length 1, to be lost in a "general" algorithm.
- intersection godir; if (!(scr->gowhere(&pt,&godir))()) return;
- intersection avdir=(alph->cdir(scr->get_c(&pt))); // disregrad neighbours
- direction dir=avdir.ask_first();
- if (!(godir>=~dir)) avdir-=~dir;
- (mark(&pt,&avdir))->proceed(&start,&avdir,&dir);
- landmark *mrk;
- point_pos offset(0,0);
- while (dir()) {
- if (offset.y() || offset.x()) {
- shape::append_stroke(offset);
- offset=point_pos(0,0);
- }
- mrk=append_stroke(scr,&pt,&dir);
- if (mrk) mrk->proceed(&start,&avdir,&dir);
- if (!dir()) { // finished first pass. reposition to pending intersection
- for (mrk=stmark; mrk; mrk=mrk->next)
- if (mrk->dirleft()) { // directions left unexplored here
- start=mrk->pos;
- offset=mrk->pos; offset-=pt;
- pt=mrk->pos;
- dir=nodir; avdir=mrk->dirleft;
- dir=avdir.ask_first();
- break;
- }
- }
- }
- // resolve missing axis_weight (in single-line shapes)
- for (stroke *sk=stsk; sk; sk=sk->get_next()) {
- weight_d wgt=sk->ask_wgt();
- if (wgt() && !(wgt.y() && wgt.x())) {
- if (!wgt.y()) wgt.replace(hdim,wgt.x());
- if (!wgt.x()) wgt.replace(vdim,wgt.y());
- sk->set_wgt(wgt);
- }
- }
- }
-
- landmark * tracing :: append_stroke(panel *scr, point_pos *cursor, direction *curdir)
- { // phase in "probe constructor" - read next arc
- ///////////// experimental code! ////////////
-
- char c=scr->get_c(cursor); if (c==' ') return NULL;
- intersection avdir=alph->cdir(c);
- if (!(avdir>=*curdir)) return NULL; // double-tipped not supported
- if (avdir.unary()) return NULL; // double-tipped not supported
- color_ind clr=scr->get_color(cursor);
- clr.normalize();
- stroke *sk=new stroke(1,*curdir,alph->cweight(c),FALSE,&clr,TRUE);
- landmark *mrk;
- for (mrk=NULL; !mrk;) { // stop when we get to junction - let caller decide
- for (mrk=stmark; mrk; mrk=mrk->next)
- if (mrk->pos==*cursor) break;
- if (mrk) { // dejavue
- if (sk->ask_len()>1)
- mrk->dirleft-=~(*curdir); // ain't coming back
- avdir=mrk->dirleft;
- if (mrk->dirleft>=*curdir) {
- mrk->dirleft-=*curdir;
- mrk=NULL; // passing through
- }
- } else if (!avdir.unary()) // unmarked branch
- if (avdir>=*curdir) { // mark and proceed
- avdir-=*curdir;
- mark(cursor,&avdir);
- avdir+=*curdir;
- } else mrk=mark(cursor,&avdir); // can't decide
- if (!alph->ccont(scr->get_c(cursor),
- scr->next_c(curdir,cursor),*curdir)
- || (scr->get_color(cursor)).ask_for_clr()!=clr.forgnd)
- { // end of arc
- mrk=mark(cursor,&avdir);
- if ((scr->gowhere(cursor,&(intersection)alldirs)).unary())
- start=*cursor; // end of scan phase
- } else { // get next
- cursor->move(*curdir); sk->expand();
- avdir=alph->cdir(scr->get_c(cursor));
- avdir-=~(*curdir); // ain't coming back
- }
- }
- if ((alph->cdir(scr->get_c(cursor))).unary()) // tipped
- sk->toggle_tip();
- shape::append_stroke(sk);
- return mrk;
- }
-
- landmark :: landmark(point_pos *pt, intersection *avdir)
- : pos(*pt), dirstart(*avdir), dirleft(*avdir)
- { next=NULL; }
-
- void landmark :: proceed(point_pos *start, intersection *avdir, direction *curdir)
- { // solve amiguity. more than one path open from point.
-
-
- if (*start!=pos) dirleft-=~(*curdir);
- if (dirleft())
- if (dirleft>=*curdir) ; // continue
- else *curdir=dirleft.ask_first(); // turn
- else *curdir=nodir; // end of the road
- *avdir=dirleft;
- }
-
- landmark * tracing :: mark(point_pos *cursor, intersection *avdir)
- { // add cursor to intesections-left-to-explore list
-
- landmark *mrk;
- if (!stmark)
- mrk=stmark=new landmark(cursor,avdir);
- else {
- for (mrk=stmark; mrk->next; mrk=mrk->next)
- if (mrk->pos==*cursor) break; // we've been here
- if (mrk->pos!=*cursor) // append
- mrk=mrk->next=new landmark(cursor,avdir);
- }
- return(mrk);
- }
-
- /*********************** sample regular shape **************************/
-
- oblong :: oblong(int inwd, int inhgt, const weight_d &inwgt)
- : shape(NULL,"oblong"), wd(inwd), hgt(inhgt), wgt(inwgt)
- {
- // allocate two sides - the rest is for the lister
- direction dir;
- append_stroke(new stroke(wd,dir,wgt)); dir.clockwise();
- append_stroke(new stroke(hgt,dir,wgt));
- }
-
- void oblong :: list(panel *scr, point_pos *pt0)
- {
- point_pos pt=*pt0;
- for (int i=1; i<=2; i++) {
- shape::list(scr,&pt,FALSE);
- stsk->invert();
- stroke *t=stsk->get_next(); t->invert();
- }
- }
-
- void oblong :: clear(panel *scr, point_pos *pt0)
- {
- point_pos pt=*pt0;
- for (int i=1; i<=2; i++) {
- shape::clear(scr,&pt,FALSE);
- stsk->invert();
- stroke *t=stsk->get_next(); t->invert();
- }
- }
-
-