g4tools  5.4.0
polygon
Go to the documentation of this file.
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  CreateETandAET (Count,(point*)Pts, &ET, &AET, m_pETEs, &SLLBlock);
112 
113  pSLL = ET.scanlines.next;
114 
115  curPtBlock = &m_FirstPtBlock;
116  pts = m_FirstPtBlock.pts;
117 
118 
119  if (rule==0)
120  {
121  /*
122  * for each scanline
123  */
124  for (y = ET.ymin; y < ET.ymax; y++) {
125  /*
126  * Add a new edge to the active edge table when we
127  * get to the next edge.
128  */
129  if (pSLL != NULL && y == pSLL->scanline)
130  {
131  LoadAET(&AET, pSLL->edgelist);
132  pSLL = pSLL->next;
133  }
134  pPrevAET = &AET;
135  pAET = AET.next;
136 
137  /*
138  * for each active edge
139  */
140  while (pAET) {
141  pts->x = pAET->bres.minor_axis;
142  pts->y = y;
143  pts++;
144  iPts++;
145 
146  /*
147  * send out the buffer
148  */
149  if (iPts == NUMPTSTOBUFFER)
150  {
151  if(numFullPtBlocks < m_numAllocPtBlocks)
152  {
153  curPtBlock = curPtBlock->next;
154  }
155  else
156  {
157  POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1);
158  if(tmpPtBlock==NULL)
159  {
160  FreeStorage(SLLBlock.next);
161  return;
162  }
163  tmpPtBlock->next = NULL; /*Barrand*/
164  curPtBlock->next = tmpPtBlock;
165  curPtBlock = tmpPtBlock;
166  m_numAllocPtBlocks++;
167  }
168  numFullPtBlocks++;
169  pts = curPtBlock->pts;
170  iPts = 0;
171  }
172 
173  EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
174  }
175  (void) InsertAndSort(&AET);
176  }
177  }
178  else
179  {
180  /*
181  * for each scanline
182  */
183  for (y = ET.ymin; y < ET.ymax; y++) {
184  /*
185  * Add a new edge to the active edge table when we
186  * get to the next edge.
187  */
188  if (pSLL != NULL && y == pSLL->scanline)
189  {
190  LoadAET(&AET, pSLL->edgelist);
191  ComputeWAET(&AET);
192  pSLL = pSLL->next;
193  }
194  pPrevAET = &AET;
195  pAET = AET.next;
196  pWETE = pAET;
197 
198  /*
199  * for each active edge
200  */
201  while (pAET) {
202  /*
203  * add to the buffer only those edges that
204  * are in the Winding active edge table.
205  */
206  if (pWETE == pAET) {
207  pts->x = pAET->bres.minor_axis;
208  pts->y = y;
209  pts++;
210  iPts++;
211 
212  /*
213  * send out the buffer
214  */
215  if (iPts == NUMPTSTOBUFFER)
216  {
217  if(numFullPtBlocks < m_numAllocPtBlocks)
218  {
219  curPtBlock = curPtBlock->next;
220  }
221  else
222  {
223  POINTBLOCK* tmpPtBlock = cmem_alloc<POINTBLOCK>(1);
224  if(tmpPtBlock==NULL)
225  {
226  FreeStorage(SLLBlock.next);
227  return;
228  }
229  tmpPtBlock->next = NULL; /*Barrand*/
230  curPtBlock->next = tmpPtBlock;
231  curPtBlock = tmpPtBlock;
232  m_numAllocPtBlocks++;
233  }
234  numFullPtBlocks++;
235  pts = curPtBlock->pts;
236  iPts = 0;
237  }
238  pWETE = pWETE->nextWETE;
239  }
240  EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
241  }
242 
243  /*
244  * recompute the winding active edge table if
245  * we just resorted or have exited an edge.
246  */
247  if ( (InsertAndSort(&AET)!=0) || (fixWAET!=0) )
248  {
249  ComputeWAET(&AET);
250  fixWAET = 0;
251  }
252  }
253  }
254  FreeStorage (SLLBlock.next);
255 
256  ScanPoints (numFullPtBlocks, iPts, &m_FirstPtBlock,a_proc,a_tag);
257 
258  }
259 protected:
260  void ScanPoints (int numFullPtBlocks,
261  int iCurPtBlock,
262  POINTBLOCK* FirstPtBlock,
263  scan_func a_proc,void* a_tag) {
264  point* pts;
265  POINTBLOCK* CurPtBlock;
266  int i;
267  CurPtBlock = FirstPtBlock;
268  for ( ; numFullPtBlocks >= 0; numFullPtBlocks--)
269  {
270  /* the loop uses 2 points per iteration */
271  i = numFullPtBlocks!=0 ? NUMPTSTOBUFFER >> 1 : iCurPtBlock >> 1 ;
272  for (pts = CurPtBlock->pts; i--; pts += 2)
273  {
274  a_proc (a_tag,(int)(pts->x),(int)pts[1].x,(int)pts->y);
275  }
276  CurPtBlock = CurPtBlock->next;
277  }
278  }
279 
280 
281 };
282 
283 }}
284 
285 #endif
_ScanLineList::scanline
int scanline
Definition: line:180
EVALUATEEDGEWINDING
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
Definition: line:220
_ScanLineList
Definition: line:179
tools::zb::CreateETandAET
void CreateETandAET(int count, point *pts, EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
Definition: edge_table:92
tools::zb::point::y
ZPos y
Definition: point:26
EdgeTable
Definition: line:186
tools::zb::LoadAET
void LoadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
Definition: edge_table:200
tools::zb::ComputeWAET
void ComputeWAET(EdgeTableEntry *AET)
Definition: edge_table:232
tools::cmem_free
void cmem_free(T *&a_p)
Definition: cmemT:16
tools::zb::polygon::clear
void clear()
Definition: polygon:33
tools::mn
T mn(const T &a, const T &b)
Definition: mnmx:10
tools::mx
T mx(const T &a, const T &b)
Definition: mnmx:13
_ScanLineList::next
struct _ScanLineList * next
Definition: line:182
_ScanLineList::edgelist
EdgeTableEntry * edgelist
Definition: line:181
_ScanLineListBlock::next
struct _ScanLineListBlock * next
Definition: line:202
_EdgeTableEntry::bres
BRESINFO bres
Definition: line:171
EVALUATEEDGEEVENODD
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
Definition: line:243
tools::zb::point::x
ZPos x
Definition: point:25
tools::zb::FreeStorage
void FreeStorage(ScanLineListBlock *pSLLBlock)
Definition: edge_table:313
tools::zb::polygon::polygon
polygon()
Definition: polygon:27
_EdgeTableEntry::next
struct _EdgeTableEntry * next
Definition: line:172
tools::zb::polygon::operator=
polygon & operator=(const polygon &)
Definition: polygon:31
tools::zb::point
Definition: point:13
tools::zb::polygon::scan
void scan(int Count, const point *Pts, int rule, scan_func a_proc, void *a_tag)
Definition: polygon:48
tools::zb::polygon
Definition: polygon:13
_ScanLineListBlock
Definition: line:200
_EdgeTableEntry::nextWETE
struct _EdgeTableEntry * nextWETE
Definition: line:174
tools::zb::polygon::ScanPoints
void ScanPoints(int numFullPtBlocks, int iCurPtBlock, POINTBLOCK *FirstPtBlock, scan_func a_proc, void *a_tag)
Definition: polygon:260
tools::zb::polygon::polygon
polygon(const polygon &)
Definition: polygon:30
tools
inlined C code : ///////////////////////////////////
Definition: aida_ntuple:26
tools::zb::InsertAndSort
int InsertAndSort(EdgeTableEntry *AET)
Definition: edge_table:278
EdgeTable::scanlines
ScanLineList scanlines
Definition: line:189
tools::zb::polygon::~polygon
virtual ~polygon()
Definition: polygon:28
BRESINFO::minor_axis
int minor_axis
Definition: line:101
EdgeTable::ymin
int ymin
Definition: line:188
tools::zb::polygon::scan_func
void(* scan_func)(void *, int, int, int)
Definition: polygon:46
_EdgeTableEntry
Definition: line:169
edge_table
EdgeTable::ymax
int ymax
Definition: line:187