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