1 /*! \file kbool/src/record.cpp
2     \author Klaas Holwerda or Julian Smart
3 
4     Copyright: 2001-2004 (C) Klaas Holwerda
5 
6     Licence: see kboollicense.txt
7 
8     RCS-ID: $Id: record.cpp,v 1.5 2005/05/24 19:13:39 titato Exp $
9 */
10 
11 #ifdef __GNUG__
12 #pragma implementation
13 #endif
14 
15 #include "kbool/include/booleng.h"
16 #include "kbool/include/record.h"
17 #include "kbool/include/node.h"
18 
19 #include <stdlib.h>
20 #include <math.h>
21 
22 #define LNK _line.GetLink()
23 
24 //int r_index=-1;
25 //void* _Record_Pool[30];
26 
27 //void DeleteRecordPool()
28 //{
29 //   while (r_index!=-1)
30 //   {
31 //     free( _Record_Pool[r_index--]);
32 //   }
33 //}
34 
~Record()35 Record::~Record()
36 {
37 }
38 
39 
40 //void* Record::operator new(size_t size)
41 //{
42 //
43 //   if (r_index!=-1)
44 //   {
45 //     return _Record_Pool[r_index--];
46 //   }
47 //
48 //   return malloc(size);
49 //}
50 
51 //void Record::operator delete(void* recordptr)
52 //{
53 //
54 //   if (r_index < 28)
55 //   {
56 //     _Record_Pool[++r_index]= recordptr;
57 //     return;
58 //   }
59 //
60 //	free (recordptr);
61 //}
62 
63 //void Record::deletepool()
64 //{
65 //
66 //   while (r_index!=-1)
67 //   {
68 //     free( _Record_Pool[r_index--]);
69 //   }
70 //}
71 
Record(KBoolLink * link,Bool_Engine * GC)72 Record::Record(KBoolLink* link,Bool_Engine* GC)
73    :_line(GC)
74 {
75    _GC=GC;
76 	_dir=GO_RIGHT;
77    _a=0;
78    _b=0;
79 	_line.Set(link);
80 	_line.CalculateLineParameters();
81 }
82 
83 
84 //when the dimensions of a link for a record changes, its line parameters need to be recalculated
SetNewLink(KBoolLink * link)85 void Record::SetNewLink(KBoolLink* link)
86 {
87 	_line.Set(link);
88    _line.CalculateLineParameters();
89 }
90 
91 //for beams calculate the ysp on the low scanline
Calc_Ysp(Node * low)92 void Record::Calc_Ysp(Node* low)
93 {
94 	if ((LNK->GetEndNode() == low) || (LNK->GetBeginNode() == low))
95    {
96       _ysp=low->GetY();
97       return;
98    }
99 
100    if	(LNK->GetEndNode()->GetX() == LNK->GetBeginNode()->GetX())
101          _ysp=low->GetY(); //flatlink only in flatbeams
102    else if (LNK->GetEndNode()->GetX() == low->GetX())
103          _ysp=LNK->GetEndNode()->GetY();
104    else if (LNK->GetBeginNode()->GetX() == low->GetX())
105          _ysp=LNK->GetBeginNode()->GetY();
106    else
107       	_ysp=_line.Calculate_Y_from_X(low->GetX());
108 }
109 
110 //to set the _dir for new links in the beam
Set_Flags()111 void Record::Set_Flags()
112 {
113 	if (LNK->GetEndNode()->GetX()==LNK->GetBeginNode()->GetX()) //flatlink ?
114 	{  //only happens in flat beams
115 		if (LNK->GetEndNode()->GetY() < LNK->GetBeginNode()->GetY())
116 			_dir=GO_RIGHT;
117 		else
118 			_dir=GO_LEFT;
119 	}
120 	else
121 	{
122 		if (LNK->GetEndNode()->GetX() > LNK->GetBeginNode()->GetX())
123 			_dir=GO_RIGHT;
124 		else
125 			_dir=GO_LEFT;
126 	}
127 }
128 
GetLink()129 KBoolLink* Record::GetLink()
130 {
131 	return LNK;
132 }
133 
Ysp()134 B_INT Record::Ysp()
135 {
136 	return _ysp;
137 }
138 
SetYsp(B_INT ysp)139 void Record::SetYsp(B_INT ysp)
140 {
141 	_ysp=ysp;
142 }
143 
Direction()144 DIRECTION Record::Direction()
145 {
146 	return DIRECTION(_dir);
147 }
148 
Calc_Left_Right(Record * record_above_me)149 bool Record::Calc_Left_Right(Record* record_above_me)
150 {
151    bool par=false;
152 
153    if (!record_above_me)   //null if no record above
154    { 	_a=0;_b=0;  }
155    else
156    {
157    	_a=record_above_me->_a;
158    	_b=record_above_me->_b;
159    }
160 
161    switch (_dir&1)
162    {
163       case GO_LEFT	:	if (LNK->Group() == GROUP_A)
164                         {
165                            LNK->SetRightA((bool)(_a>0));
166 
167                            if (_GC->GetWindingRule())
168                               LNK->GetInc() ? _a++ : _a--;
169                            else
170                            {  //ALTERNATE
171                               if (_a)
172                                  _a=0;
173                               else
174                                  _a=1;
175                            }
176 
177                            LNK->SetLeftA((bool)(_a>0));
178                            LNK->SetLeftB((bool)(_b>0));
179                            LNK->SetRightB((bool)(_b>0));
180                         }
181                         else
182                         {
183                            LNK->SetRightA((bool)(_a > 0));
184                            LNK->SetLeftA((bool)(_a>0));
185                            LNK->SetRightB((bool)(_b>0));
186 
187                            if (_GC->GetWindingRule())
188                               LNK->GetInc() ? _b++ : _b--;
189                            else //ALTERNATE
190                            {
191                                if (_b)
192                                     _b=0;
193                                else
194                                     _b=1;
195                            }
196 
197                            LNK->SetLeftB((bool)(_b>0));
198                         }
199                            break;
200       case	GO_RIGHT	:	if (LNK->Group() == GROUP_A)
201                         {
202                            LNK->SetLeftA((bool)(_a>0));
203 
204                            if (_GC->GetWindingRule())
205                               LNK->GetInc() ? _a++ : _a--;
206                            else
207                            {  //ALTERNATE
208                               if (_a)
209                                  _a=0;
210                               else
211                                  _a=1;
212                            }
213 
214                            LNK->SetRightA((bool)(_a>0));
215                            LNK->SetLeftB((bool)(_b>0));
216                            LNK->SetRightB((bool)(_b>0));
217                         }
218                         else
219                         {
220                            LNK->SetRightA((bool)(_a>0));
221                            LNK->SetLeftA((bool)(_a>0));
222                            LNK->SetLeftB((bool)(_b>0));
223 
224                            if (_GC->GetWindingRule())
225                               LNK->GetInc() ? _b++ : _b--;
226                            else
227                            {  //ALTERNATE
228                               if (_b)
229                                  _b=0;
230                               else
231                                  _b=1;
232                            }
233 
234                            LNK->SetRightB((bool)(_b>0));
235                         }
236                         break;
237       default			:  _GC->error("Undefined Direction of link","function IScanBeam::Calc_Set_Left_Right()");
238                         break;
239    }
240 
241 //THE NEXT WILL WORK for MOST windingrule polygons,
242 //even when not taking into acount windingrule
243 // not all
244 /*
245    switch (_dir&1)
246    {
247       case GO_LEFT	:	if (LNK->Group() == GROUP_A)
248                         {
249                            LNK->SetRightA((bool)(_a>0));
250 
251                            if (booleng->Get_WindingRule())
252                               LNK->GetInc() ? _a++ : _a--;
253                            else
254                               _a--;
255 
256                            LNK->SetLeftA((bool)(_a>0));
257                            LNK->SetLeftB((bool)(_b>0));
258                            LNK->SetRightB((bool)(_b>0));
259                         }
260                         else
261                         {
262                            LNK->SetRightA((bool)(_a > 0));
263                            LNK->SetLeftA((bool)(_a>0));
264                            LNK->SetRightB((bool)(_b>0));
265 
266                            if (booleng->Get_WindingRule())
267                               LNK->GetInc() ? _b++ : _b--;
268                            else
269                               _b--;
270 
271                            LNK->SetLeftB((bool)(_b>0));
272                         }
273                            break;
274       case	GO_RIGHT	:	if (LNK->Group() == GROUP_A)
275                            {
276                               LNK->SetLeftA((bool)(_a>0));
277 
278                               if (booleng->Get_WindingRule())
279                                  LNK->GetInc() ? _a++ : _a--;
280                               else
281                                  _a++;
282 
283                               LNK->SetRightA((bool)(_a>0));
284                               LNK->SetLeftB((bool)(_b>0));
285                               LNK->SetRightB((bool)(_b>0));
286                            }
287                         else
288                            {
289                               LNK->SetRightA((bool)(_a>0));
290                               LNK->SetLeftA((bool)(_a>0));
291                               LNK->SetLeftB((bool)(_b>0));
292 
293                               if (booleng->Get_WindingRule())
294                                  LNK->GetInc() ? _b++ : _b--;
295                               else
296                                  _b++;
297 
298                               LNK->SetRightB((bool)(_b>0));
299                            }
300                         break;
301       default			:  _messagehandler->error("Undefined Direction of link","function IScanBeam::Calc_Set_Left_Right()");
302                         break;
303    }
304 */
305    //if the records are parallel (same begin/endnodes)
306    //the above link a/b flag are adjusted to the current a/b depth
307    if (record_above_me && Equal(record_above_me))
308    {
309       par=true;
310 		LNK->Mark();
311    	record_above_me->_a=_a;
312    	record_above_me->_b=_b;
313 		if (Direction()== GO_LEFT)
314 		{
315          //set the bottom side  of the above link
316          if (record_above_me->Direction()== GO_LEFT)
317          {
318             record_above_me->LNK->SetLeftA(LNK->GetLeftA());
319             record_above_me->LNK->SetLeftB(LNK->GetLeftB());
320          }
321          else
322          {
323             record_above_me->LNK->SetRightA(LNK->GetLeftA());
324             record_above_me->LNK->SetRightB(LNK->GetLeftB());
325          }
326 		}
327 		else
328 		{
329          //set the bottom side  of the above link
330          if (record_above_me->Direction()== GO_LEFT)
331          {
332             record_above_me->LNK->SetLeftA(LNK->GetRightA());
333             record_above_me->LNK->SetLeftB(LNK->GetRightB());
334          }
335          else
336          {
337             record_above_me->LNK->SetRightA(LNK->GetRightA());
338             record_above_me->LNK->SetRightB(LNK->GetRightB());
339          }
340 		}
341    }
342    return par;
343 }
344 
Equal(Record * a)345 bool Record::Equal(Record *a)
346 {
347 	return((bool)( ( LNK->GetOther(a->LNK->GetBeginNode()) == a->LNK->GetEndNode())  &&
348 						  ( LNK->GetOther(a->LNK->GetEndNode())   == a->LNK->GetBeginNode())  ));
349 }
350 
351 
GetLine()352 KBoolLine* Record::GetLine()
353 {
354 	return &_line;
355 }
356 
357 
358