"Fossies" - the Fresh Open Source Software Archive

Member "asymptote-2.60/guide.h" (6 Nov 2019, 6783 Bytes) of package /linux/misc/asymptote-2.60.src.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "guide.h" see the Fossies "Dox" file reference documentation.

    1 /*****
    2  * guide.h
    3  * Andy Hammerlindl 2005/02/23
    4  *
    5  *****/
    6 
    7 #ifndef GUIDE_H
    8 #define GUIDE_H
    9 
   10 #include <iostream>
   11 #include "knot.h"
   12 #include "flatguide.h"
   13 #include "settings.h"
   14 
   15 namespace camp {
   16 
   17 // Abstract base class for guides.
   18 class guide : public gc {
   19 protected:
   20 public:
   21   virtual ~guide() {}
   22   
   23   // Returns the path that the guide represents.
   24   virtual path solve() {
   25     return path();
   26   }
   27 
   28   // Add the information in the guide to the flatguide, so that it can be
   29   // solved via the knotlist solving routines.
   30   // Returns true if guide has an interior cycle token. 
   31   virtual void flatten(flatguide&, bool allowsolve=true)=0;
   32   
   33   virtual bool cyclic() {return false;}
   34   
   35   virtual void print(ostream& out) const {
   36     out << "nullpath";
   37   }
   38   
   39   // Needed so that multiguide can know where to put in ".." symbols.
   40   virtual side printLocation() const {
   41     return END;
   42   }
   43   
   44 };
   45 
   46 inline ostream& operator<< (ostream& out, const guide& g)
   47 {
   48   g.print(out);
   49   return out;
   50 }
   51 
   52 // Draws dots between two printings of guides, if their locations are such that
   53 // the dots are necessary.
   54 inline void adjustLocation(ostream& out, side l1, side l2)
   55 {
   56   if (l1 == END)
   57     out << endl;
   58   if ((l1 == END || l1 == OUT) && (l2 == IN || l2 == END))
   59     out << "..";
   60 }
   61 
   62 // A guide representing a pair.
   63 class pairguide : public guide {
   64   pair z;
   65 
   66 public:
   67   void flatten(flatguide& g, bool=true) {
   68     g.add(z);
   69   }
   70 
   71   pairguide(pair z)
   72     : z(z) {}
   73 
   74   path solve() {
   75     return path(z);
   76   }
   77 
   78   void print(ostream& out) const {
   79     out << z;
   80   }
   81   
   82   side printLocation() const {
   83     return END;
   84   }
   85 };
   86 
   87 
   88 // A guide representing a path.
   89 class pathguide : public guide {
   90   path p;
   91 
   92 public:
   93   void flatten(flatguide& g, bool allowsolve=true) {
   94     g.add(p,allowsolve);
   95   }
   96 
   97   pathguide(path p)
   98     : p(p) {}
   99 
  100   path solve() {
  101     return p;
  102   }
  103 
  104   bool cyclic() {return p.cyclic();}
  105 
  106   void print(ostream& out) const {
  107     out << p;
  108   }
  109   
  110   side printLocation() const {
  111     return END;
  112   }
  113 };
  114 
  115 // Tension expressions are evaluated to this class before being cast to a guide,
  116 // so that they can be cast to other types (such as guide3) instead.
  117 class tensionSpecifier : public gc {
  118   double out,in;
  119   bool atleast;
  120 
  121 public:
  122   tensionSpecifier(double val, bool atleast=false)
  123     : out(val), in(val), atleast(atleast) {}
  124   tensionSpecifier(double out, double in, bool atleast=false)
  125     : out(out), in(in), atleast(atleast) {}
  126 
  127   double getOut() const { return out; }
  128   double getIn() const { return in; }
  129   bool getAtleast() const { return atleast; }
  130 };
  131 
  132 
  133 // A guide giving tension information (as part of a join).
  134 class tensionguide : public guide {
  135   tension tout,tin;
  136 
  137 public:
  138   void flatten(flatguide& g, bool=true) {
  139     g.setTension(tin,IN);
  140     g.setTension(tout,OUT);
  141   }
  142 
  143   tensionguide(tensionSpecifier spec)
  144     : tout(spec.getOut(), spec.getAtleast()),
  145       tin(spec.getIn(), spec.getAtleast()) {}
  146 
  147   void print(ostream& out) const {
  148     out << (tout.atleast ? ".. tension atleast " : ".. tension ")
  149         << tout.val << " and " << tin.val << " ..";
  150   }
  151   
  152   side printLocation() const {
  153     return JOIN;
  154   }
  155 };
  156 
  157 // Similar to tensionSpecifier, curl expression are evaluated to this type
  158 // before being cast to guides.
  159 class curlSpecifier : public gc {
  160   double value;
  161   side s;
  162 
  163 public:
  164   curlSpecifier(double value, side s)
  165     : value(value), s(s) {}
  166 
  167   double getValue() const { return value; }
  168   side getSide() const { return s; }
  169 };
  170 
  171 // A guide giving a specifier.
  172 class specguide : public guide {
  173   spec *p;
  174   side s;
  175 
  176 public:
  177   void flatten(flatguide& g, bool=true) {
  178     g.setSpec(p,s);
  179   }
  180   
  181   specguide(spec *p, side s)
  182     : p(p), s(s) {}
  183 
  184   specguide(curlSpecifier spec)
  185     : p(new curlSpec(spec.getValue())), s(spec.getSide()) {}
  186 
  187   void print(ostream& out) const {
  188     out << *p;
  189   }
  190   
  191   side printLocation() const {
  192     return s;
  193   }
  194 };
  195 
  196 // A guide for explicit control points between two knots.  This could be done
  197 // with two specguides, instead, but this prints nicer, and is easier to encode.
  198 class controlguide : public guide {
  199   pair zout, zin;
  200 
  201 public:
  202   void flatten(flatguide& g, bool=true) {
  203     g.setSpec(new controlSpec(zout), OUT);
  204     g.setSpec(new controlSpec(zin), IN);
  205   }
  206 
  207   controlguide(pair zout,pair zin)
  208     : zout(zout),zin(zin) {}
  209   controlguide(pair z)
  210     : zout(z),zin(z) {}
  211 
  212   void print(ostream& out) const {
  213     out << ".. controls "
  214         << zout << " and " << zin << " ..";
  215   }
  216   
  217   side printLocation() const {
  218     return JOIN;
  219   }
  220 };
  221 
  222 // A guide that is a sequence of other guides.  This is used, for instance is
  223 // joins, where we have the left and right guide, and possibly specifiers and
  224 // tensions in between.
  225 typedef mem::vector<guide *> guidevector;
  226 
  227 // A multiguide represents a guide given by the first "length" items of 
  228 // the vector pointed to by "base".
  229 // The constructor, if given another multiguide as a first argument,
  230 // will try to avoid allocating a new "base" array.
  231 class multiguide : public guide {
  232     guidevector *base;
  233     size_t length;
  234 
  235     guide *subguide(size_t i) const
  236     {
  237         assert(i < length);
  238         assert(length <= base->size());
  239         return (*base)[i];
  240     }
  241 
  242 public:
  243 
  244   multiguide(guidevector& v);
  245 
  246   void flatten(flatguide&, bool=true);
  247   
  248   bool cyclic() {
  249     size_t n=length;
  250     if(n < 1) return false;
  251     return subguide(n-1)->cyclic();
  252   }
  253   
  254   path solve() {
  255     if (settings::verbose>3) {
  256       cerr << "solving guide:\n";
  257       print(cerr); cerr << "\n\n";
  258     }
  259     
  260     flatguide g;
  261     this->flatten(g);
  262     path p=g.solve(false);
  263 
  264     if (settings::verbose>3)
  265       cerr << "solved as:\n" << p << "\n\n";
  266 
  267     return p;
  268   }
  269 
  270   void print(ostream& out) const;
  271   
  272   side printLocation() const {
  273     int n = length;
  274     return subguide(n-1)->printLocation();
  275   }
  276 };
  277 
  278 struct cycleToken : public gc {};
  279 
  280 // A guide representing the cycle token.
  281 class cycletokguide : public guide {
  282 public:
  283   void flatten(flatguide& g, bool allowsolve=true) {
  284     // If cycles occur in the midst of a guide, the guide up to that point
  285     // should be solved as a path.  Any subsequent guide will work with that
  286     // path locked in place.
  287     if(allowsolve)
  288       g.solve(true);
  289     else
  290       g.close();
  291   }
  292 
  293   bool cyclic() {return true;}
  294   
  295   path solve() {
  296     // Just a cycle on it's own makes an empty guide.
  297     return path();
  298   }
  299 
  300   void print(ostream& out) const {
  301     out << "cycle";
  302   }
  303 
  304   side printLocation() const {
  305     return END;
  306   }
  307 };
  308 
  309 } // namespace camp
  310 
  311 GC_DECLARE_PTRFREE(camp::pairguide);
  312 GC_DECLARE_PTRFREE(camp::tensionSpecifier);
  313 GC_DECLARE_PTRFREE(camp::tensionguide);
  314 GC_DECLARE_PTRFREE(camp::curlSpecifier);
  315 GC_DECLARE_PTRFREE(camp::controlguide);
  316 GC_DECLARE_PTRFREE(camp::cycleToken);
  317 GC_DECLARE_PTRFREE(camp::cycletokguide);
  318 
  319 #endif // GUIDE_H