Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_zb_polygon 5 #define tools_zb_polygon 6 7 #include "edge_table" 8 #include "../mnmx" 9 10 namespace tools { 11 namespace zb { 12 13 class polygon { 14 15 static const int NUMPTSTOBUFFER = 200; 16 17 typedef struct _POINTBLOCK { 18 point pts[NUMPTSTOBUFFER]; 19 struct _POINTBLOCK* next; 20 } POINTBLOCK; 21 22 int m_pETEn; 23 EdgeTableEntry* m_pETEs; 24 int m_numAllocPtBlocks; 25 POINTBLOCK m_FirstPtBlock; 26 public: 27 polygon():m_pETEn(0),m_pETEs(NULL),m_numAllocPtBlocks(0){} 28 virtual ~polygon(){clear();} 29 protected: 30 polygon(const polygon&){} 31 polygon& operator=(const polygon&){return *this;} 32 public: 33 void clear(){ 34 POINTBLOCK* curPtBlock; 35 cmem_free(m_pETEs); 36 m_pETEn = 0; 37 for(curPtBlock = m_FirstPtBlock.next; --m_numAllocPtBlocks >= 0;){ 38 POINTBLOCK* tmpPtBlock; 39 tmpPtBlock = curPtBlock->next; 40 cmem_free(curPtBlock); 41 curPtBlock = tmpPtBlock; 42 } 43 m_numAllocPtBlocks = 0; 44 } 45 46 typedef void (*scan_func)(void*,int,int,int); 47 48 void scan(int Count, /* number of pts */ 49 const point* Pts, /* the pts */ 50 int rule, /* winding rule */ 51 scan_func a_proc,void* a_tag){ 52 // polytoregion 53 // Scan converts a polygon by returning a run-length 54 // encoding of the resultant bitmap -- the run-length 55 // encoding is in the form of an array of rectangles. 56 57 EdgeTableEntry* pAET; /* Active Edge Table */ 58 int y; /* current scanline */ 59 int iPts = 0; /* number of pts in buffer */ 60 EdgeTableEntry* pWETE; /* Winding Edge Table Entry*/ 61 ScanLineList* pSLL; /* current scanLineList */ 62 63 EdgeTableEntry* pPrevAET; /* ptr to previous AET */ 64 EdgeTable ET; /* header node for ET */ 65 EdgeTableEntry AET; /* header node for AET */ 66 ScanLineListBlock SLLBlock; /* header for scanlinelist */ 67 int fixWAET = 0; 68 POINTBLOCK* curPtBlock; 69 int numFullPtBlocks = 0; 70 71 if(a_proc==NULL) return; 72 if(Count==0) return; 73 74 /* special case a rectangle */ 75 point* pts = (point*)Pts; 76 if (((Count == 4) || 77 ((Count == 5) && (pts[4].x == pts[0].x) && (pts[4].y == pts[0].y))) && 78 (((pts[0].y == pts[1].y) && 79 (pts[1].x == pts[2].x) && 80 (pts[2].y == pts[3].y) && 81 (pts[3].x == pts[0].x)) || 82 ((pts[0].x == pts[1].x) && 83 (pts[1].y == pts[2].y) && 84 (pts[2].x == pts[3].x) && 85 (pts[3].y == pts[0].y)))) 86 { 87 int xmin,xmax,ymin,ymax; 88 xmin = (int)mn(pts[0].x, pts[2].x); 89 ymin = (int)mn(pts[0].y, pts[2].y); 90 xmax = (int)mx(pts[0].x, pts[2].x); 91 ymax = (int)mx(pts[0].y, pts[2].y); 92 if ((xmin != xmax) && (ymin != ymax)) 93 { 94 for(y=ymin;y<=ymax;y++) a_proc(a_tag,xmin ,xmax ,y); 95 } 96 return; 97 } 98 99 if(Count>m_pETEn) 100 { 101 cmem_free(m_pETEs); 102 m_pETEn = Count; 103 m_pETEs = cmem_alloc<EdgeTableEntry>(m_pETEn); 104 if(m_pETEs==NULL) 105 { 106 m_pETEn = 0; 107 return; 108 } 109 } 110 111 /*G.Barrand : quiet g++-11 warnings : begin :*/ 112 ET.scanlines.next = (ScanLineList*)NULL; 113 ET.ymax = SMALL_COORDINATE; 114 ET.ymin = LARGE_COORDINATE; 115 116 AET.next = (EdgeTableEntry*)NULL; 117 AET.back = (EdgeTableEntry*)NULL; 118 AET.nextWETE = (EdgeTableEntry*)NULL; 119 AET.bres.minor_axis = SMALL_COORDINATE; 120 121 SLLBlock.next = (ScanLineListBlock*)NULL; 122 /*G.Barrand : end.*/ 123 124 CreateETandAET (Count,(point*)Pts, &ET, &AET, m_pETEs, &SLLBlock); 125 126 pSLL = ET.scanlines.next; 127 128 curPtBlock = &m_FirstPtBlock; 129 pts = m_FirstPtBlock.pts; 130 131 132 if (rule==0) 133 { 134 /* 135 * for each scanline 136 */ 137 for (y = ET.ymin; y < ET.ymax; y++) { 138 /* 139 * Add a new edge to the active edge table when we 140 * get to the next edge. 141 */ 142 if (pSLL != NULL && y == pSLL->scanline) 143 { 144 LoadAET(&AET, pSLL->edgelist); 145 pSLL = pSLL->next; 146 } 147 pPrevAET = &AET; 148 pAET = AET.next; 149 150 /* 151 * for each active edge 152 */ 153 while (pAET) { 154 pts->x = pAET->bres.minor_axis; 155 pts->y = y; 156 pts++; 157 iPts++; 158 159 /* 160 * send out the buffer 161 */ 162 if (iPts == NUMPTSTOBUFFER) 163 { 164 if(numFullPtBlocks < m_numAllocPtBlocks) 165 { 166 curPtBlock = curPtBlock->next; 167 } 168 else 169 { 170 POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1); 171 if(tmpPtBlock==NULL) 172 { 173 FreeStorage(SLLBlock.next); 174 return; 175 } 176 tmpPtBlock->next = NULL; /*Barrand*/ 177 curPtBlock->next = tmpPtBlock; 178 curPtBlock = tmpPtBlock; 179 m_numAllocPtBlocks++; 180 } 181 numFullPtBlocks++; 182 pts = curPtBlock->pts; 183 iPts = 0; 184 } 185 186 EVALUATEEDGEEVENODD(pAET, pPrevAET, y) 187 } 188 (void) InsertAndSort(&AET); 189 } 190 } 191 else 192 { 193 /* 194 * for each scanline 195 */ 196 for (y = ET.ymin; y < ET.ymax; y++) { 197 /* 198 * Add a new edge to the active edge table when we 199 * get to the next edge. 200 */ 201 if (pSLL != NULL && y == pSLL->scanline) 202 { 203 LoadAET(&AET, pSLL->edgelist); 204 ComputeWAET(&AET); 205 pSLL = pSLL->next; 206 } 207 pPrevAET = &AET; 208 pAET = AET.next; 209 pWETE = pAET; 210 211 /* 212 * for each active edge 213 */ 214 while (pAET) { 215 /* 216 * add to the buffer only those edges that 217 * are in the Winding active edge table. 218 */ 219 if (pWETE == pAET) { 220 pts->x = pAET->bres.minor_axis; 221 pts->y = y; 222 pts++; 223 iPts++; 224 225 /* 226 * send out the buffer 227 */ 228 if (iPts == NUMPTSTOBUFFER) 229 { 230 if(numFullPtBlocks < m_numAllocPtBlocks) 231 { 232 curPtBlock = curPtBlock->next; 233 } 234 else 235 { 236 POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1); 237 if(tmpPtBlock==NULL) 238 { 239 FreeStorage(SLLBlock.next); 240 return; 241 } 242 tmpPtBlock->next = NULL; /*Barrand*/ 243 curPtBlock->next = tmpPtBlock; 244 curPtBlock = tmpPtBlock; 245 m_numAllocPtBlocks++; 246 } 247 numFullPtBlocks++; 248 pts = curPtBlock->pts; 249 iPts = 0; 250 } 251 pWETE = pWETE->nextWETE; 252 } 253 EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) 254 } 255 256 /* 257 * recompute the winding active edge table if 258 * we just resorted or have exited an edge. 259 */ 260 if ( (InsertAndSort(&AET)!=0) || (fixWAET!=0) ) 261 { 262 ComputeWAET(&AET); 263 fixWAET = 0; 264 } 265 } 266 } 267 FreeStorage (SLLBlock.next); 268 269 ScanPoints (numFullPtBlocks, iPts, &m_FirstPtBlock,a_proc,a_tag); 270 271 } 272 protected: 273 void ScanPoints (int numFullPtBlocks, 274 int iCurPtBlock, 275 POINTBLOCK* FirstPtBlock, 276 scan_func a_proc,void* a_tag) { 277 point* pts; 278 POINTBLOCK* CurPtBlock; 279 int i; 280 CurPtBlock = FirstPtBlock; 281 for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) 282 { 283 /* the loop uses 2 points per iteration */ 284 i = numFullPtBlocks!=0 ? NUMPTSTOBUFFER >> 1 : iCurPtBlock >> 1 ; 285 for (pts = CurPtBlock->pts; i--; pts += 2) 286 { 287 a_proc (a_tag,(int)(pts->x),(int)pts[1].x,(int)pts->y); 288 } 289 CurPtBlock = CurPtBlock->next; 290 } 291 } 292 293 294 }; 295 296 }} 297 298 #endif