home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / krcls012.zip / KrClass / source / krcstran.cpp < prev    next >
Text File  |  1997-02-14  |  11KB  |  506 lines

  1. // Kroni's Classes: Objekte für Zeichnen im mathematischen Koordinatensystem
  2. // (c) 1997 Wolfgang Kronberg
  3. // file: krcstran.cpp
  4.  
  5.  
  6. #include "krcstran.hpp"
  7. #include "krtrace.hpp"
  8.  
  9. #define INCL_WINWINDOWMGR                        // WinWindowFromDC ()
  10. #include <os2.h>
  11.  
  12. #include <math.h>                                // log ()
  13.  
  14. #include <igrafctx.hpp>                          // IGraphicContext
  15. #include <ithread.hpp>                           // IThread
  16.  
  17.  
  18.  
  19. KrRectangle::KrRectangle (KrPoint p1, KrPoint p2)
  20. {
  21. if (p1.x < p2.x)
  22.    {
  23.    dLeft = p1.x;
  24.    dRight = p2.x;
  25.    }
  26. else
  27.    {
  28.    dLeft = p2.x;
  29.    dRight = p1.x;
  30.    }
  31.  
  32. if (p1.y < p2.y)
  33.    {
  34.    dBottom = p1.y;
  35.    dTop = p2.y;
  36.    }
  37. else
  38.    {
  39.    dBottom = p2.y;
  40.    dTop = p1.y;
  41.    }
  42. };
  43.  
  44.  
  45. void KrRectangle::setLeft (double d)
  46. {
  47. if (d<dRight)
  48.    dLeft = d;
  49. else
  50.    {
  51.    dLeft = dRight;
  52.    dRight = d;
  53.    }
  54. };
  55.  
  56.  
  57. void KrRectangle::setRight (double d)
  58. {
  59. if (d>dLeft)
  60.    dRight = d;
  61. else
  62.    {
  63.    dRight = dLeft;
  64.    dLeft = d;
  65.    }
  66. };
  67.  
  68.  
  69. void KrRectangle::setTop (double d)
  70. {
  71. if (d>dBottom)
  72.    dTop = d;
  73. else
  74.    {
  75.    dTop = dBottom;
  76.    dBottom = d;
  77.    }
  78. };
  79.  
  80.  
  81. void KrRectangle::setBottom (double d)
  82. {
  83. if (d<dTop)
  84.    dBottom = d;
  85. else
  86.    {
  87.    dBottom = dTop;
  88.    dTop = d;
  89.    }
  90. };
  91.  
  92.  
  93.  
  94. KrCoordSystemTranslator::KrCoordSystemTranslator (const KrPoint & p1, const KrPoint & p2)
  95. {
  96.   if ((p1.x==p2.x) || (p1.y==p2.y))
  97.      _KRSYSTHROW (IInvalidParameter("Neither width nor height may be zero"));
  98.  
  99.   if (p1.x<p2.x)
  100.      {
  101.      cMin.x = p1.x;
  102.      cMax.x = p2.x;
  103.      }
  104.   else
  105.      {
  106.      cMin.x = p2.x;
  107.      cMax.x = p1.x;
  108.      };
  109.  
  110.   if (p1.y<p2.y)
  111.      {
  112.      cMin.y = p1.y;
  113.      cMax.y = p2.y;
  114.      }
  115.   else
  116.      {
  117.      cMin.y = p2.y;
  118.      cMax.y = p1.y;
  119.      };
  120.  
  121.   pMin = IPoint (0,0);
  122.   pMax = IPoint (100,100);
  123.   pAspectRatio = 1;
  124.   align = KrAlignment ();
  125.  
  126.   xLog = yLog = FALSE;
  127.  
  128.   fMin = cMin; fMax = cMax;
  129.   frameList = new _KrFrameList ();
  130.  
  131.   setAspectRatio ();
  132.   setDeviceAspectRatio ();
  133.  
  134.   setStretches ();
  135. };
  136.  
  137.  
  138. void KrCoordSystemTranslator::setStretches ()
  139. {
  140.  
  141.   double deltaPH, deltaC, orgC, a;
  142.  
  143.   deltaPH = (pMax.x() - pMin.x()) / (hMax.x - hMin.x);
  144.  
  145.   if (xLog)
  146.      {
  147.      if (cMin.x<=0)
  148.         _KRSYSTHROW (IInvalidRequest("Can't use nonpositive logarithmic scale on x axis"));
  149.      orgC = log (cMin.x);
  150.      deltaC = log (cMax.x) - orgC;
  151.      }
  152.   else
  153.      {
  154.      orgC = cMin.x;
  155.      deltaC = cMax.x - orgC;
  156.      };
  157.  
  158.   xStretch = (fMax.x - fMin.x) * deltaPH / deltaC;
  159.   xOrg = pMin.x() + (fMin.x - hMin.x) * deltaPH - orgC * xStretch;
  160.  
  161.   deltaPH = (pMax.y() - pMin.y()) / (hMax.y - hMin.y);
  162.  
  163.   if (yLog)
  164.      {
  165.      if (cMin.y<=0)
  166.         _KRSYSTHROW (IInvalidRequest("Can't use nonpositive logarithmic scale on y axis"));
  167.      orgC = log (cMin.y);
  168.      deltaC = log (cMax.y) - orgC;
  169.      }
  170.   else
  171.      {
  172.      orgC = cMin.y;
  173.      deltaC = cMax.y - orgC;
  174.      };
  175.  
  176.   yStretch = (fMax.y - fMin.y) * deltaPH / deltaC;
  177.   yOrg = pMin.y() + (fMin.y - hMin.y) * deltaPH - orgC * yStretch;
  178.  
  179. };
  180.  
  181.  
  182. void KrCoordSystemTranslator::setDeviceAspectRatio (double ar)
  183. {
  184.   if (ar<0)
  185.      _KRSYSTHROW (IInvalidParameter("Aspect ratio must not be negative."));
  186.  
  187.   if (ar)
  188.      {
  189.      pAspectRatio = ar;
  190.      iFixedPAspectRatio = TRUE;
  191.      }
  192.   else
  193.      iFixedPAspectRatio = FALSE;
  194. };
  195.  
  196.  
  197. double KrCoordSystemTranslator::deviceAspectRatio ()
  198. {
  199.   return pAspectRatio;
  200. };
  201.  
  202.  
  203. Boolean KrCoordSystemTranslator::isFixedDeviceAspectRatio ()
  204. {
  205.   return iFixedPAspectRatio;
  206. };
  207.  
  208.  
  209. void KrCoordSystemTranslator::assign (const IGraphicContext & graphicContext)
  210. {
  211.   HPS hps = graphicContext.handle();             // Get the presentation space handle
  212.   HDC hdc = GpiQueryDevice (hps);                // Get the device context associated to the graphic context
  213.   HWND hwnd = WinWindowFromDC (hdc);             // Handle to the window associated with the device context
  214.  
  215.   if (hwnd)                                      // Does such a window exist?
  216.      {
  217.      RECTL rect;                                 // Yes: use its size
  218.      WinQueryWindowRect (hwnd, &rect);
  219.      pMax = IPoint (rect.xRight-rect.xLeft,rect.yTop-rect.yBottom);
  220.      pMin = IPoint (0,0);                        // Currently, we don't support anything else
  221.      }
  222.   else                                           // No: use the general page size
  223.      {
  224.      ISize size = graphicContext.pageSize ();
  225.      pMax = IPoint (size.width(), size.height());
  226.      pMin = IPoint (0,0);                        // Currently, we don't support anything else
  227.      };
  228.  
  229.   if (!iFixedPAspectRatio)                       // If we don't overrule automatic aspect ratio detection
  230.      {
  231.      LONG data[2];                               // We need two words of data for DevQueryCaps
  232.      BOOL rc;                                    // Return code of DevQueryCaps
  233.  
  234.      rc = DevQueryCaps (
  235.             hdc,                                 // Always needed for this kind of API call
  236.             CAPS_HORIZONTAL_RESOLUTION,          // The first element of interest
  237.             2,                                   // We need CAPS_HORIZONTAL_RESOLUTION and the next element
  238.             data                                 // Data array
  239.           );
  240.      if (!rc)
  241.         _KRSYSTHROW (IDeviceError("DevQueryCaps failed"));
  242.  
  243.      pAspectRatio = double(data[0])/double(data[1]);
  244.                                                  // Horizontal / vertical resolution
  245.      }
  246.  
  247.   setAspectRatio (logicalARatio);
  248.   setStretches();
  249. };
  250.  
  251.  
  252. IPoint & KrCoordSystemTranslator::translate (const KrPoint p) const
  253. {
  254.   IPair::Coord x,y;
  255.  
  256.   if (xLog)
  257.      x = log(p.x)*xStretch+xOrg;
  258.   else
  259.      x = p.x*xStretch+xOrg;
  260.  
  261.   if (yLog)
  262.      y = log(p.y)*yStretch+yOrg;
  263.   else
  264.      y = p.y*yStretch+yOrg;
  265.  
  266.   return *(new IPoint (x,y));
  267. };
  268.  
  269.  
  270. IRectangle & KrCoordSystemTranslator::translate (const KrRectangle p) const
  271. {
  272.   KrPoint lu = KrPoint (p.left(),p.bottom());
  273.   KrPoint rt = KrPoint (p.right(),p.top());
  274.   return *(new IRectangle (translate(lu),translate(rt)));
  275. };
  276.  
  277.  
  278. void KrCoordSystemTranslator::setAspectRatio (double ar)
  279. {
  280.   if (ar<0)
  281.      _KRSYSTHROW (IInvalidParameter("Aspect ratio must not be negative."));
  282.  
  283.   hMin = cMin; hMax = cMax;
  284.   double tAr = (cMax.x-cMin.x)/(cMax.y-cMin.y) * (pMax.y()-pMin.y())/(pMax.x()-pMin.x()) / pAspectRatio;
  285.  
  286.   if (ar==0)
  287.      {
  288.      aRatio = tAr;
  289.      logicalARatio = 0;
  290.      iFixedAspectRatio = FALSE;
  291.      }
  292.   else
  293.      {
  294.      aRatio = ar;
  295.      logicalARatio = ar;
  296.      iFixedAspectRatio = TRUE;
  297.      if (ar>tAr)
  298.         {
  299.         double cLen = cMax.x-cMin.x;
  300.         double hLen = cLen * ar/tAr;
  301.         switch (align.horizontal())
  302.            {
  303.            case KrAlignment::left:
  304.               hMax.x = hMin.x + hLen;
  305.               break;
  306.            case KrAlignment::right:
  307.               hMin.x = hMax.x - hLen;
  308.               break;
  309.            case KrAlignment::center:
  310.               double mid = cMin.x + cLen/2;
  311.               hMin.x = mid - hLen/2;
  312.               hMax.x = mid + hLen/2;
  313.               break;
  314.            };
  315.         }
  316.      else
  317.         {
  318.         double cLen = cMax.y-cMin.y;
  319.         double hLen = cLen * tAr/ar;
  320.         switch (align.vertical())
  321.            {
  322.            case KrAlignment::bottom:
  323.               hMax.y = hMin.y + hLen;
  324.               break;
  325.            case KrAlignment::top:
  326.               hMin.y = hMax.y - hLen;
  327.               break;
  328.            case KrAlignment::center:
  329.               double mid = cMin.y + cLen/2;
  330.               hMin.y = mid - hLen/2;
  331.               hMax.y = mid + hLen/2;
  332.               break;
  333.            };
  334.         };
  335.      };
  336. };
  337.  
  338.  
  339. void KrCoordSystemTranslator::setAlignment (const KrAlignment & alignment)
  340. {
  341.   align = alignment;
  342.   if (iFixedAspectRatio)
  343.      {
  344.      setAspectRatio (logicalARatio);
  345.      setStretches ();
  346.      };
  347. };
  348.  
  349.  
  350. KrAlignment & KrCoordSystemTranslator::alignment ()
  351. {
  352.   return align;
  353. };
  354.  
  355.  
  356. double KrCoordSystemTranslator::aspectRatio ()
  357. {
  358.   return aRatio;
  359. };
  360.  
  361.  
  362. Boolean KrCoordSystemTranslator::isFixedAspectRatio ()
  363. {
  364.   return iFixedAspectRatio;
  365. };
  366.  
  367.  
  368. void KrCoordSystemTranslator::addFrame (const KrPoint & p, double scale)
  369. {
  370.   _KrFrameList * list = frameList;
  371.   while (list->next)
  372.      list = list->next;
  373.   list->fMin = fMin;
  374.   list->fMax = fMax;
  375.   list->next = new _KrFrameList ();
  376.  
  377.   KrPoint p2;
  378.   p2.x = p.x + scale*(cMax.x-cMin.x);
  379.   p2.y = p.y + scale*(cMax.y-cMin.y);
  380.  
  381.   double z = (list->fMax.x-list->fMin.x)/(cMax.x-cMin.x);
  382.   fMin.x = (p.x-cMin.x)*z+list->fMin.x;
  383.   fMax.x = (p2.x-cMin.x)*z+list->fMin.x;
  384.   z = (list->fMax.y-list->fMin.y)/(cMax.y-cMin.y);
  385.   fMin.y = (p.y-cMin.y)*z+list->fMin.y;
  386.   fMax.y = (p2.y-cMin.y)*z+list->fMin.y;
  387.  
  388.   setStretches ();
  389. };
  390.  
  391.  
  392. void KrCoordSystemTranslator::removeFrame ()
  393. {
  394.   if (frameList->next)
  395.      {
  396.      _KrFrameList * l1 = frameList;
  397.      _KrFrameList * l2 = frameList->next;
  398.      while (l2->next)
  399.         {
  400.         l1 = l2;
  401.         l2 = l2->next;
  402.         };
  403.      delete l2;
  404.      l1->next = NULL;
  405.      fMin = l1->fMin;
  406.      fMax = l1->fMax;
  407.      }
  408.   else
  409.      _KRSYSTHROW (IInvalidRequest("No more frame present."));
  410. };
  411.  
  412.  
  413.  
  414. KrGraphicList::KrGraphicList (KrCoordSystemTranslator & trans)
  415.   : IGList ()
  416. {
  417.   translator = &trans;
  418. };
  419.  
  420.  
  421. KrGraphicList & KrGraphicList::drawOn (IGraphicContext & graphicContext)
  422. {
  423.   translator->assign (graphicContext);
  424.  
  425.   IGList::drawOn (graphicContext);
  426.   return (*this);
  427. };
  428.  
  429.  
  430.  
  431. KrAlignment::KrAlignment (int h, int v)
  432. {
  433.   setHorizontal (h);
  434.   setVertical (v);
  435. };
  436.  
  437.  
  438. void KrAlignment::setHorizontal (int h)
  439. {
  440.   switch (h)
  441.      {
  442.      case right:
  443.      case left:
  444.      case center:
  445.         horiz = h;
  446.         break;
  447.      default:
  448.         _KRSYSTHROW (IInvalidParameter("This is no alignment type."));
  449.         break;
  450.      };
  451. };
  452.  
  453.  
  454. void KrAlignment::setVertical (int v)
  455. {
  456.   switch (v)
  457.      {
  458.      case top:
  459.      case bottom:
  460.      case center:
  461.         vert = v;
  462.         break;
  463.      default:
  464.         _KRSYSTHROW (IInvalidParameter("This is no alignment type."));
  465.         break;
  466.      };
  467. };
  468.  
  469.  
  470. int KrAlignment::horizontal ()
  471. {
  472.   return horiz;
  473. };
  474.  
  475.  
  476. int KrAlignment::vertical ()
  477. {
  478.   return vert;
  479. };
  480.  
  481.  
  482.  
  483. KrDrawingCanvas::KrDrawingCanvas (unsigned long windowIdentifier, IWindow *parent, IWindow *owner,
  484.                    const IRectangle & initial, const Style style)
  485.   : IDrawingCanvas (windowIdentifier, parent, owner, initial, style)
  486. {
  487.   SIZEL size = {0,0};
  488.   HDC hdc = WinOpenWindowDC (handle());
  489.   HPS hps = GpiCreatePS (IThread::current().anchorBlock(), hdc, &size, PU_PELS | GPIT_MICRO | GPIA_ASSOC);
  490.   ip = new IPresSpaceHandle (hps);
  491.   dc = new IGraphicContext (*ip);
  492.   oldGraphicContext = graphicContext ();
  493.   setGraphicContext (dc);
  494. };
  495.  
  496.  
  497. KrDrawingCanvas::~KrDrawingCanvas ()
  498. {
  499.   setGraphicContext (oldGraphicContext);
  500.   GpiDestroyPS (*ip);
  501.   delete dc;
  502.   delete ip;
  503. };
  504.  
  505.  
  506.