Warning, /include/Geant4/tools/zb/edge_table 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_edge_table
0005 #define tools_zb_edge_table
0006
0007 #include "line"
0008 #include "point"
0009
0010 #include "../cmemT"
0011 #include <cstdio> //NULL
0012
0013 namespace tools {
0014 namespace zb {
0015
0016 /***************************************************************************/
0017 inline void InsertEdgeInET (
0018 EdgeTable* ET
0019 ,EdgeTableEntry* ETE
0020 ,int scanline
0021 ,ScanLineListBlock** SLLBlock
0022 ,int* iSLLBlock
0023 )
0024 /***************************************************************************/
0025 /*
0026 * InsertEdgeInET
0027 *
0028 * Insert the given edge into the edge table.
0029 * First we must find the correct bucket in the
0030 * Edge table, then find the right slot in the
0031 * bucket. Finally, we can insert it.
0032 *
0033 */
0034 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
0035 {
0036 EdgeTableEntry *start, *prev;
0037 ScanLineList *pSLL, *pPrevSLL;
0038 ScanLineListBlock *tmpSLLBlock;
0039 /*.........................................................................*/
0040
0041 /*
0042 * find the right bucket to put the edge into
0043 */
0044 pPrevSLL = &ET->scanlines;
0045 pSLL = pPrevSLL->next;
0046 while (pSLL && (pSLL->scanline < scanline))
0047 {
0048 pPrevSLL = pSLL;
0049 pSLL = pSLL->next;
0050 }
0051
0052 /*
0053 * reassign pSLL (pointer to ScanLineList) if necessary
0054 */
0055 if ( (pSLL==NULL) || (pSLL->scanline > scanline))
0056 {
0057 if (*iSLLBlock > SLLSPERBLOCK-1)
0058 {
0059 tmpSLLBlock = cmem_alloc<ScanLineListBlock>(1);
0060 (*SLLBlock)->next = tmpSLLBlock;
0061 tmpSLLBlock->next = (ScanLineListBlock *)NULL;
0062 *SLLBlock = tmpSLLBlock;
0063 *iSLLBlock = 0;
0064 }
0065 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
0066
0067 pSLL->next = pPrevSLL->next;
0068 pSLL->edgelist = (EdgeTableEntry *)NULL;
0069 pPrevSLL->next = pSLL;
0070 }
0071 pSLL->scanline = scanline;
0072
0073 /*
0074 * now insert the edge in the right bucket
0075 */
0076 prev = (EdgeTableEntry *)NULL;
0077 start = pSLL->edgelist;
0078 while (start && (start->bres.minor_axis < ETE->bres.minor_axis))
0079 {
0080 prev = start;
0081 start = start->next;
0082 }
0083 ETE->next = start;
0084
0085 if (prev!=NULL)
0086 prev->next = ETE;
0087 else
0088 pSLL->edgelist = ETE;
0089 }
0090
0091 /***************************************************************************/
0092 inline void CreateETandAET (
0093 int count
0094 ,point* pts
0095 ,EdgeTable* ET
0096 ,EdgeTableEntry* AET
0097 ,EdgeTableEntry* pETEs
0098 ,ScanLineListBlock* pSLLBlock
0099 )
0100 /***************************************************************************/
0101 /*
0102 * CreateEdgeTable
0103 *
0104 * This routine creates the edge table for
0105 * scan converting polygons.
0106 * The Edge Table (ET) looks like:
0107 *
0108 * EdgeTable
0109 * --------
0110 * | ymax | ScanLineLists
0111 * |scanline|-->------------>-------------->...
0112 * -------- |scanline| |scanline|
0113 * |edgelist| |edgelist|
0114 * --------- ---------
0115 * | |
0116 * | |
0117 * V V
0118 * list of ETEs list of ETEs
0119 *
0120 * where ETE is an EdgeTableEntry data structure,
0121 * and there is one ScanLineList per scanline at
0122 * which an edge is initially entered.
0123 *
0124 */
0125 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
0126 {
0127 point *top, *bottom;
0128 point *PrevPt, *CurrPt;
0129 int iSLLBlock = 0;
0130 int dy;
0131 /*.........................................................................*/
0132
0133 if (count < 2) return;
0134
0135 /*
0136 * initialize the Active Edge Table
0137 */
0138 AET->next = (EdgeTableEntry *)NULL;
0139 AET->back = (EdgeTableEntry *)NULL;
0140 AET->nextWETE = (EdgeTableEntry *)NULL;
0141 AET->bres.minor_axis = SMALL_COORDINATE;
0142
0143 /*
0144 * initialize the Edge Table.
0145 */
0146 ET->scanlines.next = (ScanLineList *)NULL;
0147 ET->ymax = SMALL_COORDINATE;
0148 ET->ymin = LARGE_COORDINATE;
0149 pSLLBlock->next = (ScanLineListBlock *)NULL;
0150
0151 PrevPt = &pts[count-1];
0152
0153 /*
0154 * for each vertex in the array of points.
0155 * In this loop we are dealing with two vertices at
0156 * a time -- these make up one edge of the polygon.
0157 */
0158 while (count--)
0159 {
0160 CurrPt = pts++;
0161
0162 /*
0163 * find out which point is above and which is below.
0164 */
0165 if (PrevPt->y > CurrPt->y)
0166 {
0167 bottom = PrevPt, top = CurrPt;
0168 pETEs->ClockWise = 0;
0169 }
0170 else
0171 {
0172 bottom = CurrPt, top = PrevPt;
0173 pETEs->ClockWise = 1;
0174 }
0175
0176 /*
0177 * don't add horizontal edges to the Edge table.
0178 */
0179 if (bottom->y != top->y)
0180 {
0181 pETEs->ymax = (int)(bottom->y-1); /* -1 so we don't get last scanline */
0182
0183 /*
0184 * initialize integer edge algorithm
0185 */
0186 dy = (int)(bottom->y - top->y);
0187 BRESINITPGONSTRUCT (dy,(int)top->x,(int)bottom->x, pETEs->bres)
0188
0189 InsertEdgeInET (ET, pETEs, (int)top->y, &pSLLBlock, &iSLLBlock);
0190
0191 if (PrevPt->y > ET->ymax) ET->ymax = (int) PrevPt->y;
0192 if (PrevPt->y < ET->ymin) ET->ymin = (int) PrevPt->y;
0193 pETEs++;
0194 }
0195
0196 PrevPt = CurrPt;
0197 }
0198 }
0199
0200 inline void LoadAET(EdgeTableEntry* AET,EdgeTableEntry* ETEs) {
0201 /*
0202 * LoadAET
0203 *
0204 * This routine moves EdgeTableEntries from the
0205 * EdgeTable into the Active Edge Table,
0206 * leaving them sorted by smaller x coordinate.
0207 *
0208 */
0209 EdgeTableEntry *pPrevAET;
0210 EdgeTableEntry *tmp;
0211
0212 pPrevAET = AET;
0213 AET = AET->next;
0214 while(ETEs) {
0215 while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
0216 {
0217 pPrevAET = AET;
0218 AET = AET->next;
0219 }
0220 tmp = ETEs->next;
0221 ETEs->next = AET;
0222 if (AET!=NULL)
0223 AET->back = ETEs;
0224 ETEs->back = pPrevAET;
0225 pPrevAET->next = ETEs;
0226 pPrevAET = ETEs;
0227
0228 ETEs = tmp;
0229 }
0230 }
0231
0232 inline void ComputeWAET(EdgeTableEntry* AET) {
0233 /*
0234 * ComputeWAET
0235 *
0236 * This routine links the AET by the
0237 * nextWETE (winding EdgeTableEntry) link for
0238 * use by the winding number rule. The final
0239 * Active Edge Table (AET) might look something
0240 * like:
0241 *
0242 * AET
0243 * ---------- --------- ---------
0244 * |ymax | |ymax | |ymax |
0245 * | ... | |... | |... |
0246 * |next |->|next |->|next |->...
0247 * |nextWETE| |nextWETE| |nextWETE|
0248 * --------- --------- ^--------
0249 * | | |
0250 * V-------------------> V---> ...
0251 *
0252 */
0253 EdgeTableEntry *pWETE;
0254 int inside = 1;
0255 int isInside = 0;
0256
0257 AET->nextWETE = (EdgeTableEntry *)NULL;
0258 pWETE = AET;
0259 AET = AET->next;
0260 while(AET) {
0261 if (AET->ClockWise!=0)
0262 isInside++;
0263 else
0264 isInside--;
0265
0266 if (( (inside==0) && (isInside==0) ) ||
0267 ( (inside!=0) && (isInside!=0) ))
0268 {
0269 pWETE->nextWETE = AET;
0270 pWETE = AET;
0271 inside = !inside;
0272 }
0273 AET = AET->next;
0274 }
0275 pWETE->nextWETE = (EdgeTableEntry *)NULL;
0276 }
0277
0278 inline int InsertAndSort(EdgeTableEntry* AET) {
0279 // InsertAndSort
0280 // Just a simple insertion sort using
0281 // pointers and back pointers to sort the Active
0282 // Edge Table.
0283
0284 EdgeTableEntry *pETEchase;
0285 EdgeTableEntry *pETEinsert;
0286 EdgeTableEntry *pETEchaseBackTMP;
0287 int changed = 0;
0288
0289 AET = AET->next;
0290 while(AET) {
0291 pETEinsert = AET;
0292 pETEchase = AET;
0293 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
0294 pETEchase = pETEchase->back;
0295
0296 AET = AET->next;
0297 if (pETEchase != pETEinsert)
0298 {
0299 pETEchaseBackTMP = pETEchase->back;
0300 pETEinsert->back->next = AET;
0301 if (AET!=NULL)
0302 AET->back = pETEinsert->back;
0303 pETEinsert->next = pETEchase;
0304 pETEchase->back->next = pETEinsert;
0305 pETEchase->back = pETEinsert;
0306 pETEinsert->back = pETEchaseBackTMP;
0307 changed = 1;
0308 }
0309 }
0310 return(changed);
0311 }
0312
0313 inline void FreeStorage(ScanLineListBlock* pSLLBlock){
0314 // Clean up our act.
0315 ScanLineListBlock* tmpSLLBlock;
0316 while(pSLLBlock) {
0317 tmpSLLBlock = pSLLBlock->next;
0318 cmem_free(pSLLBlock);
0319 pSLLBlock = tmpSLLBlock;
0320 }
0321 }
0322
0323 }}
0324
0325 #endif