"Fossies" - the Fresh Open Source Software Archive

Member "asymptote-2.60/drawelement.h" (6 Nov 2019, 11741 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 "drawelement.h" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.58_vs_2.59.

    1 /*****
    2  * drawelement.h
    3  * Andy Hammerlindl 2002/06/06
    4  *
    5  * Abstract base class of any drawable item in camp.
    6  *****/
    7 
    8 #ifndef DRAWELEMENT_H
    9 #define DRAWELEMENT_H
   10 
   11 #include <vector>
   12 
   13 #include "common.h"
   14 #include "bbox.h"
   15 #include "bbox3.h"
   16 #include "pen.h"
   17 #include "psfile.h"
   18 #include "texfile.h"
   19 #include "prcfile.h"
   20 #include "jsfile.h"
   21 #include "glrender.h"
   22 #include "arrayop.h"
   23 #include "material.h"
   24 
   25 namespace camp {
   26 
   27 static const double pixel=1.0; // Adaptive rendering constant.
   28 
   29 // Return one-sixth of the second derivative of the Bezier curve defined
   30 // by a,b,c,d at 0. 
   31 inline triple bezierPP(triple a, triple b, triple c) {
   32   return a+c-2.0*b;
   33 }
   34 
   35 // Return one-third of the third derivative of the Bezier curve defined by
   36 // a,b,c,d at 0.
   37 inline triple bezierPPP(triple a, triple b, triple c, triple d) {
   38   return d-a+3.0*(b-c);
   39 }
   40 
   41 enum Interaction {EMBEDDED=0,BILLBOARD};
   42 
   43 void copyArray4x4C(double*& dest, const vm::array *a);
   44   
   45 class box {
   46   pair p[4];
   47 public:
   48   
   49   box() {}
   50   box(const pair& a, const pair& b, const pair& c, const pair& d) {
   51     p[0]=a; p[1]=b; p[2]=c; p[3]=d;
   52   }
   53   
   54 // Returns true if the line a--b intersects box b.
   55   bool intersect(const pair& a, const pair& b) const
   56   {
   57     for(Int i=0; i < 4; ++i) {
   58       pair A=p[i];
   59       pair B=p[i < 3 ? i+1 : 0];
   60       double de=(b.x-a.x)*(A.y-B.y)-(A.x-B.x)*(b.y-a.y);
   61       if(de != 0.0) {
   62         de=1.0/de;
   63         double t=((A.x-a.x)*(A.y-B.y)-(A.x-B.x)*(A.y-a.y))*de;
   64         double T=((b.x-a.x)*(A.y-a.y)-(A.x-a.x)*(b.y-a.y))*de;
   65         if(0 <= t && t <= 1 && 0 <= T && T <= 1) return true;
   66       }
   67     }
   68     return false;
   69   }
   70   
   71   pair operator [] (Int i) const {return p[i];}
   72   
   73   bool intersect(const box& b) const {
   74     for(Int i=0; i < 4; ++i) {
   75       pair A=b[i];
   76       pair B=b[i < 3 ? i+1 : 0];
   77       if(intersect(A,B)) return true;
   78     }
   79     return false;
   80   }
   81   
   82   double xmax() {
   83     return max(max(max(p[0].x,p[1].x),p[2].x),p[3].x);
   84   }
   85   
   86   double ymax() {
   87     return max(max(max(p[0].y,p[1].y),p[2].y),p[3].y);
   88   }
   89   
   90   double xmin() {
   91     return min(min(min(p[0].x,p[1].x),p[2].x),p[3].x);
   92   }
   93   
   94   double ymin() {
   95     return min(min(min(p[0].y,p[1].y),p[2].y),p[3].y);
   96   }
   97   
   98 };
   99   
  100 class bbox2 {
  101 public:
  102   double x,y,X,Y;
  103   bbox2(size_t n, const triple *v) {
  104     Bounds(v[0]);
  105     for(size_t i=1; i < n; ++i)
  106       bounds(v[i]);
  107   }
  108     
  109   bbox2(const triple& m, const triple& M) {
  110     Bounds(m);
  111     bounds(triple(m.getx(),m.gety(),M.getz()));
  112     bounds(triple(m.getx(),M.gety(),m.getz()));
  113     bounds(triple(m.getx(),M.gety(),M.getz()));
  114     bounds(triple(M.getx(),m.gety(),m.getz()));
  115     bounds(triple(M.getx(),m.gety(),M.getz()));
  116     bounds(triple(M.getx(),M.gety(),m.getz()));
  117     bounds(M);
  118   }
  119     
  120   bbox2(const triple& m, const triple& M, const Billboard& BB) {
  121     Bounds(BB.transform(m));
  122     bounds(BB.transform(triple(m.getx(),m.gety(),M.getz())));
  123     bounds(BB.transform(triple(m.getx(),M.gety(),m.getz())));
  124     bounds(BB.transform(triple(m.getx(),M.gety(),M.getz())));
  125     bounds(BB.transform(triple(M.getx(),m.gety(),m.getz())));
  126     bounds(BB.transform(triple(M.getx(),m.gety(),M.getz())));
  127     bounds(BB.transform(triple(M.getx(),M.gety(),m.getz())));
  128     bounds(BB.transform(M));
  129   }
  130     
  131 // Is 2D bounding box formed by projecting 3d points in vector v offscreen?
  132   bool offscreen() {
  133     double eps=1.0e-2;
  134     double min=-1.0-eps;
  135     double max=1.0+eps;
  136     return X < min || x > max || Y < min || y > max;
  137   }
  138     
  139   void Bounds(const triple& v) {
  140     pair V=Transform2T(gl::dprojView,v);
  141     x=X=V.getx();
  142     y=Y=V.gety();
  143   }
  144   
  145   void bounds(const triple& v) {
  146     pair V=Transform2T(gl::dprojView,v);
  147     double a=V.getx();
  148     double b=V.gety();
  149     if(a < x) x=a;
  150     else if(a > X) X=a;
  151     if(b < y) y=b;
  152     else if(b > Y) Y=b;
  153   }
  154 };
  155 
  156 typedef mem::vector<box> boxvector;
  157   
  158 typedef mem::list<bbox> bboxlist;
  159   
  160 typedef mem::map<CONST string,unsigned> groupmap;
  161 typedef mem::vector<groupmap> groupsmap;
  162 
  163 class drawElement : public gc
  164 {
  165 public:
  166   string KEY;
  167   
  168   drawElement(const string& key="") : KEY(key == "" ? processData().KEY : key)
  169                                       {}
  170   
  171   virtual ~drawElement() {}
  172   
  173   static mem::vector<triple> center;
  174   static size_t centerIndex;
  175   static triple lastcenter;
  176   static size_t lastcenterIndex;
  177   
  178   static pen lastpen;  
  179   static const triple zero;
  180   
  181   // Adjust the bbox of the picture based on the addition of this
  182   // element. The iopipestream is needed for determining label sizes.
  183   virtual void bounds(bbox&, iopipestream&, boxvector&, bboxlist&) {}
  184   virtual void bounds(const double*, bbox3&) {}
  185   virtual void bounds(bbox3& b) { bounds(NULL, b); }
  186 
  187   // Compute bounds on ratio (x,y)/z for 3d picture (not cached).
  188   virtual void ratio(const double *t, pair &b, double (*m)(double, double),
  189                      double fuzz, bool &first) {}
  190   
  191   virtual void minratio(const double *t, pair &b, double fuzz, bool &first) {
  192     ratio(t,b,camp::min,fuzz,first);
  193   }
  194   
  195   virtual void maxratio(const double *t,pair &b, double fuzz, bool &first) {
  196     ratio(t,b,camp::max,fuzz,first);
  197   }
  198   
  199   virtual void ratio(pair &b, double (*m)(double, double), double fuzz,
  200                      bool &first) {
  201     ratio(NULL,b,m,fuzz,first);
  202   }
  203 
  204   virtual void minratio(pair &b, double fuzz, bool &first) {
  205     minratio(NULL,b,fuzz,first);
  206   }
  207 
  208   virtual void maxratio(pair &b, double fuzz, bool &first) {
  209     maxratio(NULL,b,fuzz,first);
  210   }
  211 
  212   virtual bool islabel() {return false;}
  213 
  214   virtual bool isnewpage() {return false;}
  215   
  216   virtual bool islayer() {return false;}
  217 
  218   virtual bool is3D() {return false;}
  219 
  220 // Implement element as raw SVG code?
  221   virtual bool svg() {return false;}
  222   
  223 // Implement SVG element as png image?
  224   virtual bool svgpng() {return false;}
  225   
  226   virtual bool beginclip() {return false;}
  227   virtual bool endclip() {return false;}
  228   
  229   virtual bool begingroup() {return false;}
  230   virtual bool begingroup3() {return false;}
  231 
  232   virtual bool endgroup() {return false;}
  233   virtual bool endgroup3() {return false;}
  234 
  235   virtual const double* transf3() {return NULL;}
  236 
  237   virtual void save(bool b) {}
  238   
  239   // Output to a PostScript file
  240   virtual bool draw(psfile *) {
  241     return false;
  242   }
  243 
  244   // Output to a TeX file
  245   virtual bool write(texfile *, const bbox&) {
  246     return false;
  247   }
  248 
  249   // Output to a PRC file
  250   virtual bool write(prcfile *out, unsigned int *count, double compressionlimit,
  251                      groupsmap& groups) {
  252     return false;
  253   }
  254   
  255   // Output to a JS file
  256   virtual bool write(jsfile *out) {
  257     return false;
  258   }
  259   
  260   // Used to compute deviation of a surface from a quadrilateral.
  261   virtual void displacement() {}
  262 
  263   // Render with OpenGL
  264   virtual void render(double size2, const triple& Min, const triple& Max,
  265                       double perspective, bool remesh) 
  266   {}
  267 
  268   virtual void meshinit() {}
  269   
  270   size_t centerindex(const triple& center) {
  271     if(drawElement::center.empty() || center != drawElement::lastcenter) {
  272       drawElement::lastcenter=center;
  273       drawElement::center.push_back(center);
  274       drawElement::lastcenterIndex=drawElement::center.size();
  275     }
  276     return drawElement::lastcenterIndex;
  277   }
  278 
  279   // Transform as part of a picture.
  280   virtual drawElement *transformed(const transform&) {
  281     return this;
  282   }
  283   
  284   virtual drawElement *transformed(const double* t) {
  285     return this;
  286   }
  287 
  288 };
  289 
  290 // Hold transform of an object.
  291 class drawElementLC : public virtual drawElement {
  292 public:
  293   double *T; // Keep track of accumulative picture transform
  294   
  295   drawElementLC() : T(NULL) {}
  296   
  297   drawElementLC(const double *t) : T(NULL) {
  298     copyTransform3(T,t);
  299   }
  300 
  301   drawElementLC(const vm::array& t) : T(NULL) {
  302     copyArray4x4C(T,&t);
  303   }
  304 
  305   drawElementLC(const double* t, const drawElementLC *s) : 
  306     drawElement(s->KEY), T(NULL) {
  307     multiplyTransform3(T,t,s->T);
  308   }
  309 
  310   virtual ~drawElementLC() {}
  311 
  312   virtual bool is3D() {return true;}
  313 
  314   virtual const double* transf3() {return T;}
  315 
  316   virtual drawElement* transformed(const double* t) {
  317     return new drawElementLC(t,this);
  318   }
  319 };
  320 
  321 // Base class for drawElements that involve paths.
  322 class drawPathBase : public virtual drawElement {
  323 protected:
  324   path p;
  325 
  326   path transpath(const transform& t) const {
  327     return p.transformed(t);
  328   }
  329 
  330 public:
  331   drawPathBase() {}
  332   drawPathBase(path p) : p(p) {}
  333 
  334   virtual ~drawPathBase() {}
  335 
  336   virtual void bounds(bbox& b, iopipestream&, boxvector&, bboxlist&) {
  337     b += p.bounds();
  338   }
  339   
  340   virtual void writepath(psfile *out,bool) {
  341     out->write(p);
  342   }
  343   
  344   virtual void writeclippath(psfile *out, bool newpath=true) {
  345     out->writeclip(p,newpath);
  346   }
  347   
  348   virtual void writeshiftedpath(texfile *out) {
  349     out->writeshifted(p);
  350   }
  351 };     
  352 
  353 // Base class for drawElements that involve paths and pens.
  354 class drawPathPenBase : public drawPathBase {
  355 protected:
  356   pen pentype;
  357 
  358   pen transpen(const transform& t) const {
  359     return camp::transformed(shiftless(t),pentype);
  360   }
  361 
  362 public:
  363   drawPathPenBase(path p, pen pentype) : 
  364     drawPathBase(p), pentype(pentype) {}
  365   
  366   drawPathPenBase(pen pentype) :
  367     pentype(pentype) {}
  368   
  369   virtual bool empty() {
  370     return p.empty();
  371   }
  372   
  373   virtual bool cyclic() {
  374     return p.cyclic();
  375   }
  376   
  377   void strokebounds(bbox& b, const path& p);
  378     
  379   virtual void penSave(psfile *out)
  380   {
  381     if (!pentype.getTransform().isIdentity())
  382       out->gsave();
  383   }
  384   
  385   virtual void penTranslate(psfile *out)
  386   {
  387     out->translate(shiftpair(pentype.getTransform()));
  388   }
  389 
  390   virtual void penConcat(psfile *out)
  391   {
  392     out->concat(shiftless(pentype.getTransform()));
  393   }
  394 
  395   virtual void penRestore(psfile *out)
  396   {
  397     if (!pentype.getTransform().isIdentity())
  398       out->grestore();
  399   }
  400 };
  401   
  402 // Base class for drawElements that involve superpaths and pens.
  403 class drawSuperPathPenBase : public drawPathPenBase {
  404 protected:
  405   vm::array P;
  406   size_t size;
  407   bbox bpath;
  408 
  409   vm::array transpath(const transform& t) const {
  410     vm::array *Pt=new vm::array(size);
  411     for(size_t i=0; i < size; i++)
  412       (*Pt)[i]=vm::read<path>(P,i).transformed(t);
  413     return *Pt;
  414   }
  415   
  416 public:
  417   drawSuperPathPenBase(const vm::array& P, pen pentype) :
  418     drawPathPenBase(pentype), P(P), size(P.size()) {}
  419 
  420   bool empty() {
  421     for(size_t i=0; i < size; i++) 
  422       if(vm::read<path>(P,i).size() != 0) return false;
  423     return true;
  424   }
  425   
  426   bool cyclic() {
  427     for(size_t i=0; i < size; i++) 
  428       if(!vm::read<path>(P,i).cyclic()) return false;
  429     return true;
  430   }
  431   
  432   void bounds(bbox& b, iopipestream&, boxvector&, bboxlist&) {
  433     for(size_t i=0; i < size; i++)
  434       bpath += vm::read<path>(P,i).bounds();
  435     b += bpath;
  436   }
  437   
  438   void strokepath(psfile *out) {
  439     out->strokepath();
  440   }
  441   
  442   void strokebounds(bbox& b) {
  443     for(size_t i=0; i < size; i++)
  444       drawPathPenBase::strokebounds(bpath,vm::read<path>(P,i));
  445     b += bpath;
  446   }
  447   
  448   void writepath(psfile *out, bool newpath=true) {
  449     if(size > 0) out->write(vm::read<path>(P,0),newpath);
  450     for(size_t i=1; i < size; i++)
  451       out->write(vm::read<path>(P,i),false);
  452   }
  453   
  454   void writeclippath(psfile *out, bool newpath=true) {
  455     if(size > 0) out->writeclip(vm::read<path>(P,0),newpath);
  456     for(size_t i=1; i < size; i++)
  457       out->writeclip(vm::read<path>(P,i),false);
  458   }
  459   
  460   void writeshiftedpath(texfile *out) {
  461     for(size_t i=0; i < size; i++) 
  462       out->writeshifted(vm::read<path>(P,i),i == 0);
  463   }
  464 };
  465  
  466 #ifdef HAVE_LIBGLM
  467 void setcolors(bool colors,
  468                const prc::RGBAColour& diffuse,
  469                const prc::RGBAColour& emissive,
  470                const prc::RGBAColour& specular, double shininess,
  471                double metallic, double fresnel0, jsfile *out=NULL);
  472 #endif
  473 
  474   
  475 
  476 }
  477 
  478 GC_DECLARE_PTRFREE(camp::box);
  479 GC_DECLARE_PTRFREE(camp::drawElement);
  480 
  481 #endif