Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/zb/polygon is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_zb_polygon
0005 #define tools_zb_polygon
0006 
0007 #include "edge_table"
0008 #include "../mnmx"
0009 
0010 namespace tools {
0011 namespace zb {
0012 
0013 class polygon {
0014 
0015   static const int NUMPTSTOBUFFER = 200;
0016 
0017   typedef struct _POINTBLOCK {
0018       point pts[NUMPTSTOBUFFER];
0019       struct _POINTBLOCK* next;
0020   } POINTBLOCK;
0021 
0022   int             m_pETEn;
0023   EdgeTableEntry* m_pETEs;
0024   int             m_numAllocPtBlocks;
0025   POINTBLOCK      m_FirstPtBlock;
0026 public:
0027   polygon():m_pETEn(0),m_pETEs(NULL),m_numAllocPtBlocks(0){}
0028   virtual ~polygon(){clear();}
0029 protected:
0030   polygon(const polygon&){}
0031   polygon& operator=(const polygon&){return *this;}
0032 public:
0033   void clear(){
0034     POINTBLOCK* curPtBlock;
0035     cmem_free(m_pETEs);
0036     m_pETEn = 0;
0037     for(curPtBlock = m_FirstPtBlock.next; --m_numAllocPtBlocks >= 0;){
0038         POINTBLOCK* tmpPtBlock;
0039         tmpPtBlock  = curPtBlock->next;
0040         cmem_free(curPtBlock);
0041         curPtBlock  = tmpPtBlock;
0042     }
0043     m_numAllocPtBlocks = 0;
0044   }
0045 
0046   typedef void (*scan_func)(void*,int,int,int);
0047 
0048   void scan(int    Count,         /* number of pts  */
0049             const point* Pts,     /* the pts        */
0050             int    rule,          /* winding rule   */
0051             scan_func a_proc,void* a_tag){
0052     // polytoregion
0053     //   Scan converts a polygon by returning a run-length
0054     //   encoding of the resultant bitmap -- the run-length
0055     //   encoding is in the form of an array of rectangles.
0056 
0057     EdgeTableEntry* pAET;   /* Active Edge Table       */
0058     int y;                  /* current scanline        */
0059     int iPts = 0;           /* number of pts in buffer */
0060     EdgeTableEntry* pWETE;  /* Winding Edge Table Entry*/
0061     ScanLineList*   pSLL;   /* current scanLineList    */
0062 
0063     EdgeTableEntry* pPrevAET;        /* ptr to previous AET     */
0064     EdgeTable ET;                    /* header node for ET      */
0065     EdgeTableEntry AET;              /* header node for AET     */
0066     ScanLineListBlock SLLBlock;      /* header for scanlinelist */
0067     int         fixWAET = 0;
0068     POINTBLOCK* curPtBlock;
0069     int         numFullPtBlocks = 0;
0070 
0071     if(a_proc==NULL) return;
0072     if(Count==0)  return;
0073 
0074     /* special case a rectangle */
0075     point* pts = (point*)Pts;
0076     if (((Count == 4) ||
0077          ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) &&
0078         (((pts[0].y == pts[1].y) &&
0079           (pts[1].x == pts[2].x) &&
0080           (pts[2].y == pts[3].y) &&
0081           (pts[3].x == pts[0].x)) ||
0082          ((pts[0].x == pts[1].x) &&
0083           (pts[1].y == pts[2].y) &&
0084           (pts[2].x == pts[3].x) &&
0085           (pts[3].y == pts[0].y))))
0086       {
0087         int  xmin,xmax,ymin,ymax;
0088         xmin = (int)mn(pts[0].x, pts[2].x);
0089         ymin = (int)mn(pts[0].y, pts[2].y);
0090         xmax = (int)mx(pts[0].x, pts[2].x);
0091         ymax = (int)mx(pts[0].y, pts[2].y);
0092         if ((xmin != xmax) && (ymin != ymax))
0093             {
0094               for(y=ymin;y<=ymax;y++)  a_proc(a_tag,xmin  ,xmax  ,y);
0095             }
0096         return;
0097     }
0098 
0099     if(Count>m_pETEn)
0100       {
0101         cmem_free(m_pETEs);
0102         m_pETEn = Count;
0103         m_pETEs = cmem_alloc<EdgeTableEntry>(m_pETEn);
0104         if(m_pETEs==NULL)
0105           {
0106             m_pETEn = 0;
0107             return;
0108           }
0109       }
0110 
0111     /*G.Barrand : quiet g++-11 warnings : begin :*/
0112     ET.scanlines.next = (ScanLineList*)NULL;
0113     ET.ymax = SMALL_COORDINATE;
0114     ET.ymin = LARGE_COORDINATE;
0115     
0116     AET.next = (EdgeTableEntry*)NULL;
0117     AET.back = (EdgeTableEntry*)NULL;
0118     AET.nextWETE = (EdgeTableEntry*)NULL;
0119     AET.bres.minor_axis = SMALL_COORDINATE;
0120     
0121     SLLBlock.next = (ScanLineListBlock*)NULL;
0122     /*G.Barrand : end.*/
0123     
0124     CreateETandAET (Count,(point*)Pts, &ET, &AET, m_pETEs, &SLLBlock);
0125 
0126     pSLL           = ET.scanlines.next;
0127 
0128     curPtBlock     = &m_FirstPtBlock;
0129     pts            =  m_FirstPtBlock.pts;
0130 
0131 
0132     if (rule==0)
0133       {
0134         /*
0135          *  for each scanline
0136          */
0137         for (y = ET.ymin; y < ET.ymax; y++) {
0138             /*
0139              *  Add a new edge to the active edge table when we
0140              *  get to the next edge.
0141              */
0142             if (pSLL != NULL && y == pSLL->scanline)
0143               {
0144                 LoadAET(&AET, pSLL->edgelist);
0145                 pSLL = pSLL->next;
0146               }
0147             pPrevAET = &AET;
0148             pAET = AET.next;
0149 
0150             /*
0151              *  for each active edge
0152              */
0153             while (pAET) {
0154                 pts->x = pAET->bres.minor_axis;
0155                 pts->y = y;
0156                 pts++;
0157                 iPts++;
0158 
0159                 /*
0160                  *  send out the buffer
0161                  */
0162                 if (iPts == NUMPTSTOBUFFER)
0163                   {
0164                     if(numFullPtBlocks < m_numAllocPtBlocks)
0165                       {
0166                         curPtBlock = curPtBlock->next;
0167                       }
0168                     else
0169                       {
0170                         POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1);
0171                         if(tmpPtBlock==NULL)
0172                           {
0173                             FreeStorage(SLLBlock.next);
0174                             return;
0175                           }
0176                         tmpPtBlock->next = NULL; /*Barrand*/
0177                         curPtBlock->next = tmpPtBlock;
0178                         curPtBlock       = tmpPtBlock;
0179                         m_numAllocPtBlocks++;
0180                       }
0181                     numFullPtBlocks++;
0182                     pts  = curPtBlock->pts;
0183                     iPts = 0;
0184                   }
0185 
0186                 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
0187             }
0188             (void) InsertAndSort(&AET);
0189         }
0190       }
0191     else
0192       {
0193         /*
0194          *  for each scanline
0195          */
0196         for (y = ET.ymin; y < ET.ymax; y++) {
0197             /*
0198              *  Add a new edge to the active edge table when we
0199              *  get to the next edge.
0200              */
0201             if (pSLL != NULL && y == pSLL->scanline)
0202               {
0203                 LoadAET(&AET, pSLL->edgelist);
0204                 ComputeWAET(&AET);
0205                 pSLL = pSLL->next;
0206               }
0207             pPrevAET = &AET;
0208             pAET = AET.next;
0209             pWETE = pAET;
0210 
0211             /*
0212              *  for each active edge
0213              */
0214             while (pAET) {
0215                 /*
0216                  *  add to the buffer only those edges that
0217                  *  are in the Winding active edge table.
0218                  */
0219                 if (pWETE == pAET) {
0220                     pts->x = pAET->bres.minor_axis;
0221                     pts->y = y;
0222                     pts++;
0223                     iPts++;
0224 
0225                     /*
0226                      *  send out the buffer
0227                      */
0228                     if (iPts == NUMPTSTOBUFFER)
0229                       {
0230                         if(numFullPtBlocks < m_numAllocPtBlocks)
0231                           {
0232                             curPtBlock = curPtBlock->next;
0233                           }
0234                         else
0235                           {
0236                             POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1);
0237                             if(tmpPtBlock==NULL)
0238                               {
0239                                 FreeStorage(SLLBlock.next);
0240                                 return;
0241                               }
0242                             tmpPtBlock->next = NULL; /*Barrand*/
0243                             curPtBlock->next = tmpPtBlock;
0244                             curPtBlock       = tmpPtBlock;
0245                             m_numAllocPtBlocks++;
0246                           }
0247                         numFullPtBlocks++;
0248                         pts  = curPtBlock->pts;
0249                         iPts = 0;
0250                       }
0251                     pWETE = pWETE->nextWETE;
0252                 }
0253                 EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
0254             }
0255 
0256             /*
0257              *  recompute the winding active edge table if
0258              *  we just resorted or have exited an edge.
0259              */
0260             if ( (InsertAndSort(&AET)!=0) || (fixWAET!=0) )
0261               {
0262                 ComputeWAET(&AET);
0263                 fixWAET = 0;
0264               }
0265         }
0266       }
0267     FreeStorage   (SLLBlock.next);
0268 
0269     ScanPoints (numFullPtBlocks, iPts, &m_FirstPtBlock,a_proc,a_tag);
0270 
0271   }
0272 protected:
0273   void ScanPoints (int  numFullPtBlocks,
0274                    int  iCurPtBlock,
0275                    POINTBLOCK* FirstPtBlock,
0276                    scan_func a_proc,void* a_tag) {
0277     point*  pts;
0278     POINTBLOCK* CurPtBlock;
0279     int         i;
0280     CurPtBlock = FirstPtBlock;
0281     for ( ; numFullPtBlocks >= 0; numFullPtBlocks--)
0282       {
0283         /* the loop uses 2 points per iteration */
0284         i = numFullPtBlocks!=0 ? NUMPTSTOBUFFER >> 1 : iCurPtBlock >> 1 ;
0285         for (pts = CurPtBlock->pts; i--; pts += 2)
0286         {
0287           a_proc (a_tag,(int)(pts->x),(int)pts[1].x,(int)pts->y);
0288         }
0289         CurPtBlock = CurPtBlock->next;
0290       }
0291   }
0292 
0293 
0294 };
0295 
0296 }}
0297 
0298 #endif