Esempio n. 1
0
/*! Add a single layout object shape into the quadTree. 
It first checks whether or not another layout object is already placed into this
quadTree. If not it simply links the shape and exits. If another object is already
here, then the new overlap area is calculated. \n In case the new area is the same as 
the existing one, then the object might be (possibly) fited into one of the childrens 
quadTree. To check this fitintree() method is called. If this is unsuccessfull, just 
then the layout object is linked to this quadTree. \n If the new overlapping area is 
bigger that the existing one, then the layout object is linked to the current quadTree 
after what the current quadTree as well as its successors has to be rebuild using 
resort().\n The method might be called recursively via fitintree() method.
*/
void laydata::quadTree::add(tdtdata* shape) {
   DBbox shovl = shape->overlap();shovl.normalize();
   if (empty()) {
   // first shape in the container
      _overlap = shovl;
      _first = shape;shape->nextis(NULL);
   }
   else {
      // save the old overlap
      DBbox oldovl = _overlap;
      // calculate the new container overlap
      _overlap.overlap(shovl);
      float areaold = oldovl.area();
      float areanew = _overlap.area();
// The equation below produce problems with severe consequences.
// It seems to be because of the type of the conversion
//      if (oldovl.area() == _overlap->area()) {
      if (areaold == areanew) {
         // if the overlapping box hasn't changed,
         // try to fit the shape into subtree
         if ((areanew <= 4 * shovl.area()) || !fitintree(shape)) {
            // shape doesn't fit into the subtree, so place it here
            shape->nextis(_first); _first = shape;
         }
      }
      else { // the overlapping box has had blown-up
         shape->nextis(_first); _first = shape;
         resort(); // re-sort the entire tree
      }   
   }
}
Esempio n. 2
0
/*! Build a new quadTree structure for the tdtdata in the inlist. The method is
using the existing _overlap variable. For every layout shape fitinsubtree()
method is called in a try to put the data in the child quadTree. At the end
the method is called for every of the child structures.
*/
void laydata::quadTree::sort(dataList& inlist)
{
   // if the input list is empty - nothing to do!
   if (0 == inlist.size()) return;
   dataList::iterator DI = inlist.begin();
   // if the list contains only one component - link it and run away
   if (1 == inlist.size())
   {
      DI->first->nextis(NULL); _first = DI->first;
      return;
   }
   byte i;
   // the overlapping box of the currnet shape 
//   DBbox shovl(TP(0,0));
   DBbox shovl = DEFAULT_OVL_BOX;
   // the maximum possible overlapping boxes of the 4 children
   DBbox maxsubbox[4] = {DEFAULT_OVL_BOX, DEFAULT_OVL_BOX, 
                         DEFAULT_OVL_BOX, DEFAULT_OVL_BOX};
   for (i = 0; i < 4; i++) maxsubbox[i] = _overlap.getcorner(i);
   // the sub-lists data will be sorted in
   dataList sublist[4];
   // which is the child where current shape fits 
   int fitinsubbox;
   // initialize the iterator
   float sharea, totalarea = _overlap.area();
   while (inlist.end() != DI)
   {
      // get the overlap of the current shape
      shovl = DI->first->overlap();shovl.normalize();
      sharea = shovl.area();
      // Check it fits in some of the children
      if (totalarea <= 4 * sharea || 
                        (-1 == (fitinsubbox = fitsubtree(shovl, maxsubbox))))
      {
         // no fit. The shape is sorted in the current tree
         DI->first->nextis(_first); _first = DI->first;
      }
      else
      {
         // fits in sub-tree fitinsubbox
         sublist[fitinsubbox].push_back(*DI);
         // check this child already exists
         if (_quads[fitinsubbox])  // yes ?
            _quads[fitinsubbox]->_overlap.overlap(shovl);
         else
         {
            // create the child, initialize the overlapping box
            _quads[fitinsubbox] = DEBUG_NEW quadTree();
            _quads[fitinsubbox]->_overlap = shovl;
         }
      }
      // in all cases get rid of the current shape pointer. It is already sorted
      DI = inlist.erase(DI);
   }
   // at this point inlist MUST be empty - split over max 4+this quadTrees
   // now go and sort the children - if any
   for(i = 0; i < 4; i++)
      if (_quads[i]) _quads[i]->sort(sublist[i]);

}
Esempio n. 3
0
/*! A temporary Draw (during move/copy operations) of the container contents
 on the screen using the virtual quadTree::tmp_draw() method of the 
 parent object. */
void laydata::tdtlayer::tmp_draw(const layprop::DrawProperties& drawprop,
                                                 ctmqueue& transtack) const {
   // check the entire layer for clipping...
   DBbox clip = drawprop.clipRegion();
   if (empty()) return;
   DBbox areal = overlap() * transtack.front();
   areal.normalize();
   if (clip.cliparea(areal) == 0) return;
   else {
      areal = areal * drawprop.ScrCTM();
      if (areal.area() < MIN_VISUAL_AREA) return;
   }   
   quadTree::tmp_draw(drawprop, transtack);
}
Esempio n. 4
0
/*! Temporary draw of the container contents on the screen using the virtual 
tmp_draw methods of the tdtddata objects. This happens only if 
the current quadTree object is visible. Current clip region data is
obtained from LayoutCanvas. In a sence this method is the same as openGL_draw
without fill and not handling selected shapes*/
void laydata::quadTree::tmp_draw(const layprop::DrawProperties& drawprop,
                                                   ctmqueue& transtack) const {
   if (empty()) return;
   // check the entire holder for clipping...
   DBbox clip = drawprop.clipRegion();   
   DBbox areal = _overlap * transtack.front(); 
   areal.normalize();
   if (clip.cliparea(areal) == 0) return;
   else {
      areal = areal * drawprop.ScrCTM();
      if (areal.area() < MIN_VISUAL_AREA) return;
   }   
   tdtdata* wdt = _first;
   while(wdt) {
      wdt->tmp_draw(drawprop, transtack);
      wdt = wdt->next();
   }
   for(byte i = 0; i < 4; i++) 
      if (_quads[i]) _quads[i]->tmp_draw(drawprop, transtack);
}
Esempio n. 5
0
/*! Draw the contents of the container on the screen using the virtual 
openGL_draw methods of the tdtddata objects. This happens only if 
the current quadTree object is visible. Current clip region data is
obtained from LayoutCanvas. Draws also the select marks in case shape is
selected. \n This is the cherry of the quadTree algorithm cake*/
void laydata::quadTree::openGL_draw(ctmstack& transtack, const layprop::DrawProperties& drawprop,
                                                   const dataList* slst) const {
   if (empty()) return;
   // check the entire holder for clipping...
   DBbox clip = drawprop.clipRegion();
   DBbox areal = _overlap * transtack.top(); 
   areal.normalize();
   if (clip.cliparea(areal) == 0) return;
   else {
      areal = areal * drawprop.ScrCTM();
      if (areal.area() < MIN_VISUAL_AREA) return;
//      std::cout << "  ... with area " << areal.area() << "\n";
   }
   tdtdata* wdt = _first;
   // The drawing will be faster like this for the cells without selected shapes
   // that will be the wast majority of the cases. A bit bigger code though.
   // Seems the bargain is worth it.
   if (slst)
      while(wdt) {
         wdt->openGL_draw(transtack,drawprop);
         // in case the shape is somehow selected...
         if       (sh_selected == wdt->status()) wdt->draw_select(transtack.top());
         else if  (sh_partsel == wdt->status()) {
            dataList::const_iterator SI;
            for (SI = slst->begin(); SI != slst->end(); SI++)
               if (SI->first == wdt) break;
            assert(SI != slst->end());
            wdt->draw_select(transtack.top(), SI->second);
         }   
         wdt = wdt->next();
      }
   else
      // if there are no selected shapes
      while(wdt) {
         wdt->openGL_draw(transtack,drawprop);
         wdt = wdt->next();
      }
   for(byte i = 0; i < 4; i++) 
      if (_quads[i]) _quads[i]->openGL_draw(transtack, drawprop, slst);
}
Esempio n. 6
0
/*! Draw the contents of the container on the screen using the virtual 
openGL_draw methods of the tdtddata objects. This happens only if 
the current quadTree object is visible. Current clip region data is
obtained from LayoutCanvas. Draws also the select marks in case shape is
selected. \n This is the cherry of the quadTree algorithm cake*/
void laydata::quadTree::openGL_draw(layprop::DrawProperties& drawprop,
                                                   const dataList* slst, bool fill, bool bound) const {
   if (empty()) return;
   // check the entire holder for clipping...
   DBbox clip = drawprop.clipRegion();
   DBbox areal = _overlap * drawprop.topCTM(); 
   areal.normalize();
   if (clip.cliparea(areal) == 0) return;
   else {
      areal = areal * drawprop.ScrCTM();
      if (areal.area() < MIN_VISUAL_AREA) return;
//      std::cout << "  ... with area " << areal.area() << "\n";
   }
   tdtdata* wdt = _first;
//   bool fill = drawprop.getCurrentFill();
   // The drawing will be faster like this for the cells without selected shapes
   // that will be the wast majority of the cases. A bit bigger code though.
   // Seems the bargain is worth it.
   if (slst)
   {
      while(wdt)
      {
         pointlist points;
         // precalculate drawing data
         wdt->openGL_precalc(drawprop, points);
         if (0 != points.size())
         {
            // draw the shape fill (contents of refs, arefs and texts)
            if (fill)  wdt->openGL_drawfill(drawprop, points);
            // draw the outline of the shapes and overlapping boxes 
            if (bound) wdt->openGL_drawline(drawprop, points);
            if ((sh_selected == wdt->status()) || (sh_partsel == wdt->status()))
            {
               drawprop.setLineProps(true);
               if       (sh_selected == wdt->status())
                  wdt->openGL_drawsel(points, NULL);
               else if  (sh_partsel  == wdt->status())
               {
                  dataList::const_iterator SI;
                  for (SI = slst->begin(); SI != slst->end(); SI++)
                     if (SI->first == wdt) break;
                  assert(SI != slst->end());
                  wdt->openGL_drawsel(points, SI->second);
               }
               drawprop.setLineProps(false);
            }
            wdt->openGL_postclean(drawprop, points);
         }
         wdt = wdt->next();
      }
   }
   else
   {
      // if there are no selected shapes
      while(wdt)
      {
         pointlist points;
         // precalculate drawing data
         wdt->openGL_precalc(drawprop, points);
         // draw the shape fill (contents of refs, arefs and texts)
         if (fill)  wdt->openGL_drawfill(drawprop, points);
         // draw the outline of the shapes and overlapping boxes
         if (bound) wdt->openGL_drawline(drawprop, points);
         // clean-up
         wdt->openGL_postclean(drawprop, points);
         wdt = wdt->next();
      }
   }
   
/*   // The drawing will be faster like this for the cells without selected shapes
   // that will be the wast majority of the cases. A bit bigger code though.
   // Seems the bargain is worth it.
   if (slst)
      while(wdt) {
         wdt->openGL_draw(drawprop);
         // in case the shape is somehow selected...
         if       (sh_selected == wdt->status()) wdt->draw_select(drawprop.topCTM());
         else if  (sh_partsel == wdt->status()) {
            dataList::const_iterator SI;
            for (SI = slst->begin(); SI != slst->end(); SI++)
               if (SI->first == wdt) break;
            assert(SI != slst->end());
            wdt->draw_select(drawprop.topCTM(), SI->second);
         }   
         wdt = wdt->next();
      }
   else
      // if there are no selected shapes
      while(wdt) {
         wdt->openGL_draw(drawprop);
         wdt = wdt->next();
      }*/
   for(byte i = 0; i < 4; i++) 
      if (_quads[i]) _quads[i]->openGL_draw(drawprop, slst, fill, bound);
}