// Abstract base class for guides.
class guide : public gc {
protected:
public:
virtual ~guide() {}
// Returns the path that the guide represents.
virtual path solve() {
return path();
}
// Add the information in the guide to the flatguide, so that it can be
// solved via the knotlist solving routines.
// Returns true if guide has an interior cycle token.
virtual void flatten(flatguide&, bool allowsolve=true)=0;
virtual bool cyclic() {return false;}
virtual void print(ostream& out) const {
out << "nullpath";
}
// Needed so that multiguide can know where to put in ".." symbols.
virtual side printLocation() const {
return END;
}
// Draws dots between two printings of guides, if their locations are such that
// the dots are necessary.
inline void adjustLocation(ostream& out, side l1, side l2)
{
if (l1 == END)
out << endl;
if ((l1 == END || l1 == OUT) && (l2 == IN || l2 == END))
out << "..";
}
// A guide representing a pair.
class pairguide : public guide {
pair z;
// Tension expressions are evaluated to this class before being cast to a guide,
// so that they can be cast to other types (such as guide3) instead.
class tensionSpecifier : public gc {
double out,in;
bool atleast;
// Similar to tensionSpecifier, curl expression are evaluated to this type
// before being cast to guides.
class curlSpecifier : public gc {
double value;
side s;
public:
curlSpecifier(double value, side s)
: value(value), s(s) {}
// A guide for explicit control points between two knots. This could be done
// with two specguides, instead, but this prints nicer, and is easier to encode.
class controlguide : public guide {
pair zout, zin;
// A guide that is a sequence of other guides. This is used, for instance is
// joins, where we have the left and right guide, and possibly specifiers and
// tensions in between.
typedef mem::vector<guide *> guidevector;
// A multiguide represents a guide given by the first "length" items of
// the vector pointed to by "base".
// The constructor, if given another multiguide as a first argument,
// will try to avoid allocating a new "base" array.
class multiguide : public guide {
guidevector *base;
size_t length;
if (settings::verbose>3)
cerr << "solved as:\n" << p << "\n\n";
return p;
}
void print(ostream& out) const;
side printLocation() const {
int n = length;
return subguide(n-1)->printLocation();
}
};
struct cycleToken : public gc {};
// A guide representing the cycle token.
class cycletokguide : public guide {
public:
void flatten(flatguide& g, bool allowsolve=true) {
// If cycles occur in the midst of a guide, the guide up to that point
// should be solved as a path. Any subsequent guide will work with that
// path locked in place.
if(allowsolve)
g.solve(true);
else
g.close();
}
bool cyclic() {return true;}
path solve() {
// Just a cycle on it's own makes an empty guide.
return path();
}
void print(ostream& out) const {
out << "cycle";
}