OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
mipolyutil.c
Go to the documentation of this file.
1 /***********************************************************
2 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
3 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
4 
5  All Rights Reserved
6 
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Digital or MIT not be
12 used in advertising or publicity pertaining to distribution of the
13 software without specific, written prior permission.
14 
15 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
16 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
17 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
18 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
19 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
20 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
21 SOFTWARE.
22 
23  ******************************************************************/
24 /* $XConsortium: mipolyutil.c,v 1.14 89/03/22 10:50:55 rws Exp $ */
25 #include <stdlib.h>
26 #include "miscstruct.h"
27 #include "gc.h"
28 #include "miscanfill.h"
29 #include "mipoly.h"
30 
31 extern void miFreeStorage();
32 
33 #define MAXINT 0x7fffffff
34 #define MININT -MAXINT
35 
36 /*
37  * fillUtils.c
38  *
39  * Written by Brian Kelleher; Oct. 1985
40  *
41  * This module contains all of the utility functions
42  * needed to scan convert a polygon.
43  *
44  */
45 
46 /*
47  * InsertEdgeInET
48  *
49  * Insert the given edge into the edge table.
50  * First we must find the correct bucket in the
51  * Edge table, then find the right slot in the
52  * bucket. Finally, we can insert it.
53  *
54  */
55 Bool
56 miInsertEdgeInET(ET, ETE, scanline, SLLBlock, iSLLBlock)
57 EdgeTable *ET;
58 EdgeTableEntry *ETE;
59 int scanline;
60 ScanLineListBlock **SLLBlock;
61 int *iSLLBlock;
62 {
63  register EdgeTableEntry *start, *prev;
64  register ScanLineList *pSLL, *pPrevSLL;
65  ScanLineListBlock *tmpSLLBlock;
66 
67  /*
68  * find the right bucket to put the edge into
69  */
70  pPrevSLL = &ET->scanlines;
71  pSLL = pPrevSLL->next;
72  while (pSLL && (pSLL->scanline < scanline)) {
73  pPrevSLL = pSLL;
74  pSLL = pSLL->next;
75  }
76 
77  /*
78  * reassign pSLL (pointer to ScanLineList) if necessary
79  */
80  if ((!pSLL) || (pSLL->scanline > scanline)) {
81  if (*iSLLBlock > SLLSPERBLOCK - 1) {
82  tmpSLLBlock =
83  (ScanLineListBlock *) malloc(sizeof (ScanLineListBlock));
84  if (!tmpSLLBlock)
85  return FALSE;
86  (*SLLBlock)->next = tmpSLLBlock;
87  tmpSLLBlock->next = (ScanLineListBlock *) NULL;
88  *SLLBlock = tmpSLLBlock;
89  *iSLLBlock = 0;
90  }
91  pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
92 
93  pSLL->next = pPrevSLL->next;
94  pSLL->edgelist = (EdgeTableEntry *) NULL;
95  pPrevSLL->next = pSLL;
96  }
97  pSLL->scanline = scanline;
98 
99  /*
100  * now insert the edge in the right bucket
101  */
102  prev = (EdgeTableEntry *) NULL;
103  start = pSLL->edgelist;
104  while (start && (start->bres.minor < ETE->bres.minor)) {
105  prev = start;
106  start = start->next;
107  }
108  ETE->next = start;
109 
110  if (prev)
111  prev->next = ETE;
112  else
113  pSLL->edgelist = ETE;
114  return TRUE;
115 }
116 
117 /*
118  * CreateEdgeTable
119  *
120  * This routine creates the edge table for
121  * scan converting polygons.
122  * The Edge Table (ET) looks like:
123  *
124  * EdgeTable
125  * --------
126  * | ymax | ScanLineLists
127  * |scanline|-->------------>-------------->...
128  * -------- |scanline| |scanline|
129  * |edgelist| |edgelist|
130  * --------- ---------
131  * | |
132  * | |
133  * V V
134  * list of ETEs list of ETEs
135  *
136  * where ETE is an EdgeTableEntry data structure,
137  * and there is one ScanLineList per scanline at
138  * which an edge is initially entered.
139  *
140  */
141 
142 Bool
143 miCreateETandAET(count, pts, ET, AET, pETEs, pSLLBlock)
144 register int count;
145 register DDXPointPtr pts;
146 EdgeTable *ET;
147 EdgeTableEntry *AET;
148 register EdgeTableEntry *pETEs;
149 ScanLineListBlock *pSLLBlock;
150 {
151  register DDXPointPtr top, bottom;
152  register DDXPointPtr PrevPt, CurrPt;
153  int iSLLBlock = 0;
154 
155  int dy;
156 
157  if (count < 2) return TRUE;
158 
159  /*
160  * initialize the Active Edge Table
161  */
162  AET->next = (EdgeTableEntry *) NULL;
163  AET->back = (EdgeTableEntry *) NULL;
164  AET->nextWETE = (EdgeTableEntry *) NULL;
165  AET->bres.minor = MININT;
166 
167  /*
168  * initialize the Edge Table.
169  */
170  ET->scanlines.next = (ScanLineList *) NULL;
171  ET->ymax = MININT;
172  ET->ymin = MAXINT;
173  pSLLBlock->next = (ScanLineListBlock *) NULL;
174 
175  PrevPt = &pts[count - 1];
176 
177  /*
178  * for each vertex in the array of points.
179  * In this loop we are dealing with two vertices at
180  * a time -- these make up one edge of the polygon.
181  */
182  while (count--) {
183  CurrPt = pts++;
184 
185  /*
186  * find out which point is above and which is below.
187  */
188  if (PrevPt->y > CurrPt->y) {
189  bottom = PrevPt, top = CurrPt;
190  pETEs->ClockWise = 0;
191  } else {
192  bottom = CurrPt, top = PrevPt;
193  pETEs->ClockWise = 1;
194  }
195 
196  /*
197  * don't add horizontal edges to the Edge table.
198  */
199  if (bottom->y != top->y) {
200  pETEs->ymax = bottom->y - 1; /* -1 so we don't get last scanline */
201 
202  /*
203  * initialize integer edge algorithm
204  */
205  dy = bottom->y - top->y;
206  BRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
207 
208  if (!miInsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock)) {
209  miFreeStorage(pSLLBlock->next);
210  return FALSE;
211  }
212 
213  ET->ymax = max(ET->ymax, PrevPt->y);
214  ET->ymin = min(ET->ymin, PrevPt->y);
215  pETEs++;
216  }
217 
218  PrevPt = CurrPt;
219  }
220  return TRUE;
221 }
222 
223 /*
224  * loadAET
225  *
226  * This routine moves EdgeTableEntries from the
227  * EdgeTable into the Active Edge Table,
228  * leaving them sorted by smaller x coordinate.
229  *
230  */
231 
232 void
233 miloadAET(AET, ETEs)
234 register EdgeTableEntry *AET, *ETEs;
235 {
236  register EdgeTableEntry *pPrevAET;
237  register EdgeTableEntry *tmp;
238 
239  pPrevAET = AET;
240  AET = AET->next;
241  while (ETEs) {
242  while (AET && (AET->bres.minor < ETEs->bres.minor)) {
243  pPrevAET = AET;
244  AET = AET->next;
245  }
246  tmp = ETEs->next;
247  ETEs->next = AET;
248  if (AET)
249  AET->back = ETEs;
250  ETEs->back = pPrevAET;
251  pPrevAET->next = ETEs;
252  pPrevAET = ETEs;
253 
254  ETEs = tmp;
255  }
256 }
257 
258 /*
259  * computeWAET
260  *
261  * This routine links the AET by the
262  * nextWETE (winding EdgeTableEntry) link for
263  * use by the winding number rule. The final
264  * Active Edge Table (AET) might look something
265  * like:
266  *
267  * AET
268  * ---------- --------- ---------
269  * |ymax | |ymax | |ymax |
270  * | ... | |... | |... |
271  * |next |->|next |->|next |->...
272  * |nextWETE| |nextWETE| |nextWETE|
273  * --------- --------- ^--------
274  * | | |
275  * V-------------------> V---> ...
276  *
277  */
278 void
280 register EdgeTableEntry *AET;
281 {
282  register EdgeTableEntry *pWETE;
283  register int inside = 1;
284  register int isInside = 0;
285 
286  AET->nextWETE = (EdgeTableEntry *) NULL;
287  pWETE = AET;
288  AET = AET->next;
289  while (AET) {
290  if (AET->ClockWise)
291  isInside++;
292  else
293  isInside--;
294 
295  if ((!inside && !isInside) ||
296  (inside && isInside)) {
297  pWETE->nextWETE = AET;
298  pWETE = AET;
299  inside = !inside;
300  }
301  AET = AET->next;
302  }
303  pWETE->nextWETE = (EdgeTableEntry *) NULL;
304 }
305 
306 /*
307  * InsertionSort
308  *
309  * Just a simple insertion sort using
310  * pointers and back pointers to sort the Active
311  * Edge Table.
312  *
313  */
314 
315 int
317 register EdgeTableEntry *AET;
318 {
319  register EdgeTableEntry *pETEchase;
320  register EdgeTableEntry *pETEinsert;
321  register EdgeTableEntry *pETEchaseBackTMP;
322  register int changed = 0;
323 
324  AET = AET->next;
325  while (AET) {
326  pETEinsert = AET;
327  pETEchase = AET;
328  while (pETEchase->back->bres.minor > AET->bres.minor)
329  pETEchase = pETEchase->back;
330 
331  AET = AET->next;
332  if (pETEchase != pETEinsert) {
333  pETEchaseBackTMP = pETEchase->back;
334  pETEinsert->back->next = AET;
335  if (AET)
336  AET->back = pETEinsert->back;
337  pETEinsert->next = pETEchase;
338  pETEchase->back->next = pETEinsert;
339  pETEchase->back = pETEinsert;
340  pETEinsert->back = pETEchaseBackTMP;
341  changed = 1;
342  }
343  }
344  return (changed);
345 }
346 
347 /*
348  * Clean up our act.
349  */
350 void
351 miFreeStorage(pSLLBlock)
352 register ScanLineListBlock *pSLLBlock;
353 {
354  register ScanLineListBlock *tmpSLLBlock;
355 
356  while (pSLLBlock) {
357  tmpSLLBlock = pSLLBlock->next;
358  free(pSLLBlock);
359  pSLLBlock = tmpSLLBlock;
360  }
361 }
int ymin
Definition: mipoly.h:77
void miloadAET(EdgeTableEntry *AET, EdgeTableEntry *ETEs)
Definition: mipolyutil.c:233
These are used to scale the SD before writing it to the HDF4 file The default is and which means the product is not scaled at all Since the product is usually stored as a float inside of this is a way to write the float out as a integer l2prod min
void micomputeWAET(EdgeTableEntry *AET)
Definition: mipolyutil.c:279
#define FALSE
Definition: rice.h:164
#define NULL
Definition: decode_rs.h:63
#define TRUE
Definition: rice.h:165
void miFreeStorage()
data_t tmp
Definition: decode_rs.h:74
Bool miCreateETandAET(int count, DDXPointPtr pts, EdgeTable *ET, EdgeTableEntry *AET, EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
Definition: mipolyutil.c:143
int ymax
Definition: mipoly.h:76
int miInsertionSort(EdgeTableEntry *AET)
Definition: mipolyutil.c:316
#define MAXINT
Definition: mipolyutil.c:33
#define SLLSPERBLOCK
Definition: mipoly.h:87
int Bool
Definition: misc.h:55
#define MININT
Definition: mipolyutil.c:34
Bool miInsertEdgeInET(EdgeTable *ET, EdgeTableEntry *ETE, int scanline, ScanLineListBlock **SLLBlock, int *iSLLBlock)
Definition: mipolyutil.c:56
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres)
Definition: miscanfill.h:103
ScanLineList scanlines
Definition: mipoly.h:78
l2prod max
int count
Definition: decode_rs.h:79