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 ,int a_pts_xmin,int a_pts_ymin,int a_pts_ymax
0100 )
0101 /***************************************************************************/
0102 /*
0103 * CreateEdgeTable
0104 *
0105 * This routine creates the edge table for
0106 * scan converting polygons.
0107 * The Edge Table (ET) looks like:
0108 *
0109 * EdgeTable
0110 * --------
0111 * | ymax | ScanLineLists
0112 * |scanline|-->------------>-------------->...
0113 * -------- |scanline| |scanline|
0114 * |edgelist| |edgelist|
0115 * --------- ---------
0116 * | |
0117 * | |
0118 * V V
0119 * list of ETEs list of ETEs
0120 *
0121 * where ETE is an EdgeTableEntry data structure,
0122 * and there is one ScanLineList per scanline at
0123 * which an edge is initially entered.
0124 *
0125 */
0126 /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
0127 {
0128 point *top, *bottom;
0129 point *PrevPt, *CurrPt;
0130 int iSLLBlock = 0;
0131 int dy;
0132 /*.........................................................................*/
0133
0134 if (count < 2) return;
0135
0136 /*
0137 * initialize the Active Edge Table
0138 */
0139 AET->next = (EdgeTableEntry *)NULL;
0140 AET->back = (EdgeTableEntry *)NULL;
0141 AET->nextWETE = (EdgeTableEntry *)NULL;
0142 AET->bres.minor_axis = a_pts_xmin;
0143
0144 /*
0145 * initialize the Edge Table.
0146 */
0147 ET->scanlines.next = (ScanLineList *)NULL;
0148 ET->ymax = a_pts_ymin;
0149 ET->ymin = a_pts_ymax;
0150 pSLLBlock->next = (ScanLineListBlock *)NULL;
0151
0152 PrevPt = &pts[count-1];
0153
0154 /*
0155 * for each vertex in the array of points.
0156 * In this loop we are dealing with two vertices at
0157 * a time -- these make up one edge of the polygon.
0158 */
0159 while (count--)
0160 {
0161 CurrPt = pts++;
0162
0163 /*
0164 * find out which point is above and which is below.
0165 */
0166 if (PrevPt->y > CurrPt->y)
0167 {
0168 bottom = PrevPt, top = CurrPt;
0169 pETEs->ClockWise = 0;
0170 }
0171 else
0172 {
0173 bottom = CurrPt, top = PrevPt;
0174 pETEs->ClockWise = 1;
0175 }
0176
0177 /*
0178 * don't add horizontal edges to the Edge table.
0179 */
0180 if (bottom->y != top->y)
0181 {
0182 pETEs->ymax = (int)(bottom->y-1); /* -1 so we don't get last scanline */
0183
0184 /*
0185 * initialize integer edge algorithm
0186 */
0187 dy = (int)(bottom->y - top->y);
0188 BRESINITPGONSTRUCT (dy,(int)top->x,(int)bottom->x, pETEs->bres)
0189
0190 InsertEdgeInET (ET, pETEs, (int)top->y, &pSLLBlock, &iSLLBlock);
0191
0192 if (PrevPt->y > ET->ymax) ET->ymax = (int) PrevPt->y;
0193 if (PrevPt->y < ET->ymin) ET->ymin = (int) PrevPt->y;
0194 pETEs++;
0195 }
0196
0197 PrevPt = CurrPt;
0198 }
0199 }
0200
0201 inline void LoadAET(EdgeTableEntry* AET,EdgeTableEntry* ETEs) {
0202 /*
0203 * LoadAET
0204 *
0205 * This routine moves EdgeTableEntries from the
0206 * EdgeTable into the Active Edge Table,
0207 * leaving them sorted by smaller x coordinate.
0208 *
0209 */
0210 EdgeTableEntry *pPrevAET;
0211 EdgeTableEntry *tmp;
0212
0213 pPrevAET = AET;
0214 AET = AET->next;
0215 while(ETEs) {
0216 while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis))
0217 {
0218 pPrevAET = AET;
0219 AET = AET->next;
0220 }
0221 tmp = ETEs->next;
0222 ETEs->next = AET;
0223 if (AET!=NULL)
0224 AET->back = ETEs;
0225 ETEs->back = pPrevAET;
0226 pPrevAET->next = ETEs;
0227 pPrevAET = ETEs;
0228
0229 ETEs = tmp;
0230 }
0231 }
0232
0233 inline void ComputeWAET(EdgeTableEntry* AET) {
0234 /*
0235 * ComputeWAET
0236 *
0237 * This routine links the AET by the
0238 * nextWETE (winding EdgeTableEntry) link for
0239 * use by the winding number rule. The final
0240 * Active Edge Table (AET) might look something
0241 * like:
0242 *
0243 * AET
0244 * ---------- --------- ---------
0245 * |ymax | |ymax | |ymax |
0246 * | ... | |... | |... |
0247 * |next |->|next |->|next |->...
0248 * |nextWETE| |nextWETE| |nextWETE|
0249 * --------- --------- ^--------
0250 * | | |
0251 * V-------------------> V---> ...
0252 *
0253 */
0254 EdgeTableEntry *pWETE;
0255 int inside = 1;
0256 int isInside = 0;
0257
0258 AET->nextWETE = (EdgeTableEntry *)NULL;
0259 pWETE = AET;
0260 AET = AET->next;
0261 while(AET) {
0262 if (AET->ClockWise!=0)
0263 isInside++;
0264 else
0265 isInside--;
0266
0267 if (( (inside==0) && (isInside==0) ) ||
0268 ( (inside!=0) && (isInside!=0) ))
0269 {
0270 pWETE->nextWETE = AET;
0271 pWETE = AET;
0272 inside = !inside;
0273 }
0274 AET = AET->next;
0275 }
0276 pWETE->nextWETE = (EdgeTableEntry *)NULL;
0277 }
0278
0279 inline int InsertAndSort(EdgeTableEntry* AET) {
0280 // InsertAndSort
0281 // Just a simple insertion sort using
0282 // pointers and back pointers to sort the Active
0283 // Edge Table.
0284
0285 EdgeTableEntry *pETEchase;
0286 EdgeTableEntry *pETEinsert;
0287 EdgeTableEntry *pETEchaseBackTMP;
0288 int changed = 0;
0289
0290 AET = AET->next;
0291 while(AET) {
0292 pETEinsert = AET;
0293 pETEchase = AET;
0294 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
0295 pETEchase = pETEchase->back;
0296
0297 AET = AET->next;
0298 if (pETEchase != pETEinsert)
0299 {
0300 pETEchaseBackTMP = pETEchase->back;
0301 pETEinsert->back->next = AET;
0302 if (AET!=NULL)
0303 AET->back = pETEinsert->back;
0304 pETEinsert->next = pETEchase;
0305 pETEchase->back->next = pETEinsert;
0306 pETEchase->back = pETEinsert;
0307 pETEinsert->back = pETEchaseBackTMP;
0308 changed = 1;
0309 }
0310 }
0311 return(changed);
0312 }
0313
0314 inline void FreeStorage(ScanLineListBlock* pSLLBlock){
0315 // Clean up our act.
0316 ScanLineListBlock* tmpSLLBlock;
0317 while(pSLLBlock) {
0318 tmpSLLBlock = pSLLBlock->next;
0319 cmem_free(pSLLBlock);
0320 pSLLBlock = tmpSLLBlock;
0321 }
0322 }
0323
0324 }}
0325
0326 #endif